blob: 0f25d686ca20b278684d18cbe38184c2d4a05eac [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 },
Magnus Dammfca36ba2008-10-14 12:47:25 -0300137 {
138 .name = "4:2:2, packed, UYVY",
139 .fourcc = V4L2_PIX_FMT_UYVY,
140 .depth = 16,
141 },
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300142 {
143 .name = "RGB565 (LE)",
144 .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
145 .depth = 16,
146 },
147 {
148 .name = "RGB565 (BE)",
149 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
150 .depth = 16,
151 },
Magnus Dammdef52392008-10-14 12:47:43 -0300152 {
153 .name = "RGB555 (LE)",
154 .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
155 .depth = 16,
156 },
157 {
158 .name = "RGB555 (BE)",
159 .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
160 .depth = 16,
161 },
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300162};
163
Magnus Dammd891f472008-10-14 12:47:09 -0300164static struct vivi_fmt *get_format(struct v4l2_format *f)
165{
166 struct vivi_fmt *fmt;
167 unsigned int k;
168
169 for (k = 0; k < ARRAY_SIZE(formats); k++) {
170 fmt = &formats[k];
171 if (fmt->fourcc == f->fmt.pix.pixelformat)
172 break;
173 }
174
175 if (k == ARRAY_SIZE(formats))
176 return NULL;
177
178 return &formats[k];
179}
180
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300181struct sg_to_addr {
182 int pos;
183 struct scatterlist *sg;
184};
185
186/* buffer for one video frame */
187struct vivi_buffer {
188 /* common v4l buffer stuff -- must be first */
189 struct videobuf_buffer vb;
190
191 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300192};
193
194struct vivi_dmaqueue {
195 struct list_head active;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300196
197 /* thread for generating video stream*/
198 struct task_struct *kthread;
199 wait_queue_head_t wq;
200 /* Counters to control fps rate */
201 int frame;
202 int ini_jiffies;
203};
204
205static LIST_HEAD(vivi_devlist);
206
207struct vivi_dev {
208 struct list_head vivi_devlist;
209
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300210 spinlock_t slock;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300211 struct mutex mutex;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300212
213 int users;
214
215 /* various device info */
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -0300216 struct video_device *vfd;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300217
218 struct vivi_dmaqueue vidq;
219
220 /* Several counters */
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300221 int h, m, s, ms;
222 unsigned long jiffies;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300223 char timestr[13];
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300224
225 int mv_count; /* Controls bars movement */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300226
227 /* Input Number */
228 int input;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300229};
230
231struct vivi_fh {
232 struct vivi_dev *dev;
233
234 /* video capture */
235 struct vivi_fmt *fmt;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300236 unsigned int width, height;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300237 struct videobuf_queue vb_vidq;
238
239 enum v4l2_buf_type type;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300240 unsigned char bars[8][3];
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300241 int input; /* Input Number on bars */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300242};
243
244/* ------------------------------------------------------------------
245 DMA and thread functions
246 ------------------------------------------------------------------*/
247
248/* Bars and Colors should match positions */
249
250enum colors {
251 WHITE,
252 AMBAR,
253 CYAN,
254 GREEN,
255 MAGENTA,
256 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300257 BLUE,
258 BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300259};
260
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300261 /* R G B */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300262#define COLOR_WHITE {204, 204, 204}
263#define COLOR_AMBAR {208, 208, 0}
264#define COLOR_CIAN { 0, 206, 206}
265#define COLOR_GREEN { 0, 239, 0}
266#define COLOR_MAGENTA {239, 0, 239}
267#define COLOR_RED {205, 0, 0}
268#define COLOR_BLUE { 0, 0, 255}
269#define COLOR_BLACK { 0, 0, 0}
270
271struct bar_std {
272 u8 bar[8][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300273};
274
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300275/* Maximum number of bars are 10 - otherwise, the input print code
276 should be modified */
277static struct bar_std bars[] = {
278 { /* Standard ITU-R color bar sequence */
279 {
280 COLOR_WHITE,
281 COLOR_AMBAR,
282 COLOR_CIAN,
283 COLOR_GREEN,
284 COLOR_MAGENTA,
285 COLOR_RED,
286 COLOR_BLUE,
287 COLOR_BLACK,
288 }
289 }, {
290 {
291 COLOR_WHITE,
292 COLOR_AMBAR,
293 COLOR_BLACK,
294 COLOR_WHITE,
295 COLOR_AMBAR,
296 COLOR_BLACK,
297 COLOR_WHITE,
298 COLOR_AMBAR,
299 }
300 }, {
301 {
302 COLOR_WHITE,
303 COLOR_CIAN,
304 COLOR_BLACK,
305 COLOR_WHITE,
306 COLOR_CIAN,
307 COLOR_BLACK,
308 COLOR_WHITE,
309 COLOR_CIAN,
310 }
311 }, {
312 {
313 COLOR_WHITE,
314 COLOR_GREEN,
315 COLOR_BLACK,
316 COLOR_WHITE,
317 COLOR_GREEN,
318 COLOR_BLACK,
319 COLOR_WHITE,
320 COLOR_GREEN,
321 }
322 },
323};
324
325#define NUM_INPUTS ARRAY_SIZE(bars)
326
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300327#define TO_Y(r, g, b) \
328 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300329/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300330#define TO_V(r, g, b) \
331 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300332/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300333#define TO_U(r, g, b) \
334 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300335
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300336#define TSTAMP_MIN_Y 24
337#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
338#define TSTAMP_INPUT_X 10
339#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300340
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300341static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
342{
343 unsigned char r_y, g_u, b_v;
344 unsigned char *p;
345 int color;
346
347 r_y = fh->bars[colorpos][0]; /* R or precalculated Y */
348 g_u = fh->bars[colorpos][1]; /* G or precalculated U */
349 b_v = fh->bars[colorpos][2]; /* B or precalculated V */
350
351 for (color = 0; color < 4; color++) {
352 p = buf + color;
353
Magnus Dammd891f472008-10-14 12:47:09 -0300354 switch (fh->fmt->fourcc) {
355 case V4L2_PIX_FMT_YUYV:
356 switch (color) {
357 case 0:
358 case 2:
359 *p = r_y;
360 break;
361 case 1:
362 *p = g_u;
363 break;
364 case 3:
365 *p = b_v;
366 break;
367 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300368 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300369 case V4L2_PIX_FMT_UYVY:
370 switch (color) {
371 case 1:
372 case 3:
373 *p = r_y;
374 break;
375 case 0:
376 *p = g_u;
377 break;
378 case 2:
379 *p = b_v;
380 break;
381 }
382 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300383 case V4L2_PIX_FMT_RGB565:
384 switch (color) {
385 case 0:
386 case 2:
387 *p = (g_u << 5) | b_v;
388 break;
389 case 1:
390 case 3:
391 *p = (r_y << 3) | (g_u >> 3);
392 break;
393 }
394 break;
395 case V4L2_PIX_FMT_RGB565X:
396 switch (color) {
397 case 0:
398 case 2:
399 *p = (r_y << 3) | (g_u >> 3);
400 break;
401 case 1:
402 case 3:
403 *p = (g_u << 5) | b_v;
404 break;
405 }
406 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300407 case V4L2_PIX_FMT_RGB555:
408 switch (color) {
409 case 0:
410 case 2:
411 *p = (g_u << 5) | b_v;
412 break;
413 case 1:
414 case 3:
415 *p = (r_y << 2) | (g_u >> 3);
416 break;
417 }
418 break;
419 case V4L2_PIX_FMT_RGB555X:
420 switch (color) {
421 case 0:
422 case 2:
423 *p = (r_y << 2) | (g_u >> 3);
424 break;
425 case 1:
426 case 3:
427 *p = (g_u << 5) | b_v;
428 break;
429 }
430 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300431 }
432 }
433}
434
435static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300436 int hmax, int line, int count, char *timestr)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300437{
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300438 int w, i, j;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300439 int pos = inipos;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300440 char *s;
441 u8 chr;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300442
443 /* We will just duplicate the second pixel at the packet */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300444 wmax /= 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300445
446 /* Generate a standard color bar pattern */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300447 for (w = 0; w < wmax; w++) {
448 int colorpos = ((w + count) * 8/(wmax + 1)) % 8;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300449
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300450 gen_twopix(fh, basep + pos, colorpos);
451 pos += 4; /* only 16 bpp supported for now */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300452 }
453
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300454 /* Prints input entry number */
455
456 /* Checks if it is possible to input number */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300457 if (TSTAMP_MAX_Y >= hmax)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300458 goto end;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300459
460 if (TSTAMP_INPUT_X + strlen(timestr) >= wmax)
461 goto end;
462
463 if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
464 chr = rom8x16_bits[fh->input * 16 + line - TSTAMP_MIN_Y];
465 pos = TSTAMP_INPUT_X;
466 for (i = 0; i < 7; i++) {
467 /* Draw white font on black background */
468 if (chr & 1 << (7 - i))
469 gen_twopix(fh, basep + pos, WHITE);
470 else
471 gen_twopix(fh, basep + pos, BLACK);
472 pos += 2;
473 }
474 }
475
476 /* Checks if it is possible to show timestamp */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300477 if (TSTAMP_MIN_X + strlen(timestr) >= wmax)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300478 goto end;
479
480 /* Print stream time */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300481 if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
482 j = TSTAMP_MIN_X;
483 for (s = timestr; *s; s++) {
484 chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y];
485 for (i = 0; i < 7; i++) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300486 pos = inipos + j * 2;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300487 /* Draw white font on black background */
488 if (chr & 1 << (7 - i))
489 gen_twopix(fh, basep + pos, WHITE);
490 else
491 gen_twopix(fh, basep + pos, BLACK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300492 j++;
493 }
494 }
495 }
496
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300497end:
Mauro Carvalho Chehabb50e7fe2007-01-25 05:00:01 -0300498 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300499}
Brandon Philips78718e52008-04-02 18:10:59 -0300500
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300501static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300502{
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300503 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300504 int h , pos = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300505 int hmax = buf->vb.height;
506 int wmax = buf->vb.width;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300507 struct timeval ts;
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300508 char *tmpbuf;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300509 void *vbuf = videobuf_to_vmalloc(&buf->vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300510
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300511 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300512 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300513
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300514 tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);
515 if (!tmpbuf)
Brandon Philips78718e52008-04-02 18:10:59 -0300516 return;
517
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300518 for (h = 0; h < hmax; h++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300519 gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count,
Mauro Carvalho Chehab3bef5e42007-09-22 02:01:33 -0300520 dev->timestr);
Brandon Philips78718e52008-04-02 18:10:59 -0300521 memcpy(vbuf + pos, tmpbuf, wmax * 2);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300522 pos += wmax*2;
523 }
524
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300525 dev->mv_count++;
Mauro Carvalho Chehab3bef5e42007-09-22 02:01:33 -0300526
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300527 kfree(tmpbuf);
528
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300529 /* Updates stream time */
530
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300531 dev->ms += jiffies_to_msecs(jiffies-dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300532 dev->jiffies = jiffies;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300533 if (dev->ms >= 1000) {
534 dev->ms -= 1000;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300535 dev->s++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300536 if (dev->s >= 60) {
537 dev->s -= 60;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300538 dev->m++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300539 if (dev->m > 60) {
540 dev->m -= 60;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300541 dev->h++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300542 if (dev->h > 24)
543 dev->h -= 24;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300544 }
545 }
546 }
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300547 sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300548 dev->h, dev->m, dev->s, dev->ms);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300549
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300550 dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n",
551 dev->timestr, (unsigned long)tmpbuf, pos);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300552
553 /* Advice that buffer was filled */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300554 buf->vb.field_count++;
555 do_gettimeofday(&ts);
556 buf->vb.ts = ts;
Brandon Philips78718e52008-04-02 18:10:59 -0300557 buf->vb.state = VIDEOBUF_DONE;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300558}
559
Brandon Philips78718e52008-04-02 18:10:59 -0300560static void vivi_thread_tick(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300561{
Brandon Philips78718e52008-04-02 18:10:59 -0300562 struct vivi_buffer *buf;
563 struct vivi_dev *dev = fh->dev;
564 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300565
Brandon Philips78718e52008-04-02 18:10:59 -0300566 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300567
Brandon Philips78718e52008-04-02 18:10:59 -0300568 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300569
Brandon Philips78718e52008-04-02 18:10:59 -0300570 spin_lock_irqsave(&dev->slock, flags);
571 if (list_empty(&dma_q->active)) {
572 dprintk(dev, 1, "No active queue to serve\n");
573 goto unlock;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300574 }
Brandon Philips78718e52008-04-02 18:10:59 -0300575
576 buf = list_entry(dma_q->active.next,
577 struct vivi_buffer, vb.queue);
578
579 /* Nobody is waiting on this buffer, return */
580 if (!waitqueue_active(&buf->vb.done))
581 goto unlock;
582
583 list_del(&buf->vb.queue);
584
585 do_gettimeofday(&buf->vb.ts);
586
587 /* Fill buffer */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300588 vivi_fillbuff(fh, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300589 dprintk(dev, 1, "filled buffer %p\n", buf);
590
591 wake_up(&buf->vb.done);
592 dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
593unlock:
594 spin_unlock_irqrestore(&dev->slock, flags);
595 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300596}
597
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300598#define frames_to_ms(frames) \
599 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
600
Brandon Philips78718e52008-04-02 18:10:59 -0300601static void vivi_sleep(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300602{
Brandon Philips78718e52008-04-02 18:10:59 -0300603 struct vivi_dev *dev = fh->dev;
604 struct vivi_dmaqueue *dma_q = &dev->vidq;
605 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300606 DECLARE_WAITQUEUE(wait, current);
607
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300608 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300609 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300610
611 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300612 if (kthread_should_stop())
613 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300614
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300615 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300616 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300617
Brandon Philips78718e52008-04-02 18:10:59 -0300618 vivi_thread_tick(fh);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300619
620 schedule_timeout_interruptible(timeout);
621
622stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300623 remove_wait_queue(&dma_q->wq, &wait);
624 try_to_freeze();
625}
626
Adrian Bunk972c3512006-04-27 21:06:50 -0300627static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300628{
Brandon Philips78718e52008-04-02 18:10:59 -0300629 struct vivi_fh *fh = data;
630 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300631
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300632 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300633
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700634 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300635
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300636 for (;;) {
Brandon Philips78718e52008-04-02 18:10:59 -0300637 vivi_sleep(fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300638
639 if (kthread_should_stop())
640 break;
641 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300642 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300643 return 0;
644}
645
Brandon Philips78718e52008-04-02 18:10:59 -0300646static int vivi_start_thread(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300647{
Brandon Philips78718e52008-04-02 18:10:59 -0300648 struct vivi_dev *dev = fh->dev;
649 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300650
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300651 dma_q->frame = 0;
652 dma_q->ini_jiffies = jiffies;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300653
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300654 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300655
Brandon Philips78718e52008-04-02 18:10:59 -0300656 dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300657
Akinobu Mita054afee2006-12-20 10:04:00 -0300658 if (IS_ERR(dma_q->kthread)) {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300659 printk(KERN_ERR "vivi: kernel_thread() failed\n");
Akinobu Mita054afee2006-12-20 10:04:00 -0300660 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300661 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300662 /* Wakes thread */
663 wake_up_interruptible(&dma_q->wq);
664
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300665 dprintk(dev, 1, "returning from %s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300666 return 0;
667}
668
Adrian Bunk972c3512006-04-27 21:06:50 -0300669static void vivi_stop_thread(struct vivi_dmaqueue *dma_q)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300670{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300671 struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
672
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300673 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300674 /* shutdown control thread */
675 if (dma_q->kthread) {
676 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300677 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300678 }
679}
680
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300681/* ------------------------------------------------------------------
682 Videobuf operations
683 ------------------------------------------------------------------*/
684static int
685buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
686{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300687 struct vivi_fh *fh = vq->priv_data;
688 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300689
690 *size = fh->width*fh->height*2;
691
692 if (0 == *count)
693 *count = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300694
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300695 while (*size * *count > vid_limit * 1024 * 1024)
696 (*count)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300697
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300698 dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300699 *count, *size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300700
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300701 return 0;
702}
703
Adrian Bunk972c3512006-04-27 21:06:50 -0300704static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300705{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300706 struct vivi_fh *fh = vq->priv_data;
707 struct vivi_dev *dev = fh->dev;
708
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300709 dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300710
711 if (in_interrupt())
712 BUG();
713
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300714 videobuf_vmalloc_free(&buf->vb);
Mauro Carvalho Chehabfbde31d2008-04-13 14:57:44 -0300715 dprintk(dev, 1, "free_buffer: freed\n");
Brandon Philips0fc06862007-11-06 20:02:36 -0300716 buf->vb.state = VIDEOBUF_NEEDS_INIT;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300717}
718
719#define norm_maxw() 1024
720#define norm_maxh() 768
721static int
722buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
723 enum v4l2_field field)
724{
725 struct vivi_fh *fh = vq->priv_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300726 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300727 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300728 int rc;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300729
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300730 dprintk(dev, 1, "%s, field=%d\n", __func__, field);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300731
732 BUG_ON(NULL == fh->fmt);
Brandon Philips78718e52008-04-02 18:10:59 -0300733
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300734 if (fh->width < 48 || fh->width > norm_maxw() ||
735 fh->height < 32 || fh->height > norm_maxh())
736 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300737
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300738 buf->vb.size = fh->width*fh->height*2;
739 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
740 return -EINVAL;
741
Brandon Philips78718e52008-04-02 18:10:59 -0300742 /* These properties only change when queue is idle, see s_fmt */
743 buf->fmt = fh->fmt;
744 buf->vb.width = fh->width;
745 buf->vb.height = fh->height;
746 buf->vb.field = field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300747
Brandon Philips0fc06862007-11-06 20:02:36 -0300748 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300749 rc = videobuf_iolock(vq, &buf->vb, NULL);
750 if (rc < 0)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300751 goto fail;
752 }
753
Brandon Philips0fc06862007-11-06 20:02:36 -0300754 buf->vb.state = VIDEOBUF_PREPARED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300755
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300756 return 0;
757
758fail:
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300759 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300760 return rc;
761}
762
763static void
764buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
765{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300766 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
767 struct vivi_fh *fh = vq->priv_data;
768 struct vivi_dev *dev = fh->dev;
Brandon Philips78718e52008-04-02 18:10:59 -0300769 struct vivi_dmaqueue *vidq = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300770
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300771 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300772
Brandon Philips78718e52008-04-02 18:10:59 -0300773 buf->vb.state = VIDEOBUF_QUEUED;
774 list_add_tail(&buf->vb.queue, &vidq->active);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300775}
776
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300777static void buffer_release(struct videobuf_queue *vq,
778 struct videobuf_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300779{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300780 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300781 struct vivi_fh *fh = vq->priv_data;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300782 struct vivi_dev *dev = (struct vivi_dev *)fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300783
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300784 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300785
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300786 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300787}
788
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300789static struct videobuf_queue_ops vivi_video_qops = {
790 .buf_setup = buffer_setup,
791 .buf_prepare = buffer_prepare,
792 .buf_queue = buffer_queue,
793 .buf_release = buffer_release,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300794};
795
796/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300797 IOCTL vidioc handling
798 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300799static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300800 struct v4l2_capability *cap)
801{
802 strcpy(cap->driver, "vivi");
803 strcpy(cap->card, "vivi");
804 cap->version = VIVI_VERSION;
805 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
806 V4L2_CAP_STREAMING |
807 V4L2_CAP_READWRITE;
808 return 0;
809}
810
Hans Verkuil78b526a2008-05-28 12:16:41 -0300811static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300812 struct v4l2_fmtdesc *f)
813{
Magnus Dammd891f472008-10-14 12:47:09 -0300814 struct vivi_fmt *fmt;
815
816 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300817 return -EINVAL;
818
Magnus Dammd891f472008-10-14 12:47:09 -0300819 fmt = &formats[f->index];
820
821 strlcpy(f->description, fmt->name, sizeof(f->description));
822 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300823 return 0;
824}
825
Hans Verkuil78b526a2008-05-28 12:16:41 -0300826static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300827 struct v4l2_format *f)
828{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300829 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300830
831 f->fmt.pix.width = fh->width;
832 f->fmt.pix.height = fh->height;
833 f->fmt.pix.field = fh->vb_vidq.field;
834 f->fmt.pix.pixelformat = fh->fmt->fourcc;
835 f->fmt.pix.bytesperline =
836 (f->fmt.pix.width * fh->fmt->depth) >> 3;
837 f->fmt.pix.sizeimage =
838 f->fmt.pix.height * f->fmt.pix.bytesperline;
839
840 return (0);
841}
842
Hans Verkuil78b526a2008-05-28 12:16:41 -0300843static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300844 struct v4l2_format *f)
845{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300846 struct vivi_fh *fh = priv;
847 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300848 struct vivi_fmt *fmt;
849 enum v4l2_field field;
850 unsigned int maxw, maxh;
851
Magnus Dammd891f472008-10-14 12:47:09 -0300852 fmt = get_format(f);
853 if (!fmt) {
854 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
855 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300856 return -EINVAL;
857 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300858
859 field = f->fmt.pix.field;
860
861 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300862 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300863 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300864 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300865 return -EINVAL;
866 }
867
868 maxw = norm_maxw();
869 maxh = norm_maxh();
870
871 f->fmt.pix.field = field;
872 if (f->fmt.pix.height < 32)
873 f->fmt.pix.height = 32;
874 if (f->fmt.pix.height > maxh)
875 f->fmt.pix.height = maxh;
876 if (f->fmt.pix.width < 48)
877 f->fmt.pix.width = 48;
878 if (f->fmt.pix.width > maxw)
879 f->fmt.pix.width = maxw;
880 f->fmt.pix.width &= ~0x03;
881 f->fmt.pix.bytesperline =
882 (f->fmt.pix.width * fmt->depth) >> 3;
883 f->fmt.pix.sizeimage =
884 f->fmt.pix.height * f->fmt.pix.bytesperline;
885
886 return 0;
887}
888
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300889/* precalculate color bar values to speed up rendering */
890static void precalculate_bars(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300891{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300892 struct vivi_dev *dev = fh->dev;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300893 unsigned char r, g, b;
Magnus Dammd891f472008-10-14 12:47:09 -0300894 int k, is_yuv;
Brandon Philips78718e52008-04-02 18:10:59 -0300895
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300896 fh->input = dev->input;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300897
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300898 for (k = 0; k < 8; k++) {
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300899 r = bars[fh->input].bar[k][0];
900 g = bars[fh->input].bar[k][1];
901 b = bars[fh->input].bar[k][2];
Magnus Dammd891f472008-10-14 12:47:09 -0300902 is_yuv = 0;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300903
Magnus Dammd891f472008-10-14 12:47:09 -0300904 switch (fh->fmt->fourcc) {
905 case V4L2_PIX_FMT_YUYV:
Magnus Dammfca36ba2008-10-14 12:47:25 -0300906 case V4L2_PIX_FMT_UYVY:
Magnus Dammd891f472008-10-14 12:47:09 -0300907 is_yuv = 1;
908 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300909 case V4L2_PIX_FMT_RGB565:
910 case V4L2_PIX_FMT_RGB565X:
911 r >>= 3;
912 g >>= 2;
913 b >>= 3;
914 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300915 case V4L2_PIX_FMT_RGB555:
916 case V4L2_PIX_FMT_RGB555X:
917 r >>= 3;
918 g >>= 3;
919 b >>= 3;
920 break;
Magnus Dammd891f472008-10-14 12:47:09 -0300921 }
922
923 if (is_yuv) {
924 fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
925 fh->bars[k][1] = TO_U(r, g, b); /* Cb */
926 fh->bars[k][2] = TO_V(r, g, b); /* Cr */
927 } else {
928 fh->bars[k][0] = r;
929 fh->bars[k][1] = g;
930 fh->bars[k][2] = b;
931 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300932 }
933
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300934}
935
936/*FIXME: This seems to be generic enough to be at videodev2 */
937static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
938 struct v4l2_format *f)
939{
940 struct vivi_fh *fh = priv;
941 struct videobuf_queue *q = &fh->vb_vidq;
942
943 int ret = vidioc_try_fmt_vid_cap(file, fh, f);
944 if (ret < 0)
945 return ret;
946
947 mutex_lock(&q->vb_lock);
948
949 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
950 dprintk(fh->dev, 1, "%s queue busy\n", __func__);
951 ret = -EBUSY;
952 goto out;
953 }
954
955 fh->fmt = get_format(f);
956 fh->width = f->fmt.pix.width;
957 fh->height = f->fmt.pix.height;
958 fh->vb_vidq.field = f->fmt.pix.field;
959 fh->type = f->type;
960
961 precalculate_bars(fh);
962
Brandon Philips78718e52008-04-02 18:10:59 -0300963 ret = 0;
964out:
965 mutex_unlock(&q->vb_lock);
966
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300967 return ret;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300968}
969
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300970static int vidioc_reqbufs(struct file *file, void *priv,
971 struct v4l2_requestbuffers *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300972{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300973 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300974
975 return (videobuf_reqbufs(&fh->vb_vidq, p));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300976}
977
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300978static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300979{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300980 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300981
982 return (videobuf_querybuf(&fh->vb_vidq, p));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300983}
984
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300985static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300986{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300987 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300988
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300989 return (videobuf_qbuf(&fh->vb_vidq, p));
990}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300991
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300992static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300993{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300994 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300995
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300996 return (videobuf_dqbuf(&fh->vb_vidq, p,
997 file->f_flags & O_NONBLOCK));
998}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300999
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -03001000#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001001static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001002{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001003 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001004
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001005 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001006}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001007#endif
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001008
Adrian Bunkdc46ace2006-06-23 06:42:44 -03001009static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001010{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001011 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001012
1013 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1014 return -EINVAL;
1015 if (i != fh->type)
1016 return -EINVAL;
1017
Brandon Philipsba32bd92007-09-27 20:55:17 -03001018 return videobuf_streamon(&fh->vb_vidq);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001019}
1020
Adrian Bunkdc46ace2006-06-23 06:42:44 -03001021static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001022{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001023 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001024
1025 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1026 return -EINVAL;
1027 if (i != fh->type)
1028 return -EINVAL;
1029
Brandon Philipsba32bd92007-09-27 20:55:17 -03001030 return videobuf_streamoff(&fh->vb_vidq);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001031}
1032
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001033static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001034{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001035 return 0;
1036}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001037
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001038/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001039static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001040 struct v4l2_input *inp)
1041{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001042 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001043 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001044
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001045 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001046 inp->std = V4L2_STD_525_60;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001047 sprintf(inp->name, "Camera %u", inp->index);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001048
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001049 return (0);
1050}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001051
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001052static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001053{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001054 struct vivi_fh *fh = priv;
1055 struct vivi_dev *dev = fh->dev;
1056
1057 *i = dev->input;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001058
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001059 return (0);
1060}
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001061static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001062{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001063 struct vivi_fh *fh = priv;
1064 struct vivi_dev *dev = fh->dev;
1065
1066 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001067 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001068
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001069 dev->input = i;
1070 precalculate_bars(fh);
1071
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001072 return (0);
1073}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001074
1075 /* --- controls ---------------------------------------------- */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001076static int vidioc_queryctrl(struct file *file, void *priv,
1077 struct v4l2_queryctrl *qc)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001078{
1079 int i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001080
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001081 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1082 if (qc->id && qc->id == vivi_qctrl[i].id) {
1083 memcpy(qc, &(vivi_qctrl[i]),
1084 sizeof(*qc));
1085 return (0);
1086 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001087
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001088 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001089}
1090
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001091static int vidioc_g_ctrl(struct file *file, void *priv,
1092 struct v4l2_control *ctrl)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001093{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001094 int i;
1095
1096 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1097 if (ctrl->id == vivi_qctrl[i].id) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001098 ctrl->value = qctl_regs[i];
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001099 return (0);
1100 }
1101
1102 return -EINVAL;
1103}
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001104static int vidioc_s_ctrl(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001105 struct v4l2_control *ctrl)
1106{
1107 int i;
1108
1109 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1110 if (ctrl->id == vivi_qctrl[i].id) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001111 if (ctrl->value < vivi_qctrl[i].minimum
1112 || ctrl->value > vivi_qctrl[i].maximum) {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001113 return (-ERANGE);
1114 }
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001115 qctl_regs[i] = ctrl->value;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001116 return (0);
1117 }
1118 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001119}
1120
1121/* ------------------------------------------------------------------
1122 File operations for the device
1123 ------------------------------------------------------------------*/
1124
Hans Verkuilbec43662008-12-30 06:58:20 -03001125static int vivi_open(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001126{
Hans Verkuilbec43662008-12-30 06:58:20 -03001127 int minor = video_devdata(file)->minor;
Trent Piephoa991f442007-10-10 05:37:43 -03001128 struct vivi_dev *dev;
Mauro Carvalho Chehab63b79cf2008-04-26 08:25:18 -03001129 struct vivi_fh *fh = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001130 int i;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001131 int retval = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001132
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001133 printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001134
Hans Verkuild56dc612008-07-30 08:43:36 -03001135 lock_kernel();
Trent Piephoa991f442007-10-10 05:37:43 -03001136 list_for_each_entry(dev, &vivi_devlist, vivi_devlist)
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001137 if (dev->vfd->minor == minor)
Trent Piephoa991f442007-10-10 05:37:43 -03001138 goto found;
Hans Verkuild56dc612008-07-30 08:43:36 -03001139 unlock_kernel();
Trent Piephoa991f442007-10-10 05:37:43 -03001140 return -ENODEV;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001141
Trent Piephoa991f442007-10-10 05:37:43 -03001142found:
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001143 mutex_lock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001144 dev->users++;
1145
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001146 if (dev->users > 1) {
1147 dev->users--;
1148 retval = -EBUSY;
1149 goto unlock;
1150 }
1151
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001152 dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor,
Trent Piephoa991f442007-10-10 05:37:43 -03001153 v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001154
1155 /* allocate + initialize per filehandle data */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001156 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001157 if (NULL == fh) {
1158 dev->users--;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001159 retval = -ENOMEM;
1160 goto unlock;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001161 }
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001162unlock:
1163 mutex_unlock(&dev->mutex);
Hans Verkuild56dc612008-07-30 08:43:36 -03001164 if (retval) {
1165 unlock_kernel();
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001166 return retval;
Hans Verkuild56dc612008-07-30 08:43:36 -03001167 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001168
1169 file->private_data = fh;
1170 fh->dev = dev;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001171
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001172 fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Magnus Dammd891f472008-10-14 12:47:09 -03001173 fh->fmt = &formats[0];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001174 fh->width = 640;
1175 fh->height = 480;
1176
1177 /* Put all controls at a sane state */
1178 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001179 qctl_regs[i] = vivi_qctrl[i].default_value;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001180
1181 /* Resets frame counters */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001182 dev->h = 0;
1183 dev->m = 0;
1184 dev->s = 0;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -03001185 dev->ms = 0;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001186 dev->mv_count = 0;
1187 dev->jiffies = jiffies;
1188 sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -03001189 dev->h, dev->m, dev->s, dev->ms);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001190
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001191 videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops,
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -03001192 NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001193 sizeof(struct vivi_buffer), fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001194
Brandon Philips78718e52008-04-02 18:10:59 -03001195 vivi_start_thread(fh);
Hans Verkuild56dc612008-07-30 08:43:36 -03001196 unlock_kernel();
Brandon Philips78718e52008-04-02 18:10:59 -03001197
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001198 return 0;
1199}
1200
1201static ssize_t
1202vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1203{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001204 struct vivi_fh *fh = file->private_data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001205
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001206 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Mauro Carvalho Chehabacb09af2007-07-29 22:56:11 -03001207 return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001208 file->f_flags & O_NONBLOCK);
1209 }
1210 return 0;
1211}
1212
1213static unsigned int
1214vivi_poll(struct file *file, struct poll_table_struct *wait)
1215{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001216 struct vivi_fh *fh = file->private_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001217 struct vivi_dev *dev = fh->dev;
Brandon Philips85c7c70bc2007-09-27 20:55:02 -03001218 struct videobuf_queue *q = &fh->vb_vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001219
Harvey Harrison7e28adb2008-04-08 23:20:00 -03001220 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001221
1222 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
1223 return POLLERR;
1224
Brandon Philips85c7c70bc2007-09-27 20:55:02 -03001225 return videobuf_poll_stream(file, q, wait);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001226}
1227
Hans Verkuilbec43662008-12-30 06:58:20 -03001228static int vivi_close(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001229{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001230 struct vivi_fh *fh = file->private_data;
1231 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001232 struct vivi_dmaqueue *vidq = &dev->vidq;
1233
Hans Verkuilbec43662008-12-30 06:58:20 -03001234 int minor = video_devdata(file)->minor;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001235
1236 vivi_stop_thread(vidq);
Brandon Philips053fcb62007-11-13 20:11:26 -03001237 videobuf_stop(&fh->vb_vidq);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001238 videobuf_mmap_free(&fh->vb_vidq);
1239
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001240 kfree(fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001241
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001242 mutex_lock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001243 dev->users--;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001244 mutex_unlock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001245
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001246 dprintk(dev, 1, "close called (minor=%d, users=%d)\n",
1247 minor, dev->users);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001248
1249 return 0;
1250}
1251
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001252static int vivi_release(void)
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001253{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001254 struct vivi_dev *dev;
1255 struct list_head *list;
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001256
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001257 while (!list_empty(&vivi_devlist)) {
1258 list = vivi_devlist.next;
1259 list_del(list);
1260 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1261
Carl Karsten745271a2008-06-10 00:02:32 -03001262 if (-1 != dev->vfd->minor) {
Adrian Bunk8da9bae2008-09-03 17:12:25 -03001263 printk(KERN_INFO "%s: unregistering /dev/video%d\n",
Hans Verkuilc6330fb2008-10-19 18:54:26 -03001264 VIVI_MODULE_NAME, dev->vfd->num);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001265 video_unregister_device(dev->vfd);
Carl Karsten745271a2008-06-10 00:02:32 -03001266 } else {
Adrian Bunk8da9bae2008-09-03 17:12:25 -03001267 printk(KERN_INFO "%s: releasing /dev/video%d\n",
Hans Verkuilc6330fb2008-10-19 18:54:26 -03001268 VIVI_MODULE_NAME, dev->vfd->num);
Adrian Bunk8da9bae2008-09-03 17:12:25 -03001269 video_device_release(dev->vfd);
Carl Karsten745271a2008-06-10 00:02:32 -03001270 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001271
1272 kfree(dev);
1273 }
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001274
1275 return 0;
1276}
1277
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001278static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001279{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001280 struct vivi_fh *fh = file->private_data;
1281 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001282 int ret;
1283
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001284 dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001285
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001286 ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001287
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001288 dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n",
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001289 (unsigned long)vma->vm_start,
1290 (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
1291 ret);
1292
1293 return ret;
1294}
1295
Hans Verkuilbec43662008-12-30 06:58:20 -03001296static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001297 .owner = THIS_MODULE,
1298 .open = vivi_open,
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001299 .release = vivi_close,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001300 .read = vivi_read,
1301 .poll = vivi_poll,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001302 .ioctl = video_ioctl2, /* V4L2 ioctl handler */
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001303 .mmap = vivi_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001304};
1305
Hans Verkuila3998102008-07-21 02:57:38 -03001306static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001307 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001308 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1309 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1310 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1311 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001312 .vidioc_reqbufs = vidioc_reqbufs,
1313 .vidioc_querybuf = vidioc_querybuf,
1314 .vidioc_qbuf = vidioc_qbuf,
1315 .vidioc_dqbuf = vidioc_dqbuf,
1316 .vidioc_s_std = vidioc_s_std,
1317 .vidioc_enum_input = vidioc_enum_input,
1318 .vidioc_g_input = vidioc_g_input,
1319 .vidioc_s_input = vidioc_s_input,
1320 .vidioc_queryctrl = vidioc_queryctrl,
1321 .vidioc_g_ctrl = vidioc_g_ctrl,
1322 .vidioc_s_ctrl = vidioc_s_ctrl,
1323 .vidioc_streamon = vidioc_streamon,
1324 .vidioc_streamoff = vidioc_streamoff,
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -03001325#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001326 .vidiocgmbuf = vidiocgmbuf,
1327#endif
Hans Verkuila3998102008-07-21 02:57:38 -03001328};
1329
1330static struct video_device vivi_template = {
1331 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001332 .fops = &vivi_fops,
1333 .ioctl_ops = &vivi_ioctl_ops,
1334 .minor = -1,
1335 .release = video_device_release,
1336
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001337 .tvnorms = V4L2_STD_525_60,
Mauro Carvalho Chehabe75f9ce2006-11-20 13:19:20 -03001338 .current_norm = V4L2_STD_NTSC_M,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001339};
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001340/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001341 Initialization and module stuff
1342 ------------------------------------------------------------------*/
1343
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001344/* This routine allocates from 1 to n_devs virtual drivers.
1345
1346 The real maximum number of virtual drivers will depend on how many drivers
1347 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001348 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001349 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001350static int __init vivi_init(void)
1351{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001352 int ret = -ENOMEM, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001353 struct vivi_dev *dev;
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001354 struct video_device *vfd;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001355
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001356 if (n_devs <= 0)
1357 n_devs = 1;
1358
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001359 for (i = 0; i < n_devs; i++) {
1360 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001361 if (!dev)
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001362 break;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001363
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001364 /* init video dma queues */
1365 INIT_LIST_HEAD(&dev->vidq.active);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001366 init_waitqueue_head(&dev->vidq.wq);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001367
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001368 /* initialize locks */
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -03001369 spin_lock_init(&dev->slock);
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001370 mutex_init(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001371
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001372 vfd = video_device_alloc();
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001373 if (!vfd) {
1374 kfree(dev);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001375 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001376 }
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001377
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001378 *vfd = vivi_template;
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001379
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001380 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001381 if (ret < 0) {
1382 video_device_release(vfd);
1383 kfree(dev);
1384
1385 /* If some registers succeeded, keep driver */
1386 if (i)
1387 ret = 0;
1388
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001389 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001390 }
1391
1392 /* Now that everything is fine, let's add it to device list */
1393 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001394
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001395 snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
1396 vivi_template.name, vfd->minor);
1397
1398 if (video_nr >= 0)
1399 video_nr++;
1400
1401 dev->vfd = vfd;
Carl Karsten745271a2008-06-10 00:02:32 -03001402 printk(KERN_INFO "%s: V4L2 device registered as /dev/video%d\n",
Hans Verkuilc6330fb2008-10-19 18:54:26 -03001403 VIVI_MODULE_NAME, vfd->num);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001404 }
1405
1406 if (ret < 0) {
1407 vivi_release();
1408 printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001409 } else {
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001410 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Carl Karsten745271a2008-06-10 00:02:32 -03001411 "Capture Board ver %u.%u.%u successfully loaded.\n",
1412 (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
1413 VIVI_VERSION & 0xFF);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001414
1415 /* n_devs will reflect the actual number of allocated devices */
1416 n_devs = i;
1417 }
1418
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001419 return ret;
1420}
1421
1422static void __exit vivi_exit(void)
1423{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001424 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001425}
1426
1427module_init(vivi_init);
1428module_exit(vivi_exit);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001429
1430MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
1431MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
1432MODULE_LICENSE("Dual BSD/GPL");
1433
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001434module_param(video_nr, uint, 0444);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001435MODULE_PARM_DESC(video_nr, "video iminor start number");
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001436
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001437module_param(n_devs, uint, 0444);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001438MODULE_PARM_DESC(n_devs, "number of video devices to create");
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001439
Mauro Carvalho Chehab8996b3f2007-12-13 06:36:22 -03001440module_param_named(debug, vivi_template.debug, int, 0444);
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001441MODULE_PARM_DESC(debug, "activates debug info");
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001442
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001443module_param(vid_limit, int, 0644);
1444MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");