blob: 66150216f976d0f99dc5397e379c2ee26b7dc767 [file] [log] [blame]
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001/*
2 * Auvitek AU0828 USB Bridge (Analog video support)
3 *
4 * Copyright (C) 2009 Devin Heitmueller <dheitmueller@linuxtv.org>
5 * Copyright (C) 2005-2008 Auvitek International, Ltd.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * As published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 */
22
23/* Developer Notes:
24 *
25 * VBI support is not yet working
26 * The hardware scaler supported is unimplemented
27 * AC97 audio support is unimplemented (only i2s audio mode)
28 *
29 */
30
31#include <linux/module.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090032#include <linux/slab.h>
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030033#include <linux/init.h>
34#include <linux/device.h>
35#include <linux/suspend.h>
36#include <linux/version.h>
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030037#include <media/v4l2-common.h>
38#include <media/v4l2-ioctl.h>
39#include <media/v4l2-chip-ident.h>
40#include <media/tuner.h>
41#include "au0828.h"
42#include "au0828-reg.h"
43
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030044static DEFINE_MUTEX(au0828_sysfs_lock);
45
46#define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1)
47
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030048/* ------------------------------------------------------------------
49 Videobuf operations
50 ------------------------------------------------------------------*/
51
52static unsigned int isoc_debug;
53module_param(isoc_debug, int, 0644);
54MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
55
56#define au0828_isocdbg(fmt, arg...) \
57do {\
58 if (isoc_debug) { \
59 printk(KERN_INFO "au0828 %s :"fmt, \
60 __func__ , ##arg); \
61 } \
62 } while (0)
63
64static inline void print_err_status(struct au0828_dev *dev,
65 int packet, int status)
66{
67 char *errmsg = "Unknown";
68
69 switch (status) {
70 case -ENOENT:
71 errmsg = "unlinked synchronuously";
72 break;
73 case -ECONNRESET:
74 errmsg = "unlinked asynchronuously";
75 break;
76 case -ENOSR:
77 errmsg = "Buffer error (overrun)";
78 break;
79 case -EPIPE:
80 errmsg = "Stalled (device not responding)";
81 break;
82 case -EOVERFLOW:
83 errmsg = "Babble (bad cable?)";
84 break;
85 case -EPROTO:
86 errmsg = "Bit-stuff error (bad cable?)";
87 break;
88 case -EILSEQ:
89 errmsg = "CRC/Timeout (could be anything)";
90 break;
91 case -ETIME:
92 errmsg = "Device does not respond";
93 break;
94 }
95 if (packet < 0) {
96 au0828_isocdbg("URB status %d [%s].\n", status, errmsg);
97 } else {
98 au0828_isocdbg("URB packet %d, status %d [%s].\n",
99 packet, status, errmsg);
100 }
101}
102
103static int check_dev(struct au0828_dev *dev)
104{
105 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300106 printk(KERN_INFO "v4l2 ioctl: device not present\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300107 return -ENODEV;
108 }
109
110 if (dev->dev_state & DEV_MISCONFIGURED) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300111 printk(KERN_INFO "v4l2 ioctl: device is misconfigured; "
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300112 "close and open it again\n");
113 return -EIO;
114 }
115 return 0;
116}
117
118/*
119 * IRQ callback, called by URB callback
120 */
121static void au0828_irq_callback(struct urb *urb)
122{
123 struct au0828_dmaqueue *dma_q = urb->context;
124 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
125 int rc, i;
126
127 switch (urb->status) {
128 case 0: /* success */
129 case -ETIMEDOUT: /* NAK */
130 break;
131 case -ECONNRESET: /* kill */
132 case -ENOENT:
133 case -ESHUTDOWN:
134 au0828_isocdbg("au0828_irq_callback called: status kill\n");
135 return;
136 default: /* unknown error */
137 au0828_isocdbg("urb completition error %d.\n", urb->status);
138 break;
139 }
140
141 /* Copy data from URB */
142 spin_lock(&dev->slock);
143 rc = dev->isoc_ctl.isoc_copy(dev, urb);
144 spin_unlock(&dev->slock);
145
146 /* Reset urb buffers */
147 for (i = 0; i < urb->number_of_packets; i++) {
148 urb->iso_frame_desc[i].status = 0;
149 urb->iso_frame_desc[i].actual_length = 0;
150 }
151 urb->status = 0;
152
153 urb->status = usb_submit_urb(urb, GFP_ATOMIC);
154 if (urb->status) {
155 au0828_isocdbg("urb resubmit failed (error=%i)\n",
156 urb->status);
157 }
158}
159
160/*
161 * Stop and Deallocate URBs
162 */
163void au0828_uninit_isoc(struct au0828_dev *dev)
164{
165 struct urb *urb;
166 int i;
167
168 au0828_isocdbg("au0828: called au0828_uninit_isoc\n");
169
170 dev->isoc_ctl.nfields = -1;
171 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
172 urb = dev->isoc_ctl.urb[i];
173 if (urb) {
174 if (!irqs_disabled())
175 usb_kill_urb(urb);
176 else
177 usb_unlink_urb(urb);
178
179 if (dev->isoc_ctl.transfer_buffer[i]) {
180 usb_buffer_free(dev->usbdev,
181 urb->transfer_buffer_length,
182 dev->isoc_ctl.transfer_buffer[i],
183 urb->transfer_dma);
184 }
185 usb_free_urb(urb);
186 dev->isoc_ctl.urb[i] = NULL;
187 }
188 dev->isoc_ctl.transfer_buffer[i] = NULL;
189 }
190
191 kfree(dev->isoc_ctl.urb);
192 kfree(dev->isoc_ctl.transfer_buffer);
193
194 dev->isoc_ctl.urb = NULL;
195 dev->isoc_ctl.transfer_buffer = NULL;
196 dev->isoc_ctl.num_bufs = 0;
197}
198
199/*
200 * Allocate URBs and start IRQ
201 */
202int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
203 int num_bufs, int max_pkt_size,
204 int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
205{
206 struct au0828_dmaqueue *dma_q = &dev->vidq;
207 int i;
208 int sb_size, pipe;
209 struct urb *urb;
210 int j, k;
211 int rc;
212
213 au0828_isocdbg("au0828: called au0828_prepare_isoc\n");
214
215 /* De-allocates all pending stuff */
216 au0828_uninit_isoc(dev);
217
218 dev->isoc_ctl.isoc_copy = isoc_copy;
219 dev->isoc_ctl.num_bufs = num_bufs;
220
221 dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
222 if (!dev->isoc_ctl.urb) {
223 au0828_isocdbg("cannot alloc memory for usb buffers\n");
224 return -ENOMEM;
225 }
226
227 dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
228 GFP_KERNEL);
229 if (!dev->isoc_ctl.transfer_buffer) {
230 au0828_isocdbg("cannot allocate memory for usb transfer\n");
231 kfree(dev->isoc_ctl.urb);
232 return -ENOMEM;
233 }
234
235 dev->isoc_ctl.max_pkt_size = max_pkt_size;
236 dev->isoc_ctl.buf = NULL;
237
238 sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
239
240 /* allocate urbs and transfer buffers */
241 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
242 urb = usb_alloc_urb(max_packets, GFP_KERNEL);
243 if (!urb) {
244 au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i);
245 au0828_uninit_isoc(dev);
246 return -ENOMEM;
247 }
248 dev->isoc_ctl.urb[i] = urb;
249
250 dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->usbdev,
251 sb_size, GFP_KERNEL, &urb->transfer_dma);
252 if (!dev->isoc_ctl.transfer_buffer[i]) {
253 printk("unable to allocate %i bytes for transfer"
254 " buffer %i%s\n",
255 sb_size, i,
256 in_interrupt() ? " while in int" : "");
257 au0828_uninit_isoc(dev);
258 return -ENOMEM;
259 }
260 memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
261
262 pipe = usb_rcvisocpipe(dev->usbdev,
263 dev->isoc_in_endpointaddr),
264
265 usb_fill_int_urb(urb, dev->usbdev, pipe,
266 dev->isoc_ctl.transfer_buffer[i], sb_size,
267 au0828_irq_callback, dma_q, 1);
268
269 urb->number_of_packets = max_packets;
Devin Heitmuellerfadadb72009-03-22 23:42:26 -0300270 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300271
272 k = 0;
273 for (j = 0; j < max_packets; j++) {
274 urb->iso_frame_desc[j].offset = k;
275 urb->iso_frame_desc[j].length =
276 dev->isoc_ctl.max_pkt_size;
277 k += dev->isoc_ctl.max_pkt_size;
278 }
279 }
280
281 init_waitqueue_head(&dma_q->wq);
282
283 /* submit urbs and enables IRQ */
284 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
285 rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
286 if (rc) {
287 au0828_isocdbg("submit of urb %i failed (error=%i)\n",
288 i, rc);
289 au0828_uninit_isoc(dev);
290 return rc;
291 }
292 }
293
294 return 0;
295}
296
297/*
298 * Announces that a buffer were filled and request the next
299 */
300static inline void buffer_filled(struct au0828_dev *dev,
301 struct au0828_dmaqueue *dma_q,
302 struct au0828_buffer *buf)
303{
304 /* Advice that buffer was filled */
305 au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
306
307 buf->vb.state = VIDEOBUF_DONE;
308 buf->vb.field_count++;
309 do_gettimeofday(&buf->vb.ts);
310
311 dev->isoc_ctl.buf = NULL;
312
313 list_del(&buf->vb.queue);
314 wake_up(&buf->vb.done);
315}
316
317/*
318 * Identify the buffer header type and properly handles
319 */
320static void au0828_copy_video(struct au0828_dev *dev,
321 struct au0828_dmaqueue *dma_q,
322 struct au0828_buffer *buf,
323 unsigned char *p,
324 unsigned char *outp, unsigned long len)
325{
326 void *fieldstart, *startwrite, *startread;
327 int linesdone, currlinedone, offset, lencopy, remain;
328 int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */
329
330 if (dma_q->pos + len > buf->vb.size)
331 len = buf->vb.size - dma_q->pos;
332
333 startread = p;
334 remain = len;
335
336 /* Interlaces frame */
337 if (buf->top_field)
338 fieldstart = outp;
339 else
340 fieldstart = outp + bytesperline;
341
342 linesdone = dma_q->pos / bytesperline;
343 currlinedone = dma_q->pos % bytesperline;
344 offset = linesdone * bytesperline * 2 + currlinedone;
345 startwrite = fieldstart + offset;
346 lencopy = bytesperline - currlinedone;
347 lencopy = lencopy > remain ? remain : lencopy;
348
349 if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
350 au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
351 ((char *)startwrite + lencopy) -
352 ((char *)outp + buf->vb.size));
353 remain = (char *)outp + buf->vb.size - (char *)startwrite;
354 lencopy = remain;
355 }
356 if (lencopy <= 0)
357 return;
358 memcpy(startwrite, startread, lencopy);
359
360 remain -= lencopy;
361
362 while (remain > 0) {
363 startwrite += lencopy + bytesperline;
364 startread += lencopy;
365 if (bytesperline > remain)
366 lencopy = remain;
367 else
368 lencopy = bytesperline;
369
370 if ((char *)startwrite + lencopy > (char *)outp +
371 buf->vb.size) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300372 au0828_isocdbg("Overflow %zi bytes past buf end (2)\n",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300373 ((char *)startwrite + lencopy) -
374 ((char *)outp + buf->vb.size));
375 lencopy = remain = (char *)outp + buf->vb.size -
376 (char *)startwrite;
377 }
378 if (lencopy <= 0)
379 break;
380
381 memcpy(startwrite, startread, lencopy);
382
383 remain -= lencopy;
384 }
385
386 if (offset > 1440) {
387 /* We have enough data to check for greenscreen */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300388 if (outp[0] < 0x60 && outp[1440] < 0x60)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300389 dev->greenscreen_detected = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300390 }
391
392 dma_q->pos += len;
393}
394
395/*
396 * video-buf generic routine to get the next available buffer
397 */
398static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
399 struct au0828_buffer **buf)
400{
401 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
402
403 if (list_empty(&dma_q->active)) {
404 au0828_isocdbg("No active queue to serve\n");
405 dev->isoc_ctl.buf = NULL;
406 *buf = NULL;
407 return;
408 }
409
410 /* Get the next buffer */
411 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
412 dev->isoc_ctl.buf = *buf;
413
414 return;
415}
416
417/*
418 * Controls the isoc copy of each urb packet
419 */
420static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
421{
422 struct au0828_buffer *buf;
423 struct au0828_dmaqueue *dma_q = urb->context;
424 unsigned char *outp = NULL;
425 int i, len = 0, rc = 1;
426 unsigned char *p;
427 unsigned char fbyte;
428
429 if (!dev)
430 return 0;
431
432 if ((dev->dev_state & DEV_DISCONNECTED) ||
433 (dev->dev_state & DEV_MISCONFIGURED))
434 return 0;
435
436 if (urb->status < 0) {
437 print_err_status(dev, -1, urb->status);
438 if (urb->status == -ENOENT)
439 return 0;
440 }
441
442 buf = dev->isoc_ctl.buf;
443 if (buf != NULL)
444 outp = videobuf_to_vmalloc(&buf->vb);
445
446 for (i = 0; i < urb->number_of_packets; i++) {
447 int status = urb->iso_frame_desc[i].status;
448
449 if (status < 0) {
450 print_err_status(dev, i, status);
451 if (urb->iso_frame_desc[i].status != -EPROTO)
452 continue;
453 }
454
Devin Heitmueller62899a22009-03-15 18:48:52 -0300455 if (urb->iso_frame_desc[i].actual_length <= 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300456 continue;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300457
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300458 if (urb->iso_frame_desc[i].actual_length >
459 dev->max_pkt_size) {
460 au0828_isocdbg("packet bigger than packet size");
461 continue;
462 }
463
464 p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
465 fbyte = p[0];
466 len = urb->iso_frame_desc[i].actual_length - 4;
467 p += 4;
468
469 if (fbyte & 0x80) {
470 len -= 4;
471 p += 4;
472 au0828_isocdbg("Video frame %s\n",
473 (fbyte & 0x40) ? "odd" : "even");
474 if (!(fbyte & 0x40)) {
475 if (buf != NULL)
476 buffer_filled(dev, dma_q, buf);
477 get_next_buf(dma_q, &buf);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300478 if (buf == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300479 outp = NULL;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300480 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300481 outp = videobuf_to_vmalloc(&buf->vb);
482 }
483
484 if (buf != NULL) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300485 if (fbyte & 0x40)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300486 buf->top_field = 1;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300487 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300488 buf->top_field = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300489 }
490
491 dma_q->pos = 0;
492 }
Devin Heitmueller62899a22009-03-15 18:48:52 -0300493 if (buf != NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300494 au0828_copy_video(dev, dma_q, buf, p, outp, len);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300495 }
496 return rc;
497}
498
499static int
500buffer_setup(struct videobuf_queue *vq, unsigned int *count,
501 unsigned int *size)
502{
503 struct au0828_fh *fh = vq->priv_data;
504 *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
505
506 if (0 == *count)
507 *count = AU0828_DEF_BUF;
508
509 if (*count < AU0828_MIN_BUF)
510 *count = AU0828_MIN_BUF;
511 return 0;
512}
513
514/* This is called *without* dev->slock held; please keep it that way */
515static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
516{
517 struct au0828_fh *fh = vq->priv_data;
518 struct au0828_dev *dev = fh->dev;
519 unsigned long flags = 0;
520 if (in_interrupt())
521 BUG();
522
523 /* We used to wait for the buffer to finish here, but this didn't work
524 because, as we were keeping the state as VIDEOBUF_QUEUED,
525 videobuf_queue_cancel marked it as finished for us.
526 (Also, it could wedge forever if the hardware was misconfigured.)
527
528 This should be safe; by the time we get here, the buffer isn't
529 queued anymore. If we ever start marking the buffers as
530 VIDEOBUF_ACTIVE, it won't be, though.
531 */
532 spin_lock_irqsave(&dev->slock, flags);
533 if (dev->isoc_ctl.buf == buf)
534 dev->isoc_ctl.buf = NULL;
535 spin_unlock_irqrestore(&dev->slock, flags);
536
537 videobuf_vmalloc_free(&buf->vb);
538 buf->vb.state = VIDEOBUF_NEEDS_INIT;
539}
540
541static int
542buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
543 enum v4l2_field field)
544{
545 struct au0828_fh *fh = vq->priv_data;
546 struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
547 struct au0828_dev *dev = fh->dev;
548 int rc = 0, urb_init = 0;
549
550 buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
551
552 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
553 return -EINVAL;
554
555 buf->vb.width = dev->width;
556 buf->vb.height = dev->height;
557 buf->vb.field = field;
558
559 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
560 rc = videobuf_iolock(vq, &buf->vb, NULL);
561 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300562 printk(KERN_INFO "videobuf_iolock failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300563 goto fail;
564 }
565 }
566
567 if (!dev->isoc_ctl.num_bufs)
568 urb_init = 1;
569
570 if (urb_init) {
571 rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,
572 AU0828_MAX_ISO_BUFS, dev->max_pkt_size,
573 au0828_isoc_copy);
574 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300575 printk(KERN_INFO "au0828_init_isoc failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300576 goto fail;
577 }
578 }
579
580 buf->vb.state = VIDEOBUF_PREPARED;
581 return 0;
582
583fail:
584 free_buffer(vq, buf);
585 return rc;
586}
587
588static void
589buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
590{
591 struct au0828_buffer *buf = container_of(vb,
592 struct au0828_buffer,
593 vb);
594 struct au0828_fh *fh = vq->priv_data;
595 struct au0828_dev *dev = fh->dev;
596 struct au0828_dmaqueue *vidq = &dev->vidq;
597
598 buf->vb.state = VIDEOBUF_QUEUED;
599 list_add_tail(&buf->vb.queue, &vidq->active);
600}
601
602static void buffer_release(struct videobuf_queue *vq,
603 struct videobuf_buffer *vb)
604{
605 struct au0828_buffer *buf = container_of(vb,
606 struct au0828_buffer,
607 vb);
608
609 free_buffer(vq, buf);
610}
611
612static struct videobuf_queue_ops au0828_video_qops = {
613 .buf_setup = buffer_setup,
614 .buf_prepare = buffer_prepare,
615 .buf_queue = buffer_queue,
616 .buf_release = buffer_release,
617};
618
619/* ------------------------------------------------------------------
620 V4L2 interface
621 ------------------------------------------------------------------*/
622
623static int au0828_i2s_init(struct au0828_dev *dev)
624{
625 /* Enable i2s mode */
626 au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);
627 return 0;
628}
629
630/*
631 * Auvitek au0828 analog stream enable
632 * Please set interface0 to AS5 before enable the stream
633 */
634int au0828_analog_stream_enable(struct au0828_dev *d)
635{
636 dprintk(1, "au0828_analog_stream_enable called\n");
637 au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
638 au0828_writereg(d, 0x106, 0x00);
639 /* set x position */
640 au0828_writereg(d, 0x110, 0x00);
641 au0828_writereg(d, 0x111, 0x00);
642 au0828_writereg(d, 0x114, 0xa0);
643 au0828_writereg(d, 0x115, 0x05);
644 /* set y position */
645 au0828_writereg(d, 0x112, 0x02);
646 au0828_writereg(d, 0x113, 0x00);
647 au0828_writereg(d, 0x116, 0xf2);
648 au0828_writereg(d, 0x117, 0x00);
649 au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
650
651 return 0;
652}
653
654int au0828_analog_stream_disable(struct au0828_dev *d)
655{
656 dprintk(1, "au0828_analog_stream_disable called\n");
657 au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
658 return 0;
659}
660
661void au0828_analog_stream_reset(struct au0828_dev *dev)
662{
663 dprintk(1, "au0828_analog_stream_reset called\n");
664 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
665 mdelay(30);
666 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);
667}
668
669/*
670 * Some operations needs to stop current streaming
671 */
672static int au0828_stream_interrupt(struct au0828_dev *dev)
673{
674 int ret = 0;
675
676 dev->stream_state = STREAM_INTERRUPT;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300677 if (dev->dev_state == DEV_DISCONNECTED)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300678 return -ENODEV;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300679 else if (ret) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300680 dev->dev_state = DEV_MISCONFIGURED;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300681 dprintk(1, "%s device is misconfigured!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300682 return ret;
683 }
684 return 0;
685}
686
687/*
688 * au0828_release_resources
689 * unregister v4l2 devices
690 */
691void au0828_analog_unregister(struct au0828_dev *dev)
692{
693 dprintk(1, "au0828_release_resources called\n");
694 mutex_lock(&au0828_sysfs_lock);
695
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200696 if (dev->vdev)
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300697 video_unregister_device(dev->vdev);
698 if (dev->vbi_dev)
699 video_unregister_device(dev->vbi_dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300700
701 mutex_unlock(&au0828_sysfs_lock);
702}
703
704
705/* Usage lock check functions */
706static int res_get(struct au0828_fh *fh)
707{
708 struct au0828_dev *dev = fh->dev;
709 int rc = 0;
710
711 /* This instance already has stream_on */
712 if (fh->stream_on)
713 return rc;
714
715 if (dev->stream_on)
716 return -EBUSY;
717
718 dev->stream_on = 1;
719 fh->stream_on = 1;
720 return rc;
721}
722
723static int res_check(struct au0828_fh *fh)
724{
725 return fh->stream_on;
726}
727
728static void res_free(struct au0828_fh *fh)
729{
730 struct au0828_dev *dev = fh->dev;
731
732 fh->stream_on = 0;
733 dev->stream_on = 0;
734}
735
736static int au0828_v4l2_open(struct file *filp)
737{
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300738 int ret = 0;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200739 struct au0828_dev *dev = video_drvdata(filp);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300740 struct au0828_fh *fh;
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200741 int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300742
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -0300743#ifdef VBI_IS_WORKING
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200744 if (video_devdata(filp)->vfl_type == VFL_TYPE_GRABBER)
745 type = V4L2_BUF_TYPE_VBI_CAPTURE;
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300746#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300747
748 fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300749 if (NULL == fh) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300750 dprintk(1, "Failed allocate au0828_fh struct!\n");
751 return -ENOMEM;
752 }
753
754 fh->type = type;
755 fh->dev = dev;
756 filp->private_data = fh;
757
Devin Heitmueller62899a22009-03-15 18:48:52 -0300758 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300759 /* set au0828 interface0 to AS5 here again */
760 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300761 if (ret < 0) {
762 printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300763 return -EBUSY;
764 }
765 dev->width = NTSC_STD_W;
766 dev->height = NTSC_STD_H;
767 dev->frame_size = dev->width * dev->height * 2;
768 dev->field_size = dev->width * dev->height;
769 dev->bytesperline = dev->width * 2;
770
771 au0828_analog_stream_enable(dev);
772 au0828_analog_stream_reset(dev);
773
774 /* If we were doing ac97 instead of i2s, it would go here...*/
775 au0828_i2s_init(dev);
776
777 dev->stream_state = STREAM_OFF;
778 dev->dev_state |= DEV_INITIALIZED;
779 }
780
781 dev->users++;
782
783 videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
784 NULL, &dev->slock, fh->type,
785 V4L2_FIELD_INTERLACED,
786 sizeof(struct au0828_buffer), fh);
787
788 return ret;
789}
790
791static int au0828_v4l2_close(struct file *filp)
792{
793 int ret;
794 struct au0828_fh *fh = filp->private_data;
795 struct au0828_dev *dev = fh->dev;
796
797 mutex_lock(&dev->lock);
798 if (res_check(fh))
799 res_free(fh);
800
Devin Heitmueller62899a22009-03-15 18:48:52 -0300801 if (dev->users == 1) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300802 videobuf_stop(&fh->vb_vidq);
803 videobuf_mmap_free(&fh->vb_vidq);
804
Devin Heitmueller62899a22009-03-15 18:48:52 -0300805 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300806 au0828_analog_unregister(dev);
807 mutex_unlock(&dev->lock);
808 kfree(dev);
809 return 0;
810 }
811
812 au0828_analog_stream_disable(dev);
813
814 au0828_uninit_isoc(dev);
815
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -0300816 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -0300817 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -0300818
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300819 /* When close the device, set the usb intf0 into alt0 to free
820 USB bandwidth */
821 ret = usb_set_interface(dev->usbdev, 0, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300822 if (ret < 0)
823 printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300824 }
825
826 kfree(fh);
827 dev->users--;
828 wake_up_interruptible_nr(&dev->open, 1);
829 mutex_unlock(&dev->lock);
830 return 0;
831}
832
833static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
834 size_t count, loff_t *pos)
835{
836 struct au0828_fh *fh = filp->private_data;
837 struct au0828_dev *dev = fh->dev;
838 int rc;
839
840 rc = check_dev(dev);
841 if (rc < 0)
842 return rc;
843
Devin Heitmueller62899a22009-03-15 18:48:52 -0300844 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300845 mutex_lock(&dev->lock);
846 rc = res_get(fh);
847 mutex_unlock(&dev->lock);
848
849 if (unlikely(rc < 0))
850 return rc;
851
852 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
853 filp->f_flags & O_NONBLOCK);
854 }
855 return 0;
856}
857
858static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
859{
860 struct au0828_fh *fh = filp->private_data;
861 struct au0828_dev *dev = fh->dev;
862 int rc;
863
864 rc = check_dev(dev);
865 if (rc < 0)
866 return rc;
867
868 mutex_lock(&dev->lock);
869 rc = res_get(fh);
870 mutex_unlock(&dev->lock);
871
872 if (unlikely(rc < 0))
873 return POLLERR;
874
875 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
876 return POLLERR;
877
878 return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
879}
880
881static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
882{
883 struct au0828_fh *fh = filp->private_data;
884 struct au0828_dev *dev = fh->dev;
885 int rc;
886
887 rc = check_dev(dev);
888 if (rc < 0)
889 return rc;
890
891 mutex_lock(&dev->lock);
892 rc = res_get(fh);
893 mutex_unlock(&dev->lock);
894
895 if (unlikely(rc < 0))
896 return rc;
897
898 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
899
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300900 return rc;
901}
902
903static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
904 struct v4l2_format *format)
905{
906 int ret;
907 int width = format->fmt.pix.width;
908 int height = format->fmt.pix.height;
909 unsigned int maxwidth, maxheight;
910
911 maxwidth = 720;
912 maxheight = 480;
913
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -0300914#ifdef VBI_IS_WORKING
Devin Heitmueller62899a22009-03-15 18:48:52 -0300915 if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300916 dprintk(1, "VBI format set: to be supported!\n");
917 return 0;
918 }
Devin Heitmueller62899a22009-03-15 18:48:52 -0300919 if (format->type == V4L2_BUF_TYPE_VBI_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300920 return 0;
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300921#endif
Devin Heitmueller62899a22009-03-15 18:48:52 -0300922 if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300923 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300924
925 /* If they are demanding a format other than the one we support,
926 bail out (tvtime asks for UYVY and then retries with YUYV) */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300927 if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300928 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300929
930 /* format->fmt.pix.width only support 720 and height 480 */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300931 if (width != 720)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300932 width = 720;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300933 if (height != 480)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300934 height = 480;
935
936 format->fmt.pix.width = width;
937 format->fmt.pix.height = height;
938 format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
939 format->fmt.pix.bytesperline = width * 2;
940 format->fmt.pix.sizeimage = width * height * 2;
941 format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
942 format->fmt.pix.field = V4L2_FIELD_INTERLACED;
943
Devin Heitmueller62899a22009-03-15 18:48:52 -0300944 if (cmd == VIDIOC_TRY_FMT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300945 return 0;
946
947 /* maybe set new image format, driver current only support 720*480 */
948 dev->width = width;
949 dev->height = height;
950 dev->frame_size = width * height * 2;
951 dev->field_size = width * height;
952 dev->bytesperline = width * 2;
953
Devin Heitmueller62899a22009-03-15 18:48:52 -0300954 if (dev->stream_state == STREAM_ON) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300955 dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
Devin Heitmueller62899a22009-03-15 18:48:52 -0300956 ret = au0828_stream_interrupt(dev);
957 if (ret != 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300958 dprintk(1, "error interrupting video stream!\n");
959 return ret;
960 }
961 }
962
963 /* set au0828 interface0 to AS5 here again */
964 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300965 if (ret < 0) {
966 printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300967 return -EBUSY;
968 }
969
970 au0828_analog_stream_enable(dev);
971
972 return 0;
973}
974
975
976static int vidioc_queryctrl(struct file *file, void *priv,
977 struct v4l2_queryctrl *qc)
978{
979 struct au0828_fh *fh = priv;
980 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -0300981 v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300982 if (qc->type)
983 return 0;
984 else
985 return -EINVAL;
986}
987
988static int vidioc_querycap(struct file *file, void *priv,
989 struct v4l2_capability *cap)
990{
991 struct au0828_fh *fh = priv;
992 struct au0828_dev *dev = fh->dev;
993
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300994 strlcpy(cap->driver, "au0828", sizeof(cap->driver));
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300995 strlcpy(cap->card, dev->board.name, sizeof(cap->card));
Devin Heitmuellerb14667f2009-03-11 03:01:04 -0300996 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300997
998 cap->version = AU0828_VERSION_CODE;
999
1000 /*set the device capabilities */
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001001 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001002#ifdef VBI_IS_WORKING
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001003 V4L2_CAP_VBI_CAPTURE |
1004#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001005 V4L2_CAP_AUDIO |
1006 V4L2_CAP_READWRITE |
1007 V4L2_CAP_STREAMING |
1008 V4L2_CAP_TUNER;
1009 return 0;
1010}
1011
1012static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1013 struct v4l2_fmtdesc *f)
1014{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001015 if (f->index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001016 return -EINVAL;
1017
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001018 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1019 strcpy(f->description, "Packed YUV2");
1020
1021 f->flags = 0;
1022 f->pixelformat = V4L2_PIX_FMT_UYVY;
1023
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001024 return 0;
1025}
1026
1027static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1028 struct v4l2_format *f)
1029{
1030 struct au0828_fh *fh = priv;
1031 struct au0828_dev *dev = fh->dev;
1032
1033 f->fmt.pix.width = dev->width;
1034 f->fmt.pix.height = dev->height;
1035 f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1036 f->fmt.pix.bytesperline = dev->bytesperline;
1037 f->fmt.pix.sizeimage = dev->frame_size;
1038 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
1039 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1040 return 0;
1041}
1042
1043static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1044 struct v4l2_format *f)
1045{
1046 struct au0828_fh *fh = priv;
1047 struct au0828_dev *dev = fh->dev;
1048
1049 return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
1050}
1051
1052static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1053 struct v4l2_format *f)
1054{
1055 struct au0828_fh *fh = priv;
1056 struct au0828_dev *dev = fh->dev;
1057 int rc;
1058
1059 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001060 printk(KERN_INFO "%s queue busy\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001061 rc = -EBUSY;
1062 goto out;
1063 }
1064
1065 if (dev->stream_on && !fh->stream_on) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001066 printk(KERN_INFO "%s device in use by another fh\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001067 rc = -EBUSY;
1068 goto out;
1069 }
1070
1071 return au0828_set_format(dev, VIDIOC_S_FMT, f);
1072out:
1073 return rc;
1074}
1075
1076static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
1077{
1078 struct au0828_fh *fh = priv;
1079 struct au0828_dev *dev = fh->dev;
1080
1081 /* FIXME: when we support something other than NTSC, we are going to
1082 have to make the au0828 bridge adjust the size of its capture
1083 buffer, which is currently hardcoded at 720x480 */
1084
Hans Verkuilf41737e2009-04-01 03:52:39 -03001085 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001086 return 0;
1087}
1088
1089static int vidioc_enum_input(struct file *file, void *priv,
1090 struct v4l2_input *input)
1091{
1092 struct au0828_fh *fh = priv;
1093 struct au0828_dev *dev = fh->dev;
1094 unsigned int tmp;
1095
1096 static const char *inames[] = {
Devin Heitmueller3d622872009-03-15 17:48:26 -03001097 [AU0828_VMUX_UNDEFINED] = "Undefined",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001098 [AU0828_VMUX_COMPOSITE] = "Composite",
1099 [AU0828_VMUX_SVIDEO] = "S-Video",
1100 [AU0828_VMUX_CABLE] = "Cable TV",
1101 [AU0828_VMUX_TELEVISION] = "Television",
1102 [AU0828_VMUX_DVB] = "DVB",
1103 [AU0828_VMUX_DEBUG] = "tv debug"
1104 };
1105
1106 tmp = input->index;
1107
Dan Carpenterf5e20c32010-03-28 08:21:18 -03001108 if (tmp >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001109 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001110 if (AUVI_INPUT(tmp).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001111 return -EINVAL;
1112
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001113 input->index = tmp;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001114 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001115 if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
1116 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001117 input->type |= V4L2_INPUT_TYPE_TUNER;
1118 else
1119 input->type |= V4L2_INPUT_TYPE_CAMERA;
1120
1121 input->std = dev->vdev->tvnorms;
1122
1123 return 0;
1124}
1125
1126static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1127{
1128 struct au0828_fh *fh = priv;
1129 struct au0828_dev *dev = fh->dev;
1130 *i = dev->ctrl_input;
1131 return 0;
1132}
1133
1134static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1135{
1136 struct au0828_fh *fh = priv;
1137 struct au0828_dev *dev = fh->dev;
1138 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001139
Devin Heitmueller62899a22009-03-15 18:48:52 -03001140 dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001141 index);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001142 if (index >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001143 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001144 if (AUVI_INPUT(index).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001145 return -EINVAL;
1146 dev->ctrl_input = index;
1147
Devin Heitmueller62899a22009-03-15 18:48:52 -03001148 switch (AUVI_INPUT(index).type) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001149 case AU0828_VMUX_SVIDEO:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001150 dev->input_type = AU0828_VMUX_SVIDEO;
1151 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001152 case AU0828_VMUX_COMPOSITE:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001153 dev->input_type = AU0828_VMUX_COMPOSITE;
1154 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001155 case AU0828_VMUX_TELEVISION:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001156 dev->input_type = AU0828_VMUX_TELEVISION;
1157 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001158 default:
Devin Heitmuellera1094c42009-03-15 17:43:13 -03001159 dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
1160 AUVI_INPUT(index).type);
1161 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001162 }
1163
Hans Verkuil5325b422009-04-02 11:26:22 -03001164 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1165 AUVI_INPUT(index).vmux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001166
1167 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1168 int enable = 0;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001169 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001170 continue;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001171
1172 if (i == index)
1173 enable = 1;
1174 else
1175 enable = 0;
1176 if (enable) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001177 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001178 } else {
1179 /* Make sure we leave it turned on if some
1180 other input is routed to this callback */
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001181 if ((AUVI_INPUT(i).audio_setup) !=
1182 ((AUVI_INPUT(index).audio_setup))) {
1183 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001184 }
1185 }
1186 }
1187
Hans Verkuil5325b422009-04-02 11:26:22 -03001188 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1189 AUVI_INPUT(index).amux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001190 return 0;
1191}
1192
1193static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1194{
1195 struct au0828_fh *fh = priv;
1196 struct au0828_dev *dev = fh->dev;
1197 unsigned int index = a->index;
1198
Devin Heitmueller62899a22009-03-15 18:48:52 -03001199 if (a->index > 1)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001200 return -EINVAL;
1201
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001202 index = dev->ctrl_ainput;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001203 if (index == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001204 strcpy(a->name, "Television");
1205 else
1206 strcpy(a->name, "Line in");
1207
1208 a->capability = V4L2_AUDCAP_STEREO;
1209 a->index = index;
1210 return 0;
1211}
1212
1213static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
1214{
1215 struct au0828_fh *fh = priv;
1216 struct au0828_dev *dev = fh->dev;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001217 if (a->index != dev->ctrl_ainput)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001218 return -EINVAL;
1219 return 0;
1220}
1221
1222static int vidioc_g_ctrl(struct file *file, void *priv,
1223 struct v4l2_control *ctrl)
1224{
1225 struct au0828_fh *fh = priv;
1226 struct au0828_dev *dev = fh->dev;
1227
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001228 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001229 return 0;
1230
1231}
1232
1233static int vidioc_s_ctrl(struct file *file, void *priv,
1234 struct v4l2_control *ctrl)
1235{
1236 struct au0828_fh *fh = priv;
1237 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001238 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001239 return 0;
1240}
1241
1242static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
1243{
1244 struct au0828_fh *fh = priv;
1245 struct au0828_dev *dev = fh->dev;
1246
Devin Heitmueller62899a22009-03-15 18:48:52 -03001247 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001248 return -EINVAL;
1249
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001250 strcpy(t->name, "Auvitek tuner");
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001251 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001252 return 0;
1253}
1254
1255static int vidioc_s_tuner(struct file *file, void *priv,
1256 struct v4l2_tuner *t)
1257{
1258 struct au0828_fh *fh = priv;
1259 struct au0828_dev *dev = fh->dev;
1260
Devin Heitmueller62899a22009-03-15 18:48:52 -03001261 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001262 return -EINVAL;
1263
1264 t->type = V4L2_TUNER_ANALOG_TV;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001265 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001266 dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
1267 t->afc);
1268 return 0;
1269
1270}
1271
1272static int vidioc_g_frequency(struct file *file, void *priv,
1273 struct v4l2_frequency *freq)
1274{
1275 struct au0828_fh *fh = priv;
1276 struct au0828_dev *dev = fh->dev;
Devin Heitmuellerc8889232009-03-15 17:38:47 -03001277
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001278 freq->type = V4L2_TUNER_ANALOG_TV;
1279 freq->frequency = dev->ctrl_freq;
1280 return 0;
1281}
1282
1283static int vidioc_s_frequency(struct file *file, void *priv,
1284 struct v4l2_frequency *freq)
1285{
1286 struct au0828_fh *fh = priv;
1287 struct au0828_dev *dev = fh->dev;
1288
Devin Heitmueller62899a22009-03-15 18:48:52 -03001289 if (freq->tuner != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001290 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001291 if (freq->type != V4L2_TUNER_ANALOG_TV)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001292 return -EINVAL;
1293
1294 dev->ctrl_freq = freq->frequency;
1295
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001296 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001297
1298 au0828_analog_stream_reset(dev);
1299
1300 return 0;
1301}
1302
1303static int vidioc_g_chip_ident(struct file *file, void *priv,
1304 struct v4l2_dbg_chip_ident *chip)
1305{
1306 struct au0828_fh *fh = priv;
1307 struct au0828_dev *dev = fh->dev;
1308 chip->ident = V4L2_IDENT_NONE;
1309 chip->revision = 0;
1310
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001311 if (v4l2_chip_match_host(&chip->match)) {
1312 chip->ident = V4L2_IDENT_AU0828;
1313 return 0;
1314 }
1315
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001316 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001317 if (chip->ident == V4L2_IDENT_NONE)
1318 return -EINVAL;
1319
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001320 return 0;
1321}
1322
1323static int vidioc_cropcap(struct file *file, void *priv,
1324 struct v4l2_cropcap *cc)
1325{
1326 struct au0828_fh *fh = priv;
1327 struct au0828_dev *dev = fh->dev;
1328
Devin Heitmueller62899a22009-03-15 18:48:52 -03001329 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001330 return -EINVAL;
1331
1332 cc->bounds.left = 0;
1333 cc->bounds.top = 0;
1334 cc->bounds.width = dev->width;
1335 cc->bounds.height = dev->height;
1336
1337 cc->defrect = cc->bounds;
1338
1339 cc->pixelaspect.numerator = 54;
1340 cc->pixelaspect.denominator = 59;
1341
1342 return 0;
1343}
1344
1345static int vidioc_streamon(struct file *file, void *priv,
1346 enum v4l2_buf_type type)
1347{
1348 struct au0828_fh *fh = priv;
1349 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001350 int rc;
1351
1352 rc = check_dev(dev);
1353 if (rc < 0)
1354 return rc;
1355
1356 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1357 au0828_analog_stream_enable(dev);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001358 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001359 }
1360
1361 mutex_lock(&dev->lock);
1362 rc = res_get(fh);
1363
1364 if (likely(rc >= 0))
1365 rc = videobuf_streamon(&fh->vb_vidq);
1366 mutex_unlock(&dev->lock);
1367
1368 return rc;
1369}
1370
1371static int vidioc_streamoff(struct file *file, void *priv,
1372 enum v4l2_buf_type type)
1373{
1374 struct au0828_fh *fh = priv;
1375 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001376 int i;
1377 int ret;
1378 int rc;
1379
1380 rc = check_dev(dev);
1381 if (rc < 0)
1382 return rc;
1383
1384 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1385 return -EINVAL;
1386 if (type != fh->type)
1387 return -EINVAL;
1388
1389 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001390 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001391 ret = au0828_stream_interrupt(dev);
1392 if (ret != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001393 return ret;
1394 }
1395
1396 for (i = 0; i < AU0828_MAX_INPUT; i++) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001397 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001398 continue;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001399 (AUVI_INPUT(i).audio_setup)(dev, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001400 }
1401
1402 mutex_lock(&dev->lock);
1403 videobuf_streamoff(&fh->vb_vidq);
1404 res_free(fh);
1405 mutex_unlock(&dev->lock);
1406
1407 return 0;
1408}
1409
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001410#ifdef CONFIG_VIDEO_ADV_DEBUG
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001411static int vidioc_g_register(struct file *file, void *priv,
1412 struct v4l2_dbg_register *reg)
1413{
1414 struct au0828_fh *fh = priv;
1415 struct au0828_dev *dev = fh->dev;
1416
1417 switch (reg->match.type) {
1418 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001419 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001420 return 0;
1421 default:
1422 return -EINVAL;
1423 }
1424}
1425
1426static int vidioc_s_register(struct file *file, void *priv,
1427 struct v4l2_dbg_register *reg)
1428{
1429 struct au0828_fh *fh = priv;
1430 struct au0828_dev *dev = fh->dev;
1431
1432 switch (reg->match.type) {
1433 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001434 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001435 return 0;
1436 default:
1437 return -EINVAL;
1438 }
1439 return 0;
1440}
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001441#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001442
1443static int vidioc_reqbufs(struct file *file, void *priv,
1444 struct v4l2_requestbuffers *rb)
1445{
1446 struct au0828_fh *fh = priv;
1447 struct au0828_dev *dev = fh->dev;
1448 int rc;
1449
1450 rc = check_dev(dev);
1451 if (rc < 0)
1452 return rc;
1453
1454 return videobuf_reqbufs(&fh->vb_vidq, rb);
1455}
1456
1457static int vidioc_querybuf(struct file *file, void *priv,
1458 struct v4l2_buffer *b)
1459{
1460 struct au0828_fh *fh = priv;
1461 struct au0828_dev *dev = fh->dev;
1462 int rc;
1463
1464 rc = check_dev(dev);
1465 if (rc < 0)
1466 return rc;
1467
1468 return videobuf_querybuf(&fh->vb_vidq, b);
1469}
1470
1471static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1472{
1473 struct au0828_fh *fh = priv;
1474 struct au0828_dev *dev = fh->dev;
1475 int rc;
1476
1477 rc = check_dev(dev);
1478 if (rc < 0)
1479 return rc;
1480
1481 return videobuf_qbuf(&fh->vb_vidq, b);
1482}
1483
1484static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1485{
1486 struct au0828_fh *fh = priv;
1487 struct au0828_dev *dev = fh->dev;
1488 int rc;
1489
1490 rc = check_dev(dev);
1491 if (rc < 0)
1492 return rc;
1493
1494 /* Workaround for a bug in the au0828 hardware design that sometimes
1495 results in the colorspace being inverted */
1496 if (dev->greenscreen_detected == 1) {
1497 dprintk(1, "Detected green frame. Resetting stream...\n");
1498 au0828_analog_stream_reset(dev);
1499 dev->greenscreen_detected = 0;
1500 }
1501
1502 return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1503}
1504
1505#ifdef CONFIG_VIDEO_V4L1_COMPAT
1506static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
1507{
1508 struct au0828_fh *fh = priv;
1509
1510 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
1511}
1512#endif
1513
1514static struct v4l2_file_operations au0828_v4l_fops = {
1515 .owner = THIS_MODULE,
1516 .open = au0828_v4l2_open,
1517 .release = au0828_v4l2_close,
1518 .read = au0828_v4l2_read,
1519 .poll = au0828_v4l2_poll,
1520 .mmap = au0828_v4l2_mmap,
1521 .ioctl = video_ioctl2,
1522};
1523
1524static const struct v4l2_ioctl_ops video_ioctl_ops = {
1525 .vidioc_querycap = vidioc_querycap,
1526 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1527 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1528 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1529 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001530#ifdef VBI_IS_WORKING
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001531 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
1532 .vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
1533 .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
1534#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001535 .vidioc_g_audio = vidioc_g_audio,
1536 .vidioc_s_audio = vidioc_s_audio,
1537 .vidioc_cropcap = vidioc_cropcap,
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001538#ifdef VBI_IS_WORKING
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001539 .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap,
1540 .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
1541 .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
1542#endif
1543 .vidioc_reqbufs = vidioc_reqbufs,
1544 .vidioc_querybuf = vidioc_querybuf,
1545 .vidioc_qbuf = vidioc_qbuf,
1546 .vidioc_dqbuf = vidioc_dqbuf,
1547 .vidioc_s_std = vidioc_s_std,
1548 .vidioc_enum_input = vidioc_enum_input,
1549 .vidioc_g_input = vidioc_g_input,
1550 .vidioc_s_input = vidioc_s_input,
1551 .vidioc_queryctrl = vidioc_queryctrl,
1552 .vidioc_g_ctrl = vidioc_g_ctrl,
1553 .vidioc_s_ctrl = vidioc_s_ctrl,
1554 .vidioc_streamon = vidioc_streamon,
1555 .vidioc_streamoff = vidioc_streamoff,
1556 .vidioc_g_tuner = vidioc_g_tuner,
1557 .vidioc_s_tuner = vidioc_s_tuner,
1558 .vidioc_g_frequency = vidioc_g_frequency,
1559 .vidioc_s_frequency = vidioc_s_frequency,
1560#ifdef CONFIG_VIDEO_ADV_DEBUG
1561 .vidioc_g_register = vidioc_g_register,
1562 .vidioc_s_register = vidioc_s_register,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001563#endif
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001564 .vidioc_g_chip_ident = vidioc_g_chip_ident,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001565#ifdef CONFIG_VIDEO_V4L1_COMPAT
1566 .vidiocgmbuf = vidiocgmbuf,
1567#endif
1568};
1569
1570static const struct video_device au0828_video_template = {
1571 .fops = &au0828_v4l_fops,
1572 .release = video_device_release,
1573 .ioctl_ops = &video_ioctl_ops,
Devin Heitmueller0ef21072009-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