blob: f42f3deaa03b21b90169f50f88de0ab20a36d0fb [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
43static LIST_HEAD(au0828_devlist);
44static 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
Devin Heitmueller2eaf3962009-03-11 03:01:02 -0300696 if (dev->vdev) {
697 list_del(&dev->au0828list);
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300698 video_unregister_device(dev->vdev);
Devin Heitmueller2eaf3962009-03-11 03:01:02 -0300699 }
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300700 if (dev->vbi_dev)
701 video_unregister_device(dev->vbi_dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300702
703 mutex_unlock(&au0828_sysfs_lock);
704}
705
706
707/* Usage lock check functions */
708static int res_get(struct au0828_fh *fh)
709{
710 struct au0828_dev *dev = fh->dev;
711 int rc = 0;
712
713 /* This instance already has stream_on */
714 if (fh->stream_on)
715 return rc;
716
717 if (dev->stream_on)
718 return -EBUSY;
719
720 dev->stream_on = 1;
721 fh->stream_on = 1;
722 return rc;
723}
724
725static int res_check(struct au0828_fh *fh)
726{
727 return fh->stream_on;
728}
729
730static void res_free(struct au0828_fh *fh)
731{
732 struct au0828_dev *dev = fh->dev;
733
734 fh->stream_on = 0;
735 dev->stream_on = 0;
736}
737
738static int au0828_v4l2_open(struct file *filp)
739{
740 int minor = video_devdata(filp)->minor;
741 int ret = 0;
742 struct au0828_dev *h, *dev = NULL;
743 struct au0828_fh *fh;
744 int type = 0;
745 struct list_head *list;
746
747 list_for_each(list, &au0828_devlist) {
748 h = list_entry(list, struct au0828_dev, au0828list);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300749 if (h->vdev->minor == minor) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300750 dev = h;
751 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
752 }
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -0300753#ifdef VBI_IS_WORKING
Devin Heitmueller62899a22009-03-15 18:48:52 -0300754 if (h->vbi_dev->minor == minor) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300755 dev = h;
756 type = V4L2_BUF_TYPE_VBI_CAPTURE;
757 }
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300758#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300759 }
760
Devin Heitmueller62899a22009-03-15 18:48:52 -0300761 if (NULL == dev)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300762 return -ENODEV;
763
764 fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300765 if (NULL == fh) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300766 dprintk(1, "Failed allocate au0828_fh struct!\n");
767 return -ENOMEM;
768 }
769
770 fh->type = type;
771 fh->dev = dev;
772 filp->private_data = fh;
773
Devin Heitmueller62899a22009-03-15 18:48:52 -0300774 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300775 /* set au0828 interface0 to AS5 here again */
776 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300777 if (ret < 0) {
778 printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300779 return -EBUSY;
780 }
781 dev->width = NTSC_STD_W;
782 dev->height = NTSC_STD_H;
783 dev->frame_size = dev->width * dev->height * 2;
784 dev->field_size = dev->width * dev->height;
785 dev->bytesperline = dev->width * 2;
786
787 au0828_analog_stream_enable(dev);
788 au0828_analog_stream_reset(dev);
789
790 /* If we were doing ac97 instead of i2s, it would go here...*/
791 au0828_i2s_init(dev);
792
793 dev->stream_state = STREAM_OFF;
794 dev->dev_state |= DEV_INITIALIZED;
795 }
796
797 dev->users++;
798
799 videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
800 NULL, &dev->slock, fh->type,
801 V4L2_FIELD_INTERLACED,
802 sizeof(struct au0828_buffer), fh);
803
804 return ret;
805}
806
807static int au0828_v4l2_close(struct file *filp)
808{
809 int ret;
810 struct au0828_fh *fh = filp->private_data;
811 struct au0828_dev *dev = fh->dev;
812
813 mutex_lock(&dev->lock);
814 if (res_check(fh))
815 res_free(fh);
816
Devin Heitmueller62899a22009-03-15 18:48:52 -0300817 if (dev->users == 1) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300818 videobuf_stop(&fh->vb_vidq);
819 videobuf_mmap_free(&fh->vb_vidq);
820
Devin Heitmueller62899a22009-03-15 18:48:52 -0300821 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300822 au0828_analog_unregister(dev);
823 mutex_unlock(&dev->lock);
824 kfree(dev);
825 return 0;
826 }
827
828 au0828_analog_stream_disable(dev);
829
830 au0828_uninit_isoc(dev);
831
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -0300832 /* Save some power by putting tuner to sleep */
833 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby);
834
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300835 /* When close the device, set the usb intf0 into alt0 to free
836 USB bandwidth */
837 ret = usb_set_interface(dev->usbdev, 0, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300838 if (ret < 0)
839 printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300840 }
841
842 kfree(fh);
843 dev->users--;
844 wake_up_interruptible_nr(&dev->open, 1);
845 mutex_unlock(&dev->lock);
846 return 0;
847}
848
849static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
850 size_t count, loff_t *pos)
851{
852 struct au0828_fh *fh = filp->private_data;
853 struct au0828_dev *dev = fh->dev;
854 int rc;
855
856 rc = check_dev(dev);
857 if (rc < 0)
858 return rc;
859
Devin Heitmueller62899a22009-03-15 18:48:52 -0300860 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300861 mutex_lock(&dev->lock);
862 rc = res_get(fh);
863 mutex_unlock(&dev->lock);
864
865 if (unlikely(rc < 0))
866 return rc;
867
868 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
869 filp->f_flags & O_NONBLOCK);
870 }
871 return 0;
872}
873
874static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
875{
876 struct au0828_fh *fh = filp->private_data;
877 struct au0828_dev *dev = fh->dev;
878 int rc;
879
880 rc = check_dev(dev);
881 if (rc < 0)
882 return rc;
883
884 mutex_lock(&dev->lock);
885 rc = res_get(fh);
886 mutex_unlock(&dev->lock);
887
888 if (unlikely(rc < 0))
889 return POLLERR;
890
891 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
892 return POLLERR;
893
894 return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
895}
896
897static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
898{
899 struct au0828_fh *fh = filp->private_data;
900 struct au0828_dev *dev = fh->dev;
901 int rc;
902
903 rc = check_dev(dev);
904 if (rc < 0)
905 return rc;
906
907 mutex_lock(&dev->lock);
908 rc = res_get(fh);
909 mutex_unlock(&dev->lock);
910
911 if (unlikely(rc < 0))
912 return rc;
913
914 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
915
916 dprintk(2, "vma start=0x%08lx, size=%ld, ret=%d\n",
917 (unsigned long)vma->vm_start,
918 (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
919 rc);
920
921 return rc;
922}
923
924static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
925 struct v4l2_format *format)
926{
927 int ret;
928 int width = format->fmt.pix.width;
929 int height = format->fmt.pix.height;
930 unsigned int maxwidth, maxheight;
931
932 maxwidth = 720;
933 maxheight = 480;
934
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -0300935#ifdef VBI_IS_WORKING
Devin Heitmueller62899a22009-03-15 18:48:52 -0300936 if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300937 dprintk(1, "VBI format set: to be supported!\n");
938 return 0;
939 }
Devin Heitmueller62899a22009-03-15 18:48:52 -0300940 if (format->type == V4L2_BUF_TYPE_VBI_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300941 return 0;
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300942#endif
Devin Heitmueller62899a22009-03-15 18:48:52 -0300943 if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300944 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300945
946 /* If they are demanding a format other than the one we support,
947 bail out (tvtime asks for UYVY and then retries with YUYV) */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300948 if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300949 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300950
951 /* format->fmt.pix.width only support 720 and height 480 */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300952 if (width != 720)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300953 width = 720;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300954 if (height != 480)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300955 height = 480;
956
957 format->fmt.pix.width = width;
958 format->fmt.pix.height = height;
959 format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
960 format->fmt.pix.bytesperline = width * 2;
961 format->fmt.pix.sizeimage = width * height * 2;
962 format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
963 format->fmt.pix.field = V4L2_FIELD_INTERLACED;
964
Devin Heitmueller62899a22009-03-15 18:48:52 -0300965 if (cmd == VIDIOC_TRY_FMT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300966 return 0;
967
968 /* maybe set new image format, driver current only support 720*480 */
969 dev->width = width;
970 dev->height = height;
971 dev->frame_size = width * height * 2;
972 dev->field_size = width * height;
973 dev->bytesperline = width * 2;
974
Devin Heitmueller62899a22009-03-15 18:48:52 -0300975 if (dev->stream_state == STREAM_ON) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300976 dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
Devin Heitmueller62899a22009-03-15 18:48:52 -0300977 ret = au0828_stream_interrupt(dev);
978 if (ret != 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300979 dprintk(1, "error interrupting video stream!\n");
980 return ret;
981 }
982 }
983
984 /* set au0828 interface0 to AS5 here again */
985 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300986 if (ret < 0) {
987 printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300988 return -EBUSY;
989 }
990
991 au0828_analog_stream_enable(dev);
992
993 return 0;
994}
995
996
997static int vidioc_queryctrl(struct file *file, void *priv,
998 struct v4l2_queryctrl *qc)
999{
1000 struct au0828_fh *fh = priv;
1001 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001002 v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001003 if (qc->type)
1004 return 0;
1005 else
1006 return -EINVAL;
1007}
1008
1009static int vidioc_querycap(struct file *file, void *priv,
1010 struct v4l2_capability *cap)
1011{
1012 struct au0828_fh *fh = priv;
1013 struct au0828_dev *dev = fh->dev;
1014
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001015 strlcpy(cap->driver, "au0828", sizeof(cap->driver));
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001016 strlcpy(cap->card, dev->board.name, sizeof(cap->card));
Devin Heitmuellerb14667f2009-03-11 03:01:04 -03001017 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001018
1019 cap->version = AU0828_VERSION_CODE;
1020
1021 /*set the device capabilities */
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001022 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001023#ifdef VBI_IS_WORKING
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001024 V4L2_CAP_VBI_CAPTURE |
1025#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001026 V4L2_CAP_AUDIO |
1027 V4L2_CAP_READWRITE |
1028 V4L2_CAP_STREAMING |
1029 V4L2_CAP_TUNER;
1030 return 0;
1031}
1032
1033static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1034 struct v4l2_fmtdesc *f)
1035{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001036 if (f->index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001037 return -EINVAL;
1038
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001039 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1040 strcpy(f->description, "Packed YUV2");
1041
1042 f->flags = 0;
1043 f->pixelformat = V4L2_PIX_FMT_UYVY;
1044
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001045 return 0;
1046}
1047
1048static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1049 struct v4l2_format *f)
1050{
1051 struct au0828_fh *fh = priv;
1052 struct au0828_dev *dev = fh->dev;
1053
1054 f->fmt.pix.width = dev->width;
1055 f->fmt.pix.height = dev->height;
1056 f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1057 f->fmt.pix.bytesperline = dev->bytesperline;
1058 f->fmt.pix.sizeimage = dev->frame_size;
1059 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
1060 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1061 return 0;
1062}
1063
1064static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1065 struct v4l2_format *f)
1066{
1067 struct au0828_fh *fh = priv;
1068 struct au0828_dev *dev = fh->dev;
1069
1070 return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
1071}
1072
1073static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1074 struct v4l2_format *f)
1075{
1076 struct au0828_fh *fh = priv;
1077 struct au0828_dev *dev = fh->dev;
1078 int rc;
1079
1080 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001081 printk(KERN_INFO "%s queue busy\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001082 rc = -EBUSY;
1083 goto out;
1084 }
1085
1086 if (dev->stream_on && !fh->stream_on) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001087 printk(KERN_INFO "%s device in use by another fh\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001088 rc = -EBUSY;
1089 goto out;
1090 }
1091
1092 return au0828_set_format(dev, VIDIOC_S_FMT, f);
1093out:
1094 return rc;
1095}
1096
1097static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
1098{
1099 struct au0828_fh *fh = priv;
1100 struct au0828_dev *dev = fh->dev;
1101
1102 /* FIXME: when we support something other than NTSC, we are going to
1103 have to make the au0828 bridge adjust the size of its capture
1104 buffer, which is currently hardcoded at 720x480 */
1105
Hans Verkuilf41737e2009-04-01 03:52:39 -03001106 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001107 return 0;
1108}
1109
1110static int vidioc_enum_input(struct file *file, void *priv,
1111 struct v4l2_input *input)
1112{
1113 struct au0828_fh *fh = priv;
1114 struct au0828_dev *dev = fh->dev;
1115 unsigned int tmp;
1116
1117 static const char *inames[] = {
Devin Heitmueller3d622872009-03-15 17:48:26 -03001118 [AU0828_VMUX_UNDEFINED] = "Undefined",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001119 [AU0828_VMUX_COMPOSITE] = "Composite",
1120 [AU0828_VMUX_SVIDEO] = "S-Video",
1121 [AU0828_VMUX_CABLE] = "Cable TV",
1122 [AU0828_VMUX_TELEVISION] = "Television",
1123 [AU0828_VMUX_DVB] = "DVB",
1124 [AU0828_VMUX_DEBUG] = "tv debug"
1125 };
1126
1127 tmp = input->index;
1128
Devin Heitmueller62899a22009-03-15 18:48:52 -03001129 if (tmp > AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001130 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001131 if (AUVI_INPUT(tmp).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001132 return -EINVAL;
1133
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001134 input->index = tmp;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001135 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001136 if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
1137 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001138 input->type |= V4L2_INPUT_TYPE_TUNER;
1139 else
1140 input->type |= V4L2_INPUT_TYPE_CAMERA;
1141
1142 input->std = dev->vdev->tvnorms;
1143
1144 return 0;
1145}
1146
1147static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1148{
1149 struct au0828_fh *fh = priv;
1150 struct au0828_dev *dev = fh->dev;
1151 *i = dev->ctrl_input;
1152 return 0;
1153}
1154
1155static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1156{
1157 struct au0828_fh *fh = priv;
1158 struct au0828_dev *dev = fh->dev;
1159 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001160
Devin Heitmueller62899a22009-03-15 18:48:52 -03001161 dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001162 index);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001163 if (index >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001164 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001165 if (AUVI_INPUT(index).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001166 return -EINVAL;
1167 dev->ctrl_input = index;
1168
Devin Heitmueller62899a22009-03-15 18:48:52 -03001169 switch (AUVI_INPUT(index).type) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001170 case AU0828_VMUX_SVIDEO:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001171 dev->input_type = AU0828_VMUX_SVIDEO;
1172 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001173 case AU0828_VMUX_COMPOSITE:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001174 dev->input_type = AU0828_VMUX_COMPOSITE;
1175 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001176 case AU0828_VMUX_TELEVISION:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001177 dev->input_type = AU0828_VMUX_TELEVISION;
1178 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001179 default:
Devin Heitmuellera1094c42009-03-15 17:43:13 -03001180 dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
1181 AUVI_INPUT(index).type);
1182 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001183 }
1184
Hans Verkuil5325b422009-04-02 11:26:22 -03001185 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1186 AUVI_INPUT(index).vmux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001187
1188 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1189 int enable = 0;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001190 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001191 continue;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001192
1193 if (i == index)
1194 enable = 1;
1195 else
1196 enable = 0;
1197 if (enable) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001198 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001199 } else {
1200 /* Make sure we leave it turned on if some
1201 other input is routed to this callback */
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001202 if ((AUVI_INPUT(i).audio_setup) !=
1203 ((AUVI_INPUT(index).audio_setup))) {
1204 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001205 }
1206 }
1207 }
1208
Hans Verkuil5325b422009-04-02 11:26:22 -03001209 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1210 AUVI_INPUT(index).amux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001211 return 0;
1212}
1213
1214static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1215{
1216 struct au0828_fh *fh = priv;
1217 struct au0828_dev *dev = fh->dev;
1218 unsigned int index = a->index;
1219
Devin Heitmueller62899a22009-03-15 18:48:52 -03001220 if (a->index > 1)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001221 return -EINVAL;
1222
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001223 index = dev->ctrl_ainput;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001224 if (index == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001225 strcpy(a->name, "Television");
1226 else
1227 strcpy(a->name, "Line in");
1228
1229 a->capability = V4L2_AUDCAP_STEREO;
1230 a->index = index;
1231 return 0;
1232}
1233
1234static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
1235{
1236 struct au0828_fh *fh = priv;
1237 struct au0828_dev *dev = fh->dev;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001238 if (a->index != dev->ctrl_ainput)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001239 return -EINVAL;
1240 return 0;
1241}
1242
1243static int vidioc_g_ctrl(struct file *file, void *priv,
1244 struct v4l2_control *ctrl)
1245{
1246 struct au0828_fh *fh = priv;
1247 struct au0828_dev *dev = fh->dev;
1248
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001249 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001250 return 0;
1251
1252}
1253
1254static int vidioc_s_ctrl(struct file *file, void *priv,
1255 struct v4l2_control *ctrl)
1256{
1257 struct au0828_fh *fh = priv;
1258 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001259 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001260 return 0;
1261}
1262
1263static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
1264{
1265 struct au0828_fh *fh = priv;
1266 struct au0828_dev *dev = fh->dev;
1267
Devin Heitmueller62899a22009-03-15 18:48:52 -03001268 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001269 return -EINVAL;
1270
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001271 strcpy(t->name, "Auvitek tuner");
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001272 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001273 return 0;
1274}
1275
1276static int vidioc_s_tuner(struct file *file, void *priv,
1277 struct v4l2_tuner *t)
1278{
1279 struct au0828_fh *fh = priv;
1280 struct au0828_dev *dev = fh->dev;
1281
Devin Heitmueller62899a22009-03-15 18:48:52 -03001282 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001283 return -EINVAL;
1284
1285 t->type = V4L2_TUNER_ANALOG_TV;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001286 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001287 dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
1288 t->afc);
1289 return 0;
1290
1291}
1292
1293static int vidioc_g_frequency(struct file *file, void *priv,
1294 struct v4l2_frequency *freq)
1295{
1296 struct au0828_fh *fh = priv;
1297 struct au0828_dev *dev = fh->dev;
Devin Heitmuellerc8889232009-03-15 17:38:47 -03001298
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001299 freq->type = V4L2_TUNER_ANALOG_TV;
1300 freq->frequency = dev->ctrl_freq;
1301 return 0;
1302}
1303
1304static int vidioc_s_frequency(struct file *file, void *priv,
1305 struct v4l2_frequency *freq)
1306{
1307 struct au0828_fh *fh = priv;
1308 struct au0828_dev *dev = fh->dev;
1309
Devin Heitmueller62899a22009-03-15 18:48:52 -03001310 if (freq->tuner != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001311 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001312 if (freq->type != V4L2_TUNER_ANALOG_TV)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001313 return -EINVAL;
1314
1315 dev->ctrl_freq = freq->frequency;
1316
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001317 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001318
1319 au0828_analog_stream_reset(dev);
1320
1321 return 0;
1322}
1323
1324static int vidioc_g_chip_ident(struct file *file, void *priv,
1325 struct v4l2_dbg_chip_ident *chip)
1326{
1327 struct au0828_fh *fh = priv;
1328 struct au0828_dev *dev = fh->dev;
1329 chip->ident = V4L2_IDENT_NONE;
1330 chip->revision = 0;
1331
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001332 if (v4l2_chip_match_host(&chip->match)) {
1333 chip->ident = V4L2_IDENT_AU0828;
1334 return 0;
1335 }
1336
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001337 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001338 if (chip->ident == V4L2_IDENT_NONE)
1339 return -EINVAL;
1340
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001341 return 0;
1342}
1343
1344static int vidioc_cropcap(struct file *file, void *priv,
1345 struct v4l2_cropcap *cc)
1346{
1347 struct au0828_fh *fh = priv;
1348 struct au0828_dev *dev = fh->dev;
1349
Devin Heitmueller62899a22009-03-15 18:48:52 -03001350 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001351 return -EINVAL;
1352
1353 cc->bounds.left = 0;
1354 cc->bounds.top = 0;
1355 cc->bounds.width = dev->width;
1356 cc->bounds.height = dev->height;
1357
1358 cc->defrect = cc->bounds;
1359
1360 cc->pixelaspect.numerator = 54;
1361 cc->pixelaspect.denominator = 59;
1362
1363 return 0;
1364}
1365
1366static int vidioc_streamon(struct file *file, void *priv,
1367 enum v4l2_buf_type type)
1368{
1369 struct au0828_fh *fh = priv;
1370 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001371 int rc;
1372
1373 rc = check_dev(dev);
1374 if (rc < 0)
1375 return rc;
1376
1377 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1378 au0828_analog_stream_enable(dev);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001379 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001380 }
1381
1382 mutex_lock(&dev->lock);
1383 rc = res_get(fh);
1384
1385 if (likely(rc >= 0))
1386 rc = videobuf_streamon(&fh->vb_vidq);
1387 mutex_unlock(&dev->lock);
1388
1389 return rc;
1390}
1391
1392static int vidioc_streamoff(struct file *file, void *priv,
1393 enum v4l2_buf_type type)
1394{
1395 struct au0828_fh *fh = priv;
1396 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001397 int i;
1398 int ret;
1399 int rc;
1400
1401 rc = check_dev(dev);
1402 if (rc < 0)
1403 return rc;
1404
1405 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1406 return -EINVAL;
1407 if (type != fh->type)
1408 return -EINVAL;
1409
1410 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001411 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001412 ret = au0828_stream_interrupt(dev);
1413 if (ret != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001414 return ret;
1415 }
1416
1417 for (i = 0; i < AU0828_MAX_INPUT; i++) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001418 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001419 continue;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001420 (AUVI_INPUT(i).audio_setup)(dev, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001421 }
1422
1423 mutex_lock(&dev->lock);
1424 videobuf_streamoff(&fh->vb_vidq);
1425 res_free(fh);
1426 mutex_unlock(&dev->lock);
1427
1428 return 0;
1429}
1430
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001431#ifdef CONFIG_VIDEO_ADV_DEBUG
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001432static int vidioc_g_register(struct file *file, void *priv,
1433 struct v4l2_dbg_register *reg)
1434{
1435 struct au0828_fh *fh = priv;
1436 struct au0828_dev *dev = fh->dev;
1437
1438 switch (reg->match.type) {
1439 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001440 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001441 return 0;
1442 default:
1443 return -EINVAL;
1444 }
1445}
1446
1447static int vidioc_s_register(struct file *file, void *priv,
1448 struct v4l2_dbg_register *reg)
1449{
1450 struct au0828_fh *fh = priv;
1451 struct au0828_dev *dev = fh->dev;
1452
1453 switch (reg->match.type) {
1454 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001455 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001456 return 0;
1457 default:
1458 return -EINVAL;
1459 }
1460 return 0;
1461}
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001462#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001463
1464static int vidioc_reqbufs(struct file *file, void *priv,
1465 struct v4l2_requestbuffers *rb)
1466{
1467 struct au0828_fh *fh = priv;
1468 struct au0828_dev *dev = fh->dev;
1469 int rc;
1470
1471 rc = check_dev(dev);
1472 if (rc < 0)
1473 return rc;
1474
1475 return videobuf_reqbufs(&fh->vb_vidq, rb);
1476}
1477
1478static int vidioc_querybuf(struct file *file, void *priv,
1479 struct v4l2_buffer *b)
1480{
1481 struct au0828_fh *fh = priv;
1482 struct au0828_dev *dev = fh->dev;
1483 int rc;
1484
1485 rc = check_dev(dev);
1486 if (rc < 0)
1487 return rc;
1488
1489 return videobuf_querybuf(&fh->vb_vidq, b);
1490}
1491
1492static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1493{
1494 struct au0828_fh *fh = priv;
1495 struct au0828_dev *dev = fh->dev;
1496 int rc;
1497
1498 rc = check_dev(dev);
1499 if (rc < 0)
1500 return rc;
1501
1502 return videobuf_qbuf(&fh->vb_vidq, b);
1503}
1504
1505static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1506{
1507 struct au0828_fh *fh = priv;
1508 struct au0828_dev *dev = fh->dev;
1509 int rc;
1510
1511 rc = check_dev(dev);
1512 if (rc < 0)
1513 return rc;
1514
1515 /* Workaround for a bug in the au0828 hardware design that sometimes
1516 results in the colorspace being inverted */
1517 if (dev->greenscreen_detected == 1) {
1518 dprintk(1, "Detected green frame. Resetting stream...\n");
1519 au0828_analog_stream_reset(dev);
1520 dev->greenscreen_detected = 0;
1521 }
1522
1523 return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1524}
1525
1526#ifdef CONFIG_VIDEO_V4L1_COMPAT
1527static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
1528{
1529 struct au0828_fh *fh = priv;
1530
1531 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
1532}
1533#endif
1534
1535static struct v4l2_file_operations au0828_v4l_fops = {
1536 .owner = THIS_MODULE,
1537 .open = au0828_v4l2_open,
1538 .release = au0828_v4l2_close,
1539 .read = au0828_v4l2_read,
1540 .poll = au0828_v4l2_poll,
1541 .mmap = au0828_v4l2_mmap,
1542 .ioctl = video_ioctl2,
1543};
1544
1545static const struct v4l2_ioctl_ops video_ioctl_ops = {
1546 .vidioc_querycap = vidioc_querycap,
1547 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1548 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1549 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1550 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001551#ifdef VBI_IS_WORKING
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001552 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
1553 .vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
1554 .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
1555#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001556 .vidioc_g_audio = vidioc_g_audio,
1557 .vidioc_s_audio = vidioc_s_audio,
1558 .vidioc_cropcap = vidioc_cropcap,
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001559#ifdef VBI_IS_WORKING
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001560 .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap,
1561 .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
1562 .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
1563#endif
1564 .vidioc_reqbufs = vidioc_reqbufs,
1565 .vidioc_querybuf = vidioc_querybuf,
1566 .vidioc_qbuf = vidioc_qbuf,
1567 .vidioc_dqbuf = vidioc_dqbuf,
1568 .vidioc_s_std = vidioc_s_std,
1569 .vidioc_enum_input = vidioc_enum_input,
1570 .vidioc_g_input = vidioc_g_input,
1571 .vidioc_s_input = vidioc_s_input,
1572 .vidioc_queryctrl = vidioc_queryctrl,
1573 .vidioc_g_ctrl = vidioc_g_ctrl,
1574 .vidioc_s_ctrl = vidioc_s_ctrl,
1575 .vidioc_streamon = vidioc_streamon,
1576 .vidioc_streamoff = vidioc_streamoff,
1577 .vidioc_g_tuner = vidioc_g_tuner,
1578 .vidioc_s_tuner = vidioc_s_tuner,
1579 .vidioc_g_frequency = vidioc_g_frequency,
1580 .vidioc_s_frequency = vidioc_s_frequency,
1581#ifdef CONFIG_VIDEO_ADV_DEBUG
1582 .vidioc_g_register = vidioc_g_register,
1583 .vidioc_s_register = vidioc_s_register,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001584#endif
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001585 .vidioc_g_chip_ident = vidioc_g_chip_ident,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001586#ifdef CONFIG_VIDEO_V4L1_COMPAT
1587 .vidiocgmbuf = vidiocgmbuf,
1588#endif
1589};
1590
1591static const struct video_device au0828_video_template = {
1592 .fops = &au0828_v4l_fops,
1593 .release = video_device_release,
1594 .ioctl_ops = &video_ioctl_ops,
1595 .minor = -1,
Devin Heitmueller0ef210712009-03-11 03:00:53 -03001596 .tvnorms = V4L2_STD_NTSC_M,
1597 .current_norm = V4L2_STD_NTSC_M,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001598};
1599
1600/**************************************************************************/
1601
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001602int au0828_analog_register(struct au0828_dev *dev,
1603 struct usb_interface *interface)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001604{
1605 int retval = -ENOMEM;
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001606 struct usb_host_interface *iface_desc;
1607 struct usb_endpoint_descriptor *endpoint;
1608 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001609
1610 dprintk(1, "au0828_analog_register called!\n");
1611
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001612 /* set au0828 usb interface0 to as5 */
1613 retval = usb_set_interface(dev->usbdev,
Devin Heitmueller62899a22009-03-15 18:48:52 -03001614 interface->cur_altsetting->desc.bInterfaceNumber, 5);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001615 if (retval != 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001616 printk(KERN_INFO "Failure setting usb interface0 to as5\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001617 return retval;
1618 }
1619
1620 /* Figure out which endpoint has the isoc interface */
1621 iface_desc = interface->cur_altsetting;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001622 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001623 endpoint = &iface_desc->endpoint[i].desc;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001624 if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1625 == USB_DIR_IN) &&
1626 ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1627 == USB_ENDPOINT_XFER_ISOC)) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001628
1629 /* we find our isoc in endpoint */
1630 u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001631 dev->max_pkt_size = (tmp & 0x07ff) *
1632 (((tmp & 0x1800) >> 11) + 1);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001633 dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
1634 }
1635 }
Devin Heitmueller62899a22009-03-15 18:48:52 -03001636 if (!(dev->isoc_in_endpointaddr)) {
1637 printk(KERN_INFO "Could not locate isoc endpoint\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001638 kfree(dev);
1639 return -ENODEV;
1640 }
1641
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001642 init_waitqueue_head(&dev->open);
1643 spin_lock_init(&dev->slock);
1644 mutex_init(&dev->lock);
1645
1646 INIT_LIST_HEAD(&dev->vidq.active);
1647 INIT_LIST_HEAD(&dev->vidq.queued);
1648
1649 dev->width = NTSC_STD_W;
1650 dev->height = NTSC_STD_H;
1651 dev->field_size = dev->width * dev->height;
1652 dev->frame_size = dev->field_size << 1;
1653 dev->bytesperline = dev->width << 1;
1654 dev->ctrl_ainput = 0;
1655
1656 /* allocate and fill v4l2 video struct */
1657 dev->vdev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001658 if (NULL == dev->vdev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001659 dprintk(1, "Can't allocate video_device.\n");
1660 return -ENOMEM;
1661 }
1662
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001663#ifdef VBI_IS_WORKING
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001664 dev->vbi_dev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001665 if (NULL == dev->vbi_dev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001666 dprintk(1, "Can't allocate vbi_device.\n");
1667 kfree(dev->vdev);
1668 return -ENOMEM;
1669 }
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001670#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001671
1672 /* Fill the video capture device struct */
1673 *dev->vdev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001674 dev->vdev->parent = &dev->usbdev->dev;
1675 strcpy(dev->vdev->name, "au0828a video");
1676
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001677#ifdef VBI_IS_WORKING
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001678 /* Setup the VBI device */
1679 *dev->vbi_dev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001680 dev->vbi_dev->parent = &dev->usbdev->dev;
1681 strcpy(dev->vbi_dev->name, "au0828a vbi");
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001682#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001683
1684 list_add_tail(&dev->au0828list, &au0828_devlist);
1685
1686 /* Register the v4l2 device */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001687 retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1688 if (retval != 0) {
1689 dprintk(1, "unable to register video device (error = %d).\n",
1690 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001691 list_del(&dev->au0828list);
1692 video_device_release(dev->vdev);
1693 return -ENODEV;
1694 }
1695
Devin Heitmuellerdd27ade2009-03-15 18:52:10 -03001696#ifdef VBI_IS_WORKING
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001697 /* Register the vbi device */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001698 retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
1699 if (retval != 0) {
1700 dprintk(1, "unable to register vbi device (error = %d).\n",
1701 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001702 list_del(&dev->au0828list);
1703 video_device_release(dev->vbi_dev);
1704 video_device_release(dev->vdev);
1705 return -ENODEV;
1706 }
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001707#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001708
Devin Heitmueller62899a22009-03-15 18:48:52 -03001709 dprintk(1, "%s completed!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001710
1711 return 0;
1712}
1713