blob: 3b9db8cbe41c0a4eac1908b706883e10b2ea5218 [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 *
Pawel Osciake007a322011-01-19 13:02:29 -020010 * Conversion to videobuf2 by Pawel Osciak & Marek Szyprowski
11 * Copyright (c) 2010 Samsung Electronics
12 *
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030013 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the BSD Licence, GNU General Public License
15 * as published by the Free Software Foundation; either version 2 of the
16 * License, or (at your option) any later version
17 */
18#include <linux/module.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030019#include <linux/errno.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030020#include <linux/kernel.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030021#include <linux/init.h>
22#include <linux/sched.h>
Randy Dunlap6b46c392010-05-07 15:22:26 -030023#include <linux/slab.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030024#include <linux/font.h>
Matthias Kaehlcke51b54022007-07-02 10:19:38 -030025#include <linux/mutex.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030026#include <linux/videodev2.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030027#include <linux/kthread.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080028#include <linux/freezer.h>
Pawel Osciake007a322011-01-19 13:02:29 -020029#include <media/videobuf2-vmalloc.h>
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030030#include <media/v4l2-device.h>
31#include <media/v4l2-ioctl.h>
Hans Verkuil7e996af2011-01-23 12:33:16 -020032#include <media/v4l2-ctrls.h>
Hans Verkuil2e4784d2011-03-11 20:01:54 -030033#include <media/v4l2-fh.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030034#include <media/v4l2-common.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030035
Mauro Carvalho Chehab584ce482008-06-10 15:21:49 -030036#define VIVI_MODULE_NAME "vivi"
Carl Karsten745271a2008-06-10 00:02:32 -030037
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030038/* Wake up at about 30 fps */
39#define WAKE_NUMERATOR 30
40#define WAKE_DENOMINATOR 1001
41#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
42
Hans Verkuil730947b2010-04-10 04:13:53 -030043#define MAX_WIDTH 1920
44#define MAX_HEIGHT 1200
45
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030046#define VIVI_VERSION "0.8.1"
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030047
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030048MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
49MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
50MODULE_LICENSE("Dual BSD/GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030051MODULE_VERSION(VIVI_VERSION);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030052
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 -0300135/* buffer for one video frame */
136struct vivi_buffer {
137 /* common v4l buffer stuff -- must be first */
Pawel Osciake007a322011-01-19 13:02:29 -0200138 struct vb2_buffer vb;
139 struct list_head list;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300140 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300141};
142
143struct vivi_dmaqueue {
144 struct list_head active;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300145
146 /* thread for generating video stream*/
147 struct task_struct *kthread;
148 wait_queue_head_t wq;
149 /* Counters to control fps rate */
150 int frame;
151 int ini_jiffies;
152};
153
154static LIST_HEAD(vivi_devlist);
155
156struct vivi_dev {
157 struct list_head vivi_devlist;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300158 struct v4l2_device v4l2_dev;
Hans Verkuil7e996af2011-01-23 12:33:16 -0200159 struct v4l2_ctrl_handler ctrl_handler;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300160
Hans Verkuil730947b2010-04-10 04:13:53 -0300161 /* controls */
Hans Verkuil7e996af2011-01-23 12:33:16 -0200162 struct v4l2_ctrl *brightness;
163 struct v4l2_ctrl *contrast;
164 struct v4l2_ctrl *saturation;
165 struct v4l2_ctrl *hue;
166 struct v4l2_ctrl *volume;
167 struct v4l2_ctrl *button;
168 struct v4l2_ctrl *boolean;
169 struct v4l2_ctrl *int32;
170 struct v4l2_ctrl *int64;
171 struct v4l2_ctrl *menu;
172 struct v4l2_ctrl *string;
Hans Verkuil730947b2010-04-10 04:13:53 -0300173
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300174 spinlock_t slock;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300175 struct mutex mutex;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300176
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300177 /* various device info */
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -0300178 struct video_device *vfd;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300179
180 struct vivi_dmaqueue vidq;
181
182 /* Several counters */
Hans Verkuil730947b2010-04-10 04:13:53 -0300183 unsigned ms;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300184 unsigned long jiffies;
Hans Verkuil7e996af2011-01-23 12:33:16 -0200185 unsigned button_pressed;
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300186
187 int mv_count; /* Controls bars movement */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300188
189 /* Input Number */
190 int input;
Hans Verkuilc41ee242009-02-14 13:43:44 -0300191
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300192 /* video capture */
193 struct vivi_fmt *fmt;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300194 unsigned int width, height;
Pawel Osciake007a322011-01-19 13:02:29 -0200195 struct vb2_queue vb_vidq;
196 enum v4l2_field field;
197 unsigned int field_count;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300198
Hans Verkuil730947b2010-04-10 04:13:53 -0300199 u8 bars[9][3];
200 u8 line[MAX_WIDTH * 4];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300201};
202
203/* ------------------------------------------------------------------
204 DMA and thread functions
205 ------------------------------------------------------------------*/
206
207/* Bars and Colors should match positions */
208
209enum colors {
210 WHITE,
Hans Verkuil730947b2010-04-10 04:13:53 -0300211 AMBER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300212 CYAN,
213 GREEN,
214 MAGENTA,
215 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300216 BLUE,
217 BLACK,
Hans Verkuil730947b2010-04-10 04:13:53 -0300218 TEXT_BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300219};
220
Hans Verkuil730947b2010-04-10 04:13:53 -0300221/* R G B */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300222#define COLOR_WHITE {204, 204, 204}
Hans Verkuil730947b2010-04-10 04:13:53 -0300223#define COLOR_AMBER {208, 208, 0}
224#define COLOR_CYAN { 0, 206, 206}
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300225#define COLOR_GREEN { 0, 239, 0}
226#define COLOR_MAGENTA {239, 0, 239}
227#define COLOR_RED {205, 0, 0}
228#define COLOR_BLUE { 0, 0, 255}
229#define COLOR_BLACK { 0, 0, 0}
230
231struct bar_std {
Hans Verkuil730947b2010-04-10 04:13:53 -0300232 u8 bar[9][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300233};
234
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300235/* Maximum number of bars are 10 - otherwise, the input print code
236 should be modified */
237static struct bar_std bars[] = {
238 { /* Standard ITU-R color bar sequence */
Hans Verkuil730947b2010-04-10 04:13:53 -0300239 { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN,
240 COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300241 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300242 { COLOR_WHITE, COLOR_AMBER, COLOR_BLACK, COLOR_WHITE,
243 COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, COLOR_AMBER, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300244 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300245 { COLOR_WHITE, COLOR_CYAN, COLOR_BLACK, COLOR_WHITE,
246 COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, COLOR_CYAN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300247 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300248 { COLOR_WHITE, COLOR_GREEN, COLOR_BLACK, COLOR_WHITE,
249 COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, COLOR_GREEN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300250 },
251};
252
253#define NUM_INPUTS ARRAY_SIZE(bars)
254
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300255#define TO_Y(r, g, b) \
256 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300257/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300258#define TO_V(r, g, b) \
259 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300260/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300261#define TO_U(r, g, b) \
262 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300263
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300264/* precalculate color bar values to speed up rendering */
Hans Verkuil730947b2010-04-10 04:13:53 -0300265static void precalculate_bars(struct vivi_dev *dev)
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300266{
Hans Verkuil730947b2010-04-10 04:13:53 -0300267 u8 r, g, b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300268 int k, is_yuv;
269
Hans Verkuil730947b2010-04-10 04:13:53 -0300270 for (k = 0; k < 9; k++) {
271 r = bars[dev->input].bar[k][0];
272 g = bars[dev->input].bar[k][1];
273 b = bars[dev->input].bar[k][2];
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300274 is_yuv = 0;
275
Hans Verkuil730947b2010-04-10 04:13:53 -0300276 switch (dev->fmt->fourcc) {
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300277 case V4L2_PIX_FMT_YUYV:
278 case V4L2_PIX_FMT_UYVY:
279 is_yuv = 1;
280 break;
281 case V4L2_PIX_FMT_RGB565:
282 case V4L2_PIX_FMT_RGB565X:
283 r >>= 3;
284 g >>= 2;
285 b >>= 3;
286 break;
287 case V4L2_PIX_FMT_RGB555:
288 case V4L2_PIX_FMT_RGB555X:
289 r >>= 3;
290 g >>= 3;
291 b >>= 3;
292 break;
293 }
294
295 if (is_yuv) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300296 dev->bars[k][0] = TO_Y(r, g, b); /* Luma */
297 dev->bars[k][1] = TO_U(r, g, b); /* Cb */
298 dev->bars[k][2] = TO_V(r, g, b); /* Cr */
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300299 } else {
Hans Verkuil730947b2010-04-10 04:13:53 -0300300 dev->bars[k][0] = r;
301 dev->bars[k][1] = g;
302 dev->bars[k][2] = b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300303 }
304 }
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300305}
306
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300307#define TSTAMP_MIN_Y 24
308#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
309#define TSTAMP_INPUT_X 10
310#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300311
Hans Verkuil730947b2010-04-10 04:13:53 -0300312static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos)
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300313{
Hans Verkuil730947b2010-04-10 04:13:53 -0300314 u8 r_y, g_u, b_v;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300315 int color;
Hans Verkuil730947b2010-04-10 04:13:53 -0300316 u8 *p;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300317
Hans Verkuil730947b2010-04-10 04:13:53 -0300318 r_y = dev->bars[colorpos][0]; /* R or precalculated Y */
319 g_u = dev->bars[colorpos][1]; /* G or precalculated U */
320 b_v = dev->bars[colorpos][2]; /* B or precalculated V */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300321
322 for (color = 0; color < 4; color++) {
323 p = buf + color;
324
Hans Verkuil730947b2010-04-10 04:13:53 -0300325 switch (dev->fmt->fourcc) {
Magnus Dammd891f472008-10-14 12:47:09 -0300326 case V4L2_PIX_FMT_YUYV:
327 switch (color) {
328 case 0:
329 case 2:
330 *p = r_y;
331 break;
332 case 1:
333 *p = g_u;
334 break;
335 case 3:
336 *p = b_v;
337 break;
338 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300339 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300340 case V4L2_PIX_FMT_UYVY:
341 switch (color) {
342 case 1:
343 case 3:
344 *p = r_y;
345 break;
346 case 0:
347 *p = g_u;
348 break;
349 case 2:
350 *p = b_v;
351 break;
352 }
353 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300354 case V4L2_PIX_FMT_RGB565:
355 switch (color) {
356 case 0:
357 case 2:
358 *p = (g_u << 5) | b_v;
359 break;
360 case 1:
361 case 3:
362 *p = (r_y << 3) | (g_u >> 3);
363 break;
364 }
365 break;
366 case V4L2_PIX_FMT_RGB565X:
367 switch (color) {
368 case 0:
369 case 2:
370 *p = (r_y << 3) | (g_u >> 3);
371 break;
372 case 1:
373 case 3:
374 *p = (g_u << 5) | b_v;
375 break;
376 }
377 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300378 case V4L2_PIX_FMT_RGB555:
379 switch (color) {
380 case 0:
381 case 2:
382 *p = (g_u << 5) | b_v;
383 break;
384 case 1:
385 case 3:
386 *p = (r_y << 2) | (g_u >> 3);
387 break;
388 }
389 break;
390 case V4L2_PIX_FMT_RGB555X:
391 switch (color) {
392 case 0:
393 case 2:
394 *p = (r_y << 2) | (g_u >> 3);
395 break;
396 case 1:
397 case 3:
398 *p = (g_u << 5) | b_v;
399 break;
400 }
401 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300402 }
403 }
404}
405
Hans Verkuil730947b2010-04-10 04:13:53 -0300406static void precalculate_line(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300407{
Hans Verkuil730947b2010-04-10 04:13:53 -0300408 int w;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300409
Hans Verkuil730947b2010-04-10 04:13:53 -0300410 for (w = 0; w < dev->width * 2; w += 2) {
411 int colorpos = (w / (dev->width / 8) % 8);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300412
Hans Verkuil730947b2010-04-10 04:13:53 -0300413 gen_twopix(dev, dev->line + w * 2, colorpos);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300414 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300415}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300416
Hans Verkuil730947b2010-04-10 04:13:53 -0300417static void gen_text(struct vivi_dev *dev, char *basep,
418 int y, int x, char *text)
419{
420 int line;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300421
Hans Verkuil730947b2010-04-10 04:13:53 -0300422 /* Checks if it is possible to show string */
423 if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width)
424 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300425
426 /* Print stream time */
Hans Verkuil730947b2010-04-10 04:13:53 -0300427 for (line = y; line < y + 16; line++) {
428 int j = 0;
429 char *pos = basep + line * dev->width * 2 + x * 2;
430 char *s;
431
432 for (s = text; *s; s++) {
433 u8 chr = font8x16[*s * 16 + line - y];
434 int i;
435
436 for (i = 0; i < 7; i++, j++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300437 /* Draw white font on black background */
Hans Verkuil730947b2010-04-10 04:13:53 -0300438 if (chr & (1 << (7 - i)))
439 gen_twopix(dev, pos + j * 2, WHITE);
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300440 else
Hans Verkuil730947b2010-04-10 04:13:53 -0300441 gen_twopix(dev, pos + j * 2, TEXT_BLACK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300442 }
443 }
444 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300445}
Brandon Philips78718e52008-04-02 18:10:59 -0300446
Hans Verkuil730947b2010-04-10 04:13:53 -0300447static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300448{
Pawel Osciake007a322011-01-19 13:02:29 -0200449 int wmax = dev->width;
450 int hmax = dev->height;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300451 struct timeval ts;
Pawel Osciake007a322011-01-19 13:02:29 -0200452 void *vbuf = vb2_plane_vaddr(&buf->vb, 0);
Hans Verkuil730947b2010-04-10 04:13:53 -0300453 unsigned ms;
454 char str[100];
455 int h, line = 1;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300456
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300457 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300458 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300459
Hans Verkuil730947b2010-04-10 04:13:53 -0300460 for (h = 0; h < hmax; h++)
461 memcpy(vbuf + h * wmax * 2, dev->line + (dev->mv_count % wmax) * 2, wmax * 2);
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300462
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300463 /* Updates stream time */
464
Hans Verkuil730947b2010-04-10 04:13:53 -0300465 dev->ms += jiffies_to_msecs(jiffies - dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300466 dev->jiffies = jiffies;
Hans Verkuil730947b2010-04-10 04:13:53 -0300467 ms = dev->ms;
468 snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d ",
469 (ms / (60 * 60 * 1000)) % 24,
470 (ms / (60 * 1000)) % 60,
471 (ms / 1000) % 60,
472 ms % 1000);
473 gen_text(dev, vbuf, line++ * 16, 16, str);
474 snprintf(str, sizeof(str), " %dx%d, input %d ",
475 dev->width, dev->height, dev->input);
476 gen_text(dev, vbuf, line++ * 16, 16, str);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300477
Hans Verkuil7e996af2011-01-23 12:33:16 -0200478 mutex_lock(&dev->ctrl_handler.lock);
Hans Verkuil730947b2010-04-10 04:13:53 -0300479 snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
Hans Verkuil7e996af2011-01-23 12:33:16 -0200480 dev->brightness->cur.val,
481 dev->contrast->cur.val,
482 dev->saturation->cur.val,
483 dev->hue->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300484 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200485 snprintf(str, sizeof(str), " volume %3d ", dev->volume->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300486 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200487 snprintf(str, sizeof(str), " int32 %d, int64 %lld ",
488 dev->int32->cur.val,
489 dev->int64->cur.val64);
490 gen_text(dev, vbuf, line++ * 16, 16, str);
491 snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
492 dev->boolean->cur.val,
493 dev->menu->qmenu[dev->menu->cur.val],
494 dev->string->cur.string);
495 mutex_unlock(&dev->ctrl_handler.lock);
496 gen_text(dev, vbuf, line++ * 16, 16, str);
497 if (dev->button_pressed) {
498 dev->button_pressed--;
499 snprintf(str, sizeof(str), " button pressed!");
500 gen_text(dev, vbuf, line++ * 16, 16, str);
501 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300502
503 dev->mv_count += 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300504
Pawel Osciake007a322011-01-19 13:02:29 -0200505 buf->vb.v4l2_buf.field = dev->field;
506 dev->field_count++;
507 buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300508 do_gettimeofday(&ts);
Pawel Osciake007a322011-01-19 13:02:29 -0200509 buf->vb.v4l2_buf.timestamp = ts;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300510}
511
Hans Verkuil730947b2010-04-10 04:13:53 -0300512static void vivi_thread_tick(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300513{
Brandon Philips78718e52008-04-02 18:10:59 -0300514 struct vivi_dmaqueue *dma_q = &dev->vidq;
Hans Verkuil730947b2010-04-10 04:13:53 -0300515 struct vivi_buffer *buf;
Brandon Philips78718e52008-04-02 18:10:59 -0300516 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300517
Brandon Philips78718e52008-04-02 18:10:59 -0300518 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300519
Brandon Philips78718e52008-04-02 18:10:59 -0300520 spin_lock_irqsave(&dev->slock, flags);
521 if (list_empty(&dma_q->active)) {
522 dprintk(dev, 1, "No active queue to serve\n");
523 goto unlock;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300524 }
Brandon Philips78718e52008-04-02 18:10:59 -0300525
Pawel Osciake007a322011-01-19 13:02:29 -0200526 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
527 list_del(&buf->list);
Brandon Philips78718e52008-04-02 18:10:59 -0300528
Pawel Osciake007a322011-01-19 13:02:29 -0200529 do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
Brandon Philips78718e52008-04-02 18:10:59 -0300530
531 /* Fill buffer */
Hans Verkuil730947b2010-04-10 04:13:53 -0300532 vivi_fillbuff(dev, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300533 dprintk(dev, 1, "filled buffer %p\n", buf);
534
Pawel Osciake007a322011-01-19 13:02:29 -0200535 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
536 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
Brandon Philips78718e52008-04-02 18:10:59 -0300537unlock:
538 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300539}
540
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300541#define frames_to_ms(frames) \
542 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
543
Hans Verkuil730947b2010-04-10 04:13:53 -0300544static void vivi_sleep(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300545{
Brandon Philips78718e52008-04-02 18:10:59 -0300546 struct vivi_dmaqueue *dma_q = &dev->vidq;
547 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300548 DECLARE_WAITQUEUE(wait, current);
549
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300550 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300551 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300552
553 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300554 if (kthread_should_stop())
555 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300556
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300557 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300558 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300559
Hans Verkuil730947b2010-04-10 04:13:53 -0300560 vivi_thread_tick(dev);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300561
562 schedule_timeout_interruptible(timeout);
563
564stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300565 remove_wait_queue(&dma_q->wq, &wait);
566 try_to_freeze();
567}
568
Adrian Bunk972c3512006-04-27 21:06:50 -0300569static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300570{
Hans Verkuil730947b2010-04-10 04:13:53 -0300571 struct vivi_dev *dev = data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300572
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300573 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300574
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700575 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300576
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300577 for (;;) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300578 vivi_sleep(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300579
580 if (kthread_should_stop())
581 break;
582 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300583 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300584 return 0;
585}
586
Pawel Osciake007a322011-01-19 13:02:29 -0200587static int vivi_start_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300588{
Brandon Philips78718e52008-04-02 18:10:59 -0300589 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300590
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300591 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300592
Hans Verkuil730947b2010-04-10 04:13:53 -0300593 /* Resets frame counters */
594 dev->ms = 0;
595 dev->mv_count = 0;
596 dev->jiffies = jiffies;
597
598 dma_q->frame = 0;
599 dma_q->ini_jiffies = jiffies;
600 dma_q->kthread = kthread_run(vivi_thread, dev, dev->v4l2_dev.name);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300601
Akinobu Mita054afee2006-12-20 10:04:00 -0300602 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300603 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Pawel Osciake007a322011-01-19 13:02:29 -0200604 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300605 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300606 /* Wakes thread */
607 wake_up_interruptible(&dma_q->wq);
608
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300609 dprintk(dev, 1, "returning from %s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200610 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300611}
612
Pawel Osciake007a322011-01-19 13:02:29 -0200613static void vivi_stop_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300614{
Hans Verkuil730947b2010-04-10 04:13:53 -0300615 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300616
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300617 dprintk(dev, 1, "%s\n", __func__);
Hans Verkuil730947b2010-04-10 04:13:53 -0300618
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300619 /* shutdown control thread */
620 if (dma_q->kthread) {
621 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300622 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300623 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300624
Pawel Osciake007a322011-01-19 13:02:29 -0200625 /*
626 * Typical driver might need to wait here until dma engine stops.
627 * In this case we can abort imiedetly, so it's just a noop.
628 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300629
Pawel Osciake007a322011-01-19 13:02:29 -0200630 /* Release all active buffers */
631 while (!list_empty(&dma_q->active)) {
632 struct vivi_buffer *buf;
633 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
634 list_del(&buf->list);
635 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
636 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
637 }
638}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300639/* ------------------------------------------------------------------
640 Videobuf operations
641 ------------------------------------------------------------------*/
Pawel Osciake007a322011-01-19 13:02:29 -0200642static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
643 unsigned int *nplanes, unsigned long sizes[],
644 void *alloc_ctxs[])
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300645{
Pawel Osciake007a322011-01-19 13:02:29 -0200646 struct vivi_dev *dev = vb2_get_drv_priv(vq);
647 unsigned long size;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300648
Pawel Osciake007a322011-01-19 13:02:29 -0200649 size = dev->width * dev->height * 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300650
Pawel Osciake007a322011-01-19 13:02:29 -0200651 if (0 == *nbuffers)
652 *nbuffers = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300653
Pawel Osciake007a322011-01-19 13:02:29 -0200654 while (size * *nbuffers > vid_limit * 1024 * 1024)
655 (*nbuffers)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300656
Pawel Osciake007a322011-01-19 13:02:29 -0200657 *nplanes = 1;
658
659 sizes[0] = size;
660
661 /*
662 * videobuf2-vmalloc allocator is context-less so no need to set
663 * alloc_ctxs array.
664 */
665
666 dprintk(dev, 1, "%s, count=%d, size=%ld\n", __func__,
667 *nbuffers, size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300668
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300669 return 0;
670}
671
Pawel Osciake007a322011-01-19 13:02:29 -0200672static int buffer_init(struct vb2_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300673{
Pawel Osciake007a322011-01-19 13:02:29 -0200674 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300675
Hans Verkuil730947b2010-04-10 04:13:53 -0300676 BUG_ON(NULL == dev->fmt);
Brandon Philips78718e52008-04-02 18:10:59 -0300677
Pawel Osciake007a322011-01-19 13:02:29 -0200678 /*
679 * This callback is called once per buffer, after its allocation.
680 *
681 * Vivi does not allow changing format during streaming, but it is
682 * possible to do so when streaming is paused (i.e. in streamoff state).
683 * Buffers however are not freed when going into streamoff and so
684 * buffer size verification has to be done in buffer_prepare, on each
685 * qbuf.
686 * It would be best to move verification code here to buf_init and
687 * s_fmt though.
688 */
689
690 return 0;
691}
692
693static int buffer_prepare(struct vb2_buffer *vb)
694{
695 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
696 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
697 unsigned long size;
698
699 dprintk(dev, 1, "%s, field=%d\n", __func__, vb->v4l2_buf.field);
700
701 BUG_ON(NULL == dev->fmt);
702
703 /*
704 * Theses properties only change when queue is idle, see s_fmt.
705 * The below checks should not be performed here, on each
706 * buffer_prepare (i.e. on each qbuf). Most of the code in this function
707 * should thus be moved to buffer_init and s_fmt.
708 */
Hans Verkuil730947b2010-04-10 04:13:53 -0300709 if (dev->width < 48 || dev->width > MAX_WIDTH ||
710 dev->height < 32 || dev->height > MAX_HEIGHT)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300711 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300712
Pawel Osciake007a322011-01-19 13:02:29 -0200713 size = dev->width * dev->height * 2;
714 if (vb2_plane_size(vb, 0) < size) {
715 dprintk(dev, 1, "%s data will not fit into plane (%lu < %lu)\n",
716 __func__, vb2_plane_size(vb, 0), size);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300717 return -EINVAL;
Pawel Osciake007a322011-01-19 13:02:29 -0200718 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300719
Pawel Osciake007a322011-01-19 13:02:29 -0200720 vb2_set_plane_payload(&buf->vb, 0, size);
721
722 buf->fmt = dev->fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300723
Hans Verkuil730947b2010-04-10 04:13:53 -0300724 precalculate_bars(dev);
725 precalculate_line(dev);
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300726
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300727 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300728}
729
Pawel Osciake007a322011-01-19 13:02:29 -0200730static int buffer_finish(struct vb2_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300731{
Pawel Osciake007a322011-01-19 13:02:29 -0200732 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
733 dprintk(dev, 1, "%s\n", __func__);
734 return 0;
735}
736
737static void buffer_cleanup(struct vb2_buffer *vb)
738{
739 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
740 dprintk(dev, 1, "%s\n", __func__);
741
742}
743
744static void buffer_queue(struct vb2_buffer *vb)
745{
746 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
Hans Verkuil730947b2010-04-10 04:13:53 -0300747 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300748 struct vivi_dmaqueue *vidq = &dev->vidq;
Pawel Osciake007a322011-01-19 13:02:29 -0200749 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300750
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300751 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300752
Pawel Osciake007a322011-01-19 13:02:29 -0200753 spin_lock_irqsave(&dev->slock, flags);
754 list_add_tail(&buf->list, &vidq->active);
755 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300756}
757
Pawel Osciake007a322011-01-19 13:02:29 -0200758static int start_streaming(struct vb2_queue *vq)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300759{
Pawel Osciake007a322011-01-19 13:02:29 -0200760 struct vivi_dev *dev = vb2_get_drv_priv(vq);
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300761 dprintk(dev, 1, "%s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200762 return vivi_start_generating(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300763}
764
Pawel Osciake007a322011-01-19 13:02:29 -0200765/* abort streaming and wait for last buffer */
766static int stop_streaming(struct vb2_queue *vq)
767{
768 struct vivi_dev *dev = vb2_get_drv_priv(vq);
769 dprintk(dev, 1, "%s\n", __func__);
770 vivi_stop_generating(dev);
771 return 0;
772}
773
774static void vivi_lock(struct vb2_queue *vq)
775{
776 struct vivi_dev *dev = vb2_get_drv_priv(vq);
777 mutex_lock(&dev->mutex);
778}
779
780static void vivi_unlock(struct vb2_queue *vq)
781{
782 struct vivi_dev *dev = vb2_get_drv_priv(vq);
783 mutex_unlock(&dev->mutex);
784}
785
786
787static struct vb2_ops vivi_video_qops = {
788 .queue_setup = queue_setup,
789 .buf_init = buffer_init,
790 .buf_prepare = buffer_prepare,
791 .buf_finish = buffer_finish,
792 .buf_cleanup = buffer_cleanup,
793 .buf_queue = buffer_queue,
794 .start_streaming = start_streaming,
795 .stop_streaming = stop_streaming,
796 .wait_prepare = vivi_unlock,
797 .wait_finish = vivi_lock,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300798};
799
800/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300801 IOCTL vidioc handling
802 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300803static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300804 struct v4l2_capability *cap)
805{
Hans Verkuil730947b2010-04-10 04:13:53 -0300806 struct vivi_dev *dev = video_drvdata(file);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300807
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300808 strcpy(cap->driver, "vivi");
809 strcpy(cap->card, "vivi");
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300810 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Hans Verkuil730947b2010-04-10 04:13:53 -0300811 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
812 V4L2_CAP_READWRITE;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300813 return 0;
814}
815
Hans Verkuil78b526a2008-05-28 12:16:41 -0300816static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300817 struct v4l2_fmtdesc *f)
818{
Magnus Dammd891f472008-10-14 12:47:09 -0300819 struct vivi_fmt *fmt;
820
821 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300822 return -EINVAL;
823
Magnus Dammd891f472008-10-14 12:47:09 -0300824 fmt = &formats[f->index];
825
826 strlcpy(f->description, fmt->name, sizeof(f->description));
827 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300828 return 0;
829}
830
Hans Verkuil78b526a2008-05-28 12:16:41 -0300831static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300832 struct v4l2_format *f)
833{
Hans Verkuil730947b2010-04-10 04:13:53 -0300834 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300835
Hans Verkuil730947b2010-04-10 04:13:53 -0300836 f->fmt.pix.width = dev->width;
837 f->fmt.pix.height = dev->height;
Pawel Osciake007a322011-01-19 13:02:29 -0200838 f->fmt.pix.field = dev->field;
Hans Verkuil730947b2010-04-10 04:13:53 -0300839 f->fmt.pix.pixelformat = dev->fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300840 f->fmt.pix.bytesperline =
Hans Verkuil730947b2010-04-10 04:13:53 -0300841 (f->fmt.pix.width * dev->fmt->depth) >> 3;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300842 f->fmt.pix.sizeimage =
843 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil730947b2010-04-10 04:13:53 -0300844 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300845}
846
Hans Verkuil78b526a2008-05-28 12:16:41 -0300847static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300848 struct v4l2_format *f)
849{
Hans Verkuil730947b2010-04-10 04:13:53 -0300850 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300851 struct vivi_fmt *fmt;
852 enum v4l2_field field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300853
Magnus Dammd891f472008-10-14 12:47:09 -0300854 fmt = get_format(f);
855 if (!fmt) {
856 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
857 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300858 return -EINVAL;
859 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300860
861 field = f->fmt.pix.field;
862
863 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300864 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300865 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300866 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300867 return -EINVAL;
868 }
869
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300870 f->fmt.pix.field = field;
Hans Verkuil730947b2010-04-10 04:13:53 -0300871 v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
872 &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300873 f->fmt.pix.bytesperline =
874 (f->fmt.pix.width * fmt->depth) >> 3;
875 f->fmt.pix.sizeimage =
876 f->fmt.pix.height * f->fmt.pix.bytesperline;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300877 return 0;
878}
879
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300880static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
881 struct v4l2_format *f)
882{
Hans Verkuil730947b2010-04-10 04:13:53 -0300883 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200884 struct vb2_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300885
Hans Verkuil730947b2010-04-10 04:13:53 -0300886 int ret = vidioc_try_fmt_vid_cap(file, priv, f);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300887 if (ret < 0)
888 return ret;
889
Pawel Osciake007a322011-01-19 13:02:29 -0200890 if (vb2_is_streaming(q)) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300891 dprintk(dev, 1, "%s device busy\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200892 return -EBUSY;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300893 }
894
Hans Verkuil730947b2010-04-10 04:13:53 -0300895 dev->fmt = get_format(f);
896 dev->width = f->fmt.pix.width;
897 dev->height = f->fmt.pix.height;
Pawel Osciake007a322011-01-19 13:02:29 -0200898 dev->field = f->fmt.pix.field;
899
900 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300901}
902
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300903static int vidioc_reqbufs(struct file *file, void *priv,
904 struct v4l2_requestbuffers *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300905{
Hans Verkuil730947b2010-04-10 04:13:53 -0300906 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200907 return vb2_reqbufs(&dev->vb_vidq, p);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300908}
909
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300910static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300911{
Hans Verkuil730947b2010-04-10 04:13:53 -0300912 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200913 return vb2_querybuf(&dev->vb_vidq, p);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300914}
915
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300916static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300917{
Hans Verkuil730947b2010-04-10 04:13:53 -0300918 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200919 return vb2_qbuf(&dev->vb_vidq, p);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300920}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300921
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300922static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300923{
Hans Verkuil730947b2010-04-10 04:13:53 -0300924 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200925 return vb2_dqbuf(&dev->vb_vidq, p, file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300926}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300927
Adrian Bunkdc46ace2006-06-23 06:42:44 -0300928static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type 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);
Pawel Osciake007a322011-01-19 13:02:29 -0200931 return vb2_streamon(&dev->vb_vidq, i);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300932}
933
Adrian Bunkdc46ace2006-06-23 06:42:44 -0300934static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300935{
Hans Verkuil730947b2010-04-10 04:13:53 -0300936 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200937 return vb2_streamoff(&dev->vb_vidq, i);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300938}
939
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300940static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300941{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300942 return 0;
943}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300944
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300945/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300946static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300947 struct v4l2_input *inp)
948{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300949 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300950 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300951
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300952 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -0300953 inp->std = V4L2_STD_525_60;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300954 sprintf(inp->name, "Camera %u", inp->index);
Hans Verkuil730947b2010-04-10 04:13:53 -0300955 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300956}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300957
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300958static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300959{
Hans Verkuil730947b2010-04-10 04:13:53 -0300960 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300961
962 *i = dev->input;
Hans Verkuil730947b2010-04-10 04:13:53 -0300963 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300964}
Hans Verkuil730947b2010-04-10 04:13:53 -0300965
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300966static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300967{
Hans Verkuil730947b2010-04-10 04:13:53 -0300968 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300969
970 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300971 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300972
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300973 dev->input = i;
Hans Verkuil730947b2010-04-10 04:13:53 -0300974 precalculate_bars(dev);
975 precalculate_line(dev);
976 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300977}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300978
Hans Verkuil730947b2010-04-10 04:13:53 -0300979/* --- controls ---------------------------------------------- */
Hans Verkuil7e996af2011-01-23 12:33:16 -0200980
981static int vivi_s_ctrl(struct v4l2_ctrl *ctrl)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300982{
Hans Verkuil7e996af2011-01-23 12:33:16 -0200983 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300984
Hans Verkuil7e996af2011-01-23 12:33:16 -0200985 if (ctrl == dev->button)
986 dev->button_pressed = 30;
987 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300988}
989
990/* ------------------------------------------------------------------
991 File operations for the device
992 ------------------------------------------------------------------*/
993
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300994static ssize_t
995vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
996{
Hans Verkuil730947b2010-04-10 04:13:53 -0300997 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300998
Pawel Osciake007a322011-01-19 13:02:29 -0200999 dprintk(dev, 1, "read called\n");
1000 return vb2_read(&dev->vb_vidq, data, count, ppos,
1001 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001002}
1003
1004static unsigned int
1005vivi_poll(struct file *file, struct poll_table_struct *wait)
1006{
Hans Verkuil730947b2010-04-10 04:13:53 -03001007 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -02001008 struct vb2_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001009
Harvey Harrison7e28adb2008-04-08 23:20:00 -03001010 dprintk(dev, 1, "%s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -02001011 return vb2_poll(q, file, wait);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001012}
1013
Hans Verkuilbec43662008-12-30 06:58:20 -03001014static int vivi_close(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001015{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001016 struct video_device *vdev = video_devdata(file);
Hans Verkuil730947b2010-04-10 04:13:53 -03001017 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001018
Pawel Osciake007a322011-01-19 13:02:29 -02001019 dprintk(dev, 1, "close called (dev=%s), file %p\n",
1020 video_device_node_name(vdev), file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001021
Hans Verkuil2e4784d2011-03-11 20:01:54 -03001022 if (v4l2_fh_is_singular_file(file))
Pawel Osciake007a322011-01-19 13:02:29 -02001023 vb2_queue_release(&dev->vb_vidq);
Hans Verkuil2e4784d2011-03-11 20:01:54 -03001024 return v4l2_fh_release(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001025}
1026
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001027static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001028{
Hans Verkuil730947b2010-04-10 04:13:53 -03001029 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001030 int ret;
1031
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001032 dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001033
Pawel Osciake007a322011-01-19 13:02:29 -02001034 ret = vb2_mmap(&dev->vb_vidq, vma);
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001035 dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n",
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001036 (unsigned long)vma->vm_start,
Hans Verkuil730947b2010-04-10 04:13:53 -03001037 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001038 ret);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001039 return ret;
1040}
1041
Hans Verkuil7e996af2011-01-23 12:33:16 -02001042static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
1043 .s_ctrl = vivi_s_ctrl,
1044};
1045
1046#define VIVI_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
1047
1048static const struct v4l2_ctrl_config vivi_ctrl_button = {
1049 .ops = &vivi_ctrl_ops,
1050 .id = VIVI_CID_CUSTOM_BASE + 0,
1051 .name = "Button",
1052 .type = V4L2_CTRL_TYPE_BUTTON,
1053};
1054
1055static const struct v4l2_ctrl_config vivi_ctrl_boolean = {
1056 .ops = &vivi_ctrl_ops,
1057 .id = VIVI_CID_CUSTOM_BASE + 1,
1058 .name = "Boolean",
1059 .type = V4L2_CTRL_TYPE_BOOLEAN,
1060 .min = 0,
1061 .max = 1,
1062 .step = 1,
1063 .def = 1,
1064};
1065
1066static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
1067 .ops = &vivi_ctrl_ops,
1068 .id = VIVI_CID_CUSTOM_BASE + 2,
1069 .name = "Integer 32 Bits",
1070 .type = V4L2_CTRL_TYPE_INTEGER,
Hans Verkuil5b283022011-01-11 17:32:28 -03001071 .min = 0x80000000,
1072 .max = 0x7fffffff,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001073 .step = 1,
1074};
1075
1076static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
1077 .ops = &vivi_ctrl_ops,
1078 .id = VIVI_CID_CUSTOM_BASE + 3,
1079 .name = "Integer 64 Bits",
1080 .type = V4L2_CTRL_TYPE_INTEGER64,
1081};
1082
1083static const char * const vivi_ctrl_menu_strings[] = {
1084 "Menu Item 0 (Skipped)",
1085 "Menu Item 1",
1086 "Menu Item 2 (Skipped)",
1087 "Menu Item 3",
1088 "Menu Item 4",
1089 "Menu Item 5 (Skipped)",
1090 NULL,
1091};
1092
1093static const struct v4l2_ctrl_config vivi_ctrl_menu = {
1094 .ops = &vivi_ctrl_ops,
1095 .id = VIVI_CID_CUSTOM_BASE + 4,
1096 .name = "Menu",
1097 .type = V4L2_CTRL_TYPE_MENU,
1098 .min = 1,
1099 .max = 4,
1100 .def = 3,
1101 .menu_skip_mask = 0x04,
1102 .qmenu = vivi_ctrl_menu_strings,
1103};
1104
1105static const struct v4l2_ctrl_config vivi_ctrl_string = {
1106 .ops = &vivi_ctrl_ops,
1107 .id = VIVI_CID_CUSTOM_BASE + 5,
1108 .name = "String",
1109 .type = V4L2_CTRL_TYPE_STRING,
1110 .min = 2,
1111 .max = 4,
1112 .step = 1,
1113};
1114
Hans Verkuilbec43662008-12-30 06:58:20 -03001115static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001116 .owner = THIS_MODULE,
Hans Verkuil2e4784d2011-03-11 20:01:54 -03001117 .open = v4l2_fh_open,
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001118 .release = vivi_close,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001119 .read = vivi_read,
1120 .poll = vivi_poll,
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001121 .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001122 .mmap = vivi_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001123};
1124
Hans Verkuila3998102008-07-21 02:57:38 -03001125static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001126 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001127 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1128 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1129 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1130 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001131 .vidioc_reqbufs = vidioc_reqbufs,
1132 .vidioc_querybuf = vidioc_querybuf,
1133 .vidioc_qbuf = vidioc_qbuf,
1134 .vidioc_dqbuf = vidioc_dqbuf,
1135 .vidioc_s_std = vidioc_s_std,
1136 .vidioc_enum_input = vidioc_enum_input,
1137 .vidioc_g_input = vidioc_g_input,
1138 .vidioc_s_input = vidioc_s_input,
Hans Verkuil730947b2010-04-10 04:13:53 -03001139 .vidioc_streamon = vidioc_streamon,
1140 .vidioc_streamoff = vidioc_streamoff,
Hans Verkuila3998102008-07-21 02:57:38 -03001141};
1142
1143static struct video_device vivi_template = {
1144 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001145 .fops = &vivi_fops,
1146 .ioctl_ops = &vivi_ioctl_ops,
Hans Verkuila3998102008-07-21 02:57:38 -03001147 .release = video_device_release,
1148
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001149 .tvnorms = V4L2_STD_525_60,
Mauro Carvalho Chehabe75f9ce2006-11-20 13:19:20 -03001150 .current_norm = V4L2_STD_NTSC_M,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001151};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001152
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001153/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001154 Initialization and module stuff
1155 ------------------------------------------------------------------*/
1156
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001157static int vivi_release(void)
1158{
1159 struct vivi_dev *dev;
1160 struct list_head *list;
1161
1162 while (!list_empty(&vivi_devlist)) {
1163 list = vivi_devlist.next;
1164 list_del(list);
1165 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1166
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001167 v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
1168 video_device_node_name(dev->vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001169 video_unregister_device(dev->vfd);
1170 v4l2_device_unregister(&dev->v4l2_dev);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001171 v4l2_ctrl_handler_free(&dev->ctrl_handler);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001172 kfree(dev);
1173 }
1174
1175 return 0;
1176}
1177
Hans Verkuilc41ee242009-02-14 13:43:44 -03001178static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001179{
1180 struct vivi_dev *dev;
1181 struct video_device *vfd;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001182 struct v4l2_ctrl_handler *hdl;
Pawel Osciake007a322011-01-19 13:02:29 -02001183 struct vb2_queue *q;
Hans Verkuil730947b2010-04-10 04:13:53 -03001184 int ret;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001185
1186 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1187 if (!dev)
1188 return -ENOMEM;
1189
1190 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001191 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001192 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1193 if (ret)
1194 goto free_dev;
1195
Hans Verkuil730947b2010-04-10 04:13:53 -03001196 dev->fmt = &formats[0];
1197 dev->width = 640;
1198 dev->height = 480;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001199 hdl = &dev->ctrl_handler;
1200 v4l2_ctrl_handler_init(hdl, 11);
1201 dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1202 V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
1203 dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1204 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1205 dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1206 V4L2_CID_CONTRAST, 0, 255, 1, 16);
1207 dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1208 V4L2_CID_SATURATION, 0, 255, 1, 127);
1209 dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1210 V4L2_CID_HUE, -128, 127, 1, 0);
1211 dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
1212 dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
1213 dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);
1214 dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL);
1215 dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL);
1216 dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL);
1217 if (hdl->error) {
1218 ret = hdl->error;
1219 goto unreg_dev;
1220 }
1221 dev->v4l2_dev.ctrl_handler = hdl;
Hans Verkuil730947b2010-04-10 04:13:53 -03001222
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001223 /* initialize locks */
1224 spin_lock_init(&dev->slock);
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001225
Pawel Osciake007a322011-01-19 13:02:29 -02001226 /* initialize queue */
1227 q = &dev->vb_vidq;
1228 memset(q, 0, sizeof(dev->vb_vidq));
1229 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1230 q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1231 q->drv_priv = dev;
1232 q->buf_struct_size = sizeof(struct vivi_buffer);
1233 q->ops = &vivi_video_qops;
1234 q->mem_ops = &vb2_vmalloc_memops;
1235
1236 vb2_queue_init(q);
1237
1238 mutex_init(&dev->mutex);
Hans Verkuil730947b2010-04-10 04:13:53 -03001239
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001240 /* init video dma queues */
1241 INIT_LIST_HEAD(&dev->vidq.active);
1242 init_waitqueue_head(&dev->vidq.wq);
1243
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001244 ret = -ENOMEM;
1245 vfd = video_device_alloc();
1246 if (!vfd)
1247 goto unreg_dev;
1248
1249 *vfd = vivi_template;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -03001250 vfd->debug = debug;
Hans Verkuil730947b2010-04-10 04:13:53 -03001251 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuilb1a873a2011-03-22 10:14:07 -03001252 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Pawel Osciake007a322011-01-19 13:02:29 -02001253
1254 /*
1255 * Provide a mutex to v4l2 core. It will be used to protect
1256 * all fops and v4l2 ioctls.
1257 */
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001258 vfd->lock = &dev->mutex;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001259
1260 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1261 if (ret < 0)
1262 goto rel_vdev;
1263
1264 video_set_drvdata(vfd, dev);
1265
1266 /* Now that everything is fine, let's add it to device list */
1267 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1268
Roel Kluin7de0b872009-12-16 13:06:33 -03001269 if (video_nr != -1)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001270 video_nr++;
1271
1272 dev->vfd = vfd;
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001273 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
1274 video_device_node_name(vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001275 return 0;
1276
1277rel_vdev:
1278 video_device_release(vfd);
1279unreg_dev:
Hans Verkuil7e996af2011-01-23 12:33:16 -02001280 v4l2_ctrl_handler_free(hdl);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001281 v4l2_device_unregister(&dev->v4l2_dev);
1282free_dev:
1283 kfree(dev);
1284 return ret;
1285}
1286
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001287/* This routine allocates from 1 to n_devs virtual drivers.
1288
1289 The real maximum number of virtual drivers will depend on how many drivers
1290 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001291 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001292 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001293static int __init vivi_init(void)
1294{
Hans Verkuil730947b2010-04-10 04:13:53 -03001295 const struct font_desc *font = find_font("VGA8x16");
Hans Verkuil9185cbf2009-03-06 09:58:12 -03001296 int ret = 0, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001297
Hans Verkuil730947b2010-04-10 04:13:53 -03001298 if (font == NULL) {
1299 printk(KERN_ERR "vivi: could not find font\n");
1300 return -ENODEV;
1301 }
1302 font8x16 = font->data;
1303
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001304 if (n_devs <= 0)
1305 n_devs = 1;
1306
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001307 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001308 ret = vivi_create_instance(i);
1309 if (ret) {
1310 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001311 if (i)
1312 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001313 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001314 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001315 }
1316
1317 if (ret < 0) {
Hans Verkuil730947b2010-04-10 04:13:53 -03001318 printk(KERN_ERR "vivi: error %d while loading driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001319 return ret;
1320 }
1321
1322 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001323 "Capture Board ver %s successfully loaded.\n",
1324 VIVI_VERSION);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001325
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001326 /* n_devs will reflect the actual number of allocated devices */
1327 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001328
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001329 return ret;
1330}
1331
1332static void __exit vivi_exit(void)
1333{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001334 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001335}
1336
1337module_init(vivi_init);
1338module_exit(vivi_exit);