blob: 6e30c094c56f8bb9be742521ae1e64d624fed084 [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>
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030036#include <media/v4l2-common.h>
37#include <media/v4l2-ioctl.h>
38#include <media/v4l2-chip-ident.h>
39#include <media/tuner.h>
40#include "au0828.h"
41#include "au0828-reg.h"
42
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030043static DEFINE_MUTEX(au0828_sysfs_lock);
44
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030045/* ------------------------------------------------------------------
46 Videobuf operations
47 ------------------------------------------------------------------*/
48
49static unsigned int isoc_debug;
50module_param(isoc_debug, int, 0644);
51MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
52
53#define au0828_isocdbg(fmt, arg...) \
54do {\
55 if (isoc_debug) { \
56 printk(KERN_INFO "au0828 %s :"fmt, \
57 __func__ , ##arg); \
58 } \
59 } while (0)
60
61static inline void print_err_status(struct au0828_dev *dev,
62 int packet, int status)
63{
64 char *errmsg = "Unknown";
65
66 switch (status) {
67 case -ENOENT:
68 errmsg = "unlinked synchronuously";
69 break;
70 case -ECONNRESET:
71 errmsg = "unlinked asynchronuously";
72 break;
73 case -ENOSR:
74 errmsg = "Buffer error (overrun)";
75 break;
76 case -EPIPE:
77 errmsg = "Stalled (device not responding)";
78 break;
79 case -EOVERFLOW:
80 errmsg = "Babble (bad cable?)";
81 break;
82 case -EPROTO:
83 errmsg = "Bit-stuff error (bad cable?)";
84 break;
85 case -EILSEQ:
86 errmsg = "CRC/Timeout (could be anything)";
87 break;
88 case -ETIME:
89 errmsg = "Device does not respond";
90 break;
91 }
92 if (packet < 0) {
93 au0828_isocdbg("URB status %d [%s].\n", status, errmsg);
94 } else {
95 au0828_isocdbg("URB packet %d, status %d [%s].\n",
96 packet, status, errmsg);
97 }
98}
99
100static int check_dev(struct au0828_dev *dev)
101{
102 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300103 printk(KERN_INFO "v4l2 ioctl: device not present\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300104 return -ENODEV;
105 }
106
107 if (dev->dev_state & DEV_MISCONFIGURED) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300108 printk(KERN_INFO "v4l2 ioctl: device is misconfigured; "
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300109 "close and open it again\n");
110 return -EIO;
111 }
112 return 0;
113}
114
115/*
116 * IRQ callback, called by URB callback
117 */
118static void au0828_irq_callback(struct urb *urb)
119{
120 struct au0828_dmaqueue *dma_q = urb->context;
121 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300122 unsigned long flags = 0;
Hans Verkuile92ba282012-05-14 10:17:35 -0300123 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300124
125 switch (urb->status) {
126 case 0: /* success */
127 case -ETIMEDOUT: /* NAK */
128 break;
129 case -ECONNRESET: /* kill */
130 case -ENOENT:
131 case -ESHUTDOWN:
132 au0828_isocdbg("au0828_irq_callback called: status kill\n");
133 return;
134 default: /* unknown error */
135 au0828_isocdbg("urb completition error %d.\n", urb->status);
136 break;
137 }
138
139 /* Copy data from URB */
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300140 spin_lock_irqsave(&dev->slock, flags);
Hans Verkuile92ba282012-05-14 10:17:35 -0300141 dev->isoc_ctl.isoc_copy(dev, urb);
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300142 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300143
144 /* Reset urb buffers */
145 for (i = 0; i < urb->number_of_packets; i++) {
146 urb->iso_frame_desc[i].status = 0;
147 urb->iso_frame_desc[i].actual_length = 0;
148 }
149 urb->status = 0;
150
151 urb->status = usb_submit_urb(urb, GFP_ATOMIC);
152 if (urb->status) {
153 au0828_isocdbg("urb resubmit failed (error=%i)\n",
154 urb->status);
155 }
156}
157
158/*
159 * Stop and Deallocate URBs
160 */
161void au0828_uninit_isoc(struct au0828_dev *dev)
162{
163 struct urb *urb;
164 int i;
165
166 au0828_isocdbg("au0828: called au0828_uninit_isoc\n");
167
168 dev->isoc_ctl.nfields = -1;
169 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
170 urb = dev->isoc_ctl.urb[i];
171 if (urb) {
172 if (!irqs_disabled())
173 usb_kill_urb(urb);
174 else
175 usb_unlink_urb(urb);
176
177 if (dev->isoc_ctl.transfer_buffer[i]) {
Daniel Mack997ea582010-04-12 13:17:25 +0200178 usb_free_coherent(dev->usbdev,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300179 urb->transfer_buffer_length,
180 dev->isoc_ctl.transfer_buffer[i],
181 urb->transfer_dma);
182 }
183 usb_free_urb(urb);
184 dev->isoc_ctl.urb[i] = NULL;
185 }
186 dev->isoc_ctl.transfer_buffer[i] = NULL;
187 }
188
189 kfree(dev->isoc_ctl.urb);
190 kfree(dev->isoc_ctl.transfer_buffer);
191
192 dev->isoc_ctl.urb = NULL;
193 dev->isoc_ctl.transfer_buffer = NULL;
194 dev->isoc_ctl.num_bufs = 0;
195}
196
197/*
198 * Allocate URBs and start IRQ
199 */
200int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
201 int num_bufs, int max_pkt_size,
202 int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
203{
204 struct au0828_dmaqueue *dma_q = &dev->vidq;
205 int i;
206 int sb_size, pipe;
207 struct urb *urb;
208 int j, k;
209 int rc;
210
211 au0828_isocdbg("au0828: called au0828_prepare_isoc\n");
212
213 /* De-allocates all pending stuff */
214 au0828_uninit_isoc(dev);
215
216 dev->isoc_ctl.isoc_copy = isoc_copy;
217 dev->isoc_ctl.num_bufs = num_bufs;
218
219 dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
220 if (!dev->isoc_ctl.urb) {
221 au0828_isocdbg("cannot alloc memory for usb buffers\n");
222 return -ENOMEM;
223 }
224
225 dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
226 GFP_KERNEL);
227 if (!dev->isoc_ctl.transfer_buffer) {
228 au0828_isocdbg("cannot allocate memory for usb transfer\n");
229 kfree(dev->isoc_ctl.urb);
230 return -ENOMEM;
231 }
232
233 dev->isoc_ctl.max_pkt_size = max_pkt_size;
234 dev->isoc_ctl.buf = NULL;
235
236 sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
237
238 /* allocate urbs and transfer buffers */
239 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
240 urb = usb_alloc_urb(max_packets, GFP_KERNEL);
241 if (!urb) {
242 au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i);
243 au0828_uninit_isoc(dev);
244 return -ENOMEM;
245 }
246 dev->isoc_ctl.urb[i] = urb;
247
Daniel Mack997ea582010-04-12 13:17:25 +0200248 dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300249 sb_size, GFP_KERNEL, &urb->transfer_dma);
250 if (!dev->isoc_ctl.transfer_buffer[i]) {
251 printk("unable to allocate %i bytes for transfer"
252 " buffer %i%s\n",
253 sb_size, i,
254 in_interrupt() ? " while in int" : "");
255 au0828_uninit_isoc(dev);
256 return -ENOMEM;
257 }
258 memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
259
260 pipe = usb_rcvisocpipe(dev->usbdev,
261 dev->isoc_in_endpointaddr),
262
263 usb_fill_int_urb(urb, dev->usbdev, pipe,
264 dev->isoc_ctl.transfer_buffer[i], sb_size,
265 au0828_irq_callback, dma_q, 1);
266
267 urb->number_of_packets = max_packets;
Devin Heitmuellerfadadb72009-03-22 23:42:26 -0300268 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300269
270 k = 0;
271 for (j = 0; j < max_packets; j++) {
272 urb->iso_frame_desc[j].offset = k;
273 urb->iso_frame_desc[j].length =
274 dev->isoc_ctl.max_pkt_size;
275 k += dev->isoc_ctl.max_pkt_size;
276 }
277 }
278
279 init_waitqueue_head(&dma_q->wq);
280
281 /* submit urbs and enables IRQ */
282 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
283 rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
284 if (rc) {
285 au0828_isocdbg("submit of urb %i failed (error=%i)\n",
286 i, rc);
287 au0828_uninit_isoc(dev);
288 return rc;
289 }
290 }
291
292 return 0;
293}
294
295/*
296 * Announces that a buffer were filled and request the next
297 */
298static inline void buffer_filled(struct au0828_dev *dev,
299 struct au0828_dmaqueue *dma_q,
300 struct au0828_buffer *buf)
301{
302 /* Advice that buffer was filled */
303 au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
304
305 buf->vb.state = VIDEOBUF_DONE;
306 buf->vb.field_count++;
307 do_gettimeofday(&buf->vb.ts);
308
309 dev->isoc_ctl.buf = NULL;
310
311 list_del(&buf->vb.queue);
312 wake_up(&buf->vb.done);
313}
314
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300315static inline void vbi_buffer_filled(struct au0828_dev *dev,
316 struct au0828_dmaqueue *dma_q,
317 struct au0828_buffer *buf)
318{
319 /* Advice that buffer was filled */
320 au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
321
322 buf->vb.state = VIDEOBUF_DONE;
323 buf->vb.field_count++;
324 do_gettimeofday(&buf->vb.ts);
325
326 dev->isoc_ctl.vbi_buf = NULL;
327
328 list_del(&buf->vb.queue);
329 wake_up(&buf->vb.done);
330}
331
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300332/*
333 * Identify the buffer header type and properly handles
334 */
335static void au0828_copy_video(struct au0828_dev *dev,
336 struct au0828_dmaqueue *dma_q,
337 struct au0828_buffer *buf,
338 unsigned char *p,
339 unsigned char *outp, unsigned long len)
340{
341 void *fieldstart, *startwrite, *startread;
342 int linesdone, currlinedone, offset, lencopy, remain;
343 int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */
344
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300345 if (len == 0)
346 return;
347
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300348 if (dma_q->pos + len > buf->vb.size)
349 len = buf->vb.size - dma_q->pos;
350
351 startread = p;
352 remain = len;
353
354 /* Interlaces frame */
355 if (buf->top_field)
356 fieldstart = outp;
357 else
358 fieldstart = outp + bytesperline;
359
360 linesdone = dma_q->pos / bytesperline;
361 currlinedone = dma_q->pos % bytesperline;
362 offset = linesdone * bytesperline * 2 + currlinedone;
363 startwrite = fieldstart + offset;
364 lencopy = bytesperline - currlinedone;
365 lencopy = lencopy > remain ? remain : lencopy;
366
367 if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
368 au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
369 ((char *)startwrite + lencopy) -
370 ((char *)outp + buf->vb.size));
371 remain = (char *)outp + buf->vb.size - (char *)startwrite;
372 lencopy = remain;
373 }
374 if (lencopy <= 0)
375 return;
376 memcpy(startwrite, startread, lencopy);
377
378 remain -= lencopy;
379
380 while (remain > 0) {
381 startwrite += lencopy + bytesperline;
382 startread += lencopy;
383 if (bytesperline > remain)
384 lencopy = remain;
385 else
386 lencopy = bytesperline;
387
388 if ((char *)startwrite + lencopy > (char *)outp +
389 buf->vb.size) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300390 au0828_isocdbg("Overflow %zi bytes past buf end (2)\n",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300391 ((char *)startwrite + lencopy) -
392 ((char *)outp + buf->vb.size));
393 lencopy = remain = (char *)outp + buf->vb.size -
394 (char *)startwrite;
395 }
396 if (lencopy <= 0)
397 break;
398
399 memcpy(startwrite, startread, lencopy);
400
401 remain -= lencopy;
402 }
403
404 if (offset > 1440) {
405 /* We have enough data to check for greenscreen */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300406 if (outp[0] < 0x60 && outp[1440] < 0x60)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300407 dev->greenscreen_detected = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300408 }
409
410 dma_q->pos += len;
411}
412
413/*
414 * video-buf generic routine to get the next available buffer
415 */
416static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
417 struct au0828_buffer **buf)
418{
419 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
420
421 if (list_empty(&dma_q->active)) {
422 au0828_isocdbg("No active queue to serve\n");
423 dev->isoc_ctl.buf = NULL;
424 *buf = NULL;
425 return;
426 }
427
428 /* Get the next buffer */
429 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
430 dev->isoc_ctl.buf = *buf;
431
432 return;
433}
434
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300435static void au0828_copy_vbi(struct au0828_dev *dev,
436 struct au0828_dmaqueue *dma_q,
437 struct au0828_buffer *buf,
438 unsigned char *p,
439 unsigned char *outp, unsigned long len)
440{
441 unsigned char *startwrite, *startread;
Dan Carpenterb5f59332010-07-23 07:09:20 -0300442 int bytesperline;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300443 int i, j = 0;
444
445 if (dev == NULL) {
446 au0828_isocdbg("dev is null\n");
447 return;
448 }
449
450 if (dma_q == NULL) {
451 au0828_isocdbg("dma_q is null\n");
452 return;
453 }
454 if (buf == NULL)
455 return;
456 if (p == NULL) {
457 au0828_isocdbg("p is null\n");
458 return;
459 }
460 if (outp == NULL) {
461 au0828_isocdbg("outp is null\n");
462 return;
463 }
464
Dan Carpenterb5f59332010-07-23 07:09:20 -0300465 bytesperline = dev->vbi_width;
466
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300467 if (dma_q->pos + len > buf->vb.size)
468 len = buf->vb.size - dma_q->pos;
469
470 startread = p;
471 startwrite = outp + (dma_q->pos / 2);
472
473 /* Make sure the bottom field populates the second half of the frame */
474 if (buf->top_field == 0)
475 startwrite += bytesperline * dev->vbi_height;
476
477 for (i = 0; i < len; i += 2)
478 startwrite[j++] = startread[i+1];
479
480 dma_q->pos += len;
481}
482
483
484/*
485 * video-buf generic routine to get the next available VBI buffer
486 */
487static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q,
488 struct au0828_buffer **buf)
489{
490 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq);
491 char *outp;
492
493 if (list_empty(&dma_q->active)) {
494 au0828_isocdbg("No active queue to serve\n");
495 dev->isoc_ctl.vbi_buf = NULL;
496 *buf = NULL;
497 return;
498 }
499
500 /* Get the next buffer */
501 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300502 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300503 outp = videobuf_to_vmalloc(&(*buf)->vb);
504 memset(outp, 0x00, (*buf)->vb.size);
505
506 dev->isoc_ctl.vbi_buf = *buf;
507
508 return;
509}
510
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300511/*
512 * Controls the isoc copy of each urb packet
513 */
514static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
515{
516 struct au0828_buffer *buf;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300517 struct au0828_buffer *vbi_buf;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300518 struct au0828_dmaqueue *dma_q = urb->context;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300519 struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300520 unsigned char *outp = NULL;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300521 unsigned char *vbioutp = NULL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300522 int i, len = 0, rc = 1;
523 unsigned char *p;
524 unsigned char fbyte;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300525 unsigned int vbi_field_size;
526 unsigned int remain, lencopy;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300527
528 if (!dev)
529 return 0;
530
531 if ((dev->dev_state & DEV_DISCONNECTED) ||
532 (dev->dev_state & DEV_MISCONFIGURED))
533 return 0;
534
535 if (urb->status < 0) {
536 print_err_status(dev, -1, urb->status);
537 if (urb->status == -ENOENT)
538 return 0;
539 }
540
541 buf = dev->isoc_ctl.buf;
542 if (buf != NULL)
543 outp = videobuf_to_vmalloc(&buf->vb);
544
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300545 vbi_buf = dev->isoc_ctl.vbi_buf;
546 if (vbi_buf != NULL)
547 vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
548
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300549 for (i = 0; i < urb->number_of_packets; i++) {
550 int status = urb->iso_frame_desc[i].status;
551
552 if (status < 0) {
553 print_err_status(dev, i, status);
554 if (urb->iso_frame_desc[i].status != -EPROTO)
555 continue;
556 }
557
Devin Heitmueller62899a22009-03-15 18:48:52 -0300558 if (urb->iso_frame_desc[i].actual_length <= 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300559 continue;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300560
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300561 if (urb->iso_frame_desc[i].actual_length >
562 dev->max_pkt_size) {
563 au0828_isocdbg("packet bigger than packet size");
564 continue;
565 }
566
567 p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
568 fbyte = p[0];
569 len = urb->iso_frame_desc[i].actual_length - 4;
570 p += 4;
571
572 if (fbyte & 0x80) {
573 len -= 4;
574 p += 4;
575 au0828_isocdbg("Video frame %s\n",
576 (fbyte & 0x40) ? "odd" : "even");
Devin Heitmuellerbde3bb92010-07-05 13:05:16 -0300577 if (fbyte & 0x40) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300578 /* VBI */
579 if (vbi_buf != NULL)
580 vbi_buffer_filled(dev,
581 vbi_dma_q,
582 vbi_buf);
583 vbi_get_next_buf(vbi_dma_q, &vbi_buf);
584 if (vbi_buf == NULL)
585 vbioutp = NULL;
586 else
587 vbioutp = videobuf_to_vmalloc(
588 &vbi_buf->vb);
589
590 /* Video */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300591 if (buf != NULL)
592 buffer_filled(dev, dma_q, buf);
593 get_next_buf(dma_q, &buf);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300594 if (buf == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300595 outp = NULL;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300596 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300597 outp = videobuf_to_vmalloc(&buf->vb);
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300598
599 /* As long as isoc traffic is arriving, keep
600 resetting the timer */
601 if (dev->vid_timeout_running)
602 mod_timer(&dev->vid_timeout,
603 jiffies + (HZ / 10));
604 if (dev->vbi_timeout_running)
605 mod_timer(&dev->vbi_timeout,
606 jiffies + (HZ / 10));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300607 }
608
609 if (buf != NULL) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300610 if (fbyte & 0x40)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300611 buf->top_field = 1;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300612 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300613 buf->top_field = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300614 }
615
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300616 if (vbi_buf != NULL) {
617 if (fbyte & 0x40)
618 vbi_buf->top_field = 1;
619 else
620 vbi_buf->top_field = 0;
621 }
622
623 dev->vbi_read = 0;
624 vbi_dma_q->pos = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300625 dma_q->pos = 0;
626 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300627
628 vbi_field_size = dev->vbi_width * dev->vbi_height * 2;
629 if (dev->vbi_read < vbi_field_size) {
630 remain = vbi_field_size - dev->vbi_read;
631 if (len < remain)
632 lencopy = len;
633 else
634 lencopy = remain;
635
636 if (vbi_buf != NULL)
637 au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
638 vbioutp, len);
639
640 len -= lencopy;
641 p += lencopy;
642 dev->vbi_read += lencopy;
643 }
644
645 if (dev->vbi_read >= vbi_field_size && buf != NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300646 au0828_copy_video(dev, dma_q, buf, p, outp, len);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300647 }
648 return rc;
649}
650
651static int
652buffer_setup(struct videobuf_queue *vq, unsigned int *count,
653 unsigned int *size)
654{
655 struct au0828_fh *fh = vq->priv_data;
656 *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
657
658 if (0 == *count)
659 *count = AU0828_DEF_BUF;
660
661 if (*count < AU0828_MIN_BUF)
662 *count = AU0828_MIN_BUF;
663 return 0;
664}
665
666/* This is called *without* dev->slock held; please keep it that way */
667static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
668{
669 struct au0828_fh *fh = vq->priv_data;
670 struct au0828_dev *dev = fh->dev;
671 unsigned long flags = 0;
672 if (in_interrupt())
673 BUG();
674
675 /* We used to wait for the buffer to finish here, but this didn't work
676 because, as we were keeping the state as VIDEOBUF_QUEUED,
677 videobuf_queue_cancel marked it as finished for us.
678 (Also, it could wedge forever if the hardware was misconfigured.)
679
680 This should be safe; by the time we get here, the buffer isn't
681 queued anymore. If we ever start marking the buffers as
682 VIDEOBUF_ACTIVE, it won't be, though.
683 */
684 spin_lock_irqsave(&dev->slock, flags);
685 if (dev->isoc_ctl.buf == buf)
686 dev->isoc_ctl.buf = NULL;
687 spin_unlock_irqrestore(&dev->slock, flags);
688
689 videobuf_vmalloc_free(&buf->vb);
690 buf->vb.state = VIDEOBUF_NEEDS_INIT;
691}
692
693static int
694buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
695 enum v4l2_field field)
696{
697 struct au0828_fh *fh = vq->priv_data;
698 struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
699 struct au0828_dev *dev = fh->dev;
700 int rc = 0, urb_init = 0;
701
702 buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
703
704 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
705 return -EINVAL;
706
707 buf->vb.width = dev->width;
708 buf->vb.height = dev->height;
709 buf->vb.field = field;
710
711 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
712 rc = videobuf_iolock(vq, &buf->vb, NULL);
713 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300714 printk(KERN_INFO "videobuf_iolock failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300715 goto fail;
716 }
717 }
718
719 if (!dev->isoc_ctl.num_bufs)
720 urb_init = 1;
721
722 if (urb_init) {
723 rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,
724 AU0828_MAX_ISO_BUFS, dev->max_pkt_size,
725 au0828_isoc_copy);
726 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300727 printk(KERN_INFO "au0828_init_isoc failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300728 goto fail;
729 }
730 }
731
732 buf->vb.state = VIDEOBUF_PREPARED;
733 return 0;
734
735fail:
736 free_buffer(vq, buf);
737 return rc;
738}
739
740static void
741buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
742{
743 struct au0828_buffer *buf = container_of(vb,
744 struct au0828_buffer,
745 vb);
746 struct au0828_fh *fh = vq->priv_data;
747 struct au0828_dev *dev = fh->dev;
748 struct au0828_dmaqueue *vidq = &dev->vidq;
749
750 buf->vb.state = VIDEOBUF_QUEUED;
751 list_add_tail(&buf->vb.queue, &vidq->active);
752}
753
754static void buffer_release(struct videobuf_queue *vq,
755 struct videobuf_buffer *vb)
756{
757 struct au0828_buffer *buf = container_of(vb,
758 struct au0828_buffer,
759 vb);
760
761 free_buffer(vq, buf);
762}
763
764static struct videobuf_queue_ops au0828_video_qops = {
765 .buf_setup = buffer_setup,
766 .buf_prepare = buffer_prepare,
767 .buf_queue = buffer_queue,
768 .buf_release = buffer_release,
769};
770
771/* ------------------------------------------------------------------
772 V4L2 interface
773 ------------------------------------------------------------------*/
774
775static int au0828_i2s_init(struct au0828_dev *dev)
776{
777 /* Enable i2s mode */
778 au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);
779 return 0;
780}
781
782/*
783 * Auvitek au0828 analog stream enable
784 * Please set interface0 to AS5 before enable the stream
785 */
786int au0828_analog_stream_enable(struct au0828_dev *d)
787{
788 dprintk(1, "au0828_analog_stream_enable called\n");
789 au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
790 au0828_writereg(d, 0x106, 0x00);
791 /* set x position */
792 au0828_writereg(d, 0x110, 0x00);
793 au0828_writereg(d, 0x111, 0x00);
794 au0828_writereg(d, 0x114, 0xa0);
795 au0828_writereg(d, 0x115, 0x05);
796 /* set y position */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300797 au0828_writereg(d, 0x112, 0x00);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300798 au0828_writereg(d, 0x113, 0x00);
799 au0828_writereg(d, 0x116, 0xf2);
800 au0828_writereg(d, 0x117, 0x00);
801 au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
802
803 return 0;
804}
805
806int au0828_analog_stream_disable(struct au0828_dev *d)
807{
808 dprintk(1, "au0828_analog_stream_disable called\n");
809 au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
810 return 0;
811}
812
813void au0828_analog_stream_reset(struct au0828_dev *dev)
814{
815 dprintk(1, "au0828_analog_stream_reset called\n");
816 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
817 mdelay(30);
818 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);
819}
820
821/*
822 * Some operations needs to stop current streaming
823 */
824static int au0828_stream_interrupt(struct au0828_dev *dev)
825{
826 int ret = 0;
827
828 dev->stream_state = STREAM_INTERRUPT;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300829 if (dev->dev_state == DEV_DISCONNECTED)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300830 return -ENODEV;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300831 else if (ret) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300832 dev->dev_state = DEV_MISCONFIGURED;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300833 dprintk(1, "%s device is misconfigured!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300834 return ret;
835 }
836 return 0;
837}
838
839/*
840 * au0828_release_resources
841 * unregister v4l2 devices
842 */
843void au0828_analog_unregister(struct au0828_dev *dev)
844{
845 dprintk(1, "au0828_release_resources called\n");
846 mutex_lock(&au0828_sysfs_lock);
847
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200848 if (dev->vdev)
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300849 video_unregister_device(dev->vdev);
850 if (dev->vbi_dev)
851 video_unregister_device(dev->vbi_dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300852
853 mutex_unlock(&au0828_sysfs_lock);
854}
855
856
857/* Usage lock check functions */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300858static int res_get(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300859{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300860 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300861
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300862 if (fh->resources & bit)
863 /* have it already allocated */
864 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300865
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300866 /* is it free? */
867 mutex_lock(&dev->lock);
868 if (dev->resources & bit) {
869 /* no, someone else uses it */
870 mutex_unlock(&dev->lock);
871 return 0;
872 }
873 /* it's free, grab it */
874 fh->resources |= bit;
875 dev->resources |= bit;
876 dprintk(1, "res: get %d\n", bit);
877 mutex_unlock(&dev->lock);
878 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300879}
880
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300881static int res_check(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300882{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300883 return fh->resources & bit;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300884}
885
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300886static int res_locked(struct au0828_dev *dev, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300887{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300888 return dev->resources & bit;
889}
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300890
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300891static void res_free(struct au0828_fh *fh, unsigned int bits)
892{
893 struct au0828_dev *dev = fh->dev;
894
895 BUG_ON((fh->resources & bits) != bits);
896
897 mutex_lock(&dev->lock);
898 fh->resources &= ~bits;
899 dev->resources &= ~bits;
900 dprintk(1, "res: put %d\n", bits);
901 mutex_unlock(&dev->lock);
902}
903
904static int get_ressource(struct au0828_fh *fh)
905{
906 switch (fh->type) {
907 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
908 return AU0828_RESOURCE_VIDEO;
909 case V4L2_BUF_TYPE_VBI_CAPTURE:
910 return AU0828_RESOURCE_VBI;
911 default:
912 BUG();
913 return 0;
914 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300915}
916
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300917/* This function ensures that video frames continue to be delivered even if
918 the ITU-656 input isn't receiving any data (thereby preventing applications
919 such as tvtime from hanging) */
920void au0828_vid_buffer_timeout(unsigned long data)
921{
922 struct au0828_dev *dev = (struct au0828_dev *) data;
923 struct au0828_dmaqueue *dma_q = &dev->vidq;
924 struct au0828_buffer *buf;
925 unsigned char *vid_data;
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300926 unsigned long flags = 0;
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300927
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300928 spin_lock_irqsave(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300929
930 buf = dev->isoc_ctl.buf;
931 if (buf != NULL) {
932 vid_data = videobuf_to_vmalloc(&buf->vb);
933 memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */
934 buffer_filled(dev, dma_q, buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300935 }
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300936 get_next_buf(dma_q, &buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300937
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300938 if (dev->vid_timeout_running == 1)
939 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
940
941 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300942}
943
944void au0828_vbi_buffer_timeout(unsigned long data)
945{
946 struct au0828_dev *dev = (struct au0828_dev *) data;
947 struct au0828_dmaqueue *dma_q = &dev->vbiq;
948 struct au0828_buffer *buf;
949 unsigned char *vbi_data;
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300950 unsigned long flags = 0;
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300951
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300952 spin_lock_irqsave(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300953
954 buf = dev->isoc_ctl.vbi_buf;
955 if (buf != NULL) {
956 vbi_data = videobuf_to_vmalloc(&buf->vb);
957 memset(vbi_data, 0x00, buf->vb.size);
958 vbi_buffer_filled(dev, dma_q, buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300959 }
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300960 vbi_get_next_buf(dma_q, &buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300961
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300962 if (dev->vbi_timeout_running == 1)
963 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
964 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300965}
966
967
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300968static int au0828_v4l2_open(struct file *filp)
969{
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300970 int ret = 0;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300971 struct video_device *vdev = video_devdata(filp);
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200972 struct au0828_dev *dev = video_drvdata(filp);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300973 struct au0828_fh *fh;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300974 int type;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300975
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300976 switch (vdev->vfl_type) {
977 case VFL_TYPE_GRABBER:
978 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
979 break;
980 case VFL_TYPE_VBI:
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200981 type = V4L2_BUF_TYPE_VBI_CAPTURE;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300982 break;
983 default:
984 return -EINVAL;
985 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300986
987 fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300988 if (NULL == fh) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300989 dprintk(1, "Failed allocate au0828_fh struct!\n");
990 return -ENOMEM;
991 }
992
993 fh->type = type;
994 fh->dev = dev;
995 filp->private_data = fh;
996
Devin Heitmueller62899a22009-03-15 18:48:52 -0300997 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300998 /* set au0828 interface0 to AS5 here again */
999 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001000 if (ret < 0) {
1001 printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001002 return -EBUSY;
1003 }
1004 dev->width = NTSC_STD_W;
1005 dev->height = NTSC_STD_H;
1006 dev->frame_size = dev->width * dev->height * 2;
1007 dev->field_size = dev->width * dev->height;
1008 dev->bytesperline = dev->width * 2;
1009
1010 au0828_analog_stream_enable(dev);
1011 au0828_analog_stream_reset(dev);
1012
1013 /* If we were doing ac97 instead of i2s, it would go here...*/
1014 au0828_i2s_init(dev);
1015
1016 dev->stream_state = STREAM_OFF;
1017 dev->dev_state |= DEV_INITIALIZED;
1018 }
1019
1020 dev->users++;
1021
1022 videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001023 NULL, &dev->slock,
1024 V4L2_BUF_TYPE_VIDEO_CAPTURE,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001025 V4L2_FIELD_INTERLACED,
Hans Verkuil08bff032010-09-20 17:39:46 -03001026 sizeof(struct au0828_buffer), fh, NULL);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001027
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001028 /* VBI Setup */
1029 dev->vbi_width = 720;
1030 dev->vbi_height = 1;
1031 videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops,
1032 NULL, &dev->slock,
1033 V4L2_BUF_TYPE_VBI_CAPTURE,
1034 V4L2_FIELD_SEQ_TB,
Hans Verkuil08bff032010-09-20 17:39:46 -03001035 sizeof(struct au0828_buffer), fh, NULL);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001036
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001037 return ret;
1038}
1039
1040static int au0828_v4l2_close(struct file *filp)
1041{
1042 int ret;
1043 struct au0828_fh *fh = filp->private_data;
1044 struct au0828_dev *dev = fh->dev;
1045
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001046 if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001047 /* Cancel timeout thread in case they didn't call streamoff */
1048 dev->vid_timeout_running = 0;
1049 del_timer_sync(&dev->vid_timeout);
1050
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001051 videobuf_stop(&fh->vb_vidq);
1052 res_free(fh, AU0828_RESOURCE_VIDEO);
1053 }
1054
1055 if (res_check(fh, AU0828_RESOURCE_VBI)) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001056 /* Cancel timeout thread in case they didn't call streamoff */
1057 dev->vbi_timeout_running = 0;
1058 del_timer_sync(&dev->vbi_timeout);
1059
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001060 videobuf_stop(&fh->vb_vbiq);
1061 res_free(fh, AU0828_RESOURCE_VBI);
1062 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001063
Devin Heitmueller62899a22009-03-15 18:48:52 -03001064 if (dev->users == 1) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001065 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001066 au0828_analog_unregister(dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001067 kfree(dev);
1068 return 0;
1069 }
1070
1071 au0828_analog_stream_disable(dev);
1072
1073 au0828_uninit_isoc(dev);
1074
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001075 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -03001076 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001077
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001078 /* When close the device, set the usb intf0 into alt0 to free
1079 USB bandwidth */
1080 ret = usb_set_interface(dev->usbdev, 0, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001081 if (ret < 0)
1082 printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001083 }
1084
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001085 videobuf_mmap_free(&fh->vb_vidq);
1086 videobuf_mmap_free(&fh->vb_vbiq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001087 kfree(fh);
1088 dev->users--;
1089 wake_up_interruptible_nr(&dev->open, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001090 return 0;
1091}
1092
1093static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
1094 size_t count, loff_t *pos)
1095{
1096 struct au0828_fh *fh = filp->private_data;
1097 struct au0828_dev *dev = fh->dev;
1098 int rc;
1099
1100 rc = check_dev(dev);
1101 if (rc < 0)
1102 return rc;
1103
Devin Heitmueller62899a22009-03-15 18:48:52 -03001104 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001105 if (res_locked(dev, AU0828_RESOURCE_VIDEO))
1106 return -EBUSY;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001107
1108 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
1109 filp->f_flags & O_NONBLOCK);
1110 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001111
1112 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1113 if (!res_get(fh, AU0828_RESOURCE_VBI))
1114 return -EBUSY;
1115
Devin Heitmuellerbf797162010-10-09 15:09:17 -03001116 if (dev->vbi_timeout_running == 0) {
1117 /* Handle case where caller tries to read without
1118 calling streamon first */
1119 dev->vbi_timeout_running = 1;
1120 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1121 }
1122
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001123 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
1124 filp->f_flags & O_NONBLOCK);
1125 }
1126
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001127 return 0;
1128}
1129
1130static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
1131{
1132 struct au0828_fh *fh = filp->private_data;
1133 struct au0828_dev *dev = fh->dev;
1134 int rc;
1135
1136 rc = check_dev(dev);
1137 if (rc < 0)
1138 return rc;
1139
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001140 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1141 if (!res_get(fh, AU0828_RESOURCE_VIDEO))
1142 return POLLERR;
1143 return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
1144 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1145 if (!res_get(fh, AU0828_RESOURCE_VBI))
1146 return POLLERR;
1147 return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
1148 } else {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001149 return POLLERR;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001150 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001151}
1152
1153static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
1154{
1155 struct au0828_fh *fh = filp->private_data;
1156 struct au0828_dev *dev = fh->dev;
1157 int rc;
1158
1159 rc = check_dev(dev);
1160 if (rc < 0)
1161 return rc;
1162
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001163 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1164 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
1165 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1166 rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001167
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001168 return rc;
1169}
1170
1171static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
1172 struct v4l2_format *format)
1173{
1174 int ret;
1175 int width = format->fmt.pix.width;
1176 int height = format->fmt.pix.height;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001177
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
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001254 /*set the device capabilities */
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001255 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001256 V4L2_CAP_VBI_CAPTURE |
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001257 V4L2_CAP_AUDIO |
1258 V4L2_CAP_READWRITE |
1259 V4L2_CAP_STREAMING |
1260 V4L2_CAP_TUNER;
1261 return 0;
1262}
1263
1264static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1265 struct v4l2_fmtdesc *f)
1266{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001267 if (f->index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001268 return -EINVAL;
1269
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001270 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1271 strcpy(f->description, "Packed YUV2");
1272
1273 f->flags = 0;
1274 f->pixelformat = V4L2_PIX_FMT_UYVY;
1275
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001276 return 0;
1277}
1278
1279static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1280 struct v4l2_format *f)
1281{
1282 struct au0828_fh *fh = priv;
1283 struct au0828_dev *dev = fh->dev;
1284
1285 f->fmt.pix.width = dev->width;
1286 f->fmt.pix.height = dev->height;
1287 f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1288 f->fmt.pix.bytesperline = dev->bytesperline;
1289 f->fmt.pix.sizeimage = dev->frame_size;
1290 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
1291 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1292 return 0;
1293}
1294
1295static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1296 struct v4l2_format *f)
1297{
1298 struct au0828_fh *fh = priv;
1299 struct au0828_dev *dev = fh->dev;
1300
1301 return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
1302}
1303
1304static int vidioc_s_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 int rc;
1310
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001311 rc = check_dev(dev);
1312 if (rc < 0)
1313 return rc;
1314
1315 mutex_lock(&dev->lock);
1316
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001317 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001318 printk(KERN_INFO "%s queue busy\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001319 rc = -EBUSY;
1320 goto out;
1321 }
1322
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001323 rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001324out:
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001325 mutex_unlock(&dev->lock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001326 return rc;
1327}
1328
1329static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
1330{
1331 struct au0828_fh *fh = priv;
1332 struct au0828_dev *dev = fh->dev;
1333
1334 /* FIXME: when we support something other than NTSC, we are going to
1335 have to make the au0828 bridge adjust the size of its capture
1336 buffer, which is currently hardcoded at 720x480 */
1337
Hans Verkuilf41737e2009-04-01 03:52:39 -03001338 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001339 return 0;
1340}
1341
1342static int vidioc_enum_input(struct file *file, void *priv,
1343 struct v4l2_input *input)
1344{
1345 struct au0828_fh *fh = priv;
1346 struct au0828_dev *dev = fh->dev;
1347 unsigned int tmp;
1348
1349 static const char *inames[] = {
Devin Heitmueller3d622872009-03-15 17:48:26 -03001350 [AU0828_VMUX_UNDEFINED] = "Undefined",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001351 [AU0828_VMUX_COMPOSITE] = "Composite",
1352 [AU0828_VMUX_SVIDEO] = "S-Video",
1353 [AU0828_VMUX_CABLE] = "Cable TV",
1354 [AU0828_VMUX_TELEVISION] = "Television",
1355 [AU0828_VMUX_DVB] = "DVB",
1356 [AU0828_VMUX_DEBUG] = "tv debug"
1357 };
1358
1359 tmp = input->index;
1360
Dan Carpenterf5e20c32010-03-28 08:21:18 -03001361 if (tmp >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001362 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001363 if (AUVI_INPUT(tmp).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001364 return -EINVAL;
1365
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001366 input->index = tmp;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001367 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001368 if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
1369 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001370 input->type |= V4L2_INPUT_TYPE_TUNER;
1371 else
1372 input->type |= V4L2_INPUT_TYPE_CAMERA;
1373
1374 input->std = dev->vdev->tvnorms;
1375
1376 return 0;
1377}
1378
1379static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1380{
1381 struct au0828_fh *fh = priv;
1382 struct au0828_dev *dev = fh->dev;
1383 *i = dev->ctrl_input;
1384 return 0;
1385}
1386
1387static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1388{
1389 struct au0828_fh *fh = priv;
1390 struct au0828_dev *dev = fh->dev;
1391 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001392
Devin Heitmueller62899a22009-03-15 18:48:52 -03001393 dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001394 index);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001395 if (index >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001396 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001397 if (AUVI_INPUT(index).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001398 return -EINVAL;
1399 dev->ctrl_input = index;
1400
Devin Heitmueller62899a22009-03-15 18:48:52 -03001401 switch (AUVI_INPUT(index).type) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001402 case AU0828_VMUX_SVIDEO:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001403 dev->input_type = AU0828_VMUX_SVIDEO;
1404 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001405 case AU0828_VMUX_COMPOSITE:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001406 dev->input_type = AU0828_VMUX_COMPOSITE;
1407 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001408 case AU0828_VMUX_TELEVISION:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001409 dev->input_type = AU0828_VMUX_TELEVISION;
1410 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001411 default:
Devin Heitmuellera1094c42009-03-15 17:43:13 -03001412 dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
1413 AUVI_INPUT(index).type);
1414 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001415 }
1416
Hans Verkuil5325b422009-04-02 11:26:22 -03001417 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1418 AUVI_INPUT(index).vmux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001419
1420 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1421 int enable = 0;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001422 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001423 continue;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001424
1425 if (i == index)
1426 enable = 1;
1427 else
1428 enable = 0;
1429 if (enable) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001430 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001431 } else {
1432 /* Make sure we leave it turned on if some
1433 other input is routed to this callback */
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001434 if ((AUVI_INPUT(i).audio_setup) !=
1435 ((AUVI_INPUT(index).audio_setup))) {
1436 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001437 }
1438 }
1439 }
1440
Hans Verkuil5325b422009-04-02 11:26:22 -03001441 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1442 AUVI_INPUT(index).amux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001443 return 0;
1444}
1445
1446static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1447{
1448 struct au0828_fh *fh = priv;
1449 struct au0828_dev *dev = fh->dev;
1450 unsigned int index = a->index;
1451
Devin Heitmueller62899a22009-03-15 18:48:52 -03001452 if (a->index > 1)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001453 return -EINVAL;
1454
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001455 index = dev->ctrl_ainput;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001456 if (index == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001457 strcpy(a->name, "Television");
1458 else
1459 strcpy(a->name, "Line in");
1460
1461 a->capability = V4L2_AUDCAP_STEREO;
1462 a->index = index;
1463 return 0;
1464}
1465
1466static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
1467{
1468 struct au0828_fh *fh = priv;
1469 struct au0828_dev *dev = fh->dev;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001470 if (a->index != dev->ctrl_ainput)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001471 return -EINVAL;
1472 return 0;
1473}
1474
1475static int vidioc_g_ctrl(struct file *file, void *priv,
1476 struct v4l2_control *ctrl)
1477{
1478 struct au0828_fh *fh = priv;
1479 struct au0828_dev *dev = fh->dev;
1480
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001481 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001482 return 0;
1483
1484}
1485
1486static int vidioc_s_ctrl(struct file *file, void *priv,
1487 struct v4l2_control *ctrl)
1488{
1489 struct au0828_fh *fh = priv;
1490 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001491 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001492 return 0;
1493}
1494
1495static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
1496{
1497 struct au0828_fh *fh = priv;
1498 struct au0828_dev *dev = fh->dev;
1499
Devin Heitmueller62899a22009-03-15 18:48:52 -03001500 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001501 return -EINVAL;
1502
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001503 strcpy(t->name, "Auvitek tuner");
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001504 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001505 return 0;
1506}
1507
1508static int vidioc_s_tuner(struct file *file, void *priv,
1509 struct v4l2_tuner *t)
1510{
1511 struct au0828_fh *fh = priv;
1512 struct au0828_dev *dev = fh->dev;
1513
Devin Heitmueller62899a22009-03-15 18:48:52 -03001514 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001515 return -EINVAL;
1516
1517 t->type = V4L2_TUNER_ANALOG_TV;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001518 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001519 dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
1520 t->afc);
1521 return 0;
1522
1523}
1524
1525static int vidioc_g_frequency(struct file *file, void *priv,
1526 struct v4l2_frequency *freq)
1527{
1528 struct au0828_fh *fh = priv;
1529 struct au0828_dev *dev = fh->dev;
Devin Heitmuellerc8889232009-03-15 17:38:47 -03001530
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001531 freq->type = V4L2_TUNER_ANALOG_TV;
1532 freq->frequency = dev->ctrl_freq;
1533 return 0;
1534}
1535
1536static int vidioc_s_frequency(struct file *file, void *priv,
1537 struct v4l2_frequency *freq)
1538{
1539 struct au0828_fh *fh = priv;
1540 struct au0828_dev *dev = fh->dev;
1541
Devin Heitmueller62899a22009-03-15 18:48:52 -03001542 if (freq->tuner != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001543 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001544 if (freq->type != V4L2_TUNER_ANALOG_TV)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001545 return -EINVAL;
1546
1547 dev->ctrl_freq = freq->frequency;
1548
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001549 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001550
1551 au0828_analog_stream_reset(dev);
1552
1553 return 0;
1554}
1555
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001556
1557/* RAW VBI ioctls */
1558
1559static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1560 struct v4l2_format *format)
1561{
1562 struct au0828_fh *fh = priv;
1563 struct au0828_dev *dev = fh->dev;
1564
1565 format->fmt.vbi.samples_per_line = dev->vbi_width;
1566 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1567 format->fmt.vbi.offset = 0;
1568 format->fmt.vbi.flags = 0;
1569 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1570
1571 format->fmt.vbi.count[0] = dev->vbi_height;
1572 format->fmt.vbi.count[1] = dev->vbi_height;
1573 format->fmt.vbi.start[0] = 21;
1574 format->fmt.vbi.start[1] = 284;
1575
1576 return 0;
1577}
1578
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001579static int vidioc_g_chip_ident(struct file *file, void *priv,
1580 struct v4l2_dbg_chip_ident *chip)
1581{
1582 struct au0828_fh *fh = priv;
1583 struct au0828_dev *dev = fh->dev;
1584 chip->ident = V4L2_IDENT_NONE;
1585 chip->revision = 0;
1586
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001587 if (v4l2_chip_match_host(&chip->match)) {
1588 chip->ident = V4L2_IDENT_AU0828;
1589 return 0;
1590 }
1591
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001592 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001593 if (chip->ident == V4L2_IDENT_NONE)
1594 return -EINVAL;
1595
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001596 return 0;
1597}
1598
1599static int vidioc_cropcap(struct file *file, void *priv,
1600 struct v4l2_cropcap *cc)
1601{
1602 struct au0828_fh *fh = priv;
1603 struct au0828_dev *dev = fh->dev;
1604
Devin Heitmueller62899a22009-03-15 18:48:52 -03001605 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001606 return -EINVAL;
1607
1608 cc->bounds.left = 0;
1609 cc->bounds.top = 0;
1610 cc->bounds.width = dev->width;
1611 cc->bounds.height = dev->height;
1612
1613 cc->defrect = cc->bounds;
1614
1615 cc->pixelaspect.numerator = 54;
1616 cc->pixelaspect.denominator = 59;
1617
1618 return 0;
1619}
1620
1621static int vidioc_streamon(struct file *file, void *priv,
1622 enum v4l2_buf_type type)
1623{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001624 struct au0828_fh *fh = priv;
1625 struct au0828_dev *dev = fh->dev;
1626 int rc = -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001627
1628 rc = check_dev(dev);
1629 if (rc < 0)
1630 return rc;
1631
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001632 if (unlikely(type != fh->type))
1633 return -EINVAL;
1634
1635 dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
1636 fh, type, fh->resources, dev->resources);
1637
1638 if (unlikely(!res_get(fh, get_ressource(fh))))
1639 return -EBUSY;
1640
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001641 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1642 au0828_analog_stream_enable(dev);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001643 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001644 }
1645
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001646 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001647 rc = videobuf_streamon(&fh->vb_vidq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001648 dev->vid_timeout_running = 1;
1649 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
1650 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001651 rc = videobuf_streamon(&fh->vb_vbiq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001652 dev->vbi_timeout_running = 1;
1653 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1654 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001655
1656 return rc;
1657}
1658
1659static int vidioc_streamoff(struct file *file, void *priv,
1660 enum v4l2_buf_type type)
1661{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001662 struct au0828_fh *fh = priv;
1663 struct au0828_dev *dev = fh->dev;
1664 int rc;
1665 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001666
1667 rc = check_dev(dev);
1668 if (rc < 0)
1669 return rc;
1670
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001671 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1672 fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001673 return -EINVAL;
1674 if (type != fh->type)
1675 return -EINVAL;
1676
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001677 dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
1678 fh, type, fh->resources, dev->resources);
1679
1680 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001681 dev->vid_timeout_running = 0;
1682 del_timer_sync(&dev->vid_timeout);
1683
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001684 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001685 rc = au0828_stream_interrupt(dev);
1686 if (rc != 0)
1687 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001688
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001689 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1690 if (AUVI_INPUT(i).audio_setup == NULL)
1691 continue;
1692 (AUVI_INPUT(i).audio_setup)(dev, 0);
1693 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001694
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001695 videobuf_streamoff(&fh->vb_vidq);
1696 res_free(fh, AU0828_RESOURCE_VIDEO);
1697 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001698 dev->vbi_timeout_running = 0;
1699 del_timer_sync(&dev->vbi_timeout);
1700
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001701 videobuf_streamoff(&fh->vb_vbiq);
1702 res_free(fh, AU0828_RESOURCE_VBI);
1703 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001704
1705 return 0;
1706}
1707
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001708#ifdef CONFIG_VIDEO_ADV_DEBUG
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001709static int vidioc_g_register(struct file *file, void *priv,
1710 struct v4l2_dbg_register *reg)
1711{
1712 struct au0828_fh *fh = priv;
1713 struct au0828_dev *dev = fh->dev;
1714
1715 switch (reg->match.type) {
1716 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001717 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001718 return 0;
1719 default:
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001720 if (!v4l2_chip_match_host(&reg->match))
1721 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001722 }
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001723
1724 reg->val = au0828_read(dev, reg->reg);
1725 return 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001726}
1727
1728static int vidioc_s_register(struct file *file, void *priv,
1729 struct v4l2_dbg_register *reg)
1730{
1731 struct au0828_fh *fh = priv;
1732 struct au0828_dev *dev = fh->dev;
1733
1734 switch (reg->match.type) {
1735 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001736 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001737 return 0;
1738 default:
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001739 if (!v4l2_chip_match_host(&reg->match))
1740 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001741 }
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001742 return au0828_writereg(dev, reg->reg, reg->val);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001743}
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001744#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001745
1746static int vidioc_reqbufs(struct file *file, void *priv,
1747 struct v4l2_requestbuffers *rb)
1748{
1749 struct au0828_fh *fh = priv;
1750 struct au0828_dev *dev = fh->dev;
1751 int rc;
1752
1753 rc = check_dev(dev);
1754 if (rc < 0)
1755 return rc;
1756
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001757 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1758 rc = videobuf_reqbufs(&fh->vb_vidq, rb);
1759 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1760 rc = videobuf_reqbufs(&fh->vb_vbiq, rb);
1761
1762 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001763}
1764
1765static int vidioc_querybuf(struct file *file, void *priv,
1766 struct v4l2_buffer *b)
1767{
1768 struct au0828_fh *fh = priv;
1769 struct au0828_dev *dev = fh->dev;
1770 int rc;
1771
1772 rc = check_dev(dev);
1773 if (rc < 0)
1774 return rc;
1775
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001776 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1777 rc = videobuf_querybuf(&fh->vb_vidq, b);
1778 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1779 rc = videobuf_querybuf(&fh->vb_vbiq, b);
1780
1781 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001782}
1783
1784static int vidioc_qbuf(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
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001794 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1795 rc = videobuf_qbuf(&fh->vb_vidq, b);
1796 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1797 rc = videobuf_qbuf(&fh->vb_vbiq, b);
1798
1799 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001800}
1801
1802static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1803{
1804 struct au0828_fh *fh = priv;
1805 struct au0828_dev *dev = fh->dev;
1806 int rc;
1807
1808 rc = check_dev(dev);
1809 if (rc < 0)
1810 return rc;
1811
1812 /* Workaround for a bug in the au0828 hardware design that sometimes
1813 results in the colorspace being inverted */
1814 if (dev->greenscreen_detected == 1) {
1815 dprintk(1, "Detected green frame. Resetting stream...\n");
1816 au0828_analog_stream_reset(dev);
1817 dev->greenscreen_detected = 0;
1818 }
1819
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001820 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1821 rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1822 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1823 rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK);
1824
1825 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001826}
1827
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001828static struct v4l2_file_operations au0828_v4l_fops = {
1829 .owner = THIS_MODULE,
1830 .open = au0828_v4l2_open,
1831 .release = au0828_v4l2_close,
1832 .read = au0828_v4l2_read,
1833 .poll = au0828_v4l2_poll,
1834 .mmap = au0828_v4l2_mmap,
1835 .ioctl = video_ioctl2,
1836};
1837
1838static const struct v4l2_ioctl_ops video_ioctl_ops = {
1839 .vidioc_querycap = vidioc_querycap,
1840 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1841 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1842 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1843 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001844 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001845 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001846 .vidioc_g_audio = vidioc_g_audio,
1847 .vidioc_s_audio = vidioc_s_audio,
1848 .vidioc_cropcap = vidioc_cropcap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001849 .vidioc_reqbufs = vidioc_reqbufs,
1850 .vidioc_querybuf = vidioc_querybuf,
1851 .vidioc_qbuf = vidioc_qbuf,
1852 .vidioc_dqbuf = vidioc_dqbuf,
1853 .vidioc_s_std = vidioc_s_std,
1854 .vidioc_enum_input = vidioc_enum_input,
1855 .vidioc_g_input = vidioc_g_input,
1856 .vidioc_s_input = vidioc_s_input,
1857 .vidioc_queryctrl = vidioc_queryctrl,
1858 .vidioc_g_ctrl = vidioc_g_ctrl,
1859 .vidioc_s_ctrl = vidioc_s_ctrl,
1860 .vidioc_streamon = vidioc_streamon,
1861 .vidioc_streamoff = vidioc_streamoff,
1862 .vidioc_g_tuner = vidioc_g_tuner,
1863 .vidioc_s_tuner = vidioc_s_tuner,
1864 .vidioc_g_frequency = vidioc_g_frequency,
1865 .vidioc_s_frequency = vidioc_s_frequency,
1866#ifdef CONFIG_VIDEO_ADV_DEBUG
1867 .vidioc_g_register = vidioc_g_register,
1868 .vidioc_s_register = vidioc_s_register,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001869#endif
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001870 .vidioc_g_chip_ident = vidioc_g_chip_ident,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001871};
1872
1873static const struct video_device au0828_video_template = {
1874 .fops = &au0828_v4l_fops,
1875 .release = video_device_release,
1876 .ioctl_ops = &video_ioctl_ops,
Devin Heitmueller0ef210712009-03-11 03:00:53 -03001877 .tvnorms = V4L2_STD_NTSC_M,
1878 .current_norm = V4L2_STD_NTSC_M,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001879};
1880
1881/**************************************************************************/
1882
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001883int au0828_analog_register(struct au0828_dev *dev,
1884 struct usb_interface *interface)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001885{
1886 int retval = -ENOMEM;
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001887 struct usb_host_interface *iface_desc;
1888 struct usb_endpoint_descriptor *endpoint;
Julia Lawalld63b21b2012-04-22 07:54:42 -03001889 int i, ret;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001890
1891 dprintk(1, "au0828_analog_register called!\n");
1892
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001893 /* set au0828 usb interface0 to as5 */
1894 retval = usb_set_interface(dev->usbdev,
Devin Heitmueller62899a22009-03-15 18:48:52 -03001895 interface->cur_altsetting->desc.bInterfaceNumber, 5);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001896 if (retval != 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001897 printk(KERN_INFO "Failure setting usb interface0 to as5\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001898 return retval;
1899 }
1900
1901 /* Figure out which endpoint has the isoc interface */
1902 iface_desc = interface->cur_altsetting;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001903 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001904 endpoint = &iface_desc->endpoint[i].desc;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001905 if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1906 == USB_DIR_IN) &&
1907 ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1908 == USB_ENDPOINT_XFER_ISOC)) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001909
1910 /* we find our isoc in endpoint */
1911 u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001912 dev->max_pkt_size = (tmp & 0x07ff) *
1913 (((tmp & 0x1800) >> 11) + 1);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001914 dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
1915 }
1916 }
Devin Heitmueller62899a22009-03-15 18:48:52 -03001917 if (!(dev->isoc_in_endpointaddr)) {
1918 printk(KERN_INFO "Could not locate isoc endpoint\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001919 kfree(dev);
1920 return -ENODEV;
1921 }
1922
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001923 init_waitqueue_head(&dev->open);
1924 spin_lock_init(&dev->slock);
1925 mutex_init(&dev->lock);
1926
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001927 /* init video dma queues */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001928 INIT_LIST_HEAD(&dev->vidq.active);
1929 INIT_LIST_HEAD(&dev->vidq.queued);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001930 INIT_LIST_HEAD(&dev->vbiq.active);
1931 INIT_LIST_HEAD(&dev->vbiq.queued);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001932
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001933 dev->vid_timeout.function = au0828_vid_buffer_timeout;
1934 dev->vid_timeout.data = (unsigned long) dev;
1935 init_timer(&dev->vid_timeout);
1936
1937 dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
1938 dev->vbi_timeout.data = (unsigned long) dev;
1939 init_timer(&dev->vbi_timeout);
1940
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001941 dev->width = NTSC_STD_W;
1942 dev->height = NTSC_STD_H;
1943 dev->field_size = dev->width * dev->height;
1944 dev->frame_size = dev->field_size << 1;
1945 dev->bytesperline = dev->width << 1;
1946 dev->ctrl_ainput = 0;
1947
1948 /* allocate and fill v4l2 video struct */
1949 dev->vdev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001950 if (NULL == dev->vdev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001951 dprintk(1, "Can't allocate video_device.\n");
1952 return -ENOMEM;
1953 }
1954
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001955 /* allocate the VBI struct */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001956 dev->vbi_dev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001957 if (NULL == dev->vbi_dev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001958 dprintk(1, "Can't allocate vbi_device.\n");
Julia Lawalld63b21b2012-04-22 07:54:42 -03001959 ret = -ENOMEM;
1960 goto err_vdev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001961 }
1962
1963 /* Fill the video capture device struct */
1964 *dev->vdev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001965 dev->vdev->parent = &dev->usbdev->dev;
1966 strcpy(dev->vdev->name, "au0828a video");
1967
1968 /* Setup the VBI device */
1969 *dev->vbi_dev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001970 dev->vbi_dev->parent = &dev->usbdev->dev;
1971 strcpy(dev->vbi_dev->name, "au0828a vbi");
1972
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001973 /* Register the v4l2 device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001974 video_set_drvdata(dev->vdev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001975 retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1976 if (retval != 0) {
1977 dprintk(1, "unable to register video device (error = %d).\n",
1978 retval);
Julia Lawalld63b21b2012-04-22 07:54:42 -03001979 ret = -ENODEV;
1980 goto err_vbi_dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001981 }
1982
1983 /* Register the vbi device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001984 video_set_drvdata(dev->vbi_dev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001985 retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
1986 if (retval != 0) {
1987 dprintk(1, "unable to register vbi device (error = %d).\n",
1988 retval);
Julia Lawalld63b21b2012-04-22 07:54:42 -03001989 ret = -ENODEV;
1990 goto err_vbi_dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001991 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001992
Devin Heitmueller62899a22009-03-15 18:48:52 -03001993 dprintk(1, "%s completed!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001994
1995 return 0;
Julia Lawalld63b21b2012-04-22 07:54:42 -03001996
1997err_vbi_dev:
1998 video_device_release(dev->vbi_dev);
1999err_vdev:
2000 video_device_release(dev->vdev);
2001 return ret;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03002002}
2003