blob: 625e9662c7ad4ccc23a5f36b4d3e548096c14037 [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,
87 .flags = 0,
88 .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,
97 .flags = 0,
98 }, {
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,
106 .flags = 0,
107 }, {
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,
115 .flags = 0,
116 }, {
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,
124 .flags = 0,
125 }
126};
127
128static int qctl_regs[ARRAY_SIZE(vivi_qctrl)];
129
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300130#define dprintk(dev, level, fmt, arg...) \
131 v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300132
133/* ------------------------------------------------------------------
134 Basic structures
135 ------------------------------------------------------------------*/
136
137struct vivi_fmt {
138 char *name;
139 u32 fourcc; /* v4l2 format id */
140 int depth;
141};
142
Magnus Dammd891f472008-10-14 12:47:09 -0300143static struct vivi_fmt formats[] = {
144 {
145 .name = "4:2:2, packed, YUYV",
146 .fourcc = V4L2_PIX_FMT_YUYV,
147 .depth = 16,
148 },
Magnus Dammfca36ba2008-10-14 12:47:25 -0300149 {
150 .name = "4:2:2, packed, UYVY",
151 .fourcc = V4L2_PIX_FMT_UYVY,
152 .depth = 16,
153 },
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300154 {
155 .name = "RGB565 (LE)",
156 .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
157 .depth = 16,
158 },
159 {
160 .name = "RGB565 (BE)",
161 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
162 .depth = 16,
163 },
Magnus Dammdef52392008-10-14 12:47:43 -0300164 {
165 .name = "RGB555 (LE)",
166 .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
167 .depth = 16,
168 },
169 {
170 .name = "RGB555 (BE)",
171 .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
172 .depth = 16,
173 },
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300174};
175
Magnus Dammd891f472008-10-14 12:47:09 -0300176static struct vivi_fmt *get_format(struct v4l2_format *f)
177{
178 struct vivi_fmt *fmt;
179 unsigned int k;
180
181 for (k = 0; k < ARRAY_SIZE(formats); k++) {
182 fmt = &formats[k];
183 if (fmt->fourcc == f->fmt.pix.pixelformat)
184 break;
185 }
186
187 if (k == ARRAY_SIZE(formats))
188 return NULL;
189
190 return &formats[k];
191}
192
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300193struct sg_to_addr {
194 int pos;
195 struct scatterlist *sg;
196};
197
198/* buffer for one video frame */
199struct vivi_buffer {
200 /* common v4l buffer stuff -- must be first */
201 struct videobuf_buffer vb;
202
203 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300204};
205
206struct vivi_dmaqueue {
207 struct list_head active;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300208
209 /* thread for generating video stream*/
210 struct task_struct *kthread;
211 wait_queue_head_t wq;
212 /* Counters to control fps rate */
213 int frame;
214 int ini_jiffies;
215};
216
217static LIST_HEAD(vivi_devlist);
218
219struct vivi_dev {
220 struct list_head vivi_devlist;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300221 struct v4l2_device v4l2_dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300222
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300223 spinlock_t slock;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300224 struct mutex mutex;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300225
226 int users;
227
228 /* various device info */
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -0300229 struct video_device *vfd;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300230
231 struct vivi_dmaqueue vidq;
232
233 /* Several counters */
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300234 int h, m, s, ms;
235 unsigned long jiffies;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300236 char timestr[13];
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300237
238 int mv_count; /* Controls bars movement */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300239
240 /* Input Number */
241 int input;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300242};
243
244struct vivi_fh {
245 struct vivi_dev *dev;
246
247 /* video capture */
248 struct vivi_fmt *fmt;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300249 unsigned int width, height;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300250 struct videobuf_queue vb_vidq;
251
252 enum v4l2_buf_type type;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300253 unsigned char bars[8][3];
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300254 int input; /* Input Number on bars */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300255};
256
257/* ------------------------------------------------------------------
258 DMA and thread functions
259 ------------------------------------------------------------------*/
260
261/* Bars and Colors should match positions */
262
263enum colors {
264 WHITE,
265 AMBAR,
266 CYAN,
267 GREEN,
268 MAGENTA,
269 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300270 BLUE,
271 BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300272};
273
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300274 /* R G B */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300275#define COLOR_WHITE {204, 204, 204}
276#define COLOR_AMBAR {208, 208, 0}
277#define COLOR_CIAN { 0, 206, 206}
278#define COLOR_GREEN { 0, 239, 0}
279#define COLOR_MAGENTA {239, 0, 239}
280#define COLOR_RED {205, 0, 0}
281#define COLOR_BLUE { 0, 0, 255}
282#define COLOR_BLACK { 0, 0, 0}
283
284struct bar_std {
285 u8 bar[8][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300286};
287
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300288/* Maximum number of bars are 10 - otherwise, the input print code
289 should be modified */
290static struct bar_std bars[] = {
291 { /* Standard ITU-R color bar sequence */
292 {
293 COLOR_WHITE,
294 COLOR_AMBAR,
295 COLOR_CIAN,
296 COLOR_GREEN,
297 COLOR_MAGENTA,
298 COLOR_RED,
299 COLOR_BLUE,
300 COLOR_BLACK,
301 }
302 }, {
303 {
304 COLOR_WHITE,
305 COLOR_AMBAR,
306 COLOR_BLACK,
307 COLOR_WHITE,
308 COLOR_AMBAR,
309 COLOR_BLACK,
310 COLOR_WHITE,
311 COLOR_AMBAR,
312 }
313 }, {
314 {
315 COLOR_WHITE,
316 COLOR_CIAN,
317 COLOR_BLACK,
318 COLOR_WHITE,
319 COLOR_CIAN,
320 COLOR_BLACK,
321 COLOR_WHITE,
322 COLOR_CIAN,
323 }
324 }, {
325 {
326 COLOR_WHITE,
327 COLOR_GREEN,
328 COLOR_BLACK,
329 COLOR_WHITE,
330 COLOR_GREEN,
331 COLOR_BLACK,
332 COLOR_WHITE,
333 COLOR_GREEN,
334 }
335 },
336};
337
338#define NUM_INPUTS ARRAY_SIZE(bars)
339
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300340#define TO_Y(r, g, b) \
341 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300342/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300343#define TO_V(r, g, b) \
344 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300345/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300346#define TO_U(r, g, b) \
347 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300348
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300349#define TSTAMP_MIN_Y 24
350#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
351#define TSTAMP_INPUT_X 10
352#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300353
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300354static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
355{
356 unsigned char r_y, g_u, b_v;
357 unsigned char *p;
358 int color;
359
360 r_y = fh->bars[colorpos][0]; /* R or precalculated Y */
361 g_u = fh->bars[colorpos][1]; /* G or precalculated U */
362 b_v = fh->bars[colorpos][2]; /* B or precalculated V */
363
364 for (color = 0; color < 4; color++) {
365 p = buf + color;
366
Magnus Dammd891f472008-10-14 12:47:09 -0300367 switch (fh->fmt->fourcc) {
368 case V4L2_PIX_FMT_YUYV:
369 switch (color) {
370 case 0:
371 case 2:
372 *p = r_y;
373 break;
374 case 1:
375 *p = g_u;
376 break;
377 case 3:
378 *p = b_v;
379 break;
380 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300381 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300382 case V4L2_PIX_FMT_UYVY:
383 switch (color) {
384 case 1:
385 case 3:
386 *p = r_y;
387 break;
388 case 0:
389 *p = g_u;
390 break;
391 case 2:
392 *p = b_v;
393 break;
394 }
395 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300396 case V4L2_PIX_FMT_RGB565:
397 switch (color) {
398 case 0:
399 case 2:
400 *p = (g_u << 5) | b_v;
401 break;
402 case 1:
403 case 3:
404 *p = (r_y << 3) | (g_u >> 3);
405 break;
406 }
407 break;
408 case V4L2_PIX_FMT_RGB565X:
409 switch (color) {
410 case 0:
411 case 2:
412 *p = (r_y << 3) | (g_u >> 3);
413 break;
414 case 1:
415 case 3:
416 *p = (g_u << 5) | b_v;
417 break;
418 }
419 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300420 case V4L2_PIX_FMT_RGB555:
421 switch (color) {
422 case 0:
423 case 2:
424 *p = (g_u << 5) | b_v;
425 break;
426 case 1:
427 case 3:
428 *p = (r_y << 2) | (g_u >> 3);
429 break;
430 }
431 break;
432 case V4L2_PIX_FMT_RGB555X:
433 switch (color) {
434 case 0:
435 case 2:
436 *p = (r_y << 2) | (g_u >> 3);
437 break;
438 case 1:
439 case 3:
440 *p = (g_u << 5) | b_v;
441 break;
442 }
443 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300444 }
445 }
446}
447
448static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300449 int hmax, int line, int count, char *timestr)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300450{
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300451 int w, i, j;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300452 int pos = inipos;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300453 char *s;
454 u8 chr;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300455
456 /* We will just duplicate the second pixel at the packet */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300457 wmax /= 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300458
459 /* Generate a standard color bar pattern */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300460 for (w = 0; w < wmax; w++) {
461 int colorpos = ((w + count) * 8/(wmax + 1)) % 8;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300462
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300463 gen_twopix(fh, basep + pos, colorpos);
464 pos += 4; /* only 16 bpp supported for now */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300465 }
466
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300467 /* Prints input entry number */
468
469 /* Checks if it is possible to input number */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300470 if (TSTAMP_MAX_Y >= hmax)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300471 goto end;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300472
473 if (TSTAMP_INPUT_X + strlen(timestr) >= wmax)
474 goto end;
475
476 if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
477 chr = rom8x16_bits[fh->input * 16 + line - TSTAMP_MIN_Y];
478 pos = TSTAMP_INPUT_X;
479 for (i = 0; i < 7; i++) {
480 /* Draw white font on black background */
481 if (chr & 1 << (7 - i))
482 gen_twopix(fh, basep + pos, WHITE);
483 else
484 gen_twopix(fh, basep + pos, BLACK);
485 pos += 2;
486 }
487 }
488
489 /* Checks if it is possible to show timestamp */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300490 if (TSTAMP_MIN_X + strlen(timestr) >= wmax)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300491 goto end;
492
493 /* Print stream time */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300494 if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
495 j = TSTAMP_MIN_X;
496 for (s = timestr; *s; s++) {
497 chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y];
498 for (i = 0; i < 7; i++) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300499 pos = inipos + j * 2;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300500 /* Draw white font on black background */
501 if (chr & 1 << (7 - i))
502 gen_twopix(fh, basep + pos, WHITE);
503 else
504 gen_twopix(fh, basep + pos, BLACK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300505 j++;
506 }
507 }
508 }
509
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300510end:
Mauro Carvalho Chehabb50e7fe2007-01-25 05:00:01 -0300511 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300512}
Brandon Philips78718e52008-04-02 18:10:59 -0300513
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300514static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300515{
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300516 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300517 int h , pos = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300518 int hmax = buf->vb.height;
519 int wmax = buf->vb.width;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300520 struct timeval ts;
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300521 char *tmpbuf;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300522 void *vbuf = videobuf_to_vmalloc(&buf->vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300523
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300524 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300525 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300526
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300527 tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);
528 if (!tmpbuf)
Brandon Philips78718e52008-04-02 18:10:59 -0300529 return;
530
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300531 for (h = 0; h < hmax; h++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300532 gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count,
Mauro Carvalho Chehab3bef5e42007-09-22 02:01:33 -0300533 dev->timestr);
Brandon Philips78718e52008-04-02 18:10:59 -0300534 memcpy(vbuf + pos, tmpbuf, wmax * 2);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300535 pos += wmax*2;
536 }
537
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300538 dev->mv_count++;
Mauro Carvalho Chehab3bef5e42007-09-22 02:01:33 -0300539
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300540 kfree(tmpbuf);
541
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300542 /* Updates stream time */
543
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300544 dev->ms += jiffies_to_msecs(jiffies-dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300545 dev->jiffies = jiffies;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300546 if (dev->ms >= 1000) {
547 dev->ms -= 1000;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300548 dev->s++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300549 if (dev->s >= 60) {
550 dev->s -= 60;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300551 dev->m++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300552 if (dev->m > 60) {
553 dev->m -= 60;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300554 dev->h++;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300555 if (dev->h > 24)
556 dev->h -= 24;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300557 }
558 }
559 }
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300560 sprintf(dev->timestr, "%02d:%02d:%02d:%03d",
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300561 dev->h, dev->m, dev->s, dev->ms);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300562
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300563 dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n",
564 dev->timestr, (unsigned long)tmpbuf, pos);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300565
566 /* Advice that buffer was filled */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300567 buf->vb.field_count++;
568 do_gettimeofday(&ts);
569 buf->vb.ts = ts;
Brandon Philips78718e52008-04-02 18:10:59 -0300570 buf->vb.state = VIDEOBUF_DONE;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300571}
572
Brandon Philips78718e52008-04-02 18:10:59 -0300573static void vivi_thread_tick(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300574{
Brandon Philips78718e52008-04-02 18:10:59 -0300575 struct vivi_buffer *buf;
576 struct vivi_dev *dev = fh->dev;
577 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300578
Brandon Philips78718e52008-04-02 18:10:59 -0300579 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300580
Brandon Philips78718e52008-04-02 18:10:59 -0300581 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300582
Brandon Philips78718e52008-04-02 18:10:59 -0300583 spin_lock_irqsave(&dev->slock, flags);
584 if (list_empty(&dma_q->active)) {
585 dprintk(dev, 1, "No active queue to serve\n");
586 goto unlock;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300587 }
Brandon Philips78718e52008-04-02 18:10:59 -0300588
589 buf = list_entry(dma_q->active.next,
590 struct vivi_buffer, vb.queue);
591
592 /* Nobody is waiting on this buffer, return */
593 if (!waitqueue_active(&buf->vb.done))
594 goto unlock;
595
596 list_del(&buf->vb.queue);
597
598 do_gettimeofday(&buf->vb.ts);
599
600 /* Fill buffer */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300601 vivi_fillbuff(fh, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300602 dprintk(dev, 1, "filled buffer %p\n", buf);
603
604 wake_up(&buf->vb.done);
605 dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
606unlock:
607 spin_unlock_irqrestore(&dev->slock, flags);
608 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300609}
610
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300611#define frames_to_ms(frames) \
612 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
613
Brandon Philips78718e52008-04-02 18:10:59 -0300614static void vivi_sleep(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300615{
Brandon Philips78718e52008-04-02 18:10:59 -0300616 struct vivi_dev *dev = fh->dev;
617 struct vivi_dmaqueue *dma_q = &dev->vidq;
618 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300619 DECLARE_WAITQUEUE(wait, current);
620
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300621 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300622 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300623
624 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300625 if (kthread_should_stop())
626 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300627
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300628 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300629 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300630
Brandon Philips78718e52008-04-02 18:10:59 -0300631 vivi_thread_tick(fh);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300632
633 schedule_timeout_interruptible(timeout);
634
635stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300636 remove_wait_queue(&dma_q->wq, &wait);
637 try_to_freeze();
638}
639
Adrian Bunk972c3512006-04-27 21:06:50 -0300640static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300641{
Brandon Philips78718e52008-04-02 18:10:59 -0300642 struct vivi_fh *fh = data;
643 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300644
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300645 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300646
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700647 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300648
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300649 for (;;) {
Brandon Philips78718e52008-04-02 18:10:59 -0300650 vivi_sleep(fh);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300651
652 if (kthread_should_stop())
653 break;
654 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300655 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300656 return 0;
657}
658
Brandon Philips78718e52008-04-02 18:10:59 -0300659static int vivi_start_thread(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300660{
Brandon Philips78718e52008-04-02 18:10:59 -0300661 struct vivi_dev *dev = fh->dev;
662 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300663
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300664 dma_q->frame = 0;
665 dma_q->ini_jiffies = jiffies;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300666
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300667 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300668
Brandon Philips78718e52008-04-02 18:10:59 -0300669 dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300670
Akinobu Mita054afee2006-12-20 10:04:00 -0300671 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300672 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Akinobu Mita054afee2006-12-20 10:04:00 -0300673 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300674 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300675 /* Wakes thread */
676 wake_up_interruptible(&dma_q->wq);
677
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300678 dprintk(dev, 1, "returning from %s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300679 return 0;
680}
681
Adrian Bunk972c3512006-04-27 21:06:50 -0300682static void vivi_stop_thread(struct vivi_dmaqueue *dma_q)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300683{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300684 struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq);
685
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300686 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300687 /* shutdown control thread */
688 if (dma_q->kthread) {
689 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300690 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300691 }
692}
693
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300694/* ------------------------------------------------------------------
695 Videobuf operations
696 ------------------------------------------------------------------*/
697static int
698buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
699{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300700 struct vivi_fh *fh = vq->priv_data;
701 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300702
703 *size = fh->width*fh->height*2;
704
705 if (0 == *count)
706 *count = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300707
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300708 while (*size * *count > vid_limit * 1024 * 1024)
709 (*count)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300710
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300711 dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300712 *count, *size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300713
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300714 return 0;
715}
716
Adrian Bunk972c3512006-04-27 21:06:50 -0300717static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300718{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300719 struct vivi_fh *fh = vq->priv_data;
720 struct vivi_dev *dev = fh->dev;
721
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300722 dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300723
724 if (in_interrupt())
725 BUG();
726
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300727 videobuf_vmalloc_free(&buf->vb);
Mauro Carvalho Chehabfbde31d2008-04-13 14:57:44 -0300728 dprintk(dev, 1, "free_buffer: freed\n");
Brandon Philips0fc06862007-11-06 20:02:36 -0300729 buf->vb.state = VIDEOBUF_NEEDS_INIT;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300730}
731
732#define norm_maxw() 1024
733#define norm_maxh() 768
734static int
735buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
736 enum v4l2_field field)
737{
738 struct vivi_fh *fh = vq->priv_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300739 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300740 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300741 int rc;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300742
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300743 dprintk(dev, 1, "%s, field=%d\n", __func__, field);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300744
745 BUG_ON(NULL == fh->fmt);
Brandon Philips78718e52008-04-02 18:10:59 -0300746
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300747 if (fh->width < 48 || fh->width > norm_maxw() ||
748 fh->height < 32 || fh->height > norm_maxh())
749 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300750
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300751 buf->vb.size = fh->width*fh->height*2;
752 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
753 return -EINVAL;
754
Brandon Philips78718e52008-04-02 18:10:59 -0300755 /* These properties only change when queue is idle, see s_fmt */
756 buf->fmt = fh->fmt;
757 buf->vb.width = fh->width;
758 buf->vb.height = fh->height;
759 buf->vb.field = field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300760
Brandon Philips0fc06862007-11-06 20:02:36 -0300761 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300762 rc = videobuf_iolock(vq, &buf->vb, NULL);
763 if (rc < 0)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300764 goto fail;
765 }
766
Brandon Philips0fc06862007-11-06 20:02:36 -0300767 buf->vb.state = VIDEOBUF_PREPARED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300768
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300769 return 0;
770
771fail:
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300772 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300773 return rc;
774}
775
776static void
777buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
778{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300779 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
780 struct vivi_fh *fh = vq->priv_data;
781 struct vivi_dev *dev = fh->dev;
Brandon Philips78718e52008-04-02 18:10:59 -0300782 struct vivi_dmaqueue *vidq = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300783
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300784 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300785
Brandon Philips78718e52008-04-02 18:10:59 -0300786 buf->vb.state = VIDEOBUF_QUEUED;
787 list_add_tail(&buf->vb.queue, &vidq->active);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300788}
789
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300790static void buffer_release(struct videobuf_queue *vq,
791 struct videobuf_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300792{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300793 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300794 struct vivi_fh *fh = vq->priv_data;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300795 struct vivi_dev *dev = (struct vivi_dev *)fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300796
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300797 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300798
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300799 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300800}
801
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300802static struct videobuf_queue_ops vivi_video_qops = {
803 .buf_setup = buffer_setup,
804 .buf_prepare = buffer_prepare,
805 .buf_queue = buffer_queue,
806 .buf_release = buffer_release,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300807};
808
809/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300810 IOCTL vidioc handling
811 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300812static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300813 struct v4l2_capability *cap)
814{
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300815 struct vivi_fh *fh = priv;
816 struct vivi_dev *dev = fh->dev;
817
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300818 strcpy(cap->driver, "vivi");
819 strcpy(cap->card, "vivi");
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300820 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300821 cap->version = VIVI_VERSION;
822 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
823 V4L2_CAP_STREAMING |
824 V4L2_CAP_READWRITE;
825 return 0;
826}
827
Hans Verkuil78b526a2008-05-28 12:16:41 -0300828static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300829 struct v4l2_fmtdesc *f)
830{
Magnus Dammd891f472008-10-14 12:47:09 -0300831 struct vivi_fmt *fmt;
832
833 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300834 return -EINVAL;
835
Magnus Dammd891f472008-10-14 12:47:09 -0300836 fmt = &formats[f->index];
837
838 strlcpy(f->description, fmt->name, sizeof(f->description));
839 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300840 return 0;
841}
842
Hans Verkuil78b526a2008-05-28 12:16:41 -0300843static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300844 struct v4l2_format *f)
845{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300846 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300847
848 f->fmt.pix.width = fh->width;
849 f->fmt.pix.height = fh->height;
850 f->fmt.pix.field = fh->vb_vidq.field;
851 f->fmt.pix.pixelformat = fh->fmt->fourcc;
852 f->fmt.pix.bytesperline =
853 (f->fmt.pix.width * fh->fmt->depth) >> 3;
854 f->fmt.pix.sizeimage =
855 f->fmt.pix.height * f->fmt.pix.bytesperline;
856
857 return (0);
858}
859
Hans Verkuil78b526a2008-05-28 12:16:41 -0300860static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300861 struct v4l2_format *f)
862{
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300863 struct vivi_fh *fh = priv;
864 struct vivi_dev *dev = fh->dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300865 struct vivi_fmt *fmt;
866 enum v4l2_field field;
867 unsigned int maxw, maxh;
868
Magnus Dammd891f472008-10-14 12:47:09 -0300869 fmt = get_format(f);
870 if (!fmt) {
871 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
872 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300873 return -EINVAL;
874 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300875
876 field = f->fmt.pix.field;
877
878 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300879 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300880 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300881 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300882 return -EINVAL;
883 }
884
885 maxw = norm_maxw();
886 maxh = norm_maxh();
887
888 f->fmt.pix.field = field;
889 if (f->fmt.pix.height < 32)
890 f->fmt.pix.height = 32;
891 if (f->fmt.pix.height > maxh)
892 f->fmt.pix.height = maxh;
893 if (f->fmt.pix.width < 48)
894 f->fmt.pix.width = 48;
895 if (f->fmt.pix.width > maxw)
896 f->fmt.pix.width = maxw;
897 f->fmt.pix.width &= ~0x03;
898 f->fmt.pix.bytesperline =
899 (f->fmt.pix.width * fmt->depth) >> 3;
900 f->fmt.pix.sizeimage =
901 f->fmt.pix.height * f->fmt.pix.bytesperline;
902
903 return 0;
904}
905
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300906/* precalculate color bar values to speed up rendering */
907static void precalculate_bars(struct vivi_fh *fh)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300908{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300909 struct vivi_dev *dev = fh->dev;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300910 unsigned char r, g, b;
Magnus Dammd891f472008-10-14 12:47:09 -0300911 int k, is_yuv;
Brandon Philips78718e52008-04-02 18:10:59 -0300912
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300913 fh->input = dev->input;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300914
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300915 for (k = 0; k < 8; k++) {
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300916 r = bars[fh->input].bar[k][0];
917 g = bars[fh->input].bar[k][1];
918 b = bars[fh->input].bar[k][2];
Magnus Dammd891f472008-10-14 12:47:09 -0300919 is_yuv = 0;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300920
Magnus Dammd891f472008-10-14 12:47:09 -0300921 switch (fh->fmt->fourcc) {
922 case V4L2_PIX_FMT_YUYV:
Magnus Dammfca36ba2008-10-14 12:47:25 -0300923 case V4L2_PIX_FMT_UYVY:
Magnus Dammd891f472008-10-14 12:47:09 -0300924 is_yuv = 1;
925 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300926 case V4L2_PIX_FMT_RGB565:
927 case V4L2_PIX_FMT_RGB565X:
928 r >>= 3;
929 g >>= 2;
930 b >>= 3;
931 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300932 case V4L2_PIX_FMT_RGB555:
933 case V4L2_PIX_FMT_RGB555X:
934 r >>= 3;
935 g >>= 3;
936 b >>= 3;
937 break;
Magnus Dammd891f472008-10-14 12:47:09 -0300938 }
939
940 if (is_yuv) {
941 fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
942 fh->bars[k][1] = TO_U(r, g, b); /* Cb */
943 fh->bars[k][2] = TO_V(r, g, b); /* Cr */
944 } else {
945 fh->bars[k][0] = r;
946 fh->bars[k][1] = g;
947 fh->bars[k][2] = b;
948 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300949 }
950
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300951}
952
953/*FIXME: This seems to be generic enough to be at videodev2 */
954static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
955 struct v4l2_format *f)
956{
957 struct vivi_fh *fh = priv;
958 struct videobuf_queue *q = &fh->vb_vidq;
959
960 int ret = vidioc_try_fmt_vid_cap(file, fh, f);
961 if (ret < 0)
962 return ret;
963
964 mutex_lock(&q->vb_lock);
965
966 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
967 dprintk(fh->dev, 1, "%s queue busy\n", __func__);
968 ret = -EBUSY;
969 goto out;
970 }
971
972 fh->fmt = get_format(f);
973 fh->width = f->fmt.pix.width;
974 fh->height = f->fmt.pix.height;
975 fh->vb_vidq.field = f->fmt.pix.field;
976 fh->type = f->type;
977
978 precalculate_bars(fh);
979
Brandon Philips78718e52008-04-02 18:10:59 -0300980 ret = 0;
981out:
982 mutex_unlock(&q->vb_lock);
983
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300984 return ret;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300985}
986
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300987static int vidioc_reqbufs(struct file *file, void *priv,
988 struct v4l2_requestbuffers *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300989{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300990 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300991
992 return (videobuf_reqbufs(&fh->vb_vidq, p));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300993}
994
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300995static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300996{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300997 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300998
999 return (videobuf_querybuf(&fh->vb_vidq, p));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001000}
1001
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001002static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001003{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001004 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001005
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001006 return (videobuf_qbuf(&fh->vb_vidq, p));
1007}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001008
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001009static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001010{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001011 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001012
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001013 return (videobuf_dqbuf(&fh->vb_vidq, p,
1014 file->f_flags & O_NONBLOCK));
1015}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001016
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -03001017#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001018static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001019{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001020 struct vivi_fh *fh = priv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001021
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001022 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001023}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001024#endif
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001025
Adrian Bunkdc46ace2006-06-23 06:42:44 -03001026static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001027{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001028 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001029
1030 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1031 return -EINVAL;
1032 if (i != fh->type)
1033 return -EINVAL;
1034
Brandon Philipsba32bd92007-09-27 20:55:17 -03001035 return videobuf_streamon(&fh->vb_vidq);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001036}
1037
Adrian Bunkdc46ace2006-06-23 06:42:44 -03001038static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001039{
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001040 struct vivi_fh *fh = priv;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001041
1042 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1043 return -EINVAL;
1044 if (i != fh->type)
1045 return -EINVAL;
1046
Brandon Philipsba32bd92007-09-27 20:55:17 -03001047 return videobuf_streamoff(&fh->vb_vidq);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001048}
1049
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001050static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001051{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001052 return 0;
1053}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001054
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001055/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001056static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001057 struct v4l2_input *inp)
1058{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001059 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001060 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001061
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001062 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001063 inp->std = V4L2_STD_525_60;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001064 sprintf(inp->name, "Camera %u", inp->index);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001065
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001066 return (0);
1067}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001068
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001069static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001070{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001071 struct vivi_fh *fh = priv;
1072 struct vivi_dev *dev = fh->dev;
1073
1074 *i = dev->input;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001075
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001076 return (0);
1077}
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001078static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001079{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001080 struct vivi_fh *fh = priv;
1081 struct vivi_dev *dev = fh->dev;
1082
1083 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001084 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001085
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001086 dev->input = i;
1087 precalculate_bars(fh);
1088
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001089 return (0);
1090}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001091
1092 /* --- controls ---------------------------------------------- */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001093static int vidioc_queryctrl(struct file *file, void *priv,
1094 struct v4l2_queryctrl *qc)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001095{
1096 int i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001097
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001098 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1099 if (qc->id && qc->id == vivi_qctrl[i].id) {
1100 memcpy(qc, &(vivi_qctrl[i]),
1101 sizeof(*qc));
1102 return (0);
1103 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001104
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001105 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001106}
1107
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001108static int vidioc_g_ctrl(struct file *file, void *priv,
1109 struct v4l2_control *ctrl)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001110{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001111 int i;
1112
1113 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1114 if (ctrl->id == vivi_qctrl[i].id) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001115 ctrl->value = qctl_regs[i];
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001116 return (0);
1117 }
1118
1119 return -EINVAL;
1120}
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001121static int vidioc_s_ctrl(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001122 struct v4l2_control *ctrl)
1123{
1124 int i;
1125
1126 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
1127 if (ctrl->id == vivi_qctrl[i].id) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001128 if (ctrl->value < vivi_qctrl[i].minimum
1129 || ctrl->value > vivi_qctrl[i].maximum) {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001130 return (-ERANGE);
1131 }
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001132 qctl_regs[i] = ctrl->value;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001133 return (0);
1134 }
1135 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001136}
1137
1138/* ------------------------------------------------------------------
1139 File operations for the device
1140 ------------------------------------------------------------------*/
1141
Hans Verkuilbec43662008-12-30 06:58:20 -03001142static int vivi_open(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001143{
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001144 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab63b79cf2008-04-26 08:25:18 -03001145 struct vivi_fh *fh = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001146 int i;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001147 int retval = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001148
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001149 mutex_lock(&dev->mutex);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001150 dev->users++;
1151
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001152 if (dev->users > 1) {
1153 dev->users--;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001154 mutex_unlock(&dev->mutex);
1155 return -EBUSY;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001156 }
1157
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001158 dprintk(dev, 1, "open /dev/video%d type=%s users=%d\n", dev->vfd->num,
Trent Piephoa991f442007-10-10 05:37:43 -03001159 v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001160
1161 /* allocate + initialize per filehandle data */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001162 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001163 if (NULL == fh) {
1164 dev->users--;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001165 retval = -ENOMEM;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001166 }
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001167 mutex_unlock(&dev->mutex);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001168
1169 if (retval)
Brandon Philipsaa9dbac2008-04-02 18:10:59 -03001170 return retval;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001171
1172 file->private_data = fh;
1173 fh->dev = dev;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001174
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001175 fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Magnus Dammd891f472008-10-14 12:47:09 -03001176 fh->fmt = &formats[0];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001177 fh->width = 640;
1178 fh->height = 480;
1179
1180 /* Put all controls at a sane state */
1181 for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001182 qctl_regs[i] = vivi_qctrl[i].default_value;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001183
1184 /* 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
1341static int __init vivi_create_instance(int i)
1342{
1343 struct vivi_dev *dev;
1344 struct video_device *vfd;
1345 int ret;
1346
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),
1352 "%s-%03d", VIVI_MODULE_NAME, i);
1353 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
1378 /* Now that everything is fine, let's add it to device list */
1379 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1380
1381 snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
1382 vivi_template.name, vfd->num);
1383
1384 if (video_nr >= 0)
1385 video_nr++;
1386
1387 dev->vfd = vfd;
1388 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n",
1389 vfd->num);
1390 return 0;
1391
1392rel_vdev:
1393 video_device_release(vfd);
1394unreg_dev:
1395 v4l2_device_unregister(&dev->v4l2_dev);
1396free_dev:
1397 kfree(dev);
1398 return ret;
1399}
1400
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001401/* This routine allocates from 1 to n_devs virtual drivers.
1402
1403 The real maximum number of virtual drivers will depend on how many drivers
1404 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001405 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001406 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001407static int __init vivi_init(void)
1408{
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001409 int ret, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001410
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001411 if (n_devs <= 0)
1412 n_devs = 1;
1413
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001414 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001415 ret = vivi_create_instance(i);
1416 if (ret) {
1417 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001418 if (i)
1419 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001420 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001421 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001422 }
1423
1424 if (ret < 0) {
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001425 printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001426 return ret;
1427 }
1428
1429 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Carl Karsten745271a2008-06-10 00:02:32 -03001430 "Capture Board ver %u.%u.%u successfully loaded.\n",
1431 (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
1432 VIVI_VERSION & 0xFF);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001433
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001434 /* n_devs will reflect the actual number of allocated devices */
1435 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001436
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001437 return ret;
1438}
1439
1440static void __exit vivi_exit(void)
1441{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001442 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001443}
1444
1445module_init(vivi_init);
1446module_exit(vivi_exit);