blob: d97e0a28fb24edc3e4aa785174192afe9de8e4ff [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);
315}
316
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300317static inline void vbi_buffer_filled(struct au0828_dev *dev,
318 struct au0828_dmaqueue *dma_q,
319 struct au0828_buffer *buf)
320{
321 /* Advice that buffer was filled */
322 au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
323
324 buf->vb.state = VIDEOBUF_DONE;
325 buf->vb.field_count++;
326 do_gettimeofday(&buf->vb.ts);
327
328 dev->isoc_ctl.vbi_buf = NULL;
329
330 list_del(&buf->vb.queue);
331 wake_up(&buf->vb.done);
332}
333
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300334/*
335 * Identify the buffer header type and properly handles
336 */
337static void au0828_copy_video(struct au0828_dev *dev,
338 struct au0828_dmaqueue *dma_q,
339 struct au0828_buffer *buf,
340 unsigned char *p,
341 unsigned char *outp, unsigned long len)
342{
343 void *fieldstart, *startwrite, *startread;
344 int linesdone, currlinedone, offset, lencopy, remain;
345 int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */
346
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300347 if (len == 0)
348 return;
349
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300350 if (dma_q->pos + len > buf->vb.size)
351 len = buf->vb.size - dma_q->pos;
352
353 startread = p;
354 remain = len;
355
356 /* Interlaces frame */
357 if (buf->top_field)
358 fieldstart = outp;
359 else
360 fieldstart = outp + bytesperline;
361
362 linesdone = dma_q->pos / bytesperline;
363 currlinedone = dma_q->pos % bytesperline;
364 offset = linesdone * bytesperline * 2 + currlinedone;
365 startwrite = fieldstart + offset;
366 lencopy = bytesperline - currlinedone;
367 lencopy = lencopy > remain ? remain : lencopy;
368
369 if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
370 au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
371 ((char *)startwrite + lencopy) -
372 ((char *)outp + buf->vb.size));
373 remain = (char *)outp + buf->vb.size - (char *)startwrite;
374 lencopy = remain;
375 }
376 if (lencopy <= 0)
377 return;
378 memcpy(startwrite, startread, lencopy);
379
380 remain -= lencopy;
381
382 while (remain > 0) {
383 startwrite += lencopy + bytesperline;
384 startread += lencopy;
385 if (bytesperline > remain)
386 lencopy = remain;
387 else
388 lencopy = bytesperline;
389
390 if ((char *)startwrite + lencopy > (char *)outp +
391 buf->vb.size) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300392 au0828_isocdbg("Overflow %zi bytes past buf end (2)\n",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300393 ((char *)startwrite + lencopy) -
394 ((char *)outp + buf->vb.size));
395 lencopy = remain = (char *)outp + buf->vb.size -
396 (char *)startwrite;
397 }
398 if (lencopy <= 0)
399 break;
400
401 memcpy(startwrite, startread, lencopy);
402
403 remain -= lencopy;
404 }
405
406 if (offset > 1440) {
407 /* We have enough data to check for greenscreen */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300408 if (outp[0] < 0x60 && outp[1440] < 0x60)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300409 dev->greenscreen_detected = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300410 }
411
412 dma_q->pos += len;
413}
414
415/*
416 * video-buf generic routine to get the next available buffer
417 */
418static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
419 struct au0828_buffer **buf)
420{
421 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
422
423 if (list_empty(&dma_q->active)) {
424 au0828_isocdbg("No active queue to serve\n");
425 dev->isoc_ctl.buf = NULL;
426 *buf = NULL;
427 return;
428 }
429
430 /* Get the next buffer */
431 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
432 dev->isoc_ctl.buf = *buf;
433
434 return;
435}
436
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300437static void au0828_copy_vbi(struct au0828_dev *dev,
438 struct au0828_dmaqueue *dma_q,
439 struct au0828_buffer *buf,
440 unsigned char *p,
441 unsigned char *outp, unsigned long len)
442{
443 unsigned char *startwrite, *startread;
444 int bytesperline = dev->vbi_width;
445 int i, j = 0;
446
447 if (dev == NULL) {
448 au0828_isocdbg("dev is null\n");
449 return;
450 }
451
452 if (dma_q == NULL) {
453 au0828_isocdbg("dma_q is null\n");
454 return;
455 }
456 if (buf == NULL)
457 return;
458 if (p == NULL) {
459 au0828_isocdbg("p is null\n");
460 return;
461 }
462 if (outp == NULL) {
463 au0828_isocdbg("outp is null\n");
464 return;
465 }
466
467 if (dma_q->pos + len > buf->vb.size)
468 len = buf->vb.size - dma_q->pos;
469
470 startread = p;
471 startwrite = outp + (dma_q->pos / 2);
472
473 /* Make sure the bottom field populates the second half of the frame */
474 if (buf->top_field == 0)
475 startwrite += bytesperline * dev->vbi_height;
476
477 for (i = 0; i < len; i += 2)
478 startwrite[j++] = startread[i+1];
479
480 dma_q->pos += len;
481}
482
483
484/*
485 * video-buf generic routine to get the next available VBI buffer
486 */
487static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q,
488 struct au0828_buffer **buf)
489{
490 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq);
491 char *outp;
492
493 if (list_empty(&dma_q->active)) {
494 au0828_isocdbg("No active queue to serve\n");
495 dev->isoc_ctl.vbi_buf = NULL;
496 *buf = NULL;
497 return;
498 }
499
500 /* Get the next buffer */
501 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
502 /* Cleans up buffer - Usefull for testing for frame/URB loss */
503 outp = videobuf_to_vmalloc(&(*buf)->vb);
504 memset(outp, 0x00, (*buf)->vb.size);
505
506 dev->isoc_ctl.vbi_buf = *buf;
507
508 return;
509}
510
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300511/*
512 * Controls the isoc copy of each urb packet
513 */
514static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
515{
516 struct au0828_buffer *buf;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300517 struct au0828_buffer *vbi_buf;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300518 struct au0828_dmaqueue *dma_q = urb->context;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300519 struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300520 unsigned char *outp = NULL;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300521 unsigned char *vbioutp = NULL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300522 int i, len = 0, rc = 1;
523 unsigned char *p;
524 unsigned char fbyte;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300525 unsigned int vbi_field_size;
526 unsigned int remain, lencopy;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300527
528 if (!dev)
529 return 0;
530
531 if ((dev->dev_state & DEV_DISCONNECTED) ||
532 (dev->dev_state & DEV_MISCONFIGURED))
533 return 0;
534
535 if (urb->status < 0) {
536 print_err_status(dev, -1, urb->status);
537 if (urb->status == -ENOENT)
538 return 0;
539 }
540
541 buf = dev->isoc_ctl.buf;
542 if (buf != NULL)
543 outp = videobuf_to_vmalloc(&buf->vb);
544
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300545 vbi_buf = dev->isoc_ctl.vbi_buf;
546 if (vbi_buf != NULL)
547 vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
548
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300549 for (i = 0; i < urb->number_of_packets; i++) {
550 int status = urb->iso_frame_desc[i].status;
551
552 if (status < 0) {
553 print_err_status(dev, i, status);
554 if (urb->iso_frame_desc[i].status != -EPROTO)
555 continue;
556 }
557
Devin Heitmueller62899a22009-03-15 18:48:52 -0300558 if (urb->iso_frame_desc[i].actual_length <= 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300559 continue;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300560
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300561 if (urb->iso_frame_desc[i].actual_length >
562 dev->max_pkt_size) {
563 au0828_isocdbg("packet bigger than packet size");
564 continue;
565 }
566
567 p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
568 fbyte = p[0];
569 len = urb->iso_frame_desc[i].actual_length - 4;
570 p += 4;
571
572 if (fbyte & 0x80) {
573 len -= 4;
574 p += 4;
575 au0828_isocdbg("Video frame %s\n",
576 (fbyte & 0x40) ? "odd" : "even");
577 if (!(fbyte & 0x40)) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300578 /* VBI */
579 if (vbi_buf != NULL)
580 vbi_buffer_filled(dev,
581 vbi_dma_q,
582 vbi_buf);
583 vbi_get_next_buf(vbi_dma_q, &vbi_buf);
584 if (vbi_buf == NULL)
585 vbioutp = NULL;
586 else
587 vbioutp = videobuf_to_vmalloc(
588 &vbi_buf->vb);
589
590 /* Video */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300591 if (buf != NULL)
592 buffer_filled(dev, dma_q, buf);
593 get_next_buf(dma_q, &buf);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300594 if (buf == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300595 outp = NULL;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300596 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300597 outp = videobuf_to_vmalloc(&buf->vb);
598 }
599
600 if (buf != NULL) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300601 if (fbyte & 0x40)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300602 buf->top_field = 1;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300603 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300604 buf->top_field = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300605 }
606
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300607 if (vbi_buf != NULL) {
608 if (fbyte & 0x40)
609 vbi_buf->top_field = 1;
610 else
611 vbi_buf->top_field = 0;
612 }
613
614 dev->vbi_read = 0;
615 vbi_dma_q->pos = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300616 dma_q->pos = 0;
617 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300618
619 vbi_field_size = dev->vbi_width * dev->vbi_height * 2;
620 if (dev->vbi_read < vbi_field_size) {
621 remain = vbi_field_size - dev->vbi_read;
622 if (len < remain)
623 lencopy = len;
624 else
625 lencopy = remain;
626
627 if (vbi_buf != NULL)
628 au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
629 vbioutp, len);
630
631 len -= lencopy;
632 p += lencopy;
633 dev->vbi_read += lencopy;
634 }
635
636 if (dev->vbi_read >= vbi_field_size && buf != NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300637 au0828_copy_video(dev, dma_q, buf, p, outp, len);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300638 }
639 return rc;
640}
641
642static int
643buffer_setup(struct videobuf_queue *vq, unsigned int *count,
644 unsigned int *size)
645{
646 struct au0828_fh *fh = vq->priv_data;
647 *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
648
649 if (0 == *count)
650 *count = AU0828_DEF_BUF;
651
652 if (*count < AU0828_MIN_BUF)
653 *count = AU0828_MIN_BUF;
654 return 0;
655}
656
657/* This is called *without* dev->slock held; please keep it that way */
658static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
659{
660 struct au0828_fh *fh = vq->priv_data;
661 struct au0828_dev *dev = fh->dev;
662 unsigned long flags = 0;
663 if (in_interrupt())
664 BUG();
665
666 /* We used to wait for the buffer to finish here, but this didn't work
667 because, as we were keeping the state as VIDEOBUF_QUEUED,
668 videobuf_queue_cancel marked it as finished for us.
669 (Also, it could wedge forever if the hardware was misconfigured.)
670
671 This should be safe; by the time we get here, the buffer isn't
672 queued anymore. If we ever start marking the buffers as
673 VIDEOBUF_ACTIVE, it won't be, though.
674 */
675 spin_lock_irqsave(&dev->slock, flags);
676 if (dev->isoc_ctl.buf == buf)
677 dev->isoc_ctl.buf = NULL;
678 spin_unlock_irqrestore(&dev->slock, flags);
679
680 videobuf_vmalloc_free(&buf->vb);
681 buf->vb.state = VIDEOBUF_NEEDS_INIT;
682}
683
684static int
685buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
686 enum v4l2_field field)
687{
688 struct au0828_fh *fh = vq->priv_data;
689 struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
690 struct au0828_dev *dev = fh->dev;
691 int rc = 0, urb_init = 0;
692
693 buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
694
695 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
696 return -EINVAL;
697
698 buf->vb.width = dev->width;
699 buf->vb.height = dev->height;
700 buf->vb.field = field;
701
702 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
703 rc = videobuf_iolock(vq, &buf->vb, NULL);
704 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300705 printk(KERN_INFO "videobuf_iolock failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300706 goto fail;
707 }
708 }
709
710 if (!dev->isoc_ctl.num_bufs)
711 urb_init = 1;
712
713 if (urb_init) {
714 rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,
715 AU0828_MAX_ISO_BUFS, dev->max_pkt_size,
716 au0828_isoc_copy);
717 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300718 printk(KERN_INFO "au0828_init_isoc failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300719 goto fail;
720 }
721 }
722
723 buf->vb.state = VIDEOBUF_PREPARED;
724 return 0;
725
726fail:
727 free_buffer(vq, buf);
728 return rc;
729}
730
731static void
732buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
733{
734 struct au0828_buffer *buf = container_of(vb,
735 struct au0828_buffer,
736 vb);
737 struct au0828_fh *fh = vq->priv_data;
738 struct au0828_dev *dev = fh->dev;
739 struct au0828_dmaqueue *vidq = &dev->vidq;
740
741 buf->vb.state = VIDEOBUF_QUEUED;
742 list_add_tail(&buf->vb.queue, &vidq->active);
743}
744
745static void buffer_release(struct videobuf_queue *vq,
746 struct videobuf_buffer *vb)
747{
748 struct au0828_buffer *buf = container_of(vb,
749 struct au0828_buffer,
750 vb);
751
752 free_buffer(vq, buf);
753}
754
755static struct videobuf_queue_ops au0828_video_qops = {
756 .buf_setup = buffer_setup,
757 .buf_prepare = buffer_prepare,
758 .buf_queue = buffer_queue,
759 .buf_release = buffer_release,
760};
761
762/* ------------------------------------------------------------------
763 V4L2 interface
764 ------------------------------------------------------------------*/
765
766static int au0828_i2s_init(struct au0828_dev *dev)
767{
768 /* Enable i2s mode */
769 au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);
770 return 0;
771}
772
773/*
774 * Auvitek au0828 analog stream enable
775 * Please set interface0 to AS5 before enable the stream
776 */
777int au0828_analog_stream_enable(struct au0828_dev *d)
778{
779 dprintk(1, "au0828_analog_stream_enable called\n");
780 au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
781 au0828_writereg(d, 0x106, 0x00);
782 /* set x position */
783 au0828_writereg(d, 0x110, 0x00);
784 au0828_writereg(d, 0x111, 0x00);
785 au0828_writereg(d, 0x114, 0xa0);
786 au0828_writereg(d, 0x115, 0x05);
787 /* set y position */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300788 au0828_writereg(d, 0x112, 0x00);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300789 au0828_writereg(d, 0x113, 0x00);
790 au0828_writereg(d, 0x116, 0xf2);
791 au0828_writereg(d, 0x117, 0x00);
792 au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
793
794 return 0;
795}
796
797int au0828_analog_stream_disable(struct au0828_dev *d)
798{
799 dprintk(1, "au0828_analog_stream_disable called\n");
800 au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
801 return 0;
802}
803
804void au0828_analog_stream_reset(struct au0828_dev *dev)
805{
806 dprintk(1, "au0828_analog_stream_reset called\n");
807 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
808 mdelay(30);
809 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);
810}
811
812/*
813 * Some operations needs to stop current streaming
814 */
815static int au0828_stream_interrupt(struct au0828_dev *dev)
816{
817 int ret = 0;
818
819 dev->stream_state = STREAM_INTERRUPT;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300820 if (dev->dev_state == DEV_DISCONNECTED)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300821 return -ENODEV;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300822 else if (ret) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300823 dev->dev_state = DEV_MISCONFIGURED;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300824 dprintk(1, "%s device is misconfigured!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300825 return ret;
826 }
827 return 0;
828}
829
830/*
831 * au0828_release_resources
832 * unregister v4l2 devices
833 */
834void au0828_analog_unregister(struct au0828_dev *dev)
835{
836 dprintk(1, "au0828_release_resources called\n");
837 mutex_lock(&au0828_sysfs_lock);
838
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200839 if (dev->vdev)
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300840 video_unregister_device(dev->vdev);
841 if (dev->vbi_dev)
842 video_unregister_device(dev->vbi_dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300843
844 mutex_unlock(&au0828_sysfs_lock);
845}
846
847
848/* Usage lock check functions */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300849static int res_get(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300850{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300851 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300852
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300853 if (fh->resources & bit)
854 /* have it already allocated */
855 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300856
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300857 /* is it free? */
858 mutex_lock(&dev->lock);
859 if (dev->resources & bit) {
860 /* no, someone else uses it */
861 mutex_unlock(&dev->lock);
862 return 0;
863 }
864 /* it's free, grab it */
865 fh->resources |= bit;
866 dev->resources |= bit;
867 dprintk(1, "res: get %d\n", bit);
868 mutex_unlock(&dev->lock);
869 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300870}
871
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300872static int res_check(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300873{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300874 return fh->resources & bit;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300875}
876
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300877static int res_locked(struct au0828_dev *dev, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300878{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300879 return dev->resources & bit;
880}
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300881
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300882static void res_free(struct au0828_fh *fh, unsigned int bits)
883{
884 struct au0828_dev *dev = fh->dev;
885
886 BUG_ON((fh->resources & bits) != bits);
887
888 mutex_lock(&dev->lock);
889 fh->resources &= ~bits;
890 dev->resources &= ~bits;
891 dprintk(1, "res: put %d\n", bits);
892 mutex_unlock(&dev->lock);
893}
894
895static int get_ressource(struct au0828_fh *fh)
896{
897 switch (fh->type) {
898 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
899 return AU0828_RESOURCE_VIDEO;
900 case V4L2_BUF_TYPE_VBI_CAPTURE:
901 return AU0828_RESOURCE_VBI;
902 default:
903 BUG();
904 return 0;
905 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300906}
907
908static int au0828_v4l2_open(struct file *filp)
909{
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300910 int ret = 0;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300911 struct video_device *vdev = video_devdata(filp);
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200912 struct au0828_dev *dev = video_drvdata(filp);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300913 struct au0828_fh *fh;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300914 int type;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300915
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300916 switch (vdev->vfl_type) {
917 case VFL_TYPE_GRABBER:
918 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
919 break;
920 case VFL_TYPE_VBI:
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200921 type = V4L2_BUF_TYPE_VBI_CAPTURE;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300922 break;
923 default:
924 return -EINVAL;
925 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300926
927 fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300928 if (NULL == fh) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300929 dprintk(1, "Failed allocate au0828_fh struct!\n");
930 return -ENOMEM;
931 }
932
933 fh->type = type;
934 fh->dev = dev;
935 filp->private_data = fh;
936
Devin Heitmueller62899a22009-03-15 18:48:52 -0300937 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300938 /* set au0828 interface0 to AS5 here again */
939 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300940 if (ret < 0) {
941 printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300942 return -EBUSY;
943 }
944 dev->width = NTSC_STD_W;
945 dev->height = NTSC_STD_H;
946 dev->frame_size = dev->width * dev->height * 2;
947 dev->field_size = dev->width * dev->height;
948 dev->bytesperline = dev->width * 2;
949
950 au0828_analog_stream_enable(dev);
951 au0828_analog_stream_reset(dev);
952
953 /* If we were doing ac97 instead of i2s, it would go here...*/
954 au0828_i2s_init(dev);
955
956 dev->stream_state = STREAM_OFF;
957 dev->dev_state |= DEV_INITIALIZED;
958 }
959
960 dev->users++;
961
962 videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300963 NULL, &dev->slock,
964 V4L2_BUF_TYPE_VIDEO_CAPTURE,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300965 V4L2_FIELD_INTERLACED,
966 sizeof(struct au0828_buffer), fh);
967
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300968 /* VBI Setup */
969 dev->vbi_width = 720;
970 dev->vbi_height = 1;
971 videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops,
972 NULL, &dev->slock,
973 V4L2_BUF_TYPE_VBI_CAPTURE,
974 V4L2_FIELD_SEQ_TB,
975 sizeof(struct au0828_buffer), fh);
976
977
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300978 return ret;
979}
980
981static int au0828_v4l2_close(struct file *filp)
982{
983 int ret;
984 struct au0828_fh *fh = filp->private_data;
985 struct au0828_dev *dev = fh->dev;
986
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300987 if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
988 videobuf_stop(&fh->vb_vidq);
989 res_free(fh, AU0828_RESOURCE_VIDEO);
990 }
991
992 if (res_check(fh, AU0828_RESOURCE_VBI)) {
993 videobuf_stop(&fh->vb_vbiq);
994 res_free(fh, AU0828_RESOURCE_VBI);
995 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300996
Devin Heitmueller62899a22009-03-15 18:48:52 -0300997 if (dev->users == 1) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300998 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300999 au0828_analog_unregister(dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001000 kfree(dev);
1001 return 0;
1002 }
1003
1004 au0828_analog_stream_disable(dev);
1005
1006 au0828_uninit_isoc(dev);
1007
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001008 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -03001009 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001010
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001011 /* When close the device, set the usb intf0 into alt0 to free
1012 USB bandwidth */
1013 ret = usb_set_interface(dev->usbdev, 0, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001014 if (ret < 0)
1015 printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001016 }
1017
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001018 videobuf_mmap_free(&fh->vb_vidq);
1019 videobuf_mmap_free(&fh->vb_vbiq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001020 kfree(fh);
1021 dev->users--;
1022 wake_up_interruptible_nr(&dev->open, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001023 return 0;
1024}
1025
1026static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
1027 size_t count, loff_t *pos)
1028{
1029 struct au0828_fh *fh = filp->private_data;
1030 struct au0828_dev *dev = fh->dev;
1031 int rc;
1032
1033 rc = check_dev(dev);
1034 if (rc < 0)
1035 return rc;
1036
Devin Heitmueller62899a22009-03-15 18:48:52 -03001037 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001038 if (res_locked(dev, AU0828_RESOURCE_VIDEO))
1039 return -EBUSY;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001040
1041 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
1042 filp->f_flags & O_NONBLOCK);
1043 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001044
1045 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1046 if (!res_get(fh, AU0828_RESOURCE_VBI))
1047 return -EBUSY;
1048
1049 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
1050 filp->f_flags & O_NONBLOCK);
1051 }
1052
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001053 return 0;
1054}
1055
1056static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
1057{
1058 struct au0828_fh *fh = filp->private_data;
1059 struct au0828_dev *dev = fh->dev;
1060 int rc;
1061
1062 rc = check_dev(dev);
1063 if (rc < 0)
1064 return rc;
1065
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001066 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1067 if (!res_get(fh, AU0828_RESOURCE_VIDEO))
1068 return POLLERR;
1069 return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
1070 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1071 if (!res_get(fh, AU0828_RESOURCE_VBI))
1072 return POLLERR;
1073 return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
1074 } else {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001075 return POLLERR;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001076 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001077}
1078
1079static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
1080{
1081 struct au0828_fh *fh = filp->private_data;
1082 struct au0828_dev *dev = fh->dev;
1083 int rc;
1084
1085 rc = check_dev(dev);
1086 if (rc < 0)
1087 return rc;
1088
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001089 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1090 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
1091 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1092 rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001093
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001094 return rc;
1095}
1096
1097static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
1098 struct v4l2_format *format)
1099{
1100 int ret;
1101 int width = format->fmt.pix.width;
1102 int height = format->fmt.pix.height;
1103 unsigned int maxwidth, maxheight;
1104
1105 maxwidth = 720;
1106 maxheight = 480;
1107
Devin Heitmueller62899a22009-03-15 18:48:52 -03001108 if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001109 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001110
1111 /* If they are demanding a format other than the one we support,
1112 bail out (tvtime asks for UYVY and then retries with YUYV) */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001113 if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001114 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001115
1116 /* format->fmt.pix.width only support 720 and height 480 */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001117 if (width != 720)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001118 width = 720;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001119 if (height != 480)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001120 height = 480;
1121
1122 format->fmt.pix.width = width;
1123 format->fmt.pix.height = height;
1124 format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1125 format->fmt.pix.bytesperline = width * 2;
1126 format->fmt.pix.sizeimage = width * height * 2;
1127 format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1128 format->fmt.pix.field = V4L2_FIELD_INTERLACED;
1129
Devin Heitmueller62899a22009-03-15 18:48:52 -03001130 if (cmd == VIDIOC_TRY_FMT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001131 return 0;
1132
1133 /* maybe set new image format, driver current only support 720*480 */
1134 dev->width = width;
1135 dev->height = height;
1136 dev->frame_size = width * height * 2;
1137 dev->field_size = width * height;
1138 dev->bytesperline = width * 2;
1139
Devin Heitmueller62899a22009-03-15 18:48:52 -03001140 if (dev->stream_state == STREAM_ON) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001141 dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
Devin Heitmueller62899a22009-03-15 18:48:52 -03001142 ret = au0828_stream_interrupt(dev);
1143 if (ret != 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001144 dprintk(1, "error interrupting video stream!\n");
1145 return ret;
1146 }
1147 }
1148
1149 /* set au0828 interface0 to AS5 here again */
1150 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001151 if (ret < 0) {
1152 printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001153 return -EBUSY;
1154 }
1155
1156 au0828_analog_stream_enable(dev);
1157
1158 return 0;
1159}
1160
1161
1162static int vidioc_queryctrl(struct file *file, void *priv,
1163 struct v4l2_queryctrl *qc)
1164{
1165 struct au0828_fh *fh = priv;
1166 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001167 v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001168 if (qc->type)
1169 return 0;
1170 else
1171 return -EINVAL;
1172}
1173
1174static int vidioc_querycap(struct file *file, void *priv,
1175 struct v4l2_capability *cap)
1176{
1177 struct au0828_fh *fh = priv;
1178 struct au0828_dev *dev = fh->dev;
1179
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001180 strlcpy(cap->driver, "au0828", sizeof(cap->driver));
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001181 strlcpy(cap->card, dev->board.name, sizeof(cap->card));
Devin Heitmuellerb14667f2009-03-11 03:01:04 -03001182 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001183
1184 cap->version = AU0828_VERSION_CODE;
1185
1186 /*set the device capabilities */
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001187 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001188 V4L2_CAP_VBI_CAPTURE |
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001189 V4L2_CAP_AUDIO |
1190 V4L2_CAP_READWRITE |
1191 V4L2_CAP_STREAMING |
1192 V4L2_CAP_TUNER;
1193 return 0;
1194}
1195
1196static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1197 struct v4l2_fmtdesc *f)
1198{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001199 if (f->index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001200 return -EINVAL;
1201
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001202 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1203 strcpy(f->description, "Packed YUV2");
1204
1205 f->flags = 0;
1206 f->pixelformat = V4L2_PIX_FMT_UYVY;
1207
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001208 return 0;
1209}
1210
1211static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1212 struct v4l2_format *f)
1213{
1214 struct au0828_fh *fh = priv;
1215 struct au0828_dev *dev = fh->dev;
1216
1217 f->fmt.pix.width = dev->width;
1218 f->fmt.pix.height = dev->height;
1219 f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1220 f->fmt.pix.bytesperline = dev->bytesperline;
1221 f->fmt.pix.sizeimage = dev->frame_size;
1222 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
1223 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1224 return 0;
1225}
1226
1227static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1228 struct v4l2_format *f)
1229{
1230 struct au0828_fh *fh = priv;
1231 struct au0828_dev *dev = fh->dev;
1232
1233 return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
1234}
1235
1236static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1237 struct v4l2_format *f)
1238{
1239 struct au0828_fh *fh = priv;
1240 struct au0828_dev *dev = fh->dev;
1241 int rc;
1242
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001243 rc = check_dev(dev);
1244 if (rc < 0)
1245 return rc;
1246
1247 mutex_lock(&dev->lock);
1248
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001249 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001250 printk(KERN_INFO "%s queue busy\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001251 rc = -EBUSY;
1252 goto out;
1253 }
1254
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001255 rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001256out:
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001257 mutex_unlock(&dev->lock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001258 return rc;
1259}
1260
1261static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
1262{
1263 struct au0828_fh *fh = priv;
1264 struct au0828_dev *dev = fh->dev;
1265
1266 /* FIXME: when we support something other than NTSC, we are going to
1267 have to make the au0828 bridge adjust the size of its capture
1268 buffer, which is currently hardcoded at 720x480 */
1269
Hans Verkuilf41737e2009-04-01 03:52:39 -03001270 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001271 return 0;
1272}
1273
1274static int vidioc_enum_input(struct file *file, void *priv,
1275 struct v4l2_input *input)
1276{
1277 struct au0828_fh *fh = priv;
1278 struct au0828_dev *dev = fh->dev;
1279 unsigned int tmp;
1280
1281 static const char *inames[] = {
Devin Heitmueller3d622872009-03-15 17:48:26 -03001282 [AU0828_VMUX_UNDEFINED] = "Undefined",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001283 [AU0828_VMUX_COMPOSITE] = "Composite",
1284 [AU0828_VMUX_SVIDEO] = "S-Video",
1285 [AU0828_VMUX_CABLE] = "Cable TV",
1286 [AU0828_VMUX_TELEVISION] = "Television",
1287 [AU0828_VMUX_DVB] = "DVB",
1288 [AU0828_VMUX_DEBUG] = "tv debug"
1289 };
1290
1291 tmp = input->index;
1292
Dan Carpenterf5e20c32010-03-28 08:21:18 -03001293 if (tmp >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001294 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001295 if (AUVI_INPUT(tmp).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001296 return -EINVAL;
1297
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001298 input->index = tmp;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001299 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001300 if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
1301 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001302 input->type |= V4L2_INPUT_TYPE_TUNER;
1303 else
1304 input->type |= V4L2_INPUT_TYPE_CAMERA;
1305
1306 input->std = dev->vdev->tvnorms;
1307
1308 return 0;
1309}
1310
1311static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1312{
1313 struct au0828_fh *fh = priv;
1314 struct au0828_dev *dev = fh->dev;
1315 *i = dev->ctrl_input;
1316 return 0;
1317}
1318
1319static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1320{
1321 struct au0828_fh *fh = priv;
1322 struct au0828_dev *dev = fh->dev;
1323 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001324
Devin Heitmueller62899a22009-03-15 18:48:52 -03001325 dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001326 index);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001327 if (index >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001328 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001329 if (AUVI_INPUT(index).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001330 return -EINVAL;
1331 dev->ctrl_input = index;
1332
Devin Heitmueller62899a22009-03-15 18:48:52 -03001333 switch (AUVI_INPUT(index).type) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001334 case AU0828_VMUX_SVIDEO:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001335 dev->input_type = AU0828_VMUX_SVIDEO;
1336 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001337 case AU0828_VMUX_COMPOSITE:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001338 dev->input_type = AU0828_VMUX_COMPOSITE;
1339 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001340 case AU0828_VMUX_TELEVISION:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001341 dev->input_type = AU0828_VMUX_TELEVISION;
1342 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001343 default:
Devin Heitmuellera1094c42009-03-15 17:43:13 -03001344 dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
1345 AUVI_INPUT(index).type);
1346 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001347 }
1348
Hans Verkuil5325b422009-04-02 11:26:22 -03001349 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1350 AUVI_INPUT(index).vmux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001351
1352 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1353 int enable = 0;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001354 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001355 continue;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001356
1357 if (i == index)
1358 enable = 1;
1359 else
1360 enable = 0;
1361 if (enable) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001362 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001363 } else {
1364 /* Make sure we leave it turned on if some
1365 other input is routed to this callback */
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001366 if ((AUVI_INPUT(i).audio_setup) !=
1367 ((AUVI_INPUT(index).audio_setup))) {
1368 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001369 }
1370 }
1371 }
1372
Hans Verkuil5325b422009-04-02 11:26:22 -03001373 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1374 AUVI_INPUT(index).amux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001375 return 0;
1376}
1377
1378static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1379{
1380 struct au0828_fh *fh = priv;
1381 struct au0828_dev *dev = fh->dev;
1382 unsigned int index = a->index;
1383
Devin Heitmueller62899a22009-03-15 18:48:52 -03001384 if (a->index > 1)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001385 return -EINVAL;
1386
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001387 index = dev->ctrl_ainput;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001388 if (index == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001389 strcpy(a->name, "Television");
1390 else
1391 strcpy(a->name, "Line in");
1392
1393 a->capability = V4L2_AUDCAP_STEREO;
1394 a->index = index;
1395 return 0;
1396}
1397
1398static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
1399{
1400 struct au0828_fh *fh = priv;
1401 struct au0828_dev *dev = fh->dev;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001402 if (a->index != dev->ctrl_ainput)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001403 return -EINVAL;
1404 return 0;
1405}
1406
1407static int vidioc_g_ctrl(struct file *file, void *priv,
1408 struct v4l2_control *ctrl)
1409{
1410 struct au0828_fh *fh = priv;
1411 struct au0828_dev *dev = fh->dev;
1412
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001413 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001414 return 0;
1415
1416}
1417
1418static int vidioc_s_ctrl(struct file *file, void *priv,
1419 struct v4l2_control *ctrl)
1420{
1421 struct au0828_fh *fh = priv;
1422 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001423 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001424 return 0;
1425}
1426
1427static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
1428{
1429 struct au0828_fh *fh = priv;
1430 struct au0828_dev *dev = fh->dev;
1431
Devin Heitmueller62899a22009-03-15 18:48:52 -03001432 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001433 return -EINVAL;
1434
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001435 strcpy(t->name, "Auvitek tuner");
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001436 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001437 return 0;
1438}
1439
1440static int vidioc_s_tuner(struct file *file, void *priv,
1441 struct v4l2_tuner *t)
1442{
1443 struct au0828_fh *fh = priv;
1444 struct au0828_dev *dev = fh->dev;
1445
Devin Heitmueller62899a22009-03-15 18:48:52 -03001446 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001447 return -EINVAL;
1448
1449 t->type = V4L2_TUNER_ANALOG_TV;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001450 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001451 dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
1452 t->afc);
1453 return 0;
1454
1455}
1456
1457static int vidioc_g_frequency(struct file *file, void *priv,
1458 struct v4l2_frequency *freq)
1459{
1460 struct au0828_fh *fh = priv;
1461 struct au0828_dev *dev = fh->dev;
Devin Heitmuellerc8889232009-03-15 17:38:47 -03001462
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001463 freq->type = V4L2_TUNER_ANALOG_TV;
1464 freq->frequency = dev->ctrl_freq;
1465 return 0;
1466}
1467
1468static int vidioc_s_frequency(struct file *file, void *priv,
1469 struct v4l2_frequency *freq)
1470{
1471 struct au0828_fh *fh = priv;
1472 struct au0828_dev *dev = fh->dev;
1473
Devin Heitmueller62899a22009-03-15 18:48:52 -03001474 if (freq->tuner != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001475 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001476 if (freq->type != V4L2_TUNER_ANALOG_TV)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001477 return -EINVAL;
1478
1479 dev->ctrl_freq = freq->frequency;
1480
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001481 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001482
1483 au0828_analog_stream_reset(dev);
1484
1485 return 0;
1486}
1487
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001488
1489/* RAW VBI ioctls */
1490
1491static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1492 struct v4l2_format *format)
1493{
1494 struct au0828_fh *fh = priv;
1495 struct au0828_dev *dev = fh->dev;
1496
1497 format->fmt.vbi.samples_per_line = dev->vbi_width;
1498 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1499 format->fmt.vbi.offset = 0;
1500 format->fmt.vbi.flags = 0;
1501 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1502
1503 format->fmt.vbi.count[0] = dev->vbi_height;
1504 format->fmt.vbi.count[1] = dev->vbi_height;
1505 format->fmt.vbi.start[0] = 21;
1506 format->fmt.vbi.start[1] = 284;
1507
1508 return 0;
1509}
1510
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001511static int vidioc_g_chip_ident(struct file *file, void *priv,
1512 struct v4l2_dbg_chip_ident *chip)
1513{
1514 struct au0828_fh *fh = priv;
1515 struct au0828_dev *dev = fh->dev;
1516 chip->ident = V4L2_IDENT_NONE;
1517 chip->revision = 0;
1518
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001519 if (v4l2_chip_match_host(&chip->match)) {
1520 chip->ident = V4L2_IDENT_AU0828;
1521 return 0;
1522 }
1523
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001524 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001525 if (chip->ident == V4L2_IDENT_NONE)
1526 return -EINVAL;
1527
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001528 return 0;
1529}
1530
1531static int vidioc_cropcap(struct file *file, void *priv,
1532 struct v4l2_cropcap *cc)
1533{
1534 struct au0828_fh *fh = priv;
1535 struct au0828_dev *dev = fh->dev;
1536
Devin Heitmueller62899a22009-03-15 18:48:52 -03001537 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001538 return -EINVAL;
1539
1540 cc->bounds.left = 0;
1541 cc->bounds.top = 0;
1542 cc->bounds.width = dev->width;
1543 cc->bounds.height = dev->height;
1544
1545 cc->defrect = cc->bounds;
1546
1547 cc->pixelaspect.numerator = 54;
1548 cc->pixelaspect.denominator = 59;
1549
1550 return 0;
1551}
1552
1553static int vidioc_streamon(struct file *file, void *priv,
1554 enum v4l2_buf_type type)
1555{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001556 struct au0828_fh *fh = priv;
1557 struct au0828_dev *dev = fh->dev;
1558 int rc = -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001559
1560 rc = check_dev(dev);
1561 if (rc < 0)
1562 return rc;
1563
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001564 if (unlikely(type != fh->type))
1565 return -EINVAL;
1566
1567 dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
1568 fh, type, fh->resources, dev->resources);
1569
1570 if (unlikely(!res_get(fh, get_ressource(fh))))
1571 return -EBUSY;
1572
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001573 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1574 au0828_analog_stream_enable(dev);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001575 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001576 }
1577
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001578 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001579 rc = videobuf_streamon(&fh->vb_vidq);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001580 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1581 rc = videobuf_streamon(&fh->vb_vbiq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001582
1583 return rc;
1584}
1585
1586static int vidioc_streamoff(struct file *file, void *priv,
1587 enum v4l2_buf_type type)
1588{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001589 struct au0828_fh *fh = priv;
1590 struct au0828_dev *dev = fh->dev;
1591 int rc;
1592 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001593
1594 rc = check_dev(dev);
1595 if (rc < 0)
1596 return rc;
1597
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001598 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1599 fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001600 return -EINVAL;
1601 if (type != fh->type)
1602 return -EINVAL;
1603
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001604 dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
1605 fh, type, fh->resources, dev->resources);
1606
1607 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001608 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001609 rc = au0828_stream_interrupt(dev);
1610 if (rc != 0)
1611 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001612
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001613 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1614 if (AUVI_INPUT(i).audio_setup == NULL)
1615 continue;
1616 (AUVI_INPUT(i).audio_setup)(dev, 0);
1617 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001618
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001619 videobuf_streamoff(&fh->vb_vidq);
1620 res_free(fh, AU0828_RESOURCE_VIDEO);
1621 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1622 videobuf_streamoff(&fh->vb_vbiq);
1623 res_free(fh, AU0828_RESOURCE_VBI);
1624 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001625
1626 return 0;
1627}
1628
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001629#ifdef CONFIG_VIDEO_ADV_DEBUG
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001630static int vidioc_g_register(struct file *file, void *priv,
1631 struct v4l2_dbg_register *reg)
1632{
1633 struct au0828_fh *fh = priv;
1634 struct au0828_dev *dev = fh->dev;
1635
1636 switch (reg->match.type) {
1637 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001638 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001639 return 0;
1640 default:
1641 return -EINVAL;
1642 }
1643}
1644
1645static int vidioc_s_register(struct file *file, void *priv,
1646 struct v4l2_dbg_register *reg)
1647{
1648 struct au0828_fh *fh = priv;
1649 struct au0828_dev *dev = fh->dev;
1650
1651 switch (reg->match.type) {
1652 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001653 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001654 return 0;
1655 default:
1656 return -EINVAL;
1657 }
1658 return 0;
1659}
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001660#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001661
1662static int vidioc_reqbufs(struct file *file, void *priv,
1663 struct v4l2_requestbuffers *rb)
1664{
1665 struct au0828_fh *fh = priv;
1666 struct au0828_dev *dev = fh->dev;
1667 int rc;
1668
1669 rc = check_dev(dev);
1670 if (rc < 0)
1671 return rc;
1672
1673 return videobuf_reqbufs(&fh->vb_vidq, rb);
1674}
1675
1676static int vidioc_querybuf(struct file *file, void *priv,
1677 struct v4l2_buffer *b)
1678{
1679 struct au0828_fh *fh = priv;
1680 struct au0828_dev *dev = fh->dev;
1681 int rc;
1682
1683 rc = check_dev(dev);
1684 if (rc < 0)
1685 return rc;
1686
1687 return videobuf_querybuf(&fh->vb_vidq, b);
1688}
1689
1690static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1691{
1692 struct au0828_fh *fh = priv;
1693 struct au0828_dev *dev = fh->dev;
1694 int rc;
1695
1696 rc = check_dev(dev);
1697 if (rc < 0)
1698 return rc;
1699
1700 return videobuf_qbuf(&fh->vb_vidq, b);
1701}
1702
1703static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1704{
1705 struct au0828_fh *fh = priv;
1706 struct au0828_dev *dev = fh->dev;
1707 int rc;
1708
1709 rc = check_dev(dev);
1710 if (rc < 0)
1711 return rc;
1712
1713 /* Workaround for a bug in the au0828 hardware design that sometimes
1714 results in the colorspace being inverted */
1715 if (dev->greenscreen_detected == 1) {
1716 dprintk(1, "Detected green frame. Resetting stream...\n");
1717 au0828_analog_stream_reset(dev);
1718 dev->greenscreen_detected = 0;
1719 }
1720
1721 return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1722}
1723
1724#ifdef CONFIG_VIDEO_V4L1_COMPAT
1725static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
1726{
1727 struct au0828_fh *fh = priv;
1728
1729 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
1730}
1731#endif
1732
1733static struct v4l2_file_operations au0828_v4l_fops = {
1734 .owner = THIS_MODULE,
1735 .open = au0828_v4l2_open,
1736 .release = au0828_v4l2_close,
1737 .read = au0828_v4l2_read,
1738 .poll = au0828_v4l2_poll,
1739 .mmap = au0828_v4l2_mmap,
1740 .ioctl = video_ioctl2,
1741};
1742
1743static const struct v4l2_ioctl_ops video_ioctl_ops = {
1744 .vidioc_querycap = vidioc_querycap,
1745 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1746 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1747 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1748 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001749 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001750 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001751 .vidioc_g_audio = vidioc_g_audio,
1752 .vidioc_s_audio = vidioc_s_audio,
1753 .vidioc_cropcap = vidioc_cropcap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001754 .vidioc_reqbufs = vidioc_reqbufs,
1755 .vidioc_querybuf = vidioc_querybuf,
1756 .vidioc_qbuf = vidioc_qbuf,
1757 .vidioc_dqbuf = vidioc_dqbuf,
1758 .vidioc_s_std = vidioc_s_std,
1759 .vidioc_enum_input = vidioc_enum_input,
1760 .vidioc_g_input = vidioc_g_input,
1761 .vidioc_s_input = vidioc_s_input,
1762 .vidioc_queryctrl = vidioc_queryctrl,
1763 .vidioc_g_ctrl = vidioc_g_ctrl,
1764 .vidioc_s_ctrl = vidioc_s_ctrl,
1765 .vidioc_streamon = vidioc_streamon,
1766 .vidioc_streamoff = vidioc_streamoff,
1767 .vidioc_g_tuner = vidioc_g_tuner,
1768 .vidioc_s_tuner = vidioc_s_tuner,
1769 .vidioc_g_frequency = vidioc_g_frequency,
1770 .vidioc_s_frequency = vidioc_s_frequency,
1771#ifdef CONFIG_VIDEO_ADV_DEBUG
1772 .vidioc_g_register = vidioc_g_register,
1773 .vidioc_s_register = vidioc_s_register,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001774#endif
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001775 .vidioc_g_chip_ident = vidioc_g_chip_ident,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001776#ifdef CONFIG_VIDEO_V4L1_COMPAT
1777 .vidiocgmbuf = vidiocgmbuf,
1778#endif
1779};
1780
1781static const struct video_device au0828_video_template = {
1782 .fops = &au0828_v4l_fops,
1783 .release = video_device_release,
1784 .ioctl_ops = &video_ioctl_ops,
Devin Heitmueller0ef210712009-03-11 03:00:53 -03001785 .tvnorms = V4L2_STD_NTSC_M,
1786 .current_norm = V4L2_STD_NTSC_M,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001787};
1788
1789/**************************************************************************/
1790
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001791int au0828_analog_register(struct au0828_dev *dev,
1792 struct usb_interface *interface)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001793{
1794 int retval = -ENOMEM;
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001795 struct usb_host_interface *iface_desc;
1796 struct usb_endpoint_descriptor *endpoint;
1797 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001798
1799 dprintk(1, "au0828_analog_register called!\n");
1800
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001801 /* set au0828 usb interface0 to as5 */
1802 retval = usb_set_interface(dev->usbdev,
Devin Heitmueller62899a22009-03-15 18:48:52 -03001803 interface->cur_altsetting->desc.bInterfaceNumber, 5);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001804 if (retval != 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001805 printk(KERN_INFO "Failure setting usb interface0 to as5\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001806 return retval;
1807 }
1808
1809 /* Figure out which endpoint has the isoc interface */
1810 iface_desc = interface->cur_altsetting;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001811 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001812 endpoint = &iface_desc->endpoint[i].desc;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001813 if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1814 == USB_DIR_IN) &&
1815 ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1816 == USB_ENDPOINT_XFER_ISOC)) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001817
1818 /* we find our isoc in endpoint */
1819 u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001820 dev->max_pkt_size = (tmp & 0x07ff) *
1821 (((tmp & 0x1800) >> 11) + 1);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001822 dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
1823 }
1824 }
Devin Heitmueller62899a22009-03-15 18:48:52 -03001825 if (!(dev->isoc_in_endpointaddr)) {
1826 printk(KERN_INFO "Could not locate isoc endpoint\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001827 kfree(dev);
1828 return -ENODEV;
1829 }
1830
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001831 init_waitqueue_head(&dev->open);
1832 spin_lock_init(&dev->slock);
1833 mutex_init(&dev->lock);
1834
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001835 /* init video dma queues */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001836 INIT_LIST_HEAD(&dev->vidq.active);
1837 INIT_LIST_HEAD(&dev->vidq.queued);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001838 INIT_LIST_HEAD(&dev->vbiq.active);
1839 INIT_LIST_HEAD(&dev->vbiq.queued);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001840
1841 dev->width = NTSC_STD_W;
1842 dev->height = NTSC_STD_H;
1843 dev->field_size = dev->width * dev->height;
1844 dev->frame_size = dev->field_size << 1;
1845 dev->bytesperline = dev->width << 1;
1846 dev->ctrl_ainput = 0;
1847
1848 /* allocate and fill v4l2 video struct */
1849 dev->vdev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001850 if (NULL == dev->vdev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001851 dprintk(1, "Can't allocate video_device.\n");
1852 return -ENOMEM;
1853 }
1854
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001855 /* allocate the VBI struct */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001856 dev->vbi_dev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001857 if (NULL == dev->vbi_dev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001858 dprintk(1, "Can't allocate vbi_device.\n");
1859 kfree(dev->vdev);
1860 return -ENOMEM;
1861 }
1862
1863 /* Fill the video capture device struct */
1864 *dev->vdev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001865 dev->vdev->parent = &dev->usbdev->dev;
1866 strcpy(dev->vdev->name, "au0828a video");
1867
1868 /* Setup the VBI device */
1869 *dev->vbi_dev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001870 dev->vbi_dev->parent = &dev->usbdev->dev;
1871 strcpy(dev->vbi_dev->name, "au0828a vbi");
1872
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001873 /* Register the v4l2 device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001874 video_set_drvdata(dev->vdev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001875 retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1876 if (retval != 0) {
1877 dprintk(1, "unable to register video device (error = %d).\n",
1878 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001879 video_device_release(dev->vdev);
1880 return -ENODEV;
1881 }
1882
1883 /* Register the vbi device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001884 video_set_drvdata(dev->vbi_dev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001885 retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
1886 if (retval != 0) {
1887 dprintk(1, "unable to register vbi device (error = %d).\n",
1888 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001889 video_device_release(dev->vbi_dev);
1890 video_device_release(dev->vdev);
1891 return -ENODEV;
1892 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001893
Devin Heitmueller62899a22009-03-15 18:48:52 -03001894 dprintk(1, "%s completed!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001895
1896 return 0;
1897}
1898