blob: 13a8a1db53492c0122e1d296b99a2117d1e6ec3a [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>
32#include <linux/init.h>
33#include <linux/device.h>
34#include <linux/suspend.h>
35#include <linux/version.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
45#define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1)
46
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030047/* ------------------------------------------------------------------
48 Videobuf operations
49 ------------------------------------------------------------------*/
50
51static unsigned int isoc_debug;
52module_param(isoc_debug, int, 0644);
53MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
54
55#define au0828_isocdbg(fmt, arg...) \
56do {\
57 if (isoc_debug) { \
58 printk(KERN_INFO "au0828 %s :"fmt, \
59 __func__ , ##arg); \
60 } \
61 } while (0)
62
63static inline void print_err_status(struct au0828_dev *dev,
64 int packet, int status)
65{
66 char *errmsg = "Unknown";
67
68 switch (status) {
69 case -ENOENT:
70 errmsg = "unlinked synchronuously";
71 break;
72 case -ECONNRESET:
73 errmsg = "unlinked asynchronuously";
74 break;
75 case -ENOSR:
76 errmsg = "Buffer error (overrun)";
77 break;
78 case -EPIPE:
79 errmsg = "Stalled (device not responding)";
80 break;
81 case -EOVERFLOW:
82 errmsg = "Babble (bad cable?)";
83 break;
84 case -EPROTO:
85 errmsg = "Bit-stuff error (bad cable?)";
86 break;
87 case -EILSEQ:
88 errmsg = "CRC/Timeout (could be anything)";
89 break;
90 case -ETIME:
91 errmsg = "Device does not respond";
92 break;
93 }
94 if (packet < 0) {
95 au0828_isocdbg("URB status %d [%s].\n", status, errmsg);
96 } else {
97 au0828_isocdbg("URB packet %d, status %d [%s].\n",
98 packet, status, errmsg);
99 }
100}
101
102static int check_dev(struct au0828_dev *dev)
103{
104 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300105 printk(KERN_INFO "v4l2 ioctl: device not present\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300106 return -ENODEV;
107 }
108
109 if (dev->dev_state & DEV_MISCONFIGURED) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300110 printk(KERN_INFO "v4l2 ioctl: device is misconfigured; "
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300111 "close and open it again\n");
112 return -EIO;
113 }
114 return 0;
115}
116
117/*
118 * IRQ callback, called by URB callback
119 */
120static void au0828_irq_callback(struct urb *urb)
121{
122 struct au0828_dmaqueue *dma_q = urb->context;
123 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
124 int rc, i;
125
126 switch (urb->status) {
127 case 0: /* success */
128 case -ETIMEDOUT: /* NAK */
129 break;
130 case -ECONNRESET: /* kill */
131 case -ENOENT:
132 case -ESHUTDOWN:
133 au0828_isocdbg("au0828_irq_callback called: status kill\n");
134 return;
135 default: /* unknown error */
136 au0828_isocdbg("urb completition error %d.\n", urb->status);
137 break;
138 }
139
140 /* Copy data from URB */
141 spin_lock(&dev->slock);
142 rc = dev->isoc_ctl.isoc_copy(dev, urb);
143 spin_unlock(&dev->slock);
144
145 /* Reset urb buffers */
146 for (i = 0; i < urb->number_of_packets; i++) {
147 urb->iso_frame_desc[i].status = 0;
148 urb->iso_frame_desc[i].actual_length = 0;
149 }
150 urb->status = 0;
151
152 urb->status = usb_submit_urb(urb, GFP_ATOMIC);
153 if (urb->status) {
154 au0828_isocdbg("urb resubmit failed (error=%i)\n",
155 urb->status);
156 }
157}
158
159/*
160 * Stop and Deallocate URBs
161 */
162void au0828_uninit_isoc(struct au0828_dev *dev)
163{
164 struct urb *urb;
165 int i;
166
167 au0828_isocdbg("au0828: called au0828_uninit_isoc\n");
168
169 dev->isoc_ctl.nfields = -1;
170 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
171 urb = dev->isoc_ctl.urb[i];
172 if (urb) {
173 if (!irqs_disabled())
174 usb_kill_urb(urb);
175 else
176 usb_unlink_urb(urb);
177
178 if (dev->isoc_ctl.transfer_buffer[i]) {
179 usb_buffer_free(dev->usbdev,
180 urb->transfer_buffer_length,
181 dev->isoc_ctl.transfer_buffer[i],
182 urb->transfer_dma);
183 }
184 usb_free_urb(urb);
185 dev->isoc_ctl.urb[i] = NULL;
186 }
187 dev->isoc_ctl.transfer_buffer[i] = NULL;
188 }
189
190 kfree(dev->isoc_ctl.urb);
191 kfree(dev->isoc_ctl.transfer_buffer);
192
193 dev->isoc_ctl.urb = NULL;
194 dev->isoc_ctl.transfer_buffer = NULL;
195 dev->isoc_ctl.num_bufs = 0;
196}
197
198/*
199 * Allocate URBs and start IRQ
200 */
201int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
202 int num_bufs, int max_pkt_size,
203 int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
204{
205 struct au0828_dmaqueue *dma_q = &dev->vidq;
206 int i;
207 int sb_size, pipe;
208 struct urb *urb;
209 int j, k;
210 int rc;
211
212 au0828_isocdbg("au0828: called au0828_prepare_isoc\n");
213
214 /* De-allocates all pending stuff */
215 au0828_uninit_isoc(dev);
216
217 dev->isoc_ctl.isoc_copy = isoc_copy;
218 dev->isoc_ctl.num_bufs = num_bufs;
219
220 dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
221 if (!dev->isoc_ctl.urb) {
222 au0828_isocdbg("cannot alloc memory for usb buffers\n");
223 return -ENOMEM;
224 }
225
226 dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
227 GFP_KERNEL);
228 if (!dev->isoc_ctl.transfer_buffer) {
229 au0828_isocdbg("cannot allocate memory for usb transfer\n");
230 kfree(dev->isoc_ctl.urb);
231 return -ENOMEM;
232 }
233
234 dev->isoc_ctl.max_pkt_size = max_pkt_size;
235 dev->isoc_ctl.buf = NULL;
236
237 sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
238
239 /* allocate urbs and transfer buffers */
240 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
241 urb = usb_alloc_urb(max_packets, GFP_KERNEL);
242 if (!urb) {
243 au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i);
244 au0828_uninit_isoc(dev);
245 return -ENOMEM;
246 }
247 dev->isoc_ctl.urb[i] = urb;
248
249 dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->usbdev,
250 sb_size, GFP_KERNEL, &urb->transfer_dma);
251 if (!dev->isoc_ctl.transfer_buffer[i]) {
252 printk("unable to allocate %i bytes for transfer"
253 " buffer %i%s\n",
254 sb_size, i,
255 in_interrupt() ? " while in int" : "");
256 au0828_uninit_isoc(dev);
257 return -ENOMEM;
258 }
259 memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
260
261 pipe = usb_rcvisocpipe(dev->usbdev,
262 dev->isoc_in_endpointaddr),
263
264 usb_fill_int_urb(urb, dev->usbdev, pipe,
265 dev->isoc_ctl.transfer_buffer[i], sb_size,
266 au0828_irq_callback, dma_q, 1);
267
268 urb->number_of_packets = max_packets;
Devin Heitmuellerfadadb72009-03-22 23:42:26 -0300269 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300270
271 k = 0;
272 for (j = 0; j < max_packets; j++) {
273 urb->iso_frame_desc[j].offset = k;
274 urb->iso_frame_desc[j].length =
275 dev->isoc_ctl.max_pkt_size;
276 k += dev->isoc_ctl.max_pkt_size;
277 }
278 }
279
280 init_waitqueue_head(&dma_q->wq);
281
282 /* submit urbs and enables IRQ */
283 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
284 rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
285 if (rc) {
286 au0828_isocdbg("submit of urb %i failed (error=%i)\n",
287 i, rc);
288 au0828_uninit_isoc(dev);
289 return rc;
290 }
291 }
292
293 return 0;
294}
295
296/*
297 * Announces that a buffer were filled and request the next
298 */
299static inline void buffer_filled(struct au0828_dev *dev,
300 struct au0828_dmaqueue *dma_q,
301 struct au0828_buffer *buf)
302{
303 /* Advice that buffer was filled */
304 au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
305
306 buf->vb.state = VIDEOBUF_DONE;
307 buf->vb.field_count++;
308 do_gettimeofday(&buf->vb.ts);
309
310 dev->isoc_ctl.buf = NULL;
311
312 list_del(&buf->vb.queue);
313 wake_up(&buf->vb.done);
314}
315
316/*
317 * Identify the buffer header type and properly handles
318 */
319static void au0828_copy_video(struct au0828_dev *dev,
320 struct au0828_dmaqueue *dma_q,
321 struct au0828_buffer *buf,
322 unsigned char *p,
323 unsigned char *outp, unsigned long len)
324{
325 void *fieldstart, *startwrite, *startread;
326 int linesdone, currlinedone, offset, lencopy, remain;
327 int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */
328
329 if (dma_q->pos + len > buf->vb.size)
330 len = buf->vb.size - dma_q->pos;
331
332 startread = p;
333 remain = len;
334
335 /* Interlaces frame */
336 if (buf->top_field)
337 fieldstart = outp;
338 else
339 fieldstart = outp + bytesperline;
340
341 linesdone = dma_q->pos / bytesperline;
342 currlinedone = dma_q->pos % bytesperline;
343 offset = linesdone * bytesperline * 2 + currlinedone;
344 startwrite = fieldstart + offset;
345 lencopy = bytesperline - currlinedone;
346 lencopy = lencopy > remain ? remain : lencopy;
347
348 if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
349 au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
350 ((char *)startwrite + lencopy) -
351 ((char *)outp + buf->vb.size));
352 remain = (char *)outp + buf->vb.size - (char *)startwrite;
353 lencopy = remain;
354 }
355 if (lencopy <= 0)
356 return;
357 memcpy(startwrite, startread, lencopy);
358
359 remain -= lencopy;
360
361 while (remain > 0) {
362 startwrite += lencopy + bytesperline;
363 startread += lencopy;
364 if (bytesperline > remain)
365 lencopy = remain;
366 else
367 lencopy = bytesperline;
368
369 if ((char *)startwrite + lencopy > (char *)outp +
370 buf->vb.size) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300371 au0828_isocdbg("Overflow %zi bytes past buf end (2)\n",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300372 ((char *)startwrite + lencopy) -
373 ((char *)outp + buf->vb.size));
374 lencopy = remain = (char *)outp + buf->vb.size -
375 (char *)startwrite;
376 }
377 if (lencopy <= 0)
378 break;
379
380 memcpy(startwrite, startread, lencopy);
381
382 remain -= lencopy;
383 }
384
385 if (offset > 1440) {
386 /* We have enough data to check for greenscreen */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300387 if (outp[0] < 0x60 && outp[1440] < 0x60)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300388 dev->greenscreen_detected = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300389 }
390
391 dma_q->pos += len;
392}
393
394/*
395 * video-buf generic routine to get the next available buffer
396 */
397static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
398 struct au0828_buffer **buf)
399{
400 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
401
402 if (list_empty(&dma_q->active)) {
403 au0828_isocdbg("No active queue to serve\n");
404 dev->isoc_ctl.buf = NULL;
405 *buf = NULL;
406 return;
407 }
408
409 /* Get the next buffer */
410 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
411 dev->isoc_ctl.buf = *buf;
412
413 return;
414}
415
416/*
417 * Controls the isoc copy of each urb packet
418 */
419static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
420{
421 struct au0828_buffer *buf;
422 struct au0828_dmaqueue *dma_q = urb->context;
423 unsigned char *outp = NULL;
424 int i, len = 0, rc = 1;
425 unsigned char *p;
426 unsigned char fbyte;
427
428 if (!dev)
429 return 0;
430
431 if ((dev->dev_state & DEV_DISCONNECTED) ||
432 (dev->dev_state & DEV_MISCONFIGURED))
433 return 0;
434
435 if (urb->status < 0) {
436 print_err_status(dev, -1, urb->status);
437 if (urb->status == -ENOENT)
438 return 0;
439 }
440
441 buf = dev->isoc_ctl.buf;
442 if (buf != NULL)
443 outp = videobuf_to_vmalloc(&buf->vb);
444
445 for (i = 0; i < urb->number_of_packets; i++) {
446 int status = urb->iso_frame_desc[i].status;
447
448 if (status < 0) {
449 print_err_status(dev, i, status);
450 if (urb->iso_frame_desc[i].status != -EPROTO)
451 continue;
452 }
453
Devin Heitmueller62899a22009-03-15 18:48:52 -0300454 if (urb->iso_frame_desc[i].actual_length <= 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300455 continue;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300456
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300457 if (urb->iso_frame_desc[i].actual_length >
458 dev->max_pkt_size) {
459 au0828_isocdbg("packet bigger than packet size");
460 continue;
461 }
462
463 p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
464 fbyte = p[0];
465 len = urb->iso_frame_desc[i].actual_length - 4;
466 p += 4;
467
468 if (fbyte & 0x80) {
469 len -= 4;
470 p += 4;
471 au0828_isocdbg("Video frame %s\n",
472 (fbyte & 0x40) ? "odd" : "even");
473 if (!(fbyte & 0x40)) {
474 if (buf != NULL)
475 buffer_filled(dev, dma_q, buf);
476 get_next_buf(dma_q, &buf);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300477 if (buf == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300478 outp = NULL;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300479 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300480 outp = videobuf_to_vmalloc(&buf->vb);
481 }
482
483 if (buf != NULL) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300484 if (fbyte & 0x40)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300485 buf->top_field = 1;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300486 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300487 buf->top_field = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300488 }
489
490 dma_q->pos = 0;
491 }
Devin Heitmueller62899a22009-03-15 18:48:52 -0300492 if (buf != NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300493 au0828_copy_video(dev, dma_q, buf, p, outp, len);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300494 }
495 return rc;
496}
497
498static int
499buffer_setup(struct videobuf_queue *vq, unsigned int *count,
500 unsigned int *size)
501{
502 struct au0828_fh *fh = vq->priv_data;
503 *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
504
505 if (0 == *count)
506 *count = AU0828_DEF_BUF;
507
508 if (*count < AU0828_MIN_BUF)
509 *count = AU0828_MIN_BUF;
510 return 0;
511}
512
513/* This is called *without* dev->slock held; please keep it that way */
514static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
515{
516 struct au0828_fh *fh = vq->priv_data;
517 struct au0828_dev *dev = fh->dev;
518 unsigned long flags = 0;
519 if (in_interrupt())
520 BUG();
521
522 /* We used to wait for the buffer to finish here, but this didn't work
523 because, as we were keeping the state as VIDEOBUF_QUEUED,
524 videobuf_queue_cancel marked it as finished for us.
525 (Also, it could wedge forever if the hardware was misconfigured.)
526
527 This should be safe; by the time we get here, the buffer isn't
528 queued anymore. If we ever start marking the buffers as
529 VIDEOBUF_ACTIVE, it won't be, though.
530 */
531 spin_lock_irqsave(&dev->slock, flags);
532 if (dev->isoc_ctl.buf == buf)
533 dev->isoc_ctl.buf = NULL;
534 spin_unlock_irqrestore(&dev->slock, flags);
535
536 videobuf_vmalloc_free(&buf->vb);
537 buf->vb.state = VIDEOBUF_NEEDS_INIT;
538}
539
540static int
541buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
542 enum v4l2_field field)
543{
544 struct au0828_fh *fh = vq->priv_data;
545 struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
546 struct au0828_dev *dev = fh->dev;
547 int rc = 0, urb_init = 0;
548
549 buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
550
551 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
552 return -EINVAL;
553
554 buf->vb.width = dev->width;
555 buf->vb.height = dev->height;
556 buf->vb.field = field;
557
558 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
559 rc = videobuf_iolock(vq, &buf->vb, NULL);
560 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300561 printk(KERN_INFO "videobuf_iolock failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300562 goto fail;
563 }
564 }
565
566 if (!dev->isoc_ctl.num_bufs)
567 urb_init = 1;
568
569 if (urb_init) {
570 rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,
571 AU0828_MAX_ISO_BUFS, dev->max_pkt_size,
572 au0828_isoc_copy);
573 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300574 printk(KERN_INFO "au0828_init_isoc failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300575 goto fail;
576 }
577 }
578
579 buf->vb.state = VIDEOBUF_PREPARED;
580 return 0;
581
582fail:
583 free_buffer(vq, buf);
584 return rc;
585}
586
587static void
588buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
589{
590 struct au0828_buffer *buf = container_of(vb,
591 struct au0828_buffer,
592 vb);
593 struct au0828_fh *fh = vq->priv_data;
594 struct au0828_dev *dev = fh->dev;
595 struct au0828_dmaqueue *vidq = &dev->vidq;
596
597 buf->vb.state = VIDEOBUF_QUEUED;
598 list_add_tail(&buf->vb.queue, &vidq->active);
599}
600
601static void buffer_release(struct videobuf_queue *vq,
602 struct videobuf_buffer *vb)
603{
604 struct au0828_buffer *buf = container_of(vb,
605 struct au0828_buffer,
606 vb);
607
608 free_buffer(vq, buf);
609}
610
611static struct videobuf_queue_ops au0828_video_qops = {
612 .buf_setup = buffer_setup,
613 .buf_prepare = buffer_prepare,
614 .buf_queue = buffer_queue,
615 .buf_release = buffer_release,
616};
617
618/* ------------------------------------------------------------------
619 V4L2 interface
620 ------------------------------------------------------------------*/
621
622static int au0828_i2s_init(struct au0828_dev *dev)
623{
624 /* Enable i2s mode */
625 au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);
626 return 0;
627}
628
629/*
630 * Auvitek au0828 analog stream enable
631 * Please set interface0 to AS5 before enable the stream
632 */
633int au0828_analog_stream_enable(struct au0828_dev *d)
634{
635 dprintk(1, "au0828_analog_stream_enable called\n");
636 au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
637 au0828_writereg(d, 0x106, 0x00);
638 /* set x position */
639 au0828_writereg(d, 0x110, 0x00);
640 au0828_writereg(d, 0x111, 0x00);
641 au0828_writereg(d, 0x114, 0xa0);
642 au0828_writereg(d, 0x115, 0x05);
643 /* set y position */
644 au0828_writereg(d, 0x112, 0x02);
645 au0828_writereg(d, 0x113, 0x00);
646 au0828_writereg(d, 0x116, 0xf2);
647 au0828_writereg(d, 0x117, 0x00);
648 au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
649
650 return 0;
651}
652
653int au0828_analog_stream_disable(struct au0828_dev *d)
654{
655 dprintk(1, "au0828_analog_stream_disable called\n");
656 au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
657 return 0;
658}
659
660void au0828_analog_stream_reset(struct au0828_dev *dev)
661{
662 dprintk(1, "au0828_analog_stream_reset called\n");
663 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
664 mdelay(30);
665 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);
666}
667
668/*
669 * Some operations needs to stop current streaming
670 */
671static int au0828_stream_interrupt(struct au0828_dev *dev)
672{
673 int ret = 0;
674
675 dev->stream_state = STREAM_INTERRUPT;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300676 if (dev->dev_state == DEV_DISCONNECTED)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300677 return -ENODEV;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300678 else if (ret) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300679 dev->dev_state = DEV_MISCONFIGURED;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300680 dprintk(1, "%s device is misconfigured!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300681 return ret;
682 }
683 return 0;
684}
685
686/*
687 * au0828_release_resources
688 * unregister v4l2 devices
689 */
690void au0828_analog_unregister(struct au0828_dev *dev)
691{
692 dprintk(1, "au0828_release_resources called\n");
693 mutex_lock(&au0828_sysfs_lock);
694
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200695 if (dev->vdev)
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300696 video_unregister_device(dev->vdev);
697 if (dev->vbi_dev)
698 video_unregister_device(dev->vbi_dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300699
700 mutex_unlock(&au0828_sysfs_lock);
701}
702
703
704/* Usage lock check functions */
705static int res_get(struct au0828_fh *fh)
706{
707 struct au0828_dev *dev = fh->dev;
708 int rc = 0;
709
710 /* This instance already has stream_on */
711 if (fh->stream_on)
712 return rc;
713
714 if (dev->stream_on)
715 return -EBUSY;
716
717 dev->stream_on = 1;
718 fh->stream_on = 1;
719 return rc;
720}
721
722static int res_check(struct au0828_fh *fh)
723{
724 return fh->stream_on;
725}
726
727static void res_free(struct au0828_fh *fh)
728{
729 struct au0828_dev *dev = fh->dev;
730
731 fh->stream_on = 0;
732 dev->stream_on = 0;
733}
734
735static int au0828_v4l2_open(struct file *filp)
736{
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300737 int ret = 0;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200738 struct au0828_dev *dev = video_drvdata(filp);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300739 struct au0828_fh *fh;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200740 int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300741
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -0300742#ifdef VBI_IS_WORKING
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200743 if (video_devdata(filp)->vfl_type == VFL_TYPE_GRABBER)
744 type = V4L2_BUF_TYPE_VBI_CAPTURE;
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300745#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300746
747 fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300748 if (NULL == fh) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300749 dprintk(1, "Failed allocate au0828_fh struct!\n");
750 return -ENOMEM;
751 }
752
753 fh->type = type;
754 fh->dev = dev;
755 filp->private_data = fh;
756
Devin Heitmueller62899a22009-03-15 18:48:52 -0300757 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300758 /* set au0828 interface0 to AS5 here again */
759 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300760 if (ret < 0) {
761 printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300762 return -EBUSY;
763 }
764 dev->width = NTSC_STD_W;
765 dev->height = NTSC_STD_H;
766 dev->frame_size = dev->width * dev->height * 2;
767 dev->field_size = dev->width * dev->height;
768 dev->bytesperline = dev->width * 2;
769
770 au0828_analog_stream_enable(dev);
771 au0828_analog_stream_reset(dev);
772
773 /* If we were doing ac97 instead of i2s, it would go here...*/
774 au0828_i2s_init(dev);
775
776 dev->stream_state = STREAM_OFF;
777 dev->dev_state |= DEV_INITIALIZED;
778 }
779
780 dev->users++;
781
782 videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
783 NULL, &dev->slock, fh->type,
784 V4L2_FIELD_INTERLACED,
785 sizeof(struct au0828_buffer), fh);
786
787 return ret;
788}
789
790static int au0828_v4l2_close(struct file *filp)
791{
792 int ret;
793 struct au0828_fh *fh = filp->private_data;
794 struct au0828_dev *dev = fh->dev;
795
796 mutex_lock(&dev->lock);
797 if (res_check(fh))
798 res_free(fh);
799
Devin Heitmueller62899a22009-03-15 18:48:52 -0300800 if (dev->users == 1) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300801 videobuf_stop(&fh->vb_vidq);
802 videobuf_mmap_free(&fh->vb_vidq);
803
Devin Heitmueller62899a22009-03-15 18:48:52 -0300804 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300805 au0828_analog_unregister(dev);
806 mutex_unlock(&dev->lock);
807 kfree(dev);
808 return 0;
809 }
810
811 au0828_analog_stream_disable(dev);
812
813 au0828_uninit_isoc(dev);
814
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -0300815 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -0300816 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -0300817
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300818 /* When close the device, set the usb intf0 into alt0 to free
819 USB bandwidth */
820 ret = usb_set_interface(dev->usbdev, 0, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300821 if (ret < 0)
822 printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300823 }
824
825 kfree(fh);
826 dev->users--;
827 wake_up_interruptible_nr(&dev->open, 1);
828 mutex_unlock(&dev->lock);
829 return 0;
830}
831
832static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
833 size_t count, loff_t *pos)
834{
835 struct au0828_fh *fh = filp->private_data;
836 struct au0828_dev *dev = fh->dev;
837 int rc;
838
839 rc = check_dev(dev);
840 if (rc < 0)
841 return rc;
842
Devin Heitmueller62899a22009-03-15 18:48:52 -0300843 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300844 mutex_lock(&dev->lock);
845 rc = res_get(fh);
846 mutex_unlock(&dev->lock);
847
848 if (unlikely(rc < 0))
849 return rc;
850
851 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
852 filp->f_flags & O_NONBLOCK);
853 }
854 return 0;
855}
856
857static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
858{
859 struct au0828_fh *fh = filp->private_data;
860 struct au0828_dev *dev = fh->dev;
861 int rc;
862
863 rc = check_dev(dev);
864 if (rc < 0)
865 return rc;
866
867 mutex_lock(&dev->lock);
868 rc = res_get(fh);
869 mutex_unlock(&dev->lock);
870
871 if (unlikely(rc < 0))
872 return POLLERR;
873
874 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
875 return POLLERR;
876
877 return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
878}
879
880static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
881{
882 struct au0828_fh *fh = filp->private_data;
883 struct au0828_dev *dev = fh->dev;
884 int rc;
885
886 rc = check_dev(dev);
887 if (rc < 0)
888 return rc;
889
890 mutex_lock(&dev->lock);
891 rc = res_get(fh);
892 mutex_unlock(&dev->lock);
893
894 if (unlikely(rc < 0))
895 return rc;
896
897 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
898
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300899 return rc;
900}
901
902static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
903 struct v4l2_format *format)
904{
905 int ret;
906 int width = format->fmt.pix.width;
907 int height = format->fmt.pix.height;
908 unsigned int maxwidth, maxheight;
909
910 maxwidth = 720;
911 maxheight = 480;
912
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -0300913#ifdef VBI_IS_WORKING
Devin Heitmueller62899a22009-03-15 18:48:52 -0300914 if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300915 dprintk(1, "VBI format set: to be supported!\n");
916 return 0;
917 }
Devin Heitmueller62899a22009-03-15 18:48:52 -0300918 if (format->type == V4L2_BUF_TYPE_VBI_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300919 return 0;
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300920#endif
Devin Heitmueller62899a22009-03-15 18:48:52 -0300921 if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300922 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300923
924 /* If they are demanding a format other than the one we support,
925 bail out (tvtime asks for UYVY and then retries with YUYV) */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300926 if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300927 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300928
929 /* format->fmt.pix.width only support 720 and height 480 */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300930 if (width != 720)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300931 width = 720;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300932 if (height != 480)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300933 height = 480;
934
935 format->fmt.pix.width = width;
936 format->fmt.pix.height = height;
937 format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
938 format->fmt.pix.bytesperline = width * 2;
939 format->fmt.pix.sizeimage = width * height * 2;
940 format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
941 format->fmt.pix.field = V4L2_FIELD_INTERLACED;
942
Devin Heitmueller62899a22009-03-15 18:48:52 -0300943 if (cmd == VIDIOC_TRY_FMT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300944 return 0;
945
946 /* maybe set new image format, driver current only support 720*480 */
947 dev->width = width;
948 dev->height = height;
949 dev->frame_size = width * height * 2;
950 dev->field_size = width * height;
951 dev->bytesperline = width * 2;
952
Devin Heitmueller62899a22009-03-15 18:48:52 -0300953 if (dev->stream_state == STREAM_ON) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300954 dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
Devin Heitmueller62899a22009-03-15 18:48:52 -0300955 ret = au0828_stream_interrupt(dev);
956 if (ret != 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300957 dprintk(1, "error interrupting video stream!\n");
958 return ret;
959 }
960 }
961
962 /* set au0828 interface0 to AS5 here again */
963 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300964 if (ret < 0) {
965 printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300966 return -EBUSY;
967 }
968
969 au0828_analog_stream_enable(dev);
970
971 return 0;
972}
973
974
975static int vidioc_queryctrl(struct file *file, void *priv,
976 struct v4l2_queryctrl *qc)
977{
978 struct au0828_fh *fh = priv;
979 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -0300980 v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300981 if (qc->type)
982 return 0;
983 else
984 return -EINVAL;
985}
986
987static int vidioc_querycap(struct file *file, void *priv,
988 struct v4l2_capability *cap)
989{
990 struct au0828_fh *fh = priv;
991 struct au0828_dev *dev = fh->dev;
992
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300993 strlcpy(cap->driver, "au0828", sizeof(cap->driver));
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300994 strlcpy(cap->card, dev->board.name, sizeof(cap->card));
Devin Heitmuellerb14667f2009-03-11 03:01:04 -0300995 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300996
997 cap->version = AU0828_VERSION_CODE;
998
999 /*set the device capabilities */
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001000 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001001#ifdef VBI_IS_WORKING
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001002 V4L2_CAP_VBI_CAPTURE |
1003#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001004 V4L2_CAP_AUDIO |
1005 V4L2_CAP_READWRITE |
1006 V4L2_CAP_STREAMING |
1007 V4L2_CAP_TUNER;
1008 return 0;
1009}
1010
1011static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1012 struct v4l2_fmtdesc *f)
1013{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001014 if (f->index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001015 return -EINVAL;
1016
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001017 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1018 strcpy(f->description, "Packed YUV2");
1019
1020 f->flags = 0;
1021 f->pixelformat = V4L2_PIX_FMT_UYVY;
1022
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001023 return 0;
1024}
1025
1026static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1027 struct v4l2_format *f)
1028{
1029 struct au0828_fh *fh = priv;
1030 struct au0828_dev *dev = fh->dev;
1031
1032 f->fmt.pix.width = dev->width;
1033 f->fmt.pix.height = dev->height;
1034 f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1035 f->fmt.pix.bytesperline = dev->bytesperline;
1036 f->fmt.pix.sizeimage = dev->frame_size;
1037 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
1038 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1039 return 0;
1040}
1041
1042static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1043 struct v4l2_format *f)
1044{
1045 struct au0828_fh *fh = priv;
1046 struct au0828_dev *dev = fh->dev;
1047
1048 return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
1049}
1050
1051static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1052 struct v4l2_format *f)
1053{
1054 struct au0828_fh *fh = priv;
1055 struct au0828_dev *dev = fh->dev;
1056 int rc;
1057
1058 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001059 printk(KERN_INFO "%s queue busy\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001060 rc = -EBUSY;
1061 goto out;
1062 }
1063
1064 if (dev->stream_on && !fh->stream_on) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001065 printk(KERN_INFO "%s device in use by another fh\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001066 rc = -EBUSY;
1067 goto out;
1068 }
1069
1070 return au0828_set_format(dev, VIDIOC_S_FMT, f);
1071out:
1072 return rc;
1073}
1074
1075static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
1076{
1077 struct au0828_fh *fh = priv;
1078 struct au0828_dev *dev = fh->dev;
1079
1080 /* FIXME: when we support something other than NTSC, we are going to
1081 have to make the au0828 bridge adjust the size of its capture
1082 buffer, which is currently hardcoded at 720x480 */
1083
Hans Verkuilf41737e2009-04-01 03:52:39 -03001084 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001085 return 0;
1086}
1087
1088static int vidioc_enum_input(struct file *file, void *priv,
1089 struct v4l2_input *input)
1090{
1091 struct au0828_fh *fh = priv;
1092 struct au0828_dev *dev = fh->dev;
1093 unsigned int tmp;
1094
1095 static const char *inames[] = {
Devin Heitmueller3d622872009-03-15 17:48:26 -03001096 [AU0828_VMUX_UNDEFINED] = "Undefined",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001097 [AU0828_VMUX_COMPOSITE] = "Composite",
1098 [AU0828_VMUX_SVIDEO] = "S-Video",
1099 [AU0828_VMUX_CABLE] = "Cable TV",
1100 [AU0828_VMUX_TELEVISION] = "Television",
1101 [AU0828_VMUX_DVB] = "DVB",
1102 [AU0828_VMUX_DEBUG] = "tv debug"
1103 };
1104
1105 tmp = input->index;
1106
Devin Heitmueller62899a22009-03-15 18:48:52 -03001107 if (tmp > AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001108 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001109 if (AUVI_INPUT(tmp).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001110 return -EINVAL;
1111
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001112 input->index = tmp;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001113 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001114 if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
1115 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001116 input->type |= V4L2_INPUT_TYPE_TUNER;
1117 else
1118 input->type |= V4L2_INPUT_TYPE_CAMERA;
1119
1120 input->std = dev->vdev->tvnorms;
1121
1122 return 0;
1123}
1124
1125static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1126{
1127 struct au0828_fh *fh = priv;
1128 struct au0828_dev *dev = fh->dev;
1129 *i = dev->ctrl_input;
1130 return 0;
1131}
1132
1133static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1134{
1135 struct au0828_fh *fh = priv;
1136 struct au0828_dev *dev = fh->dev;
1137 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001138
Devin Heitmueller62899a22009-03-15 18:48:52 -03001139 dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001140 index);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001141 if (index >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001142 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001143 if (AUVI_INPUT(index).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001144 return -EINVAL;
1145 dev->ctrl_input = index;
1146
Devin Heitmueller62899a22009-03-15 18:48:52 -03001147 switch (AUVI_INPUT(index).type) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001148 case AU0828_VMUX_SVIDEO:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001149 dev->input_type = AU0828_VMUX_SVIDEO;
1150 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001151 case AU0828_VMUX_COMPOSITE:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001152 dev->input_type = AU0828_VMUX_COMPOSITE;
1153 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001154 case AU0828_VMUX_TELEVISION:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001155 dev->input_type = AU0828_VMUX_TELEVISION;
1156 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001157 default:
Devin Heitmuellera1094c42009-03-15 17:43:13 -03001158 dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
1159 AUVI_INPUT(index).type);
1160 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001161 }
1162
Hans Verkuil5325b422009-04-02 11:26:22 -03001163 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1164 AUVI_INPUT(index).vmux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001165
1166 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1167 int enable = 0;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001168 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001169 continue;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001170
1171 if (i == index)
1172 enable = 1;
1173 else
1174 enable = 0;
1175 if (enable) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001176 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001177 } else {
1178 /* Make sure we leave it turned on if some
1179 other input is routed to this callback */
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001180 if ((AUVI_INPUT(i).audio_setup) !=
1181 ((AUVI_INPUT(index).audio_setup))) {
1182 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001183 }
1184 }
1185 }
1186
Hans Verkuil5325b422009-04-02 11:26:22 -03001187 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1188 AUVI_INPUT(index).amux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001189 return 0;
1190}
1191
1192static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1193{
1194 struct au0828_fh *fh = priv;
1195 struct au0828_dev *dev = fh->dev;
1196 unsigned int index = a->index;
1197
Devin Heitmueller62899a22009-03-15 18:48:52 -03001198 if (a->index > 1)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001199 return -EINVAL;
1200
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001201 index = dev->ctrl_ainput;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001202 if (index == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001203 strcpy(a->name, "Television");
1204 else
1205 strcpy(a->name, "Line in");
1206
1207 a->capability = V4L2_AUDCAP_STEREO;
1208 a->index = index;
1209 return 0;
1210}
1211
1212static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
1213{
1214 struct au0828_fh *fh = priv;
1215 struct au0828_dev *dev = fh->dev;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001216 if (a->index != dev->ctrl_ainput)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001217 return -EINVAL;
1218 return 0;
1219}
1220
1221static int vidioc_g_ctrl(struct file *file, void *priv,
1222 struct v4l2_control *ctrl)
1223{
1224 struct au0828_fh *fh = priv;
1225 struct au0828_dev *dev = fh->dev;
1226
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001227 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001228 return 0;
1229
1230}
1231
1232static int vidioc_s_ctrl(struct file *file, void *priv,
1233 struct v4l2_control *ctrl)
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, s_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001238 return 0;
1239}
1240
1241static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
1242{
1243 struct au0828_fh *fh = priv;
1244 struct au0828_dev *dev = fh->dev;
1245
Devin Heitmueller62899a22009-03-15 18:48:52 -03001246 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001247 return -EINVAL;
1248
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001249 strcpy(t->name, "Auvitek tuner");
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001250 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001251 return 0;
1252}
1253
1254static int vidioc_s_tuner(struct file *file, void *priv,
1255 struct v4l2_tuner *t)
1256{
1257 struct au0828_fh *fh = priv;
1258 struct au0828_dev *dev = fh->dev;
1259
Devin Heitmueller62899a22009-03-15 18:48:52 -03001260 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001261 return -EINVAL;
1262
1263 t->type = V4L2_TUNER_ANALOG_TV;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001264 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001265 dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
1266 t->afc);
1267 return 0;
1268
1269}
1270
1271static int vidioc_g_frequency(struct file *file, void *priv,
1272 struct v4l2_frequency *freq)
1273{
1274 struct au0828_fh *fh = priv;
1275 struct au0828_dev *dev = fh->dev;
Devin Heitmuellerc8889232009-03-15 17:38:47 -03001276
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001277 freq->type = V4L2_TUNER_ANALOG_TV;
1278 freq->frequency = dev->ctrl_freq;
1279 return 0;
1280}
1281
1282static int vidioc_s_frequency(struct file *file, void *priv,
1283 struct v4l2_frequency *freq)
1284{
1285 struct au0828_fh *fh = priv;
1286 struct au0828_dev *dev = fh->dev;
1287
Devin Heitmueller62899a22009-03-15 18:48:52 -03001288 if (freq->tuner != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001289 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001290 if (freq->type != V4L2_TUNER_ANALOG_TV)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001291 return -EINVAL;
1292
1293 dev->ctrl_freq = freq->frequency;
1294
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001295 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001296
1297 au0828_analog_stream_reset(dev);
1298
1299 return 0;
1300}
1301
1302static int vidioc_g_chip_ident(struct file *file, void *priv,
1303 struct v4l2_dbg_chip_ident *chip)
1304{
1305 struct au0828_fh *fh = priv;
1306 struct au0828_dev *dev = fh->dev;
1307 chip->ident = V4L2_IDENT_NONE;
1308 chip->revision = 0;
1309
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001310 if (v4l2_chip_match_host(&chip->match)) {
1311 chip->ident = V4L2_IDENT_AU0828;
1312 return 0;
1313 }
1314
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001315 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001316 if (chip->ident == V4L2_IDENT_NONE)
1317 return -EINVAL;
1318
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001319 return 0;
1320}
1321
1322static int vidioc_cropcap(struct file *file, void *priv,
1323 struct v4l2_cropcap *cc)
1324{
1325 struct au0828_fh *fh = priv;
1326 struct au0828_dev *dev = fh->dev;
1327
Devin Heitmueller62899a22009-03-15 18:48:52 -03001328 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001329 return -EINVAL;
1330
1331 cc->bounds.left = 0;
1332 cc->bounds.top = 0;
1333 cc->bounds.width = dev->width;
1334 cc->bounds.height = dev->height;
1335
1336 cc->defrect = cc->bounds;
1337
1338 cc->pixelaspect.numerator = 54;
1339 cc->pixelaspect.denominator = 59;
1340
1341 return 0;
1342}
1343
1344static int vidioc_streamon(struct file *file, void *priv,
1345 enum v4l2_buf_type type)
1346{
1347 struct au0828_fh *fh = priv;
1348 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001349 int rc;
1350
1351 rc = check_dev(dev);
1352 if (rc < 0)
1353 return rc;
1354
1355 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1356 au0828_analog_stream_enable(dev);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001357 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001358 }
1359
1360 mutex_lock(&dev->lock);
1361 rc = res_get(fh);
1362
1363 if (likely(rc >= 0))
1364 rc = videobuf_streamon(&fh->vb_vidq);
1365 mutex_unlock(&dev->lock);
1366
1367 return rc;
1368}
1369
1370static int vidioc_streamoff(struct file *file, void *priv,
1371 enum v4l2_buf_type type)
1372{
1373 struct au0828_fh *fh = priv;
1374 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001375 int i;
1376 int ret;
1377 int rc;
1378
1379 rc = check_dev(dev);
1380 if (rc < 0)
1381 return rc;
1382
1383 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1384 return -EINVAL;
1385 if (type != fh->type)
1386 return -EINVAL;
1387
1388 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001389 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001390 ret = au0828_stream_interrupt(dev);
1391 if (ret != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001392 return ret;
1393 }
1394
1395 for (i = 0; i < AU0828_MAX_INPUT; i++) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001396 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001397 continue;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001398 (AUVI_INPUT(i).audio_setup)(dev, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001399 }
1400
1401 mutex_lock(&dev->lock);
1402 videobuf_streamoff(&fh->vb_vidq);
1403 res_free(fh);
1404 mutex_unlock(&dev->lock);
1405
1406 return 0;
1407}
1408
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001409#ifdef CONFIG_VIDEO_ADV_DEBUG
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001410static int vidioc_g_register(struct file *file, void *priv,
1411 struct v4l2_dbg_register *reg)
1412{
1413 struct au0828_fh *fh = priv;
1414 struct au0828_dev *dev = fh->dev;
1415
1416 switch (reg->match.type) {
1417 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001418 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001419 return 0;
1420 default:
1421 return -EINVAL;
1422 }
1423}
1424
1425static int vidioc_s_register(struct file *file, void *priv,
1426 struct v4l2_dbg_register *reg)
1427{
1428 struct au0828_fh *fh = priv;
1429 struct au0828_dev *dev = fh->dev;
1430
1431 switch (reg->match.type) {
1432 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001433 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001434 return 0;
1435 default:
1436 return -EINVAL;
1437 }
1438 return 0;
1439}
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001440#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001441
1442static int vidioc_reqbufs(struct file *file, void *priv,
1443 struct v4l2_requestbuffers *rb)
1444{
1445 struct au0828_fh *fh = priv;
1446 struct au0828_dev *dev = fh->dev;
1447 int rc;
1448
1449 rc = check_dev(dev);
1450 if (rc < 0)
1451 return rc;
1452
1453 return videobuf_reqbufs(&fh->vb_vidq, rb);
1454}
1455
1456static int vidioc_querybuf(struct file *file, void *priv,
1457 struct v4l2_buffer *b)
1458{
1459 struct au0828_fh *fh = priv;
1460 struct au0828_dev *dev = fh->dev;
1461 int rc;
1462
1463 rc = check_dev(dev);
1464 if (rc < 0)
1465 return rc;
1466
1467 return videobuf_querybuf(&fh->vb_vidq, b);
1468}
1469
1470static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1471{
1472 struct au0828_fh *fh = priv;
1473 struct au0828_dev *dev = fh->dev;
1474 int rc;
1475
1476 rc = check_dev(dev);
1477 if (rc < 0)
1478 return rc;
1479
1480 return videobuf_qbuf(&fh->vb_vidq, b);
1481}
1482
1483static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1484{
1485 struct au0828_fh *fh = priv;
1486 struct au0828_dev *dev = fh->dev;
1487 int rc;
1488
1489 rc = check_dev(dev);
1490 if (rc < 0)
1491 return rc;
1492
1493 /* Workaround for a bug in the au0828 hardware design that sometimes
1494 results in the colorspace being inverted */
1495 if (dev->greenscreen_detected == 1) {
1496 dprintk(1, "Detected green frame. Resetting stream...\n");
1497 au0828_analog_stream_reset(dev);
1498 dev->greenscreen_detected = 0;
1499 }
1500
1501 return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1502}
1503
1504#ifdef CONFIG_VIDEO_V4L1_COMPAT
1505static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
1506{
1507 struct au0828_fh *fh = priv;
1508
1509 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
1510}
1511#endif
1512
1513static struct v4l2_file_operations au0828_v4l_fops = {
1514 .owner = THIS_MODULE,
1515 .open = au0828_v4l2_open,
1516 .release = au0828_v4l2_close,
1517 .read = au0828_v4l2_read,
1518 .poll = au0828_v4l2_poll,
1519 .mmap = au0828_v4l2_mmap,
1520 .ioctl = video_ioctl2,
1521};
1522
1523static const struct v4l2_ioctl_ops video_ioctl_ops = {
1524 .vidioc_querycap = vidioc_querycap,
1525 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1526 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1527 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1528 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001529#ifdef VBI_IS_WORKING
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001530 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
1531 .vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
1532 .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
1533#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001534 .vidioc_g_audio = vidioc_g_audio,
1535 .vidioc_s_audio = vidioc_s_audio,
1536 .vidioc_cropcap = vidioc_cropcap,
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001537#ifdef VBI_IS_WORKING
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001538 .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap,
1539 .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
1540 .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
1541#endif
1542 .vidioc_reqbufs = vidioc_reqbufs,
1543 .vidioc_querybuf = vidioc_querybuf,
1544 .vidioc_qbuf = vidioc_qbuf,
1545 .vidioc_dqbuf = vidioc_dqbuf,
1546 .vidioc_s_std = vidioc_s_std,
1547 .vidioc_enum_input = vidioc_enum_input,
1548 .vidioc_g_input = vidioc_g_input,
1549 .vidioc_s_input = vidioc_s_input,
1550 .vidioc_queryctrl = vidioc_queryctrl,
1551 .vidioc_g_ctrl = vidioc_g_ctrl,
1552 .vidioc_s_ctrl = vidioc_s_ctrl,
1553 .vidioc_streamon = vidioc_streamon,
1554 .vidioc_streamoff = vidioc_streamoff,
1555 .vidioc_g_tuner = vidioc_g_tuner,
1556 .vidioc_s_tuner = vidioc_s_tuner,
1557 .vidioc_g_frequency = vidioc_g_frequency,
1558 .vidioc_s_frequency = vidioc_s_frequency,
1559#ifdef CONFIG_VIDEO_ADV_DEBUG
1560 .vidioc_g_register = vidioc_g_register,
1561 .vidioc_s_register = vidioc_s_register,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001562#endif
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001563 .vidioc_g_chip_ident = vidioc_g_chip_ident,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001564#ifdef CONFIG_VIDEO_V4L1_COMPAT
1565 .vidiocgmbuf = vidiocgmbuf,
1566#endif
1567};
1568
1569static const struct video_device au0828_video_template = {
1570 .fops = &au0828_v4l_fops,
1571 .release = video_device_release,
1572 .ioctl_ops = &video_ioctl_ops,
1573 .minor = -1,
Devin Heitmueller0ef210712009-03-11 03:00:53 -03001574 .tvnorms = V4L2_STD_NTSC_M,
1575 .current_norm = V4L2_STD_NTSC_M,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001576};
1577
1578/**************************************************************************/
1579
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001580int au0828_analog_register(struct au0828_dev *dev,
1581 struct usb_interface *interface)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001582{
1583 int retval = -ENOMEM;
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001584 struct usb_host_interface *iface_desc;
1585 struct usb_endpoint_descriptor *endpoint;
1586 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001587
1588 dprintk(1, "au0828_analog_register called!\n");
1589
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001590 /* set au0828 usb interface0 to as5 */
1591 retval = usb_set_interface(dev->usbdev,
Devin Heitmueller62899a22009-03-15 18:48:52 -03001592 interface->cur_altsetting->desc.bInterfaceNumber, 5);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001593 if (retval != 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001594 printk(KERN_INFO "Failure setting usb interface0 to as5\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001595 return retval;
1596 }
1597
1598 /* Figure out which endpoint has the isoc interface */
1599 iface_desc = interface->cur_altsetting;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001600 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001601 endpoint = &iface_desc->endpoint[i].desc;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001602 if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1603 == USB_DIR_IN) &&
1604 ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1605 == USB_ENDPOINT_XFER_ISOC)) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001606
1607 /* we find our isoc in endpoint */
1608 u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001609 dev->max_pkt_size = (tmp & 0x07ff) *
1610 (((tmp & 0x1800) >> 11) + 1);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001611 dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
1612 }
1613 }
Devin Heitmueller62899a22009-03-15 18:48:52 -03001614 if (!(dev->isoc_in_endpointaddr)) {
1615 printk(KERN_INFO "Could not locate isoc endpoint\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001616 kfree(dev);
1617 return -ENODEV;
1618 }
1619
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001620 init_waitqueue_head(&dev->open);
1621 spin_lock_init(&dev->slock);
1622 mutex_init(&dev->lock);
1623
1624 INIT_LIST_HEAD(&dev->vidq.active);
1625 INIT_LIST_HEAD(&dev->vidq.queued);
1626
1627 dev->width = NTSC_STD_W;
1628 dev->height = NTSC_STD_H;
1629 dev->field_size = dev->width * dev->height;
1630 dev->frame_size = dev->field_size << 1;
1631 dev->bytesperline = dev->width << 1;
1632 dev->ctrl_ainput = 0;
1633
1634 /* allocate and fill v4l2 video struct */
1635 dev->vdev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001636 if (NULL == dev->vdev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001637 dprintk(1, "Can't allocate video_device.\n");
1638 return -ENOMEM;
1639 }
1640
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001641#ifdef VBI_IS_WORKING
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001642 dev->vbi_dev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001643 if (NULL == dev->vbi_dev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001644 dprintk(1, "Can't allocate vbi_device.\n");
1645 kfree(dev->vdev);
1646 return -ENOMEM;
1647 }
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001648#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001649
1650 /* Fill the video capture device struct */
1651 *dev->vdev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001652 dev->vdev->parent = &dev->usbdev->dev;
1653 strcpy(dev->vdev->name, "au0828a video");
1654
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001655#ifdef VBI_IS_WORKING
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001656 /* Setup the VBI device */
1657 *dev->vbi_dev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001658 dev->vbi_dev->parent = &dev->usbdev->dev;
1659 strcpy(dev->vbi_dev->name, "au0828a vbi");
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001660#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001661
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001662 /* Register the v4l2 device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001663 video_set_drvdata(dev->vdev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001664 retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1665 if (retval != 0) {
1666 dprintk(1, "unable to register video device (error = %d).\n",
1667 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001668 video_device_release(dev->vdev);
1669 return -ENODEV;
1670 }
1671
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001672#ifdef VBI_IS_WORKING
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001673 /* Register the vbi device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001674 video_set_drvdata(dev->vbi_dev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001675 retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
1676 if (retval != 0) {
1677 dprintk(1, "unable to register vbi device (error = %d).\n",
1678 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001679 video_device_release(dev->vbi_dev);
1680 video_device_release(dev->vdev);
1681 return -ENODEV;
1682 }
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001683#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001684
Devin Heitmueller62899a22009-03-15 18:48:52 -03001685 dprintk(1, "%s completed!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001686
1687 return 0;
1688}
1689