blob: 9797e5a69265a11cdd18fb9f5c9ddc704e6d2bbc [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>
Randy Dunlap6b46c392010-05-07 15:22:26 -030020#include <linux/slab.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030021#include <linux/font.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030022#include <linux/version.h>
Matthias Kaehlcke51b54022007-07-02 10:19:38 -030023#include <linux/mutex.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030024#include <linux/videodev2.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030025#include <linux/kthread.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030026#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080027#include <linux/freezer.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030028#endif
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030029#include <media/videobuf-vmalloc.h>
30#include <media/v4l2-device.h>
31#include <media/v4l2-ioctl.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030032#include <media/v4l2-common.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030033
Mauro Carvalho Chehab584ce482008-06-10 15:21:49 -030034#define VIVI_MODULE_NAME "vivi"
Carl Karsten745271a2008-06-10 00:02:32 -030035
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030036/* Wake up at about 30 fps */
37#define WAKE_NUMERATOR 30
38#define WAKE_DENOMINATOR 1001
39#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
40
Hans Verkuil730947b2010-04-10 04:13:53 -030041#define MAX_WIDTH 1920
42#define MAX_HEIGHT 1200
43
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030044#define VIVI_MAJOR_VERSION 0
Hans Verkuil730947b2010-04-10 04:13:53 -030045#define VIVI_MINOR_VERSION 7
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030046#define VIVI_RELEASE 0
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -030047#define VIVI_VERSION \
48 KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030049
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030050MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
51MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
52MODULE_LICENSE("Dual BSD/GPL");
53
54static unsigned video_nr = -1;
55module_param(video_nr, uint, 0644);
56MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
57
58static unsigned n_devs = 1;
59module_param(n_devs, uint, 0644);
60MODULE_PARM_DESC(n_devs, "number of video devices to create");
61
62static unsigned debug;
63module_param(debug, uint, 0644);
64MODULE_PARM_DESC(debug, "activates debug info");
65
66static unsigned int vid_limit = 16;
67module_param(vid_limit, uint, 0644);
68MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
69
Hans Verkuil730947b2010-04-10 04:13:53 -030070/* Global font descriptor */
71static const u8 *font8x16;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030072
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030073#define dprintk(dev, level, fmt, arg...) \
74 v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030075
76/* ------------------------------------------------------------------
77 Basic structures
78 ------------------------------------------------------------------*/
79
80struct vivi_fmt {
81 char *name;
82 u32 fourcc; /* v4l2 format id */
83 int depth;
84};
85
Magnus Dammd891f472008-10-14 12:47:09 -030086static struct vivi_fmt formats[] = {
87 {
88 .name = "4:2:2, packed, YUYV",
89 .fourcc = V4L2_PIX_FMT_YUYV,
90 .depth = 16,
91 },
Magnus Dammfca36ba2008-10-14 12:47:25 -030092 {
93 .name = "4:2:2, packed, UYVY",
94 .fourcc = V4L2_PIX_FMT_UYVY,
95 .depth = 16,
96 },
Magnus Dammaeadb5d2008-10-14 12:47:35 -030097 {
98 .name = "RGB565 (LE)",
99 .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
100 .depth = 16,
101 },
102 {
103 .name = "RGB565 (BE)",
104 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
105 .depth = 16,
106 },
Magnus Dammdef52392008-10-14 12:47:43 -0300107 {
108 .name = "RGB555 (LE)",
109 .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
110 .depth = 16,
111 },
112 {
113 .name = "RGB555 (BE)",
114 .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
115 .depth = 16,
116 },
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300117};
118
Magnus Dammd891f472008-10-14 12:47:09 -0300119static struct vivi_fmt *get_format(struct v4l2_format *f)
120{
121 struct vivi_fmt *fmt;
122 unsigned int k;
123
124 for (k = 0; k < ARRAY_SIZE(formats); k++) {
125 fmt = &formats[k];
126 if (fmt->fourcc == f->fmt.pix.pixelformat)
127 break;
128 }
129
130 if (k == ARRAY_SIZE(formats))
131 return NULL;
132
133 return &formats[k];
134}
135
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300136struct sg_to_addr {
137 int pos;
138 struct scatterlist *sg;
139};
140
141/* buffer for one video frame */
142struct vivi_buffer {
143 /* common v4l buffer stuff -- must be first */
144 struct videobuf_buffer vb;
145
146 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300147};
148
149struct vivi_dmaqueue {
150 struct list_head active;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300151
152 /* thread for generating video stream*/
153 struct task_struct *kthread;
154 wait_queue_head_t wq;
155 /* Counters to control fps rate */
156 int frame;
157 int ini_jiffies;
158};
159
160static LIST_HEAD(vivi_devlist);
161
162struct vivi_dev {
163 struct list_head vivi_devlist;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300164 struct v4l2_device v4l2_dev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300165
Hans Verkuil730947b2010-04-10 04:13:53 -0300166 /* controls */
167 int brightness;
168 int contrast;
169 int saturation;
170 int hue;
171 int volume;
172
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300173 spinlock_t slock;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300174 struct mutex mutex;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300175
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300176 /* various device info */
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -0300177 struct video_device *vfd;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300178
179 struct vivi_dmaqueue vidq;
180
181 /* Several counters */
Hans Verkuil730947b2010-04-10 04:13:53 -0300182 unsigned ms;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300183 unsigned long jiffies;
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300184
185 int mv_count; /* Controls bars movement */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300186
187 /* Input Number */
188 int input;
Hans Verkuilc41ee242009-02-14 13:43:44 -0300189
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300190 /* video capture */
191 struct vivi_fmt *fmt;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300192 unsigned int width, height;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300193 struct videobuf_queue vb_vidq;
194
Hans Verkuil730947b2010-04-10 04:13:53 -0300195 unsigned long generating;
196 u8 bars[9][3];
197 u8 line[MAX_WIDTH * 4];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300198};
199
200/* ------------------------------------------------------------------
201 DMA and thread functions
202 ------------------------------------------------------------------*/
203
204/* Bars and Colors should match positions */
205
206enum colors {
207 WHITE,
Hans Verkuil730947b2010-04-10 04:13:53 -0300208 AMBER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300209 CYAN,
210 GREEN,
211 MAGENTA,
212 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300213 BLUE,
214 BLACK,
Hans Verkuil730947b2010-04-10 04:13:53 -0300215 TEXT_BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300216};
217
Hans Verkuil730947b2010-04-10 04:13:53 -0300218/* R G B */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300219#define COLOR_WHITE {204, 204, 204}
Hans Verkuil730947b2010-04-10 04:13:53 -0300220#define COLOR_AMBER {208, 208, 0}
221#define COLOR_CYAN { 0, 206, 206}
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300222#define COLOR_GREEN { 0, 239, 0}
223#define COLOR_MAGENTA {239, 0, 239}
224#define COLOR_RED {205, 0, 0}
225#define COLOR_BLUE { 0, 0, 255}
226#define COLOR_BLACK { 0, 0, 0}
227
228struct bar_std {
Hans Verkuil730947b2010-04-10 04:13:53 -0300229 u8 bar[9][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300230};
231
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300232/* Maximum number of bars are 10 - otherwise, the input print code
233 should be modified */
234static struct bar_std bars[] = {
235 { /* Standard ITU-R color bar sequence */
Hans Verkuil730947b2010-04-10 04:13:53 -0300236 { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN,
237 COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300238 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300239 { COLOR_WHITE, COLOR_AMBER, COLOR_BLACK, COLOR_WHITE,
240 COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, COLOR_AMBER, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300241 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300242 { COLOR_WHITE, COLOR_CYAN, COLOR_BLACK, COLOR_WHITE,
243 COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, COLOR_CYAN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300244 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300245 { COLOR_WHITE, COLOR_GREEN, COLOR_BLACK, COLOR_WHITE,
246 COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, COLOR_GREEN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300247 },
248};
249
250#define NUM_INPUTS ARRAY_SIZE(bars)
251
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300252#define TO_Y(r, g, b) \
253 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300254/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300255#define TO_V(r, g, b) \
256 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300257/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300258#define TO_U(r, g, b) \
259 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300260
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300261/* precalculate color bar values to speed up rendering */
Hans Verkuil730947b2010-04-10 04:13:53 -0300262static void precalculate_bars(struct vivi_dev *dev)
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300263{
Hans Verkuil730947b2010-04-10 04:13:53 -0300264 u8 r, g, b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300265 int k, is_yuv;
266
Hans Verkuil730947b2010-04-10 04:13:53 -0300267 for (k = 0; k < 9; k++) {
268 r = bars[dev->input].bar[k][0];
269 g = bars[dev->input].bar[k][1];
270 b = bars[dev->input].bar[k][2];
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300271 is_yuv = 0;
272
Hans Verkuil730947b2010-04-10 04:13:53 -0300273 switch (dev->fmt->fourcc) {
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300274 case V4L2_PIX_FMT_YUYV:
275 case V4L2_PIX_FMT_UYVY:
276 is_yuv = 1;
277 break;
278 case V4L2_PIX_FMT_RGB565:
279 case V4L2_PIX_FMT_RGB565X:
280 r >>= 3;
281 g >>= 2;
282 b >>= 3;
283 break;
284 case V4L2_PIX_FMT_RGB555:
285 case V4L2_PIX_FMT_RGB555X:
286 r >>= 3;
287 g >>= 3;
288 b >>= 3;
289 break;
290 }
291
292 if (is_yuv) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300293 dev->bars[k][0] = TO_Y(r, g, b); /* Luma */
294 dev->bars[k][1] = TO_U(r, g, b); /* Cb */
295 dev->bars[k][2] = TO_V(r, g, b); /* Cr */
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300296 } else {
Hans Verkuil730947b2010-04-10 04:13:53 -0300297 dev->bars[k][0] = r;
298 dev->bars[k][1] = g;
299 dev->bars[k][2] = b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300300 }
301 }
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300302}
303
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300304#define TSTAMP_MIN_Y 24
305#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
306#define TSTAMP_INPUT_X 10
307#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300308
Hans Verkuil730947b2010-04-10 04:13:53 -0300309static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos)
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300310{
Hans Verkuil730947b2010-04-10 04:13:53 -0300311 u8 r_y, g_u, b_v;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300312 int color;
Hans Verkuil730947b2010-04-10 04:13:53 -0300313 u8 *p;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300314
Hans Verkuil730947b2010-04-10 04:13:53 -0300315 r_y = dev->bars[colorpos][0]; /* R or precalculated Y */
316 g_u = dev->bars[colorpos][1]; /* G or precalculated U */
317 b_v = dev->bars[colorpos][2]; /* B or precalculated V */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300318
319 for (color = 0; color < 4; color++) {
320 p = buf + color;
321
Hans Verkuil730947b2010-04-10 04:13:53 -0300322 switch (dev->fmt->fourcc) {
Magnus Dammd891f472008-10-14 12:47:09 -0300323 case V4L2_PIX_FMT_YUYV:
324 switch (color) {
325 case 0:
326 case 2:
327 *p = r_y;
328 break;
329 case 1:
330 *p = g_u;
331 break;
332 case 3:
333 *p = b_v;
334 break;
335 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300336 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300337 case V4L2_PIX_FMT_UYVY:
338 switch (color) {
339 case 1:
340 case 3:
341 *p = r_y;
342 break;
343 case 0:
344 *p = g_u;
345 break;
346 case 2:
347 *p = b_v;
348 break;
349 }
350 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300351 case V4L2_PIX_FMT_RGB565:
352 switch (color) {
353 case 0:
354 case 2:
355 *p = (g_u << 5) | b_v;
356 break;
357 case 1:
358 case 3:
359 *p = (r_y << 3) | (g_u >> 3);
360 break;
361 }
362 break;
363 case V4L2_PIX_FMT_RGB565X:
364 switch (color) {
365 case 0:
366 case 2:
367 *p = (r_y << 3) | (g_u >> 3);
368 break;
369 case 1:
370 case 3:
371 *p = (g_u << 5) | b_v;
372 break;
373 }
374 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300375 case V4L2_PIX_FMT_RGB555:
376 switch (color) {
377 case 0:
378 case 2:
379 *p = (g_u << 5) | b_v;
380 break;
381 case 1:
382 case 3:
383 *p = (r_y << 2) | (g_u >> 3);
384 break;
385 }
386 break;
387 case V4L2_PIX_FMT_RGB555X:
388 switch (color) {
389 case 0:
390 case 2:
391 *p = (r_y << 2) | (g_u >> 3);
392 break;
393 case 1:
394 case 3:
395 *p = (g_u << 5) | b_v;
396 break;
397 }
398 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300399 }
400 }
401}
402
Hans Verkuil730947b2010-04-10 04:13:53 -0300403static void precalculate_line(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300404{
Hans Verkuil730947b2010-04-10 04:13:53 -0300405 int w;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300406
Hans Verkuil730947b2010-04-10 04:13:53 -0300407 for (w = 0; w < dev->width * 2; w += 2) {
408 int colorpos = (w / (dev->width / 8) % 8);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300409
Hans Verkuil730947b2010-04-10 04:13:53 -0300410 gen_twopix(dev, dev->line + w * 2, colorpos);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300411 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300412}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300413
Hans Verkuil730947b2010-04-10 04:13:53 -0300414static void gen_text(struct vivi_dev *dev, char *basep,
415 int y, int x, char *text)
416{
417 int line;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300418
Hans Verkuil730947b2010-04-10 04:13:53 -0300419 /* Checks if it is possible to show string */
420 if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width)
421 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300422
423 /* Print stream time */
Hans Verkuil730947b2010-04-10 04:13:53 -0300424 for (line = y; line < y + 16; line++) {
425 int j = 0;
426 char *pos = basep + line * dev->width * 2 + x * 2;
427 char *s;
428
429 for (s = text; *s; s++) {
430 u8 chr = font8x16[*s * 16 + line - y];
431 int i;
432
433 for (i = 0; i < 7; i++, j++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300434 /* Draw white font on black background */
Hans Verkuil730947b2010-04-10 04:13:53 -0300435 if (chr & (1 << (7 - i)))
436 gen_twopix(dev, pos + j * 2, WHITE);
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300437 else
Hans Verkuil730947b2010-04-10 04:13:53 -0300438 gen_twopix(dev, pos + j * 2, TEXT_BLACK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300439 }
440 }
441 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300442}
Brandon Philips78718e52008-04-02 18:10:59 -0300443
Hans Verkuil730947b2010-04-10 04:13:53 -0300444static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300445{
Hans Verkuil730947b2010-04-10 04:13:53 -0300446 int hmax = buf->vb.height;
447 int wmax = buf->vb.width;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300448 struct timeval ts;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300449 void *vbuf = videobuf_to_vmalloc(&buf->vb);
Hans Verkuil730947b2010-04-10 04:13:53 -0300450 unsigned ms;
451 char str[100];
452 int h, line = 1;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300453
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300454 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300455 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300456
Hans Verkuil730947b2010-04-10 04:13:53 -0300457 for (h = 0; h < hmax; h++)
458 memcpy(vbuf + h * wmax * 2, dev->line + (dev->mv_count % wmax) * 2, wmax * 2);
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300459
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300460 /* Updates stream time */
461
Hans Verkuil730947b2010-04-10 04:13:53 -0300462 dev->ms += jiffies_to_msecs(jiffies - dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300463 dev->jiffies = jiffies;
Hans Verkuil730947b2010-04-10 04:13:53 -0300464 ms = dev->ms;
465 snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d ",
466 (ms / (60 * 60 * 1000)) % 24,
467 (ms / (60 * 1000)) % 60,
468 (ms / 1000) % 60,
469 ms % 1000);
470 gen_text(dev, vbuf, line++ * 16, 16, str);
471 snprintf(str, sizeof(str), " %dx%d, input %d ",
472 dev->width, dev->height, dev->input);
473 gen_text(dev, vbuf, line++ * 16, 16, str);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300474
Hans Verkuil730947b2010-04-10 04:13:53 -0300475 snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
476 dev->brightness,
477 dev->contrast,
478 dev->saturation,
479 dev->hue);
480 gen_text(dev, vbuf, line++ * 16, 16, str);
481 snprintf(str, sizeof(str), " volume %3d ", dev->volume);
482 gen_text(dev, vbuf, line++ * 16, 16, str);
483
484 dev->mv_count += 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300485
486 /* Advice that buffer was filled */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300487 buf->vb.field_count++;
488 do_gettimeofday(&ts);
489 buf->vb.ts = ts;
Brandon Philips78718e52008-04-02 18:10:59 -0300490 buf->vb.state = VIDEOBUF_DONE;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300491}
492
Hans Verkuil730947b2010-04-10 04:13:53 -0300493static void vivi_thread_tick(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300494{
Brandon Philips78718e52008-04-02 18:10:59 -0300495 struct vivi_dmaqueue *dma_q = &dev->vidq;
Hans Verkuil730947b2010-04-10 04:13:53 -0300496 struct vivi_buffer *buf;
Brandon Philips78718e52008-04-02 18:10:59 -0300497 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300498
Brandon Philips78718e52008-04-02 18:10:59 -0300499 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300500
Brandon Philips78718e52008-04-02 18:10:59 -0300501 spin_lock_irqsave(&dev->slock, flags);
502 if (list_empty(&dma_q->active)) {
503 dprintk(dev, 1, "No active queue to serve\n");
504 goto unlock;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300505 }
Brandon Philips78718e52008-04-02 18:10:59 -0300506
507 buf = list_entry(dma_q->active.next,
508 struct vivi_buffer, vb.queue);
509
510 /* Nobody is waiting on this buffer, return */
511 if (!waitqueue_active(&buf->vb.done))
512 goto unlock;
513
514 list_del(&buf->vb.queue);
515
516 do_gettimeofday(&buf->vb.ts);
517
518 /* Fill buffer */
Hans Verkuil730947b2010-04-10 04:13:53 -0300519 vivi_fillbuff(dev, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300520 dprintk(dev, 1, "filled buffer %p\n", buf);
521
522 wake_up(&buf->vb.done);
523 dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
524unlock:
525 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300526}
527
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300528#define frames_to_ms(frames) \
529 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
530
Hans Verkuil730947b2010-04-10 04:13:53 -0300531static void vivi_sleep(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300532{
Brandon Philips78718e52008-04-02 18:10:59 -0300533 struct vivi_dmaqueue *dma_q = &dev->vidq;
534 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300535 DECLARE_WAITQUEUE(wait, current);
536
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300537 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300538 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300539
540 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300541 if (kthread_should_stop())
542 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300543
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300544 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300545 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300546
Hans Verkuil730947b2010-04-10 04:13:53 -0300547 vivi_thread_tick(dev);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300548
549 schedule_timeout_interruptible(timeout);
550
551stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300552 remove_wait_queue(&dma_q->wq, &wait);
553 try_to_freeze();
554}
555
Adrian Bunk972c3512006-04-27 21:06:50 -0300556static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300557{
Hans Verkuil730947b2010-04-10 04:13:53 -0300558 struct vivi_dev *dev = data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300559
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300560 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300561
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700562 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300563
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300564 for (;;) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300565 vivi_sleep(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300566
567 if (kthread_should_stop())
568 break;
569 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300570 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300571 return 0;
572}
573
Hans Verkuil730947b2010-04-10 04:13:53 -0300574static void vivi_start_generating(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300575{
Hans Verkuil730947b2010-04-10 04:13:53 -0300576 struct vivi_dev *dev = video_drvdata(file);
Brandon Philips78718e52008-04-02 18:10:59 -0300577 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300578
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300579 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300580
Hans Verkuil730947b2010-04-10 04:13:53 -0300581 if (test_and_set_bit(0, &dev->generating))
582 return;
583 file->private_data = dev;
584
585 /* Resets frame counters */
586 dev->ms = 0;
587 dev->mv_count = 0;
588 dev->jiffies = jiffies;
589
590 dma_q->frame = 0;
591 dma_q->ini_jiffies = jiffies;
592 dma_q->kthread = kthread_run(vivi_thread, dev, dev->v4l2_dev.name);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300593
Akinobu Mita054afee2006-12-20 10:04:00 -0300594 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300595 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Hans Verkuil730947b2010-04-10 04:13:53 -0300596 clear_bit(0, &dev->generating);
597 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300598 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300599 /* Wakes thread */
600 wake_up_interruptible(&dma_q->wq);
601
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300602 dprintk(dev, 1, "returning from %s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300603}
604
Hans Verkuil730947b2010-04-10 04:13:53 -0300605static void vivi_stop_generating(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300606{
Hans Verkuil730947b2010-04-10 04:13:53 -0300607 struct vivi_dev *dev = video_drvdata(file);
608 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300609
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300610 dprintk(dev, 1, "%s\n", __func__);
Hans Verkuil730947b2010-04-10 04:13:53 -0300611
612 if (!file->private_data)
613 return;
614 if (!test_and_clear_bit(0, &dev->generating))
615 return;
616
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300617 /* shutdown control thread */
618 if (dma_q->kthread) {
619 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300620 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300621 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300622 videobuf_stop(&dev->vb_vidq);
623 videobuf_mmap_free(&dev->vb_vidq);
624}
625
626static int vivi_is_generating(struct vivi_dev *dev)
627{
628 return test_bit(0, &dev->generating);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300629}
630
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300631/* ------------------------------------------------------------------
632 Videobuf operations
633 ------------------------------------------------------------------*/
634static int
635buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
636{
Hans Verkuil730947b2010-04-10 04:13:53 -0300637 struct vivi_dev *dev = vq->priv_data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300638
Hans Verkuil730947b2010-04-10 04:13:53 -0300639 *size = dev->width * dev->height * 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300640
641 if (0 == *count)
642 *count = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300643
Hans Verkuil730947b2010-04-10 04:13:53 -0300644 while (*size * *count > vid_limit * 1024 * 1024)
645 (*count)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300646
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300647 dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300648 *count, *size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300649
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300650 return 0;
651}
652
Adrian Bunk972c3512006-04-27 21:06:50 -0300653static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300654{
Hans Verkuil730947b2010-04-10 04:13:53 -0300655 struct vivi_dev *dev = vq->priv_data;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300656
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300657 dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300658
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300659 videobuf_vmalloc_free(&buf->vb);
Mauro Carvalho Chehabfbde31d2008-04-13 14:57:44 -0300660 dprintk(dev, 1, "free_buffer: freed\n");
Brandon Philips0fc06862007-11-06 20:02:36 -0300661 buf->vb.state = VIDEOBUF_NEEDS_INIT;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300662}
663
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300664static int
665buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
666 enum v4l2_field field)
667{
Hans Verkuil730947b2010-04-10 04:13:53 -0300668 struct vivi_dev *dev = vq->priv_data;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300669 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300670 int rc;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300671
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300672 dprintk(dev, 1, "%s, field=%d\n", __func__, field);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300673
Hans Verkuil730947b2010-04-10 04:13:53 -0300674 BUG_ON(NULL == dev->fmt);
Brandon Philips78718e52008-04-02 18:10:59 -0300675
Hans Verkuil730947b2010-04-10 04:13:53 -0300676 if (dev->width < 48 || dev->width > MAX_WIDTH ||
677 dev->height < 32 || dev->height > MAX_HEIGHT)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300678 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300679
Hans Verkuil730947b2010-04-10 04:13:53 -0300680 buf->vb.size = dev->width * dev->height * 2;
681 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300682 return -EINVAL;
683
Brandon Philips78718e52008-04-02 18:10:59 -0300684 /* These properties only change when queue is idle, see s_fmt */
Hans Verkuil730947b2010-04-10 04:13:53 -0300685 buf->fmt = dev->fmt;
686 buf->vb.width = dev->width;
687 buf->vb.height = dev->height;
Brandon Philips78718e52008-04-02 18:10:59 -0300688 buf->vb.field = field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300689
Hans Verkuil730947b2010-04-10 04:13:53 -0300690 precalculate_bars(dev);
691 precalculate_line(dev);
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300692
Brandon Philips0fc06862007-11-06 20:02:36 -0300693 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300694 rc = videobuf_iolock(vq, &buf->vb, NULL);
695 if (rc < 0)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300696 goto fail;
697 }
698
Brandon Philips0fc06862007-11-06 20:02:36 -0300699 buf->vb.state = VIDEOBUF_PREPARED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300700 return 0;
701
702fail:
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300703 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300704 return rc;
705}
706
707static void
708buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
709{
Hans Verkuil730947b2010-04-10 04:13:53 -0300710 struct vivi_dev *dev = vq->priv_data;
711 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300712 struct vivi_dmaqueue *vidq = &dev->vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300713
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300714 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300715
Brandon Philips78718e52008-04-02 18:10:59 -0300716 buf->vb.state = VIDEOBUF_QUEUED;
717 list_add_tail(&buf->vb.queue, &vidq->active);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300718}
719
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300720static void buffer_release(struct videobuf_queue *vq,
721 struct videobuf_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300722{
Hans Verkuil730947b2010-04-10 04:13:53 -0300723 struct vivi_dev *dev = vq->priv_data;
724 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300725
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300726 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300727
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300728 free_buffer(vq, buf);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300729}
730
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300731static struct videobuf_queue_ops vivi_video_qops = {
732 .buf_setup = buffer_setup,
733 .buf_prepare = buffer_prepare,
734 .buf_queue = buffer_queue,
735 .buf_release = buffer_release,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300736};
737
738/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300739 IOCTL vidioc handling
740 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300741static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300742 struct v4l2_capability *cap)
743{
Hans Verkuil730947b2010-04-10 04:13:53 -0300744 struct vivi_dev *dev = video_drvdata(file);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300745
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300746 strcpy(cap->driver, "vivi");
747 strcpy(cap->card, "vivi");
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300748 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300749 cap->version = VIVI_VERSION;
Hans Verkuil730947b2010-04-10 04:13:53 -0300750 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
751 V4L2_CAP_READWRITE;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300752 return 0;
753}
754
Hans Verkuil78b526a2008-05-28 12:16:41 -0300755static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300756 struct v4l2_fmtdesc *f)
757{
Magnus Dammd891f472008-10-14 12:47:09 -0300758 struct vivi_fmt *fmt;
759
760 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300761 return -EINVAL;
762
Magnus Dammd891f472008-10-14 12:47:09 -0300763 fmt = &formats[f->index];
764
765 strlcpy(f->description, fmt->name, sizeof(f->description));
766 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300767 return 0;
768}
769
Hans Verkuil78b526a2008-05-28 12:16:41 -0300770static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300771 struct v4l2_format *f)
772{
Hans Verkuil730947b2010-04-10 04:13:53 -0300773 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300774
Hans Verkuil730947b2010-04-10 04:13:53 -0300775 f->fmt.pix.width = dev->width;
776 f->fmt.pix.height = dev->height;
777 f->fmt.pix.field = dev->vb_vidq.field;
778 f->fmt.pix.pixelformat = dev->fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300779 f->fmt.pix.bytesperline =
Hans Verkuil730947b2010-04-10 04:13:53 -0300780 (f->fmt.pix.width * dev->fmt->depth) >> 3;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300781 f->fmt.pix.sizeimage =
782 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil730947b2010-04-10 04:13:53 -0300783 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300784}
785
Hans Verkuil78b526a2008-05-28 12:16:41 -0300786static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300787 struct v4l2_format *f)
788{
Hans Verkuil730947b2010-04-10 04:13:53 -0300789 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300790 struct vivi_fmt *fmt;
791 enum v4l2_field field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300792
Magnus Dammd891f472008-10-14 12:47:09 -0300793 fmt = get_format(f);
794 if (!fmt) {
795 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
796 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300797 return -EINVAL;
798 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300799
800 field = f->fmt.pix.field;
801
802 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300803 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300804 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300805 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300806 return -EINVAL;
807 }
808
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300809 f->fmt.pix.field = field;
Hans Verkuil730947b2010-04-10 04:13:53 -0300810 v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
811 &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300812 f->fmt.pix.bytesperline =
813 (f->fmt.pix.width * fmt->depth) >> 3;
814 f->fmt.pix.sizeimage =
815 f->fmt.pix.height * f->fmt.pix.bytesperline;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300816 return 0;
817}
818
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300819static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
820 struct v4l2_format *f)
821{
Hans Verkuil730947b2010-04-10 04:13:53 -0300822 struct vivi_dev *dev = video_drvdata(file);
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
Hans Verkuil730947b2010-04-10 04:13:53 -0300828 if (vivi_is_generating(dev)) {
829 dprintk(dev, 1, "%s device busy\n", __func__);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300830 ret = -EBUSY;
831 goto out;
832 }
833
Hans Verkuil730947b2010-04-10 04:13:53 -0300834 dev->fmt = get_format(f);
835 dev->width = f->fmt.pix.width;
836 dev->height = f->fmt.pix.height;
837 dev->vb_vidq.field = f->fmt.pix.field;
Brandon Philips78718e52008-04-02 18:10:59 -0300838 ret = 0;
839out:
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300840 return ret;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300841}
842
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300843static int vidioc_reqbufs(struct file *file, void *priv,
844 struct v4l2_requestbuffers *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300845{
Hans Verkuil730947b2010-04-10 04:13:53 -0300846 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300847
Hans Verkuil730947b2010-04-10 04:13:53 -0300848 return videobuf_reqbufs(&dev->vb_vidq, p);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300849}
850
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300851static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300852{
Hans Verkuil730947b2010-04-10 04:13:53 -0300853 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300854
Hans Verkuil730947b2010-04-10 04:13:53 -0300855 return videobuf_querybuf(&dev->vb_vidq, p);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300856}
857
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300858static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300859{
Hans Verkuil730947b2010-04-10 04:13:53 -0300860 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300861
Hans Verkuil730947b2010-04-10 04:13:53 -0300862 return videobuf_qbuf(&dev->vb_vidq, p);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300863}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300864
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300865static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300866{
Hans Verkuil730947b2010-04-10 04:13:53 -0300867 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300868
Hans Verkuil730947b2010-04-10 04:13:53 -0300869 return videobuf_dqbuf(&dev->vb_vidq, p,
870 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300871}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300872
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -0300873#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300874static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300875{
Hans Verkuil730947b2010-04-10 04:13:53 -0300876 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300877
Hans Verkuil730947b2010-04-10 04:13:53 -0300878 return videobuf_cgmbuf(&dev->vb_vidq, mbuf, 8);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300879}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300880#endif
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300881
Adrian Bunkdc46ace2006-06-23 06:42:44 -0300882static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300883{
Hans Verkuil730947b2010-04-10 04:13:53 -0300884 struct vivi_dev *dev = video_drvdata(file);
885 int ret;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300886
Hans Verkuil730947b2010-04-10 04:13:53 -0300887 if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300888 return -EINVAL;
Hans Verkuil730947b2010-04-10 04:13:53 -0300889 ret = videobuf_streamon(&dev->vb_vidq);
890 if (ret)
891 return ret;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300892
Hans Verkuil730947b2010-04-10 04:13:53 -0300893 vivi_start_generating(file);
894 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300895}
896
Adrian Bunkdc46ace2006-06-23 06:42:44 -0300897static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300898{
Hans Verkuil730947b2010-04-10 04:13:53 -0300899 struct vivi_dev *dev = video_drvdata(file);
900 int ret;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300901
Hans Verkuil730947b2010-04-10 04:13:53 -0300902 if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300903 return -EINVAL;
Hans Verkuil730947b2010-04-10 04:13:53 -0300904 ret = videobuf_streamoff(&dev->vb_vidq);
905 if (!ret)
906 vivi_stop_generating(file);
907 return ret;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300908}
909
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300910static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300911{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300912 return 0;
913}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300914
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300915/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300916static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300917 struct v4l2_input *inp)
918{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300919 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300920 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300921
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300922 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -0300923 inp->std = V4L2_STD_525_60;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300924 sprintf(inp->name, "Camera %u", inp->index);
Hans Verkuil730947b2010-04-10 04:13:53 -0300925 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300926}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300927
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300928static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300929{
Hans Verkuil730947b2010-04-10 04:13:53 -0300930 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300931
932 *i = dev->input;
Hans Verkuil730947b2010-04-10 04:13:53 -0300933 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300934}
Hans Verkuil730947b2010-04-10 04:13:53 -0300935
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300936static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300937{
Hans Verkuil730947b2010-04-10 04:13:53 -0300938 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300939
940 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300941 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300942
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300943 dev->input = i;
Hans Verkuil730947b2010-04-10 04:13:53 -0300944 precalculate_bars(dev);
945 precalculate_line(dev);
946 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300947}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300948
Hans Verkuil730947b2010-04-10 04:13:53 -0300949/* --- controls ---------------------------------------------- */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300950static int vidioc_queryctrl(struct file *file, void *priv,
951 struct v4l2_queryctrl *qc)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300952{
Hans Verkuil730947b2010-04-10 04:13:53 -0300953 switch (qc->id) {
954 case V4L2_CID_AUDIO_VOLUME:
955 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 200);
956 case V4L2_CID_BRIGHTNESS:
957 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127);
958 case V4L2_CID_CONTRAST:
959 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 16);
960 case V4L2_CID_SATURATION:
961 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127);
962 case V4L2_CID_HUE:
963 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
964 }
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300965 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300966}
967
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300968static int vidioc_g_ctrl(struct file *file, void *priv,
969 struct v4l2_control *ctrl)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300970{
Hans Verkuil730947b2010-04-10 04:13:53 -0300971 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300972
Hans Verkuil730947b2010-04-10 04:13:53 -0300973 switch (ctrl->id) {
974 case V4L2_CID_AUDIO_VOLUME:
975 ctrl->value = dev->volume;
976 return 0;
977 case V4L2_CID_BRIGHTNESS:
978 ctrl->value = dev->brightness;
979 return 0;
980 case V4L2_CID_CONTRAST:
981 ctrl->value = dev->contrast;
982 return 0;
983 case V4L2_CID_SATURATION:
984 ctrl->value = dev->saturation;
985 return 0;
986 case V4L2_CID_HUE:
987 ctrl->value = dev->hue;
988 return 0;
989 }
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300990 return -EINVAL;
991}
Hans Verkuil730947b2010-04-10 04:13:53 -0300992
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300993static int vidioc_s_ctrl(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300994 struct v4l2_control *ctrl)
995{
Hans Verkuil730947b2010-04-10 04:13:53 -0300996 struct vivi_dev *dev = video_drvdata(file);
997 struct v4l2_queryctrl qc;
998 int err;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300999
Hans Verkuil730947b2010-04-10 04:13:53 -03001000 qc.id = ctrl->id;
1001 err = vidioc_queryctrl(file, priv, &qc);
1002 if (err < 0)
1003 return err;
1004 if (ctrl->value < qc.minimum || ctrl->value > qc.maximum)
1005 return -ERANGE;
1006 switch (ctrl->id) {
1007 case V4L2_CID_AUDIO_VOLUME:
1008 dev->volume = ctrl->value;
1009 return 0;
1010 case V4L2_CID_BRIGHTNESS:
1011 dev->brightness = ctrl->value;
1012 return 0;
1013 case V4L2_CID_CONTRAST:
1014 dev->contrast = ctrl->value;
1015 return 0;
1016 case V4L2_CID_SATURATION:
1017 dev->saturation = ctrl->value;
1018 return 0;
1019 case V4L2_CID_HUE:
1020 dev->hue = ctrl->value;
1021 return 0;
1022 }
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001023 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001024}
1025
1026/* ------------------------------------------------------------------
1027 File operations for the device
1028 ------------------------------------------------------------------*/
1029
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001030static ssize_t
1031vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1032{
Hans Verkuil730947b2010-04-10 04:13:53 -03001033 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001034
Hans Verkuil730947b2010-04-10 04:13:53 -03001035 vivi_start_generating(file);
1036 return videobuf_read_stream(&dev->vb_vidq, data, count, ppos, 0,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001037 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001038}
1039
1040static unsigned int
1041vivi_poll(struct file *file, struct poll_table_struct *wait)
1042{
Hans Verkuil730947b2010-04-10 04:13:53 -03001043 struct vivi_dev *dev = video_drvdata(file);
1044 struct videobuf_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001045
Harvey Harrison7e28adb2008-04-08 23:20:00 -03001046 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001047
Hans Verkuil730947b2010-04-10 04:13:53 -03001048 vivi_start_generating(file);
Brandon Philips85c7c70bc2007-09-27 20:55:02 -03001049 return videobuf_poll_stream(file, q, wait);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001050}
1051
Hans Verkuilbec43662008-12-30 06:58:20 -03001052static int vivi_close(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001053{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001054 struct video_device *vdev = video_devdata(file);
Hans Verkuil730947b2010-04-10 04:13:53 -03001055 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001056
Hans Verkuil730947b2010-04-10 04:13:53 -03001057 vivi_stop_generating(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001058
Hans Verkuil730947b2010-04-10 04:13:53 -03001059 dprintk(dev, 1, "close called (dev=%s)\n",
1060 video_device_node_name(vdev));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001061 return 0;
1062}
1063
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001064static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001065{
Hans Verkuil730947b2010-04-10 04:13:53 -03001066 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001067 int ret;
1068
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001069 dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001070
Hans Verkuil730947b2010-04-10 04:13:53 -03001071 ret = videobuf_mmap_mapper(&dev->vb_vidq, vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001072
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001073 dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n",
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001074 (unsigned long)vma->vm_start,
Hans Verkuil730947b2010-04-10 04:13:53 -03001075 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001076 ret);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001077 return ret;
1078}
1079
Hans Verkuilbec43662008-12-30 06:58:20 -03001080static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001081 .owner = THIS_MODULE,
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001082 .release = vivi_close,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001083 .read = vivi_read,
1084 .poll = vivi_poll,
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001085 .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001086 .mmap = vivi_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001087};
1088
Hans Verkuila3998102008-07-21 02:57:38 -03001089static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001090 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001091 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1092 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1093 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1094 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001095 .vidioc_reqbufs = vidioc_reqbufs,
1096 .vidioc_querybuf = vidioc_querybuf,
1097 .vidioc_qbuf = vidioc_qbuf,
1098 .vidioc_dqbuf = vidioc_dqbuf,
1099 .vidioc_s_std = vidioc_s_std,
1100 .vidioc_enum_input = vidioc_enum_input,
1101 .vidioc_g_input = vidioc_g_input,
1102 .vidioc_s_input = vidioc_s_input,
Hans Verkuil730947b2010-04-10 04:13:53 -03001103 .vidioc_streamon = vidioc_streamon,
1104 .vidioc_streamoff = vidioc_streamoff,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001105 .vidioc_queryctrl = vidioc_queryctrl,
1106 .vidioc_g_ctrl = vidioc_g_ctrl,
1107 .vidioc_s_ctrl = vidioc_s_ctrl,
Mauro Carvalho Chehab0dfa9ab2006-08-08 09:10:10 -03001108#ifdef CONFIG_VIDEO_V4L1_COMPAT
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001109 .vidiocgmbuf = vidiocgmbuf,
1110#endif
Hans Verkuila3998102008-07-21 02:57:38 -03001111};
1112
1113static struct video_device vivi_template = {
1114 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001115 .fops = &vivi_fops,
1116 .ioctl_ops = &vivi_ioctl_ops,
Hans Verkuila3998102008-07-21 02:57:38 -03001117 .release = video_device_release,
1118
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001119 .tvnorms = V4L2_STD_525_60,
Mauro Carvalho Chehabe75f9ce2006-11-20 13:19:20 -03001120 .current_norm = V4L2_STD_NTSC_M,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001121};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001122
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001123/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001124 Initialization and module stuff
1125 ------------------------------------------------------------------*/
1126
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001127static int vivi_release(void)
1128{
1129 struct vivi_dev *dev;
1130 struct list_head *list;
1131
1132 while (!list_empty(&vivi_devlist)) {
1133 list = vivi_devlist.next;
1134 list_del(list);
1135 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1136
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001137 v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
1138 video_device_node_name(dev->vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001139 video_unregister_device(dev->vfd);
1140 v4l2_device_unregister(&dev->v4l2_dev);
1141 kfree(dev);
1142 }
1143
1144 return 0;
1145}
1146
Hans Verkuilc41ee242009-02-14 13:43:44 -03001147static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001148{
1149 struct vivi_dev *dev;
1150 struct video_device *vfd;
Hans Verkuil730947b2010-04-10 04:13:53 -03001151 int ret;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001152
1153 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1154 if (!dev)
1155 return -ENOMEM;
1156
1157 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001158 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001159 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1160 if (ret)
1161 goto free_dev;
1162
Hans Verkuil730947b2010-04-10 04:13:53 -03001163 dev->fmt = &formats[0];
1164 dev->width = 640;
1165 dev->height = 480;
1166 dev->volume = 200;
1167 dev->brightness = 127;
1168 dev->contrast = 16;
1169 dev->saturation = 127;
1170 dev->hue = 0;
1171
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001172 /* initialize locks */
1173 spin_lock_init(&dev->slock);
1174 mutex_init(&dev->mutex);
1175
Hans Verkuil730947b2010-04-10 04:13:53 -03001176 videobuf_queue_vmalloc_init(&dev->vb_vidq, &vivi_video_qops,
1177 NULL, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
1178 V4L2_FIELD_INTERLACED,
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001179 sizeof(struct vivi_buffer), dev, &dev->mutex);
Hans Verkuil730947b2010-04-10 04:13:53 -03001180
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001181 /* init video dma queues */
1182 INIT_LIST_HEAD(&dev->vidq.active);
1183 init_waitqueue_head(&dev->vidq.wq);
1184
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001185 ret = -ENOMEM;
1186 vfd = video_device_alloc();
1187 if (!vfd)
1188 goto unreg_dev;
1189
1190 *vfd = vivi_template;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -03001191 vfd->debug = debug;
Hans Verkuil730947b2010-04-10 04:13:53 -03001192 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001193 vfd->lock = &dev->mutex;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001194
1195 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1196 if (ret < 0)
1197 goto rel_vdev;
1198
1199 video_set_drvdata(vfd, dev);
1200
1201 /* Now that everything is fine, let's add it to device list */
1202 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1203
Roel Kluin7de0b872009-12-16 13:06:33 -03001204 if (video_nr != -1)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001205 video_nr++;
1206
1207 dev->vfd = vfd;
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001208 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
1209 video_device_node_name(vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001210 return 0;
1211
1212rel_vdev:
1213 video_device_release(vfd);
1214unreg_dev:
1215 v4l2_device_unregister(&dev->v4l2_dev);
1216free_dev:
1217 kfree(dev);
1218 return ret;
1219}
1220
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001221/* This routine allocates from 1 to n_devs virtual drivers.
1222
1223 The real maximum number of virtual drivers will depend on how many drivers
1224 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001225 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001226 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001227static int __init vivi_init(void)
1228{
Hans Verkuil730947b2010-04-10 04:13:53 -03001229 const struct font_desc *font = find_font("VGA8x16");
Hans Verkuil9185cbf2009-03-06 09:58:12 -03001230 int ret = 0, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001231
Hans Verkuil730947b2010-04-10 04:13:53 -03001232 if (font == NULL) {
1233 printk(KERN_ERR "vivi: could not find font\n");
1234 return -ENODEV;
1235 }
1236 font8x16 = font->data;
1237
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001238 if (n_devs <= 0)
1239 n_devs = 1;
1240
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001241 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001242 ret = vivi_create_instance(i);
1243 if (ret) {
1244 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001245 if (i)
1246 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001247 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001248 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001249 }
1250
1251 if (ret < 0) {
Hans Verkuil730947b2010-04-10 04:13:53 -03001252 printk(KERN_ERR "vivi: error %d while loading driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001253 return ret;
1254 }
1255
1256 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Carl Karsten745271a2008-06-10 00:02:32 -03001257 "Capture Board ver %u.%u.%u successfully loaded.\n",
1258 (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
1259 VIVI_VERSION & 0xFF);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001260
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001261 /* n_devs will reflect the actual number of allocated devices */
1262 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001263
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001264 return ret;
1265}
1266
1267static void __exit vivi_exit(void)
1268{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001269 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001270}
1271
1272module_init(vivi_init);
1273module_exit(vivi_exit);