blob: fbfefae7886fac4cfc337a9d66b591ed9880fa11 [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>
Michael Krufkyf13df912006-03-23 22:01:44 -030031#include <linux/interrupt.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030032#include <linux/kthread.h>
33#include <linux/highmem.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080034#include <linux/freezer.h>
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030035#include <media/videobuf-vmalloc.h>
36#include <media/v4l2-device.h>
37#include <media/v4l2-ioctl.h>
38#include "font.h"
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030039
Mauro Carvalho Chehab584ce482008-06-10 15:21:49 -030040#define VIVI_MODULE_NAME "vivi"
Carl Karsten745271a2008-06-10 00:02:32 -030041
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030042/* Wake up at about 30 fps */
43#define WAKE_NUMERATOR 30
44#define WAKE_DENOMINATOR 1001
45#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
46
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030047#define VIVI_MAJOR_VERSION 0
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030048#define VIVI_MINOR_VERSION 6
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030049#define VIVI_RELEASE 0
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -030050#define VIVI_VERSION \
51 KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030052
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030053MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
54MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
55MODULE_LICENSE("Dual BSD/GPL");
56
57static unsigned video_nr = -1;
58module_param(video_nr, uint, 0644);
59MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
60
61static unsigned n_devs = 1;
62module_param(n_devs, uint, 0644);
63MODULE_PARM_DESC(n_devs, "number of video devices to create");
64
65static unsigned debug;
66module_param(debug, uint, 0644);
67MODULE_PARM_DESC(debug, "activates debug info");
68
69static unsigned int vid_limit = 16;
70module_param(vid_limit, uint, 0644);
71MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
72
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030073
74/* supported controls */
75static struct v4l2_queryctrl vivi_qctrl[] = {
76 {
77 .id = V4L2_CID_AUDIO_VOLUME,
78 .name = "Volume",
79 .minimum = 0,
80 .maximum = 65535,
81 .step = 65535/100,
82 .default_value = 65535,
Hans Verkuil4a5aa622009-02-14 13:50:19 -030083 .flags = V4L2_CTRL_FLAG_SLIDER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030084 .type = V4L2_CTRL_TYPE_INTEGER,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -030085 }, {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030086 .id = V4L2_CID_BRIGHTNESS,
87 .type = V4L2_CTRL_TYPE_INTEGER,
88 .name = "Brightness",
89 .minimum = 0,
90 .maximum = 255,
91 .step = 1,
92 .default_value = 127,
Hans Verkuil4a5aa622009-02-14 13:50:19 -030093 .flags = V4L2_CTRL_FLAG_SLIDER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030094 }, {
95 .id = V4L2_CID_CONTRAST,
96 .type = V4L2_CTRL_TYPE_INTEGER,
97 .name = "Contrast",
98 .minimum = 0,
99 .maximum = 255,
100 .step = 0x1,
101 .default_value = 0x10,
Hans Verkuil4a5aa622009-02-14 13:50:19 -0300102 .flags = V4L2_CTRL_FLAG_SLIDER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300103 }, {
104 .id = V4L2_CID_SATURATION,
105 .type = V4L2_CTRL_TYPE_INTEGER,
106 .name = "Saturation",
107 .minimum = 0,
108 .maximum = 255,
109 .step = 0x1,
110 .default_value = 127,
Hans Verkuil4a5aa622009-02-14 13:50:19 -0300111 .flags = V4L2_CTRL_FLAG_SLIDER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300112 }, {
113 .id = V4L2_CID_HUE,
114 .type = V4L2_CTRL_TYPE_INTEGER,
115 .name = "Hue",
116 .minimum = -128,
117 .maximum = 127,
118 .step = 0x1,
119 .default_value = 0,
Hans Verkuil4a5aa622009-02-14 13:50:19 -0300120 .flags = V4L2_CTRL_FLAG_SLIDER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300121 }
122};
123
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300124#define dprintk(dev, level, fmt, arg...) \
125 v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300126
127/* ------------------------------------------------------------------
128 Basic structures
129 ------------------------------------------------------------------*/
130
131struct vivi_fmt {
132 char *name;
133 u32 fourcc; /* v4l2 format id */
134 int depth;
135};
136
Magnus Dammd891f472008-10-14 12:47:09 -0300137static struct vivi_fmt formats[] = {
138 {
139 .name = "4:2:2, packed, YUYV",
140 .fourcc = V4L2_PIX_FMT_YUYV,
141 .depth = 16,
142 },
Magnus Dammfca36ba2008-10-14 12:47:25 -0300143 {
144 .name = "4:2:2, packed, UYVY",
145 .fourcc = V4L2_PIX_FMT_UYVY,
146 .depth = 16,
147 },
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300148 {
149 .name = "RGB565 (LE)",
150 .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
151 .depth = 16,
152 },
153 {
154 .name = "RGB565 (BE)",
155 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
156 .depth = 16,
157 },
Magnus Dammdef52392008-10-14 12:47:43 -0300158 {
159 .name = "RGB555 (LE)",
160 .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
161 .depth = 16,
162 },
163 {
164 .name = "RGB555 (BE)",
165 .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
166 .depth = 16,
167 },
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300168};
169
Magnus Dammd891f472008-10-14 12:47:09 -0300170static struct vivi_fmt *get_format(struct v4l2_format *f)
171{
172 struct vivi_fmt *fmt;
173 unsigned int k;
174
175 for (k = 0; k < ARRAY_SIZE(formats); k++) {
176 fmt = &formats[k];
177 if (fmt->fourcc == f->fmt.pix.pixelformat)
178 break;
179 }
180
181 if (k == ARRAY_SIZE(formats))
182 return NULL;
183
184 return &formats[k];
185}
186
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300187struct sg_to_addr {
188 int pos;
189 struct scatterlist *sg;
190};
191
192/* buffer for one video frame */
193struct vivi_buffer {
194 /* common v4l buffer stuff -- must be first */
195 struct videobuf_buffer vb;
196
197 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300198};
199
200struct vivi_dmaqueue {
201 struct list_head active;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300202
203 /* thread for generating video stream*/
204 struct task_struct *kthread;
205 wait_queue_head_t wq;
206 /* Counters to control fps rate */
207 int frame;
208 int ini_jiffies;
209};
210
211static LIST_HEAD(vivi_devlist);
212
213struct vivi_dev {
214 struct list_head vivi_devlist;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300215 struct v4l2_device v4l2_dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300216
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300217 spinlock_t slock;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300218 struct mutex mutex;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300219
220 int users;
221
222 /* various device info */
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -0300223 struct video_device *vfd;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300224
225 struct vivi_dmaqueue vidq;
226
227 /* Several counters */
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300228 int h, m, s, ms;
229 unsigned long jiffies;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300230 char timestr[13];
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300231
232 int mv_count; /* Controls bars movement */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300233
234 /* Input Number */
235 int input;
Hans Verkuilc41ee242009-02-14 13:43:44 -0300236
237 /* Control 'registers' */
238 int qctl_regs[ARRAY_SIZE(vivi_qctrl)];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300239};
240
241struct vivi_fh {
242 struct vivi_dev *dev;
243
244 /* video capture */
245 struct vivi_fmt *fmt;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300246 unsigned int width, height;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300247 struct videobuf_queue vb_vidq;
248
249 enum v4l2_buf_type type;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300250 unsigned char bars[8][3];
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300251 int input; /* Input Number on bars */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300252};
253
254/* ------------------------------------------------------------------
255 DMA and thread functions
256 ------------------------------------------------------------------*/
257
258/* Bars and Colors should match positions */
259
260enum colors {
261 WHITE,
262 AMBAR,
263 CYAN,
264 GREEN,
265 MAGENTA,
266 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300267 BLUE,
268 BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300269};
270
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300271 /* R G B */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300272#define COLOR_WHITE {204, 204, 204}
273#define COLOR_AMBAR {208, 208, 0}
274#define COLOR_CIAN { 0, 206, 206}
275#define COLOR_GREEN { 0, 239, 0}
276#define COLOR_MAGENTA {239, 0, 239}
277#define COLOR_RED {205, 0, 0}
278#define COLOR_BLUE { 0, 0, 255}
279#define COLOR_BLACK { 0, 0, 0}
280
281struct bar_std {
282 u8 bar[8][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300283};
284
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300285/* Maximum number of bars are 10 - otherwise, the input print code
286 should be modified */
287static struct bar_std bars[] = {
288 { /* Standard ITU-R color bar sequence */
289 {
290 COLOR_WHITE,
291 COLOR_AMBAR,
292 COLOR_CIAN,
293 COLOR_GREEN,
294 COLOR_MAGENTA,
295 COLOR_RED,
296 COLOR_BLUE,
297 COLOR_BLACK,
298 }
299 }, {
300 {
301 COLOR_WHITE,
302 COLOR_AMBAR,
303 COLOR_BLACK,
304 COLOR_WHITE,
305 COLOR_AMBAR,
306 COLOR_BLACK,
307 COLOR_WHITE,
308 COLOR_AMBAR,
309 }
310 }, {
311 {
312 COLOR_WHITE,
313 COLOR_CIAN,
314 COLOR_BLACK,
315 COLOR_WHITE,
316 COLOR_CIAN,
317 COLOR_BLACK,
318 COLOR_WHITE,
319 COLOR_CIAN,
320 }
321 }, {
322 {
323 COLOR_WHITE,
324 COLOR_GREEN,
325 COLOR_BLACK,
326 COLOR_WHITE,
327 COLOR_GREEN,
328 COLOR_BLACK,
329 COLOR_WHITE,
330 COLOR_GREEN,
331 }
332 },
333};
334
335#define NUM_INPUTS ARRAY_SIZE(bars)
336
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300337#define TO_Y(r, g, b) \
338 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300339/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300340#define TO_V(r, g, b) \
341 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300342/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300343#define TO_U(r, g, b) \
344 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300345
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300346#define TSTAMP_MIN_Y 24
347#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
348#define TSTAMP_INPUT_X 10
349#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300350
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300351static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
352{
353 unsigned char r_y, g_u, b_v;
354 unsigned char *p;
355 int color;
356
357 r_y = fh->bars[colorpos][0]; /* R or precalculated Y */
358 g_u = fh->bars[colorpos][1]; /* G or precalculated U */
359 b_v = fh->bars[colorpos][2]; /* B or precalculated V */
360
361 for (color = 0; color < 4; color++) {
362 p = buf + color;
363
Magnus Dammd891f472008-10-14 12:47:09 -0300364 switch (fh->fmt->fourcc) {
365 case V4L2_PIX_FMT_YUYV:
366 switch (color) {
367 case 0:
368 case 2:
369 *p = r_y;
370 break;
371 case 1:
372 *p = g_u;
373 break;
374 case 3:
375 *p = b_v;
376 break;
377 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300378 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300379 case V4L2_PIX_FMT_UYVY:
380 switch (color) {
381 case 1:
382 case 3:
383 *p = r_y;
384 break;
385 case 0:
386 *p = g_u;
387 break;
388 case 2:
389 *p = b_v;
390 break;
391 }
392 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300393 case V4L2_PIX_FMT_RGB565:
394 switch (color) {
395 case 0:
396 case 2:
397 *p = (g_u << 5) | b_v;
398 break;
399 case 1:
400 case 3:
401 *p = (r_y << 3) | (g_u >> 3);
402 break;
403 }
404 break;
405 case V4L2_PIX_FMT_RGB565X:
406 switch (color) {
407 case 0:
408 case 2:
409 *p = (r_y << 3) | (g_u >> 3);
410 break;
411 case 1:
412 case 3:
413 *p = (g_u << 5) | b_v;
414 break;
415 }
416 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300417 case V4L2_PIX_FMT_RGB555:
418 switch (color) {
419 case 0:
420 case 2:
421 *p = (g_u << 5) | b_v;
422 break;
423 case 1:
424 case 3:
425 *p = (r_y << 2) | (g_u >> 3);
426 break;
427 }
428 break;
429 case V4L2_PIX_FMT_RGB555X:
430 switch (color) {
431 case 0:
432 case 2:
433 *p = (r_y << 2) | (g_u >> 3);
434 break;
435 case 1:
436 case 3:
437 *p = (g_u << 5) | b_v;
438 break;
439 }
440 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300441 }
442 }
443}
444
445static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300446 int hmax, int line, int count, char *timestr)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300447{
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300448 int w, i, j;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300449 int pos = inipos;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300450 char *s;
451 u8 chr;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300452
453 /* We will just duplicate the second pixel at the packet */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300454 wmax /= 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300455
456 /* Generate a standard color bar pattern */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300457 for (w = 0; w < wmax; w++) {
458 int colorpos = ((w + count) * 8/(wmax + 1)) % 8;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300459
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300460 gen_twopix(fh, basep + pos, colorpos);
461 pos += 4; /* only 16 bpp supported for now */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300462 }
463
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300464 /* Prints input entry number */
465
466 /* Checks if it is possible to input number */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300467 if (TSTAMP_MAX_Y >= hmax)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300468 goto end;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300469
470 if (TSTAMP_INPUT_X + strlen(timestr) >= wmax)
471 goto end;
472
473 if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
474 chr = rom8x16_bits[fh->input * 16 + line - TSTAMP_MIN_Y];
475 pos = TSTAMP_INPUT_X;
476 for (i = 0; i < 7; i++) {
477 /* Draw white font on black background */
478 if (chr & 1 << (7 - i))
479 gen_twopix(fh, basep + pos, WHITE);
480 else
481 gen_twopix(fh, basep + pos, BLACK);
482 pos += 2;
483 }
484 }
485
486 /* Checks if it is possible to show timestamp */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300487 if (TSTAMP_MIN_X + strlen(timestr) >= wmax)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300488 goto end;
489
490 /* Print stream time */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300491 if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
492 j = TSTAMP_MIN_X;
493 for (s = timestr; *s; s++) {
494 chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y];
495 for (i = 0; i < 7; i++) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300496 pos = inipos + j * 2;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300497 /* Draw white font on black background */
498 if (chr & 1 << (7 - i))
499 gen_twopix(fh, basep + pos, WHITE);
500 else
501 gen_twopix(fh, basep + pos, BLACK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300502 j++;
503 }
504 }
505 }
506
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300507end:
Mauro Carvalho Chehabb50e7fe2007-01-25 05:00:01 -0300508 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300509}
Brandon Philips78718e52008-04-02 18:10:59 -0300510
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300511static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300512{
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300513 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300514 int h , pos = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300515 int hmax = buf->vb.height;
516 int wmax = buf->vb.width;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300517 struct timeval ts;
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300518 char *tmpbuf;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300519 void *vbuf = videobuf_to_vmalloc(&buf->vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300520
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300521 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300522 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300523
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300524 tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);
525 if (!tmpbuf)
Brandon Philips78718e52008-04-02 18:10:59 -0300526 return;
527
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300528 for (h = 0; h < hmax; h++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300529 gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count,
Mauro Carvalho Chehab3bef5e42007-09-22 02:01:33 -0300530 dev->timestr);
Brandon Philips78718e52008-04-02 18:10:59 -0300531 memcpy(vbuf + pos, tmpbuf, wmax * 2);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300532 pos += wmax*2;
533 }
534
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300535 dev->mv_count++;
Mauro Carvalho Chehab3bef5e42007-09-22 02:01:33 -0300536
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300537 kfree(tmpbuf);
538
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300539 /* Updates stream time */
540
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300541 dev->ms += jiffies_to_msecs(jiffies-dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300542 dev->jiffies = jiffies;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300543 if (dev->ms >= 1000) {
544 dev->ms -= 1000;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300545 dev->s++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300546 if (dev->s >= 60) {
547 dev->s -= 60;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300548 dev->m++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300549 if (dev->m > 60) {
550 dev->m -= 60;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300551 dev->h++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300552 if (dev->h > 24)
553 dev->h -= 24;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300554 }
555 }
556 }
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300557 sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300558 dev->h, dev->m, dev->s, dev->ms);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300559
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300560 dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n",
561 dev->timestr, (unsigned long)tmpbuf, pos);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300562
563 /* Advice that buffer was filled */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300564 buf->vb.field_count++;
565 do_gettimeofday(&ts);
566 buf->vb.ts = ts;
Brandon Philips78718e52008-04-02 18:10:59 -0300567 buf->vb.state = VIDEOBUF_DONE;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300568}
569
Brandon Philips78718e52008-04-02 18:10:59 -0300570static void vivi_thread_tick(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300571{
Brandon Philips78718e52008-04-02 18:10:59 -0300572 struct vivi_buffer *buf;
573 struct vivi_dev *dev = fh->dev;
574 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300575
Brandon Philips78718e52008-04-02 18:10:59 -0300576 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300577
Brandon Philips78718e52008-04-02 18:10:59 -0300578 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300579
Brandon Philips78718e52008-04-02 18:10:59 -0300580 spin_lock_irqsave(&dev->slock, flags);
581 if (list_empty(&dma_q->active)) {
582 dprintk(dev, 1, "No active queue to serve\n");
583 goto unlock;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300584 }
Brandon Philips78718e52008-04-02 18:10:59 -0300585
586 buf = list_entry(dma_q->active.next,
587 struct vivi_buffer, vb.queue);
588
589 /* Nobody is waiting on this buffer, return */
590 if (!waitqueue_active(&buf->vb.done))
591 goto unlock;
592
593 list_del(&buf->vb.queue);
594
595 do_gettimeofday(&buf->vb.ts);
596
597 /* Fill buffer */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300598 vivi_fillbuff(fh, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300599 dprintk(dev, 1, "filled buffer %p\n", buf);
600
601 wake_up(&buf->vb.done);
602 dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
603unlock:
604 spin_unlock_irqrestore(&dev->slock, flags);
605 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300606}
607
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300608#define frames_to_ms(frames) \
609 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
610
Brandon Philips78718e52008-04-02 18:10:59 -0300611static void vivi_sleep(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300612{
Brandon Philips78718e52008-04-02 18:10:59 -0300613 struct vivi_dev *dev = fh->dev;
614 struct vivi_dmaqueue *dma_q = &dev->vidq;
615 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300616 DECLARE_WAITQUEUE(wait, current);
617
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300618 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300619 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300620
621 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300622 if (kthread_should_stop())
623 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300624
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300625 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300626 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300627
Brandon Philips78718e52008-04-02 18:10:59 -0300628 vivi_thread_tick(fh);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300629
630 schedule_timeout_interruptible(timeout);
631
632stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300633 remove_wait_queue(&dma_q->wq, &wait);
634 try_to_freeze();
635}
636
Adrian Bunk972c3512006-04-27 21:06:50 -0300637static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300638{
Brandon Philips78718e52008-04-02 18:10:59 -0300639 struct vivi_fh *fh = data;
640 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300641
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300642 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300643
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700644 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300645
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300646 for (;;) {
Brandon Philips78718e52008-04-02 18:10:59 -0300647 vivi_sleep(fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300648
649 if (kthread_should_stop())
650 break;
651 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300652 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300653 return 0;
654}
655
Brandon Philips78718e52008-04-02 18:10:59 -0300656static int vivi_start_thread(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300657{
Brandon Philips78718e52008-04-02 18:10:59 -0300658 struct vivi_dev *dev = fh->dev;
659 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300660
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300661 dma_q->frame = 0;
662 dma_q->ini_jiffies = jiffies;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300663
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300664 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300665
Brandon Philips78718e52008-04-02 18:10:59 -0300666 dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300667
Akinobu Mita054afee2006-12-20 10:04:00 -0300668 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300669 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Akinobu Mita054afee2006-12-20 10:04:00 -0300670 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300671 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300672 /* Wakes thread */
673 wake_up_interruptible(&dma_q->wq);
674
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300675 dprintk(dev, 1, "returning from %s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300676 return 0;
677}
678
Adrian Bunk972c3512006-04-27 21:06:50 -0300679static void vivi_stop_thread(struct vivi_dmaqueue *dma_q)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300680{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300681 struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
682
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300683 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300684 /* shutdown control thread */
685 if (dma_q->kthread) {
686 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300687 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300688 }
689}
690
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300691/* ------------------------------------------------------------------
692 Videobuf operations
693 ------------------------------------------------------------------*/
694static int
695buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
696{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300697 struct vivi_fh *fh = vq->priv_data;
698 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300699
700 *size = fh->width*fh->height*2;
701
702 if (0 == *count)
703 *count = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300704
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300705 while (*size * *count > vid_limit * 1024 * 1024)
706 (*count)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300707
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300708 dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300709 *count, *size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300710
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300711 return 0;
712}
713
Adrian Bunk972c3512006-04-27 21:06:50 -0300714static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300715{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300716 struct vivi_fh *fh = vq->priv_data;
717 struct vivi_dev *dev = fh->dev;
718
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300719 dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300720
721 if (in_interrupt())
722 BUG();
723
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300724 videobuf_vmalloc_free(&buf->vb);
Mauro Carvalho Chehabfbde31d2008-04-13 14:57:44 -0300725 dprintk(dev, 1, "free_buffer: freed\n");
Brandon Philips0fc06862007-11-06 20:02:36 -0300726 buf->vb.state = VIDEOBUF_NEEDS_INIT;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300727}
728
729#define norm_maxw() 1024
730#define norm_maxh() 768
731static int
732buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
733 enum v4l2_field field)
734{
735 struct vivi_fh *fh = vq->priv_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300736 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300737 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300738 int rc;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300739
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300740 dprintk(dev, 1, "%s, field=%d\n", __func__, field);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300741
742 BUG_ON(NULL == fh->fmt);
Brandon Philips78718e52008-04-02 18:10:59 -0300743
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300744 if (fh->width < 48 || fh->width > norm_maxw() ||
745 fh->height < 32 || fh->height > norm_maxh())
746 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300747
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300748 buf->vb.size = fh->width*fh->height*2;
749 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
750 return -EINVAL;
751
Brandon Philips78718e52008-04-02 18:10:59 -0300752 /* These properties only change when queue is idle, see s_fmt */
753 buf->fmt = fh->fmt;
754 buf->vb.width = fh->width;
755 buf->vb.height = fh->height;
756 buf->vb.field = field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300757
Brandon Philips0fc06862007-11-06 20:02:36 -0300758 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300759 rc = videobuf_iolock(vq, &buf->vb, NULL);
760 if (rc < 0)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300761 goto fail;
762 }
763
Brandon Philips0fc06862007-11-06 20:02:36 -0300764 buf->vb.state = VIDEOBUF_PREPARED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300765
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300766 return 0;
767
768fail:
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300769 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300770 return rc;
771}
772
773static void
774buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
775{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300776 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
777 struct vivi_fh *fh = vq->priv_data;
778 struct vivi_dev *dev = fh->dev;
Brandon Philips78718e52008-04-02 18:10:59 -0300779 struct vivi_dmaqueue *vidq = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300780
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300781 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300782
Brandon Philips78718e52008-04-02 18:10:59 -0300783 buf->vb.state = VIDEOBUF_QUEUED;
784 list_add_tail(&buf->vb.queue, &vidq->active);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300785}
786
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300787static void buffer_release(struct videobuf_queue *vq,
788 struct videobuf_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300789{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300790 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300791 struct vivi_fh *fh = vq->priv_data;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300792 struct vivi_dev *dev = (struct vivi_dev *)fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300793
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300794 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300795
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300796 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300797}
798
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300799static struct videobuf_queue_ops vivi_video_qops = {
800 .buf_setup = buffer_setup,
801 .buf_prepare = buffer_prepare,
802 .buf_queue = buffer_queue,
803 .buf_release = buffer_release,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300804};
805
806/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300807 IOCTL vidioc handling
808 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300809static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300810 struct v4l2_capability *cap)
811{
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300812 struct vivi_fh *fh = priv;
813 struct vivi_dev *dev = fh->dev;
814
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300815 strcpy(cap->driver, "vivi");
816 strcpy(cap->card, "vivi");
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300817 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300818 cap->version = VIVI_VERSION;
819 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
820 V4L2_CAP_STREAMING |
821 V4L2_CAP_READWRITE;
822 return 0;
823}
824
Hans Verkuil78b526a2008-05-28 12:16:41 -0300825static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300826 struct v4l2_fmtdesc *f)
827{
Magnus Dammd891f472008-10-14 12:47:09 -0300828 struct vivi_fmt *fmt;
829
830 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300831 return -EINVAL;
832
Magnus Dammd891f472008-10-14 12:47:09 -0300833 fmt = &formats[f->index];
834
835 strlcpy(f->description, fmt->name, sizeof(f->description));
836 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300837 return 0;
838}
839
Hans Verkuil78b526a2008-05-28 12:16:41 -0300840static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300841 struct v4l2_format *f)
842{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300843 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300844
845 f->fmt.pix.width = fh->width;
846 f->fmt.pix.height = fh->height;
847 f->fmt.pix.field = fh->vb_vidq.field;
848 f->fmt.pix.pixelformat = fh->fmt->fourcc;
849 f->fmt.pix.bytesperline =
850 (f->fmt.pix.width * fh->fmt->depth) >> 3;
851 f->fmt.pix.sizeimage =
852 f->fmt.pix.height * f->fmt.pix.bytesperline;
853
854 return (0);
855}
856
Hans Verkuil78b526a2008-05-28 12:16:41 -0300857static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300858 struct v4l2_format *f)
859{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300860 struct vivi_fh *fh = priv;
861 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300862 struct vivi_fmt *fmt;
863 enum v4l2_field field;
864 unsigned int maxw, maxh;
865
Magnus Dammd891f472008-10-14 12:47:09 -0300866 fmt = get_format(f);
867 if (!fmt) {
868 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
869 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300870 return -EINVAL;
871 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300872
873 field = f->fmt.pix.field;
874
875 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300876 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300877 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300878 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300879 return -EINVAL;
880 }
881
882 maxw = norm_maxw();
883 maxh = norm_maxh();
884
885 f->fmt.pix.field = field;
886 if (f->fmt.pix.height < 32)
887 f->fmt.pix.height = 32;
888 if (f->fmt.pix.height > maxh)
889 f->fmt.pix.height = maxh;
890 if (f->fmt.pix.width < 48)
891 f->fmt.pix.width = 48;
892 if (f->fmt.pix.width > maxw)
893 f->fmt.pix.width = maxw;
894 f->fmt.pix.width &= ~0x03;
895 f->fmt.pix.bytesperline =
896 (f->fmt.pix.width * fmt->depth) >> 3;
897 f->fmt.pix.sizeimage =
898 f->fmt.pix.height * f->fmt.pix.bytesperline;
899
900 return 0;
901}
902
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300903/* precalculate color bar values to speed up rendering */
904static void precalculate_bars(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300905{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300906 struct vivi_dev *dev = fh->dev;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300907 unsigned char r, g, b;
Magnus Dammd891f472008-10-14 12:47:09 -0300908 int k, is_yuv;
Brandon Philips78718e52008-04-02 18:10:59 -0300909
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300910 fh->input = dev->input;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300911
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300912 for (k = 0; k < 8; k++) {
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300913 r = bars[fh->input].bar[k][0];
914 g = bars[fh->input].bar[k][1];
915 b = bars[fh->input].bar[k][2];
Magnus Dammd891f472008-10-14 12:47:09 -0300916 is_yuv = 0;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300917
Magnus Dammd891f472008-10-14 12:47:09 -0300918 switch (fh->fmt->fourcc) {
919 case V4L2_PIX_FMT_YUYV:
Magnus Dammfca36ba2008-10-14 12:47:25 -0300920 case V4L2_PIX_FMT_UYVY:
Magnus Dammd891f472008-10-14 12:47:09 -0300921 is_yuv = 1;
922 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300923 case V4L2_PIX_FMT_RGB565:
924 case V4L2_PIX_FMT_RGB565X:
925 r >>= 3;
926 g >>= 2;
927 b >>= 3;
928 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300929 case V4L2_PIX_FMT_RGB555:
930 case V4L2_PIX_FMT_RGB555X:
931 r >>= 3;
932 g >>= 3;
933 b >>= 3;
934 break;
Magnus Dammd891f472008-10-14 12:47:09 -0300935 }
936
937 if (is_yuv) {
938 fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
939 fh->bars[k][1] = TO_U(r, g, b); /* Cb */
940 fh->bars[k][2] = TO_V(r, g, b); /* Cr */
941 } else {
942 fh->bars[k][0] = r;
943 fh->bars[k][1] = g;
944 fh->bars[k][2] = b;
945 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300946 }
947
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300948}
949
950/*FIXME: This seems to be generic enough to be at videodev2 */
951static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
952 struct v4l2_format *f)
953{
954 struct vivi_fh *fh = priv;
955 struct videobuf_queue *q = &fh->vb_vidq;
956
957 int ret = vidioc_try_fmt_vid_cap(file, fh, f);
958 if (ret < 0)
959 return ret;
960
961 mutex_lock(&q->vb_lock);
962
963 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
964 dprintk(fh->dev, 1, "%s queue busy\n", __func__);
965 ret = -EBUSY;
966 goto out;
967 }
968
969 fh->fmt = get_format(f);
970 fh->width = f->fmt.pix.width;
971 fh->height = f->fmt.pix.height;
972 fh->vb_vidq.field = f->fmt.pix.field;
973 fh->type = f->type;
974
975 precalculate_bars(fh);
976
Brandon Philips78718e52008-04-02 18:10:59 -0300977 ret = 0;
978out:
979 mutex_unlock(&q->vb_lock);
980
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300981 return ret;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300982}
983
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300984static int vidioc_reqbufs(struct file *file, void *priv,
985 struct v4l2_requestbuffers *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 Chehabc820cc42006-06-04 10:34:12 -0300988
989 return (videobuf_reqbufs(&fh->vb_vidq, p));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300990}
991
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300992static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300993{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300994 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300995
996 return (videobuf_querybuf(&fh->vb_vidq, p));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300997}
998
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300999static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001000{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001001 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001002
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001003 return (videobuf_qbuf(&fh->vb_vidq, p));
1004}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001005
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001006static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001007{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001008 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001009
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001010 return (videobuf_dqbuf(&fh->vb_vidq, p,
1011 file->f_flags & O_NONBLOCK));
1012}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001013
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -03001014#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001015static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001016{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001017 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001018
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001019 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001020}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001021#endif
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001022
Adrian Bunkdc46ace2006-06-23 06:42:44 -03001023static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001024{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001025 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001026
1027 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1028 return -EINVAL;
1029 if (i != fh->type)
1030 return -EINVAL;
1031
Brandon Philipsba32bd92007-09-27 20:55:17 -03001032 return videobuf_streamon(&fh->vb_vidq);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001033}
1034
Adrian Bunkdc46ace2006-06-23 06:42:44 -03001035static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001036{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001037 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001038
1039 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1040 return -EINVAL;
1041 if (i != fh->type)
1042 return -EINVAL;
1043
Brandon Philipsba32bd92007-09-27 20:55:17 -03001044 return videobuf_streamoff(&fh->vb_vidq);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001045}
1046
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001047static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001048{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001049 return 0;
1050}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001051
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001052/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001053static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001054 struct v4l2_input *inp)
1055{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001056 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001057 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001058
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001059 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001060 inp->std = V4L2_STD_525_60;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001061 sprintf(inp->name, "Camera %u", inp->index);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001062
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001063 return (0);
1064}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001065
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001066static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001067{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001068 struct vivi_fh *fh = priv;
1069 struct vivi_dev *dev = fh->dev;
1070
1071 *i = dev->input;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001072
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001073 return (0);
1074}
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001075static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001076{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001077 struct vivi_fh *fh = priv;
1078 struct vivi_dev *dev = fh->dev;
1079
1080 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001081 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001082
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001083 dev->input = i;
1084 precalculate_bars(fh);
1085
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001086 return (0);
1087}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001088
1089 /* --- controls ---------------------------------------------- */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001090static int vidioc_queryctrl(struct file *file, void *priv,
1091 struct v4l2_queryctrl *qc)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001092{
1093 int i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001094
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001095 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1096 if (qc->id && qc->id == vivi_qctrl[i].id) {
1097 memcpy(qc, &(vivi_qctrl[i]),
1098 sizeof(*qc));
1099 return (0);
1100 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001101
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001102 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001103}
1104
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001105static int vidioc_g_ctrl(struct file *file, void *priv,
1106 struct v4l2_control *ctrl)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001107{
Hans Verkuilc41ee242009-02-14 13:43:44 -03001108 struct vivi_fh *fh = priv;
1109 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001110 int i;
1111
1112 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1113 if (ctrl->id == vivi_qctrl[i].id) {
Hans Verkuilc41ee242009-02-14 13:43:44 -03001114 ctrl->value = dev->qctl_regs[i];
1115 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001116 }
1117
1118 return -EINVAL;
1119}
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001120static int vidioc_s_ctrl(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001121 struct v4l2_control *ctrl)
1122{
Hans Verkuilc41ee242009-02-14 13:43:44 -03001123 struct vivi_fh *fh = priv;
1124 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001125 int i;
1126
1127 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1128 if (ctrl->id == vivi_qctrl[i].id) {
Hans Verkuilc41ee242009-02-14 13:43:44 -03001129 if (ctrl->value < vivi_qctrl[i].minimum ||
1130 ctrl->value > vivi_qctrl[i].maximum) {
1131 return -ERANGE;
1132 }
1133 dev->qctl_regs[i] = ctrl->value;
1134 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001135 }
1136 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001137}
1138
1139/* ------------------------------------------------------------------
1140 File operations for the device
1141 ------------------------------------------------------------------*/
1142
Hans Verkuilbec43662008-12-30 06:58:20 -03001143static int vivi_open(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001144{
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001145 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab63b79cf2008-04-26 08:25:18 -03001146 struct vivi_fh *fh = NULL;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001147 int retval = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001148
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001149 mutex_lock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001150 dev->users++;
1151
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001152 if (dev->users > 1) {
1153 dev->users--;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001154 mutex_unlock(&dev->mutex);
1155 return -EBUSY;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001156 }
1157
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001158 dprintk(dev, 1, "open /dev/video%d type=%s users=%d\n", dev->vfd->num,
Trent Piephoa991f442007-10-10 05:37:43 -03001159 v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001160
1161 /* allocate + initialize per filehandle data */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001162 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001163 if (NULL == fh) {
1164 dev->users--;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001165 retval = -ENOMEM;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001166 }
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001167 mutex_unlock(&dev->mutex);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001168
1169 if (retval)
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001170 return retval;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001171
1172 file->private_data = fh;
1173 fh->dev = dev;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001174
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001175 fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Magnus Dammd891f472008-10-14 12:47:09 -03001176 fh->fmt = &formats[0];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001177 fh->width = 640;
1178 fh->height = 480;
1179
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001180 /* Resets frame counters */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001181 dev->h = 0;
1182 dev->m = 0;
1183 dev->s = 0;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -03001184 dev->ms = 0;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001185 dev->mv_count = 0;
1186 dev->jiffies = jiffies;
1187 sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -03001188 dev->h, dev->m, dev->s, dev->ms);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001189
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001190 videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops,
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -03001191 NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001192 sizeof(struct vivi_buffer), fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001193
Brandon Philips78718e52008-04-02 18:10:59 -03001194 vivi_start_thread(fh);
1195
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001196 return 0;
1197}
1198
1199static ssize_t
1200vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1201{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001202 struct vivi_fh *fh = file->private_data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001203
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001204 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Mauro Carvalho Chehabacb09af2007-07-29 22:56:11 -03001205 return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001206 file->f_flags & O_NONBLOCK);
1207 }
1208 return 0;
1209}
1210
1211static unsigned int
1212vivi_poll(struct file *file, struct poll_table_struct *wait)
1213{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001214 struct vivi_fh *fh = file->private_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001215 struct vivi_dev *dev = fh->dev;
Brandon Philips85c7c70bc2007-09-27 20:55:02 -03001216 struct videobuf_queue *q = &fh->vb_vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001217
Harvey Harrison7e28adb2008-04-08 23:20:00 -03001218 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001219
1220 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
1221 return POLLERR;
1222
Brandon Philips85c7c70bc2007-09-27 20:55:02 -03001223 return videobuf_poll_stream(file, q, wait);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001224}
1225
Hans Verkuilbec43662008-12-30 06:58:20 -03001226static int vivi_close(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001227{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001228 struct vivi_fh *fh = file->private_data;
1229 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001230 struct vivi_dmaqueue *vidq = &dev->vidq;
1231
Hans Verkuilbec43662008-12-30 06:58:20 -03001232 int minor = video_devdata(file)->minor;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001233
1234 vivi_stop_thread(vidq);
Brandon Philips053fcb62007-11-13 20:11:26 -03001235 videobuf_stop(&fh->vb_vidq);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001236 videobuf_mmap_free(&fh->vb_vidq);
1237
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001238 kfree(fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001239
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001240 mutex_lock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001241 dev->users--;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001242 mutex_unlock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001243
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001244 dprintk(dev, 1, "close called (minor=%d, users=%d)\n",
1245 minor, dev->users);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001246
1247 return 0;
1248}
1249
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001250static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001251{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001252 struct vivi_fh *fh = file->private_data;
1253 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001254 int ret;
1255
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001256 dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001257
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001258 ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001259
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001260 dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n",
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001261 (unsigned long)vma->vm_start,
1262 (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
1263 ret);
1264
1265 return ret;
1266}
1267
Hans Verkuilbec43662008-12-30 06:58:20 -03001268static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001269 .owner = THIS_MODULE,
1270 .open = vivi_open,
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001271 .release = vivi_close,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001272 .read = vivi_read,
1273 .poll = vivi_poll,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001274 .ioctl = video_ioctl2, /* V4L2 ioctl handler */
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001275 .mmap = vivi_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001276};
1277
Hans Verkuila3998102008-07-21 02:57:38 -03001278static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001279 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001280 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1281 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1282 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1283 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001284 .vidioc_reqbufs = vidioc_reqbufs,
1285 .vidioc_querybuf = vidioc_querybuf,
1286 .vidioc_qbuf = vidioc_qbuf,
1287 .vidioc_dqbuf = vidioc_dqbuf,
1288 .vidioc_s_std = vidioc_s_std,
1289 .vidioc_enum_input = vidioc_enum_input,
1290 .vidioc_g_input = vidioc_g_input,
1291 .vidioc_s_input = vidioc_s_input,
1292 .vidioc_queryctrl = vidioc_queryctrl,
1293 .vidioc_g_ctrl = vidioc_g_ctrl,
1294 .vidioc_s_ctrl = vidioc_s_ctrl,
1295 .vidioc_streamon = vidioc_streamon,
1296 .vidioc_streamoff = vidioc_streamoff,
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -03001297#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001298 .vidiocgmbuf = vidiocgmbuf,
1299#endif
Hans Verkuila3998102008-07-21 02:57:38 -03001300};
1301
1302static struct video_device vivi_template = {
1303 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001304 .fops = &vivi_fops,
1305 .ioctl_ops = &vivi_ioctl_ops,
1306 .minor = -1,
1307 .release = video_device_release,
1308
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001309 .tvnorms = V4L2_STD_525_60,
Mauro Carvalho Chehabe75f9ce2006-11-20 13:19:20 -03001310 .current_norm = V4L2_STD_NTSC_M,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001311};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001312
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001313/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001314 Initialization and module stuff
1315 ------------------------------------------------------------------*/
1316
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001317static int vivi_release(void)
1318{
1319 struct vivi_dev *dev;
1320 struct list_head *list;
1321
1322 while (!list_empty(&vivi_devlist)) {
1323 list = vivi_devlist.next;
1324 list_del(list);
1325 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1326
1327 v4l2_info(&dev->v4l2_dev, "unregistering /dev/video%d\n",
1328 dev->vfd->num);
1329 video_unregister_device(dev->vfd);
1330 v4l2_device_unregister(&dev->v4l2_dev);
1331 kfree(dev);
1332 }
1333
1334 return 0;
1335}
1336
Hans Verkuilc41ee242009-02-14 13:43:44 -03001337static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001338{
1339 struct vivi_dev *dev;
1340 struct video_device *vfd;
Hans Verkuilc41ee242009-02-14 13:43:44 -03001341 int ret, i;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001342
1343 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1344 if (!dev)
1345 return -ENOMEM;
1346
1347 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001348 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001349 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1350 if (ret)
1351 goto free_dev;
1352
1353 /* init video dma queues */
1354 INIT_LIST_HEAD(&dev->vidq.active);
1355 init_waitqueue_head(&dev->vidq.wq);
1356
1357 /* initialize locks */
1358 spin_lock_init(&dev->slock);
1359 mutex_init(&dev->mutex);
1360
1361 ret = -ENOMEM;
1362 vfd = video_device_alloc();
1363 if (!vfd)
1364 goto unreg_dev;
1365
1366 *vfd = vivi_template;
1367
1368 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1369 if (ret < 0)
1370 goto rel_vdev;
1371
1372 video_set_drvdata(vfd, dev);
1373
Hans Verkuilc41ee242009-02-14 13:43:44 -03001374 /* Set all controls to their default value. */
1375 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1376 dev->qctl_regs[i] = vivi_qctrl[i].default_value;
1377
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001378 /* Now that everything is fine, let's add it to device list */
1379 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1380
1381 snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
1382 vivi_template.name, vfd->num);
1383
1384 if (video_nr >= 0)
1385 video_nr++;
1386
1387 dev->vfd = vfd;
1388 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n",
1389 vfd->num);
1390 return 0;
1391
1392rel_vdev:
1393 video_device_release(vfd);
1394unreg_dev:
1395 v4l2_device_unregister(&dev->v4l2_dev);
1396free_dev:
1397 kfree(dev);
1398 return ret;
1399}
1400
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001401/* This routine allocates from 1 to n_devs virtual drivers.
1402
1403 The real maximum number of virtual drivers will depend on how many drivers
1404 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001405 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001406 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001407static int __init vivi_init(void)
1408{
Hans Verkuil9185cbf2009-03-06 09:58:12 -03001409 int ret = 0, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001410
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001411 if (n_devs <= 0)
1412 n_devs = 1;
1413
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001414 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001415 ret = vivi_create_instance(i);
1416 if (ret) {
1417 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001418 if (i)
1419 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001420 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001421 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001422 }
1423
1424 if (ret < 0) {
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001425 printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001426 return ret;
1427 }
1428
1429 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Carl Karsten745271a2008-06-10 00:02:32 -03001430 "Capture Board ver %u.%u.%u successfully loaded.\n",
1431 (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
1432 VIVI_VERSION & 0xFF);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001433
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001434 /* n_devs will reflect the actual number of allocated devices */
1435 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001436
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001437 return ret;
1438}
1439
1440static void __exit vivi_exit(void)
1441{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001442 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001443}
1444
1445module_init(vivi_init);
1446module_exit(vivi_exit);