blob: 523f78c48472300cb9b046461be6577c35d489b7 [file] [log] [blame]
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001/*
2 * Virtual Video driver - This code emulates a real video device with v4l2 api
3 *
4 * Copyright (c) 2006 by:
5 * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
6 * Ted Walther <ted--a.t--enumera.com>
7 * John Sokol <sokol--a.t--videotechnology.com>
8 * http://v4l.videotechnology.com/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the BSD Licence, GNU General Public License
12 * as published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version
14 */
15#include <linux/module.h>
16#include <linux/delay.h>
17#include <linux/errno.h>
18#include <linux/fs.h>
19#include <linux/kernel.h>
20#include <linux/slab.h>
21#include <linux/mm.h>
22#include <linux/ioport.h>
23#include <linux/init.h>
24#include <linux/sched.h>
25#include <linux/pci.h>
26#include <linux/random.h>
27#include <linux/version.h>
Matthias Kaehlcke51b54022007-07-02 10:19:38 -030028#include <linux/mutex.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030029#include <linux/videodev2.h>
Andrew Morton10951362006-04-27 10:10:58 -030030#include <linux/dma-mapping.h>
Mauro Carvalho Chehabcd41e282006-04-09 15:43:41 -030031#ifdef CONFIG_VIDEO_V4L1_COMPAT
32/* Include V4L1 specific functions. Should be removed soon */
33#include <linux/videodev.h>
34#endif
Michael Krufkyf13df912006-03-23 22:01:44 -030035#include <linux/interrupt.h>
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -030036#include <media/videobuf-vmalloc.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030037#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030038#include <media/v4l2-ioctl.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030039#include <linux/kthread.h>
40#include <linux/highmem.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080041#include <linux/freezer.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030042
Mauro Carvalho Chehab584ce482008-06-10 15:21:49 -030043#define VIVI_MODULE_NAME "vivi"
Carl Karsten745271a2008-06-10 00:02:32 -030044
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030045/* Wake up at about 30 fps */
46#define WAKE_NUMERATOR 30
47#define WAKE_DENOMINATOR 1001
48#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
49
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030050#include "font.h"
51
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030052#define VIVI_MAJOR_VERSION 0
Carl Karsten745271a2008-06-10 00:02:32 -030053#define VIVI_MINOR_VERSION 5
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030054#define VIVI_RELEASE 0
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -030055#define VIVI_VERSION \
56 KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030057
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -030058/* Declare static vars that will be used as parameters */
59static unsigned int vid_limit = 16; /* Video memory limit, in Mb */
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -030060static int video_nr = -1; /* /dev/videoN, -1 for autodetect */
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -030061static int n_devs = 1; /* Number of virtual devices */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030062
63/* supported controls */
64static struct v4l2_queryctrl vivi_qctrl[] = {
65 {
66 .id = V4L2_CID_AUDIO_VOLUME,
67 .name = "Volume",
68 .minimum = 0,
69 .maximum = 65535,
70 .step = 65535/100,
71 .default_value = 65535,
72 .flags = 0,
73 .type = V4L2_CTRL_TYPE_INTEGER,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -030074 }, {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030075 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = 0,
79 .maximum = 255,
80 .step = 1,
81 .default_value = 127,
82 .flags = 0,
83 }, {
84 .id = V4L2_CID_CONTRAST,
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .name = "Contrast",
87 .minimum = 0,
88 .maximum = 255,
89 .step = 0x1,
90 .default_value = 0x10,
91 .flags = 0,
92 }, {
93 .id = V4L2_CID_SATURATION,
94 .type = V4L2_CTRL_TYPE_INTEGER,
95 .name = "Saturation",
96 .minimum = 0,
97 .maximum = 255,
98 .step = 0x1,
99 .default_value = 127,
100 .flags = 0,
101 }, {
102 .id = V4L2_CID_HUE,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Hue",
105 .minimum = -128,
106 .maximum = 127,
107 .step = 0x1,
108 .default_value = 0,
109 .flags = 0,
110 }
111};
112
113static int qctl_regs[ARRAY_SIZE(vivi_qctrl)];
114
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300115#define dprintk(dev, level, fmt, arg...) \
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300116 do { \
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300117 if (dev->vfd->debug >= (level)) \
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300118 printk(KERN_DEBUG "vivi: " fmt , ## arg); \
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300119 } while (0)
120
121/* ------------------------------------------------------------------
122 Basic structures
123 ------------------------------------------------------------------*/
124
125struct vivi_fmt {
126 char *name;
127 u32 fourcc; /* v4l2 format id */
128 int depth;
129};
130
Magnus Dammd891f472008-10-14 12:47:09 -0300131static struct vivi_fmt formats[] = {
132 {
133 .name = "4:2:2, packed, YUYV",
134 .fourcc = V4L2_PIX_FMT_YUYV,
135 .depth = 16,
136 },
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300137};
138
Magnus Dammd891f472008-10-14 12:47:09 -0300139static struct vivi_fmt *get_format(struct v4l2_format *f)
140{
141 struct vivi_fmt *fmt;
142 unsigned int k;
143
144 for (k = 0; k < ARRAY_SIZE(formats); k++) {
145 fmt = &formats[k];
146 if (fmt->fourcc == f->fmt.pix.pixelformat)
147 break;
148 }
149
150 if (k == ARRAY_SIZE(formats))
151 return NULL;
152
153 return &formats[k];
154}
155
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300156struct sg_to_addr {
157 int pos;
158 struct scatterlist *sg;
159};
160
161/* buffer for one video frame */
162struct vivi_buffer {
163 /* common v4l buffer stuff -- must be first */
164 struct videobuf_buffer vb;
165
166 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300167};
168
169struct vivi_dmaqueue {
170 struct list_head active;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300171
172 /* thread for generating video stream*/
173 struct task_struct *kthread;
174 wait_queue_head_t wq;
175 /* Counters to control fps rate */
176 int frame;
177 int ini_jiffies;
178};
179
180static LIST_HEAD(vivi_devlist);
181
182struct vivi_dev {
183 struct list_head vivi_devlist;
184
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300185 spinlock_t slock;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300186 struct mutex mutex;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300187
188 int users;
189
190 /* various device info */
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -0300191 struct video_device *vfd;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300192
193 struct vivi_dmaqueue vidq;
194
195 /* Several counters */
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300196 int h, m, s, ms;
197 unsigned long jiffies;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300198 char timestr[13];
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300199
200 int mv_count; /* Controls bars movement */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300201};
202
203struct vivi_fh {
204 struct vivi_dev *dev;
205
206 /* video capture */
207 struct vivi_fmt *fmt;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300208 unsigned int width, height;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300209 struct videobuf_queue vb_vidq;
210
211 enum v4l2_buf_type type;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300212 unsigned char bars[8][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300213};
214
215/* ------------------------------------------------------------------
216 DMA and thread functions
217 ------------------------------------------------------------------*/
218
219/* Bars and Colors should match positions */
220
221enum colors {
222 WHITE,
223 AMBAR,
224 CYAN,
225 GREEN,
226 MAGENTA,
227 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300228 BLUE,
229 BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300230};
231
232static u8 bars[8][3] = {
233 /* R G B */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300234 {204, 204, 204}, /* white */
235 {208, 208, 0}, /* ambar */
236 { 0, 206, 206}, /* cyan */
237 { 0, 239, 0}, /* green */
238 {239, 0, 239}, /* magenta */
239 {205, 0, 0}, /* red */
240 { 0, 0, 255}, /* blue */
241 { 0, 0, 0}, /* black */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300242};
243
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300244#define TO_Y(r, g, b) \
245 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300246/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300247#define TO_V(r, g, b) \
248 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300249/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300250#define TO_U(r, g, b) \
251 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300252
253#define TSTAMP_MIN_Y 24
254#define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
255#define TSTAMP_MIN_X 64
256
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300257static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
258{
259 unsigned char r_y, g_u, b_v;
260 unsigned char *p;
261 int color;
262
263 r_y = fh->bars[colorpos][0]; /* R or precalculated Y */
264 g_u = fh->bars[colorpos][1]; /* G or precalculated U */
265 b_v = fh->bars[colorpos][2]; /* B or precalculated V */
266
267 for (color = 0; color < 4; color++) {
268 p = buf + color;
269
Magnus Dammd891f472008-10-14 12:47:09 -0300270 switch (fh->fmt->fourcc) {
271 case V4L2_PIX_FMT_YUYV:
272 switch (color) {
273 case 0:
274 case 2:
275 *p = r_y;
276 break;
277 case 1:
278 *p = g_u;
279 break;
280 case 3:
281 *p = b_v;
282 break;
283 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300284 break;
285 }
286 }
287}
288
289static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300290 int hmax, int line, int count, char *timestr)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300291{
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300292 int w, i, j;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300293 int pos = inipos;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300294 char *s;
295 u8 chr;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300296
297 /* We will just duplicate the second pixel at the packet */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300298 wmax /= 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300299
300 /* Generate a standard color bar pattern */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300301 for (w = 0; w < wmax; w++) {
302 int colorpos = ((w + count) * 8/(wmax + 1)) % 8;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300303
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300304 gen_twopix(fh, basep + pos, colorpos);
305 pos += 4; /* only 16 bpp supported for now */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300306 }
307
308 /* Checks if it is possible to show timestamp */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300309 if (TSTAMP_MAX_Y >= hmax)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300310 goto end;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300311 if (TSTAMP_MIN_X + strlen(timestr) >= wmax)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300312 goto end;
313
314 /* Print stream time */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300315 if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
316 j = TSTAMP_MIN_X;
317 for (s = timestr; *s; s++) {
318 chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y];
319 for (i = 0; i < 7; i++) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300320 pos = inipos + j * 2;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300321 /* Draw white font on black background */
322 if (chr & 1 << (7 - i))
323 gen_twopix(fh, basep + pos, WHITE);
324 else
325 gen_twopix(fh, basep + pos, BLACK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300326 j++;
327 }
328 }
329 }
330
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300331end:
Mauro Carvalho Chehabb50e7fe2007-01-25 05:00:01 -0300332 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300333}
Brandon Philips78718e52008-04-02 18:10:59 -0300334
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300335static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300336{
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300337 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300338 int h , pos = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300339 int hmax = buf->vb.height;
340 int wmax = buf->vb.width;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300341 struct timeval ts;
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300342 char *tmpbuf;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300343 void *vbuf = videobuf_to_vmalloc(&buf->vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300344
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300345 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300346 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300347
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300348 tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);
349 if (!tmpbuf)
Brandon Philips78718e52008-04-02 18:10:59 -0300350 return;
351
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300352 for (h = 0; h < hmax; h++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300353 gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count,
Mauro Carvalho Chehab3bef5e42007-09-22 02:01:33 -0300354 dev->timestr);
Brandon Philips78718e52008-04-02 18:10:59 -0300355 memcpy(vbuf + pos, tmpbuf, wmax * 2);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300356 pos += wmax*2;
357 }
358
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300359 dev->mv_count++;
Mauro Carvalho Chehab3bef5e42007-09-22 02:01:33 -0300360
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300361 kfree(tmpbuf);
362
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300363 /* Updates stream time */
364
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300365 dev->ms += jiffies_to_msecs(jiffies-dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300366 dev->jiffies = jiffies;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300367 if (dev->ms >= 1000) {
368 dev->ms -= 1000;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300369 dev->s++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300370 if (dev->s >= 60) {
371 dev->s -= 60;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300372 dev->m++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300373 if (dev->m > 60) {
374 dev->m -= 60;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300375 dev->h++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300376 if (dev->h > 24)
377 dev->h -= 24;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300378 }
379 }
380 }
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300381 sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300382 dev->h, dev->m, dev->s, dev->ms);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300383
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300384 dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n",
385 dev->timestr, (unsigned long)tmpbuf, pos);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300386
387 /* Advice that buffer was filled */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300388 buf->vb.field_count++;
389 do_gettimeofday(&ts);
390 buf->vb.ts = ts;
Brandon Philips78718e52008-04-02 18:10:59 -0300391 buf->vb.state = VIDEOBUF_DONE;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300392}
393
Brandon Philips78718e52008-04-02 18:10:59 -0300394static void vivi_thread_tick(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300395{
Brandon Philips78718e52008-04-02 18:10:59 -0300396 struct vivi_buffer *buf;
397 struct vivi_dev *dev = fh->dev;
398 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300399
Brandon Philips78718e52008-04-02 18:10:59 -0300400 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300401
Brandon Philips78718e52008-04-02 18:10:59 -0300402 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300403
Brandon Philips78718e52008-04-02 18:10:59 -0300404 spin_lock_irqsave(&dev->slock, flags);
405 if (list_empty(&dma_q->active)) {
406 dprintk(dev, 1, "No active queue to serve\n");
407 goto unlock;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300408 }
Brandon Philips78718e52008-04-02 18:10:59 -0300409
410 buf = list_entry(dma_q->active.next,
411 struct vivi_buffer, vb.queue);
412
413 /* Nobody is waiting on this buffer, return */
414 if (!waitqueue_active(&buf->vb.done))
415 goto unlock;
416
417 list_del(&buf->vb.queue);
418
419 do_gettimeofday(&buf->vb.ts);
420
421 /* Fill buffer */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300422 vivi_fillbuff(fh, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300423 dprintk(dev, 1, "filled buffer %p\n", buf);
424
425 wake_up(&buf->vb.done);
426 dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
427unlock:
428 spin_unlock_irqrestore(&dev->slock, flags);
429 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300430}
431
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300432#define frames_to_ms(frames) \
433 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
434
Brandon Philips78718e52008-04-02 18:10:59 -0300435static void vivi_sleep(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300436{
Brandon Philips78718e52008-04-02 18:10:59 -0300437 struct vivi_dev *dev = fh->dev;
438 struct vivi_dmaqueue *dma_q = &dev->vidq;
439 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300440 DECLARE_WAITQUEUE(wait, current);
441
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300442 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300443 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300444
445 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300446 if (kthread_should_stop())
447 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300448
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300449 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300450 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300451
Brandon Philips78718e52008-04-02 18:10:59 -0300452 vivi_thread_tick(fh);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300453
454 schedule_timeout_interruptible(timeout);
455
456stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300457 remove_wait_queue(&dma_q->wq, &wait);
458 try_to_freeze();
459}
460
Adrian Bunk972c3512006-04-27 21:06:50 -0300461static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300462{
Brandon Philips78718e52008-04-02 18:10:59 -0300463 struct vivi_fh *fh = data;
464 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300465
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300466 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300467
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700468 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300469
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300470 for (;;) {
Brandon Philips78718e52008-04-02 18:10:59 -0300471 vivi_sleep(fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300472
473 if (kthread_should_stop())
474 break;
475 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300476 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300477 return 0;
478}
479
Brandon Philips78718e52008-04-02 18:10:59 -0300480static int vivi_start_thread(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300481{
Brandon Philips78718e52008-04-02 18:10:59 -0300482 struct vivi_dev *dev = fh->dev;
483 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300484
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300485 dma_q->frame = 0;
486 dma_q->ini_jiffies = jiffies;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300487
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300488 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300489
Brandon Philips78718e52008-04-02 18:10:59 -0300490 dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300491
Akinobu Mita054afee2006-12-20 10:04:00 -0300492 if (IS_ERR(dma_q->kthread)) {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300493 printk(KERN_ERR "vivi: kernel_thread() failed\n");
Akinobu Mita054afee2006-12-20 10:04:00 -0300494 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300495 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300496 /* Wakes thread */
497 wake_up_interruptible(&dma_q->wq);
498
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300499 dprintk(dev, 1, "returning from %s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300500 return 0;
501}
502
Adrian Bunk972c3512006-04-27 21:06:50 -0300503static void vivi_stop_thread(struct vivi_dmaqueue *dma_q)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300504{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300505 struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
506
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300507 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300508 /* shutdown control thread */
509 if (dma_q->kthread) {
510 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300511 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300512 }
513}
514
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300515/* ------------------------------------------------------------------
516 Videobuf operations
517 ------------------------------------------------------------------*/
518static int
519buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
520{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300521 struct vivi_fh *fh = vq->priv_data;
522 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300523
524 *size = fh->width*fh->height*2;
525
526 if (0 == *count)
527 *count = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300528
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300529 while (*size * *count > vid_limit * 1024 * 1024)
530 (*count)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300531
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300532 dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300533 *count, *size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300534
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300535 return 0;
536}
537
Adrian Bunk972c3512006-04-27 21:06:50 -0300538static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300539{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300540 struct vivi_fh *fh = vq->priv_data;
541 struct vivi_dev *dev = fh->dev;
542
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300543 dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300544
545 if (in_interrupt())
546 BUG();
547
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300548 videobuf_vmalloc_free(&buf->vb);
Mauro Carvalho Chehabfbde31d2008-04-13 14:57:44 -0300549 dprintk(dev, 1, "free_buffer: freed\n");
Brandon Philips0fc06862007-11-06 20:02:36 -0300550 buf->vb.state = VIDEOBUF_NEEDS_INIT;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300551}
552
553#define norm_maxw() 1024
554#define norm_maxh() 768
555static int
556buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
557 enum v4l2_field field)
558{
559 struct vivi_fh *fh = vq->priv_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300560 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300561 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300562 int rc;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300563
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300564 dprintk(dev, 1, "%s, field=%d\n", __func__, field);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300565
566 BUG_ON(NULL == fh->fmt);
Brandon Philips78718e52008-04-02 18:10:59 -0300567
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300568 if (fh->width < 48 || fh->width > norm_maxw() ||
569 fh->height < 32 || fh->height > norm_maxh())
570 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300571
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300572 buf->vb.size = fh->width*fh->height*2;
573 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
574 return -EINVAL;
575
Brandon Philips78718e52008-04-02 18:10:59 -0300576 /* These properties only change when queue is idle, see s_fmt */
577 buf->fmt = fh->fmt;
578 buf->vb.width = fh->width;
579 buf->vb.height = fh->height;
580 buf->vb.field = field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300581
Brandon Philips0fc06862007-11-06 20:02:36 -0300582 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300583 rc = videobuf_iolock(vq, &buf->vb, NULL);
584 if (rc < 0)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300585 goto fail;
586 }
587
Brandon Philips0fc06862007-11-06 20:02:36 -0300588 buf->vb.state = VIDEOBUF_PREPARED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300589
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300590 return 0;
591
592fail:
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300593 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300594 return rc;
595}
596
597static void
598buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
599{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300600 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
601 struct vivi_fh *fh = vq->priv_data;
602 struct vivi_dev *dev = fh->dev;
Brandon Philips78718e52008-04-02 18:10:59 -0300603 struct vivi_dmaqueue *vidq = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300604
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300605 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300606
Brandon Philips78718e52008-04-02 18:10:59 -0300607 buf->vb.state = VIDEOBUF_QUEUED;
608 list_add_tail(&buf->vb.queue, &vidq->active);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300609}
610
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300611static void buffer_release(struct videobuf_queue *vq,
612 struct videobuf_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300613{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300614 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300615 struct vivi_fh *fh = vq->priv_data;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300616 struct vivi_dev *dev = (struct vivi_dev *)fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300617
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300618 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300619
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300620 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300621}
622
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300623static struct videobuf_queue_ops vivi_video_qops = {
624 .buf_setup = buffer_setup,
625 .buf_prepare = buffer_prepare,
626 .buf_queue = buffer_queue,
627 .buf_release = buffer_release,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300628};
629
630/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300631 IOCTL vidioc handling
632 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300633static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300634 struct v4l2_capability *cap)
635{
636 strcpy(cap->driver, "vivi");
637 strcpy(cap->card, "vivi");
638 cap->version = VIVI_VERSION;
639 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
640 V4L2_CAP_STREAMING |
641 V4L2_CAP_READWRITE;
642 return 0;
643}
644
Hans Verkuil78b526a2008-05-28 12:16:41 -0300645static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300646 struct v4l2_fmtdesc *f)
647{
Magnus Dammd891f472008-10-14 12:47:09 -0300648 struct vivi_fmt *fmt;
649
650 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300651 return -EINVAL;
652
Magnus Dammd891f472008-10-14 12:47:09 -0300653 fmt = &formats[f->index];
654
655 strlcpy(f->description, fmt->name, sizeof(f->description));
656 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300657 return 0;
658}
659
Hans Verkuil78b526a2008-05-28 12:16:41 -0300660static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300661 struct v4l2_format *f)
662{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300663 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300664
665 f->fmt.pix.width = fh->width;
666 f->fmt.pix.height = fh->height;
667 f->fmt.pix.field = fh->vb_vidq.field;
668 f->fmt.pix.pixelformat = fh->fmt->fourcc;
669 f->fmt.pix.bytesperline =
670 (f->fmt.pix.width * fh->fmt->depth) >> 3;
671 f->fmt.pix.sizeimage =
672 f->fmt.pix.height * f->fmt.pix.bytesperline;
673
674 return (0);
675}
676
Hans Verkuil78b526a2008-05-28 12:16:41 -0300677static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300678 struct v4l2_format *f)
679{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300680 struct vivi_fh *fh = priv;
681 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300682 struct vivi_fmt *fmt;
683 enum v4l2_field field;
684 unsigned int maxw, maxh;
685
Magnus Dammd891f472008-10-14 12:47:09 -0300686 fmt = get_format(f);
687 if (!fmt) {
688 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
689 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300690 return -EINVAL;
691 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300692
693 field = f->fmt.pix.field;
694
695 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300696 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300697 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300698 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300699 return -EINVAL;
700 }
701
702 maxw = norm_maxw();
703 maxh = norm_maxh();
704
705 f->fmt.pix.field = field;
706 if (f->fmt.pix.height < 32)
707 f->fmt.pix.height = 32;
708 if (f->fmt.pix.height > maxh)
709 f->fmt.pix.height = maxh;
710 if (f->fmt.pix.width < 48)
711 f->fmt.pix.width = 48;
712 if (f->fmt.pix.width > maxw)
713 f->fmt.pix.width = maxw;
714 f->fmt.pix.width &= ~0x03;
715 f->fmt.pix.bytesperline =
716 (f->fmt.pix.width * fmt->depth) >> 3;
717 f->fmt.pix.sizeimage =
718 f->fmt.pix.height * f->fmt.pix.bytesperline;
719
720 return 0;
721}
722
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300723/*FIXME: This seems to be generic enough to be at videodev2 */
Hans Verkuil78b526a2008-05-28 12:16:41 -0300724static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300725 struct v4l2_format *f)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300726{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300727 struct vivi_fh *fh = priv;
Brandon Philips78718e52008-04-02 18:10:59 -0300728 struct videobuf_queue *q = &fh->vb_vidq;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300729 unsigned char r, g, b;
Magnus Dammd891f472008-10-14 12:47:09 -0300730 int k, is_yuv;
Brandon Philips78718e52008-04-02 18:10:59 -0300731
Hans Verkuil78b526a2008-05-28 12:16:41 -0300732 int ret = vidioc_try_fmt_vid_cap(file, fh, f);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300733 if (ret < 0)
734 return (ret);
735
Brandon Philips78718e52008-04-02 18:10:59 -0300736 mutex_lock(&q->vb_lock);
737
738 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300739 dprintk(fh->dev, 1, "%s queue busy\n", __func__);
Brandon Philips78718e52008-04-02 18:10:59 -0300740 ret = -EBUSY;
741 goto out;
742 }
743
Magnus Dammd891f472008-10-14 12:47:09 -0300744 fh->fmt = get_format(f);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300745 fh->width = f->fmt.pix.width;
746 fh->height = f->fmt.pix.height;
747 fh->vb_vidq.field = f->fmt.pix.field;
748 fh->type = f->type;
749
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300750 /* precalculate color bar values to speed up rendering */
751 for (k = 0; k < 8; k++) {
752 r = bars[k][0];
753 g = bars[k][1];
754 b = bars[k][2];
Magnus Dammd891f472008-10-14 12:47:09 -0300755 is_yuv = 0;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300756
Magnus Dammd891f472008-10-14 12:47:09 -0300757 switch (fh->fmt->fourcc) {
758 case V4L2_PIX_FMT_YUYV:
759 is_yuv = 1;
760 break;
761 }
762
763 if (is_yuv) {
764 fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
765 fh->bars[k][1] = TO_U(r, g, b); /* Cb */
766 fh->bars[k][2] = TO_V(r, g, b); /* Cr */
767 } else {
768 fh->bars[k][0] = r;
769 fh->bars[k][1] = g;
770 fh->bars[k][2] = b;
771 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300772 }
773
Brandon Philips78718e52008-04-02 18:10:59 -0300774 ret = 0;
775out:
776 mutex_unlock(&q->vb_lock);
777
778 return (ret);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300779}
780
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300781static int vidioc_reqbufs(struct file *file, void *priv,
782 struct v4l2_requestbuffers *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300783{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300784 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300785
786 return (videobuf_reqbufs(&fh->vb_vidq, p));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300787}
788
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300789static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300790{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300791 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300792
793 return (videobuf_querybuf(&fh->vb_vidq, p));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300794}
795
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300796static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300797{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300798 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300799
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300800 return (videobuf_qbuf(&fh->vb_vidq, p));
801}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300802
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300803static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300804{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300805 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300806
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300807 return (videobuf_dqbuf(&fh->vb_vidq, p,
808 file->f_flags & O_NONBLOCK));
809}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300810
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -0300811#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300812static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300813{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300814 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300815
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300816 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300817}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300818#endif
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300819
Adrian Bunkdc46ace2006-06-23 06:42:44 -0300820static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300821{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300822 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300823
824 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
825 return -EINVAL;
826 if (i != fh->type)
827 return -EINVAL;
828
Brandon Philipsba32bd92007-09-27 20:55:17 -0300829 return videobuf_streamon(&fh->vb_vidq);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300830}
831
Adrian Bunkdc46ace2006-06-23 06:42:44 -0300832static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300833{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300834 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300835
836 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
837 return -EINVAL;
838 if (i != fh->type)
839 return -EINVAL;
840
Brandon Philipsba32bd92007-09-27 20:55:17 -0300841 return videobuf_streamoff(&fh->vb_vidq);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300842}
843
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300844static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300845{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300846 return 0;
847}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300848
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300849/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300850static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300851 struct v4l2_input *inp)
852{
853 if (inp->index != 0)
854 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300855
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300856 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -0300857 inp->std = V4L2_STD_525_60;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300858 strcpy(inp->name, "Camera");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300859
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300860 return (0);
861}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300862
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300863static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300864{
865 *i = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300866
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300867 return (0);
868}
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300869static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300870{
871 if (i > 0)
872 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300873
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300874 return (0);
875}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300876
877 /* --- controls ---------------------------------------------- */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300878static int vidioc_queryctrl(struct file *file, void *priv,
879 struct v4l2_queryctrl *qc)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300880{
881 int i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300882
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300883 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
884 if (qc->id && qc->id == vivi_qctrl[i].id) {
885 memcpy(qc, &(vivi_qctrl[i]),
886 sizeof(*qc));
887 return (0);
888 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300889
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300890 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300891}
892
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300893static int vidioc_g_ctrl(struct file *file, void *priv,
894 struct v4l2_control *ctrl)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300895{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300896 int i;
897
898 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
899 if (ctrl->id == vivi_qctrl[i].id) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300900 ctrl->value = qctl_regs[i];
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300901 return (0);
902 }
903
904 return -EINVAL;
905}
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300906static int vidioc_s_ctrl(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300907 struct v4l2_control *ctrl)
908{
909 int i;
910
911 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
912 if (ctrl->id == vivi_qctrl[i].id) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300913 if (ctrl->value < vivi_qctrl[i].minimum
914 || ctrl->value > vivi_qctrl[i].maximum) {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300915 return (-ERANGE);
916 }
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300917 qctl_regs[i] = ctrl->value;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300918 return (0);
919 }
920 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300921}
922
923/* ------------------------------------------------------------------
924 File operations for the device
925 ------------------------------------------------------------------*/
926
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300927static int vivi_open(struct inode *inode, struct file *file)
928{
929 int minor = iminor(inode);
Trent Piephoa991f442007-10-10 05:37:43 -0300930 struct vivi_dev *dev;
Mauro Carvalho Chehab63b79cf2008-04-26 08:25:18 -0300931 struct vivi_fh *fh = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300932 int i;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300933 int retval = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300934
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300935 printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300936
Hans Verkuild56dc612008-07-30 08:43:36 -0300937 lock_kernel();
Trent Piephoa991f442007-10-10 05:37:43 -0300938 list_for_each_entry(dev, &vivi_devlist, vivi_devlist)
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -0300939 if (dev->vfd->minor == minor)
Trent Piephoa991f442007-10-10 05:37:43 -0300940 goto found;
Hans Verkuild56dc612008-07-30 08:43:36 -0300941 unlock_kernel();
Trent Piephoa991f442007-10-10 05:37:43 -0300942 return -ENODEV;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300943
Trent Piephoa991f442007-10-10 05:37:43 -0300944found:
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300945 mutex_lock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300946 dev->users++;
947
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300948 if (dev->users > 1) {
949 dev->users--;
950 retval = -EBUSY;
951 goto unlock;
952 }
953
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300954 dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor,
Trent Piephoa991f442007-10-10 05:37:43 -0300955 v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300956
957 /* allocate + initialize per filehandle data */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300958 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300959 if (NULL == fh) {
960 dev->users--;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300961 retval = -ENOMEM;
962 goto unlock;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300963 }
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300964unlock:
965 mutex_unlock(&dev->mutex);
Hans Verkuild56dc612008-07-30 08:43:36 -0300966 if (retval) {
967 unlock_kernel();
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300968 return retval;
Hans Verkuild56dc612008-07-30 08:43:36 -0300969 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300970
971 file->private_data = fh;
972 fh->dev = dev;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300973
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300974 fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Magnus Dammd891f472008-10-14 12:47:09 -0300975 fh->fmt = &formats[0];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300976 fh->width = 640;
977 fh->height = 480;
978
979 /* Put all controls at a sane state */
980 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300981 qctl_regs[i] = vivi_qctrl[i].default_value;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300982
983 /* Resets frame counters */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300984 dev->h = 0;
985 dev->m = 0;
986 dev->s = 0;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300987 dev->ms = 0;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300988 dev->mv_count = 0;
989 dev->jiffies = jiffies;
990 sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300991 dev->h, dev->m, dev->s, dev->ms);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300992
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300993 videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops,
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300994 NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300995 sizeof(struct vivi_buffer), fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300996
Brandon Philips78718e52008-04-02 18:10:59 -0300997 vivi_start_thread(fh);
Hans Verkuild56dc612008-07-30 08:43:36 -0300998 unlock_kernel();
Brandon Philips78718e52008-04-02 18:10:59 -0300999
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001000 return 0;
1001}
1002
1003static ssize_t
1004vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1005{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001006 struct vivi_fh *fh = file->private_data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001007
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001008 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Mauro Carvalho Chehabacb09af2007-07-29 22:56:11 -03001009 return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001010 file->f_flags & O_NONBLOCK);
1011 }
1012 return 0;
1013}
1014
1015static unsigned int
1016vivi_poll(struct file *file, struct poll_table_struct *wait)
1017{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001018 struct vivi_fh *fh = file->private_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001019 struct vivi_dev *dev = fh->dev;
Brandon Philips85c7c70bc2007-09-27 20:55:02 -03001020 struct videobuf_queue *q = &fh->vb_vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001021
Harvey Harrison7e28adb2008-04-08 23:20:00 -03001022 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001023
1024 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
1025 return POLLERR;
1026
Brandon Philips85c7c70bc2007-09-27 20:55:02 -03001027 return videobuf_poll_stream(file, q, wait);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001028}
1029
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001030static int vivi_close(struct inode *inode, struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001031{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001032 struct vivi_fh *fh = file->private_data;
1033 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001034 struct vivi_dmaqueue *vidq = &dev->vidq;
1035
1036 int minor = iminor(inode);
1037
1038 vivi_stop_thread(vidq);
Brandon Philips053fcb62007-11-13 20:11:26 -03001039 videobuf_stop(&fh->vb_vidq);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001040 videobuf_mmap_free(&fh->vb_vidq);
1041
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001042 kfree(fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001043
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001044 mutex_lock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001045 dev->users--;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001046 mutex_unlock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001047
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001048 dprintk(dev, 1, "close called (minor=%d, users=%d)\n",
1049 minor, dev->users);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001050
1051 return 0;
1052}
1053
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001054static int vivi_release(void)
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001055{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001056 struct vivi_dev *dev;
1057 struct list_head *list;
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001058
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001059 while (!list_empty(&vivi_devlist)) {
1060 list = vivi_devlist.next;
1061 list_del(list);
1062 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1063
Carl Karsten745271a2008-06-10 00:02:32 -03001064 if (-1 != dev->vfd->minor) {
Adrian Bunk8da9bae2008-09-03 17:12:25 -03001065 printk(KERN_INFO "%s: unregistering /dev/video%d\n",
1066 VIVI_MODULE_NAME, dev->vfd->minor);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001067 video_unregister_device(dev->vfd);
Carl Karsten745271a2008-06-10 00:02:32 -03001068 } else {
Adrian Bunk8da9bae2008-09-03 17:12:25 -03001069 printk(KERN_INFO "%s: releasing /dev/video%d\n",
Mauro Carvalho Chehab584ce482008-06-10 15:21:49 -03001070 VIVI_MODULE_NAME, dev->vfd->minor);
Adrian Bunk8da9bae2008-09-03 17:12:25 -03001071 video_device_release(dev->vfd);
Carl Karsten745271a2008-06-10 00:02:32 -03001072 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001073
1074 kfree(dev);
1075 }
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001076
1077 return 0;
1078}
1079
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001080static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001081{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001082 struct vivi_fh *fh = file->private_data;
1083 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001084 int ret;
1085
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001086 dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001087
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001088 ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001089
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001090 dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n",
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001091 (unsigned long)vma->vm_start,
1092 (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
1093 ret);
1094
1095 return ret;
1096}
1097
Arjan van de Venfa027c22007-02-12 00:55:33 -08001098static const struct file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001099 .owner = THIS_MODULE,
1100 .open = vivi_open,
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001101 .release = vivi_close,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001102 .read = vivi_read,
1103 .poll = vivi_poll,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001104 .ioctl = video_ioctl2, /* V4L2 ioctl handler */
Mauro Carvalho Chehabfbde31d2008-04-13 14:57:44 -03001105 .compat_ioctl = v4l_compat_ioctl32,
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001106 .mmap = vivi_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001107 .llseek = no_llseek,
1108};
1109
Hans Verkuila3998102008-07-21 02:57:38 -03001110static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001111 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001112 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1113 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1114 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1115 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001116 .vidioc_reqbufs = vidioc_reqbufs,
1117 .vidioc_querybuf = vidioc_querybuf,
1118 .vidioc_qbuf = vidioc_qbuf,
1119 .vidioc_dqbuf = vidioc_dqbuf,
1120 .vidioc_s_std = vidioc_s_std,
1121 .vidioc_enum_input = vidioc_enum_input,
1122 .vidioc_g_input = vidioc_g_input,
1123 .vidioc_s_input = vidioc_s_input,
1124 .vidioc_queryctrl = vidioc_queryctrl,
1125 .vidioc_g_ctrl = vidioc_g_ctrl,
1126 .vidioc_s_ctrl = vidioc_s_ctrl,
1127 .vidioc_streamon = vidioc_streamon,
1128 .vidioc_streamoff = vidioc_streamoff,
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -03001129#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001130 .vidiocgmbuf = vidiocgmbuf,
1131#endif
Hans Verkuila3998102008-07-21 02:57:38 -03001132};
1133
1134static struct video_device vivi_template = {
1135 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001136 .fops = &vivi_fops,
1137 .ioctl_ops = &vivi_ioctl_ops,
1138 .minor = -1,
1139 .release = video_device_release,
1140
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001141 .tvnorms = V4L2_STD_525_60,
Mauro Carvalho Chehabe75f9ce2006-11-20 13:19:20 -03001142 .current_norm = V4L2_STD_NTSC_M,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001143};
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001144/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001145 Initialization and module stuff
1146 ------------------------------------------------------------------*/
1147
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001148/* This routine allocates from 1 to n_devs virtual drivers.
1149
1150 The real maximum number of virtual drivers will depend on how many drivers
1151 will succeed. This is limited to the maximum number of devices that
1152 videodev supports. Since there are 64 minors for video grabbers, this is
1153 currently the theoretical maximum limit. However, a further limit does
1154 exist at videodev that forbids any driver to register more than 32 video
1155 grabbers.
1156 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001157static int __init vivi_init(void)
1158{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001159 int ret = -ENOMEM, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001160 struct vivi_dev *dev;
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001161 struct video_device *vfd;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001162
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001163 if (n_devs <= 0)
1164 n_devs = 1;
1165
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001166 for (i = 0; i < n_devs; i++) {
1167 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001168 if (!dev)
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001169 break;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001170
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001171 /* init video dma queues */
1172 INIT_LIST_HEAD(&dev->vidq.active);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001173 init_waitqueue_head(&dev->vidq.wq);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001174
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001175 /* initialize locks */
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -03001176 spin_lock_init(&dev->slock);
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001177 mutex_init(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001178
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001179 vfd = video_device_alloc();
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001180 if (!vfd) {
1181 kfree(dev);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001182 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001183 }
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001184
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001185 *vfd = vivi_template;
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001186
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001187 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001188 if (ret < 0) {
1189 video_device_release(vfd);
1190 kfree(dev);
1191
1192 /* If some registers succeeded, keep driver */
1193 if (i)
1194 ret = 0;
1195
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001196 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001197 }
1198
1199 /* Now that everything is fine, let's add it to device list */
1200 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001201
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001202 snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
1203 vivi_template.name, vfd->minor);
1204
1205 if (video_nr >= 0)
1206 video_nr++;
1207
1208 dev->vfd = vfd;
Carl Karsten745271a2008-06-10 00:02:32 -03001209 printk(KERN_INFO "%s: V4L2 device registered as /dev/video%d\n",
Mauro Carvalho Chehab584ce482008-06-10 15:21:49 -03001210 VIVI_MODULE_NAME, vfd->minor);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001211 }
1212
1213 if (ret < 0) {
1214 vivi_release();
1215 printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001216 } else {
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001217 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Carl Karsten745271a2008-06-10 00:02:32 -03001218 "Capture Board ver %u.%u.%u successfully loaded.\n",
1219 (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
1220 VIVI_VERSION & 0xFF);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001221
1222 /* n_devs will reflect the actual number of allocated devices */
1223 n_devs = i;
1224 }
1225
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001226 return ret;
1227}
1228
1229static void __exit vivi_exit(void)
1230{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001231 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001232}
1233
1234module_init(vivi_init);
1235module_exit(vivi_exit);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001236
1237MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
1238MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
1239MODULE_LICENSE("Dual BSD/GPL");
1240
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001241module_param(video_nr, uint, 0444);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001242MODULE_PARM_DESC(video_nr, "video iminor start number");
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001243
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001244module_param(n_devs, uint, 0444);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001245MODULE_PARM_DESC(n_devs, "number of video devices to create");
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001246
Mauro Carvalho Chehab8996b3f2007-12-13 06:36:22 -03001247module_param_named(debug, vivi_template.debug, int, 0444);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001248MODULE_PARM_DESC(debug, "activates debug info");
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001249
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001250module_param(vid_limit, int, 0644);
1251MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");