blob: a90a0b9771b37b263b3ce0a561999df0b0b593e7 [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>
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030036#include <media/v4l2-common.h>
37#include <media/v4l2-ioctl.h>
Hans Verkuil83b09422013-02-15 09:14:00 -030038#include <media/v4l2-event.h>
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030039#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
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030046/* ------------------------------------------------------------------
47 Videobuf operations
48 ------------------------------------------------------------------*/
49
50static unsigned int isoc_debug;
51module_param(isoc_debug, int, 0644);
52MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
53
54#define au0828_isocdbg(fmt, arg...) \
55do {\
56 if (isoc_debug) { \
57 printk(KERN_INFO "au0828 %s :"fmt, \
58 __func__ , ##arg); \
59 } \
60 } while (0)
61
Hans Verkuilfa09cb92013-03-11 16:10:33 -030062static inline void i2c_gate_ctrl(struct au0828_dev *dev, int val)
63{
64 if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
65 dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, val);
66}
67
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030068static inline void print_err_status(struct au0828_dev *dev,
69 int packet, int status)
70{
71 char *errmsg = "Unknown";
72
73 switch (status) {
74 case -ENOENT:
75 errmsg = "unlinked synchronuously";
76 break;
77 case -ECONNRESET:
78 errmsg = "unlinked asynchronuously";
79 break;
80 case -ENOSR:
81 errmsg = "Buffer error (overrun)";
82 break;
83 case -EPIPE:
84 errmsg = "Stalled (device not responding)";
85 break;
86 case -EOVERFLOW:
87 errmsg = "Babble (bad cable?)";
88 break;
89 case -EPROTO:
90 errmsg = "Bit-stuff error (bad cable?)";
91 break;
92 case -EILSEQ:
93 errmsg = "CRC/Timeout (could be anything)";
94 break;
95 case -ETIME:
96 errmsg = "Device does not respond";
97 break;
98 }
99 if (packet < 0) {
100 au0828_isocdbg("URB status %d [%s].\n", status, errmsg);
101 } else {
102 au0828_isocdbg("URB packet %d, status %d [%s].\n",
103 packet, status, errmsg);
104 }
105}
106
107static int check_dev(struct au0828_dev *dev)
108{
109 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300110 printk(KERN_INFO "v4l2 ioctl: device not present\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300111 return -ENODEV;
112 }
113
114 if (dev->dev_state & DEV_MISCONFIGURED) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300115 printk(KERN_INFO "v4l2 ioctl: device is misconfigured; "
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300116 "close and open it again\n");
117 return -EIO;
118 }
119 return 0;
120}
121
122/*
123 * IRQ callback, called by URB callback
124 */
125static void au0828_irq_callback(struct urb *urb)
126{
127 struct au0828_dmaqueue *dma_q = urb->context;
128 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300129 unsigned long flags = 0;
Hans Verkuile92ba282012-05-14 10:17:35 -0300130 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300131
132 switch (urb->status) {
133 case 0: /* success */
134 case -ETIMEDOUT: /* NAK */
135 break;
136 case -ECONNRESET: /* kill */
137 case -ENOENT:
138 case -ESHUTDOWN:
139 au0828_isocdbg("au0828_irq_callback called: status kill\n");
140 return;
141 default: /* unknown error */
142 au0828_isocdbg("urb completition error %d.\n", urb->status);
143 break;
144 }
145
146 /* Copy data from URB */
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300147 spin_lock_irqsave(&dev->slock, flags);
Hans Verkuile92ba282012-05-14 10:17:35 -0300148 dev->isoc_ctl.isoc_copy(dev, urb);
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300149 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300150
151 /* Reset urb buffers */
152 for (i = 0; i < urb->number_of_packets; i++) {
153 urb->iso_frame_desc[i].status = 0;
154 urb->iso_frame_desc[i].actual_length = 0;
155 }
156 urb->status = 0;
157
158 urb->status = usb_submit_urb(urb, GFP_ATOMIC);
159 if (urb->status) {
160 au0828_isocdbg("urb resubmit failed (error=%i)\n",
161 urb->status);
162 }
163}
164
165/*
166 * Stop and Deallocate URBs
167 */
Mauro Carvalho Chehaba094ca42012-10-27 14:00:30 -0300168static void au0828_uninit_isoc(struct au0828_dev *dev)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300169{
170 struct urb *urb;
171 int i;
172
173 au0828_isocdbg("au0828: called au0828_uninit_isoc\n");
174
175 dev->isoc_ctl.nfields = -1;
176 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
177 urb = dev->isoc_ctl.urb[i];
178 if (urb) {
179 if (!irqs_disabled())
180 usb_kill_urb(urb);
181 else
182 usb_unlink_urb(urb);
183
184 if (dev->isoc_ctl.transfer_buffer[i]) {
Daniel Mack997ea582010-04-12 13:17:25 +0200185 usb_free_coherent(dev->usbdev,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300186 urb->transfer_buffer_length,
187 dev->isoc_ctl.transfer_buffer[i],
188 urb->transfer_dma);
189 }
190 usb_free_urb(urb);
191 dev->isoc_ctl.urb[i] = NULL;
192 }
193 dev->isoc_ctl.transfer_buffer[i] = NULL;
194 }
195
196 kfree(dev->isoc_ctl.urb);
197 kfree(dev->isoc_ctl.transfer_buffer);
198
199 dev->isoc_ctl.urb = NULL;
200 dev->isoc_ctl.transfer_buffer = NULL;
201 dev->isoc_ctl.num_bufs = 0;
202}
203
204/*
205 * Allocate URBs and start IRQ
206 */
Mauro Carvalho Chehaba094ca42012-10-27 14:00:30 -0300207static int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
208 int num_bufs, int max_pkt_size,
209 int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300210{
211 struct au0828_dmaqueue *dma_q = &dev->vidq;
212 int i;
213 int sb_size, pipe;
214 struct urb *urb;
215 int j, k;
216 int rc;
217
218 au0828_isocdbg("au0828: called au0828_prepare_isoc\n");
219
220 /* De-allocates all pending stuff */
221 au0828_uninit_isoc(dev);
222
223 dev->isoc_ctl.isoc_copy = isoc_copy;
224 dev->isoc_ctl.num_bufs = num_bufs;
225
226 dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
227 if (!dev->isoc_ctl.urb) {
228 au0828_isocdbg("cannot alloc memory for usb buffers\n");
229 return -ENOMEM;
230 }
231
232 dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
233 GFP_KERNEL);
234 if (!dev->isoc_ctl.transfer_buffer) {
235 au0828_isocdbg("cannot allocate memory for usb transfer\n");
236 kfree(dev->isoc_ctl.urb);
237 return -ENOMEM;
238 }
239
240 dev->isoc_ctl.max_pkt_size = max_pkt_size;
241 dev->isoc_ctl.buf = NULL;
242
243 sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
244
245 /* allocate urbs and transfer buffers */
246 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
247 urb = usb_alloc_urb(max_packets, GFP_KERNEL);
248 if (!urb) {
249 au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i);
250 au0828_uninit_isoc(dev);
251 return -ENOMEM;
252 }
253 dev->isoc_ctl.urb[i] = urb;
254
Daniel Mack997ea582010-04-12 13:17:25 +0200255 dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300256 sb_size, GFP_KERNEL, &urb->transfer_dma);
257 if (!dev->isoc_ctl.transfer_buffer[i]) {
258 printk("unable to allocate %i bytes for transfer"
259 " buffer %i%s\n",
260 sb_size, i,
261 in_interrupt() ? " while in int" : "");
262 au0828_uninit_isoc(dev);
263 return -ENOMEM;
264 }
265 memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
266
267 pipe = usb_rcvisocpipe(dev->usbdev,
268 dev->isoc_in_endpointaddr),
269
270 usb_fill_int_urb(urb, dev->usbdev, pipe,
271 dev->isoc_ctl.transfer_buffer[i], sb_size,
272 au0828_irq_callback, dma_q, 1);
273
274 urb->number_of_packets = max_packets;
Devin Heitmuellerfadadb72009-03-22 23:42:26 -0300275 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300276
277 k = 0;
278 for (j = 0; j < max_packets; j++) {
279 urb->iso_frame_desc[j].offset = k;
280 urb->iso_frame_desc[j].length =
281 dev->isoc_ctl.max_pkt_size;
282 k += dev->isoc_ctl.max_pkt_size;
283 }
284 }
285
286 init_waitqueue_head(&dma_q->wq);
287
288 /* submit urbs and enables IRQ */
289 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
290 rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
291 if (rc) {
292 au0828_isocdbg("submit of urb %i failed (error=%i)\n",
293 i, rc);
294 au0828_uninit_isoc(dev);
295 return rc;
296 }
297 }
298
299 return 0;
300}
301
302/*
303 * Announces that a buffer were filled and request the next
304 */
305static inline void buffer_filled(struct au0828_dev *dev,
306 struct au0828_dmaqueue *dma_q,
307 struct au0828_buffer *buf)
308{
309 /* Advice that buffer was filled */
310 au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
311
312 buf->vb.state = VIDEOBUF_DONE;
313 buf->vb.field_count++;
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300314 v4l2_get_timestamp(&buf->vb.ts);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300315
316 dev->isoc_ctl.buf = NULL;
317
318 list_del(&buf->vb.queue);
319 wake_up(&buf->vb.done);
320}
321
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300322static inline void vbi_buffer_filled(struct au0828_dev *dev,
323 struct au0828_dmaqueue *dma_q,
324 struct au0828_buffer *buf)
325{
326 /* Advice that buffer was filled */
327 au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
328
329 buf->vb.state = VIDEOBUF_DONE;
330 buf->vb.field_count++;
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300331 v4l2_get_timestamp(&buf->vb.ts);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300332
333 dev->isoc_ctl.vbi_buf = NULL;
334
335 list_del(&buf->vb.queue);
336 wake_up(&buf->vb.done);
337}
338
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300339/*
340 * Identify the buffer header type and properly handles
341 */
342static void au0828_copy_video(struct au0828_dev *dev,
343 struct au0828_dmaqueue *dma_q,
344 struct au0828_buffer *buf,
345 unsigned char *p,
346 unsigned char *outp, unsigned long len)
347{
348 void *fieldstart, *startwrite, *startread;
349 int linesdone, currlinedone, offset, lencopy, remain;
350 int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */
351
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300352 if (len == 0)
353 return;
354
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300355 if (dma_q->pos + len > buf->vb.size)
356 len = buf->vb.size - dma_q->pos;
357
358 startread = p;
359 remain = len;
360
361 /* Interlaces frame */
362 if (buf->top_field)
363 fieldstart = outp;
364 else
365 fieldstart = outp + bytesperline;
366
367 linesdone = dma_q->pos / bytesperline;
368 currlinedone = dma_q->pos % bytesperline;
369 offset = linesdone * bytesperline * 2 + currlinedone;
370 startwrite = fieldstart + offset;
371 lencopy = bytesperline - currlinedone;
372 lencopy = lencopy > remain ? remain : lencopy;
373
374 if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
375 au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
376 ((char *)startwrite + lencopy) -
377 ((char *)outp + buf->vb.size));
378 remain = (char *)outp + buf->vb.size - (char *)startwrite;
379 lencopy = remain;
380 }
381 if (lencopy <= 0)
382 return;
383 memcpy(startwrite, startread, lencopy);
384
385 remain -= lencopy;
386
387 while (remain > 0) {
388 startwrite += lencopy + bytesperline;
389 startread += lencopy;
390 if (bytesperline > remain)
391 lencopy = remain;
392 else
393 lencopy = bytesperline;
394
395 if ((char *)startwrite + lencopy > (char *)outp +
396 buf->vb.size) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300397 au0828_isocdbg("Overflow %zi bytes past buf end (2)\n",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300398 ((char *)startwrite + lencopy) -
399 ((char *)outp + buf->vb.size));
400 lencopy = remain = (char *)outp + buf->vb.size -
401 (char *)startwrite;
402 }
403 if (lencopy <= 0)
404 break;
405
406 memcpy(startwrite, startread, lencopy);
407
408 remain -= lencopy;
409 }
410
411 if (offset > 1440) {
412 /* We have enough data to check for greenscreen */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300413 if (outp[0] < 0x60 && outp[1440] < 0x60)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300414 dev->greenscreen_detected = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300415 }
416
417 dma_q->pos += len;
418}
419
420/*
421 * video-buf generic routine to get the next available buffer
422 */
423static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
424 struct au0828_buffer **buf)
425{
426 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
427
428 if (list_empty(&dma_q->active)) {
429 au0828_isocdbg("No active queue to serve\n");
430 dev->isoc_ctl.buf = NULL;
431 *buf = NULL;
432 return;
433 }
434
435 /* Get the next buffer */
436 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
437 dev->isoc_ctl.buf = *buf;
438
439 return;
440}
441
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300442static void au0828_copy_vbi(struct au0828_dev *dev,
443 struct au0828_dmaqueue *dma_q,
444 struct au0828_buffer *buf,
445 unsigned char *p,
446 unsigned char *outp, unsigned long len)
447{
448 unsigned char *startwrite, *startread;
Dan Carpenterb5f59332010-07-23 07:09:20 -0300449 int bytesperline;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300450 int i, j = 0;
451
452 if (dev == NULL) {
453 au0828_isocdbg("dev is null\n");
454 return;
455 }
456
457 if (dma_q == NULL) {
458 au0828_isocdbg("dma_q is null\n");
459 return;
460 }
461 if (buf == NULL)
462 return;
463 if (p == NULL) {
464 au0828_isocdbg("p is null\n");
465 return;
466 }
467 if (outp == NULL) {
468 au0828_isocdbg("outp is null\n");
469 return;
470 }
471
Dan Carpenterb5f59332010-07-23 07:09:20 -0300472 bytesperline = dev->vbi_width;
473
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300474 if (dma_q->pos + len > buf->vb.size)
475 len = buf->vb.size - dma_q->pos;
476
477 startread = p;
478 startwrite = outp + (dma_q->pos / 2);
479
480 /* Make sure the bottom field populates the second half of the frame */
481 if (buf->top_field == 0)
482 startwrite += bytesperline * dev->vbi_height;
483
484 for (i = 0; i < len; i += 2)
485 startwrite[j++] = startread[i+1];
486
487 dma_q->pos += len;
488}
489
490
491/*
492 * video-buf generic routine to get the next available VBI buffer
493 */
494static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q,
495 struct au0828_buffer **buf)
496{
497 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq);
498 char *outp;
499
500 if (list_empty(&dma_q->active)) {
501 au0828_isocdbg("No active queue to serve\n");
502 dev->isoc_ctl.vbi_buf = NULL;
503 *buf = NULL;
504 return;
505 }
506
507 /* Get the next buffer */
508 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300509 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300510 outp = videobuf_to_vmalloc(&(*buf)->vb);
511 memset(outp, 0x00, (*buf)->vb.size);
512
513 dev->isoc_ctl.vbi_buf = *buf;
514
515 return;
516}
517
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300518/*
519 * Controls the isoc copy of each urb packet
520 */
521static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
522{
523 struct au0828_buffer *buf;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300524 struct au0828_buffer *vbi_buf;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300525 struct au0828_dmaqueue *dma_q = urb->context;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300526 struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300527 unsigned char *outp = NULL;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300528 unsigned char *vbioutp = NULL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300529 int i, len = 0, rc = 1;
530 unsigned char *p;
531 unsigned char fbyte;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300532 unsigned int vbi_field_size;
533 unsigned int remain, lencopy;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300534
535 if (!dev)
536 return 0;
537
538 if ((dev->dev_state & DEV_DISCONNECTED) ||
539 (dev->dev_state & DEV_MISCONFIGURED))
540 return 0;
541
542 if (urb->status < 0) {
543 print_err_status(dev, -1, urb->status);
544 if (urb->status == -ENOENT)
545 return 0;
546 }
547
548 buf = dev->isoc_ctl.buf;
549 if (buf != NULL)
550 outp = videobuf_to_vmalloc(&buf->vb);
551
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300552 vbi_buf = dev->isoc_ctl.vbi_buf;
553 if (vbi_buf != NULL)
554 vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
555
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300556 for (i = 0; i < urb->number_of_packets; i++) {
557 int status = urb->iso_frame_desc[i].status;
558
559 if (status < 0) {
560 print_err_status(dev, i, status);
561 if (urb->iso_frame_desc[i].status != -EPROTO)
562 continue;
563 }
564
Devin Heitmueller62899a22009-03-15 18:48:52 -0300565 if (urb->iso_frame_desc[i].actual_length <= 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300566 continue;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300567
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300568 if (urb->iso_frame_desc[i].actual_length >
569 dev->max_pkt_size) {
570 au0828_isocdbg("packet bigger than packet size");
571 continue;
572 }
573
574 p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
575 fbyte = p[0];
576 len = urb->iso_frame_desc[i].actual_length - 4;
577 p += 4;
578
579 if (fbyte & 0x80) {
580 len -= 4;
581 p += 4;
582 au0828_isocdbg("Video frame %s\n",
583 (fbyte & 0x40) ? "odd" : "even");
Devin Heitmuellerbde3bb92010-07-05 13:05:16 -0300584 if (fbyte & 0x40) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300585 /* VBI */
586 if (vbi_buf != NULL)
587 vbi_buffer_filled(dev,
588 vbi_dma_q,
589 vbi_buf);
590 vbi_get_next_buf(vbi_dma_q, &vbi_buf);
591 if (vbi_buf == NULL)
592 vbioutp = NULL;
593 else
594 vbioutp = videobuf_to_vmalloc(
595 &vbi_buf->vb);
596
597 /* Video */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300598 if (buf != NULL)
599 buffer_filled(dev, dma_q, buf);
600 get_next_buf(dma_q, &buf);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300601 if (buf == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300602 outp = NULL;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300603 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300604 outp = videobuf_to_vmalloc(&buf->vb);
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300605
606 /* As long as isoc traffic is arriving, keep
607 resetting the timer */
608 if (dev->vid_timeout_running)
609 mod_timer(&dev->vid_timeout,
610 jiffies + (HZ / 10));
611 if (dev->vbi_timeout_running)
612 mod_timer(&dev->vbi_timeout,
613 jiffies + (HZ / 10));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300614 }
615
616 if (buf != NULL) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300617 if (fbyte & 0x40)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300618 buf->top_field = 1;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300619 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300620 buf->top_field = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300621 }
622
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300623 if (vbi_buf != NULL) {
624 if (fbyte & 0x40)
625 vbi_buf->top_field = 1;
626 else
627 vbi_buf->top_field = 0;
628 }
629
630 dev->vbi_read = 0;
631 vbi_dma_q->pos = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300632 dma_q->pos = 0;
633 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300634
635 vbi_field_size = dev->vbi_width * dev->vbi_height * 2;
636 if (dev->vbi_read < vbi_field_size) {
637 remain = vbi_field_size - dev->vbi_read;
638 if (len < remain)
639 lencopy = len;
640 else
641 lencopy = remain;
642
643 if (vbi_buf != NULL)
644 au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
645 vbioutp, len);
646
647 len -= lencopy;
648 p += lencopy;
649 dev->vbi_read += lencopy;
650 }
651
652 if (dev->vbi_read >= vbi_field_size && buf != NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300653 au0828_copy_video(dev, dma_q, buf, p, outp, len);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300654 }
655 return rc;
656}
657
658static int
659buffer_setup(struct videobuf_queue *vq, unsigned int *count,
660 unsigned int *size)
661{
662 struct au0828_fh *fh = vq->priv_data;
663 *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
664
665 if (0 == *count)
666 *count = AU0828_DEF_BUF;
667
668 if (*count < AU0828_MIN_BUF)
669 *count = AU0828_MIN_BUF;
670 return 0;
671}
672
673/* This is called *without* dev->slock held; please keep it that way */
674static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
675{
676 struct au0828_fh *fh = vq->priv_data;
677 struct au0828_dev *dev = fh->dev;
678 unsigned long flags = 0;
679 if (in_interrupt())
680 BUG();
681
682 /* We used to wait for the buffer to finish here, but this didn't work
683 because, as we were keeping the state as VIDEOBUF_QUEUED,
684 videobuf_queue_cancel marked it as finished for us.
685 (Also, it could wedge forever if the hardware was misconfigured.)
686
687 This should be safe; by the time we get here, the buffer isn't
688 queued anymore. If we ever start marking the buffers as
689 VIDEOBUF_ACTIVE, it won't be, though.
690 */
691 spin_lock_irqsave(&dev->slock, flags);
692 if (dev->isoc_ctl.buf == buf)
693 dev->isoc_ctl.buf = NULL;
694 spin_unlock_irqrestore(&dev->slock, flags);
695
696 videobuf_vmalloc_free(&buf->vb);
697 buf->vb.state = VIDEOBUF_NEEDS_INIT;
698}
699
700static int
701buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
702 enum v4l2_field field)
703{
704 struct au0828_fh *fh = vq->priv_data;
705 struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
706 struct au0828_dev *dev = fh->dev;
707 int rc = 0, urb_init = 0;
708
709 buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
710
711 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
712 return -EINVAL;
713
714 buf->vb.width = dev->width;
715 buf->vb.height = dev->height;
716 buf->vb.field = field;
717
718 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
719 rc = videobuf_iolock(vq, &buf->vb, NULL);
720 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300721 printk(KERN_INFO "videobuf_iolock failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300722 goto fail;
723 }
724 }
725
726 if (!dev->isoc_ctl.num_bufs)
727 urb_init = 1;
728
729 if (urb_init) {
730 rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,
731 AU0828_MAX_ISO_BUFS, dev->max_pkt_size,
732 au0828_isoc_copy);
733 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300734 printk(KERN_INFO "au0828_init_isoc failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300735 goto fail;
736 }
737 }
738
739 buf->vb.state = VIDEOBUF_PREPARED;
740 return 0;
741
742fail:
743 free_buffer(vq, buf);
744 return rc;
745}
746
747static void
748buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
749{
750 struct au0828_buffer *buf = container_of(vb,
751 struct au0828_buffer,
752 vb);
753 struct au0828_fh *fh = vq->priv_data;
754 struct au0828_dev *dev = fh->dev;
755 struct au0828_dmaqueue *vidq = &dev->vidq;
756
757 buf->vb.state = VIDEOBUF_QUEUED;
758 list_add_tail(&buf->vb.queue, &vidq->active);
759}
760
761static void buffer_release(struct videobuf_queue *vq,
762 struct videobuf_buffer *vb)
763{
764 struct au0828_buffer *buf = container_of(vb,
765 struct au0828_buffer,
766 vb);
767
768 free_buffer(vq, buf);
769}
770
771static struct videobuf_queue_ops au0828_video_qops = {
772 .buf_setup = buffer_setup,
773 .buf_prepare = buffer_prepare,
774 .buf_queue = buffer_queue,
775 .buf_release = buffer_release,
776};
777
778/* ------------------------------------------------------------------
779 V4L2 interface
780 ------------------------------------------------------------------*/
781
782static int au0828_i2s_init(struct au0828_dev *dev)
783{
784 /* Enable i2s mode */
785 au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);
786 return 0;
787}
788
789/*
790 * Auvitek au0828 analog stream enable
791 * Please set interface0 to AS5 before enable the stream
792 */
Mauro Carvalho Chehaba094ca42012-10-27 14:00:30 -0300793static int au0828_analog_stream_enable(struct au0828_dev *d)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300794{
795 dprintk(1, "au0828_analog_stream_enable called\n");
796 au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
797 au0828_writereg(d, 0x106, 0x00);
798 /* set x position */
799 au0828_writereg(d, 0x110, 0x00);
800 au0828_writereg(d, 0x111, 0x00);
801 au0828_writereg(d, 0x114, 0xa0);
802 au0828_writereg(d, 0x115, 0x05);
803 /* set y position */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300804 au0828_writereg(d, 0x112, 0x00);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300805 au0828_writereg(d, 0x113, 0x00);
806 au0828_writereg(d, 0x116, 0xf2);
807 au0828_writereg(d, 0x117, 0x00);
808 au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
809
810 return 0;
811}
812
813int au0828_analog_stream_disable(struct au0828_dev *d)
814{
815 dprintk(1, "au0828_analog_stream_disable called\n");
816 au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
817 return 0;
818}
819
Mauro Carvalho Chehaba094ca42012-10-27 14:00:30 -0300820static void au0828_analog_stream_reset(struct au0828_dev *dev)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300821{
822 dprintk(1, "au0828_analog_stream_reset called\n");
823 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
824 mdelay(30);
825 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);
826}
827
828/*
829 * Some operations needs to stop current streaming
830 */
831static int au0828_stream_interrupt(struct au0828_dev *dev)
832{
833 int ret = 0;
834
835 dev->stream_state = STREAM_INTERRUPT;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300836 if (dev->dev_state == DEV_DISCONNECTED)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300837 return -ENODEV;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300838 else if (ret) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300839 dev->dev_state = DEV_MISCONFIGURED;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300840 dprintk(1, "%s device is misconfigured!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300841 return ret;
842 }
843 return 0;
844}
845
846/*
847 * au0828_release_resources
848 * unregister v4l2 devices
849 */
850void au0828_analog_unregister(struct au0828_dev *dev)
851{
852 dprintk(1, "au0828_release_resources called\n");
853 mutex_lock(&au0828_sysfs_lock);
854
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200855 if (dev->vdev)
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300856 video_unregister_device(dev->vdev);
857 if (dev->vbi_dev)
858 video_unregister_device(dev->vbi_dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300859
860 mutex_unlock(&au0828_sysfs_lock);
861}
862
863
864/* Usage lock check functions */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300865static int res_get(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300866{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300867 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300868
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300869 if (fh->resources & bit)
870 /* have it already allocated */
871 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300872
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300873 /* is it free? */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300874 if (dev->resources & bit) {
875 /* no, someone else uses it */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300876 return 0;
877 }
878 /* it's free, grab it */
879 fh->resources |= bit;
880 dev->resources |= bit;
881 dprintk(1, "res: get %d\n", bit);
Devin Heitmueller549ee4d2012-08-06 22:46:58 -0300882
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300883 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300884}
885
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300886static int res_check(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300887{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300888 return fh->resources & bit;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300889}
890
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300891static int res_locked(struct au0828_dev *dev, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300892{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300893 return dev->resources & bit;
894}
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300895
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300896static void res_free(struct au0828_fh *fh, unsigned int bits)
897{
898 struct au0828_dev *dev = fh->dev;
899
900 BUG_ON((fh->resources & bits) != bits);
901
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300902 fh->resources &= ~bits;
903 dev->resources &= ~bits;
904 dprintk(1, "res: put %d\n", bits);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300905}
906
907static int get_ressource(struct au0828_fh *fh)
908{
909 switch (fh->type) {
910 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
911 return AU0828_RESOURCE_VIDEO;
912 case V4L2_BUF_TYPE_VBI_CAPTURE:
913 return AU0828_RESOURCE_VBI;
914 default:
915 BUG();
916 return 0;
917 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300918}
919
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300920/* This function ensures that video frames continue to be delivered even if
921 the ITU-656 input isn't receiving any data (thereby preventing applications
922 such as tvtime from hanging) */
Mauro Carvalho Chehaba094ca42012-10-27 14:00:30 -0300923static void au0828_vid_buffer_timeout(unsigned long data)
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300924{
925 struct au0828_dev *dev = (struct au0828_dev *) data;
926 struct au0828_dmaqueue *dma_q = &dev->vidq;
927 struct au0828_buffer *buf;
928 unsigned char *vid_data;
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300929 unsigned long flags = 0;
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300930
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300931 spin_lock_irqsave(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300932
933 buf = dev->isoc_ctl.buf;
934 if (buf != NULL) {
935 vid_data = videobuf_to_vmalloc(&buf->vb);
936 memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */
937 buffer_filled(dev, dma_q, buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300938 }
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300939 get_next_buf(dma_q, &buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300940
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300941 if (dev->vid_timeout_running == 1)
942 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
943
944 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300945}
946
Mauro Carvalho Chehaba094ca42012-10-27 14:00:30 -0300947static void au0828_vbi_buffer_timeout(unsigned long data)
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300948{
949 struct au0828_dev *dev = (struct au0828_dev *) data;
950 struct au0828_dmaqueue *dma_q = &dev->vbiq;
951 struct au0828_buffer *buf;
952 unsigned char *vbi_data;
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300953 unsigned long flags = 0;
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300954
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300955 spin_lock_irqsave(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300956
957 buf = dev->isoc_ctl.vbi_buf;
958 if (buf != NULL) {
959 vbi_data = videobuf_to_vmalloc(&buf->vb);
960 memset(vbi_data, 0x00, buf->vb.size);
961 vbi_buffer_filled(dev, dma_q, buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300962 }
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300963 vbi_get_next_buf(dma_q, &buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300964
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300965 if (dev->vbi_timeout_running == 1)
966 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
967 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300968}
969
970
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300971static int au0828_v4l2_open(struct file *filp)
972{
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300973 int ret = 0;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300974 struct video_device *vdev = video_devdata(filp);
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200975 struct au0828_dev *dev = video_drvdata(filp);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300976 struct au0828_fh *fh;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300977 int type;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300978
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300979 switch (vdev->vfl_type) {
980 case VFL_TYPE_GRABBER:
981 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
982 break;
983 case VFL_TYPE_VBI:
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200984 type = V4L2_BUF_TYPE_VBI_CAPTURE;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300985 break;
986 default:
987 return -EINVAL;
988 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300989
990 fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300991 if (NULL == fh) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300992 dprintk(1, "Failed allocate au0828_fh struct!\n");
993 return -ENOMEM;
994 }
995
996 fh->type = type;
997 fh->dev = dev;
Hans Verkuil83b09422013-02-15 09:14:00 -0300998 v4l2_fh_init(&fh->fh, vdev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300999 filp->private_data = fh;
1000
Devin Heitmueller62899a22009-03-15 18:48:52 -03001001 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001002 /* set au0828 interface0 to AS5 here again */
1003 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001004 if (ret < 0) {
1005 printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001006 return -EBUSY;
1007 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001008
1009 au0828_analog_stream_enable(dev);
1010 au0828_analog_stream_reset(dev);
1011
1012 /* If we were doing ac97 instead of i2s, it would go here...*/
1013 au0828_i2s_init(dev);
1014
1015 dev->stream_state = STREAM_OFF;
1016 dev->dev_state |= DEV_INITIALIZED;
1017 }
1018
1019 dev->users++;
1020
1021 videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001022 NULL, &dev->slock,
1023 V4L2_BUF_TYPE_VIDEO_CAPTURE,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001024 V4L2_FIELD_INTERLACED,
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03001025 sizeof(struct au0828_buffer), fh,
1026 &dev->lock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001027
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001028 /* VBI Setup */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001029 videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops,
1030 NULL, &dev->slock,
1031 V4L2_BUF_TYPE_VBI_CAPTURE,
1032 V4L2_FIELD_SEQ_TB,
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03001033 sizeof(struct au0828_buffer), fh,
1034 &dev->lock);
Hans Verkuil83b09422013-02-15 09:14:00 -03001035 v4l2_fh_add(&fh->fh);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001036 return ret;
1037}
1038
1039static int au0828_v4l2_close(struct file *filp)
1040{
1041 int ret;
1042 struct au0828_fh *fh = filp->private_data;
1043 struct au0828_dev *dev = fh->dev;
1044
Hans Verkuil83b09422013-02-15 09:14:00 -03001045 v4l2_fh_del(&fh->fh);
1046 v4l2_fh_exit(&fh->fh);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001047 if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001048 /* Cancel timeout thread in case they didn't call streamoff */
1049 dev->vid_timeout_running = 0;
1050 del_timer_sync(&dev->vid_timeout);
1051
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001052 videobuf_stop(&fh->vb_vidq);
1053 res_free(fh, AU0828_RESOURCE_VIDEO);
1054 }
1055
1056 if (res_check(fh, AU0828_RESOURCE_VBI)) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001057 /* Cancel timeout thread in case they didn't call streamoff */
1058 dev->vbi_timeout_running = 0;
1059 del_timer_sync(&dev->vbi_timeout);
1060
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001061 videobuf_stop(&fh->vb_vbiq);
1062 res_free(fh, AU0828_RESOURCE_VBI);
1063 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001064
Hans Verkuil823beb72013-03-11 10:16:45 -03001065 if (dev->users == 1 && video_is_registered(video_devdata(filp))) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001066 au0828_analog_stream_disable(dev);
1067
1068 au0828_uninit_isoc(dev);
1069
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001070 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -03001071 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001072
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001073 /* When close the device, set the usb intf0 into alt0 to free
1074 USB bandwidth */
1075 ret = usb_set_interface(dev->usbdev, 0, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001076 if (ret < 0)
1077 printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001078 }
1079
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001080 videobuf_mmap_free(&fh->vb_vidq);
1081 videobuf_mmap_free(&fh->vb_vbiq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001082 kfree(fh);
1083 dev->users--;
1084 wake_up_interruptible_nr(&dev->open, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001085 return 0;
1086}
1087
1088static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
1089 size_t count, loff_t *pos)
1090{
1091 struct au0828_fh *fh = filp->private_data;
1092 struct au0828_dev *dev = fh->dev;
1093 int rc;
1094
1095 rc = check_dev(dev);
1096 if (rc < 0)
1097 return rc;
1098
Devin Heitmueller62899a22009-03-15 18:48:52 -03001099 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001100 if (res_locked(dev, AU0828_RESOURCE_VIDEO))
1101 return -EBUSY;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001102
1103 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
1104 filp->f_flags & O_NONBLOCK);
1105 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001106
1107 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1108 if (!res_get(fh, AU0828_RESOURCE_VBI))
1109 return -EBUSY;
1110
Devin Heitmuellerbf797162010-10-09 15:09:17 -03001111 if (dev->vbi_timeout_running == 0) {
1112 /* Handle case where caller tries to read without
1113 calling streamon first */
1114 dev->vbi_timeout_running = 1;
1115 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1116 }
1117
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001118 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
1119 filp->f_flags & O_NONBLOCK);
1120 }
1121
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001122 return 0;
1123}
1124
1125static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
1126{
1127 struct au0828_fh *fh = filp->private_data;
1128 struct au0828_dev *dev = fh->dev;
Hans Verkuil83b09422013-02-15 09:14:00 -03001129 unsigned long req_events = poll_requested_events(wait);
1130 unsigned int res;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001131
Hans Verkuil83b09422013-02-15 09:14:00 -03001132 if (check_dev(dev) < 0)
1133 return POLLERR;
1134
1135 res = v4l2_ctrl_poll(filp, wait);
1136 if (!(req_events & (POLLIN | POLLRDNORM)))
1137 return res;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001138
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001139 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1140 if (!res_get(fh, AU0828_RESOURCE_VIDEO))
1141 return POLLERR;
Hans Verkuil83b09422013-02-15 09:14:00 -03001142 return res | videobuf_poll_stream(filp, &fh->vb_vidq, wait);
1143 }
1144 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001145 if (!res_get(fh, AU0828_RESOURCE_VBI))
1146 return POLLERR;
Hans Verkuil83b09422013-02-15 09:14:00 -03001147 return res | videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001148 }
Hans Verkuil83b09422013-02-15 09:14:00 -03001149 return POLLERR;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001150}
1151
1152static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
1153{
1154 struct au0828_fh *fh = filp->private_data;
1155 struct au0828_dev *dev = fh->dev;
1156 int rc;
1157
1158 rc = check_dev(dev);
1159 if (rc < 0)
1160 return rc;
1161
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001162 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1163 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
1164 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1165 rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001166
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001167 return rc;
1168}
1169
1170static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
1171 struct v4l2_format *format)
1172{
1173 int ret;
1174 int width = format->fmt.pix.width;
1175 int height = format->fmt.pix.height;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001176
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001177 /* If they are demanding a format other than the one we support,
1178 bail out (tvtime asks for UYVY and then retries with YUYV) */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001179 if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001180 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001181
1182 /* format->fmt.pix.width only support 720 and height 480 */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001183 if (width != 720)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001184 width = 720;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001185 if (height != 480)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001186 height = 480;
1187
1188 format->fmt.pix.width = width;
1189 format->fmt.pix.height = height;
1190 format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1191 format->fmt.pix.bytesperline = width * 2;
1192 format->fmt.pix.sizeimage = width * height * 2;
1193 format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1194 format->fmt.pix.field = V4L2_FIELD_INTERLACED;
Hans Verkuil8d86e4e2013-03-11 17:48:34 -03001195 format->fmt.pix.priv = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001196
Devin Heitmueller62899a22009-03-15 18:48:52 -03001197 if (cmd == VIDIOC_TRY_FMT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001198 return 0;
1199
1200 /* maybe set new image format, driver current only support 720*480 */
1201 dev->width = width;
1202 dev->height = height;
1203 dev->frame_size = width * height * 2;
1204 dev->field_size = width * height;
1205 dev->bytesperline = width * 2;
1206
Devin Heitmueller62899a22009-03-15 18:48:52 -03001207 if (dev->stream_state == STREAM_ON) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001208 dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
Devin Heitmueller62899a22009-03-15 18:48:52 -03001209 ret = au0828_stream_interrupt(dev);
1210 if (ret != 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001211 dprintk(1, "error interrupting video stream!\n");
1212 return ret;
1213 }
1214 }
1215
1216 /* set au0828 interface0 to AS5 here again */
1217 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001218 if (ret < 0) {
1219 printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001220 return -EBUSY;
1221 }
1222
1223 au0828_analog_stream_enable(dev);
1224
1225 return 0;
1226}
1227
1228
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001229static int vidioc_querycap(struct file *file, void *priv,
1230 struct v4l2_capability *cap)
1231{
Hans Verkuil59e05482013-02-15 08:11:04 -03001232 struct video_device *vdev = video_devdata(file);
1233 struct au0828_fh *fh = priv;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001234 struct au0828_dev *dev = fh->dev;
1235
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001236 strlcpy(cap->driver, "au0828", sizeof(cap->driver));
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001237 strlcpy(cap->card, dev->board.name, sizeof(cap->card));
Hans Verkuil59e05482013-02-15 08:11:04 -03001238 usb_make_path(dev->usbdev, cap->bus_info, sizeof(cap->bus_info));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001239
Hans Verkuil59e05482013-02-15 08:11:04 -03001240 /* set the device capabilities */
1241 cap->device_caps = V4L2_CAP_AUDIO |
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001242 V4L2_CAP_READWRITE |
1243 V4L2_CAP_STREAMING |
1244 V4L2_CAP_TUNER;
Hans Verkuil59e05482013-02-15 08:11:04 -03001245 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1246 cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
1247 else
1248 cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
1249 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1250 V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001251 return 0;
1252}
1253
1254static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1255 struct v4l2_fmtdesc *f)
1256{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001257 if (f->index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001258 return -EINVAL;
1259
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001260 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1261 strcpy(f->description, "Packed YUV2");
1262
1263 f->flags = 0;
1264 f->pixelformat = V4L2_PIX_FMT_UYVY;
1265
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001266 return 0;
1267}
1268
1269static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1270 struct v4l2_format *f)
1271{
1272 struct au0828_fh *fh = priv;
1273 struct au0828_dev *dev = fh->dev;
1274
1275 f->fmt.pix.width = dev->width;
1276 f->fmt.pix.height = dev->height;
1277 f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1278 f->fmt.pix.bytesperline = dev->bytesperline;
1279 f->fmt.pix.sizeimage = dev->frame_size;
1280 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
1281 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
Hans Verkuil8d86e4e2013-03-11 17:48:34 -03001282 f->fmt.pix.priv = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001283 return 0;
1284}
1285
1286static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1287 struct v4l2_format *f)
1288{
1289 struct au0828_fh *fh = priv;
1290 struct au0828_dev *dev = fh->dev;
1291
1292 return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
1293}
1294
1295static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1296 struct v4l2_format *f)
1297{
1298 struct au0828_fh *fh = priv;
1299 struct au0828_dev *dev = fh->dev;
1300 int rc;
1301
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001302 rc = check_dev(dev);
1303 if (rc < 0)
1304 return rc;
1305
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001306 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001307 printk(KERN_INFO "%s queue busy\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001308 rc = -EBUSY;
1309 goto out;
1310 }
1311
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001312 rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001313out:
1314 return rc;
1315}
1316
Hans Verkuil314527a2013-03-15 06:10:40 -03001317static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001318{
1319 struct au0828_fh *fh = priv;
1320 struct au0828_dev *dev = fh->dev;
1321
Hans Verkuilfa09cb92013-03-11 16:10:33 -03001322 i2c_gate_ctrl(dev, 1);
Devin Heitmuellere58071f2012-08-06 22:47:12 -03001323
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001324 /* FIXME: when we support something other than NTSC, we are going to
1325 have to make the au0828 bridge adjust the size of its capture
1326 buffer, which is currently hardcoded at 720x480 */
1327
Hans Verkuil314527a2013-03-15 06:10:40 -03001328 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, norm);
Devin Heitmuellerc98bc032012-08-06 22:46:59 -03001329 dev->std_set_in_tuner_core = 1;
Devin Heitmuellere58071f2012-08-06 22:47:12 -03001330
Hans Verkuilfa09cb92013-03-11 16:10:33 -03001331 i2c_gate_ctrl(dev, 0);
Hans Verkuil33b6b892013-02-15 09:22:37 -03001332 dev->std = norm;
Devin Heitmuellere58071f2012-08-06 22:47:12 -03001333
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001334 return 0;
1335}
1336
Hans Verkuil33b6b892013-02-15 09:22:37 -03001337static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1338{
1339 struct au0828_fh *fh = priv;
1340 struct au0828_dev *dev = fh->dev;
1341
1342 *norm = dev->std;
1343 return 0;
1344}
1345
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001346static int vidioc_enum_input(struct file *file, void *priv,
1347 struct v4l2_input *input)
1348{
1349 struct au0828_fh *fh = priv;
1350 struct au0828_dev *dev = fh->dev;
1351 unsigned int tmp;
1352
1353 static const char *inames[] = {
Devin Heitmueller3d622872009-03-15 17:48:26 -03001354 [AU0828_VMUX_UNDEFINED] = "Undefined",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001355 [AU0828_VMUX_COMPOSITE] = "Composite",
1356 [AU0828_VMUX_SVIDEO] = "S-Video",
1357 [AU0828_VMUX_CABLE] = "Cable TV",
1358 [AU0828_VMUX_TELEVISION] = "Television",
1359 [AU0828_VMUX_DVB] = "DVB",
1360 [AU0828_VMUX_DEBUG] = "tv debug"
1361 };
1362
1363 tmp = input->index;
1364
Dan Carpenterf5e20c32010-03-28 08:21:18 -03001365 if (tmp >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001366 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001367 if (AUVI_INPUT(tmp).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001368 return -EINVAL;
1369
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001370 input->index = tmp;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001371 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001372 if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001373 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001374 input->type |= V4L2_INPUT_TYPE_TUNER;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001375 input->audioset = 1;
1376 } else {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001377 input->type |= V4L2_INPUT_TYPE_CAMERA;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001378 input->audioset = 2;
1379 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001380
1381 input->std = dev->vdev->tvnorms;
1382
1383 return 0;
1384}
1385
1386static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1387{
1388 struct au0828_fh *fh = priv;
1389 struct au0828_dev *dev = fh->dev;
1390 *i = dev->ctrl_input;
1391 return 0;
1392}
1393
Hans Verkuil56230d12013-03-11 16:18:31 -03001394static void au0828_s_input(struct au0828_dev *dev, int index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001395{
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001396 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001397
Devin Heitmueller62899a22009-03-15 18:48:52 -03001398 switch (AUVI_INPUT(index).type) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001399 case AU0828_VMUX_SVIDEO:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001400 dev->input_type = AU0828_VMUX_SVIDEO;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001401 dev->ctrl_ainput = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001402 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001403 case AU0828_VMUX_COMPOSITE:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001404 dev->input_type = AU0828_VMUX_COMPOSITE;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001405 dev->ctrl_ainput = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001406 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001407 case AU0828_VMUX_TELEVISION:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001408 dev->input_type = AU0828_VMUX_TELEVISION;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001409 dev->ctrl_ainput = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001410 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001411 default:
Hans Verkuil56230d12013-03-11 16:18:31 -03001412 dprintk(1, "unknown input type set [%d]\n",
Devin Heitmuellera1094c42009-03-15 17:43:13 -03001413 AUVI_INPUT(index).type);
1414 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001415 }
1416
Hans Verkuil5325b422009-04-02 11:26:22 -03001417 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1418 AUVI_INPUT(index).vmux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001419
1420 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1421 int enable = 0;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001422 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001423 continue;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001424
1425 if (i == index)
1426 enable = 1;
1427 else
1428 enable = 0;
1429 if (enable) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001430 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001431 } else {
1432 /* Make sure we leave it turned on if some
1433 other input is routed to this callback */
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001434 if ((AUVI_INPUT(i).audio_setup) !=
1435 ((AUVI_INPUT(index).audio_setup))) {
1436 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001437 }
1438 }
1439 }
1440
Hans Verkuil5325b422009-04-02 11:26:22 -03001441 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1442 AUVI_INPUT(index).amux, 0, 0);
Hans Verkuil56230d12013-03-11 16:18:31 -03001443}
1444
1445static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1446{
1447 struct au0828_fh *fh = priv;
1448 struct au0828_dev *dev = fh->dev;
1449
1450 dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
1451 index);
1452 if (index >= AU0828_MAX_INPUT)
1453 return -EINVAL;
1454 if (AUVI_INPUT(index).type == 0)
1455 return -EINVAL;
1456 dev->ctrl_input = index;
1457 au0828_s_input(dev, index);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001458 return 0;
1459}
1460
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001461static int vidioc_enumaudio(struct file *file, void *priv, struct v4l2_audio *a)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001462{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001463 if (a->index > 1)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001464 return -EINVAL;
1465
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001466 if (a->index == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001467 strcpy(a->name, "Television");
1468 else
1469 strcpy(a->name, "Line in");
1470
1471 a->capability = V4L2_AUDCAP_STEREO;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001472 return 0;
1473}
1474
1475static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1476{
1477 struct au0828_fh *fh = priv;
1478 struct au0828_dev *dev = fh->dev;
1479
1480 a->index = dev->ctrl_ainput;
1481 if (a->index == 0)
1482 strcpy(a->name, "Television");
1483 else
1484 strcpy(a->name, "Line in");
1485
1486 a->capability = V4L2_AUDCAP_STEREO;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001487 return 0;
1488}
1489
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001490static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001491{
1492 struct au0828_fh *fh = priv;
1493 struct au0828_dev *dev = fh->dev;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001494
Devin Heitmueller62899a22009-03-15 18:48:52 -03001495 if (a->index != dev->ctrl_ainput)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001496 return -EINVAL;
1497 return 0;
1498}
1499
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001500static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
1501{
1502 struct au0828_fh *fh = priv;
1503 struct au0828_dev *dev = fh->dev;
1504
Devin Heitmueller62899a22009-03-15 18:48:52 -03001505 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001506 return -EINVAL;
1507
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001508 strcpy(t->name, "Auvitek tuner");
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001509 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001510 return 0;
1511}
1512
1513static int vidioc_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001514 const struct v4l2_tuner *t)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001515{
1516 struct au0828_fh *fh = priv;
1517 struct au0828_dev *dev = fh->dev;
1518
Devin Heitmueller62899a22009-03-15 18:48:52 -03001519 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001520 return -EINVAL;
1521
Hans Verkuilfa09cb92013-03-11 16:10:33 -03001522 i2c_gate_ctrl(dev, 1);
Devin Heitmuellere58071f2012-08-06 22:47:12 -03001523
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001524 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Devin Heitmuellere58071f2012-08-06 22:47:12 -03001525
Hans Verkuilfa09cb92013-03-11 16:10:33 -03001526 i2c_gate_ctrl(dev, 0);
Devin Heitmuellere58071f2012-08-06 22:47:12 -03001527
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001528 dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
1529 t->afc);
Devin Heitmuellere58071f2012-08-06 22:47:12 -03001530
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001531 return 0;
1532
1533}
1534
1535static int vidioc_g_frequency(struct file *file, void *priv,
1536 struct v4l2_frequency *freq)
1537{
1538 struct au0828_fh *fh = priv;
1539 struct au0828_dev *dev = fh->dev;
Devin Heitmuellerc8889232009-03-15 17:38:47 -03001540
Hans Verkuile1cf6582013-03-22 13:32:20 -03001541 if (freq->tuner != 0)
1542 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001543 freq->frequency = dev->ctrl_freq;
1544 return 0;
1545}
1546
1547static int vidioc_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001548 const struct v4l2_frequency *freq)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001549{
1550 struct au0828_fh *fh = priv;
1551 struct au0828_dev *dev = fh->dev;
Hans Verkuile1cf6582013-03-22 13:32:20 -03001552 struct v4l2_frequency new_freq = *freq;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001553
Devin Heitmueller62899a22009-03-15 18:48:52 -03001554 if (freq->tuner != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001555 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001556
Hans Verkuilfa09cb92013-03-11 16:10:33 -03001557 i2c_gate_ctrl(dev, 1);
Devin Heitmueller4a03daf2012-08-06 22:47:02 -03001558
Devin Heitmuellerc98bc032012-08-06 22:46:59 -03001559 if (dev->std_set_in_tuner_core == 0) {
Hans Verkuil38823b22013-02-15 08:28:27 -03001560 /* If we've never sent the standard in tuner core, do so now.
1561 We don't do this at device probe because we don't want to
1562 incur the cost of a firmware load */
1563 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std,
1564 dev->vdev->tvnorms);
1565 dev->std_set_in_tuner_core = 1;
Devin Heitmuellerc98bc032012-08-06 22:46:59 -03001566 }
1567
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001568 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
Hans Verkuile1cf6582013-03-22 13:32:20 -03001569 /* Get the actual set (and possibly clamped) frequency */
1570 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, &new_freq);
1571 dev->ctrl_freq = new_freq.frequency;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001572
Hans Verkuilfa09cb92013-03-11 16:10:33 -03001573 i2c_gate_ctrl(dev, 0);
Devin Heitmueller4a03daf2012-08-06 22:47:02 -03001574
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001575 au0828_analog_stream_reset(dev);
1576
1577 return 0;
1578}
1579
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001580
1581/* RAW VBI ioctls */
1582
1583static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1584 struct v4l2_format *format)
1585{
1586 struct au0828_fh *fh = priv;
1587 struct au0828_dev *dev = fh->dev;
1588
1589 format->fmt.vbi.samples_per_line = dev->vbi_width;
1590 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1591 format->fmt.vbi.offset = 0;
1592 format->fmt.vbi.flags = 0;
1593 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1594
1595 format->fmt.vbi.count[0] = dev->vbi_height;
1596 format->fmt.vbi.count[1] = dev->vbi_height;
1597 format->fmt.vbi.start[0] = 21;
1598 format->fmt.vbi.start[1] = 284;
Hans Verkuil8d86e4e2013-03-11 17:48:34 -03001599 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001600
1601 return 0;
1602}
1603
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001604static int vidioc_g_chip_ident(struct file *file, void *priv,
1605 struct v4l2_dbg_chip_ident *chip)
1606{
1607 struct au0828_fh *fh = priv;
1608 struct au0828_dev *dev = fh->dev;
1609 chip->ident = V4L2_IDENT_NONE;
1610 chip->revision = 0;
1611
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001612 if (v4l2_chip_match_host(&chip->match)) {
1613 chip->ident = V4L2_IDENT_AU0828;
1614 return 0;
1615 }
1616
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001617 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
Devin Heitmuellerd9109be2009-03-11 03:00:58 -03001618 if (chip->ident == V4L2_IDENT_NONE)
1619 return -EINVAL;
1620
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001621 return 0;
1622}
1623
1624static int vidioc_cropcap(struct file *file, void *priv,
1625 struct v4l2_cropcap *cc)
1626{
1627 struct au0828_fh *fh = priv;
1628 struct au0828_dev *dev = fh->dev;
1629
Devin Heitmueller62899a22009-03-15 18:48:52 -03001630 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001631 return -EINVAL;
1632
1633 cc->bounds.left = 0;
1634 cc->bounds.top = 0;
1635 cc->bounds.width = dev->width;
1636 cc->bounds.height = dev->height;
1637
1638 cc->defrect = cc->bounds;
1639
1640 cc->pixelaspect.numerator = 54;
1641 cc->pixelaspect.denominator = 59;
1642
1643 return 0;
1644}
1645
1646static int vidioc_streamon(struct file *file, void *priv,
1647 enum v4l2_buf_type type)
1648{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001649 struct au0828_fh *fh = priv;
1650 struct au0828_dev *dev = fh->dev;
1651 int rc = -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001652
1653 rc = check_dev(dev);
1654 if (rc < 0)
1655 return rc;
1656
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001657 if (unlikely(type != fh->type))
1658 return -EINVAL;
1659
1660 dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
1661 fh, type, fh->resources, dev->resources);
1662
1663 if (unlikely(!res_get(fh, get_ressource(fh))))
1664 return -EBUSY;
1665
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001666 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1667 au0828_analog_stream_enable(dev);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001668 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001669 }
1670
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001671 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001672 rc = videobuf_streamon(&fh->vb_vidq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001673 dev->vid_timeout_running = 1;
1674 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
1675 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001676 rc = videobuf_streamon(&fh->vb_vbiq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001677 dev->vbi_timeout_running = 1;
1678 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1679 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001680
1681 return rc;
1682}
1683
1684static int vidioc_streamoff(struct file *file, void *priv,
1685 enum v4l2_buf_type type)
1686{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001687 struct au0828_fh *fh = priv;
1688 struct au0828_dev *dev = fh->dev;
1689 int rc;
1690 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001691
1692 rc = check_dev(dev);
1693 if (rc < 0)
1694 return rc;
1695
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001696 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1697 fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001698 return -EINVAL;
1699 if (type != fh->type)
1700 return -EINVAL;
1701
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001702 dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
1703 fh, type, fh->resources, dev->resources);
1704
1705 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001706 dev->vid_timeout_running = 0;
1707 del_timer_sync(&dev->vid_timeout);
1708
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001709 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001710 rc = au0828_stream_interrupt(dev);
1711 if (rc != 0)
1712 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001713
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001714 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1715 if (AUVI_INPUT(i).audio_setup == NULL)
1716 continue;
1717 (AUVI_INPUT(i).audio_setup)(dev, 0);
1718 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001719
Devin Heitmuellera595c1c2012-08-06 22:47:03 -03001720 if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
1721 videobuf_streamoff(&fh->vb_vidq);
1722 res_free(fh, AU0828_RESOURCE_VIDEO);
1723 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001724 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001725 dev->vbi_timeout_running = 0;
1726 del_timer_sync(&dev->vbi_timeout);
1727
Devin Heitmuellera595c1c2012-08-06 22:47:03 -03001728 if (res_check(fh, AU0828_RESOURCE_VBI)) {
1729 videobuf_streamoff(&fh->vb_vbiq);
1730 res_free(fh, AU0828_RESOURCE_VBI);
1731 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001732 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001733
1734 return 0;
1735}
1736
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001737#ifdef CONFIG_VIDEO_ADV_DEBUG
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001738static int vidioc_g_register(struct file *file, void *priv,
1739 struct v4l2_dbg_register *reg)
1740{
1741 struct au0828_fh *fh = priv;
1742 struct au0828_dev *dev = fh->dev;
1743
1744 switch (reg->match.type) {
1745 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001746 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001747 return 0;
1748 default:
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001749 if (!v4l2_chip_match_host(&reg->match))
1750 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001751 }
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001752
1753 reg->val = au0828_read(dev, reg->reg);
1754 return 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001755}
1756
1757static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001758 const struct v4l2_dbg_register *reg)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001759{
1760 struct au0828_fh *fh = priv;
1761 struct au0828_dev *dev = fh->dev;
1762
1763 switch (reg->match.type) {
1764 case V4L2_CHIP_MATCH_I2C_DRIVER:
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001765 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001766 return 0;
1767 default:
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001768 if (!v4l2_chip_match_host(&reg->match))
1769 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001770 }
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001771 return au0828_writereg(dev, reg->reg, reg->val);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001772}
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001773#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001774
Hans Verkuil83b09422013-02-15 09:14:00 -03001775static int vidioc_log_status(struct file *file, void *fh)
1776{
1777 struct video_device *vdev = video_devdata(file);
1778
1779 v4l2_ctrl_log_status(file, fh);
1780 v4l2_device_call_all(vdev->v4l2_dev, 0, core, log_status);
1781 return 0;
1782}
1783
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001784static int vidioc_reqbufs(struct file *file, void *priv,
1785 struct v4l2_requestbuffers *rb)
1786{
1787 struct au0828_fh *fh = priv;
1788 struct au0828_dev *dev = fh->dev;
1789 int rc;
1790
1791 rc = check_dev(dev);
1792 if (rc < 0)
1793 return rc;
1794
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001795 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1796 rc = videobuf_reqbufs(&fh->vb_vidq, rb);
1797 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1798 rc = videobuf_reqbufs(&fh->vb_vbiq, rb);
1799
1800 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001801}
1802
1803static int vidioc_querybuf(struct file *file, void *priv,
1804 struct v4l2_buffer *b)
1805{
1806 struct au0828_fh *fh = priv;
1807 struct au0828_dev *dev = fh->dev;
1808 int rc;
1809
1810 rc = check_dev(dev);
1811 if (rc < 0)
1812 return rc;
1813
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001814 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1815 rc = videobuf_querybuf(&fh->vb_vidq, b);
1816 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1817 rc = videobuf_querybuf(&fh->vb_vbiq, b);
1818
1819 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001820}
1821
1822static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1823{
1824 struct au0828_fh *fh = priv;
1825 struct au0828_dev *dev = fh->dev;
1826 int rc;
1827
1828 rc = check_dev(dev);
1829 if (rc < 0)
1830 return rc;
1831
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001832 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1833 rc = videobuf_qbuf(&fh->vb_vidq, b);
1834 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1835 rc = videobuf_qbuf(&fh->vb_vbiq, b);
1836
1837 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001838}
1839
1840static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1841{
1842 struct au0828_fh *fh = priv;
1843 struct au0828_dev *dev = fh->dev;
1844 int rc;
1845
1846 rc = check_dev(dev);
1847 if (rc < 0)
1848 return rc;
1849
1850 /* Workaround for a bug in the au0828 hardware design that sometimes
1851 results in the colorspace being inverted */
1852 if (dev->greenscreen_detected == 1) {
1853 dprintk(1, "Detected green frame. Resetting stream...\n");
1854 au0828_analog_stream_reset(dev);
1855 dev->greenscreen_detected = 0;
1856 }
1857
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001858 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1859 rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1860 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1861 rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK);
1862
1863 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001864}
1865
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001866static struct v4l2_file_operations au0828_v4l_fops = {
1867 .owner = THIS_MODULE,
1868 .open = au0828_v4l2_open,
1869 .release = au0828_v4l2_close,
1870 .read = au0828_v4l2_read,
1871 .poll = au0828_v4l2_poll,
1872 .mmap = au0828_v4l2_mmap,
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03001873 .unlocked_ioctl = video_ioctl2,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001874};
1875
1876static const struct v4l2_ioctl_ops video_ioctl_ops = {
1877 .vidioc_querycap = vidioc_querycap,
1878 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1879 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1880 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1881 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001882 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil8d86e4e2013-03-11 17:48:34 -03001883 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001884 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001885 .vidioc_enumaudio = vidioc_enumaudio,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001886 .vidioc_g_audio = vidioc_g_audio,
1887 .vidioc_s_audio = vidioc_s_audio,
1888 .vidioc_cropcap = vidioc_cropcap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001889 .vidioc_reqbufs = vidioc_reqbufs,
1890 .vidioc_querybuf = vidioc_querybuf,
1891 .vidioc_qbuf = vidioc_qbuf,
1892 .vidioc_dqbuf = vidioc_dqbuf,
1893 .vidioc_s_std = vidioc_s_std,
Hans Verkuil33b6b892013-02-15 09:22:37 -03001894 .vidioc_g_std = vidioc_g_std,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001895 .vidioc_enum_input = vidioc_enum_input,
1896 .vidioc_g_input = vidioc_g_input,
1897 .vidioc_s_input = vidioc_s_input,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001898 .vidioc_streamon = vidioc_streamon,
1899 .vidioc_streamoff = vidioc_streamoff,
1900 .vidioc_g_tuner = vidioc_g_tuner,
1901 .vidioc_s_tuner = vidioc_s_tuner,
1902 .vidioc_g_frequency = vidioc_g_frequency,
1903 .vidioc_s_frequency = vidioc_s_frequency,
1904#ifdef CONFIG_VIDEO_ADV_DEBUG
1905 .vidioc_g_register = vidioc_g_register,
1906 .vidioc_s_register = vidioc_s_register,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001907#endif
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001908 .vidioc_g_chip_ident = vidioc_g_chip_ident,
Hans Verkuil83b09422013-02-15 09:14:00 -03001909 .vidioc_log_status = vidioc_log_status,
1910 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1911 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001912};
1913
1914static const struct video_device au0828_video_template = {
1915 .fops = &au0828_v4l_fops,
1916 .release = video_device_release,
1917 .ioctl_ops = &video_ioctl_ops,
Devin Heitmueller0ef210712009-03-11 03:00:53 -03001918 .tvnorms = V4L2_STD_NTSC_M,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001919};
1920
1921/**************************************************************************/
1922
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001923int au0828_analog_register(struct au0828_dev *dev,
1924 struct usb_interface *interface)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001925{
1926 int retval = -ENOMEM;
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001927 struct usb_host_interface *iface_desc;
1928 struct usb_endpoint_descriptor *endpoint;
Julia Lawalld63b21b2012-04-22 07:54:42 -03001929 int i, ret;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001930
1931 dprintk(1, "au0828_analog_register called!\n");
1932
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001933 /* set au0828 usb interface0 to as5 */
1934 retval = usb_set_interface(dev->usbdev,
Devin Heitmueller62899a22009-03-15 18:48:52 -03001935 interface->cur_altsetting->desc.bInterfaceNumber, 5);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001936 if (retval != 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001937 printk(KERN_INFO "Failure setting usb interface0 to as5\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001938 return retval;
1939 }
1940
1941 /* Figure out which endpoint has the isoc interface */
1942 iface_desc = interface->cur_altsetting;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001943 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001944 endpoint = &iface_desc->endpoint[i].desc;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001945 if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1946 == USB_DIR_IN) &&
1947 ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1948 == USB_ENDPOINT_XFER_ISOC)) {
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001949
1950 /* we find our isoc in endpoint */
1951 u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001952 dev->max_pkt_size = (tmp & 0x07ff) *
1953 (((tmp & 0x1800) >> 11) + 1);
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001954 dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
1955 }
1956 }
Devin Heitmueller62899a22009-03-15 18:48:52 -03001957 if (!(dev->isoc_in_endpointaddr)) {
1958 printk(KERN_INFO "Could not locate isoc endpoint\n");
Devin Heitmuellerfc4ce6c2009-03-11 03:01:00 -03001959 kfree(dev);
1960 return -ENODEV;
1961 }
1962
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001963 init_waitqueue_head(&dev->open);
1964 spin_lock_init(&dev->slock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001965
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001966 /* init video dma queues */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001967 INIT_LIST_HEAD(&dev->vidq.active);
1968 INIT_LIST_HEAD(&dev->vidq.queued);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001969 INIT_LIST_HEAD(&dev->vbiq.active);
1970 INIT_LIST_HEAD(&dev->vbiq.queued);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001971
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001972 dev->vid_timeout.function = au0828_vid_buffer_timeout;
1973 dev->vid_timeout.data = (unsigned long) dev;
1974 init_timer(&dev->vid_timeout);
1975
1976 dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
1977 dev->vbi_timeout.data = (unsigned long) dev;
1978 init_timer(&dev->vbi_timeout);
1979
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001980 dev->width = NTSC_STD_W;
1981 dev->height = NTSC_STD_H;
1982 dev->field_size = dev->width * dev->height;
1983 dev->frame_size = dev->field_size << 1;
1984 dev->bytesperline = dev->width << 1;
Hans Verkuilde8d2bb2013-03-11 16:12:17 -03001985 dev->vbi_width = 720;
1986 dev->vbi_height = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001987 dev->ctrl_ainput = 0;
Hans Verkuile1cf6582013-03-22 13:32:20 -03001988 dev->ctrl_freq = 960;
Hans Verkuil33b6b892013-02-15 09:22:37 -03001989 dev->std = V4L2_STD_NTSC_M;
Hans Verkuil56230d12013-03-11 16:18:31 -03001990 au0828_s_input(dev, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001991
1992 /* allocate and fill v4l2 video struct */
1993 dev->vdev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03001994 if (NULL == dev->vdev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001995 dprintk(1, "Can't allocate video_device.\n");
1996 return -ENOMEM;
1997 }
1998
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001999 /* allocate the VBI struct */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03002000 dev->vbi_dev = video_device_alloc();
Devin Heitmueller62899a22009-03-15 18:48:52 -03002001 if (NULL == dev->vbi_dev) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03002002 dprintk(1, "Can't allocate vbi_device.\n");
Julia Lawalld63b21b2012-04-22 07:54:42 -03002003 ret = -ENOMEM;
2004 goto err_vdev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03002005 }
2006
2007 /* Fill the video capture device struct */
2008 *dev->vdev = au0828_video_template;
Hans Verkuile8c26f42013-02-15 08:55:41 -03002009 dev->vdev->v4l2_dev = &dev->v4l2_dev;
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03002010 dev->vdev->lock = &dev->lock;
Hans Verkuil83b09422013-02-15 09:14:00 -03002011 set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev->flags);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03002012 strcpy(dev->vdev->name, "au0828a video");
2013
2014 /* Setup the VBI device */
2015 *dev->vbi_dev = au0828_video_template;
Hans Verkuile8c26f42013-02-15 08:55:41 -03002016 dev->vbi_dev->v4l2_dev = &dev->v4l2_dev;
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03002017 dev->vbi_dev->lock = &dev->lock;
Hans Verkuil83b09422013-02-15 09:14:00 -03002018 set_bit(V4L2_FL_USE_FH_PRIO, &dev->vbi_dev->flags);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03002019 strcpy(dev->vbi_dev->name, "au0828a vbi");
2020
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03002021 /* Register the v4l2 device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002022 video_set_drvdata(dev->vdev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03002023 retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
2024 if (retval != 0) {
2025 dprintk(1, "unable to register video device (error = %d).\n",
2026 retval);
Julia Lawalld63b21b2012-04-22 07:54:42 -03002027 ret = -ENODEV;
2028 goto err_vbi_dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03002029 }
2030
2031 /* Register the vbi device */
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -02002032 video_set_drvdata(dev->vbi_dev, dev);
Devin Heitmueller62899a22009-03-15 18:48:52 -03002033 retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
2034 if (retval != 0) {
2035 dprintk(1, "unable to register vbi device (error = %d).\n",
2036 retval);
Julia Lawalld63b21b2012-04-22 07:54:42 -03002037 ret = -ENODEV;
2038 goto err_vbi_dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03002039 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03002040
Devin Heitmueller62899a22009-03-15 18:48:52 -03002041 dprintk(1, "%s completed!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03002042
2043 return 0;
Julia Lawalld63b21b2012-04-22 07:54:42 -03002044
2045err_vbi_dev:
2046 video_device_release(dev->vbi_dev);
2047err_vdev:
2048 video_device_release(dev->vdev);
2049 return ret;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03002050}
2051