blob: 20ba5915542f535dff61d78ac9e3a87e7614ec90 [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;
Dan Carpenterb5f59332010-07-23 07:09:20 -0300444 int bytesperline;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300445 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
Dan Carpenterb5f59332010-07-23 07:09:20 -0300467 bytesperline = dev->vbi_width;
468
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300469 if (dma_q->pos + len > buf->vb.size)
470 len = buf->vb.size - dma_q->pos;
471
472 startread = p;
473 startwrite = outp + (dma_q->pos / 2);
474
475 /* Make sure the bottom field populates the second half of the frame */
476 if (buf->top_field == 0)
477 startwrite += bytesperline * dev->vbi_height;
478
479 for (i = 0; i < len; i += 2)
480 startwrite[j++] = startread[i+1];
481
482 dma_q->pos += len;
483}
484
485
486/*
487 * video-buf generic routine to get the next available VBI buffer
488 */
489static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q,
490 struct au0828_buffer **buf)
491{
492 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq);
493 char *outp;
494
495 if (list_empty(&dma_q->active)) {
496 au0828_isocdbg("No active queue to serve\n");
497 dev->isoc_ctl.vbi_buf = NULL;
498 *buf = NULL;
499 return;
500 }
501
502 /* Get the next buffer */
503 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
504 /* Cleans up buffer - Usefull for testing for frame/URB loss */
505 outp = videobuf_to_vmalloc(&(*buf)->vb);
506 memset(outp, 0x00, (*buf)->vb.size);
507
508 dev->isoc_ctl.vbi_buf = *buf;
509
510 return;
511}
512
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300513/*
514 * Controls the isoc copy of each urb packet
515 */
516static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
517{
518 struct au0828_buffer *buf;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300519 struct au0828_buffer *vbi_buf;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300520 struct au0828_dmaqueue *dma_q = urb->context;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300521 struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300522 unsigned char *outp = NULL;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300523 unsigned char *vbioutp = NULL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300524 int i, len = 0, rc = 1;
525 unsigned char *p;
526 unsigned char fbyte;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300527 unsigned int vbi_field_size;
528 unsigned int remain, lencopy;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300529
530 if (!dev)
531 return 0;
532
533 if ((dev->dev_state & DEV_DISCONNECTED) ||
534 (dev->dev_state & DEV_MISCONFIGURED))
535 return 0;
536
537 if (urb->status < 0) {
538 print_err_status(dev, -1, urb->status);
539 if (urb->status == -ENOENT)
540 return 0;
541 }
542
543 buf = dev->isoc_ctl.buf;
544 if (buf != NULL)
545 outp = videobuf_to_vmalloc(&buf->vb);
546
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300547 vbi_buf = dev->isoc_ctl.vbi_buf;
548 if (vbi_buf != NULL)
549 vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
550
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300551 for (i = 0; i < urb->number_of_packets; i++) {
552 int status = urb->iso_frame_desc[i].status;
553
554 if (status < 0) {
555 print_err_status(dev, i, status);
556 if (urb->iso_frame_desc[i].status != -EPROTO)
557 continue;
558 }
559
Devin Heitmueller62899a22009-03-15 18:48:52 -0300560 if (urb->iso_frame_desc[i].actual_length <= 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300561 continue;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300562
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300563 if (urb->iso_frame_desc[i].actual_length >
564 dev->max_pkt_size) {
565 au0828_isocdbg("packet bigger than packet size");
566 continue;
567 }
568
569 p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
570 fbyte = p[0];
571 len = urb->iso_frame_desc[i].actual_length - 4;
572 p += 4;
573
574 if (fbyte & 0x80) {
575 len -= 4;
576 p += 4;
577 au0828_isocdbg("Video frame %s\n",
578 (fbyte & 0x40) ? "odd" : "even");
Devin Heitmuellerbde3bb92010-07-05 13:05:16 -0300579 if (fbyte & 0x40) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300580 /* VBI */
581 if (vbi_buf != NULL)
582 vbi_buffer_filled(dev,
583 vbi_dma_q,
584 vbi_buf);
585 vbi_get_next_buf(vbi_dma_q, &vbi_buf);
586 if (vbi_buf == NULL)
587 vbioutp = NULL;
588 else
589 vbioutp = videobuf_to_vmalloc(
590 &vbi_buf->vb);
591
592 /* Video */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300593 if (buf != NULL)
594 buffer_filled(dev, dma_q, buf);
595 get_next_buf(dma_q, &buf);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300596 if (buf == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300597 outp = NULL;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300598 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300599 outp = videobuf_to_vmalloc(&buf->vb);
600 }
601
602 if (buf != NULL) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300603 if (fbyte & 0x40)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300604 buf->top_field = 1;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300605 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300606 buf->top_field = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300607 }
608
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300609 if (vbi_buf != NULL) {
610 if (fbyte & 0x40)
611 vbi_buf->top_field = 1;
612 else
613 vbi_buf->top_field = 0;
614 }
615
616 dev->vbi_read = 0;
617 vbi_dma_q->pos = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300618 dma_q->pos = 0;
619 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300620
621 vbi_field_size = dev->vbi_width * dev->vbi_height * 2;
622 if (dev->vbi_read < vbi_field_size) {
623 remain = vbi_field_size - dev->vbi_read;
624 if (len < remain)
625 lencopy = len;
626 else
627 lencopy = remain;
628
629 if (vbi_buf != NULL)
630 au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
631 vbioutp, len);
632
633 len -= lencopy;
634 p += lencopy;
635 dev->vbi_read += lencopy;
636 }
637
638 if (dev->vbi_read >= vbi_field_size && buf != NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300639 au0828_copy_video(dev, dma_q, buf, p, outp, len);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300640 }
641 return rc;
642}
643
644static int
645buffer_setup(struct videobuf_queue *vq, unsigned int *count,
646 unsigned int *size)
647{
648 struct au0828_fh *fh = vq->priv_data;
649 *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
650
651 if (0 == *count)
652 *count = AU0828_DEF_BUF;
653
654 if (*count < AU0828_MIN_BUF)
655 *count = AU0828_MIN_BUF;
656 return 0;
657}
658
659/* This is called *without* dev->slock held; please keep it that way */
660static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
661{
662 struct au0828_fh *fh = vq->priv_data;
663 struct au0828_dev *dev = fh->dev;
664 unsigned long flags = 0;
665 if (in_interrupt())
666 BUG();
667
668 /* We used to wait for the buffer to finish here, but this didn't work
669 because, as we were keeping the state as VIDEOBUF_QUEUED,
670 videobuf_queue_cancel marked it as finished for us.
671 (Also, it could wedge forever if the hardware was misconfigured.)
672
673 This should be safe; by the time we get here, the buffer isn't
674 queued anymore. If we ever start marking the buffers as
675 VIDEOBUF_ACTIVE, it won't be, though.
676 */
677 spin_lock_irqsave(&dev->slock, flags);
678 if (dev->isoc_ctl.buf == buf)
679 dev->isoc_ctl.buf = NULL;
680 spin_unlock_irqrestore(&dev->slock, flags);
681
682 videobuf_vmalloc_free(&buf->vb);
683 buf->vb.state = VIDEOBUF_NEEDS_INIT;
684}
685
686static int
687buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
688 enum v4l2_field field)
689{
690 struct au0828_fh *fh = vq->priv_data;
691 struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
692 struct au0828_dev *dev = fh->dev;
693 int rc = 0, urb_init = 0;
694
695 buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
696
697 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
698 return -EINVAL;
699
700 buf->vb.width = dev->width;
701 buf->vb.height = dev->height;
702 buf->vb.field = field;
703
704 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
705 rc = videobuf_iolock(vq, &buf->vb, NULL);
706 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300707 printk(KERN_INFO "videobuf_iolock failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300708 goto fail;
709 }
710 }
711
712 if (!dev->isoc_ctl.num_bufs)
713 urb_init = 1;
714
715 if (urb_init) {
716 rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,
717 AU0828_MAX_ISO_BUFS, dev->max_pkt_size,
718 au0828_isoc_copy);
719 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300720 printk(KERN_INFO "au0828_init_isoc failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300721 goto fail;
722 }
723 }
724
725 buf->vb.state = VIDEOBUF_PREPARED;
726 return 0;
727
728fail:
729 free_buffer(vq, buf);
730 return rc;
731}
732
733static void
734buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
735{
736 struct au0828_buffer *buf = container_of(vb,
737 struct au0828_buffer,
738 vb);
739 struct au0828_fh *fh = vq->priv_data;
740 struct au0828_dev *dev = fh->dev;
741 struct au0828_dmaqueue *vidq = &dev->vidq;
742
743 buf->vb.state = VIDEOBUF_QUEUED;
744 list_add_tail(&buf->vb.queue, &vidq->active);
745}
746
747static void buffer_release(struct videobuf_queue *vq,
748 struct videobuf_buffer *vb)
749{
750 struct au0828_buffer *buf = container_of(vb,
751 struct au0828_buffer,
752 vb);
753
754 free_buffer(vq, buf);
755}
756
757static struct videobuf_queue_ops au0828_video_qops = {
758 .buf_setup = buffer_setup,
759 .buf_prepare = buffer_prepare,
760 .buf_queue = buffer_queue,
761 .buf_release = buffer_release,
762};
763
764/* ------------------------------------------------------------------
765 V4L2 interface
766 ------------------------------------------------------------------*/
767
768static int au0828_i2s_init(struct au0828_dev *dev)
769{
770 /* Enable i2s mode */
771 au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);
772 return 0;
773}
774
775/*
776 * Auvitek au0828 analog stream enable
777 * Please set interface0 to AS5 before enable the stream
778 */
779int au0828_analog_stream_enable(struct au0828_dev *d)
780{
781 dprintk(1, "au0828_analog_stream_enable called\n");
782 au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
783 au0828_writereg(d, 0x106, 0x00);
784 /* set x position */
785 au0828_writereg(d, 0x110, 0x00);
786 au0828_writereg(d, 0x111, 0x00);
787 au0828_writereg(d, 0x114, 0xa0);
788 au0828_writereg(d, 0x115, 0x05);
789 /* set y position */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300790 au0828_writereg(d, 0x112, 0x00);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300791 au0828_writereg(d, 0x113, 0x00);
792 au0828_writereg(d, 0x116, 0xf2);
793 au0828_writereg(d, 0x117, 0x00);
794 au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
795
796 return 0;
797}
798
799int au0828_analog_stream_disable(struct au0828_dev *d)
800{
801 dprintk(1, "au0828_analog_stream_disable called\n");
802 au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
803 return 0;
804}
805
806void au0828_analog_stream_reset(struct au0828_dev *dev)
807{
808 dprintk(1, "au0828_analog_stream_reset called\n");
809 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
810 mdelay(30);
811 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);
812}
813
814/*
815 * Some operations needs to stop current streaming
816 */
817static int au0828_stream_interrupt(struct au0828_dev *dev)
818{
819 int ret = 0;
820
821 dev->stream_state = STREAM_INTERRUPT;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300822 if (dev->dev_state == DEV_DISCONNECTED)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300823 return -ENODEV;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300824 else if (ret) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300825 dev->dev_state = DEV_MISCONFIGURED;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300826 dprintk(1, "%s device is misconfigured!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300827 return ret;
828 }
829 return 0;
830}
831
832/*
833 * au0828_release_resources
834 * unregister v4l2 devices
835 */
836void au0828_analog_unregister(struct au0828_dev *dev)
837{
838 dprintk(1, "au0828_release_resources called\n");
839 mutex_lock(&au0828_sysfs_lock);
840
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200841 if (dev->vdev)
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300842 video_unregister_device(dev->vdev);
843 if (dev->vbi_dev)
844 video_unregister_device(dev->vbi_dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300845
846 mutex_unlock(&au0828_sysfs_lock);
847}
848
849
850/* Usage lock check functions */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300851static int res_get(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300852{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300853 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300854
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300855 if (fh->resources & bit)
856 /* have it already allocated */
857 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300858
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300859 /* is it free? */
860 mutex_lock(&dev->lock);
861 if (dev->resources & bit) {
862 /* no, someone else uses it */
863 mutex_unlock(&dev->lock);
864 return 0;
865 }
866 /* it's free, grab it */
867 fh->resources |= bit;
868 dev->resources |= bit;
869 dprintk(1, "res: get %d\n", bit);
870 mutex_unlock(&dev->lock);
871 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300872}
873
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300874static int res_check(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300875{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300876 return fh->resources & bit;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300877}
878
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300879static int res_locked(struct au0828_dev *dev, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300880{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300881 return dev->resources & bit;
882}
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300883
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300884static void res_free(struct au0828_fh *fh, unsigned int bits)
885{
886 struct au0828_dev *dev = fh->dev;
887
888 BUG_ON((fh->resources & bits) != bits);
889
890 mutex_lock(&dev->lock);
891 fh->resources &= ~bits;
892 dev->resources &= ~bits;
893 dprintk(1, "res: put %d\n", bits);
894 mutex_unlock(&dev->lock);
895}
896
897static int get_ressource(struct au0828_fh *fh)
898{
899 switch (fh->type) {
900 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
901 return AU0828_RESOURCE_VIDEO;
902 case V4L2_BUF_TYPE_VBI_CAPTURE:
903 return AU0828_RESOURCE_VBI;
904 default:
905 BUG();
906 return 0;
907 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300908}
909
910static int au0828_v4l2_open(struct file *filp)
911{
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300912 int ret = 0;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300913 struct video_device *vdev = video_devdata(filp);
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200914 struct au0828_dev *dev = video_drvdata(filp);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300915 struct au0828_fh *fh;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300916 int type;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300917
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300918 switch (vdev->vfl_type) {
919 case VFL_TYPE_GRABBER:
920 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
921 break;
922 case VFL_TYPE_VBI:
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200923 type = V4L2_BUF_TYPE_VBI_CAPTURE;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300924 break;
925 default:
926 return -EINVAL;
927 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300928
929 fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300930 if (NULL == fh) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300931 dprintk(1, "Failed allocate au0828_fh struct!\n");
932 return -ENOMEM;
933 }
934
935 fh->type = type;
936 fh->dev = dev;
937 filp->private_data = fh;
938
Devin Heitmueller62899a22009-03-15 18:48:52 -0300939 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300940 /* set au0828 interface0 to AS5 here again */
941 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300942 if (ret < 0) {
943 printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300944 return -EBUSY;
945 }
946 dev->width = NTSC_STD_W;
947 dev->height = NTSC_STD_H;
948 dev->frame_size = dev->width * dev->height * 2;
949 dev->field_size = dev->width * dev->height;
950 dev->bytesperline = dev->width * 2;
951
952 au0828_analog_stream_enable(dev);
953 au0828_analog_stream_reset(dev);
954
955 /* If we were doing ac97 instead of i2s, it would go here...*/
956 au0828_i2s_init(dev);
957
958 dev->stream_state = STREAM_OFF;
959 dev->dev_state |= DEV_INITIALIZED;
960 }
961
962 dev->users++;
963
964 videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300965 NULL, &dev->slock,
966 V4L2_BUF_TYPE_VIDEO_CAPTURE,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300967 V4L2_FIELD_INTERLACED,
Hans Verkuil08bff032010-09-20 17:39:46 -0300968 sizeof(struct au0828_buffer), fh, NULL);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300969
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300970 /* VBI Setup */
971 dev->vbi_width = 720;
972 dev->vbi_height = 1;
973 videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops,
974 NULL, &dev->slock,
975 V4L2_BUF_TYPE_VBI_CAPTURE,
976 V4L2_FIELD_SEQ_TB,
Hans Verkuil08bff032010-09-20 17:39:46 -0300977 sizeof(struct au0828_buffer), fh, NULL);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300978
979
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300980 return ret;
981}
982
983static int au0828_v4l2_close(struct file *filp)
984{
985 int ret;
986 struct au0828_fh *fh = filp->private_data;
987 struct au0828_dev *dev = fh->dev;
988
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300989 if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
990 videobuf_stop(&fh->vb_vidq);
991 res_free(fh, AU0828_RESOURCE_VIDEO);
992 }
993
994 if (res_check(fh, AU0828_RESOURCE_VBI)) {
995 videobuf_stop(&fh->vb_vbiq);
996 res_free(fh, AU0828_RESOURCE_VBI);
997 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300998
Devin Heitmueller62899a22009-03-15 18:48:52 -0300999 if (dev->users == 1) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001000 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001001 au0828_analog_unregister(dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001002 kfree(dev);
1003 return 0;
1004 }
1005
1006 au0828_analog_stream_disable(dev);
1007
1008 au0828_uninit_isoc(dev);
1009
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001010 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -03001011 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001012
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001013 /* When close the device, set the usb intf0 into alt0 to free
1014 USB bandwidth */
1015 ret = usb_set_interface(dev->usbdev, 0, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001016 if (ret < 0)
1017 printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001018 }
1019
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001020 videobuf_mmap_free(&fh->vb_vidq);
1021 videobuf_mmap_free(&fh->vb_vbiq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001022 kfree(fh);
1023 dev->users--;
1024 wake_up_interruptible_nr(&dev->open, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001025 return 0;
1026}
1027
1028static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
1029 size_t count, loff_t *pos)
1030{
1031 struct au0828_fh *fh = filp->private_data;
1032 struct au0828_dev *dev = fh->dev;
1033 int rc;
1034
1035 rc = check_dev(dev);
1036 if (rc < 0)
1037 return rc;
1038
Devin Heitmueller62899a22009-03-15 18:48:52 -03001039 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001040 if (res_locked(dev, AU0828_RESOURCE_VIDEO))
1041 return -EBUSY;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001042
1043 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
1044 filp->f_flags & O_NONBLOCK);
1045 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001046
1047 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1048 if (!res_get(fh, AU0828_RESOURCE_VBI))
1049 return -EBUSY;
1050
1051 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
1052 filp->f_flags & O_NONBLOCK);
1053 }
1054
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001055 return 0;
1056}
1057
1058static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
1059{
1060 struct au0828_fh *fh = filp->private_data;
1061 struct au0828_dev *dev = fh->dev;
1062 int rc;
1063
1064 rc = check_dev(dev);
1065 if (rc < 0)
1066 return rc;
1067
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001068 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1069 if (!res_get(fh, AU0828_RESOURCE_VIDEO))
1070 return POLLERR;
1071 return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
1072 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1073 if (!res_get(fh, AU0828_RESOURCE_VBI))
1074 return POLLERR;
1075 return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
1076 } else {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001077 return POLLERR;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001078 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001079}
1080
1081static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
1082{
1083 struct au0828_fh *fh = filp->private_data;
1084 struct au0828_dev *dev = fh->dev;
1085 int rc;
1086
1087 rc = check_dev(dev);
1088 if (rc < 0)
1089 return rc;
1090
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001091 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1092 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
1093 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1094 rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001095
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001096 return rc;
1097}
1098
1099static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
1100 struct v4l2_format *format)
1101{
1102 int ret;
1103 int width = format->fmt.pix.width;
1104 int height = format->fmt.pix.height;
1105 unsigned int maxwidth, maxheight;
1106
1107 maxwidth = 720;
1108 maxheight = 480;
1109
Devin Heitmueller62899a22009-03-15 18:48:52 -03001110 if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001111 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001112
1113 /* If they are demanding a format other than the one we support,
1114 bail out (tvtime asks for UYVY and then retries with YUYV) */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001115 if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001116 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001117
1118 /* format->fmt.pix.width only support 720 and height 480 */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001119 if (width != 720)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001120 width = 720;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001121 if (height != 480)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001122 height = 480;
1123
1124 format->fmt.pix.width = width;
1125 format->fmt.pix.height = height;
1126 format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1127 format->fmt.pix.bytesperline = width * 2;
1128 format->fmt.pix.sizeimage = width * height * 2;
1129 format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1130 format->fmt.pix.field = V4L2_FIELD_INTERLACED;
1131
Devin Heitmueller62899a22009-03-15 18:48:52 -03001132 if (cmd == VIDIOC_TRY_FMT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001133 return 0;
1134
1135 /* maybe set new image format, driver current only support 720*480 */
1136 dev->width = width;
1137 dev->height = height;
1138 dev->frame_size = width * height * 2;
1139 dev->field_size = width * height;
1140 dev->bytesperline = width * 2;
1141
Devin Heitmueller62899a22009-03-15 18:48:52 -03001142 if (dev->stream_state == STREAM_ON) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001143 dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
Devin Heitmueller62899a22009-03-15 18:48:52 -03001144 ret = au0828_stream_interrupt(dev);
1145 if (ret != 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001146 dprintk(1, "error interrupting video stream!\n");
1147 return ret;
1148 }
1149 }
1150
1151 /* set au0828 interface0 to AS5 here again */
1152 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001153 if (ret < 0) {
1154 printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001155 return -EBUSY;
1156 }
1157
1158 au0828_analog_stream_enable(dev);
1159
1160 return 0;
1161}
1162
1163
1164static int vidioc_queryctrl(struct file *file, void *priv,
1165 struct v4l2_queryctrl *qc)
1166{
1167 struct au0828_fh *fh = priv;
1168 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001169 v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001170 if (qc->type)
1171 return 0;
1172 else
1173 return -EINVAL;
1174}
1175
1176static int vidioc_querycap(struct file *file, void *priv,
1177 struct v4l2_capability *cap)
1178{
1179 struct au0828_fh *fh = priv;
1180 struct au0828_dev *dev = fh->dev;
1181
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001182 strlcpy(cap->driver, "au0828", sizeof(cap->driver));
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001183 strlcpy(cap->card, dev->board.name, sizeof(cap->card));
Devin Heitmuellerb14667f2009-03-11 03:01:04 -03001184 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001185
1186 cap->version = AU0828_VERSION_CODE;
1187
1188 /*set the device capabilities */
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001189 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001190 V4L2_CAP_VBI_CAPTURE |
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001191 V4L2_CAP_AUDIO |
1192 V4L2_CAP_READWRITE |
1193 V4L2_CAP_STREAMING |
1194 V4L2_CAP_TUNER;
1195 return 0;
1196}
1197
1198static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1199 struct v4l2_fmtdesc *f)
1200{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001201 if (f->index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001202 return -EINVAL;
1203
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001204 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1205 strcpy(f->description, "Packed YUV2");
1206
1207 f->flags = 0;
1208 f->pixelformat = V4L2_PIX_FMT_UYVY;
1209
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001210 return 0;
1211}
1212
1213static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1214 struct v4l2_format *f)
1215{
1216 struct au0828_fh *fh = priv;
1217 struct au0828_dev *dev = fh->dev;
1218
1219 f->fmt.pix.width = dev->width;
1220 f->fmt.pix.height = dev->height;
1221 f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1222 f->fmt.pix.bytesperline = dev->bytesperline;
1223 f->fmt.pix.sizeimage = dev->frame_size;
1224 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
1225 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
1226 return 0;
1227}
1228
1229static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1230 struct v4l2_format *f)
1231{
1232 struct au0828_fh *fh = priv;
1233 struct au0828_dev *dev = fh->dev;
1234
1235 return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
1236}
1237
1238static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1239 struct v4l2_format *f)
1240{
1241 struct au0828_fh *fh = priv;
1242 struct au0828_dev *dev = fh->dev;
1243 int rc;
1244
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001245 rc = check_dev(dev);
1246 if (rc < 0)
1247 return rc;
1248
1249 mutex_lock(&dev->lock);
1250
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001251 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001252 printk(KERN_INFO "%s queue busy\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001253 rc = -EBUSY;
1254 goto out;
1255 }
1256
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001257 rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001258out:
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001259 mutex_unlock(&dev->lock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001260 return rc;
1261}
1262
1263static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
1264{
1265 struct au0828_fh *fh = priv;
1266 struct au0828_dev *dev = fh->dev;
1267
1268 /* FIXME: when we support something other than NTSC, we are going to
1269 have to make the au0828 bridge adjust the size of its capture
1270 buffer, which is currently hardcoded at 720x480 */
1271
Hans Verkuilf41737e2009-04-01 03:52:39 -03001272 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001273 return 0;
1274}
1275
1276static int vidioc_enum_input(struct file *file, void *priv,
1277 struct v4l2_input *input)
1278{
1279 struct au0828_fh *fh = priv;
1280 struct au0828_dev *dev = fh->dev;
1281 unsigned int tmp;
1282
1283 static const char *inames[] = {
Devin Heitmueller3d622872009-03-15 17:48:26 -03001284 [AU0828_VMUX_UNDEFINED] = "Undefined",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001285 [AU0828_VMUX_COMPOSITE] = "Composite",
1286 [AU0828_VMUX_SVIDEO] = "S-Video",
1287 [AU0828_VMUX_CABLE] = "Cable TV",
1288 [AU0828_VMUX_TELEVISION] = "Television",
1289 [AU0828_VMUX_DVB] = "DVB",
1290 [AU0828_VMUX_DEBUG] = "tv debug"
1291 };
1292
1293 tmp = input->index;
1294
Dan Carpenterf5e20c32010-03-28 08:21:18 -03001295 if (tmp >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001296 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001297 if (AUVI_INPUT(tmp).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001298 return -EINVAL;
1299
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001300 input->index = tmp;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001301 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001302 if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
1303 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001304 input->type |= V4L2_INPUT_TYPE_TUNER;
1305 else
1306 input->type |= V4L2_INPUT_TYPE_CAMERA;
1307
1308 input->std = dev->vdev->tvnorms;
1309
1310 return 0;
1311}
1312
1313static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1314{
1315 struct au0828_fh *fh = priv;
1316 struct au0828_dev *dev = fh->dev;
1317 *i = dev->ctrl_input;
1318 return 0;
1319}
1320
1321static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1322{
1323 struct au0828_fh *fh = priv;
1324 struct au0828_dev *dev = fh->dev;
1325 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001326
Devin Heitmueller62899a22009-03-15 18:48:52 -03001327 dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001328 index);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001329 if (index >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001330 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001331 if (AUVI_INPUT(index).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001332 return -EINVAL;
1333 dev->ctrl_input = index;
1334
Devin Heitmueller62899a22009-03-15 18:48:52 -03001335 switch (AUVI_INPUT(index).type) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001336 case AU0828_VMUX_SVIDEO:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001337 dev->input_type = AU0828_VMUX_SVIDEO;
1338 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001339 case AU0828_VMUX_COMPOSITE:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001340 dev->input_type = AU0828_VMUX_COMPOSITE;
1341 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001342 case AU0828_VMUX_TELEVISION:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001343 dev->input_type = AU0828_VMUX_TELEVISION;
1344 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001345 default:
Devin Heitmuellera1094c42009-03-15 17:43:13 -03001346 dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
1347 AUVI_INPUT(index).type);
1348 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001349 }
1350
Hans Verkuil5325b422009-04-02 11:26:22 -03001351 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1352 AUVI_INPUT(index).vmux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001353
1354 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1355 int enable = 0;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001356 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001357 continue;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001358
1359 if (i == index)
1360 enable = 1;
1361 else
1362 enable = 0;
1363 if (enable) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001364 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001365 } else {
1366 /* Make sure we leave it turned on if some
1367 other input is routed to this callback */
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001368 if ((AUVI_INPUT(i).audio_setup) !=
1369 ((AUVI_INPUT(index).audio_setup))) {
1370 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001371 }
1372 }
1373 }
1374
Hans Verkuil5325b422009-04-02 11:26:22 -03001375 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1376 AUVI_INPUT(index).amux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001377 return 0;
1378}
1379
1380static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1381{
1382 struct au0828_fh *fh = priv;
1383 struct au0828_dev *dev = fh->dev;
1384 unsigned int index = a->index;
1385
Devin Heitmueller62899a22009-03-15 18:48:52 -03001386 if (a->index > 1)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001387 return -EINVAL;
1388
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001389 index = dev->ctrl_ainput;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001390 if (index == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001391 strcpy(a->name, "Television");
1392 else
1393 strcpy(a->name, "Line in");
1394
1395 a->capability = V4L2_AUDCAP_STEREO;
1396 a->index = index;
1397 return 0;
1398}
1399
1400static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
1401{
1402 struct au0828_fh *fh = priv;
1403 struct au0828_dev *dev = fh->dev;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001404 if (a->index != dev->ctrl_ainput)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001405 return -EINVAL;
1406 return 0;
1407}
1408
1409static int vidioc_g_ctrl(struct file *file, void *priv,
1410 struct v4l2_control *ctrl)
1411{
1412 struct au0828_fh *fh = priv;
1413 struct au0828_dev *dev = fh->dev;
1414
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001415 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001416 return 0;
1417
1418}
1419
1420static int vidioc_s_ctrl(struct file *file, void *priv,
1421 struct v4l2_control *ctrl)
1422{
1423 struct au0828_fh *fh = priv;
1424 struct au0828_dev *dev = fh->dev;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001425 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001426 return 0;
1427}
1428
1429static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
1430{
1431 struct au0828_fh *fh = priv;
1432 struct au0828_dev *dev = fh->dev;
1433
Devin Heitmueller62899a22009-03-15 18:48:52 -03001434 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001435 return -EINVAL;
1436
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001437 strcpy(t->name, "Auvitek tuner");
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001438 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001439 return 0;
1440}
1441
1442static int vidioc_s_tuner(struct file *file, void *priv,
1443 struct v4l2_tuner *t)
1444{
1445 struct au0828_fh *fh = priv;
1446 struct au0828_dev *dev = fh->dev;
1447
Devin Heitmueller62899a22009-03-15 18:48:52 -03001448 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001449 return -EINVAL;
1450
1451 t->type = V4L2_TUNER_ANALOG_TV;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001452 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001453 dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
1454 t->afc);
1455 return 0;
1456
1457}
1458
1459static int vidioc_g_frequency(struct file *file, void *priv,
1460 struct v4l2_frequency *freq)
1461{
1462 struct au0828_fh *fh = priv;
1463 struct au0828_dev *dev = fh->dev;
Devin Heitmuellerc8889232009-03-15 17:38:47 -03001464
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001465 freq->type = V4L2_TUNER_ANALOG_TV;
1466 freq->frequency = dev->ctrl_freq;
1467 return 0;
1468}
1469
1470static int vidioc_s_frequency(struct file *file, void *priv,
1471 struct v4l2_frequency *freq)
1472{
1473 struct au0828_fh *fh = priv;
1474 struct au0828_dev *dev = fh->dev;
1475
Devin Heitmueller62899a22009-03-15 18:48:52 -03001476 if (freq->tuner != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001477 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001478 if (freq->type != V4L2_TUNER_ANALOG_TV)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001479 return -EINVAL;
1480
1481 dev->ctrl_freq = freq->frequency;
1482
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001483 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001484
1485 au0828_analog_stream_reset(dev);
1486
1487 return 0;
1488}
1489
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001490
1491/* RAW VBI ioctls */
1492
1493static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1494 struct v4l2_format *format)
1495{
1496 struct au0828_fh *fh = priv;
1497 struct au0828_dev *dev = fh->dev;
1498
1499 format->fmt.vbi.samples_per_line = dev->vbi_width;
1500 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1501 format->fmt.vbi.offset = 0;
1502 format->fmt.vbi.flags = 0;
1503 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1504
1505 format->fmt.vbi.count[0] = dev->vbi_height;
1506 format->fmt.vbi.count[1] = dev->vbi_height;
1507 format->fmt.vbi.start[0] = 21;
1508 format->fmt.vbi.start[1] = 284;
1509
1510 return 0;
1511}
1512
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001513static int vidioc_g_chip_ident(struct file *file, void *priv,
1514 struct v4l2_dbg_chip_ident *chip)
1515{
1516 struct au0828_fh *fh = priv;
1517 struct au0828_dev *dev = fh->dev;
1518 chip->ident = V4L2_IDENT_NONE;
1519 chip->revision = 0;
1520
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001521 if (v4l2_chip_match_host(&chip->match)) {
1522 chip->ident = V4L2_IDENT_AU0828;
1523 return 0;
1524 }
1525
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001526 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001527 if (chip->ident == V4L2_IDENT_NONE)
1528 return -EINVAL;
1529
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001530 return 0;
1531}
1532
1533static int vidioc_cropcap(struct file *file, void *priv,
1534 struct v4l2_cropcap *cc)
1535{
1536 struct au0828_fh *fh = priv;
1537 struct au0828_dev *dev = fh->dev;
1538
Devin Heitmueller62899a22009-03-15 18:48:52 -03001539 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001540 return -EINVAL;
1541
1542 cc->bounds.left = 0;
1543 cc->bounds.top = 0;
1544 cc->bounds.width = dev->width;
1545 cc->bounds.height = dev->height;
1546
1547 cc->defrect = cc->bounds;
1548
1549 cc->pixelaspect.numerator = 54;
1550 cc->pixelaspect.denominator = 59;
1551
1552 return 0;
1553}
1554
1555static int vidioc_streamon(struct file *file, void *priv,
1556 enum v4l2_buf_type type)
1557{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001558 struct au0828_fh *fh = priv;
1559 struct au0828_dev *dev = fh->dev;
1560 int rc = -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001561
1562 rc = check_dev(dev);
1563 if (rc < 0)
1564 return rc;
1565
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001566 if (unlikely(type != fh->type))
1567 return -EINVAL;
1568
1569 dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
1570 fh, type, fh->resources, dev->resources);
1571
1572 if (unlikely(!res_get(fh, get_ressource(fh))))
1573 return -EBUSY;
1574
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001575 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1576 au0828_analog_stream_enable(dev);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001577 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001578 }
1579
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001580 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001581 rc = videobuf_streamon(&fh->vb_vidq);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001582 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1583 rc = videobuf_streamon(&fh->vb_vbiq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001584
1585 return rc;
1586}
1587
1588static int vidioc_streamoff(struct file *file, void *priv,
1589 enum v4l2_buf_type type)
1590{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001591 struct au0828_fh *fh = priv;
1592 struct au0828_dev *dev = fh->dev;
1593 int rc;
1594 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001595
1596 rc = check_dev(dev);
1597 if (rc < 0)
1598 return rc;
1599
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001600 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1601 fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001602 return -EINVAL;
1603 if (type != fh->type)
1604 return -EINVAL;
1605
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001606 dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
1607 fh, type, fh->resources, dev->resources);
1608
1609 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001610 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001611 rc = au0828_stream_interrupt(dev);
1612 if (rc != 0)
1613 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001614
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001615 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1616 if (AUVI_INPUT(i).audio_setup == NULL)
1617 continue;
1618 (AUVI_INPUT(i).audio_setup)(dev, 0);
1619 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001620
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001621 videobuf_streamoff(&fh->vb_vidq);
1622 res_free(fh, AU0828_RESOURCE_VIDEO);
1623 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1624 videobuf_streamoff(&fh->vb_vbiq);
1625 res_free(fh, AU0828_RESOURCE_VBI);
1626 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001627
1628 return 0;
1629}
1630
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001631#ifdef CONFIG_VIDEO_ADV_DEBUG
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001632static int vidioc_g_register(struct file *file, void *priv,
1633 struct v4l2_dbg_register *reg)
1634{
1635 struct au0828_fh *fh = priv;
1636 struct au0828_dev *dev = fh->dev;
1637
1638 switch (reg->match.type) {
1639 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001640 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001641 return 0;
1642 default:
1643 return -EINVAL;
1644 }
1645}
1646
1647static int vidioc_s_register(struct file *file, void *priv,
1648 struct v4l2_dbg_register *reg)
1649{
1650 struct au0828_fh *fh = priv;
1651 struct au0828_dev *dev = fh->dev;
1652
1653 switch (reg->match.type) {
1654 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001655 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001656 return 0;
1657 default:
1658 return -EINVAL;
1659 }
1660 return 0;
1661}
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001662#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001663
1664static int vidioc_reqbufs(struct file *file, void *priv,
1665 struct v4l2_requestbuffers *rb)
1666{
1667 struct au0828_fh *fh = priv;
1668 struct au0828_dev *dev = fh->dev;
1669 int rc;
1670
1671 rc = check_dev(dev);
1672 if (rc < 0)
1673 return rc;
1674
1675 return videobuf_reqbufs(&fh->vb_vidq, rb);
1676}
1677
1678static int vidioc_querybuf(struct file *file, void *priv,
1679 struct v4l2_buffer *b)
1680{
1681 struct au0828_fh *fh = priv;
1682 struct au0828_dev *dev = fh->dev;
1683 int rc;
1684
1685 rc = check_dev(dev);
1686 if (rc < 0)
1687 return rc;
1688
1689 return videobuf_querybuf(&fh->vb_vidq, b);
1690}
1691
1692static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1693{
1694 struct au0828_fh *fh = priv;
1695 struct au0828_dev *dev = fh->dev;
1696 int rc;
1697
1698 rc = check_dev(dev);
1699 if (rc < 0)
1700 return rc;
1701
1702 return videobuf_qbuf(&fh->vb_vidq, b);
1703}
1704
1705static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1706{
1707 struct au0828_fh *fh = priv;
1708 struct au0828_dev *dev = fh->dev;
1709 int rc;
1710
1711 rc = check_dev(dev);
1712 if (rc < 0)
1713 return rc;
1714
1715 /* Workaround for a bug in the au0828 hardware design that sometimes
1716 results in the colorspace being inverted */
1717 if (dev->greenscreen_detected == 1) {
1718 dprintk(1, "Detected green frame. Resetting stream...\n");
1719 au0828_analog_stream_reset(dev);
1720 dev->greenscreen_detected = 0;
1721 }
1722
1723 return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1724}
1725
1726#ifdef CONFIG_VIDEO_V4L1_COMPAT
1727static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
1728{
1729 struct au0828_fh *fh = priv;
1730
1731 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
1732}
1733#endif
1734
1735static struct v4l2_file_operations au0828_v4l_fops = {
1736 .owner = THIS_MODULE,
1737 .open = au0828_v4l2_open,
1738 .release = au0828_v4l2_close,
1739 .read = au0828_v4l2_read,
1740 .poll = au0828_v4l2_poll,
1741 .mmap = au0828_v4l2_mmap,
1742 .ioctl = video_ioctl2,
1743};
1744
1745static const struct v4l2_ioctl_ops video_ioctl_ops = {
1746 .vidioc_querycap = vidioc_querycap,
1747 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1748 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1749 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1750 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001751 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001752 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001753 .vidioc_g_audio = vidioc_g_audio,
1754 .vidioc_s_audio = vidioc_s_audio,
1755 .vidioc_cropcap = vidioc_cropcap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001756 .vidioc_reqbufs = vidioc_reqbufs,
1757 .vidioc_querybuf = vidioc_querybuf,
1758 .vidioc_qbuf = vidioc_qbuf,
1759 .vidioc_dqbuf = vidioc_dqbuf,
1760 .vidioc_s_std = vidioc_s_std,
1761 .vidioc_enum_input = vidioc_enum_input,
1762 .vidioc_g_input = vidioc_g_input,
1763 .vidioc_s_input = vidioc_s_input,
1764 .vidioc_queryctrl = vidioc_queryctrl,
1765 .vidioc_g_ctrl = vidioc_g_ctrl,
1766 .vidioc_s_ctrl = vidioc_s_ctrl,
1767 .vidioc_streamon = vidioc_streamon,
1768 .vidioc_streamoff = vidioc_streamoff,
1769 .vidioc_g_tuner = vidioc_g_tuner,
1770 .vidioc_s_tuner = vidioc_s_tuner,
1771 .vidioc_g_frequency = vidioc_g_frequency,
1772 .vidioc_s_frequency = vidioc_s_frequency,
1773#ifdef CONFIG_VIDEO_ADV_DEBUG
1774 .vidioc_g_register = vidioc_g_register,
1775 .vidioc_s_register = vidioc_s_register,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001776#endif
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001777 .vidioc_g_chip_ident = vidioc_g_chip_ident,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001778#ifdef CONFIG_VIDEO_V4L1_COMPAT
1779 .vidiocgmbuf = vidiocgmbuf,
1780#endif
1781};
1782
1783static const struct video_device au0828_video_template = {
1784 .fops = &au0828_v4l_fops,
1785 .release = video_device_release,
1786 .ioctl_ops = &video_ioctl_ops,
Devin Heitmueller0ef210712009-03-11 03:00:53 -03001787 .tvnorms = V4L2_STD_NTSC_M,
1788 .current_norm = V4L2_STD_NTSC_M,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001789};
1790
1791/**************************************************************************/
1792
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001793int au0828_analog_register(struct au0828_dev *dev,
1794 struct usb_interface *interface)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001795{
1796 int retval = -ENOMEM;
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001797 struct usb_host_interface *iface_desc;
1798 struct usb_endpoint_descriptor *endpoint;
1799 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001800
1801 dprintk(1, "au0828_analog_register called!\n");
1802
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001803 /* set au0828 usb interface0 to as5 */
1804 retval = usb_set_interface(dev->usbdev,
Devin Heitmueller62899a22009-03-15 18:48:52 -03001805 interface->cur_altsetting->desc.bInterfaceNumber, 5);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001806 if (retval != 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001807 printk(KERN_INFO "Failure setting usb interface0 to as5\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001808 return retval;
1809 }
1810
1811 /* Figure out which endpoint has the isoc interface */
1812 iface_desc = interface->cur_altsetting;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001813 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001814 endpoint = &iface_desc->endpoint[i].desc;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001815 if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1816 == USB_DIR_IN) &&
1817 ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1818 == USB_ENDPOINT_XFER_ISOC)) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001819
1820 /* we find our isoc in endpoint */
1821 u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001822 dev->max_pkt_size = (tmp & 0x07ff) *
1823 (((tmp & 0x1800) >> 11) + 1);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001824 dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
1825 }
1826 }
Devin Heitmueller62899a22009-03-15 18:48:52 -03001827 if (!(dev->isoc_in_endpointaddr)) {
1828 printk(KERN_INFO "Could not locate isoc endpoint\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001829 kfree(dev);
1830 return -ENODEV;
1831 }
1832
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001833 init_waitqueue_head(&dev->open);
1834 spin_lock_init(&dev->slock);
1835 mutex_init(&dev->lock);
1836
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001837 /* init video dma queues */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001838 INIT_LIST_HEAD(&dev->vidq.active);
1839 INIT_LIST_HEAD(&dev->vidq.queued);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001840 INIT_LIST_HEAD(&dev->vbiq.active);
1841 INIT_LIST_HEAD(&dev->vbiq.queued);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001842
1843 dev->width = NTSC_STD_W;
1844 dev->height = NTSC_STD_H;
1845 dev->field_size = dev->width * dev->height;
1846 dev->frame_size = dev->field_size << 1;
1847 dev->bytesperline = dev->width << 1;
1848 dev->ctrl_ainput = 0;
1849
1850 /* allocate and fill v4l2 video struct */
1851 dev->vdev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001852 if (NULL == dev->vdev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001853 dprintk(1, "Can't allocate video_device.\n");
1854 return -ENOMEM;
1855 }
1856
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001857 /* allocate the VBI struct */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001858 dev->vbi_dev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001859 if (NULL == dev->vbi_dev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001860 dprintk(1, "Can't allocate vbi_device.\n");
1861 kfree(dev->vdev);
1862 return -ENOMEM;
1863 }
1864
1865 /* Fill the video capture device struct */
1866 *dev->vdev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001867 dev->vdev->parent = &dev->usbdev->dev;
1868 strcpy(dev->vdev->name, "au0828a video");
1869
1870 /* Setup the VBI device */
1871 *dev->vbi_dev = au0828_video_template;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001872 dev->vbi_dev->parent = &dev->usbdev->dev;
1873 strcpy(dev->vbi_dev->name, "au0828a vbi");
1874
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001875 /* Register the v4l2 device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001876 video_set_drvdata(dev->vdev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001877 retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1878 if (retval != 0) {
1879 dprintk(1, "unable to register video device (error = %d).\n",
1880 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001881 video_device_release(dev->vdev);
1882 return -ENODEV;
1883 }
1884
1885 /* Register the vbi device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02001886 video_set_drvdata(dev->vbi_dev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001887 retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
1888 if (retval != 0) {
1889 dprintk(1, "unable to register vbi device (error = %d).\n",
1890 retval);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001891 video_device_release(dev->vbi_dev);
1892 video_device_release(dev->vdev);
1893 return -ENODEV;
1894 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001895
Devin Heitmueller62899a22009-03-15 18:48:52 -03001896 dprintk(1, "%s completed!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001897
1898 return 0;
1899}
1900