blob: b1f8d1856eec1f5fd31f7e7eea7e71fa55875a0a [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? */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300867 if (dev->resources & bit) {
868 /* no, someone else uses it */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300869 return 0;
870 }
871 /* it's free, grab it */
872 fh->resources |= bit;
873 dev->resources |= bit;
874 dprintk(1, "res: get %d\n", bit);
Devin Heitmueller549ee4d2012-08-06 22:46:58 -0300875
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300876 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300877}
878
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300879static int res_check(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300880{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300881 return fh->resources & bit;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300882}
883
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300884static int res_locked(struct au0828_dev *dev, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300885{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300886 return dev->resources & bit;
887}
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300888
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300889static void res_free(struct au0828_fh *fh, unsigned int bits)
890{
891 struct au0828_dev *dev = fh->dev;
892
893 BUG_ON((fh->resources & bits) != bits);
894
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300895 fh->resources &= ~bits;
896 dev->resources &= ~bits;
897 dprintk(1, "res: put %d\n", bits);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300898}
899
900static int get_ressource(struct au0828_fh *fh)
901{
902 switch (fh->type) {
903 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
904 return AU0828_RESOURCE_VIDEO;
905 case V4L2_BUF_TYPE_VBI_CAPTURE:
906 return AU0828_RESOURCE_VBI;
907 default:
908 BUG();
909 return 0;
910 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300911}
912
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300913/* This function ensures that video frames continue to be delivered even if
914 the ITU-656 input isn't receiving any data (thereby preventing applications
915 such as tvtime from hanging) */
916void au0828_vid_buffer_timeout(unsigned long data)
917{
918 struct au0828_dev *dev = (struct au0828_dev *) data;
919 struct au0828_dmaqueue *dma_q = &dev->vidq;
920 struct au0828_buffer *buf;
921 unsigned char *vid_data;
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300922 unsigned long flags = 0;
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300923
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300924 spin_lock_irqsave(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300925
926 buf = dev->isoc_ctl.buf;
927 if (buf != NULL) {
928 vid_data = videobuf_to_vmalloc(&buf->vb);
929 memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */
930 buffer_filled(dev, dma_q, buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300931 }
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300932 get_next_buf(dma_q, &buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300933
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300934 if (dev->vid_timeout_running == 1)
935 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
936
937 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300938}
939
940void au0828_vbi_buffer_timeout(unsigned long data)
941{
942 struct au0828_dev *dev = (struct au0828_dev *) data;
943 struct au0828_dmaqueue *dma_q = &dev->vbiq;
944 struct au0828_buffer *buf;
945 unsigned char *vbi_data;
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300946 unsigned long flags = 0;
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300947
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300948 spin_lock_irqsave(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300949
950 buf = dev->isoc_ctl.vbi_buf;
951 if (buf != NULL) {
952 vbi_data = videobuf_to_vmalloc(&buf->vb);
953 memset(vbi_data, 0x00, buf->vb.size);
954 vbi_buffer_filled(dev, dma_q, buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300955 }
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300956 vbi_get_next_buf(dma_q, &buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300957
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300958 if (dev->vbi_timeout_running == 1)
959 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
960 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300961}
962
963
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300964static int au0828_v4l2_open(struct file *filp)
965{
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300966 int ret = 0;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300967 struct video_device *vdev = video_devdata(filp);
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200968 struct au0828_dev *dev = video_drvdata(filp);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300969 struct au0828_fh *fh;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300970 int type;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300971
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300972 switch (vdev->vfl_type) {
973 case VFL_TYPE_GRABBER:
974 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
975 break;
976 case VFL_TYPE_VBI:
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200977 type = V4L2_BUF_TYPE_VBI_CAPTURE;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300978 break;
979 default:
980 return -EINVAL;
981 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300982
983 fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300984 if (NULL == fh) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300985 dprintk(1, "Failed allocate au0828_fh struct!\n");
986 return -ENOMEM;
987 }
988
989 fh->type = type;
990 fh->dev = dev;
991 filp->private_data = fh;
992
Devin Heitmueller62899a22009-03-15 18:48:52 -0300993 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300994 /* set au0828 interface0 to AS5 here again */
995 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300996 if (ret < 0) {
997 printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300998 return -EBUSY;
999 }
1000 dev->width = NTSC_STD_W;
1001 dev->height = NTSC_STD_H;
1002 dev->frame_size = dev->width * dev->height * 2;
1003 dev->field_size = dev->width * dev->height;
1004 dev->bytesperline = dev->width * 2;
1005
1006 au0828_analog_stream_enable(dev);
1007 au0828_analog_stream_reset(dev);
1008
1009 /* If we were doing ac97 instead of i2s, it would go here...*/
1010 au0828_i2s_init(dev);
1011
1012 dev->stream_state = STREAM_OFF;
1013 dev->dev_state |= DEV_INITIALIZED;
1014 }
1015
1016 dev->users++;
1017
1018 videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001019 NULL, &dev->slock,
1020 V4L2_BUF_TYPE_VIDEO_CAPTURE,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001021 V4L2_FIELD_INTERLACED,
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03001022 sizeof(struct au0828_buffer), fh,
1023 &dev->lock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001024
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001025 /* VBI Setup */
1026 dev->vbi_width = 720;
1027 dev->vbi_height = 1;
1028 videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops,
1029 NULL, &dev->slock,
1030 V4L2_BUF_TYPE_VBI_CAPTURE,
1031 V4L2_FIELD_SEQ_TB,
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03001032 sizeof(struct au0828_buffer), fh,
1033 &dev->lock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001034 return ret;
1035}
1036
1037static int au0828_v4l2_close(struct file *filp)
1038{
1039 int ret;
1040 struct au0828_fh *fh = filp->private_data;
1041 struct au0828_dev *dev = fh->dev;
1042
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001043 if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001044 /* Cancel timeout thread in case they didn't call streamoff */
1045 dev->vid_timeout_running = 0;
1046 del_timer_sync(&dev->vid_timeout);
1047
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001048 videobuf_stop(&fh->vb_vidq);
1049 res_free(fh, AU0828_RESOURCE_VIDEO);
1050 }
1051
1052 if (res_check(fh, AU0828_RESOURCE_VBI)) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001053 /* Cancel timeout thread in case they didn't call streamoff */
1054 dev->vbi_timeout_running = 0;
1055 del_timer_sync(&dev->vbi_timeout);
1056
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001057 videobuf_stop(&fh->vb_vbiq);
1058 res_free(fh, AU0828_RESOURCE_VBI);
1059 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001060
Devin Heitmueller62899a22009-03-15 18:48:52 -03001061 if (dev->users == 1) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001062 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001063 au0828_analog_unregister(dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001064 kfree(dev);
1065 return 0;
1066 }
1067
1068 au0828_analog_stream_disable(dev);
1069
1070 au0828_uninit_isoc(dev);
1071
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001072 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -03001073 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001074
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001075 /* When close the device, set the usb intf0 into alt0 to free
1076 USB bandwidth */
1077 ret = usb_set_interface(dev->usbdev, 0, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001078 if (ret < 0)
1079 printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001080 }
1081
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001082 videobuf_mmap_free(&fh->vb_vidq);
1083 videobuf_mmap_free(&fh->vb_vbiq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001084 kfree(fh);
1085 dev->users--;
1086 wake_up_interruptible_nr(&dev->open, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001087 return 0;
1088}
1089
1090static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
1091 size_t count, loff_t *pos)
1092{
1093 struct au0828_fh *fh = filp->private_data;
1094 struct au0828_dev *dev = fh->dev;
1095 int rc;
1096
1097 rc = check_dev(dev);
1098 if (rc < 0)
1099 return rc;
1100
Devin Heitmueller62899a22009-03-15 18:48:52 -03001101 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001102 if (res_locked(dev, AU0828_RESOURCE_VIDEO))
1103 return -EBUSY;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001104
1105 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
1106 filp->f_flags & O_NONBLOCK);
1107 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001108
1109 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1110 if (!res_get(fh, AU0828_RESOURCE_VBI))
1111 return -EBUSY;
1112
Devin Heitmuellerbf797162010-10-09 15:09:17 -03001113 if (dev->vbi_timeout_running == 0) {
1114 /* Handle case where caller tries to read without
1115 calling streamon first */
1116 dev->vbi_timeout_running = 1;
1117 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1118 }
1119
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001120 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
1121 filp->f_flags & O_NONBLOCK);
1122 }
1123
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001124 return 0;
1125}
1126
1127static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
1128{
1129 struct au0828_fh *fh = filp->private_data;
1130 struct au0828_dev *dev = fh->dev;
1131 int rc;
1132
1133 rc = check_dev(dev);
1134 if (rc < 0)
1135 return rc;
1136
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001137 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1138 if (!res_get(fh, AU0828_RESOURCE_VIDEO))
1139 return POLLERR;
1140 return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
1141 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1142 if (!res_get(fh, AU0828_RESOURCE_VBI))
1143 return POLLERR;
1144 return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
1145 } else {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001146 return POLLERR;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001147 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001148}
1149
1150static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
1151{
1152 struct au0828_fh *fh = filp->private_data;
1153 struct au0828_dev *dev = fh->dev;
1154 int rc;
1155
1156 rc = check_dev(dev);
1157 if (rc < 0)
1158 return rc;
1159
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001160 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1161 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
1162 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1163 rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001164
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001165 return rc;
1166}
1167
1168static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
1169 struct v4l2_format *format)
1170{
1171 int ret;
1172 int width = format->fmt.pix.width;
1173 int height = format->fmt.pix.height;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001174
Devin Heitmueller62899a22009-03-15 18:48:52 -03001175 if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001176 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001177
1178 /* If they are demanding a format other than the one we support,
1179 bail out (tvtime asks for UYVY and then retries with YUYV) */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001180 if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001181 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001182
1183 /* format->fmt.pix.width only support 720 and height 480 */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001184 if (width != 720)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001185 width = 720;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001186 if (height != 480)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001187 height = 480;
1188
1189 format->fmt.pix.width = width;
1190 format->fmt.pix.height = height;
1191 format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1192 format->fmt.pix.bytesperline = width * 2;
1193 format->fmt.pix.sizeimage = width * height * 2;
1194 format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1195 format->fmt.pix.field = V4L2_FIELD_INTERLACED;
1196
Devin Heitmueller62899a22009-03-15 18:48:52 -03001197 if (cmd == VIDIOC_TRY_FMT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001198 return 0;
1199
1200 /* maybe set new image format, driver current only support 720*480 */
1201 dev->width = width;
1202 dev->height = height;
1203 dev->frame_size = width * height * 2;
1204 dev->field_size = width * height;
1205 dev->bytesperline = width * 2;
1206
Devin Heitmueller62899a22009-03-15 18:48:52 -03001207 if (dev->stream_state == STREAM_ON) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001208 dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
Devin Heitmueller62899a22009-03-15 18:48:52 -03001209 ret = au0828_stream_interrupt(dev);
1210 if (ret != 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001211 dprintk(1, "error interrupting video stream!\n");
1212 return ret;
1213 }
1214 }
1215
1216 /* set au0828 interface0 to AS5 here again */
1217 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001218 if (ret < 0) {
1219 printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001220 return -EBUSY;
1221 }
1222
1223 au0828_analog_stream_enable(dev);
1224
1225 return 0;
1226}
1227
1228
1229static int vidioc_queryctrl(struct file *file, void *priv,
1230 struct v4l2_queryctrl *qc)
1231{
1232 struct au0828_fh *fh = priv;
1233 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001234 v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001235 if (qc->type)
1236 return 0;
1237 else
1238 return -EINVAL;
1239}
1240
1241static int vidioc_querycap(struct file *file, void *priv,
1242 struct v4l2_capability *cap)
1243{
1244 struct au0828_fh *fh = priv;
1245 struct au0828_dev *dev = fh->dev;
1246
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001247 strlcpy(cap->driver, "au0828", sizeof(cap->driver));
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001248 strlcpy(cap->card, dev->board.name, sizeof(cap->card));
Devin Heitmuellerb14667f2009-03-11 03:01:04 -03001249 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001250
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001251 /*set the device capabilities */
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001252 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001253 V4L2_CAP_VBI_CAPTURE |
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001254 V4L2_CAP_AUDIO |
1255 V4L2_CAP_READWRITE |
1256 V4L2_CAP_STREAMING |
1257 V4L2_CAP_TUNER;
1258 return 0;
1259}
1260
1261static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1262 struct v4l2_fmtdesc *f)
1263{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001264 if (f->index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001265 return -EINVAL;
1266
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001267 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1268 strcpy(f->description, "Packed YUV2");
1269
1270 f->flags = 0;
1271 f->pixelformat = V4L2_PIX_FMT_UYVY;
1272
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001273 return 0;
1274}
1275
1276static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1277 struct v4l2_format *f)
1278{
1279 struct au0828_fh *fh = priv;
1280 struct au0828_dev *dev = fh->dev;
1281
1282 f->fmt.pix.width = dev->width;
1283 f->fmt.pix.height = dev->height;
1284 f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1285 f->fmt.pix.bytesperline = dev->bytesperline;
1286 f->fmt.pix.sizeimage = dev->frame_size;
1287 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
1288 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1289 return 0;
1290}
1291
1292static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1293 struct v4l2_format *f)
1294{
1295 struct au0828_fh *fh = priv;
1296 struct au0828_dev *dev = fh->dev;
1297
1298 return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
1299}
1300
1301static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1302 struct v4l2_format *f)
1303{
1304 struct au0828_fh *fh = priv;
1305 struct au0828_dev *dev = fh->dev;
1306 int rc;
1307
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001308 rc = check_dev(dev);
1309 if (rc < 0)
1310 return rc;
1311
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001312 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001313 printk(KERN_INFO "%s queue busy\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001314 rc = -EBUSY;
1315 goto out;
1316 }
1317
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001318 rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001319out:
1320 return rc;
1321}
1322
1323static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
1324{
1325 struct au0828_fh *fh = priv;
1326 struct au0828_dev *dev = fh->dev;
1327
1328 /* FIXME: when we support something other than NTSC, we are going to
1329 have to make the au0828 bridge adjust the size of its capture
1330 buffer, which is currently hardcoded at 720x480 */
1331
Hans Verkuilf41737e2009-04-01 03:52:39 -03001332 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001333 return 0;
1334}
1335
1336static int vidioc_enum_input(struct file *file, void *priv,
1337 struct v4l2_input *input)
1338{
1339 struct au0828_fh *fh = priv;
1340 struct au0828_dev *dev = fh->dev;
1341 unsigned int tmp;
1342
1343 static const char *inames[] = {
Devin Heitmueller3d622872009-03-15 17:48:26 -03001344 [AU0828_VMUX_UNDEFINED] = "Undefined",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001345 [AU0828_VMUX_COMPOSITE] = "Composite",
1346 [AU0828_VMUX_SVIDEO] = "S-Video",
1347 [AU0828_VMUX_CABLE] = "Cable TV",
1348 [AU0828_VMUX_TELEVISION] = "Television",
1349 [AU0828_VMUX_DVB] = "DVB",
1350 [AU0828_VMUX_DEBUG] = "tv debug"
1351 };
1352
1353 tmp = input->index;
1354
Dan Carpenterf5e20c32010-03-28 08:21:18 -03001355 if (tmp >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001356 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001357 if (AUVI_INPUT(tmp).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001358 return -EINVAL;
1359
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001360 input->index = tmp;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001361 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001362 if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
1363 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001364 input->type |= V4L2_INPUT_TYPE_TUNER;
1365 else
1366 input->type |= V4L2_INPUT_TYPE_CAMERA;
1367
1368 input->std = dev->vdev->tvnorms;
1369
1370 return 0;
1371}
1372
1373static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1374{
1375 struct au0828_fh *fh = priv;
1376 struct au0828_dev *dev = fh->dev;
1377 *i = dev->ctrl_input;
1378 return 0;
1379}
1380
1381static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1382{
1383 struct au0828_fh *fh = priv;
1384 struct au0828_dev *dev = fh->dev;
1385 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001386
Devin Heitmueller62899a22009-03-15 18:48:52 -03001387 dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001388 index);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001389 if (index >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001390 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001391 if (AUVI_INPUT(index).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001392 return -EINVAL;
1393 dev->ctrl_input = index;
1394
Devin Heitmueller62899a22009-03-15 18:48:52 -03001395 switch (AUVI_INPUT(index).type) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001396 case AU0828_VMUX_SVIDEO:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001397 dev->input_type = AU0828_VMUX_SVIDEO;
1398 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001399 case AU0828_VMUX_COMPOSITE:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001400 dev->input_type = AU0828_VMUX_COMPOSITE;
1401 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001402 case AU0828_VMUX_TELEVISION:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001403 dev->input_type = AU0828_VMUX_TELEVISION;
1404 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001405 default:
Devin Heitmuellera1094c42009-03-15 17:43:13 -03001406 dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
1407 AUVI_INPUT(index).type);
1408 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001409 }
1410
Hans Verkuil5325b422009-04-02 11:26:22 -03001411 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1412 AUVI_INPUT(index).vmux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001413
1414 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1415 int enable = 0;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001416 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001417 continue;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001418
1419 if (i == index)
1420 enable = 1;
1421 else
1422 enable = 0;
1423 if (enable) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001424 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001425 } else {
1426 /* Make sure we leave it turned on if some
1427 other input is routed to this callback */
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001428 if ((AUVI_INPUT(i).audio_setup) !=
1429 ((AUVI_INPUT(index).audio_setup))) {
1430 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001431 }
1432 }
1433 }
1434
Hans Verkuil5325b422009-04-02 11:26:22 -03001435 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1436 AUVI_INPUT(index).amux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001437 return 0;
1438}
1439
1440static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1441{
1442 struct au0828_fh *fh = priv;
1443 struct au0828_dev *dev = fh->dev;
1444 unsigned int index = a->index;
1445
Devin Heitmueller62899a22009-03-15 18:48:52 -03001446 if (a->index > 1)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001447 return -EINVAL;
1448
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001449 index = dev->ctrl_ainput;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001450 if (index == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001451 strcpy(a->name, "Television");
1452 else
1453 strcpy(a->name, "Line in");
1454
1455 a->capability = V4L2_AUDCAP_STEREO;
1456 a->index = index;
1457 return 0;
1458}
1459
1460static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
1461{
1462 struct au0828_fh *fh = priv;
1463 struct au0828_dev *dev = fh->dev;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001464 if (a->index != dev->ctrl_ainput)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001465 return -EINVAL;
1466 return 0;
1467}
1468
1469static int vidioc_g_ctrl(struct file *file, void *priv,
1470 struct v4l2_control *ctrl)
1471{
1472 struct au0828_fh *fh = priv;
1473 struct au0828_dev *dev = fh->dev;
1474
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001475 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001476 return 0;
1477
1478}
1479
1480static int vidioc_s_ctrl(struct file *file, void *priv,
1481 struct v4l2_control *ctrl)
1482{
1483 struct au0828_fh *fh = priv;
1484 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001485 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001486 return 0;
1487}
1488
1489static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
1490{
1491 struct au0828_fh *fh = priv;
1492 struct au0828_dev *dev = fh->dev;
1493
Devin Heitmueller62899a22009-03-15 18:48:52 -03001494 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001495 return -EINVAL;
1496
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001497 strcpy(t->name, "Auvitek tuner");
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001498 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001499 return 0;
1500}
1501
1502static int vidioc_s_tuner(struct file *file, void *priv,
1503 struct v4l2_tuner *t)
1504{
1505 struct au0828_fh *fh = priv;
1506 struct au0828_dev *dev = fh->dev;
1507
Devin Heitmueller62899a22009-03-15 18:48:52 -03001508 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001509 return -EINVAL;
1510
1511 t->type = V4L2_TUNER_ANALOG_TV;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001512 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001513 dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
1514 t->afc);
1515 return 0;
1516
1517}
1518
1519static int vidioc_g_frequency(struct file *file, void *priv,
1520 struct v4l2_frequency *freq)
1521{
1522 struct au0828_fh *fh = priv;
1523 struct au0828_dev *dev = fh->dev;
Devin Heitmuellerc8889232009-03-15 17:38:47 -03001524
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001525 freq->type = V4L2_TUNER_ANALOG_TV;
1526 freq->frequency = dev->ctrl_freq;
1527 return 0;
1528}
1529
1530static int vidioc_s_frequency(struct file *file, void *priv,
1531 struct v4l2_frequency *freq)
1532{
1533 struct au0828_fh *fh = priv;
1534 struct au0828_dev *dev = fh->dev;
1535
Devin Heitmueller62899a22009-03-15 18:48:52 -03001536 if (freq->tuner != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001537 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001538 if (freq->type != V4L2_TUNER_ANALOG_TV)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001539 return -EINVAL;
1540
1541 dev->ctrl_freq = freq->frequency;
1542
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001543 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001544
1545 au0828_analog_stream_reset(dev);
1546
1547 return 0;
1548}
1549
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001550
1551/* RAW VBI ioctls */
1552
1553static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1554 struct v4l2_format *format)
1555{
1556 struct au0828_fh *fh = priv;
1557 struct au0828_dev *dev = fh->dev;
1558
1559 format->fmt.vbi.samples_per_line = dev->vbi_width;
1560 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1561 format->fmt.vbi.offset = 0;
1562 format->fmt.vbi.flags = 0;
1563 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1564
1565 format->fmt.vbi.count[0] = dev->vbi_height;
1566 format->fmt.vbi.count[1] = dev->vbi_height;
1567 format->fmt.vbi.start[0] = 21;
1568 format->fmt.vbi.start[1] = 284;
1569
1570 return 0;
1571}
1572
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001573static int vidioc_g_chip_ident(struct file *file, void *priv,
1574 struct v4l2_dbg_chip_ident *chip)
1575{
1576 struct au0828_fh *fh = priv;
1577 struct au0828_dev *dev = fh->dev;
1578 chip->ident = V4L2_IDENT_NONE;
1579 chip->revision = 0;
1580
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001581 if (v4l2_chip_match_host(&chip->match)) {
1582 chip->ident = V4L2_IDENT_AU0828;
1583 return 0;
1584 }
1585
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001586 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001587 if (chip->ident == V4L2_IDENT_NONE)
1588 return -EINVAL;
1589
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001590 return 0;
1591}
1592
1593static int vidioc_cropcap(struct file *file, void *priv,
1594 struct v4l2_cropcap *cc)
1595{
1596 struct au0828_fh *fh = priv;
1597 struct au0828_dev *dev = fh->dev;
1598
Devin Heitmueller62899a22009-03-15 18:48:52 -03001599 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001600 return -EINVAL;
1601
1602 cc->bounds.left = 0;
1603 cc->bounds.top = 0;
1604 cc->bounds.width = dev->width;
1605 cc->bounds.height = dev->height;
1606
1607 cc->defrect = cc->bounds;
1608
1609 cc->pixelaspect.numerator = 54;
1610 cc->pixelaspect.denominator = 59;
1611
1612 return 0;
1613}
1614
1615static int vidioc_streamon(struct file *file, void *priv,
1616 enum v4l2_buf_type type)
1617{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001618 struct au0828_fh *fh = priv;
1619 struct au0828_dev *dev = fh->dev;
1620 int rc = -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001621
1622 rc = check_dev(dev);
1623 if (rc < 0)
1624 return rc;
1625
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001626 if (unlikely(type != fh->type))
1627 return -EINVAL;
1628
1629 dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
1630 fh, type, fh->resources, dev->resources);
1631
1632 if (unlikely(!res_get(fh, get_ressource(fh))))
1633 return -EBUSY;
1634
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001635 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1636 au0828_analog_stream_enable(dev);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001637 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001638 }
1639
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001640 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001641 rc = videobuf_streamon(&fh->vb_vidq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001642 dev->vid_timeout_running = 1;
1643 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
1644 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001645 rc = videobuf_streamon(&fh->vb_vbiq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001646 dev->vbi_timeout_running = 1;
1647 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1648 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001649
1650 return rc;
1651}
1652
1653static int vidioc_streamoff(struct file *file, void *priv,
1654 enum v4l2_buf_type type)
1655{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001656 struct au0828_fh *fh = priv;
1657 struct au0828_dev *dev = fh->dev;
1658 int rc;
1659 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001660
1661 rc = check_dev(dev);
1662 if (rc < 0)
1663 return rc;
1664
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001665 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1666 fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001667 return -EINVAL;
1668 if (type != fh->type)
1669 return -EINVAL;
1670
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001671 dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
1672 fh, type, fh->resources, dev->resources);
1673
1674 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001675 dev->vid_timeout_running = 0;
1676 del_timer_sync(&dev->vid_timeout);
1677
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001678 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001679 rc = au0828_stream_interrupt(dev);
1680 if (rc != 0)
1681 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001682
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001683 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1684 if (AUVI_INPUT(i).audio_setup == NULL)
1685 continue;
1686 (AUVI_INPUT(i).audio_setup)(dev, 0);
1687 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001688
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001689 videobuf_streamoff(&fh->vb_vidq);
1690 res_free(fh, AU0828_RESOURCE_VIDEO);
1691 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001692 dev->vbi_timeout_running = 0;
1693 del_timer_sync(&dev->vbi_timeout);
1694
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001695 videobuf_streamoff(&fh->vb_vbiq);
1696 res_free(fh, AU0828_RESOURCE_VBI);
1697 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001698
1699 return 0;
1700}
1701
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001702#ifdef CONFIG_VIDEO_ADV_DEBUG
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001703static int vidioc_g_register(struct file *file, void *priv,
1704 struct v4l2_dbg_register *reg)
1705{
1706 struct au0828_fh *fh = priv;
1707 struct au0828_dev *dev = fh->dev;
1708
1709 switch (reg->match.type) {
1710 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001711 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001712 return 0;
1713 default:
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001714 if (!v4l2_chip_match_host(&reg->match))
1715 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001716 }
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001717
1718 reg->val = au0828_read(dev, reg->reg);
1719 return 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001720}
1721
1722static int vidioc_s_register(struct file *file, void *priv,
1723 struct v4l2_dbg_register *reg)
1724{
1725 struct au0828_fh *fh = priv;
1726 struct au0828_dev *dev = fh->dev;
1727
1728 switch (reg->match.type) {
1729 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001730 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001731 return 0;
1732 default:
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001733 if (!v4l2_chip_match_host(&reg->match))
1734 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001735 }
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001736 return au0828_writereg(dev, reg->reg, reg->val);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001737}
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001738#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001739
1740static int vidioc_reqbufs(struct file *file, void *priv,
1741 struct v4l2_requestbuffers *rb)
1742{
1743 struct au0828_fh *fh = priv;
1744 struct au0828_dev *dev = fh->dev;
1745 int rc;
1746
1747 rc = check_dev(dev);
1748 if (rc < 0)
1749 return rc;
1750
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001751 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1752 rc = videobuf_reqbufs(&fh->vb_vidq, rb);
1753 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1754 rc = videobuf_reqbufs(&fh->vb_vbiq, rb);
1755
1756 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001757}
1758
1759static int vidioc_querybuf(struct file *file, void *priv,
1760 struct v4l2_buffer *b)
1761{
1762 struct au0828_fh *fh = priv;
1763 struct au0828_dev *dev = fh->dev;
1764 int rc;
1765
1766 rc = check_dev(dev);
1767 if (rc < 0)
1768 return rc;
1769
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001770 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1771 rc = videobuf_querybuf(&fh->vb_vidq, b);
1772 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1773 rc = videobuf_querybuf(&fh->vb_vbiq, b);
1774
1775 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001776}
1777
1778static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1779{
1780 struct au0828_fh *fh = priv;
1781 struct au0828_dev *dev = fh->dev;
1782 int rc;
1783
1784 rc = check_dev(dev);
1785 if (rc < 0)
1786 return rc;
1787
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001788 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1789 rc = videobuf_qbuf(&fh->vb_vidq, b);
1790 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1791 rc = videobuf_qbuf(&fh->vb_vbiq, b);
1792
1793 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001794}
1795
1796static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1797{
1798 struct au0828_fh *fh = priv;
1799 struct au0828_dev *dev = fh->dev;
1800 int rc;
1801
1802 rc = check_dev(dev);
1803 if (rc < 0)
1804 return rc;
1805
1806 /* Workaround for a bug in the au0828 hardware design that sometimes
1807 results in the colorspace being inverted */
1808 if (dev->greenscreen_detected == 1) {
1809 dprintk(1, "Detected green frame. Resetting stream...\n");
1810 au0828_analog_stream_reset(dev);
1811 dev->greenscreen_detected = 0;
1812 }
1813
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001814 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1815 rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1816 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1817 rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK);
1818
1819 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001820}
1821
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001822static struct v4l2_file_operations au0828_v4l_fops = {
1823 .owner = THIS_MODULE,
1824 .open = au0828_v4l2_open,
1825 .release = au0828_v4l2_close,
1826 .read = au0828_v4l2_read,
1827 .poll = au0828_v4l2_poll,
1828 .mmap = au0828_v4l2_mmap,
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03001829 .unlocked_ioctl = video_ioctl2,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001830};
1831
1832static const struct v4l2_ioctl_ops video_ioctl_ops = {
1833 .vidioc_querycap = vidioc_querycap,
1834 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1835 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1836 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1837 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001838 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001839 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001840 .vidioc_g_audio = vidioc_g_audio,
1841 .vidioc_s_audio = vidioc_s_audio,
1842 .vidioc_cropcap = vidioc_cropcap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001843 .vidioc_reqbufs = vidioc_reqbufs,
1844 .vidioc_querybuf = vidioc_querybuf,
1845 .vidioc_qbuf = vidioc_qbuf,
1846 .vidioc_dqbuf = vidioc_dqbuf,
1847 .vidioc_s_std = vidioc_s_std,
1848 .vidioc_enum_input = vidioc_enum_input,
1849 .vidioc_g_input = vidioc_g_input,
1850 .vidioc_s_input = vidioc_s_input,
1851 .vidioc_queryctrl = vidioc_queryctrl,
1852 .vidioc_g_ctrl = vidioc_g_ctrl,
1853 .vidioc_s_ctrl = vidioc_s_ctrl,
1854 .vidioc_streamon = vidioc_streamon,
1855 .vidioc_streamoff = vidioc_streamoff,
1856 .vidioc_g_tuner = vidioc_g_tuner,
1857 .vidioc_s_tuner = vidioc_s_tuner,
1858 .vidioc_g_frequency = vidioc_g_frequency,
1859 .vidioc_s_frequency = vidioc_s_frequency,
1860#ifdef CONFIG_VIDEO_ADV_DEBUG
1861 .vidioc_g_register = vidioc_g_register,
1862 .vidioc_s_register = vidioc_s_register,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001863#endif
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001864 .vidioc_g_chip_ident = vidioc_g_chip_ident,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001865};
1866
1867static const struct video_device au0828_video_template = {
1868 .fops = &au0828_v4l_fops,
1869 .release = video_device_release,
1870 .ioctl_ops = &video_ioctl_ops,
Devin Heitmueller0ef210712009-03-11 03:00:53 -03001871 .tvnorms = V4L2_STD_NTSC_M,
1872 .current_norm = V4L2_STD_NTSC_M,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001873};
1874
1875/**************************************************************************/
1876
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001877int au0828_analog_register(struct au0828_dev *dev,
1878 struct usb_interface *interface)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001879{
1880 int retval = -ENOMEM;
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001881 struct usb_host_interface *iface_desc;
1882 struct usb_endpoint_descriptor *endpoint;
Julia Lawalld63b21b2012-04-22 07:54:42 -03001883 int i, ret;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001884
1885 dprintk(1, "au0828_analog_register called!\n");
1886
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001887 /* set au0828 usb interface0 to as5 */
1888 retval = usb_set_interface(dev->usbdev,
Devin Heitmueller62899a22009-03-15 18:48:52 -03001889 interface->cur_altsetting->desc.bInterfaceNumber, 5);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001890 if (retval != 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001891 printk(KERN_INFO "Failure setting usb interface0 to as5\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001892 return retval;
1893 }
1894
1895 /* Figure out which endpoint has the isoc interface */
1896 iface_desc = interface->cur_altsetting;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001897 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001898 endpoint = &iface_desc->endpoint[i].desc;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001899 if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1900 == USB_DIR_IN) &&
1901 ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1902 == USB_ENDPOINT_XFER_ISOC)) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001903
1904 /* we find our isoc in endpoint */
1905 u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001906 dev->max_pkt_size = (tmp & 0x07ff) *
1907 (((tmp & 0x1800) >> 11) + 1);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001908 dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
1909 }
1910 }
Devin Heitmueller62899a22009-03-15 18:48:52 -03001911 if (!(dev->isoc_in_endpointaddr)) {
1912 printk(KERN_INFO "Could not locate isoc endpoint\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001913 kfree(dev);
1914 return -ENODEV;
1915 }
1916
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001917 init_waitqueue_head(&dev->open);
1918 spin_lock_init(&dev->slock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001919
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001920 /* init video dma queues */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001921 INIT_LIST_HEAD(&dev->vidq.active);
1922 INIT_LIST_HEAD(&dev->vidq.queued);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001923 INIT_LIST_HEAD(&dev->vbiq.active);
1924 INIT_LIST_HEAD(&dev->vbiq.queued);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001925
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001926 dev->vid_timeout.function = au0828_vid_buffer_timeout;
1927 dev->vid_timeout.data = (unsigned long) dev;
1928 init_timer(&dev->vid_timeout);
1929
1930 dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
1931 dev->vbi_timeout.data = (unsigned long) dev;
1932 init_timer(&dev->vbi_timeout);
1933
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001934 dev->width = NTSC_STD_W;
1935 dev->height = NTSC_STD_H;
1936 dev->field_size = dev->width * dev->height;
1937 dev->frame_size = dev->field_size << 1;
1938 dev->bytesperline = dev->width << 1;
1939 dev->ctrl_ainput = 0;
1940
1941 /* allocate and fill v4l2 video struct */
1942 dev->vdev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001943 if (NULL == dev->vdev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001944 dprintk(1, "Can't allocate video_device.\n");
1945 return -ENOMEM;
1946 }
1947
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001948 /* allocate the VBI struct */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001949 dev->vbi_dev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001950 if (NULL == dev->vbi_dev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001951 dprintk(1, "Can't allocate vbi_device.\n");
Julia Lawalld63b21b2012-04-22 07:54:42 -03001952 ret = -ENOMEM;
1953 goto err_vdev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001954 }
1955
1956 /* Fill the video capture device struct */
1957 *dev->vdev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001958 dev->vdev->parent = &dev->usbdev->dev;
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03001959 dev->vdev->lock = &dev->lock;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001960 strcpy(dev->vdev->name, "au0828a video");
1961
1962 /* Setup the VBI device */
1963 *dev->vbi_dev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001964 dev->vbi_dev->parent = &dev->usbdev->dev;
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03001965 dev->vbi_dev->lock = &dev->lock;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001966 strcpy(dev->vbi_dev->name, "au0828a vbi");
1967
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001968 /* Register the v4l2 device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001969 video_set_drvdata(dev->vdev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001970 retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1971 if (retval != 0) {
1972 dprintk(1, "unable to register video device (error = %d).\n",
1973 retval);
Julia Lawalld63b21b2012-04-22 07:54:42 -03001974 ret = -ENODEV;
1975 goto err_vbi_dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001976 }
1977
1978 /* Register the vbi device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001979 video_set_drvdata(dev->vbi_dev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001980 retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
1981 if (retval != 0) {
1982 dprintk(1, "unable to register vbi device (error = %d).\n",
1983 retval);
Julia Lawalld63b21b2012-04-22 07:54:42 -03001984 ret = -ENODEV;
1985 goto err_vbi_dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001986 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001987
Devin Heitmueller62899a22009-03-15 18:48:52 -03001988 dprintk(1, "%s completed!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001989
1990 return 0;
Julia Lawalld63b21b2012-04-22 07:54:42 -03001991
1992err_vbi_dev:
1993 video_device_release(dev->vbi_dev);
1994err_vdev:
1995 video_device_release(dev->vdev);
1996 return ret;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001997}
1998