blob: f6154546b5c0b3d9a70fad164b07bb5e3d27e134 [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/tuner.h>
40#include "au0828.h"
41#include "au0828-reg.h"
42
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030043static DEFINE_MUTEX(au0828_sysfs_lock);
44
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030045/* ------------------------------------------------------------------
46 Videobuf operations
47 ------------------------------------------------------------------*/
48
49static unsigned int isoc_debug;
50module_param(isoc_debug, int, 0644);
51MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
52
53#define au0828_isocdbg(fmt, arg...) \
54do {\
55 if (isoc_debug) { \
56 printk(KERN_INFO "au0828 %s :"fmt, \
57 __func__ , ##arg); \
58 } \
59 } while (0)
60
Hans Verkuilfa09cb92013-03-11 16:10:33 -030061static inline void i2c_gate_ctrl(struct au0828_dev *dev, int val)
62{
63 if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
64 dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, val);
65}
66
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030067static inline void print_err_status(struct au0828_dev *dev,
68 int packet, int status)
69{
70 char *errmsg = "Unknown";
71
72 switch (status) {
73 case -ENOENT:
74 errmsg = "unlinked synchronuously";
75 break;
76 case -ECONNRESET:
77 errmsg = "unlinked asynchronuously";
78 break;
79 case -ENOSR:
80 errmsg = "Buffer error (overrun)";
81 break;
82 case -EPIPE:
83 errmsg = "Stalled (device not responding)";
84 break;
85 case -EOVERFLOW:
86 errmsg = "Babble (bad cable?)";
87 break;
88 case -EPROTO:
89 errmsg = "Bit-stuff error (bad cable?)";
90 break;
91 case -EILSEQ:
92 errmsg = "CRC/Timeout (could be anything)";
93 break;
94 case -ETIME:
95 errmsg = "Device does not respond";
96 break;
97 }
98 if (packet < 0) {
99 au0828_isocdbg("URB status %d [%s].\n", status, errmsg);
100 } else {
101 au0828_isocdbg("URB packet %d, status %d [%s].\n",
102 packet, status, errmsg);
103 }
104}
105
106static int check_dev(struct au0828_dev *dev)
107{
108 if (dev->dev_state & DEV_DISCONNECTED) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300109 printk(KERN_INFO "v4l2 ioctl: device not present\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300110 return -ENODEV;
111 }
112
113 if (dev->dev_state & DEV_MISCONFIGURED) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300114 printk(KERN_INFO "v4l2 ioctl: device is misconfigured; "
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300115 "close and open it again\n");
116 return -EIO;
117 }
118 return 0;
119}
120
121/*
122 * IRQ callback, called by URB callback
123 */
124static void au0828_irq_callback(struct urb *urb)
125{
126 struct au0828_dmaqueue *dma_q = urb->context;
127 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300128 unsigned long flags = 0;
Hans Verkuile92ba282012-05-14 10:17:35 -0300129 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300130
131 switch (urb->status) {
132 case 0: /* success */
133 case -ETIMEDOUT: /* NAK */
134 break;
135 case -ECONNRESET: /* kill */
136 case -ENOENT:
137 case -ESHUTDOWN:
138 au0828_isocdbg("au0828_irq_callback called: status kill\n");
139 return;
140 default: /* unknown error */
141 au0828_isocdbg("urb completition error %d.\n", urb->status);
142 break;
143 }
144
145 /* Copy data from URB */
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300146 spin_lock_irqsave(&dev->slock, flags);
Hans Verkuile92ba282012-05-14 10:17:35 -0300147 dev->isoc_ctl.isoc_copy(dev, urb);
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300148 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300149
150 /* Reset urb buffers */
151 for (i = 0; i < urb->number_of_packets; i++) {
152 urb->iso_frame_desc[i].status = 0;
153 urb->iso_frame_desc[i].actual_length = 0;
154 }
155 urb->status = 0;
156
157 urb->status = usb_submit_urb(urb, GFP_ATOMIC);
158 if (urb->status) {
159 au0828_isocdbg("urb resubmit failed (error=%i)\n",
160 urb->status);
161 }
162}
163
164/*
165 * Stop and Deallocate URBs
166 */
Mauro Carvalho Chehaba094ca42012-10-27 14:00:30 -0300167static void au0828_uninit_isoc(struct au0828_dev *dev)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300168{
169 struct urb *urb;
170 int i;
171
172 au0828_isocdbg("au0828: called au0828_uninit_isoc\n");
173
174 dev->isoc_ctl.nfields = -1;
175 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
176 urb = dev->isoc_ctl.urb[i];
177 if (urb) {
178 if (!irqs_disabled())
179 usb_kill_urb(urb);
180 else
181 usb_unlink_urb(urb);
182
183 if (dev->isoc_ctl.transfer_buffer[i]) {
Daniel Mack997ea582010-04-12 13:17:25 +0200184 usb_free_coherent(dev->usbdev,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300185 urb->transfer_buffer_length,
186 dev->isoc_ctl.transfer_buffer[i],
187 urb->transfer_dma);
188 }
189 usb_free_urb(urb);
190 dev->isoc_ctl.urb[i] = NULL;
191 }
192 dev->isoc_ctl.transfer_buffer[i] = NULL;
193 }
194
195 kfree(dev->isoc_ctl.urb);
196 kfree(dev->isoc_ctl.transfer_buffer);
197
198 dev->isoc_ctl.urb = NULL;
199 dev->isoc_ctl.transfer_buffer = NULL;
200 dev->isoc_ctl.num_bufs = 0;
201}
202
203/*
204 * Allocate URBs and start IRQ
205 */
Mauro Carvalho Chehaba094ca42012-10-27 14:00:30 -0300206static int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
207 int num_bufs, int max_pkt_size,
208 int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300209{
210 struct au0828_dmaqueue *dma_q = &dev->vidq;
211 int i;
212 int sb_size, pipe;
213 struct urb *urb;
214 int j, k;
215 int rc;
216
217 au0828_isocdbg("au0828: called au0828_prepare_isoc\n");
218
219 /* De-allocates all pending stuff */
220 au0828_uninit_isoc(dev);
221
222 dev->isoc_ctl.isoc_copy = isoc_copy;
223 dev->isoc_ctl.num_bufs = num_bufs;
224
225 dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
226 if (!dev->isoc_ctl.urb) {
227 au0828_isocdbg("cannot alloc memory for usb buffers\n");
228 return -ENOMEM;
229 }
230
231 dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
232 GFP_KERNEL);
233 if (!dev->isoc_ctl.transfer_buffer) {
234 au0828_isocdbg("cannot allocate memory for usb transfer\n");
235 kfree(dev->isoc_ctl.urb);
236 return -ENOMEM;
237 }
238
239 dev->isoc_ctl.max_pkt_size = max_pkt_size;
240 dev->isoc_ctl.buf = NULL;
241
242 sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
243
244 /* allocate urbs and transfer buffers */
245 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
246 urb = usb_alloc_urb(max_packets, GFP_KERNEL);
247 if (!urb) {
248 au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i);
249 au0828_uninit_isoc(dev);
250 return -ENOMEM;
251 }
252 dev->isoc_ctl.urb[i] = urb;
253
Daniel Mack997ea582010-04-12 13:17:25 +0200254 dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300255 sb_size, GFP_KERNEL, &urb->transfer_dma);
256 if (!dev->isoc_ctl.transfer_buffer[i]) {
257 printk("unable to allocate %i bytes for transfer"
258 " buffer %i%s\n",
259 sb_size, i,
260 in_interrupt() ? " while in int" : "");
261 au0828_uninit_isoc(dev);
262 return -ENOMEM;
263 }
264 memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
265
266 pipe = usb_rcvisocpipe(dev->usbdev,
267 dev->isoc_in_endpointaddr),
268
269 usb_fill_int_urb(urb, dev->usbdev, pipe,
270 dev->isoc_ctl.transfer_buffer[i], sb_size,
271 au0828_irq_callback, dma_q, 1);
272
273 urb->number_of_packets = max_packets;
Devin Heitmuellerfadadb72009-03-22 23:42:26 -0300274 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300275
276 k = 0;
277 for (j = 0; j < max_packets; j++) {
278 urb->iso_frame_desc[j].offset = k;
279 urb->iso_frame_desc[j].length =
280 dev->isoc_ctl.max_pkt_size;
281 k += dev->isoc_ctl.max_pkt_size;
282 }
283 }
284
285 init_waitqueue_head(&dma_q->wq);
286
287 /* submit urbs and enables IRQ */
288 for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
289 rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
290 if (rc) {
291 au0828_isocdbg("submit of urb %i failed (error=%i)\n",
292 i, rc);
293 au0828_uninit_isoc(dev);
294 return rc;
295 }
296 }
297
298 return 0;
299}
300
301/*
302 * Announces that a buffer were filled and request the next
303 */
304static inline void buffer_filled(struct au0828_dev *dev,
305 struct au0828_dmaqueue *dma_q,
306 struct au0828_buffer *buf)
307{
308 /* Advice that buffer was filled */
309 au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
310
311 buf->vb.state = VIDEOBUF_DONE;
312 buf->vb.field_count++;
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300313 v4l2_get_timestamp(&buf->vb.ts);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300314
315 dev->isoc_ctl.buf = NULL;
316
317 list_del(&buf->vb.queue);
318 wake_up(&buf->vb.done);
319}
320
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300321static inline void vbi_buffer_filled(struct au0828_dev *dev,
322 struct au0828_dmaqueue *dma_q,
323 struct au0828_buffer *buf)
324{
325 /* Advice that buffer was filled */
326 au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
327
328 buf->vb.state = VIDEOBUF_DONE;
329 buf->vb.field_count++;
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300330 v4l2_get_timestamp(&buf->vb.ts);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300331
332 dev->isoc_ctl.vbi_buf = NULL;
333
334 list_del(&buf->vb.queue);
335 wake_up(&buf->vb.done);
336}
337
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300338/*
339 * Identify the buffer header type and properly handles
340 */
341static void au0828_copy_video(struct au0828_dev *dev,
342 struct au0828_dmaqueue *dma_q,
343 struct au0828_buffer *buf,
344 unsigned char *p,
345 unsigned char *outp, unsigned long len)
346{
347 void *fieldstart, *startwrite, *startread;
348 int linesdone, currlinedone, offset, lencopy, remain;
349 int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */
350
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300351 if (len == 0)
352 return;
353
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300354 if (dma_q->pos + len > buf->vb.size)
355 len = buf->vb.size - dma_q->pos;
356
357 startread = p;
358 remain = len;
359
360 /* Interlaces frame */
361 if (buf->top_field)
362 fieldstart = outp;
363 else
364 fieldstart = outp + bytesperline;
365
366 linesdone = dma_q->pos / bytesperline;
367 currlinedone = dma_q->pos % bytesperline;
368 offset = linesdone * bytesperline * 2 + currlinedone;
369 startwrite = fieldstart + offset;
370 lencopy = bytesperline - currlinedone;
371 lencopy = lencopy > remain ? remain : lencopy;
372
373 if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
374 au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
375 ((char *)startwrite + lencopy) -
376 ((char *)outp + buf->vb.size));
377 remain = (char *)outp + buf->vb.size - (char *)startwrite;
378 lencopy = remain;
379 }
380 if (lencopy <= 0)
381 return;
382 memcpy(startwrite, startread, lencopy);
383
384 remain -= lencopy;
385
386 while (remain > 0) {
387 startwrite += lencopy + bytesperline;
388 startread += lencopy;
389 if (bytesperline > remain)
390 lencopy = remain;
391 else
392 lencopy = bytesperline;
393
394 if ((char *)startwrite + lencopy > (char *)outp +
395 buf->vb.size) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300396 au0828_isocdbg("Overflow %zi bytes past buf end (2)\n",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300397 ((char *)startwrite + lencopy) -
398 ((char *)outp + buf->vb.size));
399 lencopy = remain = (char *)outp + buf->vb.size -
400 (char *)startwrite;
401 }
402 if (lencopy <= 0)
403 break;
404
405 memcpy(startwrite, startread, lencopy);
406
407 remain -= lencopy;
408 }
409
410 if (offset > 1440) {
411 /* We have enough data to check for greenscreen */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300412 if (outp[0] < 0x60 && outp[1440] < 0x60)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300413 dev->greenscreen_detected = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300414 }
415
416 dma_q->pos += len;
417}
418
419/*
420 * video-buf generic routine to get the next available buffer
421 */
422static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
423 struct au0828_buffer **buf)
424{
425 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
426
427 if (list_empty(&dma_q->active)) {
428 au0828_isocdbg("No active queue to serve\n");
429 dev->isoc_ctl.buf = NULL;
430 *buf = NULL;
431 return;
432 }
433
434 /* Get the next buffer */
435 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
436 dev->isoc_ctl.buf = *buf;
437
438 return;
439}
440
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300441static void au0828_copy_vbi(struct au0828_dev *dev,
442 struct au0828_dmaqueue *dma_q,
443 struct au0828_buffer *buf,
444 unsigned char *p,
445 unsigned char *outp, unsigned long len)
446{
447 unsigned char *startwrite, *startread;
Dan Carpenterb5f59332010-07-23 07:09:20 -0300448 int bytesperline;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300449 int i, j = 0;
450
451 if (dev == NULL) {
452 au0828_isocdbg("dev is null\n");
453 return;
454 }
455
456 if (dma_q == NULL) {
457 au0828_isocdbg("dma_q is null\n");
458 return;
459 }
460 if (buf == NULL)
461 return;
462 if (p == NULL) {
463 au0828_isocdbg("p is null\n");
464 return;
465 }
466 if (outp == NULL) {
467 au0828_isocdbg("outp is null\n");
468 return;
469 }
470
Dan Carpenterb5f59332010-07-23 07:09:20 -0300471 bytesperline = dev->vbi_width;
472
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300473 if (dma_q->pos + len > buf->vb.size)
474 len = buf->vb.size - dma_q->pos;
475
476 startread = p;
477 startwrite = outp + (dma_q->pos / 2);
478
479 /* Make sure the bottom field populates the second half of the frame */
480 if (buf->top_field == 0)
481 startwrite += bytesperline * dev->vbi_height;
482
483 for (i = 0; i < len; i += 2)
484 startwrite[j++] = startread[i+1];
485
486 dma_q->pos += len;
487}
488
489
490/*
491 * video-buf generic routine to get the next available VBI buffer
492 */
493static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q,
494 struct au0828_buffer **buf)
495{
496 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq);
497 char *outp;
498
499 if (list_empty(&dma_q->active)) {
500 au0828_isocdbg("No active queue to serve\n");
501 dev->isoc_ctl.vbi_buf = NULL;
502 *buf = NULL;
503 return;
504 }
505
506 /* Get the next buffer */
507 *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300508 /* Cleans up buffer - Useful for testing for frame/URB loss */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300509 outp = videobuf_to_vmalloc(&(*buf)->vb);
510 memset(outp, 0x00, (*buf)->vb.size);
511
512 dev->isoc_ctl.vbi_buf = *buf;
513
514 return;
515}
516
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300517/*
518 * Controls the isoc copy of each urb packet
519 */
520static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
521{
522 struct au0828_buffer *buf;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300523 struct au0828_buffer *vbi_buf;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300524 struct au0828_dmaqueue *dma_q = urb->context;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300525 struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300526 unsigned char *outp = NULL;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300527 unsigned char *vbioutp = NULL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300528 int i, len = 0, rc = 1;
529 unsigned char *p;
530 unsigned char fbyte;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300531 unsigned int vbi_field_size;
532 unsigned int remain, lencopy;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300533
534 if (!dev)
535 return 0;
536
537 if ((dev->dev_state & DEV_DISCONNECTED) ||
538 (dev->dev_state & DEV_MISCONFIGURED))
539 return 0;
540
541 if (urb->status < 0) {
542 print_err_status(dev, -1, urb->status);
543 if (urb->status == -ENOENT)
544 return 0;
545 }
546
547 buf = dev->isoc_ctl.buf;
548 if (buf != NULL)
549 outp = videobuf_to_vmalloc(&buf->vb);
550
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300551 vbi_buf = dev->isoc_ctl.vbi_buf;
552 if (vbi_buf != NULL)
553 vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
554
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300555 for (i = 0; i < urb->number_of_packets; i++) {
556 int status = urb->iso_frame_desc[i].status;
557
558 if (status < 0) {
559 print_err_status(dev, i, status);
560 if (urb->iso_frame_desc[i].status != -EPROTO)
561 continue;
562 }
563
Devin Heitmueller62899a22009-03-15 18:48:52 -0300564 if (urb->iso_frame_desc[i].actual_length <= 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300565 continue;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300566
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300567 if (urb->iso_frame_desc[i].actual_length >
568 dev->max_pkt_size) {
569 au0828_isocdbg("packet bigger than packet size");
570 continue;
571 }
572
573 p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
574 fbyte = p[0];
575 len = urb->iso_frame_desc[i].actual_length - 4;
576 p += 4;
577
578 if (fbyte & 0x80) {
579 len -= 4;
580 p += 4;
581 au0828_isocdbg("Video frame %s\n",
582 (fbyte & 0x40) ? "odd" : "even");
Devin Heitmuellerbde3bb92010-07-05 13:05:16 -0300583 if (fbyte & 0x40) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300584 /* VBI */
585 if (vbi_buf != NULL)
586 vbi_buffer_filled(dev,
587 vbi_dma_q,
588 vbi_buf);
589 vbi_get_next_buf(vbi_dma_q, &vbi_buf);
590 if (vbi_buf == NULL)
591 vbioutp = NULL;
592 else
593 vbioutp = videobuf_to_vmalloc(
594 &vbi_buf->vb);
595
596 /* Video */
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300597 if (buf != NULL)
598 buffer_filled(dev, dma_q, buf);
599 get_next_buf(dma_q, &buf);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300600 if (buf == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300601 outp = NULL;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300602 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300603 outp = videobuf_to_vmalloc(&buf->vb);
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300604
605 /* As long as isoc traffic is arriving, keep
606 resetting the timer */
607 if (dev->vid_timeout_running)
608 mod_timer(&dev->vid_timeout,
609 jiffies + (HZ / 10));
610 if (dev->vbi_timeout_running)
611 mod_timer(&dev->vbi_timeout,
612 jiffies + (HZ / 10));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300613 }
614
615 if (buf != NULL) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300616 if (fbyte & 0x40)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300617 buf->top_field = 1;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300618 else
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300619 buf->top_field = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300620 }
621
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300622 if (vbi_buf != NULL) {
623 if (fbyte & 0x40)
624 vbi_buf->top_field = 1;
625 else
626 vbi_buf->top_field = 0;
627 }
628
629 dev->vbi_read = 0;
630 vbi_dma_q->pos = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300631 dma_q->pos = 0;
632 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300633
634 vbi_field_size = dev->vbi_width * dev->vbi_height * 2;
635 if (dev->vbi_read < vbi_field_size) {
636 remain = vbi_field_size - dev->vbi_read;
637 if (len < remain)
638 lencopy = len;
639 else
640 lencopy = remain;
641
642 if (vbi_buf != NULL)
643 au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
644 vbioutp, len);
645
646 len -= lencopy;
647 p += lencopy;
648 dev->vbi_read += lencopy;
649 }
650
651 if (dev->vbi_read >= vbi_field_size && buf != NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300652 au0828_copy_video(dev, dma_q, buf, p, outp, len);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300653 }
654 return rc;
655}
656
657static int
658buffer_setup(struct videobuf_queue *vq, unsigned int *count,
659 unsigned int *size)
660{
661 struct au0828_fh *fh = vq->priv_data;
662 *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
663
664 if (0 == *count)
665 *count = AU0828_DEF_BUF;
666
667 if (*count < AU0828_MIN_BUF)
668 *count = AU0828_MIN_BUF;
669 return 0;
670}
671
672/* This is called *without* dev->slock held; please keep it that way */
673static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
674{
675 struct au0828_fh *fh = vq->priv_data;
676 struct au0828_dev *dev = fh->dev;
677 unsigned long flags = 0;
678 if (in_interrupt())
679 BUG();
680
681 /* We used to wait for the buffer to finish here, but this didn't work
682 because, as we were keeping the state as VIDEOBUF_QUEUED,
683 videobuf_queue_cancel marked it as finished for us.
684 (Also, it could wedge forever if the hardware was misconfigured.)
685
686 This should be safe; by the time we get here, the buffer isn't
687 queued anymore. If we ever start marking the buffers as
688 VIDEOBUF_ACTIVE, it won't be, though.
689 */
690 spin_lock_irqsave(&dev->slock, flags);
691 if (dev->isoc_ctl.buf == buf)
692 dev->isoc_ctl.buf = NULL;
693 spin_unlock_irqrestore(&dev->slock, flags);
694
695 videobuf_vmalloc_free(&buf->vb);
696 buf->vb.state = VIDEOBUF_NEEDS_INIT;
697}
698
699static int
700buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
701 enum v4l2_field field)
702{
703 struct au0828_fh *fh = vq->priv_data;
704 struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
705 struct au0828_dev *dev = fh->dev;
706 int rc = 0, urb_init = 0;
707
708 buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
709
710 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
711 return -EINVAL;
712
713 buf->vb.width = dev->width;
714 buf->vb.height = dev->height;
715 buf->vb.field = field;
716
717 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
718 rc = videobuf_iolock(vq, &buf->vb, NULL);
719 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300720 printk(KERN_INFO "videobuf_iolock failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300721 goto fail;
722 }
723 }
724
725 if (!dev->isoc_ctl.num_bufs)
726 urb_init = 1;
727
728 if (urb_init) {
729 rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,
730 AU0828_MAX_ISO_BUFS, dev->max_pkt_size,
731 au0828_isoc_copy);
732 if (rc < 0) {
Devin Heitmueller62899a22009-03-15 18:48:52 -0300733 printk(KERN_INFO "au0828_init_isoc failed\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300734 goto fail;
735 }
736 }
737
738 buf->vb.state = VIDEOBUF_PREPARED;
739 return 0;
740
741fail:
742 free_buffer(vq, buf);
743 return rc;
744}
745
746static void
747buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
748{
749 struct au0828_buffer *buf = container_of(vb,
750 struct au0828_buffer,
751 vb);
752 struct au0828_fh *fh = vq->priv_data;
753 struct au0828_dev *dev = fh->dev;
754 struct au0828_dmaqueue *vidq = &dev->vidq;
755
756 buf->vb.state = VIDEOBUF_QUEUED;
757 list_add_tail(&buf->vb.queue, &vidq->active);
758}
759
760static void buffer_release(struct videobuf_queue *vq,
761 struct videobuf_buffer *vb)
762{
763 struct au0828_buffer *buf = container_of(vb,
764 struct au0828_buffer,
765 vb);
766
767 free_buffer(vq, buf);
768}
769
770static struct videobuf_queue_ops au0828_video_qops = {
771 .buf_setup = buffer_setup,
772 .buf_prepare = buffer_prepare,
773 .buf_queue = buffer_queue,
774 .buf_release = buffer_release,
775};
776
777/* ------------------------------------------------------------------
778 V4L2 interface
779 ------------------------------------------------------------------*/
780
781static int au0828_i2s_init(struct au0828_dev *dev)
782{
783 /* Enable i2s mode */
784 au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);
785 return 0;
786}
787
788/*
789 * Auvitek au0828 analog stream enable
790 * Please set interface0 to AS5 before enable the stream
791 */
Mauro Carvalho Chehaba094ca42012-10-27 14:00:30 -0300792static int au0828_analog_stream_enable(struct au0828_dev *d)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300793{
794 dprintk(1, "au0828_analog_stream_enable called\n");
795 au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
796 au0828_writereg(d, 0x106, 0x00);
797 /* set x position */
798 au0828_writereg(d, 0x110, 0x00);
799 au0828_writereg(d, 0x111, 0x00);
800 au0828_writereg(d, 0x114, 0xa0);
801 au0828_writereg(d, 0x115, 0x05);
802 /* set y position */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300803 au0828_writereg(d, 0x112, 0x00);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300804 au0828_writereg(d, 0x113, 0x00);
805 au0828_writereg(d, 0x116, 0xf2);
806 au0828_writereg(d, 0x117, 0x00);
807 au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
808
809 return 0;
810}
811
812int au0828_analog_stream_disable(struct au0828_dev *d)
813{
814 dprintk(1, "au0828_analog_stream_disable called\n");
815 au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
816 return 0;
817}
818
Mauro Carvalho Chehaba094ca42012-10-27 14:00:30 -0300819static void au0828_analog_stream_reset(struct au0828_dev *dev)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300820{
821 dprintk(1, "au0828_analog_stream_reset called\n");
822 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
823 mdelay(30);
824 au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);
825}
826
827/*
828 * Some operations needs to stop current streaming
829 */
830static int au0828_stream_interrupt(struct au0828_dev *dev)
831{
832 int ret = 0;
833
834 dev->stream_state = STREAM_INTERRUPT;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300835 if (dev->dev_state == DEV_DISCONNECTED)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300836 return -ENODEV;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300837 else if (ret) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300838 dev->dev_state = DEV_MISCONFIGURED;
Devin Heitmueller62899a22009-03-15 18:48:52 -0300839 dprintk(1, "%s device is misconfigured!\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300840 return ret;
841 }
842 return 0;
843}
844
845/*
846 * au0828_release_resources
847 * unregister v4l2 devices
848 */
849void au0828_analog_unregister(struct au0828_dev *dev)
850{
851 dprintk(1, "au0828_release_resources called\n");
852 mutex_lock(&au0828_sysfs_lock);
853
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200854 if (dev->vdev)
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -0300855 video_unregister_device(dev->vdev);
856 if (dev->vbi_dev)
857 video_unregister_device(dev->vbi_dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300858
859 mutex_unlock(&au0828_sysfs_lock);
860}
861
862
863/* Usage lock check functions */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300864static int res_get(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300865{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300866 struct au0828_dev *dev = fh->dev;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300867
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300868 if (fh->resources & bit)
869 /* have it already allocated */
870 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300871
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300872 /* is it free? */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300873 if (dev->resources & bit) {
874 /* no, someone else uses it */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300875 return 0;
876 }
877 /* it's free, grab it */
878 fh->resources |= bit;
879 dev->resources |= bit;
880 dprintk(1, "res: get %d\n", bit);
Devin Heitmueller549ee4d2012-08-06 22:46:58 -0300881
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300882 return 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300883}
884
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300885static int res_check(struct au0828_fh *fh, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300886{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300887 return fh->resources & bit;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300888}
889
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300890static int res_locked(struct au0828_dev *dev, unsigned int bit)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300891{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300892 return dev->resources & bit;
893}
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300894
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300895static void res_free(struct au0828_fh *fh, unsigned int bits)
896{
897 struct au0828_dev *dev = fh->dev;
898
899 BUG_ON((fh->resources & bits) != bits);
900
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300901 fh->resources &= ~bits;
902 dev->resources &= ~bits;
903 dprintk(1, "res: put %d\n", bits);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300904}
905
906static int get_ressource(struct au0828_fh *fh)
907{
908 switch (fh->type) {
909 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
910 return AU0828_RESOURCE_VIDEO;
911 case V4L2_BUF_TYPE_VBI_CAPTURE:
912 return AU0828_RESOURCE_VBI;
913 default:
914 BUG();
915 return 0;
916 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300917}
918
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300919/* This function ensures that video frames continue to be delivered even if
920 the ITU-656 input isn't receiving any data (thereby preventing applications
921 such as tvtime from hanging) */
Mauro Carvalho Chehaba094ca42012-10-27 14:00:30 -0300922static void au0828_vid_buffer_timeout(unsigned long data)
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300923{
924 struct au0828_dev *dev = (struct au0828_dev *) data;
925 struct au0828_dmaqueue *dma_q = &dev->vidq;
926 struct au0828_buffer *buf;
927 unsigned char *vid_data;
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300928 unsigned long flags = 0;
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300929
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300930 spin_lock_irqsave(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300931
932 buf = dev->isoc_ctl.buf;
933 if (buf != NULL) {
934 vid_data = videobuf_to_vmalloc(&buf->vb);
935 memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */
936 buffer_filled(dev, dma_q, buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300937 }
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300938 get_next_buf(dma_q, &buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300939
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300940 if (dev->vid_timeout_running == 1)
941 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
942
943 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300944}
945
Mauro Carvalho Chehaba094ca42012-10-27 14:00:30 -0300946static void au0828_vbi_buffer_timeout(unsigned long data)
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300947{
948 struct au0828_dev *dev = (struct au0828_dev *) data;
949 struct au0828_dmaqueue *dma_q = &dev->vbiq;
950 struct au0828_buffer *buf;
951 unsigned char *vbi_data;
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300952 unsigned long flags = 0;
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300953
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300954 spin_lock_irqsave(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300955
956 buf = dev->isoc_ctl.vbi_buf;
957 if (buf != NULL) {
958 vbi_data = videobuf_to_vmalloc(&buf->vb);
959 memset(vbi_data, 0x00, buf->vb.size);
960 vbi_buffer_filled(dev, dma_q, buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300961 }
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300962 vbi_get_next_buf(dma_q, &buf);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300963
Devin Heitmueller78ca5002010-10-09 14:43:53 -0300964 if (dev->vbi_timeout_running == 1)
965 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
966 spin_unlock_irqrestore(&dev->slock, flags);
Devin Heitmueller6e04b7b2010-09-01 22:03:43 -0300967}
968
969
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300970static int au0828_v4l2_open(struct file *filp)
971{
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300972 int ret = 0;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300973 struct video_device *vdev = video_devdata(filp);
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200974 struct au0828_dev *dev = video_drvdata(filp);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300975 struct au0828_fh *fh;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300976 int type;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300977
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300978 switch (vdev->vfl_type) {
979 case VFL_TYPE_GRABBER:
980 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
981 break;
982 case VFL_TYPE_VBI:
Laurent Pinchart63b0d5a2009-12-10 11:44:04 -0200983 type = V4L2_BUF_TYPE_VBI_CAPTURE;
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -0300984 break;
985 default:
986 return -EINVAL;
987 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300988
989 fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300990 if (NULL == fh) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300991 dprintk(1, "Failed allocate au0828_fh struct!\n");
992 return -ENOMEM;
993 }
994
995 fh->type = type;
996 fh->dev = dev;
Hans Verkuil83b09422013-02-15 09:14:00 -0300997 v4l2_fh_init(&fh->fh, vdev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300998 filp->private_data = fh;
999
Hans Verkuilea86968f2013-03-11 16:22:13 -03001000 if (mutex_lock_interruptible(&dev->lock)) {
1001 kfree(fh);
1002 return -ERESTARTSYS;
1003 }
1004 if (dev->users == 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001005 /* set au0828 interface0 to AS5 here again */
1006 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001007 if (ret < 0) {
Hans Verkuilea86968f2013-03-11 16:22:13 -03001008 mutex_unlock(&dev->lock);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001009 printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
Hans Verkuilea86968f2013-03-11 16:22:13 -03001010 kfree(fh);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001011 return -EBUSY;
1012 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001013
1014 au0828_analog_stream_enable(dev);
1015 au0828_analog_stream_reset(dev);
1016
1017 /* If we were doing ac97 instead of i2s, it would go here...*/
1018 au0828_i2s_init(dev);
1019
1020 dev->stream_state = STREAM_OFF;
1021 dev->dev_state |= DEV_INITIALIZED;
1022 }
1023
1024 dev->users++;
Hans Verkuilea86968f2013-03-11 16:22:13 -03001025 mutex_unlock(&dev->lock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001026
1027 videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001028 NULL, &dev->slock,
1029 V4L2_BUF_TYPE_VIDEO_CAPTURE,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001030 V4L2_FIELD_INTERLACED,
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03001031 sizeof(struct au0828_buffer), fh,
1032 &dev->lock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001033
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001034 /* VBI Setup */
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001035 videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops,
1036 NULL, &dev->slock,
1037 V4L2_BUF_TYPE_VBI_CAPTURE,
1038 V4L2_FIELD_SEQ_TB,
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03001039 sizeof(struct au0828_buffer), fh,
1040 &dev->lock);
Hans Verkuil83b09422013-02-15 09:14:00 -03001041 v4l2_fh_add(&fh->fh);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001042 return ret;
1043}
1044
1045static int au0828_v4l2_close(struct file *filp)
1046{
1047 int ret;
1048 struct au0828_fh *fh = filp->private_data;
1049 struct au0828_dev *dev = fh->dev;
1050
Hans Verkuil83b09422013-02-15 09:14:00 -03001051 v4l2_fh_del(&fh->fh);
1052 v4l2_fh_exit(&fh->fh);
Hans Verkuilea86968f2013-03-11 16:22:13 -03001053 mutex_lock(&dev->lock);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001054 if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001055 /* Cancel timeout thread in case they didn't call streamoff */
1056 dev->vid_timeout_running = 0;
1057 del_timer_sync(&dev->vid_timeout);
1058
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001059 videobuf_stop(&fh->vb_vidq);
1060 res_free(fh, AU0828_RESOURCE_VIDEO);
1061 }
1062
1063 if (res_check(fh, AU0828_RESOURCE_VBI)) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001064 /* Cancel timeout thread in case they didn't call streamoff */
1065 dev->vbi_timeout_running = 0;
1066 del_timer_sync(&dev->vbi_timeout);
1067
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001068 videobuf_stop(&fh->vb_vbiq);
1069 res_free(fh, AU0828_RESOURCE_VBI);
1070 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001071
Hans Verkuil823beb72013-03-11 10:16:45 -03001072 if (dev->users == 1 && video_is_registered(video_devdata(filp))) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001073 au0828_analog_stream_disable(dev);
1074
1075 au0828_uninit_isoc(dev);
1076
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001077 /* Save some power by putting tuner to sleep */
Laurent Pinchart622b8282009-10-05 10:48:17 -03001078 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
Hans Verkuilea86968f2013-03-11 16:22:13 -03001079 dev->std_set_in_tuner_core = 0;
Devin Heitmuellere4b8bc52009-05-06 20:54:00 -03001080
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001081 /* When close the device, set the usb intf0 into alt0 to free
1082 USB bandwidth */
1083 ret = usb_set_interface(dev->usbdev, 0, 0);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001084 if (ret < 0)
1085 printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001086 }
Hans Verkuilea86968f2013-03-11 16:22:13 -03001087 mutex_unlock(&dev->lock);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001088
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001089 videobuf_mmap_free(&fh->vb_vidq);
1090 videobuf_mmap_free(&fh->vb_vbiq);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001091 kfree(fh);
1092 dev->users--;
1093 wake_up_interruptible_nr(&dev->open, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001094 return 0;
1095}
1096
Hans Verkuilea86968f2013-03-11 16:22:13 -03001097/* Must be called with dev->lock held */
1098static void au0828_init_tuner(struct au0828_dev *dev)
1099{
1100 struct v4l2_frequency f = {
1101 .frequency = dev->ctrl_freq,
1102 .type = V4L2_TUNER_ANALOG_TV,
1103 };
1104
1105 if (dev->std_set_in_tuner_core)
1106 return;
1107 dev->std_set_in_tuner_core = 1;
1108 i2c_gate_ctrl(dev, 1);
1109 /* If we've never sent the standard in tuner core, do so now.
1110 We don't do this at device probe because we don't want to
1111 incur the cost of a firmware load */
1112 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->std);
1113 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
1114 i2c_gate_ctrl(dev, 0);
1115}
1116
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001117static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
1118 size_t count, loff_t *pos)
1119{
1120 struct au0828_fh *fh = filp->private_data;
1121 struct au0828_dev *dev = fh->dev;
1122 int rc;
1123
1124 rc = check_dev(dev);
1125 if (rc < 0)
1126 return rc;
1127
Hans Verkuilea86968f2013-03-11 16:22:13 -03001128 if (mutex_lock_interruptible(&dev->lock))
1129 return -ERESTARTSYS;
1130 au0828_init_tuner(dev);
1131 mutex_unlock(&dev->lock);
1132
Devin Heitmueller62899a22009-03-15 18:48:52 -03001133 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001134 if (res_locked(dev, AU0828_RESOURCE_VIDEO))
1135 return -EBUSY;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001136
1137 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
1138 filp->f_flags & O_NONBLOCK);
1139 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001140
1141 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1142 if (!res_get(fh, AU0828_RESOURCE_VBI))
1143 return -EBUSY;
1144
Devin Heitmuellerbf797162010-10-09 15:09:17 -03001145 if (dev->vbi_timeout_running == 0) {
1146 /* Handle case where caller tries to read without
1147 calling streamon first */
1148 dev->vbi_timeout_running = 1;
1149 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1150 }
1151
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001152 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
1153 filp->f_flags & O_NONBLOCK);
1154 }
1155
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001156 return 0;
1157}
1158
1159static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
1160{
1161 struct au0828_fh *fh = filp->private_data;
1162 struct au0828_dev *dev = fh->dev;
Hans Verkuil83b09422013-02-15 09:14:00 -03001163 unsigned long req_events = poll_requested_events(wait);
1164 unsigned int res;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001165
Hans Verkuil83b09422013-02-15 09:14:00 -03001166 if (check_dev(dev) < 0)
1167 return POLLERR;
1168
1169 res = v4l2_ctrl_poll(filp, wait);
1170 if (!(req_events & (POLLIN | POLLRDNORM)))
1171 return res;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001172
Hans Verkuilea86968f2013-03-11 16:22:13 -03001173 if (mutex_lock_interruptible(&dev->lock))
1174 return -ERESTARTSYS;
1175 au0828_init_tuner(dev);
1176 mutex_unlock(&dev->lock);
1177
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001178 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1179 if (!res_get(fh, AU0828_RESOURCE_VIDEO))
1180 return POLLERR;
Hans Verkuil83b09422013-02-15 09:14:00 -03001181 return res | videobuf_poll_stream(filp, &fh->vb_vidq, wait);
1182 }
1183 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001184 if (!res_get(fh, AU0828_RESOURCE_VBI))
1185 return POLLERR;
Hans Verkuil83b09422013-02-15 09:14:00 -03001186 return res | videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001187 }
Hans Verkuil83b09422013-02-15 09:14:00 -03001188 return POLLERR;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001189}
1190
1191static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
1192{
1193 struct au0828_fh *fh = filp->private_data;
1194 struct au0828_dev *dev = fh->dev;
1195 int rc;
1196
1197 rc = check_dev(dev);
1198 if (rc < 0)
1199 return rc;
1200
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001201 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1202 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
1203 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1204 rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001205
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001206 return rc;
1207}
1208
1209static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
1210 struct v4l2_format *format)
1211{
1212 int ret;
1213 int width = format->fmt.pix.width;
1214 int height = format->fmt.pix.height;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001215
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001216 /* If they are demanding a format other than the one we support,
1217 bail out (tvtime asks for UYVY and then retries with YUYV) */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001218 if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001219 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001220
1221 /* format->fmt.pix.width only support 720 and height 480 */
Devin Heitmueller62899a22009-03-15 18:48:52 -03001222 if (width != 720)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001223 width = 720;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001224 if (height != 480)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001225 height = 480;
1226
1227 format->fmt.pix.width = width;
1228 format->fmt.pix.height = height;
1229 format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1230 format->fmt.pix.bytesperline = width * 2;
1231 format->fmt.pix.sizeimage = width * height * 2;
1232 format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1233 format->fmt.pix.field = V4L2_FIELD_INTERLACED;
Hans Verkuil8d86e4e2013-03-11 17:48:34 -03001234 format->fmt.pix.priv = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001235
Devin Heitmueller62899a22009-03-15 18:48:52 -03001236 if (cmd == VIDIOC_TRY_FMT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001237 return 0;
1238
1239 /* maybe set new image format, driver current only support 720*480 */
1240 dev->width = width;
1241 dev->height = height;
1242 dev->frame_size = width * height * 2;
1243 dev->field_size = width * height;
1244 dev->bytesperline = width * 2;
1245
Devin Heitmueller62899a22009-03-15 18:48:52 -03001246 if (dev->stream_state == STREAM_ON) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001247 dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
Devin Heitmueller62899a22009-03-15 18:48:52 -03001248 ret = au0828_stream_interrupt(dev);
1249 if (ret != 0) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001250 dprintk(1, "error interrupting video stream!\n");
1251 return ret;
1252 }
1253 }
1254
1255 /* set au0828 interface0 to AS5 here again */
1256 ret = usb_set_interface(dev->usbdev, 0, 5);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001257 if (ret < 0) {
1258 printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001259 return -EBUSY;
1260 }
1261
1262 au0828_analog_stream_enable(dev);
1263
1264 return 0;
1265}
1266
1267
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001268static int vidioc_querycap(struct file *file, void *priv,
1269 struct v4l2_capability *cap)
1270{
Hans Verkuil59e05482013-02-15 08:11:04 -03001271 struct video_device *vdev = video_devdata(file);
1272 struct au0828_fh *fh = priv;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001273 struct au0828_dev *dev = fh->dev;
1274
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001275 strlcpy(cap->driver, "au0828", sizeof(cap->driver));
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001276 strlcpy(cap->card, dev->board.name, sizeof(cap->card));
Hans Verkuil59e05482013-02-15 08:11:04 -03001277 usb_make_path(dev->usbdev, cap->bus_info, sizeof(cap->bus_info));
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001278
Hans Verkuil59e05482013-02-15 08:11:04 -03001279 /* set the device capabilities */
1280 cap->device_caps = V4L2_CAP_AUDIO |
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001281 V4L2_CAP_READWRITE |
1282 V4L2_CAP_STREAMING |
1283 V4L2_CAP_TUNER;
Hans Verkuil59e05482013-02-15 08:11:04 -03001284 if (vdev->vfl_type == VFL_TYPE_GRABBER)
1285 cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
1286 else
1287 cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
1288 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
1289 V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001290 return 0;
1291}
1292
1293static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1294 struct v4l2_fmtdesc *f)
1295{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001296 if (f->index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001297 return -EINVAL;
1298
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001299 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1300 strcpy(f->description, "Packed YUV2");
1301
1302 f->flags = 0;
1303 f->pixelformat = V4L2_PIX_FMT_UYVY;
1304
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001305 return 0;
1306}
1307
1308static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1309 struct v4l2_format *f)
1310{
1311 struct au0828_fh *fh = priv;
1312 struct au0828_dev *dev = fh->dev;
1313
1314 f->fmt.pix.width = dev->width;
1315 f->fmt.pix.height = dev->height;
1316 f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1317 f->fmt.pix.bytesperline = dev->bytesperline;
1318 f->fmt.pix.sizeimage = dev->frame_size;
1319 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
1320 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
Hans Verkuil8d86e4e2013-03-11 17:48:34 -03001321 f->fmt.pix.priv = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001322 return 0;
1323}
1324
1325static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1326 struct v4l2_format *f)
1327{
1328 struct au0828_fh *fh = priv;
1329 struct au0828_dev *dev = fh->dev;
1330
1331 return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
1332}
1333
1334static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1335 struct v4l2_format *f)
1336{
1337 struct au0828_fh *fh = priv;
1338 struct au0828_dev *dev = fh->dev;
1339 int rc;
1340
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001341 rc = check_dev(dev);
1342 if (rc < 0)
1343 return rc;
1344
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001345 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Devin Heitmueller62899a22009-03-15 18:48:52 -03001346 printk(KERN_INFO "%s queue busy\n", __func__);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001347 rc = -EBUSY;
1348 goto out;
1349 }
1350
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001351 rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001352out:
1353 return rc;
1354}
1355
Hans Verkuil314527a2013-03-15 06:10:40 -03001356static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001357{
1358 struct au0828_fh *fh = priv;
1359 struct au0828_dev *dev = fh->dev;
1360
Hans Verkuilea86968f2013-03-11 16:22:13 -03001361 dev->std = norm;
1362
1363 au0828_init_tuner(dev);
1364
Hans Verkuilfa09cb92013-03-11 16:10:33 -03001365 i2c_gate_ctrl(dev, 1);
Devin Heitmuellere58071f2012-08-06 22:47:12 -03001366
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001367 /* FIXME: when we support something other than NTSC, we are going to
1368 have to make the au0828 bridge adjust the size of its capture
1369 buffer, which is currently hardcoded at 720x480 */
1370
Hans Verkuil314527a2013-03-15 06:10:40 -03001371 v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, norm);
Devin Heitmuellere58071f2012-08-06 22:47:12 -03001372
Hans Verkuilfa09cb92013-03-11 16:10:33 -03001373 i2c_gate_ctrl(dev, 0);
Devin Heitmuellere58071f2012-08-06 22:47:12 -03001374
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001375 return 0;
1376}
1377
Hans Verkuil33b6b892013-02-15 09:22:37 -03001378static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
1379{
1380 struct au0828_fh *fh = priv;
1381 struct au0828_dev *dev = fh->dev;
1382
1383 *norm = dev->std;
1384 return 0;
1385}
1386
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001387static int vidioc_enum_input(struct file *file, void *priv,
1388 struct v4l2_input *input)
1389{
1390 struct au0828_fh *fh = priv;
1391 struct au0828_dev *dev = fh->dev;
1392 unsigned int tmp;
1393
1394 static const char *inames[] = {
Devin Heitmueller3d622872009-03-15 17:48:26 -03001395 [AU0828_VMUX_UNDEFINED] = "Undefined",
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001396 [AU0828_VMUX_COMPOSITE] = "Composite",
1397 [AU0828_VMUX_SVIDEO] = "S-Video",
1398 [AU0828_VMUX_CABLE] = "Cable TV",
1399 [AU0828_VMUX_TELEVISION] = "Television",
1400 [AU0828_VMUX_DVB] = "DVB",
1401 [AU0828_VMUX_DEBUG] = "tv debug"
1402 };
1403
1404 tmp = input->index;
1405
Dan Carpenterf5e20c32010-03-28 08:21:18 -03001406 if (tmp >= AU0828_MAX_INPUT)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001407 return -EINVAL;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001408 if (AUVI_INPUT(tmp).type == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001409 return -EINVAL;
1410
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001411 input->index = tmp;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001412 strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
Devin Heitmueller62899a22009-03-15 18:48:52 -03001413 if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001414 (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001415 input->type |= V4L2_INPUT_TYPE_TUNER;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001416 input->audioset = 1;
1417 } else {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001418 input->type |= V4L2_INPUT_TYPE_CAMERA;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001419 input->audioset = 2;
1420 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001421
1422 input->std = dev->vdev->tvnorms;
1423
1424 return 0;
1425}
1426
1427static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1428{
1429 struct au0828_fh *fh = priv;
1430 struct au0828_dev *dev = fh->dev;
1431 *i = dev->ctrl_input;
1432 return 0;
1433}
1434
Hans Verkuil56230d12013-03-11 16:18:31 -03001435static void au0828_s_input(struct au0828_dev *dev, int index)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001436{
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001437 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001438
Devin Heitmueller62899a22009-03-15 18:48:52 -03001439 switch (AUVI_INPUT(index).type) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001440 case AU0828_VMUX_SVIDEO:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001441 dev->input_type = AU0828_VMUX_SVIDEO;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001442 dev->ctrl_ainput = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001443 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001444 case AU0828_VMUX_COMPOSITE:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001445 dev->input_type = AU0828_VMUX_COMPOSITE;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001446 dev->ctrl_ainput = 1;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001447 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001448 case AU0828_VMUX_TELEVISION:
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001449 dev->input_type = AU0828_VMUX_TELEVISION;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001450 dev->ctrl_ainput = 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001451 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001452 default:
Hans Verkuil56230d12013-03-11 16:18:31 -03001453 dprintk(1, "unknown input type set [%d]\n",
Devin Heitmuellera1094c42009-03-15 17:43:13 -03001454 AUVI_INPUT(index).type);
1455 break;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001456 }
1457
Hans Verkuil5325b422009-04-02 11:26:22 -03001458 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
1459 AUVI_INPUT(index).vmux, 0, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001460
1461 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1462 int enable = 0;
Devin Heitmueller62899a22009-03-15 18:48:52 -03001463 if (AUVI_INPUT(i).audio_setup == NULL)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001464 continue;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001465
1466 if (i == index)
1467 enable = 1;
1468 else
1469 enable = 0;
1470 if (enable) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001471 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001472 } else {
1473 /* Make sure we leave it turned on if some
1474 other input is routed to this callback */
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -03001475 if ((AUVI_INPUT(i).audio_setup) !=
1476 ((AUVI_INPUT(index).audio_setup))) {
1477 (AUVI_INPUT(i).audio_setup)(dev, enable);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001478 }
1479 }
1480 }
1481
Hans Verkuil5325b422009-04-02 11:26:22 -03001482 v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
1483 AUVI_INPUT(index).amux, 0, 0);
Hans Verkuil56230d12013-03-11 16:18:31 -03001484}
1485
1486static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
1487{
1488 struct au0828_fh *fh = priv;
1489 struct au0828_dev *dev = fh->dev;
1490
1491 dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
1492 index);
1493 if (index >= AU0828_MAX_INPUT)
1494 return -EINVAL;
1495 if (AUVI_INPUT(index).type == 0)
1496 return -EINVAL;
1497 dev->ctrl_input = index;
1498 au0828_s_input(dev, index);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001499 return 0;
1500}
1501
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001502static int vidioc_enumaudio(struct file *file, void *priv, struct v4l2_audio *a)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001503{
Devin Heitmueller62899a22009-03-15 18:48:52 -03001504 if (a->index > 1)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001505 return -EINVAL;
1506
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001507 if (a->index == 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001508 strcpy(a->name, "Television");
1509 else
1510 strcpy(a->name, "Line in");
1511
1512 a->capability = V4L2_AUDCAP_STEREO;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001513 return 0;
1514}
1515
1516static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
1517{
1518 struct au0828_fh *fh = priv;
1519 struct au0828_dev *dev = fh->dev;
1520
1521 a->index = dev->ctrl_ainput;
1522 if (a->index == 0)
1523 strcpy(a->name, "Television");
1524 else
1525 strcpy(a->name, "Line in");
1526
1527 a->capability = V4L2_AUDCAP_STEREO;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001528 return 0;
1529}
1530
Hans Verkuil0e8025b92012-09-04 11:59:31 -03001531static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001532{
1533 struct au0828_fh *fh = priv;
1534 struct au0828_dev *dev = fh->dev;
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001535
Devin Heitmueller62899a22009-03-15 18:48:52 -03001536 if (a->index != dev->ctrl_ainput)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001537 return -EINVAL;
1538 return 0;
1539}
1540
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001541static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
1542{
1543 struct au0828_fh *fh = priv;
1544 struct au0828_dev *dev = fh->dev;
1545
Devin Heitmueller62899a22009-03-15 18:48:52 -03001546 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001547 return -EINVAL;
1548
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001549 strcpy(t->name, "Auvitek tuner");
Hans Verkuilea86968f2013-03-11 16:22:13 -03001550
1551 au0828_init_tuner(dev);
1552 i2c_gate_ctrl(dev, 1);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001553 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
Hans Verkuilea86968f2013-03-11 16:22:13 -03001554 i2c_gate_ctrl(dev, 0);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001555 return 0;
1556}
1557
1558static int vidioc_s_tuner(struct file *file, void *priv,
Hans Verkuil2f73c7c2013-03-15 06:10:06 -03001559 const struct v4l2_tuner *t)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001560{
1561 struct au0828_fh *fh = priv;
1562 struct au0828_dev *dev = fh->dev;
1563
Devin Heitmueller62899a22009-03-15 18:48:52 -03001564 if (t->index != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001565 return -EINVAL;
1566
Hans Verkuilea86968f2013-03-11 16:22:13 -03001567 au0828_init_tuner(dev);
Hans Verkuilfa09cb92013-03-11 16:10:33 -03001568 i2c_gate_ctrl(dev, 1);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001569 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
Hans Verkuilfa09cb92013-03-11 16:10:33 -03001570 i2c_gate_ctrl(dev, 0);
Devin Heitmuellere58071f2012-08-06 22:47:12 -03001571
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001572 dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
1573 t->afc);
Devin Heitmuellere58071f2012-08-06 22:47:12 -03001574
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001575 return 0;
1576
1577}
1578
1579static int vidioc_g_frequency(struct file *file, void *priv,
1580 struct v4l2_frequency *freq)
1581{
1582 struct au0828_fh *fh = priv;
1583 struct au0828_dev *dev = fh->dev;
Devin Heitmuellerc8889232009-03-15 17:38:47 -03001584
Hans Verkuile1cf6582013-03-22 13:32:20 -03001585 if (freq->tuner != 0)
1586 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001587 freq->frequency = dev->ctrl_freq;
1588 return 0;
1589}
1590
1591static int vidioc_s_frequency(struct file *file, void *priv,
Hans Verkuilb530a442013-03-19 04:09:26 -03001592 const struct v4l2_frequency *freq)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001593{
1594 struct au0828_fh *fh = priv;
1595 struct au0828_dev *dev = fh->dev;
Hans Verkuile1cf6582013-03-22 13:32:20 -03001596 struct v4l2_frequency new_freq = *freq;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001597
Devin Heitmueller62899a22009-03-15 18:48:52 -03001598 if (freq->tuner != 0)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001599 return -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001600
Hans Verkuilea86968f2013-03-11 16:22:13 -03001601 au0828_init_tuner(dev);
Hans Verkuilfa09cb92013-03-11 16:10:33 -03001602 i2c_gate_ctrl(dev, 1);
Devin Heitmueller4a03daf2012-08-06 22:47:02 -03001603
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001604 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
Hans Verkuile1cf6582013-03-22 13:32:20 -03001605 /* Get the actual set (and possibly clamped) frequency */
1606 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, &new_freq);
1607 dev->ctrl_freq = new_freq.frequency;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001608
Hans Verkuilfa09cb92013-03-11 16:10:33 -03001609 i2c_gate_ctrl(dev, 0);
Devin Heitmueller4a03daf2012-08-06 22:47:02 -03001610
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001611 au0828_analog_stream_reset(dev);
1612
1613 return 0;
1614}
1615
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001616
1617/* RAW VBI ioctls */
1618
1619static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
1620 struct v4l2_format *format)
1621{
1622 struct au0828_fh *fh = priv;
1623 struct au0828_dev *dev = fh->dev;
1624
1625 format->fmt.vbi.samples_per_line = dev->vbi_width;
1626 format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
1627 format->fmt.vbi.offset = 0;
1628 format->fmt.vbi.flags = 0;
1629 format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
1630
1631 format->fmt.vbi.count[0] = dev->vbi_height;
1632 format->fmt.vbi.count[1] = dev->vbi_height;
1633 format->fmt.vbi.start[0] = 21;
1634 format->fmt.vbi.start[1] = 284;
Hans Verkuil8d86e4e2013-03-11 17:48:34 -03001635 memset(format->fmt.vbi.reserved, 0, sizeof(format->fmt.vbi.reserved));
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001636
1637 return 0;
1638}
1639
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001640static int vidioc_cropcap(struct file *file, void *priv,
1641 struct v4l2_cropcap *cc)
1642{
1643 struct au0828_fh *fh = priv;
1644 struct au0828_dev *dev = fh->dev;
1645
Devin Heitmueller62899a22009-03-15 18:48:52 -03001646 if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001647 return -EINVAL;
1648
1649 cc->bounds.left = 0;
1650 cc->bounds.top = 0;
1651 cc->bounds.width = dev->width;
1652 cc->bounds.height = dev->height;
1653
1654 cc->defrect = cc->bounds;
1655
1656 cc->pixelaspect.numerator = 54;
1657 cc->pixelaspect.denominator = 59;
1658
1659 return 0;
1660}
1661
1662static int vidioc_streamon(struct file *file, void *priv,
1663 enum v4l2_buf_type type)
1664{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001665 struct au0828_fh *fh = priv;
1666 struct au0828_dev *dev = fh->dev;
1667 int rc = -EINVAL;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001668
1669 rc = check_dev(dev);
1670 if (rc < 0)
1671 return rc;
1672
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001673 if (unlikely(type != fh->type))
1674 return -EINVAL;
1675
1676 dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
1677 fh, type, fh->resources, dev->resources);
1678
1679 if (unlikely(!res_get(fh, get_ressource(fh))))
1680 return -EBUSY;
1681
Hans Verkuilea86968f2013-03-11 16:22:13 -03001682 au0828_init_tuner(dev);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001683 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1684 au0828_analog_stream_enable(dev);
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001685 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001686 }
1687
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001688 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001689 rc = videobuf_streamon(&fh->vb_vidq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001690 dev->vid_timeout_running = 1;
1691 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
1692 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001693 rc = videobuf_streamon(&fh->vb_vbiq);
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001694 dev->vbi_timeout_running = 1;
1695 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1696 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001697
1698 return rc;
1699}
1700
1701static int vidioc_streamoff(struct file *file, void *priv,
1702 enum v4l2_buf_type type)
1703{
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001704 struct au0828_fh *fh = priv;
1705 struct au0828_dev *dev = fh->dev;
1706 int rc;
1707 int i;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001708
1709 rc = check_dev(dev);
1710 if (rc < 0)
1711 return rc;
1712
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001713 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1714 fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001715 return -EINVAL;
1716 if (type != fh->type)
1717 return -EINVAL;
1718
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001719 dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
1720 fh, type, fh->resources, dev->resources);
1721
1722 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001723 dev->vid_timeout_running = 0;
1724 del_timer_sync(&dev->vid_timeout);
1725
Devin Heitmueller2689d3d2009-03-15 20:01:53 -03001726 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001727 rc = au0828_stream_interrupt(dev);
1728 if (rc != 0)
1729 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001730
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001731 for (i = 0; i < AU0828_MAX_INPUT; i++) {
1732 if (AUVI_INPUT(i).audio_setup == NULL)
1733 continue;
1734 (AUVI_INPUT(i).audio_setup)(dev, 0);
1735 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001736
Devin Heitmuellera595c1c2012-08-06 22:47:03 -03001737 if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
1738 videobuf_streamoff(&fh->vb_vidq);
1739 res_free(fh, AU0828_RESOURCE_VIDEO);
1740 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001741 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Devin Heitmueller78ca5002010-10-09 14:43:53 -03001742 dev->vbi_timeout_running = 0;
1743 del_timer_sync(&dev->vbi_timeout);
1744
Devin Heitmuellera595c1c2012-08-06 22:47:03 -03001745 if (res_check(fh, AU0828_RESOURCE_VBI)) {
1746 videobuf_streamoff(&fh->vb_vbiq);
1747 res_free(fh, AU0828_RESOURCE_VBI);
1748 }
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001749 }
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001750
1751 return 0;
1752}
1753
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001754#ifdef CONFIG_VIDEO_ADV_DEBUG
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001755static int vidioc_g_register(struct file *file, void *priv,
1756 struct v4l2_dbg_register *reg)
1757{
1758 struct au0828_fh *fh = priv;
1759 struct au0828_dev *dev = fh->dev;
1760
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001761 reg->val = au0828_read(dev, reg->reg);
Hans Verkuilead5bc42013-05-29 07:00:03 -03001762 reg->size = 1;
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001763 return 0;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001764}
1765
1766static int vidioc_s_register(struct file *file, void *priv,
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001767 const struct v4l2_dbg_register *reg)
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001768{
1769 struct au0828_fh *fh = priv;
1770 struct au0828_dev *dev = fh->dev;
1771
Devin Heitmueller364d2db2012-08-06 22:46:54 -03001772 return au0828_writereg(dev, reg->reg, reg->val);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001773}
Mauro Carvalho Chehab80c6e352009-03-19 19:26:23 -03001774#endif
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001775
Hans Verkuil83b09422013-02-15 09:14:00 -03001776static int vidioc_log_status(struct file *file, void *fh)
1777{
1778 struct video_device *vdev = video_devdata(file);
1779
1780 v4l2_ctrl_log_status(file, fh);
1781 v4l2_device_call_all(vdev->v4l2_dev, 0, core, log_status);
1782 return 0;
1783}
1784
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001785static int vidioc_reqbufs(struct file *file, void *priv,
1786 struct v4l2_requestbuffers *rb)
1787{
1788 struct au0828_fh *fh = priv;
1789 struct au0828_dev *dev = fh->dev;
1790 int rc;
1791
1792 rc = check_dev(dev);
1793 if (rc < 0)
1794 return rc;
1795
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001796 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1797 rc = videobuf_reqbufs(&fh->vb_vidq, rb);
1798 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1799 rc = videobuf_reqbufs(&fh->vb_vbiq, rb);
1800
1801 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001802}
1803
1804static int vidioc_querybuf(struct file *file, void *priv,
1805 struct v4l2_buffer *b)
1806{
1807 struct au0828_fh *fh = priv;
1808 struct au0828_dev *dev = fh->dev;
1809 int rc;
1810
1811 rc = check_dev(dev);
1812 if (rc < 0)
1813 return rc;
1814
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001815 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1816 rc = videobuf_querybuf(&fh->vb_vidq, b);
1817 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1818 rc = videobuf_querybuf(&fh->vb_vbiq, b);
1819
1820 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001821}
1822
1823static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1824{
1825 struct au0828_fh *fh = priv;
1826 struct au0828_dev *dev = fh->dev;
1827 int rc;
1828
1829 rc = check_dev(dev);
1830 if (rc < 0)
1831 return rc;
1832
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001833 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1834 rc = videobuf_qbuf(&fh->vb_vidq, b);
1835 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1836 rc = videobuf_qbuf(&fh->vb_vbiq, b);
1837
1838 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001839}
1840
1841static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1842{
1843 struct au0828_fh *fh = priv;
1844 struct au0828_dev *dev = fh->dev;
1845 int rc;
1846
1847 rc = check_dev(dev);
1848 if (rc < 0)
1849 return rc;
1850
1851 /* Workaround for a bug in the au0828 hardware design that sometimes
1852 results in the colorspace being inverted */
1853 if (dev->greenscreen_detected == 1) {
1854 dprintk(1, "Detected green frame. Resetting stream...\n");
1855 au0828_analog_stream_reset(dev);
1856 dev->greenscreen_detected = 0;
1857 }
1858
Devin Heitmueller54ebb8b2011-01-23 19:12:27 -03001859 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1860 rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1861 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1862 rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK);
1863
1864 return rc;
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001865}
1866
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001867static struct v4l2_file_operations au0828_v4l_fops = {
1868 .owner = THIS_MODULE,
1869 .open = au0828_v4l2_open,
1870 .release = au0828_v4l2_close,
1871 .read = au0828_v4l2_read,
1872 .poll = au0828_v4l2_poll,
1873 .mmap = au0828_v4l2_mmap,
Devin Heitmueller549ee4d2012-08-06 22:46:58 -03001874 .unlocked_ioctl = video_ioctl2,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001875};
1876
1877static const struct v4l2_ioctl_ops video_ioctl_ops = {
1878 .vidioc_querycap = vidioc_querycap,
1879 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1880 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1881 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1882 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Devin Heitmueller5a5a4e12009-03-11 03:00:55 -03001883 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuil8d86e4e2013-03-11 17:48:34 -03001884 .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Devin Heitmueller7f8eacd2010-05-29 17:18:45 -03001885 .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
Hans Verkuila2cf96f2013-02-15 08:41:24 -03001886 .vidioc_enumaudio = vidioc_enumaudio,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001887 .vidioc_g_audio = vidioc_g_audio,
1888 .vidioc_s_audio = vidioc_s_audio,
1889 .vidioc_cropcap = vidioc_cropcap,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001890 .vidioc_reqbufs = vidioc_reqbufs,
1891 .vidioc_querybuf = vidioc_querybuf,
1892 .vidioc_qbuf = vidioc_qbuf,
1893 .vidioc_dqbuf = vidioc_dqbuf,
1894 .vidioc_s_std = vidioc_s_std,
Hans Verkuil33b6b892013-02-15 09:22:37 -03001895 .vidioc_g_std = vidioc_g_std,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001896 .vidioc_enum_input = vidioc_enum_input,
1897 .vidioc_g_input = vidioc_g_input,
1898 .vidioc_s_input = vidioc_s_input,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001899 .vidioc_streamon = vidioc_streamon,
1900 .vidioc_streamoff = vidioc_streamoff,
1901 .vidioc_g_tuner = vidioc_g_tuner,
1902 .vidioc_s_tuner = vidioc_s_tuner,
1903 .vidioc_g_frequency = vidioc_g_frequency,
1904 .vidioc_s_frequency = vidioc_s_frequency,
1905#ifdef CONFIG_VIDEO_ADV_DEBUG
1906 .vidioc_g_register = vidioc_g_register,
1907 .vidioc_s_register = vidioc_s_register,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -03001908#endif
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