blob: 8d11e544c8797209e1203323f0847a893eff3ead [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]) {
Daniel Mack997ea582010-04-12 13:17:25 +0200180 usb_free_coherent(dev->usbdev,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300181 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
Daniel Mack997ea582010-04-12 13:17:25 +0200250 dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300251 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);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300315
316 /* Reset the timer for "no video condition" */
317 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300318}
319
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300320static inline void vbi_buffer_filled(struct au0828_dev *dev,
321 struct au0828_dmaqueue *dma_q,
322 struct au0828_buffer *buf)
323{
324 /* Advice that buffer was filled */
325 au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
326
327 buf->vb.state = VIDEOBUF_DONE;
328 buf->vb.field_count++;
329 do_gettimeofday(&buf->vb.ts);
330
331 dev->isoc_ctl.vbi_buf = NULL;
332
333 list_del(&buf->vb.queue);
334 wake_up(&buf->vb.done);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300335
336 /* Reset the timer for "no video condition" */
337 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300338}
339
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300340/*
341 * Identify the buffer header type and properly handles
342 */
343static void au0828_copy_video(struct au0828_dev *dev,
344 struct au0828_dmaqueue *dma_q,
345 struct au0828_buffer *buf,
346 unsigned char *p,
347 unsigned char *outp, unsigned long len)
348{
349 void *fieldstart, *startwrite, *startread;
350 int linesdone, currlinedone, offset, lencopy, remain;
351 int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */
352
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300353 if (len == 0)
354 return;
355
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300356 if (dma_q->pos + len > buf->vb.size)
357 len = buf->vb.size - dma_q->pos;
358
359 startread = p;
360 remain = len;
361
362 /* Interlaces frame */
363 if (buf->top_field)
364 fieldstart = outp;
365 else
366 fieldstart = outp + bytesperline;
367
368 linesdone = dma_q->pos / bytesperline;
369 currlinedone = dma_q->pos % bytesperline;
370 offset = linesdone * bytesperline * 2 + currlinedone;
371 startwrite = fieldstart + offset;
372 lencopy = bytesperline - currlinedone;
373 lencopy = lencopy > remain ? remain : lencopy;
374
375 if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
376 au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
377 ((char *)startwrite + lencopy) -
378 ((char *)outp + buf->vb.size));
379 remain = (char *)outp + buf->vb.size - (char *)startwrite;
380 lencopy = remain;
381 }
382 if (lencopy <= 0)
383 return;
384 memcpy(startwrite, startread, lencopy);
385
386 remain -= lencopy;
387
388 while (remain > 0) {
389 startwrite += lencopy + bytesperline;
390 startread += lencopy;
391 if (bytesperline > remain)
392 lencopy = remain;
393 else
394 lencopy = bytesperline;
395
396 if ((char *)startwrite + lencopy > (char *)outp +
397 buf->vb.size) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300398 au0828_isocdbg("Overflow %zi bytes past buf end (2)\n",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300399 ((char *)startwrite + lencopy) -
400 ((char *)outp + buf->vb.size));
401 lencopy = remain = (char *)outp + buf->vb.size -
402 (char *)startwrite;
403 }
404 if (lencopy <= 0)
405 break;
406
407 memcpy(startwrite, startread, lencopy);
408
409 remain -= lencopy;
410 }
411
412 if (offset > 1440) {
413 /* We have enough data to check for greenscreen */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300414 if (outp[0] < 0x60 && outp[1440] < 0x60)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300415 dev->greenscreen_detected = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300416 }
417
418 dma_q->pos += len;
419}
420
421/*
422 * video-buf generic routine to get the next available buffer
423 */
424static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
425 struct au0828_buffer **buf)
426{
427 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
428
429 if (list_empty(&dma_q->active)) {
430 au0828_isocdbg("No active queue to serve\n");
431 dev->isoc_ctl.buf = NULL;
432 *buf = NULL;
433 return;
434 }
435
436 /* Get the next buffer */
437 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
438 dev->isoc_ctl.buf = *buf;
439
440 return;
441}
442
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300443static void au0828_copy_vbi(struct au0828_dev *dev,
444 struct au0828_dmaqueue *dma_q,
445 struct au0828_buffer *buf,
446 unsigned char *p,
447 unsigned char *outp, unsigned long len)
448{
449 unsigned char *startwrite, *startread;
Dan Carpenterb5f59332010-07-23 07:09:20 -0300450 int bytesperline;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300451 int i, j = 0;
452
453 if (dev == NULL) {
454 au0828_isocdbg("dev is null\n");
455 return;
456 }
457
458 if (dma_q == NULL) {
459 au0828_isocdbg("dma_q is null\n");
460 return;
461 }
462 if (buf == NULL)
463 return;
464 if (p == NULL) {
465 au0828_isocdbg("p is null\n");
466 return;
467 }
468 if (outp == NULL) {
469 au0828_isocdbg("outp is null\n");
470 return;
471 }
472
Dan Carpenterb5f59332010-07-23 07:09:20 -0300473 bytesperline = dev->vbi_width;
474
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300475 if (dma_q->pos + len > buf->vb.size)
476 len = buf->vb.size - dma_q->pos;
477
478 startread = p;
479 startwrite = outp + (dma_q->pos / 2);
480
481 /* Make sure the bottom field populates the second half of the frame */
482 if (buf->top_field == 0)
483 startwrite += bytesperline * dev->vbi_height;
484
485 for (i = 0; i < len; i += 2)
486 startwrite[j++] = startread[i+1];
487
488 dma_q->pos += len;
489}
490
491
492/*
493 * video-buf generic routine to get the next available VBI buffer
494 */
495static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q,
496 struct au0828_buffer **buf)
497{
498 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq);
499 char *outp;
500
501 if (list_empty(&dma_q->active)) {
502 au0828_isocdbg("No active queue to serve\n");
503 dev->isoc_ctl.vbi_buf = NULL;
504 *buf = NULL;
505 return;
506 }
507
508 /* Get the next buffer */
509 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
510 /* Cleans up buffer - Usefull for testing for frame/URB loss */
511 outp = videobuf_to_vmalloc(&(*buf)->vb);
512 memset(outp, 0x00, (*buf)->vb.size);
513
514 dev->isoc_ctl.vbi_buf = *buf;
515
516 return;
517}
518
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300519/*
520 * Controls the isoc copy of each urb packet
521 */
522static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
523{
524 struct au0828_buffer *buf;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300525 struct au0828_buffer *vbi_buf;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300526 struct au0828_dmaqueue *dma_q = urb->context;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300527 struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300528 unsigned char *outp = NULL;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300529 unsigned char *vbioutp = NULL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300530 int i, len = 0, rc = 1;
531 unsigned char *p;
532 unsigned char fbyte;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300533 unsigned int vbi_field_size;
534 unsigned int remain, lencopy;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300535
536 if (!dev)
537 return 0;
538
539 if ((dev->dev_state & DEV_DISCONNECTED) ||
540 (dev->dev_state & DEV_MISCONFIGURED))
541 return 0;
542
543 if (urb->status < 0) {
544 print_err_status(dev, -1, urb->status);
545 if (urb->status == -ENOENT)
546 return 0;
547 }
548
549 buf = dev->isoc_ctl.buf;
550 if (buf != NULL)
551 outp = videobuf_to_vmalloc(&buf->vb);
552
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300553 vbi_buf = dev->isoc_ctl.vbi_buf;
554 if (vbi_buf != NULL)
555 vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
556
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300557 for (i = 0; i < urb->number_of_packets; i++) {
558 int status = urb->iso_frame_desc[i].status;
559
560 if (status < 0) {
561 print_err_status(dev, i, status);
562 if (urb->iso_frame_desc[i].status != -EPROTO)
563 continue;
564 }
565
Devin Heitmueller62899a22009-03-15 18:48:52 -0300566 if (urb->iso_frame_desc[i].actual_length <= 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300567 continue;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300568
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300569 if (urb->iso_frame_desc[i].actual_length >
570 dev->max_pkt_size) {
571 au0828_isocdbg("packet bigger than packet size");
572 continue;
573 }
574
575 p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
576 fbyte = p[0];
577 len = urb->iso_frame_desc[i].actual_length - 4;
578 p += 4;
579
580 if (fbyte & 0x80) {
581 len -= 4;
582 p += 4;
583 au0828_isocdbg("Video frame %s\n",
584 (fbyte & 0x40) ? "odd" : "even");
Devin Heitmuellerbde3bb92010-07-05 13:05:16 -0300585 if (fbyte & 0x40) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300586 /* VBI */
587 if (vbi_buf != NULL)
588 vbi_buffer_filled(dev,
589 vbi_dma_q,
590 vbi_buf);
591 vbi_get_next_buf(vbi_dma_q, &vbi_buf);
592 if (vbi_buf == NULL)
593 vbioutp = NULL;
594 else
595 vbioutp = videobuf_to_vmalloc(
596 &vbi_buf->vb);
597
598 /* Video */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300599 if (buf != NULL)
600 buffer_filled(dev, dma_q, buf);
601 get_next_buf(dma_q, &buf);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300602 if (buf == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300603 outp = NULL;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300604 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300605 outp = videobuf_to_vmalloc(&buf->vb);
606 }
607
608 if (buf != NULL) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300609 if (fbyte & 0x40)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300610 buf->top_field = 1;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300611 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300612 buf->top_field = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300613 }
614
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300615 if (vbi_buf != NULL) {
616 if (fbyte & 0x40)
617 vbi_buf->top_field = 1;
618 else
619 vbi_buf->top_field = 0;
620 }
621
622 dev->vbi_read = 0;
623 vbi_dma_q->pos = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300624 dma_q->pos = 0;
625 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300626
627 vbi_field_size = dev->vbi_width * dev->vbi_height * 2;
628 if (dev->vbi_read < vbi_field_size) {
629 remain = vbi_field_size - dev->vbi_read;
630 if (len < remain)
631 lencopy = len;
632 else
633 lencopy = remain;
634
635 if (vbi_buf != NULL)
636 au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
637 vbioutp, len);
638
639 len -= lencopy;
640 p += lencopy;
641 dev->vbi_read += lencopy;
642 }
643
644 if (dev->vbi_read >= vbi_field_size && buf != NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300645 au0828_copy_video(dev, dma_q, buf, p, outp, len);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300646 }
647 return rc;
648}
649
650static int
651buffer_setup(struct videobuf_queue *vq, unsigned int *count,
652 unsigned int *size)
653{
654 struct au0828_fh *fh = vq->priv_data;
655 *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
656
657 if (0 == *count)
658 *count = AU0828_DEF_BUF;
659
660 if (*count < AU0828_MIN_BUF)
661 *count = AU0828_MIN_BUF;
662 return 0;
663}
664
665/* This is called *without* dev->slock held; please keep it that way */
666static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
667{
668 struct au0828_fh *fh = vq->priv_data;
669 struct au0828_dev *dev = fh->dev;
670 unsigned long flags = 0;
671 if (in_interrupt())
672 BUG();
673
674 /* We used to wait for the buffer to finish here, but this didn't work
675 because, as we were keeping the state as VIDEOBUF_QUEUED,
676 videobuf_queue_cancel marked it as finished for us.
677 (Also, it could wedge forever if the hardware was misconfigured.)
678
679 This should be safe; by the time we get here, the buffer isn't
680 queued anymore. If we ever start marking the buffers as
681 VIDEOBUF_ACTIVE, it won't be, though.
682 */
683 spin_lock_irqsave(&dev->slock, flags);
684 if (dev->isoc_ctl.buf == buf)
685 dev->isoc_ctl.buf = NULL;
686 spin_unlock_irqrestore(&dev->slock, flags);
687
688 videobuf_vmalloc_free(&buf->vb);
689 buf->vb.state = VIDEOBUF_NEEDS_INIT;
690}
691
692static int
693buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
694 enum v4l2_field field)
695{
696 struct au0828_fh *fh = vq->priv_data;
697 struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
698 struct au0828_dev *dev = fh->dev;
699 int rc = 0, urb_init = 0;
700
701 buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
702
703 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
704 return -EINVAL;
705
706 buf->vb.width = dev->width;
707 buf->vb.height = dev->height;
708 buf->vb.field = field;
709
710 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
711 rc = videobuf_iolock(vq, &buf->vb, NULL);
712 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300713 printk(KERN_INFO "videobuf_iolock failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300714 goto fail;
715 }
716 }
717
718 if (!dev->isoc_ctl.num_bufs)
719 urb_init = 1;
720
721 if (urb_init) {
722 rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,
723 AU0828_MAX_ISO_BUFS, dev->max_pkt_size,
724 au0828_isoc_copy);
725 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300726 printk(KERN_INFO "au0828_init_isoc failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300727 goto fail;
728 }
729 }
730
731 buf->vb.state = VIDEOBUF_PREPARED;
732 return 0;
733
734fail:
735 free_buffer(vq, buf);
736 return rc;
737}
738
739static void
740buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
741{
742 struct au0828_buffer *buf = container_of(vb,
743 struct au0828_buffer,
744 vb);
745 struct au0828_fh *fh = vq->priv_data;
746 struct au0828_dev *dev = fh->dev;
747 struct au0828_dmaqueue *vidq = &dev->vidq;
748
749 buf->vb.state = VIDEOBUF_QUEUED;
750 list_add_tail(&buf->vb.queue, &vidq->active);
751}
752
753static void buffer_release(struct videobuf_queue *vq,
754 struct videobuf_buffer *vb)
755{
756 struct au0828_buffer *buf = container_of(vb,
757 struct au0828_buffer,
758 vb);
759
760 free_buffer(vq, buf);
761}
762
763static struct videobuf_queue_ops au0828_video_qops = {
764 .buf_setup = buffer_setup,
765 .buf_prepare = buffer_prepare,
766 .buf_queue = buffer_queue,
767 .buf_release = buffer_release,
768};
769
770/* ------------------------------------------------------------------
771 V4L2 interface
772 ------------------------------------------------------------------*/
773
774static int au0828_i2s_init(struct au0828_dev *dev)
775{
776 /* Enable i2s mode */
777 au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);
778 return 0;
779}
780
781/*
782 * Auvitek au0828 analog stream enable
783 * Please set interface0 to AS5 before enable the stream
784 */
785int au0828_analog_stream_enable(struct au0828_dev *d)
786{
787 dprintk(1, "au0828_analog_stream_enable called\n");
788 au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
789 au0828_writereg(d, 0x106, 0x00);
790 /* set x position */
791 au0828_writereg(d, 0x110, 0x00);
792 au0828_writereg(d, 0x111, 0x00);
793 au0828_writereg(d, 0x114, 0xa0);
794 au0828_writereg(d, 0x115, 0x05);
795 /* set y position */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300796 au0828_writereg(d, 0x112, 0x00);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300797 au0828_writereg(d, 0x113, 0x00);
798 au0828_writereg(d, 0x116, 0xf2);
799 au0828_writereg(d, 0x117, 0x00);
800 au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
801
802 return 0;
803}
804
805int au0828_analog_stream_disable(struct au0828_dev *d)
806{
807 dprintk(1, "au0828_analog_stream_disable called\n");
808 au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
809 return 0;
810}
811
812void au0828_analog_stream_reset(struct au0828_dev *dev)
813{
814 dprintk(1, "au0828_analog_stream_reset called\n");
815 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
816 mdelay(30);
817 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);
818}
819
820/*
821 * Some operations needs to stop current streaming
822 */
823static int au0828_stream_interrupt(struct au0828_dev *dev)
824{
825 int ret = 0;
826
827 dev->stream_state = STREAM_INTERRUPT;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300828 if (dev->dev_state == DEV_DISCONNECTED)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300829 return -ENODEV;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300830 else if (ret) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300831 dev->dev_state = DEV_MISCONFIGURED;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300832 dprintk(1, "%s device is misconfigured!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300833 return ret;
834 }
835 return 0;
836}
837
838/*
839 * au0828_release_resources
840 * unregister v4l2 devices
841 */
842void au0828_analog_unregister(struct au0828_dev *dev)
843{
844 dprintk(1, "au0828_release_resources called\n");
845 mutex_lock(&au0828_sysfs_lock);
846
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200847 if (dev->vdev)
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300848 video_unregister_device(dev->vdev);
849 if (dev->vbi_dev)
850 video_unregister_device(dev->vbi_dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300851
852 mutex_unlock(&au0828_sysfs_lock);
853}
854
855
856/* Usage lock check functions */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300857static int res_get(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300858{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300859 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300860
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300861 if (fh->resources & bit)
862 /* have it already allocated */
863 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300864
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300865 /* is it free? */
866 mutex_lock(&dev->lock);
867 if (dev->resources & bit) {
868 /* no, someone else uses it */
869 mutex_unlock(&dev->lock);
870 return 0;
871 }
872 /* it's free, grab it */
873 fh->resources |= bit;
874 dev->resources |= bit;
875 dprintk(1, "res: get %d\n", bit);
876 mutex_unlock(&dev->lock);
877 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300878}
879
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300880static int res_check(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300881{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300882 return fh->resources & bit;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300883}
884
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300885static int res_locked(struct au0828_dev *dev, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300886{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300887 return dev->resources & bit;
888}
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300889
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300890static void res_free(struct au0828_fh *fh, unsigned int bits)
891{
892 struct au0828_dev *dev = fh->dev;
893
894 BUG_ON((fh->resources & bits) != bits);
895
896 mutex_lock(&dev->lock);
897 fh->resources &= ~bits;
898 dev->resources &= ~bits;
899 dprintk(1, "res: put %d\n", bits);
900 mutex_unlock(&dev->lock);
901}
902
903static int get_ressource(struct au0828_fh *fh)
904{
905 switch (fh->type) {
906 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
907 return AU0828_RESOURCE_VIDEO;
908 case V4L2_BUF_TYPE_VBI_CAPTURE:
909 return AU0828_RESOURCE_VBI;
910 default:
911 BUG();
912 return 0;
913 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300914}
915
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300916/* This function ensures that video frames continue to be delivered even if
917 the ITU-656 input isn't receiving any data (thereby preventing applications
918 such as tvtime from hanging) */
919void au0828_vid_buffer_timeout(unsigned long data)
920{
921 struct au0828_dev *dev = (struct au0828_dev *) data;
922 struct au0828_dmaqueue *dma_q = &dev->vidq;
923 struct au0828_buffer *buf;
924 unsigned char *vid_data;
925
926 spin_lock(&dev->slock);
927
928 buf = dev->isoc_ctl.buf;
929 if (buf != NULL) {
930 vid_data = videobuf_to_vmalloc(&buf->vb);
931 memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */
932 buffer_filled(dev, dma_q, buf);
933 get_next_buf(dma_q, &buf);
934 }
935
936 spin_unlock(&dev->slock);
937}
938
939void au0828_vbi_buffer_timeout(unsigned long data)
940{
941 struct au0828_dev *dev = (struct au0828_dev *) data;
942 struct au0828_dmaqueue *dma_q = &dev->vbiq;
943 struct au0828_buffer *buf;
944 unsigned char *vbi_data;
945
946 spin_lock(&dev->slock);
947
948 buf = dev->isoc_ctl.vbi_buf;
949 if (buf != NULL) {
950 vbi_data = videobuf_to_vmalloc(&buf->vb);
951 memset(vbi_data, 0x00, buf->vb.size);
952 vbi_buffer_filled(dev, dma_q, buf);
953 vbi_get_next_buf(dma_q, &buf);
954 }
955
956 spin_unlock(&dev->slock);
957}
958
959
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300960static int au0828_v4l2_open(struct file *filp)
961{
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300962 int ret = 0;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300963 struct video_device *vdev = video_devdata(filp);
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200964 struct au0828_dev *dev = video_drvdata(filp);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300965 struct au0828_fh *fh;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300966 int type;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300967
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300968 switch (vdev->vfl_type) {
969 case VFL_TYPE_GRABBER:
970 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
971 break;
972 case VFL_TYPE_VBI:
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200973 type = V4L2_BUF_TYPE_VBI_CAPTURE;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300974 break;
975 default:
976 return -EINVAL;
977 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300978
979 fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300980 if (NULL == fh) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300981 dprintk(1, "Failed allocate au0828_fh struct!\n");
982 return -ENOMEM;
983 }
984
985 fh->type = type;
986 fh->dev = dev;
987 filp->private_data = fh;
988
Devin Heitmueller62899a22009-03-15 18:48:52 -0300989 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300990 /* set au0828 interface0 to AS5 here again */
991 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300992 if (ret < 0) {
993 printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300994 return -EBUSY;
995 }
996 dev->width = NTSC_STD_W;
997 dev->height = NTSC_STD_H;
998 dev->frame_size = dev->width * dev->height * 2;
999 dev->field_size = dev->width * dev->height;
1000 dev->bytesperline = dev->width * 2;
1001
1002 au0828_analog_stream_enable(dev);
1003 au0828_analog_stream_reset(dev);
1004
1005 /* If we were doing ac97 instead of i2s, it would go here...*/
1006 au0828_i2s_init(dev);
1007
1008 dev->stream_state = STREAM_OFF;
1009 dev->dev_state |= DEV_INITIALIZED;
1010 }
1011
1012 dev->users++;
1013
1014 videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001015 NULL, &dev->slock,
1016 V4L2_BUF_TYPE_VIDEO_CAPTURE,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001017 V4L2_FIELD_INTERLACED,
Hans Verkuil08bff032010-09-20 17:39:46 -03001018 sizeof(struct au0828_buffer), fh, NULL);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001019
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001020 /* VBI Setup */
1021 dev->vbi_width = 720;
1022 dev->vbi_height = 1;
1023 videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops,
1024 NULL, &dev->slock,
1025 V4L2_BUF_TYPE_VBI_CAPTURE,
1026 V4L2_FIELD_SEQ_TB,
Hans Verkuil08bff032010-09-20 17:39:46 -03001027 sizeof(struct au0828_buffer), fh, NULL);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001028
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -03001029 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1030 dev->vid_timeout.function = au0828_vid_buffer_timeout;
1031 dev->vid_timeout.data = (unsigned long) dev;
1032 init_timer(&dev->vid_timeout);
1033 } else {
1034 dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
1035 dev->vbi_timeout.data = (unsigned long) dev;
1036 init_timer(&dev->vbi_timeout);
1037 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001038
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001039 return ret;
1040}
1041
1042static int au0828_v4l2_close(struct file *filp)
1043{
1044 int ret;
1045 struct au0828_fh *fh = filp->private_data;
1046 struct au0828_dev *dev = fh->dev;
1047
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001048 if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -03001049 del_timer(&dev->vid_timeout);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001050 videobuf_stop(&fh->vb_vidq);
1051 res_free(fh, AU0828_RESOURCE_VIDEO);
1052 }
1053
1054 if (res_check(fh, AU0828_RESOURCE_VBI)) {
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -03001055 del_timer(&dev->vbi_timeout);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001056 videobuf_stop(&fh->vb_vbiq);
1057 res_free(fh, AU0828_RESOURCE_VBI);
1058 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001059
Devin Heitmueller62899a22009-03-15 18:48:52 -03001060 if (dev->users == 1) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001061 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001062 au0828_analog_unregister(dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001063 kfree(dev);
1064 return 0;
1065 }
1066
1067 au0828_analog_stream_disable(dev);
1068
1069 au0828_uninit_isoc(dev);
1070
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001071 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -03001072 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001073
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001074 /* When close the device, set the usb intf0 into alt0 to free
1075 USB bandwidth */
1076 ret = usb_set_interface(dev->usbdev, 0, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001077 if (ret < 0)
1078 printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001079 }
1080
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001081 videobuf_mmap_free(&fh->vb_vidq);
1082 videobuf_mmap_free(&fh->vb_vbiq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001083 kfree(fh);
1084 dev->users--;
1085 wake_up_interruptible_nr(&dev->open, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001086 return 0;
1087}
1088
1089static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
1090 size_t count, loff_t *pos)
1091{
1092 struct au0828_fh *fh = filp->private_data;
1093 struct au0828_dev *dev = fh->dev;
1094 int rc;
1095
1096 rc = check_dev(dev);
1097 if (rc < 0)
1098 return rc;
1099
Devin Heitmueller62899a22009-03-15 18:48:52 -03001100 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001101 if (res_locked(dev, AU0828_RESOURCE_VIDEO))
1102 return -EBUSY;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001103
1104 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
1105 filp->f_flags & O_NONBLOCK);
1106 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001107
1108 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1109 if (!res_get(fh, AU0828_RESOURCE_VBI))
1110 return -EBUSY;
1111
1112 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
1113 filp->f_flags & O_NONBLOCK);
1114 }
1115
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001116 return 0;
1117}
1118
1119static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
1120{
1121 struct au0828_fh *fh = filp->private_data;
1122 struct au0828_dev *dev = fh->dev;
1123 int rc;
1124
1125 rc = check_dev(dev);
1126 if (rc < 0)
1127 return rc;
1128
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001129 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1130 if (!res_get(fh, AU0828_RESOURCE_VIDEO))
1131 return POLLERR;
1132 return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
1133 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1134 if (!res_get(fh, AU0828_RESOURCE_VBI))
1135 return POLLERR;
1136 return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
1137 } else {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001138 return POLLERR;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001139 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001140}
1141
1142static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
1143{
1144 struct au0828_fh *fh = filp->private_data;
1145 struct au0828_dev *dev = fh->dev;
1146 int rc;
1147
1148 rc = check_dev(dev);
1149 if (rc < 0)
1150 return rc;
1151
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001152 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1153 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
1154 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1155 rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001156
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001157 return rc;
1158}
1159
1160static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
1161 struct v4l2_format *format)
1162{
1163 int ret;
1164 int width = format->fmt.pix.width;
1165 int height = format->fmt.pix.height;
1166 unsigned int maxwidth, maxheight;
1167
1168 maxwidth = 720;
1169 maxheight = 480;
1170
Devin Heitmueller62899a22009-03-15 18:48:52 -03001171 if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001172 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001173
1174 /* If they are demanding a format other than the one we support,
1175 bail out (tvtime asks for UYVY and then retries with YUYV) */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001176 if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001177 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001178
1179 /* format->fmt.pix.width only support 720 and height 480 */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001180 if (width != 720)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001181 width = 720;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001182 if (height != 480)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001183 height = 480;
1184
1185 format->fmt.pix.width = width;
1186 format->fmt.pix.height = height;
1187 format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1188 format->fmt.pix.bytesperline = width * 2;
1189 format->fmt.pix.sizeimage = width * height * 2;
1190 format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1191 format->fmt.pix.field = V4L2_FIELD_INTERLACED;
1192
Devin Heitmueller62899a22009-03-15 18:48:52 -03001193 if (cmd == VIDIOC_TRY_FMT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001194 return 0;
1195
1196 /* maybe set new image format, driver current only support 720*480 */
1197 dev->width = width;
1198 dev->height = height;
1199 dev->frame_size = width * height * 2;
1200 dev->field_size = width * height;
1201 dev->bytesperline = width * 2;
1202
Devin Heitmueller62899a22009-03-15 18:48:52 -03001203 if (dev->stream_state == STREAM_ON) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001204 dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
Devin Heitmueller62899a22009-03-15 18:48:52 -03001205 ret = au0828_stream_interrupt(dev);
1206 if (ret != 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001207 dprintk(1, "error interrupting video stream!\n");
1208 return ret;
1209 }
1210 }
1211
1212 /* set au0828 interface0 to AS5 here again */
1213 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001214 if (ret < 0) {
1215 printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001216 return -EBUSY;
1217 }
1218
1219 au0828_analog_stream_enable(dev);
1220
1221 return 0;
1222}
1223
1224
1225static int vidioc_queryctrl(struct file *file, void *priv,
1226 struct v4l2_queryctrl *qc)
1227{
1228 struct au0828_fh *fh = priv;
1229 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001230 v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001231 if (qc->type)
1232 return 0;
1233 else
1234 return -EINVAL;
1235}
1236
1237static int vidioc_querycap(struct file *file, void *priv,
1238 struct v4l2_capability *cap)
1239{
1240 struct au0828_fh *fh = priv;
1241 struct au0828_dev *dev = fh->dev;
1242
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001243 strlcpy(cap->driver, "au0828", sizeof(cap->driver));
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001244 strlcpy(cap->card, dev->board.name, sizeof(cap->card));
Devin Heitmuellerb14667f2009-03-11 03:01:04 -03001245 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001246
1247 cap->version = AU0828_VERSION_CODE;
1248
1249 /*set the device capabilities */
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001250 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001251 V4L2_CAP_VBI_CAPTURE |
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001252 V4L2_CAP_AUDIO |
1253 V4L2_CAP_READWRITE |
1254 V4L2_CAP_STREAMING |
1255 V4L2_CAP_TUNER;
1256 return 0;
1257}
1258
1259static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1260 struct v4l2_fmtdesc *f)
1261{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001262 if (f->index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001263 return -EINVAL;
1264
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001265 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1266 strcpy(f->description, "Packed YUV2");
1267
1268 f->flags = 0;
1269 f->pixelformat = V4L2_PIX_FMT_UYVY;
1270
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001271 return 0;
1272}
1273
1274static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1275 struct v4l2_format *f)
1276{
1277 struct au0828_fh *fh = priv;
1278 struct au0828_dev *dev = fh->dev;
1279
1280 f->fmt.pix.width = dev->width;
1281 f->fmt.pix.height = dev->height;
1282 f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1283 f->fmt.pix.bytesperline = dev->bytesperline;
1284 f->fmt.pix.sizeimage = dev->frame_size;
1285 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
1286 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1287 return 0;
1288}
1289
1290static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1291 struct v4l2_format *f)
1292{
1293 struct au0828_fh *fh = priv;
1294 struct au0828_dev *dev = fh->dev;
1295
1296 return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
1297}
1298
1299static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1300 struct v4l2_format *f)
1301{
1302 struct au0828_fh *fh = priv;
1303 struct au0828_dev *dev = fh->dev;
1304 int rc;
1305
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001306 rc = check_dev(dev);
1307 if (rc < 0)
1308 return rc;
1309
1310 mutex_lock(&dev->lock);
1311
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001312 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001313 printk(KERN_INFO "%s queue busy\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001314 rc = -EBUSY;
1315 goto out;
1316 }
1317
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001318 rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001319out:
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001320 mutex_unlock(&dev->lock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001321 return rc;
1322}
1323
1324static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
1325{
1326 struct au0828_fh *fh = priv;
1327 struct au0828_dev *dev = fh->dev;
1328
1329 /* FIXME: when we support something other than NTSC, we are going to
1330 have to make the au0828 bridge adjust the size of its capture
1331 buffer, which is currently hardcoded at 720x480 */
1332
Hans Verkuilf41737e2009-04-01 03:52:39 -03001333 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001334 return 0;
1335}
1336
1337static int vidioc_enum_input(struct file *file, void *priv,
1338 struct v4l2_input *input)
1339{
1340 struct au0828_fh *fh = priv;
1341 struct au0828_dev *dev = fh->dev;
1342 unsigned int tmp;
1343
1344 static const char *inames[] = {
Devin Heitmueller3d622872009-03-15 17:48:26 -03001345 [AU0828_VMUX_UNDEFINED] = "Undefined",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001346 [AU0828_VMUX_COMPOSITE] = "Composite",
1347 [AU0828_VMUX_SVIDEO] = "S-Video",
1348 [AU0828_VMUX_CABLE] = "Cable TV",
1349 [AU0828_VMUX_TELEVISION] = "Television",
1350 [AU0828_VMUX_DVB] = "DVB",
1351 [AU0828_VMUX_DEBUG] = "tv debug"
1352 };
1353
1354 tmp = input->index;
1355
Dan Carpenterf5e20c32010-03-28 08:21:18 -03001356 if (tmp >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001357 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001358 if (AUVI_INPUT(tmp).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001359 return -EINVAL;
1360
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001361 input->index = tmp;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001362 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001363 if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
1364 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001365 input->type |= V4L2_INPUT_TYPE_TUNER;
1366 else
1367 input->type |= V4L2_INPUT_TYPE_CAMERA;
1368
1369 input->std = dev->vdev->tvnorms;
1370
1371 return 0;
1372}
1373
1374static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1375{
1376 struct au0828_fh *fh = priv;
1377 struct au0828_dev *dev = fh->dev;
1378 *i = dev->ctrl_input;
1379 return 0;
1380}
1381
1382static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1383{
1384 struct au0828_fh *fh = priv;
1385 struct au0828_dev *dev = fh->dev;
1386 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001387
Devin Heitmueller62899a22009-03-15 18:48:52 -03001388 dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001389 index);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001390 if (index >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001391 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001392 if (AUVI_INPUT(index).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001393 return -EINVAL;
1394 dev->ctrl_input = index;
1395
Devin Heitmueller62899a22009-03-15 18:48:52 -03001396 switch (AUVI_INPUT(index).type) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001397 case AU0828_VMUX_SVIDEO:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001398 dev->input_type = AU0828_VMUX_SVIDEO;
1399 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001400 case AU0828_VMUX_COMPOSITE:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001401 dev->input_type = AU0828_VMUX_COMPOSITE;
1402 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001403 case AU0828_VMUX_TELEVISION:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001404 dev->input_type = AU0828_VMUX_TELEVISION;
1405 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001406 default:
Devin Heitmuellera1094c42009-03-15 17:43:13 -03001407 dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
1408 AUVI_INPUT(index).type);
1409 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001410 }
1411
Hans Verkuil5325b422009-04-02 11:26:22 -03001412 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1413 AUVI_INPUT(index).vmux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001414
1415 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1416 int enable = 0;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001417 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001418 continue;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001419
1420 if (i == index)
1421 enable = 1;
1422 else
1423 enable = 0;
1424 if (enable) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001425 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001426 } else {
1427 /* Make sure we leave it turned on if some
1428 other input is routed to this callback */
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001429 if ((AUVI_INPUT(i).audio_setup) !=
1430 ((AUVI_INPUT(index).audio_setup))) {
1431 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001432 }
1433 }
1434 }
1435
Hans Verkuil5325b422009-04-02 11:26:22 -03001436 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1437 AUVI_INPUT(index).amux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001438 return 0;
1439}
1440
1441static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1442{
1443 struct au0828_fh *fh = priv;
1444 struct au0828_dev *dev = fh->dev;
1445 unsigned int index = a->index;
1446
Devin Heitmueller62899a22009-03-15 18:48:52 -03001447 if (a->index > 1)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001448 return -EINVAL;
1449
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001450 index = dev->ctrl_ainput;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001451 if (index == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001452 strcpy(a->name, "Television");
1453 else
1454 strcpy(a->name, "Line in");
1455
1456 a->capability = V4L2_AUDCAP_STEREO;
1457 a->index = index;
1458 return 0;
1459}
1460
1461static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
1462{
1463 struct au0828_fh *fh = priv;
1464 struct au0828_dev *dev = fh->dev;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001465 if (a->index != dev->ctrl_ainput)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001466 return -EINVAL;
1467 return 0;
1468}
1469
1470static int vidioc_g_ctrl(struct file *file, void *priv,
1471 struct v4l2_control *ctrl)
1472{
1473 struct au0828_fh *fh = priv;
1474 struct au0828_dev *dev = fh->dev;
1475
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001476 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001477 return 0;
1478
1479}
1480
1481static int vidioc_s_ctrl(struct file *file, void *priv,
1482 struct v4l2_control *ctrl)
1483{
1484 struct au0828_fh *fh = priv;
1485 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001486 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001487 return 0;
1488}
1489
1490static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
1491{
1492 struct au0828_fh *fh = priv;
1493 struct au0828_dev *dev = fh->dev;
1494
Devin Heitmueller62899a22009-03-15 18:48:52 -03001495 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001496 return -EINVAL;
1497
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001498 strcpy(t->name, "Auvitek tuner");
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001499 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001500 return 0;
1501}
1502
1503static int vidioc_s_tuner(struct file *file, void *priv,
1504 struct v4l2_tuner *t)
1505{
1506 struct au0828_fh *fh = priv;
1507 struct au0828_dev *dev = fh->dev;
1508
Devin Heitmueller62899a22009-03-15 18:48:52 -03001509 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001510 return -EINVAL;
1511
1512 t->type = V4L2_TUNER_ANALOG_TV;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001513 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001514 dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
1515 t->afc);
1516 return 0;
1517
1518}
1519
1520static int vidioc_g_frequency(struct file *file, void *priv,
1521 struct v4l2_frequency *freq)
1522{
1523 struct au0828_fh *fh = priv;
1524 struct au0828_dev *dev = fh->dev;
Devin Heitmuellerc8889232009-03-15 17:38:47 -03001525
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001526 freq->type = V4L2_TUNER_ANALOG_TV;
1527 freq->frequency = dev->ctrl_freq;
1528 return 0;
1529}
1530
1531static int vidioc_s_frequency(struct file *file, void *priv,
1532 struct v4l2_frequency *freq)
1533{
1534 struct au0828_fh *fh = priv;
1535 struct au0828_dev *dev = fh->dev;
1536
Devin Heitmueller62899a22009-03-15 18:48:52 -03001537 if (freq->tuner != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001538 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001539 if (freq->type != V4L2_TUNER_ANALOG_TV)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001540 return -EINVAL;
1541
1542 dev->ctrl_freq = freq->frequency;
1543
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001544 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001545
1546 au0828_analog_stream_reset(dev);
1547
1548 return 0;
1549}
1550
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001551
1552/* RAW VBI ioctls */
1553
1554static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1555 struct v4l2_format *format)
1556{
1557 struct au0828_fh *fh = priv;
1558 struct au0828_dev *dev = fh->dev;
1559
1560 format->fmt.vbi.samples_per_line = dev->vbi_width;
1561 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1562 format->fmt.vbi.offset = 0;
1563 format->fmt.vbi.flags = 0;
1564 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1565
1566 format->fmt.vbi.count[0] = dev->vbi_height;
1567 format->fmt.vbi.count[1] = dev->vbi_height;
1568 format->fmt.vbi.start[0] = 21;
1569 format->fmt.vbi.start[1] = 284;
1570
1571 return 0;
1572}
1573
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001574static int vidioc_g_chip_ident(struct file *file, void *priv,
1575 struct v4l2_dbg_chip_ident *chip)
1576{
1577 struct au0828_fh *fh = priv;
1578 struct au0828_dev *dev = fh->dev;
1579 chip->ident = V4L2_IDENT_NONE;
1580 chip->revision = 0;
1581
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001582 if (v4l2_chip_match_host(&chip->match)) {
1583 chip->ident = V4L2_IDENT_AU0828;
1584 return 0;
1585 }
1586
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001587 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001588 if (chip->ident == V4L2_IDENT_NONE)
1589 return -EINVAL;
1590
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001591 return 0;
1592}
1593
1594static int vidioc_cropcap(struct file *file, void *priv,
1595 struct v4l2_cropcap *cc)
1596{
1597 struct au0828_fh *fh = priv;
1598 struct au0828_dev *dev = fh->dev;
1599
Devin Heitmueller62899a22009-03-15 18:48:52 -03001600 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001601 return -EINVAL;
1602
1603 cc->bounds.left = 0;
1604 cc->bounds.top = 0;
1605 cc->bounds.width = dev->width;
1606 cc->bounds.height = dev->height;
1607
1608 cc->defrect = cc->bounds;
1609
1610 cc->pixelaspect.numerator = 54;
1611 cc->pixelaspect.denominator = 59;
1612
1613 return 0;
1614}
1615
1616static int vidioc_streamon(struct file *file, void *priv,
1617 enum v4l2_buf_type type)
1618{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001619 struct au0828_fh *fh = priv;
1620 struct au0828_dev *dev = fh->dev;
1621 int rc = -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001622
1623 rc = check_dev(dev);
1624 if (rc < 0)
1625 return rc;
1626
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001627 if (unlikely(type != fh->type))
1628 return -EINVAL;
1629
1630 dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
1631 fh, type, fh->resources, dev->resources);
1632
1633 if (unlikely(!res_get(fh, get_ressource(fh))))
1634 return -EBUSY;
1635
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001636 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1637 au0828_analog_stream_enable(dev);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001638 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001639 }
1640
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001641 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001642 rc = videobuf_streamon(&fh->vb_vidq);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001643 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1644 rc = videobuf_streamon(&fh->vb_vbiq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001645
1646 return rc;
1647}
1648
1649static int vidioc_streamoff(struct file *file, void *priv,
1650 enum v4l2_buf_type type)
1651{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001652 struct au0828_fh *fh = priv;
1653 struct au0828_dev *dev = fh->dev;
1654 int rc;
1655 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001656
1657 rc = check_dev(dev);
1658 if (rc < 0)
1659 return rc;
1660
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001661 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1662 fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001663 return -EINVAL;
1664 if (type != fh->type)
1665 return -EINVAL;
1666
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001667 dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
1668 fh, type, fh->resources, dev->resources);
1669
1670 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001671 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001672 rc = au0828_stream_interrupt(dev);
1673 if (rc != 0)
1674 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001675
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001676 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1677 if (AUVI_INPUT(i).audio_setup == NULL)
1678 continue;
1679 (AUVI_INPUT(i).audio_setup)(dev, 0);
1680 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001681
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001682 videobuf_streamoff(&fh->vb_vidq);
1683 res_free(fh, AU0828_RESOURCE_VIDEO);
1684 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1685 videobuf_streamoff(&fh->vb_vbiq);
1686 res_free(fh, AU0828_RESOURCE_VBI);
1687 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001688
1689 return 0;
1690}
1691
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001692#ifdef CONFIG_VIDEO_ADV_DEBUG
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001693static int vidioc_g_register(struct file *file, void *priv,
1694 struct v4l2_dbg_register *reg)
1695{
1696 struct au0828_fh *fh = priv;
1697 struct au0828_dev *dev = fh->dev;
1698
1699 switch (reg->match.type) {
1700 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001701 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001702 return 0;
1703 default:
1704 return -EINVAL;
1705 }
1706}
1707
1708static int vidioc_s_register(struct file *file, void *priv,
1709 struct v4l2_dbg_register *reg)
1710{
1711 struct au0828_fh *fh = priv;
1712 struct au0828_dev *dev = fh->dev;
1713
1714 switch (reg->match.type) {
1715 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001716 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001717 return 0;
1718 default:
1719 return -EINVAL;
1720 }
1721 return 0;
1722}
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001723#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001724
1725static int vidioc_reqbufs(struct file *file, void *priv,
1726 struct v4l2_requestbuffers *rb)
1727{
1728 struct au0828_fh *fh = priv;
1729 struct au0828_dev *dev = fh->dev;
1730 int rc;
1731
1732 rc = check_dev(dev);
1733 if (rc < 0)
1734 return rc;
1735
1736 return videobuf_reqbufs(&fh->vb_vidq, rb);
1737}
1738
1739static int vidioc_querybuf(struct file *file, void *priv,
1740 struct v4l2_buffer *b)
1741{
1742 struct au0828_fh *fh = priv;
1743 struct au0828_dev *dev = fh->dev;
1744 int rc;
1745
1746 rc = check_dev(dev);
1747 if (rc < 0)
1748 return rc;
1749
1750 return videobuf_querybuf(&fh->vb_vidq, b);
1751}
1752
1753static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1754{
1755 struct au0828_fh *fh = priv;
1756 struct au0828_dev *dev = fh->dev;
1757 int rc;
1758
1759 rc = check_dev(dev);
1760 if (rc < 0)
1761 return rc;
1762
1763 return videobuf_qbuf(&fh->vb_vidq, b);
1764}
1765
1766static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1767{
1768 struct au0828_fh *fh = priv;
1769 struct au0828_dev *dev = fh->dev;
1770 int rc;
1771
1772 rc = check_dev(dev);
1773 if (rc < 0)
1774 return rc;
1775
1776 /* Workaround for a bug in the au0828 hardware design that sometimes
1777 results in the colorspace being inverted */
1778 if (dev->greenscreen_detected == 1) {
1779 dprintk(1, "Detected green frame. Resetting stream...\n");
1780 au0828_analog_stream_reset(dev);
1781 dev->greenscreen_detected = 0;
1782 }
1783
1784 return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1785}
1786
1787#ifdef CONFIG_VIDEO_V4L1_COMPAT
1788static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
1789{
1790 struct au0828_fh *fh = priv;
1791
1792 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
1793}
1794#endif
1795
1796static struct v4l2_file_operations au0828_v4l_fops = {
1797 .owner = THIS_MODULE,
1798 .open = au0828_v4l2_open,
1799 .release = au0828_v4l2_close,
1800 .read = au0828_v4l2_read,
1801 .poll = au0828_v4l2_poll,
1802 .mmap = au0828_v4l2_mmap,
1803 .ioctl = video_ioctl2,
1804};
1805
1806static const struct v4l2_ioctl_ops video_ioctl_ops = {
1807 .vidioc_querycap = vidioc_querycap,
1808 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1809 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1810 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1811 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001812 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001813 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001814 .vidioc_g_audio = vidioc_g_audio,
1815 .vidioc_s_audio = vidioc_s_audio,
1816 .vidioc_cropcap = vidioc_cropcap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001817 .vidioc_reqbufs = vidioc_reqbufs,
1818 .vidioc_querybuf = vidioc_querybuf,
1819 .vidioc_qbuf = vidioc_qbuf,
1820 .vidioc_dqbuf = vidioc_dqbuf,
1821 .vidioc_s_std = vidioc_s_std,
1822 .vidioc_enum_input = vidioc_enum_input,
1823 .vidioc_g_input = vidioc_g_input,
1824 .vidioc_s_input = vidioc_s_input,
1825 .vidioc_queryctrl = vidioc_queryctrl,
1826 .vidioc_g_ctrl = vidioc_g_ctrl,
1827 .vidioc_s_ctrl = vidioc_s_ctrl,
1828 .vidioc_streamon = vidioc_streamon,
1829 .vidioc_streamoff = vidioc_streamoff,
1830 .vidioc_g_tuner = vidioc_g_tuner,
1831 .vidioc_s_tuner = vidioc_s_tuner,
1832 .vidioc_g_frequency = vidioc_g_frequency,
1833 .vidioc_s_frequency = vidioc_s_frequency,
1834#ifdef CONFIG_VIDEO_ADV_DEBUG
1835 .vidioc_g_register = vidioc_g_register,
1836 .vidioc_s_register = vidioc_s_register,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001837#endif
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001838 .vidioc_g_chip_ident = vidioc_g_chip_ident,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001839#ifdef CONFIG_VIDEO_V4L1_COMPAT
1840 .vidiocgmbuf = vidiocgmbuf,
1841#endif
1842};
1843
1844static const struct video_device au0828_video_template = {
1845 .fops = &au0828_v4l_fops,
1846 .release = video_device_release,
1847 .ioctl_ops = &video_ioctl_ops,
Devin Heitmueller0ef210712009-03-11 03:00:53 -03001848 .tvnorms = V4L2_STD_NTSC_M,
1849 .current_norm = V4L2_STD_NTSC_M,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001850};
1851
1852/**************************************************************************/
1853
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001854int au0828_analog_register(struct au0828_dev *dev,
1855 struct usb_interface *interface)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001856{
1857 int retval = -ENOMEM;
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001858 struct usb_host_interface *iface_desc;
1859 struct usb_endpoint_descriptor *endpoint;
1860 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001861
1862 dprintk(1, "au0828_analog_register called!\n");
1863
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001864 /* set au0828 usb interface0 to as5 */
1865 retval = usb_set_interface(dev->usbdev,
Devin Heitmueller62899a22009-03-15 18:48:52 -03001866 interface->cur_altsetting->desc.bInterfaceNumber, 5);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001867 if (retval != 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001868 printk(KERN_INFO "Failure setting usb interface0 to as5\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001869 return retval;
1870 }
1871
1872 /* Figure out which endpoint has the isoc interface */
1873 iface_desc = interface->cur_altsetting;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001874 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001875 endpoint = &iface_desc->endpoint[i].desc;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001876 if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1877 == USB_DIR_IN) &&
1878 ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1879 == USB_ENDPOINT_XFER_ISOC)) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001880
1881 /* we find our isoc in endpoint */
1882 u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001883 dev->max_pkt_size = (tmp & 0x07ff) *
1884 (((tmp & 0x1800) >> 11) + 1);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001885 dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
1886 }
1887 }
Devin Heitmueller62899a22009-03-15 18:48:52 -03001888 if (!(dev->isoc_in_endpointaddr)) {
1889 printk(KERN_INFO "Could not locate isoc endpoint\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001890 kfree(dev);
1891 return -ENODEV;
1892 }
1893
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001894 init_waitqueue_head(&dev->open);
1895 spin_lock_init(&dev->slock);
1896 mutex_init(&dev->lock);
1897
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001898 /* init video dma queues */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001899 INIT_LIST_HEAD(&dev->vidq.active);
1900 INIT_LIST_HEAD(&dev->vidq.queued);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001901 INIT_LIST_HEAD(&dev->vbiq.active);
1902 INIT_LIST_HEAD(&dev->vbiq.queued);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001903
1904 dev->width = NTSC_STD_W;
1905 dev->height = NTSC_STD_H;
1906 dev->field_size = dev->width * dev->height;
1907 dev->frame_size = dev->field_size << 1;
1908 dev->bytesperline = dev->width << 1;
1909 dev->ctrl_ainput = 0;
1910
1911 /* allocate and fill v4l2 video struct */
1912 dev->vdev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001913 if (NULL == dev->vdev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001914 dprintk(1, "Can't allocate video_device.\n");
1915 return -ENOMEM;
1916 }
1917
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001918 /* allocate the VBI struct */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001919 dev->vbi_dev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001920 if (NULL == dev->vbi_dev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001921 dprintk(1, "Can't allocate vbi_device.\n");
1922 kfree(dev->vdev);
1923 return -ENOMEM;
1924 }
1925
1926 /* Fill the video capture device struct */
1927 *dev->vdev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001928 dev->vdev->parent = &dev->usbdev->dev;
1929 strcpy(dev->vdev->name, "au0828a video");
1930
1931 /* Setup the VBI device */
1932 *dev->vbi_dev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001933 dev->vbi_dev->parent = &dev->usbdev->dev;
1934 strcpy(dev->vbi_dev->name, "au0828a vbi");
1935
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001936 /* Register the v4l2 device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001937 video_set_drvdata(dev->vdev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001938 retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1939 if (retval != 0) {
1940 dprintk(1, "unable to register video device (error = %d).\n",
1941 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001942 video_device_release(dev->vdev);
1943 return -ENODEV;
1944 }
1945
1946 /* Register the vbi device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001947 video_set_drvdata(dev->vbi_dev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001948 retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
1949 if (retval != 0) {
1950 dprintk(1, "unable to register vbi device (error = %d).\n",
1951 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001952 video_device_release(dev->vbi_dev);
1953 video_device_release(dev->vdev);
1954 return -ENODEV;
1955 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001956
Devin Heitmueller62899a22009-03-15 18:48:52 -03001957 dprintk(1, "%s completed!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001958
1959 return 0;
1960}
1961