blob: 616eb1a8dbee3a5bdf69c3e48fb955d185957d96 [file] [log] [blame]
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001/*
2 * Virtual Video driver - This code emulates a real video device with v4l2 api
3 *
4 * Copyright (c) 2006 by:
5 * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
6 * Ted Walther <ted--a.t--enumera.com>
7 * John Sokol <sokol--a.t--videotechnology.com>
8 * http://v4l.videotechnology.com/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the BSD Licence, GNU General Public License
12 * as published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version
14 */
15#include <linux/module.h>
16#include <linux/delay.h>
17#include <linux/errno.h>
18#include <linux/fs.h>
19#include <linux/kernel.h>
20#include <linux/slab.h>
21#include <linux/mm.h>
22#include <linux/ioport.h>
23#include <linux/init.h>
24#include <linux/sched.h>
25#include <linux/pci.h>
26#include <linux/random.h>
27#include <linux/version.h>
Matthias Kaehlcke51b54022007-07-02 10:19:38 -030028#include <linux/mutex.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030029#include <linux/videodev2.h>
Andrew Morton10951362006-04-27 10:10:58 -030030#include <linux/dma-mapping.h>
Mauro Carvalho Chehabcd41e282006-04-09 15:43:41 -030031#ifdef CONFIG_VIDEO_V4L1_COMPAT
32/* Include V4L1 specific functions. Should be removed soon */
33#include <linux/videodev.h>
34#endif
Michael Krufkyf13df912006-03-23 22:01:44 -030035#include <linux/interrupt.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030036#include <linux/kthread.h>
37#include <linux/highmem.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080038#include <linux/freezer.h>
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030039#include <media/videobuf-vmalloc.h>
40#include <media/v4l2-device.h>
41#include <media/v4l2-ioctl.h>
42#include "font.h"
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030043
Mauro Carvalho Chehab584ce482008-06-10 15:21:49 -030044#define VIVI_MODULE_NAME "vivi"
Carl Karsten745271a2008-06-10 00:02:32 -030045
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030046/* Wake up at about 30 fps */
47#define WAKE_NUMERATOR 30
48#define WAKE_DENOMINATOR 1001
49#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
50
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030051#define VIVI_MAJOR_VERSION 0
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030052#define VIVI_MINOR_VERSION 6
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030053#define VIVI_RELEASE 0
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -030054#define VIVI_VERSION \
55 KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030056
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030057MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
58MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
59MODULE_LICENSE("Dual BSD/GPL");
60
61static unsigned video_nr = -1;
62module_param(video_nr, uint, 0644);
63MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
64
65static unsigned n_devs = 1;
66module_param(n_devs, uint, 0644);
67MODULE_PARM_DESC(n_devs, "number of video devices to create");
68
69static unsigned debug;
70module_param(debug, uint, 0644);
71MODULE_PARM_DESC(debug, "activates debug info");
72
73static unsigned int vid_limit = 16;
74module_param(vid_limit, uint, 0644);
75MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
76
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030077
78/* supported controls */
79static struct v4l2_queryctrl vivi_qctrl[] = {
80 {
81 .id = V4L2_CID_AUDIO_VOLUME,
82 .name = "Volume",
83 .minimum = 0,
84 .maximum = 65535,
85 .step = 65535/100,
86 .default_value = 65535,
Hans Verkuil4a5aa622009-02-14 13:50:19 -030087 .flags = V4L2_CTRL_FLAG_SLIDER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030088 .type = V4L2_CTRL_TYPE_INTEGER,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -030089 }, {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030090 .id = V4L2_CID_BRIGHTNESS,
91 .type = V4L2_CTRL_TYPE_INTEGER,
92 .name = "Brightness",
93 .minimum = 0,
94 .maximum = 255,
95 .step = 1,
96 .default_value = 127,
Hans Verkuil4a5aa622009-02-14 13:50:19 -030097 .flags = V4L2_CTRL_FLAG_SLIDER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030098 }, {
99 .id = V4L2_CID_CONTRAST,
100 .type = V4L2_CTRL_TYPE_INTEGER,
101 .name = "Contrast",
102 .minimum = 0,
103 .maximum = 255,
104 .step = 0x1,
105 .default_value = 0x10,
Hans Verkuil4a5aa622009-02-14 13:50:19 -0300106 .flags = V4L2_CTRL_FLAG_SLIDER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300107 }, {
108 .id = V4L2_CID_SATURATION,
109 .type = V4L2_CTRL_TYPE_INTEGER,
110 .name = "Saturation",
111 .minimum = 0,
112 .maximum = 255,
113 .step = 0x1,
114 .default_value = 127,
Hans Verkuil4a5aa622009-02-14 13:50:19 -0300115 .flags = V4L2_CTRL_FLAG_SLIDER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300116 }, {
117 .id = V4L2_CID_HUE,
118 .type = V4L2_CTRL_TYPE_INTEGER,
119 .name = "Hue",
120 .minimum = -128,
121 .maximum = 127,
122 .step = 0x1,
123 .default_value = 0,
Hans Verkuil4a5aa622009-02-14 13:50:19 -0300124 .flags = V4L2_CTRL_FLAG_SLIDER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300125 }
126};
127
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300128#define dprintk(dev, level, fmt, arg...) \
129 v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300130
131/* ------------------------------------------------------------------
132 Basic structures
133 ------------------------------------------------------------------*/
134
135struct vivi_fmt {
136 char *name;
137 u32 fourcc; /* v4l2 format id */
138 int depth;
139};
140
Magnus Dammd891f472008-10-14 12:47:09 -0300141static struct vivi_fmt formats[] = {
142 {
143 .name = "4:2:2, packed, YUYV",
144 .fourcc = V4L2_PIX_FMT_YUYV,
145 .depth = 16,
146 },
Magnus Dammfca36ba2008-10-14 12:47:25 -0300147 {
148 .name = "4:2:2, packed, UYVY",
149 .fourcc = V4L2_PIX_FMT_UYVY,
150 .depth = 16,
151 },
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300152 {
153 .name = "RGB565 (LE)",
154 .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
155 .depth = 16,
156 },
157 {
158 .name = "RGB565 (BE)",
159 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
160 .depth = 16,
161 },
Magnus Dammdef52392008-10-14 12:47:43 -0300162 {
163 .name = "RGB555 (LE)",
164 .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
165 .depth = 16,
166 },
167 {
168 .name = "RGB555 (BE)",
169 .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
170 .depth = 16,
171 },
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300172};
173
Magnus Dammd891f472008-10-14 12:47:09 -0300174static struct vivi_fmt *get_format(struct v4l2_format *f)
175{
176 struct vivi_fmt *fmt;
177 unsigned int k;
178
179 for (k = 0; k < ARRAY_SIZE(formats); k++) {
180 fmt = &formats[k];
181 if (fmt->fourcc == f->fmt.pix.pixelformat)
182 break;
183 }
184
185 if (k == ARRAY_SIZE(formats))
186 return NULL;
187
188 return &formats[k];
189}
190
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300191struct sg_to_addr {
192 int pos;
193 struct scatterlist *sg;
194};
195
196/* buffer for one video frame */
197struct vivi_buffer {
198 /* common v4l buffer stuff -- must be first */
199 struct videobuf_buffer vb;
200
201 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300202};
203
204struct vivi_dmaqueue {
205 struct list_head active;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300206
207 /* thread for generating video stream*/
208 struct task_struct *kthread;
209 wait_queue_head_t wq;
210 /* Counters to control fps rate */
211 int frame;
212 int ini_jiffies;
213};
214
215static LIST_HEAD(vivi_devlist);
216
217struct vivi_dev {
218 struct list_head vivi_devlist;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300219 struct v4l2_device v4l2_dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300220
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300221 spinlock_t slock;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300222 struct mutex mutex;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300223
224 int users;
225
226 /* various device info */
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -0300227 struct video_device *vfd;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300228
229 struct vivi_dmaqueue vidq;
230
231 /* Several counters */
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300232 int h, m, s, ms;
233 unsigned long jiffies;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300234 char timestr[13];
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300235
236 int mv_count; /* Controls bars movement */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300237
238 /* Input Number */
239 int input;
Hans Verkuilc41ee242009-02-14 13:43:44 -0300240
241 /* Control 'registers' */
242 int qctl_regs[ARRAY_SIZE(vivi_qctrl)];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300243};
244
245struct vivi_fh {
246 struct vivi_dev *dev;
247
248 /* video capture */
249 struct vivi_fmt *fmt;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300250 unsigned int width, height;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300251 struct videobuf_queue vb_vidq;
252
253 enum v4l2_buf_type type;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300254 unsigned char bars[8][3];
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300255 int input; /* Input Number on bars */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300256};
257
258/* ------------------------------------------------------------------
259 DMA and thread functions
260 ------------------------------------------------------------------*/
261
262/* Bars and Colors should match positions */
263
264enum colors {
265 WHITE,
266 AMBAR,
267 CYAN,
268 GREEN,
269 MAGENTA,
270 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300271 BLUE,
272 BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300273};
274
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300275 /* R G B */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300276#define COLOR_WHITE {204, 204, 204}
277#define COLOR_AMBAR {208, 208, 0}
278#define COLOR_CIAN { 0, 206, 206}
279#define COLOR_GREEN { 0, 239, 0}
280#define COLOR_MAGENTA {239, 0, 239}
281#define COLOR_RED {205, 0, 0}
282#define COLOR_BLUE { 0, 0, 255}
283#define COLOR_BLACK { 0, 0, 0}
284
285struct bar_std {
286 u8 bar[8][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300287};
288
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300289/* Maximum number of bars are 10 - otherwise, the input print code
290 should be modified */
291static struct bar_std bars[] = {
292 { /* Standard ITU-R color bar sequence */
293 {
294 COLOR_WHITE,
295 COLOR_AMBAR,
296 COLOR_CIAN,
297 COLOR_GREEN,
298 COLOR_MAGENTA,
299 COLOR_RED,
300 COLOR_BLUE,
301 COLOR_BLACK,
302 }
303 }, {
304 {
305 COLOR_WHITE,
306 COLOR_AMBAR,
307 COLOR_BLACK,
308 COLOR_WHITE,
309 COLOR_AMBAR,
310 COLOR_BLACK,
311 COLOR_WHITE,
312 COLOR_AMBAR,
313 }
314 }, {
315 {
316 COLOR_WHITE,
317 COLOR_CIAN,
318 COLOR_BLACK,
319 COLOR_WHITE,
320 COLOR_CIAN,
321 COLOR_BLACK,
322 COLOR_WHITE,
323 COLOR_CIAN,
324 }
325 }, {
326 {
327 COLOR_WHITE,
328 COLOR_GREEN,
329 COLOR_BLACK,
330 COLOR_WHITE,
331 COLOR_GREEN,
332 COLOR_BLACK,
333 COLOR_WHITE,
334 COLOR_GREEN,
335 }
336 },
337};
338
339#define NUM_INPUTS ARRAY_SIZE(bars)
340
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300341#define TO_Y(r, g, b) \
342 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300343/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300344#define TO_V(r, g, b) \
345 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300346/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300347#define TO_U(r, g, b) \
348 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300349
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300350#define TSTAMP_MIN_Y 24
351#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
352#define TSTAMP_INPUT_X 10
353#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300354
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300355static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
356{
357 unsigned char r_y, g_u, b_v;
358 unsigned char *p;
359 int color;
360
361 r_y = fh->bars[colorpos][0]; /* R or precalculated Y */
362 g_u = fh->bars[colorpos][1]; /* G or precalculated U */
363 b_v = fh->bars[colorpos][2]; /* B or precalculated V */
364
365 for (color = 0; color < 4; color++) {
366 p = buf + color;
367
Magnus Dammd891f472008-10-14 12:47:09 -0300368 switch (fh->fmt->fourcc) {
369 case V4L2_PIX_FMT_YUYV:
370 switch (color) {
371 case 0:
372 case 2:
373 *p = r_y;
374 break;
375 case 1:
376 *p = g_u;
377 break;
378 case 3:
379 *p = b_v;
380 break;
381 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300382 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300383 case V4L2_PIX_FMT_UYVY:
384 switch (color) {
385 case 1:
386 case 3:
387 *p = r_y;
388 break;
389 case 0:
390 *p = g_u;
391 break;
392 case 2:
393 *p = b_v;
394 break;
395 }
396 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300397 case V4L2_PIX_FMT_RGB565:
398 switch (color) {
399 case 0:
400 case 2:
401 *p = (g_u << 5) | b_v;
402 break;
403 case 1:
404 case 3:
405 *p = (r_y << 3) | (g_u >> 3);
406 break;
407 }
408 break;
409 case V4L2_PIX_FMT_RGB565X:
410 switch (color) {
411 case 0:
412 case 2:
413 *p = (r_y << 3) | (g_u >> 3);
414 break;
415 case 1:
416 case 3:
417 *p = (g_u << 5) | b_v;
418 break;
419 }
420 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300421 case V4L2_PIX_FMT_RGB555:
422 switch (color) {
423 case 0:
424 case 2:
425 *p = (g_u << 5) | b_v;
426 break;
427 case 1:
428 case 3:
429 *p = (r_y << 2) | (g_u >> 3);
430 break;
431 }
432 break;
433 case V4L2_PIX_FMT_RGB555X:
434 switch (color) {
435 case 0:
436 case 2:
437 *p = (r_y << 2) | (g_u >> 3);
438 break;
439 case 1:
440 case 3:
441 *p = (g_u << 5) | b_v;
442 break;
443 }
444 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300445 }
446 }
447}
448
449static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300450 int hmax, int line, int count, char *timestr)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300451{
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300452 int w, i, j;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300453 int pos = inipos;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300454 char *s;
455 u8 chr;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300456
457 /* We will just duplicate the second pixel at the packet */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300458 wmax /= 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300459
460 /* Generate a standard color bar pattern */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300461 for (w = 0; w < wmax; w++) {
462 int colorpos = ((w + count) * 8/(wmax + 1)) % 8;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300463
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300464 gen_twopix(fh, basep + pos, colorpos);
465 pos += 4; /* only 16 bpp supported for now */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300466 }
467
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300468 /* Prints input entry number */
469
470 /* Checks if it is possible to input number */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300471 if (TSTAMP_MAX_Y >= hmax)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300472 goto end;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300473
474 if (TSTAMP_INPUT_X + strlen(timestr) >= wmax)
475 goto end;
476
477 if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
478 chr = rom8x16_bits[fh->input * 16 + line - TSTAMP_MIN_Y];
479 pos = TSTAMP_INPUT_X;
480 for (i = 0; i < 7; i++) {
481 /* Draw white font on black background */
482 if (chr & 1 << (7 - i))
483 gen_twopix(fh, basep + pos, WHITE);
484 else
485 gen_twopix(fh, basep + pos, BLACK);
486 pos += 2;
487 }
488 }
489
490 /* Checks if it is possible to show timestamp */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300491 if (TSTAMP_MIN_X + strlen(timestr) >= wmax)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300492 goto end;
493
494 /* Print stream time */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300495 if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
496 j = TSTAMP_MIN_X;
497 for (s = timestr; *s; s++) {
498 chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y];
499 for (i = 0; i < 7; i++) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300500 pos = inipos + j * 2;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300501 /* Draw white font on black background */
502 if (chr & 1 << (7 - i))
503 gen_twopix(fh, basep + pos, WHITE);
504 else
505 gen_twopix(fh, basep + pos, BLACK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300506 j++;
507 }
508 }
509 }
510
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300511end:
Mauro Carvalho Chehabb50e7fe2007-01-25 05:00:01 -0300512 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300513}
Brandon Philips78718e52008-04-02 18:10:59 -0300514
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300515static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300516{
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300517 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300518 int h , pos = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300519 int hmax = buf->vb.height;
520 int wmax = buf->vb.width;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300521 struct timeval ts;
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300522 char *tmpbuf;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300523 void *vbuf = videobuf_to_vmalloc(&buf->vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300524
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300525 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300526 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300527
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300528 tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);
529 if (!tmpbuf)
Brandon Philips78718e52008-04-02 18:10:59 -0300530 return;
531
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300532 for (h = 0; h < hmax; h++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300533 gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count,
Mauro Carvalho Chehab3bef5e42007-09-22 02:01:33 -0300534 dev->timestr);
Brandon Philips78718e52008-04-02 18:10:59 -0300535 memcpy(vbuf + pos, tmpbuf, wmax * 2);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300536 pos += wmax*2;
537 }
538
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300539 dev->mv_count++;
Mauro Carvalho Chehab3bef5e42007-09-22 02:01:33 -0300540
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300541 kfree(tmpbuf);
542
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300543 /* Updates stream time */
544
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300545 dev->ms += jiffies_to_msecs(jiffies-dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300546 dev->jiffies = jiffies;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300547 if (dev->ms >= 1000) {
548 dev->ms -= 1000;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300549 dev->s++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300550 if (dev->s >= 60) {
551 dev->s -= 60;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300552 dev->m++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300553 if (dev->m > 60) {
554 dev->m -= 60;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300555 dev->h++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300556 if (dev->h > 24)
557 dev->h -= 24;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300558 }
559 }
560 }
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300561 sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300562 dev->h, dev->m, dev->s, dev->ms);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300563
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300564 dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n",
565 dev->timestr, (unsigned long)tmpbuf, pos);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300566
567 /* Advice that buffer was filled */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300568 buf->vb.field_count++;
569 do_gettimeofday(&ts);
570 buf->vb.ts = ts;
Brandon Philips78718e52008-04-02 18:10:59 -0300571 buf->vb.state = VIDEOBUF_DONE;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300572}
573
Brandon Philips78718e52008-04-02 18:10:59 -0300574static void vivi_thread_tick(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300575{
Brandon Philips78718e52008-04-02 18:10:59 -0300576 struct vivi_buffer *buf;
577 struct vivi_dev *dev = fh->dev;
578 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300579
Brandon Philips78718e52008-04-02 18:10:59 -0300580 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300581
Brandon Philips78718e52008-04-02 18:10:59 -0300582 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300583
Brandon Philips78718e52008-04-02 18:10:59 -0300584 spin_lock_irqsave(&dev->slock, flags);
585 if (list_empty(&dma_q->active)) {
586 dprintk(dev, 1, "No active queue to serve\n");
587 goto unlock;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300588 }
Brandon Philips78718e52008-04-02 18:10:59 -0300589
590 buf = list_entry(dma_q->active.next,
591 struct vivi_buffer, vb.queue);
592
593 /* Nobody is waiting on this buffer, return */
594 if (!waitqueue_active(&buf->vb.done))
595 goto unlock;
596
597 list_del(&buf->vb.queue);
598
599 do_gettimeofday(&buf->vb.ts);
600
601 /* Fill buffer */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300602 vivi_fillbuff(fh, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300603 dprintk(dev, 1, "filled buffer %p\n", buf);
604
605 wake_up(&buf->vb.done);
606 dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
607unlock:
608 spin_unlock_irqrestore(&dev->slock, flags);
609 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300610}
611
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300612#define frames_to_ms(frames) \
613 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
614
Brandon Philips78718e52008-04-02 18:10:59 -0300615static void vivi_sleep(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300616{
Brandon Philips78718e52008-04-02 18:10:59 -0300617 struct vivi_dev *dev = fh->dev;
618 struct vivi_dmaqueue *dma_q = &dev->vidq;
619 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300620 DECLARE_WAITQUEUE(wait, current);
621
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300622 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300623 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300624
625 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300626 if (kthread_should_stop())
627 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300628
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300629 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300630 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300631
Brandon Philips78718e52008-04-02 18:10:59 -0300632 vivi_thread_tick(fh);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300633
634 schedule_timeout_interruptible(timeout);
635
636stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300637 remove_wait_queue(&dma_q->wq, &wait);
638 try_to_freeze();
639}
640
Adrian Bunk972c3512006-04-27 21:06:50 -0300641static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300642{
Brandon Philips78718e52008-04-02 18:10:59 -0300643 struct vivi_fh *fh = data;
644 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300645
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300646 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300647
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700648 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300649
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300650 for (;;) {
Brandon Philips78718e52008-04-02 18:10:59 -0300651 vivi_sleep(fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300652
653 if (kthread_should_stop())
654 break;
655 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300656 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300657 return 0;
658}
659
Brandon Philips78718e52008-04-02 18:10:59 -0300660static int vivi_start_thread(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300661{
Brandon Philips78718e52008-04-02 18:10:59 -0300662 struct vivi_dev *dev = fh->dev;
663 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300664
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300665 dma_q->frame = 0;
666 dma_q->ini_jiffies = jiffies;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300667
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300668 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300669
Brandon Philips78718e52008-04-02 18:10:59 -0300670 dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300671
Akinobu Mita054afee2006-12-20 10:04:00 -0300672 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300673 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Akinobu Mita054afee2006-12-20 10:04:00 -0300674 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300675 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300676 /* Wakes thread */
677 wake_up_interruptible(&dma_q->wq);
678
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300679 dprintk(dev, 1, "returning from %s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300680 return 0;
681}
682
Adrian Bunk972c3512006-04-27 21:06:50 -0300683static void vivi_stop_thread(struct vivi_dmaqueue *dma_q)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300684{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300685 struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
686
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300687 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300688 /* shutdown control thread */
689 if (dma_q->kthread) {
690 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300691 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300692 }
693}
694
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300695/* ------------------------------------------------------------------
696 Videobuf operations
697 ------------------------------------------------------------------*/
698static int
699buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
700{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300701 struct vivi_fh *fh = vq->priv_data;
702 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300703
704 *size = fh->width*fh->height*2;
705
706 if (0 == *count)
707 *count = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300708
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300709 while (*size * *count > vid_limit * 1024 * 1024)
710 (*count)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300711
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300712 dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300713 *count, *size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300714
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300715 return 0;
716}
717
Adrian Bunk972c3512006-04-27 21:06:50 -0300718static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300719{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300720 struct vivi_fh *fh = vq->priv_data;
721 struct vivi_dev *dev = fh->dev;
722
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300723 dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300724
725 if (in_interrupt())
726 BUG();
727
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300728 videobuf_vmalloc_free(&buf->vb);
Mauro Carvalho Chehabfbde31d2008-04-13 14:57:44 -0300729 dprintk(dev, 1, "free_buffer: freed\n");
Brandon Philips0fc06862007-11-06 20:02:36 -0300730 buf->vb.state = VIDEOBUF_NEEDS_INIT;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300731}
732
733#define norm_maxw() 1024
734#define norm_maxh() 768
735static int
736buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
737 enum v4l2_field field)
738{
739 struct vivi_fh *fh = vq->priv_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300740 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300741 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300742 int rc;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300743
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300744 dprintk(dev, 1, "%s, field=%d\n", __func__, field);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300745
746 BUG_ON(NULL == fh->fmt);
Brandon Philips78718e52008-04-02 18:10:59 -0300747
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300748 if (fh->width < 48 || fh->width > norm_maxw() ||
749 fh->height < 32 || fh->height > norm_maxh())
750 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300751
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300752 buf->vb.size = fh->width*fh->height*2;
753 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
754 return -EINVAL;
755
Brandon Philips78718e52008-04-02 18:10:59 -0300756 /* These properties only change when queue is idle, see s_fmt */
757 buf->fmt = fh->fmt;
758 buf->vb.width = fh->width;
759 buf->vb.height = fh->height;
760 buf->vb.field = field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300761
Brandon Philips0fc06862007-11-06 20:02:36 -0300762 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300763 rc = videobuf_iolock(vq, &buf->vb, NULL);
764 if (rc < 0)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300765 goto fail;
766 }
767
Brandon Philips0fc06862007-11-06 20:02:36 -0300768 buf->vb.state = VIDEOBUF_PREPARED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300769
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300770 return 0;
771
772fail:
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300773 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300774 return rc;
775}
776
777static void
778buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
779{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300780 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
781 struct vivi_fh *fh = vq->priv_data;
782 struct vivi_dev *dev = fh->dev;
Brandon Philips78718e52008-04-02 18:10:59 -0300783 struct vivi_dmaqueue *vidq = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300784
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300785 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300786
Brandon Philips78718e52008-04-02 18:10:59 -0300787 buf->vb.state = VIDEOBUF_QUEUED;
788 list_add_tail(&buf->vb.queue, &vidq->active);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300789}
790
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300791static void buffer_release(struct videobuf_queue *vq,
792 struct videobuf_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300793{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300794 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300795 struct vivi_fh *fh = vq->priv_data;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300796 struct vivi_dev *dev = (struct vivi_dev *)fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300797
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300798 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300799
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300800 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300801}
802
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300803static struct videobuf_queue_ops vivi_video_qops = {
804 .buf_setup = buffer_setup,
805 .buf_prepare = buffer_prepare,
806 .buf_queue = buffer_queue,
807 .buf_release = buffer_release,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300808};
809
810/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300811 IOCTL vidioc handling
812 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300813static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300814 struct v4l2_capability *cap)
815{
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300816 struct vivi_fh *fh = priv;
817 struct vivi_dev *dev = fh->dev;
818
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300819 strcpy(cap->driver, "vivi");
820 strcpy(cap->card, "vivi");
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300821 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300822 cap->version = VIVI_VERSION;
823 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
824 V4L2_CAP_STREAMING |
825 V4L2_CAP_READWRITE;
826 return 0;
827}
828
Hans Verkuil78b526a2008-05-28 12:16:41 -0300829static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300830 struct v4l2_fmtdesc *f)
831{
Magnus Dammd891f472008-10-14 12:47:09 -0300832 struct vivi_fmt *fmt;
833
834 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300835 return -EINVAL;
836
Magnus Dammd891f472008-10-14 12:47:09 -0300837 fmt = &formats[f->index];
838
839 strlcpy(f->description, fmt->name, sizeof(f->description));
840 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300841 return 0;
842}
843
Hans Verkuil78b526a2008-05-28 12:16:41 -0300844static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300845 struct v4l2_format *f)
846{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300847 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300848
849 f->fmt.pix.width = fh->width;
850 f->fmt.pix.height = fh->height;
851 f->fmt.pix.field = fh->vb_vidq.field;
852 f->fmt.pix.pixelformat = fh->fmt->fourcc;
853 f->fmt.pix.bytesperline =
854 (f->fmt.pix.width * fh->fmt->depth) >> 3;
855 f->fmt.pix.sizeimage =
856 f->fmt.pix.height * f->fmt.pix.bytesperline;
857
858 return (0);
859}
860
Hans Verkuil78b526a2008-05-28 12:16:41 -0300861static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300862 struct v4l2_format *f)
863{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300864 struct vivi_fh *fh = priv;
865 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300866 struct vivi_fmt *fmt;
867 enum v4l2_field field;
868 unsigned int maxw, maxh;
869
Magnus Dammd891f472008-10-14 12:47:09 -0300870 fmt = get_format(f);
871 if (!fmt) {
872 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
873 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300874 return -EINVAL;
875 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300876
877 field = f->fmt.pix.field;
878
879 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300880 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300881 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300882 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300883 return -EINVAL;
884 }
885
886 maxw = norm_maxw();
887 maxh = norm_maxh();
888
889 f->fmt.pix.field = field;
890 if (f->fmt.pix.height < 32)
891 f->fmt.pix.height = 32;
892 if (f->fmt.pix.height > maxh)
893 f->fmt.pix.height = maxh;
894 if (f->fmt.pix.width < 48)
895 f->fmt.pix.width = 48;
896 if (f->fmt.pix.width > maxw)
897 f->fmt.pix.width = maxw;
898 f->fmt.pix.width &= ~0x03;
899 f->fmt.pix.bytesperline =
900 (f->fmt.pix.width * fmt->depth) >> 3;
901 f->fmt.pix.sizeimage =
902 f->fmt.pix.height * f->fmt.pix.bytesperline;
903
904 return 0;
905}
906
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300907/* precalculate color bar values to speed up rendering */
908static void precalculate_bars(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300909{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300910 struct vivi_dev *dev = fh->dev;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300911 unsigned char r, g, b;
Magnus Dammd891f472008-10-14 12:47:09 -0300912 int k, is_yuv;
Brandon Philips78718e52008-04-02 18:10:59 -0300913
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300914 fh->input = dev->input;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300915
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300916 for (k = 0; k < 8; k++) {
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300917 r = bars[fh->input].bar[k][0];
918 g = bars[fh->input].bar[k][1];
919 b = bars[fh->input].bar[k][2];
Magnus Dammd891f472008-10-14 12:47:09 -0300920 is_yuv = 0;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300921
Magnus Dammd891f472008-10-14 12:47:09 -0300922 switch (fh->fmt->fourcc) {
923 case V4L2_PIX_FMT_YUYV:
Magnus Dammfca36ba2008-10-14 12:47:25 -0300924 case V4L2_PIX_FMT_UYVY:
Magnus Dammd891f472008-10-14 12:47:09 -0300925 is_yuv = 1;
926 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300927 case V4L2_PIX_FMT_RGB565:
928 case V4L2_PIX_FMT_RGB565X:
929 r >>= 3;
930 g >>= 2;
931 b >>= 3;
932 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300933 case V4L2_PIX_FMT_RGB555:
934 case V4L2_PIX_FMT_RGB555X:
935 r >>= 3;
936 g >>= 3;
937 b >>= 3;
938 break;
Magnus Dammd891f472008-10-14 12:47:09 -0300939 }
940
941 if (is_yuv) {
942 fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
943 fh->bars[k][1] = TO_U(r, g, b); /* Cb */
944 fh->bars[k][2] = TO_V(r, g, b); /* Cr */
945 } else {
946 fh->bars[k][0] = r;
947 fh->bars[k][1] = g;
948 fh->bars[k][2] = b;
949 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300950 }
951
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300952}
953
954/*FIXME: This seems to be generic enough to be at videodev2 */
955static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
956 struct v4l2_format *f)
957{
958 struct vivi_fh *fh = priv;
959 struct videobuf_queue *q = &fh->vb_vidq;
960
961 int ret = vidioc_try_fmt_vid_cap(file, fh, f);
962 if (ret < 0)
963 return ret;
964
965 mutex_lock(&q->vb_lock);
966
967 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
968 dprintk(fh->dev, 1, "%s queue busy\n", __func__);
969 ret = -EBUSY;
970 goto out;
971 }
972
973 fh->fmt = get_format(f);
974 fh->width = f->fmt.pix.width;
975 fh->height = f->fmt.pix.height;
976 fh->vb_vidq.field = f->fmt.pix.field;
977 fh->type = f->type;
978
979 precalculate_bars(fh);
980
Brandon Philips78718e52008-04-02 18:10:59 -0300981 ret = 0;
982out:
983 mutex_unlock(&q->vb_lock);
984
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300985 return ret;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300986}
987
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300988static int vidioc_reqbufs(struct file *file, void *priv,
989 struct v4l2_requestbuffers *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300990{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300991 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300992
993 return (videobuf_reqbufs(&fh->vb_vidq, p));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300994}
995
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300996static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300997{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300998 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300999
1000 return (videobuf_querybuf(&fh->vb_vidq, p));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001001}
1002
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001003static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001004{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001005 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001006
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001007 return (videobuf_qbuf(&fh->vb_vidq, p));
1008}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001009
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001010static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001011{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001012 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001013
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001014 return (videobuf_dqbuf(&fh->vb_vidq, p,
1015 file->f_flags & O_NONBLOCK));
1016}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001017
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -03001018#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001019static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001020{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001021 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001022
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001023 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001024}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001025#endif
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001026
Adrian Bunkdc46ace2006-06-23 06:42:44 -03001027static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001028{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001029 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001030
1031 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1032 return -EINVAL;
1033 if (i != fh->type)
1034 return -EINVAL;
1035
Brandon Philipsba32bd92007-09-27 20:55:17 -03001036 return videobuf_streamon(&fh->vb_vidq);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001037}
1038
Adrian Bunkdc46ace2006-06-23 06:42:44 -03001039static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001040{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001041 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001042
1043 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1044 return -EINVAL;
1045 if (i != fh->type)
1046 return -EINVAL;
1047
Brandon Philipsba32bd92007-09-27 20:55:17 -03001048 return videobuf_streamoff(&fh->vb_vidq);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001049}
1050
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001051static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001052{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001053 return 0;
1054}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001055
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001056/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001057static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001058 struct v4l2_input *inp)
1059{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001060 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001061 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001062
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001063 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001064 inp->std = V4L2_STD_525_60;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001065 sprintf(inp->name, "Camera %u", inp->index);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001066
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001067 return (0);
1068}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001069
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001070static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001071{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001072 struct vivi_fh *fh = priv;
1073 struct vivi_dev *dev = fh->dev;
1074
1075 *i = dev->input;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001076
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001077 return (0);
1078}
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001079static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001080{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001081 struct vivi_fh *fh = priv;
1082 struct vivi_dev *dev = fh->dev;
1083
1084 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001085 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001086
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001087 dev->input = i;
1088 precalculate_bars(fh);
1089
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001090 return (0);
1091}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001092
1093 /* --- controls ---------------------------------------------- */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001094static int vidioc_queryctrl(struct file *file, void *priv,
1095 struct v4l2_queryctrl *qc)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001096{
1097 int i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001098
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001099 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1100 if (qc->id && qc->id == vivi_qctrl[i].id) {
1101 memcpy(qc, &(vivi_qctrl[i]),
1102 sizeof(*qc));
1103 return (0);
1104 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001105
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001106 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001107}
1108
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001109static int vidioc_g_ctrl(struct file *file, void *priv,
1110 struct v4l2_control *ctrl)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001111{
Hans Verkuilc41ee242009-02-14 13:43:44 -03001112 struct vivi_fh *fh = priv;
1113 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001114 int i;
1115
1116 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1117 if (ctrl->id == vivi_qctrl[i].id) {
Hans Verkuilc41ee242009-02-14 13:43:44 -03001118 ctrl->value = dev->qctl_regs[i];
1119 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001120 }
1121
1122 return -EINVAL;
1123}
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001124static int vidioc_s_ctrl(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001125 struct v4l2_control *ctrl)
1126{
Hans Verkuilc41ee242009-02-14 13:43:44 -03001127 struct vivi_fh *fh = priv;
1128 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001129 int i;
1130
1131 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1132 if (ctrl->id == vivi_qctrl[i].id) {
Hans Verkuilc41ee242009-02-14 13:43:44 -03001133 if (ctrl->value < vivi_qctrl[i].minimum ||
1134 ctrl->value > vivi_qctrl[i].maximum) {
1135 return -ERANGE;
1136 }
1137 dev->qctl_regs[i] = ctrl->value;
1138 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001139 }
1140 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001141}
1142
1143/* ------------------------------------------------------------------
1144 File operations for the device
1145 ------------------------------------------------------------------*/
1146
Hans Verkuilbec43662008-12-30 06:58:20 -03001147static int vivi_open(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001148{
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001149 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab63b79cf2008-04-26 08:25:18 -03001150 struct vivi_fh *fh = NULL;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001151 int retval = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001152
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001153 mutex_lock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001154 dev->users++;
1155
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001156 if (dev->users > 1) {
1157 dev->users--;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001158 mutex_unlock(&dev->mutex);
1159 return -EBUSY;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001160 }
1161
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001162 dprintk(dev, 1, "open /dev/video%d type=%s users=%d\n", dev->vfd->num,
Trent Piephoa991f442007-10-10 05:37:43 -03001163 v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001164
1165 /* allocate + initialize per filehandle data */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001166 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001167 if (NULL == fh) {
1168 dev->users--;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001169 retval = -ENOMEM;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001170 }
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001171 mutex_unlock(&dev->mutex);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001172
1173 if (retval)
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001174 return retval;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001175
1176 file->private_data = fh;
1177 fh->dev = dev;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001178
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001179 fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Magnus Dammd891f472008-10-14 12:47:09 -03001180 fh->fmt = &formats[0];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001181 fh->width = 640;
1182 fh->height = 480;
1183
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001184 /* Resets frame counters */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001185 dev->h = 0;
1186 dev->m = 0;
1187 dev->s = 0;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -03001188 dev->ms = 0;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001189 dev->mv_count = 0;
1190 dev->jiffies = jiffies;
1191 sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -03001192 dev->h, dev->m, dev->s, dev->ms);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001193
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001194 videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops,
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -03001195 NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001196 sizeof(struct vivi_buffer), fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001197
Brandon Philips78718e52008-04-02 18:10:59 -03001198 vivi_start_thread(fh);
1199
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001200 return 0;
1201}
1202
1203static ssize_t
1204vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1205{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001206 struct vivi_fh *fh = file->private_data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001207
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001208 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Mauro Carvalho Chehabacb09af2007-07-29 22:56:11 -03001209 return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001210 file->f_flags & O_NONBLOCK);
1211 }
1212 return 0;
1213}
1214
1215static unsigned int
1216vivi_poll(struct file *file, struct poll_table_struct *wait)
1217{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001218 struct vivi_fh *fh = file->private_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001219 struct vivi_dev *dev = fh->dev;
Brandon Philips85c7c70bc2007-09-27 20:55:02 -03001220 struct videobuf_queue *q = &fh->vb_vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001221
Harvey Harrison7e28adb2008-04-08 23:20:00 -03001222 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001223
1224 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
1225 return POLLERR;
1226
Brandon Philips85c7c70bc2007-09-27 20:55:02 -03001227 return videobuf_poll_stream(file, q, wait);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001228}
1229
Hans Verkuilbec43662008-12-30 06:58:20 -03001230static int vivi_close(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001231{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001232 struct vivi_fh *fh = file->private_data;
1233 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001234 struct vivi_dmaqueue *vidq = &dev->vidq;
1235
Hans Verkuilbec43662008-12-30 06:58:20 -03001236 int minor = video_devdata(file)->minor;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001237
1238 vivi_stop_thread(vidq);
Brandon Philips053fcb62007-11-13 20:11:26 -03001239 videobuf_stop(&fh->vb_vidq);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001240 videobuf_mmap_free(&fh->vb_vidq);
1241
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001242 kfree(fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001243
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001244 mutex_lock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001245 dev->users--;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001246 mutex_unlock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001247
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001248 dprintk(dev, 1, "close called (minor=%d, users=%d)\n",
1249 minor, dev->users);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001250
1251 return 0;
1252}
1253
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001254static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001255{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001256 struct vivi_fh *fh = file->private_data;
1257 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001258 int ret;
1259
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001260 dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001261
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001262 ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001263
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001264 dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n",
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001265 (unsigned long)vma->vm_start,
1266 (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
1267 ret);
1268
1269 return ret;
1270}
1271
Hans Verkuilbec43662008-12-30 06:58:20 -03001272static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001273 .owner = THIS_MODULE,
1274 .open = vivi_open,
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001275 .release = vivi_close,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001276 .read = vivi_read,
1277 .poll = vivi_poll,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001278 .ioctl = video_ioctl2, /* V4L2 ioctl handler */
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001279 .mmap = vivi_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001280};
1281
Hans Verkuila3998102008-07-21 02:57:38 -03001282static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001283 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001284 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1285 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1286 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1287 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001288 .vidioc_reqbufs = vidioc_reqbufs,
1289 .vidioc_querybuf = vidioc_querybuf,
1290 .vidioc_qbuf = vidioc_qbuf,
1291 .vidioc_dqbuf = vidioc_dqbuf,
1292 .vidioc_s_std = vidioc_s_std,
1293 .vidioc_enum_input = vidioc_enum_input,
1294 .vidioc_g_input = vidioc_g_input,
1295 .vidioc_s_input = vidioc_s_input,
1296 .vidioc_queryctrl = vidioc_queryctrl,
1297 .vidioc_g_ctrl = vidioc_g_ctrl,
1298 .vidioc_s_ctrl = vidioc_s_ctrl,
1299 .vidioc_streamon = vidioc_streamon,
1300 .vidioc_streamoff = vidioc_streamoff,
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -03001301#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001302 .vidiocgmbuf = vidiocgmbuf,
1303#endif
Hans Verkuila3998102008-07-21 02:57:38 -03001304};
1305
1306static struct video_device vivi_template = {
1307 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001308 .fops = &vivi_fops,
1309 .ioctl_ops = &vivi_ioctl_ops,
1310 .minor = -1,
1311 .release = video_device_release,
1312
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001313 .tvnorms = V4L2_STD_525_60,
Mauro Carvalho Chehabe75f9ce2006-11-20 13:19:20 -03001314 .current_norm = V4L2_STD_NTSC_M,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001315};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001316
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001317/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001318 Initialization and module stuff
1319 ------------------------------------------------------------------*/
1320
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001321static int vivi_release(void)
1322{
1323 struct vivi_dev *dev;
1324 struct list_head *list;
1325
1326 while (!list_empty(&vivi_devlist)) {
1327 list = vivi_devlist.next;
1328 list_del(list);
1329 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1330
1331 v4l2_info(&dev->v4l2_dev, "unregistering /dev/video%d\n",
1332 dev->vfd->num);
1333 video_unregister_device(dev->vfd);
1334 v4l2_device_unregister(&dev->v4l2_dev);
1335 kfree(dev);
1336 }
1337
1338 return 0;
1339}
1340
Hans Verkuilc41ee242009-02-14 13:43:44 -03001341static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001342{
1343 struct vivi_dev *dev;
1344 struct video_device *vfd;
Hans Verkuilc41ee242009-02-14 13:43:44 -03001345 int ret, i;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001346
1347 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1348 if (!dev)
1349 return -ENOMEM;
1350
1351 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001352 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001353 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1354 if (ret)
1355 goto free_dev;
1356
1357 /* init video dma queues */
1358 INIT_LIST_HEAD(&dev->vidq.active);
1359 init_waitqueue_head(&dev->vidq.wq);
1360
1361 /* initialize locks */
1362 spin_lock_init(&dev->slock);
1363 mutex_init(&dev->mutex);
1364
1365 ret = -ENOMEM;
1366 vfd = video_device_alloc();
1367 if (!vfd)
1368 goto unreg_dev;
1369
1370 *vfd = vivi_template;
1371
1372 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1373 if (ret < 0)
1374 goto rel_vdev;
1375
1376 video_set_drvdata(vfd, dev);
1377
Hans Verkuilc41ee242009-02-14 13:43:44 -03001378 /* Set all controls to their default value. */
1379 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1380 dev->qctl_regs[i] = vivi_qctrl[i].default_value;
1381
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001382 /* Now that everything is fine, let's add it to device list */
1383 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1384
1385 snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
1386 vivi_template.name, vfd->num);
1387
1388 if (video_nr >= 0)
1389 video_nr++;
1390
1391 dev->vfd = vfd;
1392 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n",
1393 vfd->num);
1394 return 0;
1395
1396rel_vdev:
1397 video_device_release(vfd);
1398unreg_dev:
1399 v4l2_device_unregister(&dev->v4l2_dev);
1400free_dev:
1401 kfree(dev);
1402 return ret;
1403}
1404
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001405/* This routine allocates from 1 to n_devs virtual drivers.
1406
1407 The real maximum number of virtual drivers will depend on how many drivers
1408 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001409 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001410 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001411static int __init vivi_init(void)
1412{
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001413 int ret, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001414
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001415 if (n_devs <= 0)
1416 n_devs = 1;
1417
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001418 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001419 ret = vivi_create_instance(i);
1420 if (ret) {
1421 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001422 if (i)
1423 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001424 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001425 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001426 }
1427
1428 if (ret < 0) {
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001429 printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001430 return ret;
1431 }
1432
1433 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Carl Karsten745271a2008-06-10 00:02:32 -03001434 "Capture Board ver %u.%u.%u successfully loaded.\n",
1435 (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
1436 VIVI_VERSION & 0xFF);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001437
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001438 /* n_devs will reflect the actual number of allocated devices */
1439 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001440
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001441 return ret;
1442}
1443
1444static void __exit vivi_exit(void)
1445{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001446 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001447}
1448
1449module_init(vivi_init);
1450module_exit(vivi_exit);