blob: 5a736b8a5a33f50aa72ad151ed193f02b0a4519a [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 Chehabc285add2009-06-25 16:28:23 -0300346/* precalculate color bar values to speed up rendering */
347static void precalculate_bars(struct vivi_fh *fh)
348{
349 struct vivi_dev *dev = fh->dev;
350 unsigned char r, g, b;
351 int k, is_yuv;
352
353 fh->input = dev->input;
354
355 for (k = 0; k < 8; k++) {
356 r = bars[fh->input].bar[k][0];
357 g = bars[fh->input].bar[k][1];
358 b = bars[fh->input].bar[k][2];
359 is_yuv = 0;
360
361 switch (fh->fmt->fourcc) {
362 case V4L2_PIX_FMT_YUYV:
363 case V4L2_PIX_FMT_UYVY:
364 is_yuv = 1;
365 break;
366 case V4L2_PIX_FMT_RGB565:
367 case V4L2_PIX_FMT_RGB565X:
368 r >>= 3;
369 g >>= 2;
370 b >>= 3;
371 break;
372 case V4L2_PIX_FMT_RGB555:
373 case V4L2_PIX_FMT_RGB555X:
374 r >>= 3;
375 g >>= 3;
376 b >>= 3;
377 break;
378 }
379
380 if (is_yuv) {
381 fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
382 fh->bars[k][1] = TO_U(r, g, b); /* Cb */
383 fh->bars[k][2] = TO_V(r, g, b); /* Cr */
384 } else {
385 fh->bars[k][0] = r;
386 fh->bars[k][1] = g;
387 fh->bars[k][2] = b;
388 }
389 }
390
391}
392
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300393#define TSTAMP_MIN_Y 24
394#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
395#define TSTAMP_INPUT_X 10
396#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300397
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300398static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
399{
400 unsigned char r_y, g_u, b_v;
401 unsigned char *p;
402 int color;
403
404 r_y = fh->bars[colorpos][0]; /* R or precalculated Y */
405 g_u = fh->bars[colorpos][1]; /* G or precalculated U */
406 b_v = fh->bars[colorpos][2]; /* B or precalculated V */
407
408 for (color = 0; color < 4; color++) {
409 p = buf + color;
410
Magnus Dammd891f472008-10-14 12:47:09 -0300411 switch (fh->fmt->fourcc) {
412 case V4L2_PIX_FMT_YUYV:
413 switch (color) {
414 case 0:
415 case 2:
416 *p = r_y;
417 break;
418 case 1:
419 *p = g_u;
420 break;
421 case 3:
422 *p = b_v;
423 break;
424 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300425 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300426 case V4L2_PIX_FMT_UYVY:
427 switch (color) {
428 case 1:
429 case 3:
430 *p = r_y;
431 break;
432 case 0:
433 *p = g_u;
434 break;
435 case 2:
436 *p = b_v;
437 break;
438 }
439 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300440 case V4L2_PIX_FMT_RGB565:
441 switch (color) {
442 case 0:
443 case 2:
444 *p = (g_u << 5) | b_v;
445 break;
446 case 1:
447 case 3:
448 *p = (r_y << 3) | (g_u >> 3);
449 break;
450 }
451 break;
452 case V4L2_PIX_FMT_RGB565X:
453 switch (color) {
454 case 0:
455 case 2:
456 *p = (r_y << 3) | (g_u >> 3);
457 break;
458 case 1:
459 case 3:
460 *p = (g_u << 5) | b_v;
461 break;
462 }
463 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300464 case V4L2_PIX_FMT_RGB555:
465 switch (color) {
466 case 0:
467 case 2:
468 *p = (g_u << 5) | b_v;
469 break;
470 case 1:
471 case 3:
472 *p = (r_y << 2) | (g_u >> 3);
473 break;
474 }
475 break;
476 case V4L2_PIX_FMT_RGB555X:
477 switch (color) {
478 case 0:
479 case 2:
480 *p = (r_y << 2) | (g_u >> 3);
481 break;
482 case 1:
483 case 3:
484 *p = (g_u << 5) | b_v;
485 break;
486 }
487 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300488 }
489 }
490}
491
492static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300493 int hmax, int line, int count, char *timestr)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300494{
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300495 int w, i, j;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300496 int pos = inipos;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300497 char *s;
498 u8 chr;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300499
500 /* We will just duplicate the second pixel at the packet */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300501 wmax /= 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300502
503 /* Generate a standard color bar pattern */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300504 for (w = 0; w < wmax; w++) {
505 int colorpos = ((w + count) * 8/(wmax + 1)) % 8;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300506
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300507 gen_twopix(fh, basep + pos, colorpos);
508 pos += 4; /* only 16 bpp supported for now */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300509 }
510
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300511 /* Prints input entry number */
512
513 /* Checks if it is possible to input number */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300514 if (TSTAMP_MAX_Y >= hmax)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300515 goto end;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300516
517 if (TSTAMP_INPUT_X + strlen(timestr) >= wmax)
518 goto end;
519
520 if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
521 chr = rom8x16_bits[fh->input * 16 + line - TSTAMP_MIN_Y];
522 pos = TSTAMP_INPUT_X;
523 for (i = 0; i < 7; i++) {
524 /* Draw white font on black background */
525 if (chr & 1 << (7 - i))
526 gen_twopix(fh, basep + pos, WHITE);
527 else
528 gen_twopix(fh, basep + pos, BLACK);
529 pos += 2;
530 }
531 }
532
533 /* Checks if it is possible to show timestamp */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300534 if (TSTAMP_MIN_X + strlen(timestr) >= wmax)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300535 goto end;
536
537 /* Print stream time */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300538 if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
539 j = TSTAMP_MIN_X;
540 for (s = timestr; *s; s++) {
541 chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y];
542 for (i = 0; i < 7; i++) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300543 pos = inipos + j * 2;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300544 /* Draw white font on black background */
545 if (chr & 1 << (7 - i))
546 gen_twopix(fh, basep + pos, WHITE);
547 else
548 gen_twopix(fh, basep + pos, BLACK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300549 j++;
550 }
551 }
552 }
553
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300554end:
Mauro Carvalho Chehabb50e7fe2007-01-25 05:00:01 -0300555 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300556}
Brandon Philips78718e52008-04-02 18:10:59 -0300557
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300558static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300559{
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300560 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300561 int h , pos = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300562 int hmax = buf->vb.height;
563 int wmax = buf->vb.width;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300564 struct timeval ts;
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300565 char *tmpbuf;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300566 void *vbuf = videobuf_to_vmalloc(&buf->vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300567
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300568 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300569 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300570
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300571 tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);
572 if (!tmpbuf)
Brandon Philips78718e52008-04-02 18:10:59 -0300573 return;
574
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300575 for (h = 0; h < hmax; h++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300576 gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count,
Mauro Carvalho Chehab3bef5e42007-09-22 02:01:33 -0300577 dev->timestr);
Brandon Philips78718e52008-04-02 18:10:59 -0300578 memcpy(vbuf + pos, tmpbuf, wmax * 2);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300579 pos += wmax*2;
580 }
581
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300582 dev->mv_count++;
Mauro Carvalho Chehab3bef5e42007-09-22 02:01:33 -0300583
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300584 kfree(tmpbuf);
585
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300586 /* Updates stream time */
587
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300588 dev->ms += jiffies_to_msecs(jiffies-dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300589 dev->jiffies = jiffies;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300590 if (dev->ms >= 1000) {
591 dev->ms -= 1000;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300592 dev->s++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300593 if (dev->s >= 60) {
594 dev->s -= 60;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300595 dev->m++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300596 if (dev->m > 60) {
597 dev->m -= 60;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300598 dev->h++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300599 if (dev->h > 24)
600 dev->h -= 24;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300601 }
602 }
603 }
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300604 sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300605 dev->h, dev->m, dev->s, dev->ms);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300606
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300607 dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n",
608 dev->timestr, (unsigned long)tmpbuf, pos);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300609
610 /* Advice that buffer was filled */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300611 buf->vb.field_count++;
612 do_gettimeofday(&ts);
613 buf->vb.ts = ts;
Brandon Philips78718e52008-04-02 18:10:59 -0300614 buf->vb.state = VIDEOBUF_DONE;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300615}
616
Brandon Philips78718e52008-04-02 18:10:59 -0300617static void vivi_thread_tick(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300618{
Brandon Philips78718e52008-04-02 18:10:59 -0300619 struct vivi_buffer *buf;
620 struct vivi_dev *dev = fh->dev;
621 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300622
Brandon Philips78718e52008-04-02 18:10:59 -0300623 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300624
Brandon Philips78718e52008-04-02 18:10:59 -0300625 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300626
Brandon Philips78718e52008-04-02 18:10:59 -0300627 spin_lock_irqsave(&dev->slock, flags);
628 if (list_empty(&dma_q->active)) {
629 dprintk(dev, 1, "No active queue to serve\n");
630 goto unlock;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300631 }
Brandon Philips78718e52008-04-02 18:10:59 -0300632
633 buf = list_entry(dma_q->active.next,
634 struct vivi_buffer, vb.queue);
635
636 /* Nobody is waiting on this buffer, return */
637 if (!waitqueue_active(&buf->vb.done))
638 goto unlock;
639
640 list_del(&buf->vb.queue);
641
642 do_gettimeofday(&buf->vb.ts);
643
644 /* Fill buffer */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300645 vivi_fillbuff(fh, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300646 dprintk(dev, 1, "filled buffer %p\n", buf);
647
648 wake_up(&buf->vb.done);
649 dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
650unlock:
651 spin_unlock_irqrestore(&dev->slock, flags);
652 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300653}
654
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300655#define frames_to_ms(frames) \
656 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
657
Brandon Philips78718e52008-04-02 18:10:59 -0300658static void vivi_sleep(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300659{
Brandon Philips78718e52008-04-02 18:10:59 -0300660 struct vivi_dev *dev = fh->dev;
661 struct vivi_dmaqueue *dma_q = &dev->vidq;
662 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300663 DECLARE_WAITQUEUE(wait, current);
664
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300665 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300666 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300667
668 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300669 if (kthread_should_stop())
670 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300671
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300672 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300673 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300674
Brandon Philips78718e52008-04-02 18:10:59 -0300675 vivi_thread_tick(fh);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300676
677 schedule_timeout_interruptible(timeout);
678
679stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300680 remove_wait_queue(&dma_q->wq, &wait);
681 try_to_freeze();
682}
683
Adrian Bunk972c3512006-04-27 21:06:50 -0300684static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300685{
Brandon Philips78718e52008-04-02 18:10:59 -0300686 struct vivi_fh *fh = data;
687 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300688
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300689 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300690
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700691 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300692
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300693 for (;;) {
Brandon Philips78718e52008-04-02 18:10:59 -0300694 vivi_sleep(fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300695
696 if (kthread_should_stop())
697 break;
698 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300699 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300700 return 0;
701}
702
Brandon Philips78718e52008-04-02 18:10:59 -0300703static int vivi_start_thread(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300704{
Brandon Philips78718e52008-04-02 18:10:59 -0300705 struct vivi_dev *dev = fh->dev;
706 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300707
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300708 dma_q->frame = 0;
709 dma_q->ini_jiffies = jiffies;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300710
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300711 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300712
Brandon Philips78718e52008-04-02 18:10:59 -0300713 dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300714
Akinobu Mita054afee2006-12-20 10:04:00 -0300715 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300716 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Akinobu Mita054afee2006-12-20 10:04:00 -0300717 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300718 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300719 /* Wakes thread */
720 wake_up_interruptible(&dma_q->wq);
721
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300722 dprintk(dev, 1, "returning from %s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300723 return 0;
724}
725
Adrian Bunk972c3512006-04-27 21:06:50 -0300726static void vivi_stop_thread(struct vivi_dmaqueue *dma_q)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300727{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300728 struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
729
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300730 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300731 /* shutdown control thread */
732 if (dma_q->kthread) {
733 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300734 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300735 }
736}
737
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300738/* ------------------------------------------------------------------
739 Videobuf operations
740 ------------------------------------------------------------------*/
741static int
742buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
743{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300744 struct vivi_fh *fh = vq->priv_data;
745 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300746
747 *size = fh->width*fh->height*2;
748
749 if (0 == *count)
750 *count = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300751
Andreas Bombedab7e312010-03-21 16:02:45 -0300752 if (*size * *count > vid_limit * 1024 * 1024)
753 *count = (vid_limit * 1024 * 1024) / *size;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300754
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300755 dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300756 *count, *size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300757
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300758 return 0;
759}
760
Adrian Bunk972c3512006-04-27 21:06:50 -0300761static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300762{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300763 struct vivi_fh *fh = vq->priv_data;
764 struct vivi_dev *dev = fh->dev;
765
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300766 dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300767
768 if (in_interrupt())
769 BUG();
770
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300771 videobuf_vmalloc_free(&buf->vb);
Mauro Carvalho Chehabfbde31d2008-04-13 14:57:44 -0300772 dprintk(dev, 1, "free_buffer: freed\n");
Brandon Philips0fc06862007-11-06 20:02:36 -0300773 buf->vb.state = VIDEOBUF_NEEDS_INIT;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300774}
775
776#define norm_maxw() 1024
777#define norm_maxh() 768
778static int
779buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
780 enum v4l2_field field)
781{
782 struct vivi_fh *fh = vq->priv_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300783 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300784 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300785 int rc;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300786
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300787 dprintk(dev, 1, "%s, field=%d\n", __func__, field);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300788
789 BUG_ON(NULL == fh->fmt);
Brandon Philips78718e52008-04-02 18:10:59 -0300790
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300791 if (fh->width < 48 || fh->width > norm_maxw() ||
792 fh->height < 32 || fh->height > norm_maxh())
793 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300794
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300795 buf->vb.size = fh->width*fh->height*2;
796 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
797 return -EINVAL;
798
Brandon Philips78718e52008-04-02 18:10:59 -0300799 /* These properties only change when queue is idle, see s_fmt */
800 buf->fmt = fh->fmt;
801 buf->vb.width = fh->width;
802 buf->vb.height = fh->height;
803 buf->vb.field = field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300804
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300805 precalculate_bars(fh);
806
Brandon Philips0fc06862007-11-06 20:02:36 -0300807 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300808 rc = videobuf_iolock(vq, &buf->vb, NULL);
809 if (rc < 0)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300810 goto fail;
811 }
812
Brandon Philips0fc06862007-11-06 20:02:36 -0300813 buf->vb.state = VIDEOBUF_PREPARED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300814
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300815 return 0;
816
817fail:
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300818 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300819 return rc;
820}
821
822static void
823buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
824{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300825 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
826 struct vivi_fh *fh = vq->priv_data;
827 struct vivi_dev *dev = fh->dev;
Brandon Philips78718e52008-04-02 18:10:59 -0300828 struct vivi_dmaqueue *vidq = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300829
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300830 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300831
Brandon Philips78718e52008-04-02 18:10:59 -0300832 buf->vb.state = VIDEOBUF_QUEUED;
833 list_add_tail(&buf->vb.queue, &vidq->active);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300834}
835
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300836static void buffer_release(struct videobuf_queue *vq,
837 struct videobuf_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300838{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300839 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300840 struct vivi_fh *fh = vq->priv_data;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300841 struct vivi_dev *dev = (struct vivi_dev *)fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300842
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300843 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300844
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300845 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300846}
847
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300848static struct videobuf_queue_ops vivi_video_qops = {
849 .buf_setup = buffer_setup,
850 .buf_prepare = buffer_prepare,
851 .buf_queue = buffer_queue,
852 .buf_release = buffer_release,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300853};
854
855/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300856 IOCTL vidioc handling
857 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300858static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300859 struct v4l2_capability *cap)
860{
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300861 struct vivi_fh *fh = priv;
862 struct vivi_dev *dev = fh->dev;
863
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300864 strcpy(cap->driver, "vivi");
865 strcpy(cap->card, "vivi");
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300866 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300867 cap->version = VIVI_VERSION;
868 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
869 V4L2_CAP_STREAMING |
870 V4L2_CAP_READWRITE;
871 return 0;
872}
873
Hans Verkuil78b526a2008-05-28 12:16:41 -0300874static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300875 struct v4l2_fmtdesc *f)
876{
Magnus Dammd891f472008-10-14 12:47:09 -0300877 struct vivi_fmt *fmt;
878
879 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300880 return -EINVAL;
881
Magnus Dammd891f472008-10-14 12:47:09 -0300882 fmt = &formats[f->index];
883
884 strlcpy(f->description, fmt->name, sizeof(f->description));
885 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300886 return 0;
887}
888
Hans Verkuil78b526a2008-05-28 12:16:41 -0300889static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300890 struct v4l2_format *f)
891{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300892 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300893
894 f->fmt.pix.width = fh->width;
895 f->fmt.pix.height = fh->height;
896 f->fmt.pix.field = fh->vb_vidq.field;
897 f->fmt.pix.pixelformat = fh->fmt->fourcc;
898 f->fmt.pix.bytesperline =
899 (f->fmt.pix.width * fh->fmt->depth) >> 3;
900 f->fmt.pix.sizeimage =
901 f->fmt.pix.height * f->fmt.pix.bytesperline;
902
903 return (0);
904}
905
Hans Verkuil78b526a2008-05-28 12:16:41 -0300906static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300907 struct v4l2_format *f)
908{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300909 struct vivi_fh *fh = priv;
910 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300911 struct vivi_fmt *fmt;
912 enum v4l2_field field;
913 unsigned int maxw, maxh;
914
Magnus Dammd891f472008-10-14 12:47:09 -0300915 fmt = get_format(f);
916 if (!fmt) {
917 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
918 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300919 return -EINVAL;
920 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300921
922 field = f->fmt.pix.field;
923
924 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300925 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300926 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300927 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300928 return -EINVAL;
929 }
930
931 maxw = norm_maxw();
932 maxh = norm_maxh();
933
934 f->fmt.pix.field = field;
Trent Piepho3adbbb82009-05-30 21:45:46 -0300935 v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
936 &f->fmt.pix.height, 32, maxh, 0, 0);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300937 f->fmt.pix.bytesperline =
938 (f->fmt.pix.width * fmt->depth) >> 3;
939 f->fmt.pix.sizeimage =
940 f->fmt.pix.height * f->fmt.pix.bytesperline;
941
942 return 0;
943}
944
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300945/*FIXME: This seems to be generic enough to be at videodev2 */
946static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
947 struct v4l2_format *f)
948{
949 struct vivi_fh *fh = priv;
950 struct videobuf_queue *q = &fh->vb_vidq;
951
952 int ret = vidioc_try_fmt_vid_cap(file, fh, f);
953 if (ret < 0)
954 return ret;
955
956 mutex_lock(&q->vb_lock);
957
958 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
959 dprintk(fh->dev, 1, "%s queue busy\n", __func__);
960 ret = -EBUSY;
961 goto out;
962 }
963
964 fh->fmt = get_format(f);
965 fh->width = f->fmt.pix.width;
966 fh->height = f->fmt.pix.height;
967 fh->vb_vidq.field = f->fmt.pix.field;
968 fh->type = f->type;
969
Brandon Philips78718e52008-04-02 18:10:59 -0300970 ret = 0;
971out:
972 mutex_unlock(&q->vb_lock);
973
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300974 return ret;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300975}
976
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300977static int vidioc_reqbufs(struct file *file, void *priv,
978 struct v4l2_requestbuffers *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_reqbufs(&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_querybuf(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 Chehabc820cc42006-06-04 10:34:12 -0300988
989 return (videobuf_querybuf(&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_qbuf(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 Chehab1e6dd652006-03-10 12:40:10 -0300995
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300996 return (videobuf_qbuf(&fh->vb_vidq, p));
997}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300998
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300999static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -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_dqbuf(&fh->vb_vidq, p,
1004 file->f_flags & O_NONBLOCK));
1005}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001006
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -03001007#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001008static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001009{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001010 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001011
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001012 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001013}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001014#endif
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001015
Adrian Bunkdc46ace2006-06-23 06:42:44 -03001016static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001017{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001018 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001019
1020 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1021 return -EINVAL;
1022 if (i != fh->type)
1023 return -EINVAL;
1024
Brandon Philipsba32bd92007-09-27 20:55:17 -03001025 return videobuf_streamon(&fh->vb_vidq);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001026}
1027
Adrian Bunkdc46ace2006-06-23 06:42:44 -03001028static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001029{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001030 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001031
1032 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1033 return -EINVAL;
1034 if (i != fh->type)
1035 return -EINVAL;
1036
Brandon Philipsba32bd92007-09-27 20:55:17 -03001037 return videobuf_streamoff(&fh->vb_vidq);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001038}
1039
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001040static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001041{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001042 return 0;
1043}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001044
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001045/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001046static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001047 struct v4l2_input *inp)
1048{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001049 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001050 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001051
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001052 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001053 inp->std = V4L2_STD_525_60;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001054 sprintf(inp->name, "Camera %u", inp->index);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001055
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001056 return (0);
1057}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001058
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001059static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001060{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001061 struct vivi_fh *fh = priv;
1062 struct vivi_dev *dev = fh->dev;
1063
1064 *i = dev->input;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001065
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001066 return (0);
1067}
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001068static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001069{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001070 struct vivi_fh *fh = priv;
1071 struct vivi_dev *dev = fh->dev;
1072
1073 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001074 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001075
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001076 dev->input = i;
1077 precalculate_bars(fh);
1078
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001079 return (0);
1080}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001081
1082 /* --- controls ---------------------------------------------- */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001083static int vidioc_queryctrl(struct file *file, void *priv,
1084 struct v4l2_queryctrl *qc)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001085{
1086 int i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001087
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001088 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1089 if (qc->id && qc->id == vivi_qctrl[i].id) {
1090 memcpy(qc, &(vivi_qctrl[i]),
1091 sizeof(*qc));
1092 return (0);
1093 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001094
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001095 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001096}
1097
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001098static int vidioc_g_ctrl(struct file *file, void *priv,
1099 struct v4l2_control *ctrl)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001100{
Hans Verkuilc41ee242009-02-14 13:43:44 -03001101 struct vivi_fh *fh = priv;
1102 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001103 int i;
1104
1105 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1106 if (ctrl->id == vivi_qctrl[i].id) {
Hans Verkuilc41ee242009-02-14 13:43:44 -03001107 ctrl->value = dev->qctl_regs[i];
1108 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001109 }
1110
1111 return -EINVAL;
1112}
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001113static int vidioc_s_ctrl(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001114 struct v4l2_control *ctrl)
1115{
Hans Verkuilc41ee242009-02-14 13:43:44 -03001116 struct vivi_fh *fh = priv;
1117 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001118 int i;
1119
1120 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1121 if (ctrl->id == vivi_qctrl[i].id) {
Hans Verkuilc41ee242009-02-14 13:43:44 -03001122 if (ctrl->value < vivi_qctrl[i].minimum ||
1123 ctrl->value > vivi_qctrl[i].maximum) {
1124 return -ERANGE;
1125 }
1126 dev->qctl_regs[i] = ctrl->value;
1127 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001128 }
1129 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001130}
1131
1132/* ------------------------------------------------------------------
1133 File operations for the device
1134 ------------------------------------------------------------------*/
1135
Hans Verkuilbec43662008-12-30 06:58:20 -03001136static int vivi_open(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001137{
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001138 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab63b79cf2008-04-26 08:25:18 -03001139 struct vivi_fh *fh = NULL;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001140 int retval = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001141
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001142 mutex_lock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001143 dev->users++;
1144
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001145 if (dev->users > 1) {
1146 dev->users--;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001147 mutex_unlock(&dev->mutex);
1148 return -EBUSY;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001149 }
1150
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001151 dprintk(dev, 1, "open %s type=%s users=%d\n",
1152 video_device_node_name(dev->vfd),
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;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001160 }
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001161 mutex_unlock(&dev->mutex);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001162
1163 if (retval)
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001164 return retval;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001165
1166 file->private_data = fh;
1167 fh->dev = dev;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001168
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001169 fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Magnus Dammd891f472008-10-14 12:47:09 -03001170 fh->fmt = &formats[0];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001171 fh->width = 640;
1172 fh->height = 480;
1173
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001174 /* Resets frame counters */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001175 dev->h = 0;
1176 dev->m = 0;
1177 dev->s = 0;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -03001178 dev->ms = 0;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001179 dev->mv_count = 0;
1180 dev->jiffies = jiffies;
1181 sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -03001182 dev->h, dev->m, dev->s, dev->ms);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001183
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001184 videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops,
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -03001185 NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001186 sizeof(struct vivi_buffer), fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001187
Brandon Philips78718e52008-04-02 18:10:59 -03001188 vivi_start_thread(fh);
1189
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001190 return 0;
1191}
1192
1193static ssize_t
1194vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1195{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001196 struct vivi_fh *fh = file->private_data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001197
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001198 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Mauro Carvalho Chehabacb09af2007-07-29 22:56:11 -03001199 return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001200 file->f_flags & O_NONBLOCK);
1201 }
1202 return 0;
1203}
1204
1205static unsigned int
1206vivi_poll(struct file *file, struct poll_table_struct *wait)
1207{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001208 struct vivi_fh *fh = file->private_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001209 struct vivi_dev *dev = fh->dev;
Brandon Philips85c7c70bc2007-09-27 20:55:02 -03001210 struct videobuf_queue *q = &fh->vb_vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001211
Harvey Harrison7e28adb2008-04-08 23:20:00 -03001212 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001213
1214 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
1215 return POLLERR;
1216
Brandon Philips85c7c70bc2007-09-27 20:55:02 -03001217 return videobuf_poll_stream(file, q, wait);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001218}
1219
Hans Verkuilbec43662008-12-30 06:58:20 -03001220static int vivi_close(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001221{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001222 struct vivi_fh *fh = file->private_data;
1223 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001224 struct vivi_dmaqueue *vidq = &dev->vidq;
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001225 struct video_device *vdev = video_devdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001226
1227 vivi_stop_thread(vidq);
Brandon Philips053fcb62007-11-13 20:11:26 -03001228 videobuf_stop(&fh->vb_vidq);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001229 videobuf_mmap_free(&fh->vb_vidq);
1230
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001231 kfree(fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001232
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001233 mutex_lock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001234 dev->users--;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001235 mutex_unlock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001236
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001237 dprintk(dev, 1, "close called (dev=%s, users=%d)\n",
1238 video_device_node_name(vdev), dev->users);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001239
1240 return 0;
1241}
1242
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001243static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001244{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001245 struct vivi_fh *fh = file->private_data;
1246 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001247 int ret;
1248
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001249 dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001250
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001251 ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001252
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001253 dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n",
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001254 (unsigned long)vma->vm_start,
1255 (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
1256 ret);
1257
1258 return ret;
1259}
1260
Hans Verkuilbec43662008-12-30 06:58:20 -03001261static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001262 .owner = THIS_MODULE,
1263 .open = vivi_open,
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001264 .release = vivi_close,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001265 .read = vivi_read,
1266 .poll = vivi_poll,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001267 .ioctl = video_ioctl2, /* V4L2 ioctl handler */
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001268 .mmap = vivi_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001269};
1270
Hans Verkuila3998102008-07-21 02:57:38 -03001271static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001272 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001273 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1274 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1275 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1276 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001277 .vidioc_reqbufs = vidioc_reqbufs,
1278 .vidioc_querybuf = vidioc_querybuf,
1279 .vidioc_qbuf = vidioc_qbuf,
1280 .vidioc_dqbuf = vidioc_dqbuf,
1281 .vidioc_s_std = vidioc_s_std,
1282 .vidioc_enum_input = vidioc_enum_input,
1283 .vidioc_g_input = vidioc_g_input,
1284 .vidioc_s_input = vidioc_s_input,
1285 .vidioc_queryctrl = vidioc_queryctrl,
1286 .vidioc_g_ctrl = vidioc_g_ctrl,
1287 .vidioc_s_ctrl = vidioc_s_ctrl,
1288 .vidioc_streamon = vidioc_streamon,
1289 .vidioc_streamoff = vidioc_streamoff,
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -03001290#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001291 .vidiocgmbuf = vidiocgmbuf,
1292#endif
Hans Verkuila3998102008-07-21 02:57:38 -03001293};
1294
1295static struct video_device vivi_template = {
1296 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001297 .fops = &vivi_fops,
1298 .ioctl_ops = &vivi_ioctl_ops,
Hans Verkuila3998102008-07-21 02:57:38 -03001299 .release = video_device_release,
1300
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001301 .tvnorms = V4L2_STD_525_60,
Mauro Carvalho Chehabe75f9ce2006-11-20 13:19:20 -03001302 .current_norm = V4L2_STD_NTSC_M,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001303};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001304
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001305/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001306 Initialization and module stuff
1307 ------------------------------------------------------------------*/
1308
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001309static int vivi_release(void)
1310{
1311 struct vivi_dev *dev;
1312 struct list_head *list;
1313
1314 while (!list_empty(&vivi_devlist)) {
1315 list = vivi_devlist.next;
1316 list_del(list);
1317 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1318
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001319 v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
1320 video_device_node_name(dev->vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001321 video_unregister_device(dev->vfd);
1322 v4l2_device_unregister(&dev->v4l2_dev);
1323 kfree(dev);
1324 }
1325
1326 return 0;
1327}
1328
Hans Verkuilc41ee242009-02-14 13:43:44 -03001329static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001330{
1331 struct vivi_dev *dev;
1332 struct video_device *vfd;
Hans Verkuilc41ee242009-02-14 13:43:44 -03001333 int ret, i;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001334
1335 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1336 if (!dev)
1337 return -ENOMEM;
1338
1339 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001340 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001341 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1342 if (ret)
1343 goto free_dev;
1344
1345 /* init video dma queues */
1346 INIT_LIST_HEAD(&dev->vidq.active);
1347 init_waitqueue_head(&dev->vidq.wq);
1348
1349 /* initialize locks */
1350 spin_lock_init(&dev->slock);
1351 mutex_init(&dev->mutex);
1352
1353 ret = -ENOMEM;
1354 vfd = video_device_alloc();
1355 if (!vfd)
1356 goto unreg_dev;
1357
1358 *vfd = vivi_template;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -03001359 vfd->debug = debug;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001360
1361 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1362 if (ret < 0)
1363 goto rel_vdev;
1364
1365 video_set_drvdata(vfd, dev);
1366
Hans Verkuilc41ee242009-02-14 13:43:44 -03001367 /* Set all controls to their default value. */
1368 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1369 dev->qctl_regs[i] = vivi_qctrl[i].default_value;
1370
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001371 /* Now that everything is fine, let's add it to device list */
1372 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1373
Roel Kluin7de0b872009-12-16 13:06:33 -03001374 if (video_nr != -1)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001375 video_nr++;
1376
1377 dev->vfd = vfd;
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001378 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
1379 video_device_node_name(vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001380 return 0;
1381
1382rel_vdev:
1383 video_device_release(vfd);
1384unreg_dev:
1385 v4l2_device_unregister(&dev->v4l2_dev);
1386free_dev:
1387 kfree(dev);
1388 return ret;
1389}
1390
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001391/* This routine allocates from 1 to n_devs virtual drivers.
1392
1393 The real maximum number of virtual drivers will depend on how many drivers
1394 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001395 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001396 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001397static int __init vivi_init(void)
1398{
Hans Verkuil9185cbf2009-03-06 09:58:12 -03001399 int ret = 0, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001400
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001401 if (n_devs <= 0)
1402 n_devs = 1;
1403
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001404 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001405 ret = vivi_create_instance(i);
1406 if (ret) {
1407 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001408 if (i)
1409 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001410 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001411 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001412 }
1413
1414 if (ret < 0) {
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001415 printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001416 return ret;
1417 }
1418
1419 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Carl Karsten745271a2008-06-10 00:02:32 -03001420 "Capture Board ver %u.%u.%u successfully loaded.\n",
1421 (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
1422 VIVI_VERSION & 0xFF);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001423
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001424 /* n_devs will reflect the actual number of allocated devices */
1425 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001426
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001427 return ret;
1428}
1429
1430static void __exit vivi_exit(void)
1431{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001432 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001433}
1434
1435module_init(vivi_init);
1436module_exit(vivi_exit);