blob: d5e30b85c5592db37eddc7b93b082e177f75ad6e [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>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030016#include <linux/errno.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030017#include <linux/kernel.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030018#include <linux/init.h>
19#include <linux/sched.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030020#include <linux/font.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030021#include <linux/version.h>
Matthias Kaehlcke51b54022007-07-02 10:19:38 -030022#include <linux/mutex.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030023#include <linux/videodev2.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030024#include <linux/kthread.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030025#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080026#include <linux/freezer.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030027#endif
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030028#include <media/videobuf-vmalloc.h>
29#include <media/v4l2-device.h>
30#include <media/v4l2-ioctl.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030031#include <media/v4l2-common.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030032
Mauro Carvalho Chehab584ce482008-06-10 15:21:49 -030033#define VIVI_MODULE_NAME "vivi"
Carl Karsten745271a2008-06-10 00:02:32 -030034
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030035/* Wake up at about 30 fps */
36#define WAKE_NUMERATOR 30
37#define WAKE_DENOMINATOR 1001
38#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
39
Hans Verkuil730947b2010-04-10 04:13:53 -030040#define MAX_WIDTH 1920
41#define MAX_HEIGHT 1200
42
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030043#define VIVI_MAJOR_VERSION 0
Hans Verkuil730947b2010-04-10 04:13:53 -030044#define VIVI_MINOR_VERSION 7
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030045#define VIVI_RELEASE 0
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -030046#define VIVI_VERSION \
47 KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030048
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030049MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
50MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
51MODULE_LICENSE("Dual BSD/GPL");
52
53static unsigned video_nr = -1;
54module_param(video_nr, uint, 0644);
55MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
56
57static unsigned n_devs = 1;
58module_param(n_devs, uint, 0644);
59MODULE_PARM_DESC(n_devs, "number of video devices to create");
60
61static unsigned debug;
62module_param(debug, uint, 0644);
63MODULE_PARM_DESC(debug, "activates debug info");
64
65static unsigned int vid_limit = 16;
66module_param(vid_limit, uint, 0644);
67MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
68
Hans Verkuil730947b2010-04-10 04:13:53 -030069/* Global font descriptor */
70static const u8 *font8x16;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030071
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030072#define dprintk(dev, level, fmt, arg...) \
73 v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030074
75/* ------------------------------------------------------------------
76 Basic structures
77 ------------------------------------------------------------------*/
78
79struct vivi_fmt {
80 char *name;
81 u32 fourcc; /* v4l2 format id */
82 int depth;
83};
84
Magnus Dammd891f472008-10-14 12:47:09 -030085static struct vivi_fmt formats[] = {
86 {
87 .name = "4:2:2, packed, YUYV",
88 .fourcc = V4L2_PIX_FMT_YUYV,
89 .depth = 16,
90 },
Magnus Dammfca36ba2008-10-14 12:47:25 -030091 {
92 .name = "4:2:2, packed, UYVY",
93 .fourcc = V4L2_PIX_FMT_UYVY,
94 .depth = 16,
95 },
Magnus Dammaeadb5d2008-10-14 12:47:35 -030096 {
97 .name = "RGB565 (LE)",
98 .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
99 .depth = 16,
100 },
101 {
102 .name = "RGB565 (BE)",
103 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
104 .depth = 16,
105 },
Magnus Dammdef52392008-10-14 12:47:43 -0300106 {
107 .name = "RGB555 (LE)",
108 .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
109 .depth = 16,
110 },
111 {
112 .name = "RGB555 (BE)",
113 .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
114 .depth = 16,
115 },
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300116};
117
Magnus Dammd891f472008-10-14 12:47:09 -0300118static struct vivi_fmt *get_format(struct v4l2_format *f)
119{
120 struct vivi_fmt *fmt;
121 unsigned int k;
122
123 for (k = 0; k < ARRAY_SIZE(formats); k++) {
124 fmt = &formats[k];
125 if (fmt->fourcc == f->fmt.pix.pixelformat)
126 break;
127 }
128
129 if (k == ARRAY_SIZE(formats))
130 return NULL;
131
132 return &formats[k];
133}
134
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300135struct sg_to_addr {
136 int pos;
137 struct scatterlist *sg;
138};
139
140/* buffer for one video frame */
141struct vivi_buffer {
142 /* common v4l buffer stuff -- must be first */
143 struct videobuf_buffer vb;
144
145 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300146};
147
148struct vivi_dmaqueue {
149 struct list_head active;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300150
151 /* thread for generating video stream*/
152 struct task_struct *kthread;
153 wait_queue_head_t wq;
154 /* Counters to control fps rate */
155 int frame;
156 int ini_jiffies;
157};
158
159static LIST_HEAD(vivi_devlist);
160
161struct vivi_dev {
162 struct list_head vivi_devlist;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300163 struct v4l2_device v4l2_dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300164
Hans Verkuil730947b2010-04-10 04:13:53 -0300165 /* controls */
166 int brightness;
167 int contrast;
168 int saturation;
169 int hue;
170 int volume;
171
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300172 spinlock_t slock;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300173 struct mutex mutex;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300174
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300175 /* various device info */
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -0300176 struct video_device *vfd;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300177
178 struct vivi_dmaqueue vidq;
179
180 /* Several counters */
Hans Verkuil730947b2010-04-10 04:13:53 -0300181 unsigned ms;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300182 unsigned long jiffies;
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300183
184 int mv_count; /* Controls bars movement */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300185
186 /* Input Number */
187 int input;
Hans Verkuilc41ee242009-02-14 13:43:44 -0300188
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300189 /* video capture */
190 struct vivi_fmt *fmt;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300191 unsigned int width, height;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300192 struct videobuf_queue vb_vidq;
193
Hans Verkuil730947b2010-04-10 04:13:53 -0300194 unsigned long generating;
195 u8 bars[9][3];
196 u8 line[MAX_WIDTH * 4];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300197};
198
199/* ------------------------------------------------------------------
200 DMA and thread functions
201 ------------------------------------------------------------------*/
202
203/* Bars and Colors should match positions */
204
205enum colors {
206 WHITE,
Hans Verkuil730947b2010-04-10 04:13:53 -0300207 AMBER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300208 CYAN,
209 GREEN,
210 MAGENTA,
211 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300212 BLUE,
213 BLACK,
Hans Verkuil730947b2010-04-10 04:13:53 -0300214 TEXT_BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300215};
216
Hans Verkuil730947b2010-04-10 04:13:53 -0300217/* R G B */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300218#define COLOR_WHITE {204, 204, 204}
Hans Verkuil730947b2010-04-10 04:13:53 -0300219#define COLOR_AMBER {208, 208, 0}
220#define COLOR_CYAN { 0, 206, 206}
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300221#define COLOR_GREEN { 0, 239, 0}
222#define COLOR_MAGENTA {239, 0, 239}
223#define COLOR_RED {205, 0, 0}
224#define COLOR_BLUE { 0, 0, 255}
225#define COLOR_BLACK { 0, 0, 0}
226
227struct bar_std {
Hans Verkuil730947b2010-04-10 04:13:53 -0300228 u8 bar[9][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300229};
230
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300231/* Maximum number of bars are 10 - otherwise, the input print code
232 should be modified */
233static struct bar_std bars[] = {
234 { /* Standard ITU-R color bar sequence */
Hans Verkuil730947b2010-04-10 04:13:53 -0300235 { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN,
236 COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300237 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300238 { COLOR_WHITE, COLOR_AMBER, COLOR_BLACK, COLOR_WHITE,
239 COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, COLOR_AMBER, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300240 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300241 { COLOR_WHITE, COLOR_CYAN, COLOR_BLACK, COLOR_WHITE,
242 COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, COLOR_CYAN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300243 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300244 { COLOR_WHITE, COLOR_GREEN, COLOR_BLACK, COLOR_WHITE,
245 COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, COLOR_GREEN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300246 },
247};
248
249#define NUM_INPUTS ARRAY_SIZE(bars)
250
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300251#define TO_Y(r, g, b) \
252 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300253/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300254#define TO_V(r, g, b) \
255 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300256/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300257#define TO_U(r, g, b) \
258 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300259
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300260/* precalculate color bar values to speed up rendering */
Hans Verkuil730947b2010-04-10 04:13:53 -0300261static void precalculate_bars(struct vivi_dev *dev)
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300262{
Hans Verkuil730947b2010-04-10 04:13:53 -0300263 u8 r, g, b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300264 int k, is_yuv;
265
Hans Verkuil730947b2010-04-10 04:13:53 -0300266 for (k = 0; k < 9; k++) {
267 r = bars[dev->input].bar[k][0];
268 g = bars[dev->input].bar[k][1];
269 b = bars[dev->input].bar[k][2];
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300270 is_yuv = 0;
271
Hans Verkuil730947b2010-04-10 04:13:53 -0300272 switch (dev->fmt->fourcc) {
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300273 case V4L2_PIX_FMT_YUYV:
274 case V4L2_PIX_FMT_UYVY:
275 is_yuv = 1;
276 break;
277 case V4L2_PIX_FMT_RGB565:
278 case V4L2_PIX_FMT_RGB565X:
279 r >>= 3;
280 g >>= 2;
281 b >>= 3;
282 break;
283 case V4L2_PIX_FMT_RGB555:
284 case V4L2_PIX_FMT_RGB555X:
285 r >>= 3;
286 g >>= 3;
287 b >>= 3;
288 break;
289 }
290
291 if (is_yuv) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300292 dev->bars[k][0] = TO_Y(r, g, b); /* Luma */
293 dev->bars[k][1] = TO_U(r, g, b); /* Cb */
294 dev->bars[k][2] = TO_V(r, g, b); /* Cr */
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300295 } else {
Hans Verkuil730947b2010-04-10 04:13:53 -0300296 dev->bars[k][0] = r;
297 dev->bars[k][1] = g;
298 dev->bars[k][2] = b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300299 }
300 }
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300301}
302
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300303#define TSTAMP_MIN_Y 24
304#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
305#define TSTAMP_INPUT_X 10
306#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300307
Hans Verkuil730947b2010-04-10 04:13:53 -0300308static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos)
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300309{
Hans Verkuil730947b2010-04-10 04:13:53 -0300310 u8 r_y, g_u, b_v;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300311 int color;
Hans Verkuil730947b2010-04-10 04:13:53 -0300312 u8 *p;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300313
Hans Verkuil730947b2010-04-10 04:13:53 -0300314 r_y = dev->bars[colorpos][0]; /* R or precalculated Y */
315 g_u = dev->bars[colorpos][1]; /* G or precalculated U */
316 b_v = dev->bars[colorpos][2]; /* B or precalculated V */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300317
318 for (color = 0; color < 4; color++) {
319 p = buf + color;
320
Hans Verkuil730947b2010-04-10 04:13:53 -0300321 switch (dev->fmt->fourcc) {
Magnus Dammd891f472008-10-14 12:47:09 -0300322 case V4L2_PIX_FMT_YUYV:
323 switch (color) {
324 case 0:
325 case 2:
326 *p = r_y;
327 break;
328 case 1:
329 *p = g_u;
330 break;
331 case 3:
332 *p = b_v;
333 break;
334 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300335 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300336 case V4L2_PIX_FMT_UYVY:
337 switch (color) {
338 case 1:
339 case 3:
340 *p = r_y;
341 break;
342 case 0:
343 *p = g_u;
344 break;
345 case 2:
346 *p = b_v;
347 break;
348 }
349 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300350 case V4L2_PIX_FMT_RGB565:
351 switch (color) {
352 case 0:
353 case 2:
354 *p = (g_u << 5) | b_v;
355 break;
356 case 1:
357 case 3:
358 *p = (r_y << 3) | (g_u >> 3);
359 break;
360 }
361 break;
362 case V4L2_PIX_FMT_RGB565X:
363 switch (color) {
364 case 0:
365 case 2:
366 *p = (r_y << 3) | (g_u >> 3);
367 break;
368 case 1:
369 case 3:
370 *p = (g_u << 5) | b_v;
371 break;
372 }
373 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300374 case V4L2_PIX_FMT_RGB555:
375 switch (color) {
376 case 0:
377 case 2:
378 *p = (g_u << 5) | b_v;
379 break;
380 case 1:
381 case 3:
382 *p = (r_y << 2) | (g_u >> 3);
383 break;
384 }
385 break;
386 case V4L2_PIX_FMT_RGB555X:
387 switch (color) {
388 case 0:
389 case 2:
390 *p = (r_y << 2) | (g_u >> 3);
391 break;
392 case 1:
393 case 3:
394 *p = (g_u << 5) | b_v;
395 break;
396 }
397 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300398 }
399 }
400}
401
Hans Verkuil730947b2010-04-10 04:13:53 -0300402static void precalculate_line(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300403{
Hans Verkuil730947b2010-04-10 04:13:53 -0300404 int w;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300405
Hans Verkuil730947b2010-04-10 04:13:53 -0300406 for (w = 0; w < dev->width * 2; w += 2) {
407 int colorpos = (w / (dev->width / 8) % 8);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300408
Hans Verkuil730947b2010-04-10 04:13:53 -0300409 gen_twopix(dev, dev->line + w * 2, colorpos);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300410 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300411}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300412
Hans Verkuil730947b2010-04-10 04:13:53 -0300413static void gen_text(struct vivi_dev *dev, char *basep,
414 int y, int x, char *text)
415{
416 int line;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300417
Hans Verkuil730947b2010-04-10 04:13:53 -0300418 /* Checks if it is possible to show string */
419 if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width)
420 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300421
422 /* Print stream time */
Hans Verkuil730947b2010-04-10 04:13:53 -0300423 for (line = y; line < y + 16; line++) {
424 int j = 0;
425 char *pos = basep + line * dev->width * 2 + x * 2;
426 char *s;
427
428 for (s = text; *s; s++) {
429 u8 chr = font8x16[*s * 16 + line - y];
430 int i;
431
432 for (i = 0; i < 7; i++, j++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300433 /* Draw white font on black background */
Hans Verkuil730947b2010-04-10 04:13:53 -0300434 if (chr & (1 << (7 - i)))
435 gen_twopix(dev, pos + j * 2, WHITE);
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300436 else
Hans Verkuil730947b2010-04-10 04:13:53 -0300437 gen_twopix(dev, pos + j * 2, TEXT_BLACK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300438 }
439 }
440 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300441}
Brandon Philips78718e52008-04-02 18:10:59 -0300442
Hans Verkuil730947b2010-04-10 04:13:53 -0300443static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300444{
Hans Verkuil730947b2010-04-10 04:13:53 -0300445 int hmax = buf->vb.height;
446 int wmax = buf->vb.width;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300447 struct timeval ts;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300448 void *vbuf = videobuf_to_vmalloc(&buf->vb);
Hans Verkuil730947b2010-04-10 04:13:53 -0300449 unsigned ms;
450 char str[100];
451 int h, line = 1;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300452
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300453 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300454 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300455
Hans Verkuil730947b2010-04-10 04:13:53 -0300456 for (h = 0; h < hmax; h++)
457 memcpy(vbuf + h * wmax * 2, dev->line + (dev->mv_count % wmax) * 2, wmax * 2);
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300458
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300459 /* Updates stream time */
460
Hans Verkuil730947b2010-04-10 04:13:53 -0300461 dev->ms += jiffies_to_msecs(jiffies - dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300462 dev->jiffies = jiffies;
Hans Verkuil730947b2010-04-10 04:13:53 -0300463 ms = dev->ms;
464 snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d ",
465 (ms / (60 * 60 * 1000)) % 24,
466 (ms / (60 * 1000)) % 60,
467 (ms / 1000) % 60,
468 ms % 1000);
469 gen_text(dev, vbuf, line++ * 16, 16, str);
470 snprintf(str, sizeof(str), " %dx%d, input %d ",
471 dev->width, dev->height, dev->input);
472 gen_text(dev, vbuf, line++ * 16, 16, str);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300473
Hans Verkuil730947b2010-04-10 04:13:53 -0300474 snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
475 dev->brightness,
476 dev->contrast,
477 dev->saturation,
478 dev->hue);
479 gen_text(dev, vbuf, line++ * 16, 16, str);
480 snprintf(str, sizeof(str), " volume %3d ", dev->volume);
481 gen_text(dev, vbuf, line++ * 16, 16, str);
482
483 dev->mv_count += 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300484
485 /* Advice that buffer was filled */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300486 buf->vb.field_count++;
487 do_gettimeofday(&ts);
488 buf->vb.ts = ts;
Brandon Philips78718e52008-04-02 18:10:59 -0300489 buf->vb.state = VIDEOBUF_DONE;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300490}
491
Hans Verkuil730947b2010-04-10 04:13:53 -0300492static void vivi_thread_tick(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300493{
Brandon Philips78718e52008-04-02 18:10:59 -0300494 struct vivi_dmaqueue *dma_q = &dev->vidq;
Hans Verkuil730947b2010-04-10 04:13:53 -0300495 struct vivi_buffer *buf;
Brandon Philips78718e52008-04-02 18:10:59 -0300496 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300497
Brandon Philips78718e52008-04-02 18:10:59 -0300498 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300499
Brandon Philips78718e52008-04-02 18:10:59 -0300500 spin_lock_irqsave(&dev->slock, flags);
501 if (list_empty(&dma_q->active)) {
502 dprintk(dev, 1, "No active queue to serve\n");
503 goto unlock;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300504 }
Brandon Philips78718e52008-04-02 18:10:59 -0300505
506 buf = list_entry(dma_q->active.next,
507 struct vivi_buffer, vb.queue);
508
509 /* Nobody is waiting on this buffer, return */
510 if (!waitqueue_active(&buf->vb.done))
511 goto unlock;
512
513 list_del(&buf->vb.queue);
514
515 do_gettimeofday(&buf->vb.ts);
516
517 /* Fill buffer */
Hans Verkuil730947b2010-04-10 04:13:53 -0300518 vivi_fillbuff(dev, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300519 dprintk(dev, 1, "filled buffer %p\n", buf);
520
521 wake_up(&buf->vb.done);
522 dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
523unlock:
524 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300525}
526
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300527#define frames_to_ms(frames) \
528 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
529
Hans Verkuil730947b2010-04-10 04:13:53 -0300530static void vivi_sleep(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300531{
Brandon Philips78718e52008-04-02 18:10:59 -0300532 struct vivi_dmaqueue *dma_q = &dev->vidq;
533 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300534 DECLARE_WAITQUEUE(wait, current);
535
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300536 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300537 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300538
539 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300540 if (kthread_should_stop())
541 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300542
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300543 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300544 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300545
Hans Verkuil730947b2010-04-10 04:13:53 -0300546 vivi_thread_tick(dev);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300547
548 schedule_timeout_interruptible(timeout);
549
550stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300551 remove_wait_queue(&dma_q->wq, &wait);
552 try_to_freeze();
553}
554
Adrian Bunk972c3512006-04-27 21:06:50 -0300555static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300556{
Hans Verkuil730947b2010-04-10 04:13:53 -0300557 struct vivi_dev *dev = data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300558
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300559 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300560
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700561 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300562
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300563 for (;;) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300564 vivi_sleep(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300565
566 if (kthread_should_stop())
567 break;
568 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300569 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300570 return 0;
571}
572
Hans Verkuil730947b2010-04-10 04:13:53 -0300573static void vivi_start_generating(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300574{
Hans Verkuil730947b2010-04-10 04:13:53 -0300575 struct vivi_dev *dev = video_drvdata(file);
Brandon Philips78718e52008-04-02 18:10:59 -0300576 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300577
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300578 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300579
Hans Verkuil730947b2010-04-10 04:13:53 -0300580 if (test_and_set_bit(0, &dev->generating))
581 return;
582 file->private_data = dev;
583
584 /* Resets frame counters */
585 dev->ms = 0;
586 dev->mv_count = 0;
587 dev->jiffies = jiffies;
588
589 dma_q->frame = 0;
590 dma_q->ini_jiffies = jiffies;
591 dma_q->kthread = kthread_run(vivi_thread, dev, dev->v4l2_dev.name);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300592
Akinobu Mita054afee2006-12-20 10:04:00 -0300593 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300594 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Hans Verkuil730947b2010-04-10 04:13:53 -0300595 clear_bit(0, &dev->generating);
596 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300597 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300598 /* Wakes thread */
599 wake_up_interruptible(&dma_q->wq);
600
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300601 dprintk(dev, 1, "returning from %s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300602}
603
Hans Verkuil730947b2010-04-10 04:13:53 -0300604static void vivi_stop_generating(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300605{
Hans Verkuil730947b2010-04-10 04:13:53 -0300606 struct vivi_dev *dev = video_drvdata(file);
607 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300608
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300609 dprintk(dev, 1, "%s\n", __func__);
Hans Verkuil730947b2010-04-10 04:13:53 -0300610
611 if (!file->private_data)
612 return;
613 if (!test_and_clear_bit(0, &dev->generating))
614 return;
615
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300616 /* shutdown control thread */
617 if (dma_q->kthread) {
618 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300619 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300620 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300621 videobuf_stop(&dev->vb_vidq);
622 videobuf_mmap_free(&dev->vb_vidq);
623}
624
625static int vivi_is_generating(struct vivi_dev *dev)
626{
627 return test_bit(0, &dev->generating);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300628}
629
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300630/* ------------------------------------------------------------------
631 Videobuf operations
632 ------------------------------------------------------------------*/
633static int
634buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
635{
Hans Verkuil730947b2010-04-10 04:13:53 -0300636 struct vivi_dev *dev = vq->priv_data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300637
Hans Verkuil730947b2010-04-10 04:13:53 -0300638 *size = dev->width * dev->height * 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300639
640 if (0 == *count)
641 *count = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300642
Hans Verkuil730947b2010-04-10 04:13:53 -0300643 while (*size * *count > vid_limit * 1024 * 1024)
644 (*count)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300645
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300646 dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300647 *count, *size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300648
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300649 return 0;
650}
651
Adrian Bunk972c3512006-04-27 21:06:50 -0300652static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300653{
Hans Verkuil730947b2010-04-10 04:13:53 -0300654 struct vivi_dev *dev = vq->priv_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300655
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300656 dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300657
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300658 videobuf_vmalloc_free(&buf->vb);
Mauro Carvalho Chehabfbde31d2008-04-13 14:57:44 -0300659 dprintk(dev, 1, "free_buffer: freed\n");
Brandon Philips0fc06862007-11-06 20:02:36 -0300660 buf->vb.state = VIDEOBUF_NEEDS_INIT;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300661}
662
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300663static int
664buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
665 enum v4l2_field field)
666{
Hans Verkuil730947b2010-04-10 04:13:53 -0300667 struct vivi_dev *dev = vq->priv_data;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300668 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300669 int rc;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300670
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300671 dprintk(dev, 1, "%s, field=%d\n", __func__, field);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300672
Hans Verkuil730947b2010-04-10 04:13:53 -0300673 BUG_ON(NULL == dev->fmt);
Brandon Philips78718e52008-04-02 18:10:59 -0300674
Hans Verkuil730947b2010-04-10 04:13:53 -0300675 if (dev->width < 48 || dev->width > MAX_WIDTH ||
676 dev->height < 32 || dev->height > MAX_HEIGHT)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300677 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300678
Hans Verkuil730947b2010-04-10 04:13:53 -0300679 buf->vb.size = dev->width * dev->height * 2;
680 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300681 return -EINVAL;
682
Brandon Philips78718e52008-04-02 18:10:59 -0300683 /* These properties only change when queue is idle, see s_fmt */
Hans Verkuil730947b2010-04-10 04:13:53 -0300684 buf->fmt = dev->fmt;
685 buf->vb.width = dev->width;
686 buf->vb.height = dev->height;
Brandon Philips78718e52008-04-02 18:10:59 -0300687 buf->vb.field = field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300688
Hans Verkuil730947b2010-04-10 04:13:53 -0300689 precalculate_bars(dev);
690 precalculate_line(dev);
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300691
Brandon Philips0fc06862007-11-06 20:02:36 -0300692 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300693 rc = videobuf_iolock(vq, &buf->vb, NULL);
694 if (rc < 0)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300695 goto fail;
696 }
697
Brandon Philips0fc06862007-11-06 20:02:36 -0300698 buf->vb.state = VIDEOBUF_PREPARED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300699 return 0;
700
701fail:
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300702 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300703 return rc;
704}
705
706static void
707buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
708{
Hans Verkuil730947b2010-04-10 04:13:53 -0300709 struct vivi_dev *dev = vq->priv_data;
710 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300711 struct vivi_dmaqueue *vidq = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300712
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300713 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300714
Brandon Philips78718e52008-04-02 18:10:59 -0300715 buf->vb.state = VIDEOBUF_QUEUED;
716 list_add_tail(&buf->vb.queue, &vidq->active);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300717}
718
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300719static void buffer_release(struct videobuf_queue *vq,
720 struct videobuf_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300721{
Hans Verkuil730947b2010-04-10 04:13:53 -0300722 struct vivi_dev *dev = vq->priv_data;
723 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300724
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300725 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300726
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300727 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300728}
729
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300730static struct videobuf_queue_ops vivi_video_qops = {
731 .buf_setup = buffer_setup,
732 .buf_prepare = buffer_prepare,
733 .buf_queue = buffer_queue,
734 .buf_release = buffer_release,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300735};
736
737/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300738 IOCTL vidioc handling
739 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300740static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300741 struct v4l2_capability *cap)
742{
Hans Verkuil730947b2010-04-10 04:13:53 -0300743 struct vivi_dev *dev = video_drvdata(file);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300744
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300745 strcpy(cap->driver, "vivi");
746 strcpy(cap->card, "vivi");
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300747 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300748 cap->version = VIVI_VERSION;
Hans Verkuil730947b2010-04-10 04:13:53 -0300749 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
750 V4L2_CAP_READWRITE;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300751 return 0;
752}
753
Hans Verkuil78b526a2008-05-28 12:16:41 -0300754static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300755 struct v4l2_fmtdesc *f)
756{
Magnus Dammd891f472008-10-14 12:47:09 -0300757 struct vivi_fmt *fmt;
758
759 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300760 return -EINVAL;
761
Magnus Dammd891f472008-10-14 12:47:09 -0300762 fmt = &formats[f->index];
763
764 strlcpy(f->description, fmt->name, sizeof(f->description));
765 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300766 return 0;
767}
768
Hans Verkuil78b526a2008-05-28 12:16:41 -0300769static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300770 struct v4l2_format *f)
771{
Hans Verkuil730947b2010-04-10 04:13:53 -0300772 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300773
Hans Verkuil730947b2010-04-10 04:13:53 -0300774 f->fmt.pix.width = dev->width;
775 f->fmt.pix.height = dev->height;
776 f->fmt.pix.field = dev->vb_vidq.field;
777 f->fmt.pix.pixelformat = dev->fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300778 f->fmt.pix.bytesperline =
Hans Verkuil730947b2010-04-10 04:13:53 -0300779 (f->fmt.pix.width * dev->fmt->depth) >> 3;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300780 f->fmt.pix.sizeimage =
781 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil730947b2010-04-10 04:13:53 -0300782 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300783}
784
Hans Verkuil78b526a2008-05-28 12:16:41 -0300785static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300786 struct v4l2_format *f)
787{
Hans Verkuil730947b2010-04-10 04:13:53 -0300788 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300789 struct vivi_fmt *fmt;
790 enum v4l2_field field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300791
Magnus Dammd891f472008-10-14 12:47:09 -0300792 fmt = get_format(f);
793 if (!fmt) {
794 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
795 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300796 return -EINVAL;
797 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300798
799 field = f->fmt.pix.field;
800
801 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300802 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300803 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300804 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300805 return -EINVAL;
806 }
807
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300808 f->fmt.pix.field = field;
Hans Verkuil730947b2010-04-10 04:13:53 -0300809 v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
810 &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300811 f->fmt.pix.bytesperline =
812 (f->fmt.pix.width * fmt->depth) >> 3;
813 f->fmt.pix.sizeimage =
814 f->fmt.pix.height * f->fmt.pix.bytesperline;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300815 return 0;
816}
817
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300818static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
819 struct v4l2_format *f)
820{
Hans Verkuil730947b2010-04-10 04:13:53 -0300821 struct vivi_dev *dev = video_drvdata(file);
822 struct videobuf_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300823
Hans Verkuil730947b2010-04-10 04:13:53 -0300824 int ret = vidioc_try_fmt_vid_cap(file, priv, f);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300825 if (ret < 0)
826 return ret;
827
828 mutex_lock(&q->vb_lock);
829
Hans Verkuil730947b2010-04-10 04:13:53 -0300830 if (vivi_is_generating(dev)) {
831 dprintk(dev, 1, "%s device busy\n", __func__);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300832 ret = -EBUSY;
833 goto out;
834 }
835
Hans Verkuil730947b2010-04-10 04:13:53 -0300836 dev->fmt = get_format(f);
837 dev->width = f->fmt.pix.width;
838 dev->height = f->fmt.pix.height;
839 dev->vb_vidq.field = f->fmt.pix.field;
Brandon Philips78718e52008-04-02 18:10:59 -0300840 ret = 0;
841out:
842 mutex_unlock(&q->vb_lock);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300843 return ret;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300844}
845
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300846static int vidioc_reqbufs(struct file *file, void *priv,
847 struct v4l2_requestbuffers *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300848{
Hans Verkuil730947b2010-04-10 04:13:53 -0300849 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300850
Hans Verkuil730947b2010-04-10 04:13:53 -0300851 return videobuf_reqbufs(&dev->vb_vidq, p);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300852}
853
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300854static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300855{
Hans Verkuil730947b2010-04-10 04:13:53 -0300856 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300857
Hans Verkuil730947b2010-04-10 04:13:53 -0300858 return videobuf_querybuf(&dev->vb_vidq, p);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300859}
860
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300861static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300862{
Hans Verkuil730947b2010-04-10 04:13:53 -0300863 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300864
Hans Verkuil730947b2010-04-10 04:13:53 -0300865 return videobuf_qbuf(&dev->vb_vidq, p);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300866}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300867
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300868static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300869{
Hans Verkuil730947b2010-04-10 04:13:53 -0300870 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300871
Hans Verkuil730947b2010-04-10 04:13:53 -0300872 return videobuf_dqbuf(&dev->vb_vidq, p,
873 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300874}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300875
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -0300876#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300877static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300878{
Hans Verkuil730947b2010-04-10 04:13:53 -0300879 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300880
Hans Verkuil730947b2010-04-10 04:13:53 -0300881 return videobuf_cgmbuf(&dev->vb_vidq, mbuf, 8);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300882}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300883#endif
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300884
Adrian Bunkdc46ace2006-06-23 06:42:44 -0300885static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300886{
Hans Verkuil730947b2010-04-10 04:13:53 -0300887 struct vivi_dev *dev = video_drvdata(file);
888 int ret;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300889
Hans Verkuil730947b2010-04-10 04:13:53 -0300890 if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300891 return -EINVAL;
Hans Verkuil730947b2010-04-10 04:13:53 -0300892 ret = videobuf_streamon(&dev->vb_vidq);
893 if (ret)
894 return ret;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300895
Hans Verkuil730947b2010-04-10 04:13:53 -0300896 vivi_start_generating(file);
897 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300898}
899
Adrian Bunkdc46ace2006-06-23 06:42:44 -0300900static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300901{
Hans Verkuil730947b2010-04-10 04:13:53 -0300902 struct vivi_dev *dev = video_drvdata(file);
903 int ret;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300904
Hans Verkuil730947b2010-04-10 04:13:53 -0300905 if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300906 return -EINVAL;
Hans Verkuil730947b2010-04-10 04:13:53 -0300907 ret = videobuf_streamoff(&dev->vb_vidq);
908 if (!ret)
909 vivi_stop_generating(file);
910 return ret;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300911}
912
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300913static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300914{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300915 return 0;
916}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300917
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300918/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300919static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300920 struct v4l2_input *inp)
921{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300922 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300923 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300924
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300925 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -0300926 inp->std = V4L2_STD_525_60;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300927 sprintf(inp->name, "Camera %u", inp->index);
Hans Verkuil730947b2010-04-10 04:13:53 -0300928 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300929}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300930
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300931static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300932{
Hans Verkuil730947b2010-04-10 04:13:53 -0300933 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300934
935 *i = dev->input;
Hans Verkuil730947b2010-04-10 04:13:53 -0300936 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300937}
Hans Verkuil730947b2010-04-10 04:13:53 -0300938
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300939static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300940{
Hans Verkuil730947b2010-04-10 04:13:53 -0300941 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300942
943 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300944 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300945
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300946 dev->input = i;
Hans Verkuil730947b2010-04-10 04:13:53 -0300947 precalculate_bars(dev);
948 precalculate_line(dev);
949 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300950}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300951
Hans Verkuil730947b2010-04-10 04:13:53 -0300952/* --- controls ---------------------------------------------- */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300953static int vidioc_queryctrl(struct file *file, void *priv,
954 struct v4l2_queryctrl *qc)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300955{
Hans Verkuil730947b2010-04-10 04:13:53 -0300956 switch (qc->id) {
957 case V4L2_CID_AUDIO_VOLUME:
958 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 200);
959 case V4L2_CID_BRIGHTNESS:
960 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127);
961 case V4L2_CID_CONTRAST:
962 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 16);
963 case V4L2_CID_SATURATION:
964 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127);
965 case V4L2_CID_HUE:
966 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
967 }
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300968 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300969}
970
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300971static int vidioc_g_ctrl(struct file *file, void *priv,
972 struct v4l2_control *ctrl)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300973{
Hans Verkuil730947b2010-04-10 04:13:53 -0300974 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300975
Hans Verkuil730947b2010-04-10 04:13:53 -0300976 switch (ctrl->id) {
977 case V4L2_CID_AUDIO_VOLUME:
978 ctrl->value = dev->volume;
979 return 0;
980 case V4L2_CID_BRIGHTNESS:
981 ctrl->value = dev->brightness;
982 return 0;
983 case V4L2_CID_CONTRAST:
984 ctrl->value = dev->contrast;
985 return 0;
986 case V4L2_CID_SATURATION:
987 ctrl->value = dev->saturation;
988 return 0;
989 case V4L2_CID_HUE:
990 ctrl->value = dev->hue;
991 return 0;
992 }
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300993 return -EINVAL;
994}
Hans Verkuil730947b2010-04-10 04:13:53 -0300995
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300996static int vidioc_s_ctrl(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300997 struct v4l2_control *ctrl)
998{
Hans Verkuil730947b2010-04-10 04:13:53 -0300999 struct vivi_dev *dev = video_drvdata(file);
1000 struct v4l2_queryctrl qc;
1001 int err;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001002
Hans Verkuil730947b2010-04-10 04:13:53 -03001003 qc.id = ctrl->id;
1004 err = vidioc_queryctrl(file, priv, &qc);
1005 if (err < 0)
1006 return err;
1007 if (ctrl->value < qc.minimum || ctrl->value > qc.maximum)
1008 return -ERANGE;
1009 switch (ctrl->id) {
1010 case V4L2_CID_AUDIO_VOLUME:
1011 dev->volume = ctrl->value;
1012 return 0;
1013 case V4L2_CID_BRIGHTNESS:
1014 dev->brightness = ctrl->value;
1015 return 0;
1016 case V4L2_CID_CONTRAST:
1017 dev->contrast = ctrl->value;
1018 return 0;
1019 case V4L2_CID_SATURATION:
1020 dev->saturation = ctrl->value;
1021 return 0;
1022 case V4L2_CID_HUE:
1023 dev->hue = ctrl->value;
1024 return 0;
1025 }
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001026 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001027}
1028
1029/* ------------------------------------------------------------------
1030 File operations for the device
1031 ------------------------------------------------------------------*/
1032
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001033static ssize_t
1034vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1035{
Hans Verkuil730947b2010-04-10 04:13:53 -03001036 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001037
Hans Verkuil730947b2010-04-10 04:13:53 -03001038 vivi_start_generating(file);
1039 return videobuf_read_stream(&dev->vb_vidq, data, count, ppos, 0,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001040 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001041}
1042
1043static unsigned int
1044vivi_poll(struct file *file, struct poll_table_struct *wait)
1045{
Hans Verkuil730947b2010-04-10 04:13:53 -03001046 struct vivi_dev *dev = video_drvdata(file);
1047 struct videobuf_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001048
Harvey Harrison7e28adb2008-04-08 23:20:00 -03001049 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001050
Hans Verkuil730947b2010-04-10 04:13:53 -03001051 vivi_start_generating(file);
Brandon Philips85c7c70bc2007-09-27 20:55:02 -03001052 return videobuf_poll_stream(file, q, wait);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001053}
1054
Hans Verkuilbec43662008-12-30 06:58:20 -03001055static int vivi_close(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001056{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001057 struct video_device *vdev = video_devdata(file);
Hans Verkuil730947b2010-04-10 04:13:53 -03001058 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001059
Hans Verkuil730947b2010-04-10 04:13:53 -03001060 vivi_stop_generating(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001061
Hans Verkuil730947b2010-04-10 04:13:53 -03001062 dprintk(dev, 1, "close called (dev=%s)\n",
1063 video_device_node_name(vdev));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001064 return 0;
1065}
1066
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001067static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001068{
Hans Verkuil730947b2010-04-10 04:13:53 -03001069 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001070 int ret;
1071
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001072 dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001073
Hans Verkuil730947b2010-04-10 04:13:53 -03001074 ret = videobuf_mmap_mapper(&dev->vb_vidq, vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001075
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001076 dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n",
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001077 (unsigned long)vma->vm_start,
Hans Verkuil730947b2010-04-10 04:13:53 -03001078 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001079 ret);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001080 return ret;
1081}
1082
Hans Verkuilbec43662008-12-30 06:58:20 -03001083static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001084 .owner = THIS_MODULE,
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001085 .release = vivi_close,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001086 .read = vivi_read,
1087 .poll = vivi_poll,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001088 .ioctl = video_ioctl2, /* V4L2 ioctl handler */
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001089 .mmap = vivi_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001090};
1091
Hans Verkuila3998102008-07-21 02:57:38 -03001092static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001093 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001094 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1095 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1096 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1097 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001098 .vidioc_reqbufs = vidioc_reqbufs,
1099 .vidioc_querybuf = vidioc_querybuf,
1100 .vidioc_qbuf = vidioc_qbuf,
1101 .vidioc_dqbuf = vidioc_dqbuf,
1102 .vidioc_s_std = vidioc_s_std,
1103 .vidioc_enum_input = vidioc_enum_input,
1104 .vidioc_g_input = vidioc_g_input,
1105 .vidioc_s_input = vidioc_s_input,
Hans Verkuil730947b2010-04-10 04:13:53 -03001106 .vidioc_streamon = vidioc_streamon,
1107 .vidioc_streamoff = vidioc_streamoff,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001108 .vidioc_queryctrl = vidioc_queryctrl,
1109 .vidioc_g_ctrl = vidioc_g_ctrl,
1110 .vidioc_s_ctrl = vidioc_s_ctrl,
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -03001111#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001112 .vidiocgmbuf = vidiocgmbuf,
1113#endif
Hans Verkuila3998102008-07-21 02:57:38 -03001114};
1115
1116static struct video_device vivi_template = {
1117 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001118 .fops = &vivi_fops,
1119 .ioctl_ops = &vivi_ioctl_ops,
Hans Verkuila3998102008-07-21 02:57:38 -03001120 .release = video_device_release,
1121
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001122 .tvnorms = V4L2_STD_525_60,
Mauro Carvalho Chehabe75f9ce2006-11-20 13:19:20 -03001123 .current_norm = V4L2_STD_NTSC_M,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001124};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001125
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001126/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001127 Initialization and module stuff
1128 ------------------------------------------------------------------*/
1129
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001130static int vivi_release(void)
1131{
1132 struct vivi_dev *dev;
1133 struct list_head *list;
1134
1135 while (!list_empty(&vivi_devlist)) {
1136 list = vivi_devlist.next;
1137 list_del(list);
1138 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1139
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001140 v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
1141 video_device_node_name(dev->vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001142 video_unregister_device(dev->vfd);
1143 v4l2_device_unregister(&dev->v4l2_dev);
1144 kfree(dev);
1145 }
1146
1147 return 0;
1148}
1149
Hans Verkuilc41ee242009-02-14 13:43:44 -03001150static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001151{
1152 struct vivi_dev *dev;
1153 struct video_device *vfd;
Hans Verkuil730947b2010-04-10 04:13:53 -03001154 int ret;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001155
1156 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1157 if (!dev)
1158 return -ENOMEM;
1159
1160 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001161 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001162 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1163 if (ret)
1164 goto free_dev;
1165
Hans Verkuil730947b2010-04-10 04:13:53 -03001166 dev->fmt = &formats[0];
1167 dev->width = 640;
1168 dev->height = 480;
1169 dev->volume = 200;
1170 dev->brightness = 127;
1171 dev->contrast = 16;
1172 dev->saturation = 127;
1173 dev->hue = 0;
1174
1175 videobuf_queue_vmalloc_init(&dev->vb_vidq, &vivi_video_qops,
1176 NULL, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
1177 V4L2_FIELD_INTERLACED,
1178 sizeof(struct vivi_buffer), dev);
1179
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001180 /* init video dma queues */
1181 INIT_LIST_HEAD(&dev->vidq.active);
1182 init_waitqueue_head(&dev->vidq.wq);
1183
1184 /* initialize locks */
1185 spin_lock_init(&dev->slock);
1186 mutex_init(&dev->mutex);
1187
1188 ret = -ENOMEM;
1189 vfd = video_device_alloc();
1190 if (!vfd)
1191 goto unreg_dev;
1192
1193 *vfd = vivi_template;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -03001194 vfd->debug = debug;
Hans Verkuil730947b2010-04-10 04:13:53 -03001195 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001196
1197 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1198 if (ret < 0)
1199 goto rel_vdev;
1200
1201 video_set_drvdata(vfd, dev);
1202
1203 /* Now that everything is fine, let's add it to device list */
1204 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1205
Roel Kluin7de0b872009-12-16 13:06:33 -03001206 if (video_nr != -1)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001207 video_nr++;
1208
1209 dev->vfd = vfd;
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001210 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
1211 video_device_node_name(vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001212 return 0;
1213
1214rel_vdev:
1215 video_device_release(vfd);
1216unreg_dev:
1217 v4l2_device_unregister(&dev->v4l2_dev);
1218free_dev:
1219 kfree(dev);
1220 return ret;
1221}
1222
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001223/* This routine allocates from 1 to n_devs virtual drivers.
1224
1225 The real maximum number of virtual drivers will depend on how many drivers
1226 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001227 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001228 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001229static int __init vivi_init(void)
1230{
Hans Verkuil730947b2010-04-10 04:13:53 -03001231 const struct font_desc *font = find_font("VGA8x16");
Hans Verkuil9185cbf2009-03-06 09:58:12 -03001232 int ret = 0, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001233
Hans Verkuil730947b2010-04-10 04:13:53 -03001234 if (font == NULL) {
1235 printk(KERN_ERR "vivi: could not find font\n");
1236 return -ENODEV;
1237 }
1238 font8x16 = font->data;
1239
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001240 if (n_devs <= 0)
1241 n_devs = 1;
1242
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001243 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001244 ret = vivi_create_instance(i);
1245 if (ret) {
1246 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001247 if (i)
1248 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001249 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001250 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001251 }
1252
1253 if (ret < 0) {
Hans Verkuil730947b2010-04-10 04:13:53 -03001254 printk(KERN_ERR "vivi: error %d while loading driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001255 return ret;
1256 }
1257
1258 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Carl Karsten745271a2008-06-10 00:02:32 -03001259 "Capture Board ver %u.%u.%u successfully loaded.\n",
1260 (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
1261 VIVI_VERSION & 0xFF);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001262
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001263 /* n_devs will reflect the actual number of allocated devices */
1264 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001265
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001266 return ret;
1267}
1268
1269static void __exit vivi_exit(void)
1270{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001271 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001272}
1273
1274module_init(vivi_init);
1275module_exit(vivi_exit);