blob: 2f0a1b40dd295460a089a30276cbedd05cf63124 [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;
Hans Verkuila1c894f2011-06-07 06:34:41 -0300166 struct {
167 /* autogain/gain cluster */
168 struct v4l2_ctrl *autogain;
169 struct v4l2_ctrl *gain;
170 };
Hans Verkuil7e996af2011-01-23 12:33:16 -0200171 struct v4l2_ctrl *volume;
172 struct v4l2_ctrl *button;
173 struct v4l2_ctrl *boolean;
174 struct v4l2_ctrl *int32;
175 struct v4l2_ctrl *int64;
176 struct v4l2_ctrl *menu;
177 struct v4l2_ctrl *string;
Hans Verkuil730947b2010-04-10 04:13:53 -0300178
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300179 spinlock_t slock;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300180 struct mutex mutex;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300181
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300182 /* various device info */
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -0300183 struct video_device *vfd;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300184
185 struct vivi_dmaqueue vidq;
186
187 /* Several counters */
Hans Verkuil730947b2010-04-10 04:13:53 -0300188 unsigned ms;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300189 unsigned long jiffies;
Hans Verkuil7e996af2011-01-23 12:33:16 -0200190 unsigned button_pressed;
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300191
192 int mv_count; /* Controls bars movement */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300193
194 /* Input Number */
195 int input;
Hans Verkuilc41ee242009-02-14 13:43:44 -0300196
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300197 /* video capture */
198 struct vivi_fmt *fmt;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300199 unsigned int width, height;
Pawel Osciake007a322011-01-19 13:02:29 -0200200 struct vb2_queue vb_vidq;
201 enum v4l2_field field;
202 unsigned int field_count;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300203
Hans Verkuil730947b2010-04-10 04:13:53 -0300204 u8 bars[9][3];
205 u8 line[MAX_WIDTH * 4];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300206};
207
208/* ------------------------------------------------------------------
209 DMA and thread functions
210 ------------------------------------------------------------------*/
211
212/* Bars and Colors should match positions */
213
214enum colors {
215 WHITE,
Hans Verkuil730947b2010-04-10 04:13:53 -0300216 AMBER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300217 CYAN,
218 GREEN,
219 MAGENTA,
220 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300221 BLUE,
222 BLACK,
Hans Verkuil730947b2010-04-10 04:13:53 -0300223 TEXT_BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300224};
225
Hans Verkuil730947b2010-04-10 04:13:53 -0300226/* R G B */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300227#define COLOR_WHITE {204, 204, 204}
Hans Verkuil730947b2010-04-10 04:13:53 -0300228#define COLOR_AMBER {208, 208, 0}
229#define COLOR_CYAN { 0, 206, 206}
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300230#define COLOR_GREEN { 0, 239, 0}
231#define COLOR_MAGENTA {239, 0, 239}
232#define COLOR_RED {205, 0, 0}
233#define COLOR_BLUE { 0, 0, 255}
234#define COLOR_BLACK { 0, 0, 0}
235
236struct bar_std {
Hans Verkuil730947b2010-04-10 04:13:53 -0300237 u8 bar[9][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300238};
239
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300240/* Maximum number of bars are 10 - otherwise, the input print code
241 should be modified */
242static struct bar_std bars[] = {
243 { /* Standard ITU-R color bar sequence */
Hans Verkuil730947b2010-04-10 04:13:53 -0300244 { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN,
245 COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300246 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300247 { COLOR_WHITE, COLOR_AMBER, COLOR_BLACK, COLOR_WHITE,
248 COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, COLOR_AMBER, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300249 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300250 { COLOR_WHITE, COLOR_CYAN, COLOR_BLACK, COLOR_WHITE,
251 COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, COLOR_CYAN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300252 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300253 { COLOR_WHITE, COLOR_GREEN, COLOR_BLACK, COLOR_WHITE,
254 COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, COLOR_GREEN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300255 },
256};
257
258#define NUM_INPUTS ARRAY_SIZE(bars)
259
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300260#define TO_Y(r, g, b) \
261 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300262/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300263#define TO_V(r, g, b) \
264 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300265/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300266#define TO_U(r, g, b) \
267 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300268
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300269/* precalculate color bar values to speed up rendering */
Hans Verkuil730947b2010-04-10 04:13:53 -0300270static void precalculate_bars(struct vivi_dev *dev)
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300271{
Hans Verkuil730947b2010-04-10 04:13:53 -0300272 u8 r, g, b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300273 int k, is_yuv;
274
Hans Verkuil730947b2010-04-10 04:13:53 -0300275 for (k = 0; k < 9; k++) {
276 r = bars[dev->input].bar[k][0];
277 g = bars[dev->input].bar[k][1];
278 b = bars[dev->input].bar[k][2];
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300279 is_yuv = 0;
280
Hans Verkuil730947b2010-04-10 04:13:53 -0300281 switch (dev->fmt->fourcc) {
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300282 case V4L2_PIX_FMT_YUYV:
283 case V4L2_PIX_FMT_UYVY:
284 is_yuv = 1;
285 break;
286 case V4L2_PIX_FMT_RGB565:
287 case V4L2_PIX_FMT_RGB565X:
288 r >>= 3;
289 g >>= 2;
290 b >>= 3;
291 break;
292 case V4L2_PIX_FMT_RGB555:
293 case V4L2_PIX_FMT_RGB555X:
294 r >>= 3;
295 g >>= 3;
296 b >>= 3;
297 break;
298 }
299
300 if (is_yuv) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300301 dev->bars[k][0] = TO_Y(r, g, b); /* Luma */
302 dev->bars[k][1] = TO_U(r, g, b); /* Cb */
303 dev->bars[k][2] = TO_V(r, g, b); /* Cr */
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300304 } else {
Hans Verkuil730947b2010-04-10 04:13:53 -0300305 dev->bars[k][0] = r;
306 dev->bars[k][1] = g;
307 dev->bars[k][2] = b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300308 }
309 }
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300310}
311
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300312#define TSTAMP_MIN_Y 24
313#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
314#define TSTAMP_INPUT_X 10
315#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300316
Hans Verkuil730947b2010-04-10 04:13:53 -0300317static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos)
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300318{
Hans Verkuil730947b2010-04-10 04:13:53 -0300319 u8 r_y, g_u, b_v;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300320 int color;
Hans Verkuil730947b2010-04-10 04:13:53 -0300321 u8 *p;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300322
Hans Verkuil730947b2010-04-10 04:13:53 -0300323 r_y = dev->bars[colorpos][0]; /* R or precalculated Y */
324 g_u = dev->bars[colorpos][1]; /* G or precalculated U */
325 b_v = dev->bars[colorpos][2]; /* B or precalculated V */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300326
327 for (color = 0; color < 4; color++) {
328 p = buf + color;
329
Hans Verkuil730947b2010-04-10 04:13:53 -0300330 switch (dev->fmt->fourcc) {
Magnus Dammd891f472008-10-14 12:47:09 -0300331 case V4L2_PIX_FMT_YUYV:
332 switch (color) {
333 case 0:
334 case 2:
335 *p = r_y;
336 break;
337 case 1:
338 *p = g_u;
339 break;
340 case 3:
341 *p = b_v;
342 break;
343 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300344 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300345 case V4L2_PIX_FMT_UYVY:
346 switch (color) {
347 case 1:
348 case 3:
349 *p = r_y;
350 break;
351 case 0:
352 *p = g_u;
353 break;
354 case 2:
355 *p = b_v;
356 break;
357 }
358 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300359 case V4L2_PIX_FMT_RGB565:
360 switch (color) {
361 case 0:
362 case 2:
363 *p = (g_u << 5) | b_v;
364 break;
365 case 1:
366 case 3:
367 *p = (r_y << 3) | (g_u >> 3);
368 break;
369 }
370 break;
371 case V4L2_PIX_FMT_RGB565X:
372 switch (color) {
373 case 0:
374 case 2:
375 *p = (r_y << 3) | (g_u >> 3);
376 break;
377 case 1:
378 case 3:
379 *p = (g_u << 5) | b_v;
380 break;
381 }
382 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300383 case V4L2_PIX_FMT_RGB555:
384 switch (color) {
385 case 0:
386 case 2:
387 *p = (g_u << 5) | b_v;
388 break;
389 case 1:
390 case 3:
391 *p = (r_y << 2) | (g_u >> 3);
392 break;
393 }
394 break;
395 case V4L2_PIX_FMT_RGB555X:
396 switch (color) {
397 case 0:
398 case 2:
399 *p = (r_y << 2) | (g_u >> 3);
400 break;
401 case 1:
402 case 3:
403 *p = (g_u << 5) | b_v;
404 break;
405 }
406 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300407 }
408 }
409}
410
Hans Verkuil730947b2010-04-10 04:13:53 -0300411static void precalculate_line(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300412{
Hans Verkuil730947b2010-04-10 04:13:53 -0300413 int w;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300414
Hans Verkuil730947b2010-04-10 04:13:53 -0300415 for (w = 0; w < dev->width * 2; w += 2) {
416 int colorpos = (w / (dev->width / 8) % 8);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300417
Hans Verkuil730947b2010-04-10 04:13:53 -0300418 gen_twopix(dev, dev->line + w * 2, colorpos);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300419 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300420}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300421
Hans Verkuil730947b2010-04-10 04:13:53 -0300422static void gen_text(struct vivi_dev *dev, char *basep,
423 int y, int x, char *text)
424{
425 int line;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300426
Hans Verkuil730947b2010-04-10 04:13:53 -0300427 /* Checks if it is possible to show string */
428 if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width)
429 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300430
431 /* Print stream time */
Hans Verkuil730947b2010-04-10 04:13:53 -0300432 for (line = y; line < y + 16; line++) {
433 int j = 0;
434 char *pos = basep + line * dev->width * 2 + x * 2;
435 char *s;
436
437 for (s = text; *s; s++) {
438 u8 chr = font8x16[*s * 16 + line - y];
439 int i;
440
441 for (i = 0; i < 7; i++, j++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300442 /* Draw white font on black background */
Hans Verkuil730947b2010-04-10 04:13:53 -0300443 if (chr & (1 << (7 - i)))
444 gen_twopix(dev, pos + j * 2, WHITE);
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300445 else
Hans Verkuil730947b2010-04-10 04:13:53 -0300446 gen_twopix(dev, pos + j * 2, TEXT_BLACK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300447 }
448 }
449 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300450}
Brandon Philips78718e52008-04-02 18:10:59 -0300451
Hans Verkuil730947b2010-04-10 04:13:53 -0300452static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300453{
Pawel Osciake007a322011-01-19 13:02:29 -0200454 int wmax = dev->width;
455 int hmax = dev->height;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300456 struct timeval ts;
Pawel Osciake007a322011-01-19 13:02:29 -0200457 void *vbuf = vb2_plane_vaddr(&buf->vb, 0);
Hans Verkuil730947b2010-04-10 04:13:53 -0300458 unsigned ms;
459 char str[100];
460 int h, line = 1;
Hans Verkuila1c894f2011-06-07 06:34:41 -0300461 s32 gain;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300462
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300463 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300464 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300465
Hans Verkuil730947b2010-04-10 04:13:53 -0300466 for (h = 0; h < hmax; h++)
467 memcpy(vbuf + h * wmax * 2, dev->line + (dev->mv_count % wmax) * 2, wmax * 2);
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300468
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300469 /* Updates stream time */
470
Hans Verkuil730947b2010-04-10 04:13:53 -0300471 dev->ms += jiffies_to_msecs(jiffies - dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300472 dev->jiffies = jiffies;
Hans Verkuil730947b2010-04-10 04:13:53 -0300473 ms = dev->ms;
474 snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d ",
475 (ms / (60 * 60 * 1000)) % 24,
476 (ms / (60 * 1000)) % 60,
477 (ms / 1000) % 60,
478 ms % 1000);
479 gen_text(dev, vbuf, line++ * 16, 16, str);
480 snprintf(str, sizeof(str), " %dx%d, input %d ",
481 dev->width, dev->height, dev->input);
482 gen_text(dev, vbuf, line++ * 16, 16, str);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300483
Hans Verkuila1c894f2011-06-07 06:34:41 -0300484 gain = v4l2_ctrl_g_ctrl(dev->gain);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200485 mutex_lock(&dev->ctrl_handler.lock);
Hans Verkuil730947b2010-04-10 04:13:53 -0300486 snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
Hans Verkuil7e996af2011-01-23 12:33:16 -0200487 dev->brightness->cur.val,
488 dev->contrast->cur.val,
489 dev->saturation->cur.val,
490 dev->hue->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300491 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuila1c894f2011-06-07 06:34:41 -0300492 snprintf(str, sizeof(str), " autogain %d, gain %3d, volume %3d ",
493 dev->autogain->cur.val, gain, dev->volume->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300494 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200495 snprintf(str, sizeof(str), " int32 %d, int64 %lld ",
496 dev->int32->cur.val,
497 dev->int64->cur.val64);
498 gen_text(dev, vbuf, line++ * 16, 16, str);
499 snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
500 dev->boolean->cur.val,
501 dev->menu->qmenu[dev->menu->cur.val],
502 dev->string->cur.string);
503 mutex_unlock(&dev->ctrl_handler.lock);
504 gen_text(dev, vbuf, line++ * 16, 16, str);
505 if (dev->button_pressed) {
506 dev->button_pressed--;
507 snprintf(str, sizeof(str), " button pressed!");
508 gen_text(dev, vbuf, line++ * 16, 16, str);
509 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300510
511 dev->mv_count += 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300512
Pawel Osciake007a322011-01-19 13:02:29 -0200513 buf->vb.v4l2_buf.field = dev->field;
514 dev->field_count++;
515 buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300516 do_gettimeofday(&ts);
Pawel Osciake007a322011-01-19 13:02:29 -0200517 buf->vb.v4l2_buf.timestamp = ts;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300518}
519
Hans Verkuil730947b2010-04-10 04:13:53 -0300520static void vivi_thread_tick(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300521{
Brandon Philips78718e52008-04-02 18:10:59 -0300522 struct vivi_dmaqueue *dma_q = &dev->vidq;
Hans Verkuil730947b2010-04-10 04:13:53 -0300523 struct vivi_buffer *buf;
Brandon Philips78718e52008-04-02 18:10:59 -0300524 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300525
Brandon Philips78718e52008-04-02 18:10:59 -0300526 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300527
Brandon Philips78718e52008-04-02 18:10:59 -0300528 spin_lock_irqsave(&dev->slock, flags);
529 if (list_empty(&dma_q->active)) {
530 dprintk(dev, 1, "No active queue to serve\n");
531 goto unlock;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300532 }
Brandon Philips78718e52008-04-02 18:10:59 -0300533
Pawel Osciake007a322011-01-19 13:02:29 -0200534 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
535 list_del(&buf->list);
Brandon Philips78718e52008-04-02 18:10:59 -0300536
Pawel Osciake007a322011-01-19 13:02:29 -0200537 do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
Brandon Philips78718e52008-04-02 18:10:59 -0300538
539 /* Fill buffer */
Hans Verkuil730947b2010-04-10 04:13:53 -0300540 vivi_fillbuff(dev, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300541 dprintk(dev, 1, "filled buffer %p\n", buf);
542
Pawel Osciake007a322011-01-19 13:02:29 -0200543 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
544 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
Brandon Philips78718e52008-04-02 18:10:59 -0300545unlock:
546 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300547}
548
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300549#define frames_to_ms(frames) \
550 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
551
Hans Verkuil730947b2010-04-10 04:13:53 -0300552static void vivi_sleep(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300553{
Brandon Philips78718e52008-04-02 18:10:59 -0300554 struct vivi_dmaqueue *dma_q = &dev->vidq;
555 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300556 DECLARE_WAITQUEUE(wait, current);
557
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300558 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300559 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300560
561 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300562 if (kthread_should_stop())
563 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300564
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300565 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300566 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300567
Hans Verkuil730947b2010-04-10 04:13:53 -0300568 vivi_thread_tick(dev);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300569
570 schedule_timeout_interruptible(timeout);
571
572stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300573 remove_wait_queue(&dma_q->wq, &wait);
574 try_to_freeze();
575}
576
Adrian Bunk972c3512006-04-27 21:06:50 -0300577static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300578{
Hans Verkuil730947b2010-04-10 04:13:53 -0300579 struct vivi_dev *dev = data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300580
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300581 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300582
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700583 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300584
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300585 for (;;) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300586 vivi_sleep(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300587
588 if (kthread_should_stop())
589 break;
590 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300591 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300592 return 0;
593}
594
Pawel Osciake007a322011-01-19 13:02:29 -0200595static int vivi_start_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300596{
Brandon Philips78718e52008-04-02 18:10:59 -0300597 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300598
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300599 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300600
Hans Verkuil730947b2010-04-10 04:13:53 -0300601 /* Resets frame counters */
602 dev->ms = 0;
603 dev->mv_count = 0;
604 dev->jiffies = jiffies;
605
606 dma_q->frame = 0;
607 dma_q->ini_jiffies = jiffies;
608 dma_q->kthread = kthread_run(vivi_thread, dev, dev->v4l2_dev.name);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300609
Akinobu Mita054afee2006-12-20 10:04:00 -0300610 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300611 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Pawel Osciake007a322011-01-19 13:02:29 -0200612 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300613 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300614 /* Wakes thread */
615 wake_up_interruptible(&dma_q->wq);
616
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300617 dprintk(dev, 1, "returning from %s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200618 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300619}
620
Pawel Osciake007a322011-01-19 13:02:29 -0200621static void vivi_stop_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300622{
Hans Verkuil730947b2010-04-10 04:13:53 -0300623 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300624
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300625 dprintk(dev, 1, "%s\n", __func__);
Hans Verkuil730947b2010-04-10 04:13:53 -0300626
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300627 /* shutdown control thread */
628 if (dma_q->kthread) {
629 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300630 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300631 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300632
Pawel Osciake007a322011-01-19 13:02:29 -0200633 /*
634 * Typical driver might need to wait here until dma engine stops.
635 * In this case we can abort imiedetly, so it's just a noop.
636 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300637
Pawel Osciake007a322011-01-19 13:02:29 -0200638 /* Release all active buffers */
639 while (!list_empty(&dma_q->active)) {
640 struct vivi_buffer *buf;
641 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
642 list_del(&buf->list);
643 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
644 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
645 }
646}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300647/* ------------------------------------------------------------------
648 Videobuf operations
649 ------------------------------------------------------------------*/
Pawel Osciake007a322011-01-19 13:02:29 -0200650static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
651 unsigned int *nplanes, unsigned long sizes[],
652 void *alloc_ctxs[])
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300653{
Pawel Osciake007a322011-01-19 13:02:29 -0200654 struct vivi_dev *dev = vb2_get_drv_priv(vq);
655 unsigned long size;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300656
Pawel Osciake007a322011-01-19 13:02:29 -0200657 size = dev->width * dev->height * 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300658
Pawel Osciake007a322011-01-19 13:02:29 -0200659 if (0 == *nbuffers)
660 *nbuffers = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300661
Pawel Osciake007a322011-01-19 13:02:29 -0200662 while (size * *nbuffers > vid_limit * 1024 * 1024)
663 (*nbuffers)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300664
Pawel Osciake007a322011-01-19 13:02:29 -0200665 *nplanes = 1;
666
667 sizes[0] = size;
668
669 /*
670 * videobuf2-vmalloc allocator is context-less so no need to set
671 * alloc_ctxs array.
672 */
673
674 dprintk(dev, 1, "%s, count=%d, size=%ld\n", __func__,
675 *nbuffers, size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300676
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300677 return 0;
678}
679
Pawel Osciake007a322011-01-19 13:02:29 -0200680static int buffer_init(struct vb2_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300681{
Pawel Osciake007a322011-01-19 13:02:29 -0200682 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300683
Hans Verkuil730947b2010-04-10 04:13:53 -0300684 BUG_ON(NULL == dev->fmt);
Brandon Philips78718e52008-04-02 18:10:59 -0300685
Pawel Osciake007a322011-01-19 13:02:29 -0200686 /*
687 * This callback is called once per buffer, after its allocation.
688 *
689 * Vivi does not allow changing format during streaming, but it is
690 * possible to do so when streaming is paused (i.e. in streamoff state).
691 * Buffers however are not freed when going into streamoff and so
692 * buffer size verification has to be done in buffer_prepare, on each
693 * qbuf.
694 * It would be best to move verification code here to buf_init and
695 * s_fmt though.
696 */
697
698 return 0;
699}
700
701static int buffer_prepare(struct vb2_buffer *vb)
702{
703 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
704 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
705 unsigned long size;
706
707 dprintk(dev, 1, "%s, field=%d\n", __func__, vb->v4l2_buf.field);
708
709 BUG_ON(NULL == dev->fmt);
710
711 /*
712 * Theses properties only change when queue is idle, see s_fmt.
713 * The below checks should not be performed here, on each
714 * buffer_prepare (i.e. on each qbuf). Most of the code in this function
715 * should thus be moved to buffer_init and s_fmt.
716 */
Hans Verkuil730947b2010-04-10 04:13:53 -0300717 if (dev->width < 48 || dev->width > MAX_WIDTH ||
718 dev->height < 32 || dev->height > MAX_HEIGHT)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300719 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300720
Pawel Osciake007a322011-01-19 13:02:29 -0200721 size = dev->width * dev->height * 2;
722 if (vb2_plane_size(vb, 0) < size) {
723 dprintk(dev, 1, "%s data will not fit into plane (%lu < %lu)\n",
724 __func__, vb2_plane_size(vb, 0), size);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300725 return -EINVAL;
Pawel Osciake007a322011-01-19 13:02:29 -0200726 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300727
Pawel Osciake007a322011-01-19 13:02:29 -0200728 vb2_set_plane_payload(&buf->vb, 0, size);
729
730 buf->fmt = dev->fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300731
Hans Verkuil730947b2010-04-10 04:13:53 -0300732 precalculate_bars(dev);
733 precalculate_line(dev);
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300734
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300735 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300736}
737
Pawel Osciake007a322011-01-19 13:02:29 -0200738static int buffer_finish(struct vb2_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300739{
Pawel Osciake007a322011-01-19 13:02:29 -0200740 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
741 dprintk(dev, 1, "%s\n", __func__);
742 return 0;
743}
744
745static void buffer_cleanup(struct vb2_buffer *vb)
746{
747 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
748 dprintk(dev, 1, "%s\n", __func__);
749
750}
751
752static void buffer_queue(struct vb2_buffer *vb)
753{
754 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
Hans Verkuil730947b2010-04-10 04:13:53 -0300755 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300756 struct vivi_dmaqueue *vidq = &dev->vidq;
Pawel Osciake007a322011-01-19 13:02:29 -0200757 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300758
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300759 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300760
Pawel Osciake007a322011-01-19 13:02:29 -0200761 spin_lock_irqsave(&dev->slock, flags);
762 list_add_tail(&buf->list, &vidq->active);
763 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300764}
765
Pawel Osciake007a322011-01-19 13:02:29 -0200766static int start_streaming(struct vb2_queue *vq)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300767{
Pawel Osciake007a322011-01-19 13:02:29 -0200768 struct vivi_dev *dev = vb2_get_drv_priv(vq);
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300769 dprintk(dev, 1, "%s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200770 return vivi_start_generating(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300771}
772
Pawel Osciake007a322011-01-19 13:02:29 -0200773/* abort streaming and wait for last buffer */
774static int stop_streaming(struct vb2_queue *vq)
775{
776 struct vivi_dev *dev = vb2_get_drv_priv(vq);
777 dprintk(dev, 1, "%s\n", __func__);
778 vivi_stop_generating(dev);
779 return 0;
780}
781
782static void vivi_lock(struct vb2_queue *vq)
783{
784 struct vivi_dev *dev = vb2_get_drv_priv(vq);
785 mutex_lock(&dev->mutex);
786}
787
788static void vivi_unlock(struct vb2_queue *vq)
789{
790 struct vivi_dev *dev = vb2_get_drv_priv(vq);
791 mutex_unlock(&dev->mutex);
792}
793
794
795static struct vb2_ops vivi_video_qops = {
796 .queue_setup = queue_setup,
797 .buf_init = buffer_init,
798 .buf_prepare = buffer_prepare,
799 .buf_finish = buffer_finish,
800 .buf_cleanup = buffer_cleanup,
801 .buf_queue = buffer_queue,
802 .start_streaming = start_streaming,
803 .stop_streaming = stop_streaming,
804 .wait_prepare = vivi_unlock,
805 .wait_finish = vivi_lock,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300806};
807
808/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300809 IOCTL vidioc handling
810 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300811static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300812 struct v4l2_capability *cap)
813{
Hans Verkuil730947b2010-04-10 04:13:53 -0300814 struct vivi_dev *dev = video_drvdata(file);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300815
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300816 strcpy(cap->driver, "vivi");
817 strcpy(cap->card, "vivi");
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300818 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Hans Verkuil730947b2010-04-10 04:13:53 -0300819 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
820 V4L2_CAP_READWRITE;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300821 return 0;
822}
823
Hans Verkuil78b526a2008-05-28 12:16:41 -0300824static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300825 struct v4l2_fmtdesc *f)
826{
Magnus Dammd891f472008-10-14 12:47:09 -0300827 struct vivi_fmt *fmt;
828
829 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300830 return -EINVAL;
831
Magnus Dammd891f472008-10-14 12:47:09 -0300832 fmt = &formats[f->index];
833
834 strlcpy(f->description, fmt->name, sizeof(f->description));
835 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300836 return 0;
837}
838
Hans Verkuil78b526a2008-05-28 12:16:41 -0300839static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300840 struct v4l2_format *f)
841{
Hans Verkuil730947b2010-04-10 04:13:53 -0300842 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300843
Hans Verkuil730947b2010-04-10 04:13:53 -0300844 f->fmt.pix.width = dev->width;
845 f->fmt.pix.height = dev->height;
Pawel Osciake007a322011-01-19 13:02:29 -0200846 f->fmt.pix.field = dev->field;
Hans Verkuil730947b2010-04-10 04:13:53 -0300847 f->fmt.pix.pixelformat = dev->fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300848 f->fmt.pix.bytesperline =
Hans Verkuil730947b2010-04-10 04:13:53 -0300849 (f->fmt.pix.width * dev->fmt->depth) >> 3;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300850 f->fmt.pix.sizeimage =
851 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil730947b2010-04-10 04:13:53 -0300852 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300853}
854
Hans Verkuil78b526a2008-05-28 12:16:41 -0300855static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300856 struct v4l2_format *f)
857{
Hans Verkuil730947b2010-04-10 04:13:53 -0300858 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300859 struct vivi_fmt *fmt;
860 enum v4l2_field field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300861
Magnus Dammd891f472008-10-14 12:47:09 -0300862 fmt = get_format(f);
863 if (!fmt) {
864 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
865 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300866 return -EINVAL;
867 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300868
869 field = f->fmt.pix.field;
870
871 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300872 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300873 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300874 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300875 return -EINVAL;
876 }
877
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300878 f->fmt.pix.field = field;
Hans Verkuil730947b2010-04-10 04:13:53 -0300879 v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
880 &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300881 f->fmt.pix.bytesperline =
882 (f->fmt.pix.width * fmt->depth) >> 3;
883 f->fmt.pix.sizeimage =
884 f->fmt.pix.height * f->fmt.pix.bytesperline;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300885 return 0;
886}
887
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300888static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
889 struct v4l2_format *f)
890{
Hans Verkuil730947b2010-04-10 04:13:53 -0300891 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200892 struct vb2_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300893
Hans Verkuil730947b2010-04-10 04:13:53 -0300894 int ret = vidioc_try_fmt_vid_cap(file, priv, f);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300895 if (ret < 0)
896 return ret;
897
Pawel Osciake007a322011-01-19 13:02:29 -0200898 if (vb2_is_streaming(q)) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300899 dprintk(dev, 1, "%s device busy\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200900 return -EBUSY;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300901 }
902
Hans Verkuil730947b2010-04-10 04:13:53 -0300903 dev->fmt = get_format(f);
904 dev->width = f->fmt.pix.width;
905 dev->height = f->fmt.pix.height;
Pawel Osciake007a322011-01-19 13:02:29 -0200906 dev->field = f->fmt.pix.field;
907
908 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300909}
910
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300911static int vidioc_reqbufs(struct file *file, void *priv,
912 struct v4l2_requestbuffers *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300913{
Hans Verkuil730947b2010-04-10 04:13:53 -0300914 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200915 return vb2_reqbufs(&dev->vb_vidq, p);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300916}
917
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300918static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300919{
Hans Verkuil730947b2010-04-10 04:13:53 -0300920 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200921 return vb2_querybuf(&dev->vb_vidq, p);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300922}
923
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300924static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300925{
Hans Verkuil730947b2010-04-10 04:13:53 -0300926 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200927 return vb2_qbuf(&dev->vb_vidq, p);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300928}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300929
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300930static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300931{
Hans Verkuil730947b2010-04-10 04:13:53 -0300932 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200933 return vb2_dqbuf(&dev->vb_vidq, p, file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300934}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300935
Adrian Bunkdc46ace2006-06-23 06:42:44 -0300936static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type 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);
Pawel Osciake007a322011-01-19 13:02:29 -0200939 return vb2_streamon(&dev->vb_vidq, i);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300940}
941
Adrian Bunkdc46ace2006-06-23 06:42:44 -0300942static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300943{
Hans Verkuil730947b2010-04-10 04:13:53 -0300944 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200945 return vb2_streamoff(&dev->vb_vidq, i);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300946}
947
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300948static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300949{
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300950 return 0;
951}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300952
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300953/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300954static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300955 struct v4l2_input *inp)
956{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300957 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300958 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300959
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300960 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -0300961 inp->std = V4L2_STD_525_60;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300962 sprintf(inp->name, "Camera %u", inp->index);
Hans Verkuil730947b2010-04-10 04:13:53 -0300963 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300964}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300965
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300966static int vidioc_g_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 *i = dev->input;
Hans Verkuil730947b2010-04-10 04:13:53 -0300971 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300972}
Hans Verkuil730947b2010-04-10 04:13:53 -0300973
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300974static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300975{
Hans Verkuil730947b2010-04-10 04:13:53 -0300976 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300977
978 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300979 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300980
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300981 dev->input = i;
Hans Verkuil730947b2010-04-10 04:13:53 -0300982 precalculate_bars(dev);
983 precalculate_line(dev);
984 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300985}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300986
Hans Verkuil730947b2010-04-10 04:13:53 -0300987/* --- controls ---------------------------------------------- */
Hans Verkuil7e996af2011-01-23 12:33:16 -0200988
Hans Verkuila1c894f2011-06-07 06:34:41 -0300989static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
990{
991 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
992
993 if (ctrl == dev->autogain)
994 dev->gain->val = jiffies & 0xff;
995 return 0;
996}
997
Hans Verkuil7e996af2011-01-23 12:33:16 -0200998static int vivi_s_ctrl(struct v4l2_ctrl *ctrl)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300999{
Hans Verkuil7e996af2011-01-23 12:33:16 -02001000 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001001
Hans Verkuil7e996af2011-01-23 12:33:16 -02001002 if (ctrl == dev->button)
1003 dev->button_pressed = 30;
1004 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001005}
1006
1007/* ------------------------------------------------------------------
1008 File operations for the device
1009 ------------------------------------------------------------------*/
1010
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001011static ssize_t
1012vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1013{
Hans Verkuil730947b2010-04-10 04:13:53 -03001014 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001015
Pawel Osciake007a322011-01-19 13:02:29 -02001016 dprintk(dev, 1, "read called\n");
1017 return vb2_read(&dev->vb_vidq, data, count, ppos,
1018 file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001019}
1020
1021static unsigned int
1022vivi_poll(struct file *file, struct poll_table_struct *wait)
1023{
Hans Verkuil730947b2010-04-10 04:13:53 -03001024 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -02001025 struct vb2_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001026
Harvey Harrison7e28adb2008-04-08 23:20:00 -03001027 dprintk(dev, 1, "%s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -02001028 return vb2_poll(q, file, wait);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001029}
1030
Hans Verkuilbec43662008-12-30 06:58:20 -03001031static int vivi_close(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001032{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001033 struct video_device *vdev = video_devdata(file);
Hans Verkuil730947b2010-04-10 04:13:53 -03001034 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001035
Pawel Osciake007a322011-01-19 13:02:29 -02001036 dprintk(dev, 1, "close called (dev=%s), file %p\n",
1037 video_device_node_name(vdev), file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001038
Hans Verkuil2e4784d2011-03-11 20:01:54 -03001039 if (v4l2_fh_is_singular_file(file))
Pawel Osciake007a322011-01-19 13:02:29 -02001040 vb2_queue_release(&dev->vb_vidq);
Hans Verkuil2e4784d2011-03-11 20:01:54 -03001041 return v4l2_fh_release(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001042}
1043
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001044static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001045{
Hans Verkuil730947b2010-04-10 04:13:53 -03001046 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001047 int ret;
1048
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001049 dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001050
Pawel Osciake007a322011-01-19 13:02:29 -02001051 ret = vb2_mmap(&dev->vb_vidq, vma);
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001052 dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n",
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001053 (unsigned long)vma->vm_start,
Hans Verkuil730947b2010-04-10 04:13:53 -03001054 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001055 ret);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001056 return ret;
1057}
1058
Hans Verkuil7e996af2011-01-23 12:33:16 -02001059static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
Hans Verkuila1c894f2011-06-07 06:34:41 -03001060 .g_volatile_ctrl = vivi_g_volatile_ctrl,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001061 .s_ctrl = vivi_s_ctrl,
1062};
1063
1064#define VIVI_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
1065
1066static const struct v4l2_ctrl_config vivi_ctrl_button = {
1067 .ops = &vivi_ctrl_ops,
1068 .id = VIVI_CID_CUSTOM_BASE + 0,
1069 .name = "Button",
1070 .type = V4L2_CTRL_TYPE_BUTTON,
1071};
1072
1073static const struct v4l2_ctrl_config vivi_ctrl_boolean = {
1074 .ops = &vivi_ctrl_ops,
1075 .id = VIVI_CID_CUSTOM_BASE + 1,
1076 .name = "Boolean",
1077 .type = V4L2_CTRL_TYPE_BOOLEAN,
1078 .min = 0,
1079 .max = 1,
1080 .step = 1,
1081 .def = 1,
1082};
1083
1084static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
1085 .ops = &vivi_ctrl_ops,
1086 .id = VIVI_CID_CUSTOM_BASE + 2,
1087 .name = "Integer 32 Bits",
1088 .type = V4L2_CTRL_TYPE_INTEGER,
Hans Verkuil5b283022011-01-11 17:32:28 -03001089 .min = 0x80000000,
1090 .max = 0x7fffffff,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001091 .step = 1,
1092};
1093
1094static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
1095 .ops = &vivi_ctrl_ops,
1096 .id = VIVI_CID_CUSTOM_BASE + 3,
1097 .name = "Integer 64 Bits",
1098 .type = V4L2_CTRL_TYPE_INTEGER64,
1099};
1100
1101static const char * const vivi_ctrl_menu_strings[] = {
1102 "Menu Item 0 (Skipped)",
1103 "Menu Item 1",
1104 "Menu Item 2 (Skipped)",
1105 "Menu Item 3",
1106 "Menu Item 4",
1107 "Menu Item 5 (Skipped)",
1108 NULL,
1109};
1110
1111static const struct v4l2_ctrl_config vivi_ctrl_menu = {
1112 .ops = &vivi_ctrl_ops,
1113 .id = VIVI_CID_CUSTOM_BASE + 4,
1114 .name = "Menu",
1115 .type = V4L2_CTRL_TYPE_MENU,
1116 .min = 1,
1117 .max = 4,
1118 .def = 3,
1119 .menu_skip_mask = 0x04,
1120 .qmenu = vivi_ctrl_menu_strings,
1121};
1122
1123static const struct v4l2_ctrl_config vivi_ctrl_string = {
1124 .ops = &vivi_ctrl_ops,
1125 .id = VIVI_CID_CUSTOM_BASE + 5,
1126 .name = "String",
1127 .type = V4L2_CTRL_TYPE_STRING,
1128 .min = 2,
1129 .max = 4,
1130 .step = 1,
1131};
1132
Hans Verkuilbec43662008-12-30 06:58:20 -03001133static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001134 .owner = THIS_MODULE,
Hans Verkuil2e4784d2011-03-11 20:01:54 -03001135 .open = v4l2_fh_open,
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001136 .release = vivi_close,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001137 .read = vivi_read,
1138 .poll = vivi_poll,
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001139 .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001140 .mmap = vivi_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001141};
1142
Hans Verkuila3998102008-07-21 02:57:38 -03001143static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001144 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001145 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1146 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1147 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1148 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001149 .vidioc_reqbufs = vidioc_reqbufs,
1150 .vidioc_querybuf = vidioc_querybuf,
1151 .vidioc_qbuf = vidioc_qbuf,
1152 .vidioc_dqbuf = vidioc_dqbuf,
1153 .vidioc_s_std = vidioc_s_std,
1154 .vidioc_enum_input = vidioc_enum_input,
1155 .vidioc_g_input = vidioc_g_input,
1156 .vidioc_s_input = vidioc_s_input,
Hans Verkuil730947b2010-04-10 04:13:53 -03001157 .vidioc_streamon = vidioc_streamon,
1158 .vidioc_streamoff = vidioc_streamoff,
Hans Verkuila3998102008-07-21 02:57:38 -03001159};
1160
1161static struct video_device vivi_template = {
1162 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001163 .fops = &vivi_fops,
1164 .ioctl_ops = &vivi_ioctl_ops,
Hans Verkuila3998102008-07-21 02:57:38 -03001165 .release = video_device_release,
1166
Mauro Carvalho Chehab784c6682007-12-13 06:35:26 -03001167 .tvnorms = V4L2_STD_525_60,
Mauro Carvalho Chehabe75f9ce2006-11-20 13:19:20 -03001168 .current_norm = V4L2_STD_NTSC_M,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001169};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001170
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001171/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001172 Initialization and module stuff
1173 ------------------------------------------------------------------*/
1174
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001175static int vivi_release(void)
1176{
1177 struct vivi_dev *dev;
1178 struct list_head *list;
1179
1180 while (!list_empty(&vivi_devlist)) {
1181 list = vivi_devlist.next;
1182 list_del(list);
1183 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1184
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001185 v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
1186 video_device_node_name(dev->vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001187 video_unregister_device(dev->vfd);
1188 v4l2_device_unregister(&dev->v4l2_dev);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001189 v4l2_ctrl_handler_free(&dev->ctrl_handler);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001190 kfree(dev);
1191 }
1192
1193 return 0;
1194}
1195
Hans Verkuilc41ee242009-02-14 13:43:44 -03001196static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001197{
1198 struct vivi_dev *dev;
1199 struct video_device *vfd;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001200 struct v4l2_ctrl_handler *hdl;
Pawel Osciake007a322011-01-19 13:02:29 -02001201 struct vb2_queue *q;
Hans Verkuil730947b2010-04-10 04:13:53 -03001202 int ret;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001203
1204 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1205 if (!dev)
1206 return -ENOMEM;
1207
1208 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001209 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001210 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1211 if (ret)
1212 goto free_dev;
1213
Hans Verkuil730947b2010-04-10 04:13:53 -03001214 dev->fmt = &formats[0];
1215 dev->width = 640;
1216 dev->height = 480;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001217 hdl = &dev->ctrl_handler;
1218 v4l2_ctrl_handler_init(hdl, 11);
1219 dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1220 V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
1221 dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1222 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1223 dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1224 V4L2_CID_CONTRAST, 0, 255, 1, 16);
1225 dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1226 V4L2_CID_SATURATION, 0, 255, 1, 127);
1227 dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1228 V4L2_CID_HUE, -128, 127, 1, 0);
Hans Verkuila1c894f2011-06-07 06:34:41 -03001229 dev->autogain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1230 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1231 dev->gain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1232 V4L2_CID_GAIN, 0, 255, 1, 100);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001233 dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
1234 dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
1235 dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);
1236 dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL);
1237 dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL);
1238 dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL);
1239 if (hdl->error) {
1240 ret = hdl->error;
1241 goto unreg_dev;
1242 }
Hans Verkuila1c894f2011-06-07 06:34:41 -03001243 v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001244 dev->v4l2_dev.ctrl_handler = hdl;
Hans Verkuil730947b2010-04-10 04:13:53 -03001245
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001246 /* initialize locks */
1247 spin_lock_init(&dev->slock);
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001248
Pawel Osciake007a322011-01-19 13:02:29 -02001249 /* initialize queue */
1250 q = &dev->vb_vidq;
1251 memset(q, 0, sizeof(dev->vb_vidq));
1252 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1253 q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1254 q->drv_priv = dev;
1255 q->buf_struct_size = sizeof(struct vivi_buffer);
1256 q->ops = &vivi_video_qops;
1257 q->mem_ops = &vb2_vmalloc_memops;
1258
1259 vb2_queue_init(q);
1260
1261 mutex_init(&dev->mutex);
Hans Verkuil730947b2010-04-10 04:13:53 -03001262
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001263 /* init video dma queues */
1264 INIT_LIST_HEAD(&dev->vidq.active);
1265 init_waitqueue_head(&dev->vidq.wq);
1266
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001267 ret = -ENOMEM;
1268 vfd = video_device_alloc();
1269 if (!vfd)
1270 goto unreg_dev;
1271
1272 *vfd = vivi_template;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -03001273 vfd->debug = debug;
Hans Verkuil730947b2010-04-10 04:13:53 -03001274 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuilb1a873a2011-03-22 10:14:07 -03001275 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Pawel Osciake007a322011-01-19 13:02:29 -02001276
1277 /*
1278 * Provide a mutex to v4l2 core. It will be used to protect
1279 * all fops and v4l2 ioctls.
1280 */
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001281 vfd->lock = &dev->mutex;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001282
1283 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1284 if (ret < 0)
1285 goto rel_vdev;
1286
1287 video_set_drvdata(vfd, dev);
1288
1289 /* Now that everything is fine, let's add it to device list */
1290 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1291
Roel Kluin7de0b872009-12-16 13:06:33 -03001292 if (video_nr != -1)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001293 video_nr++;
1294
1295 dev->vfd = vfd;
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001296 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
1297 video_device_node_name(vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001298 return 0;
1299
1300rel_vdev:
1301 video_device_release(vfd);
1302unreg_dev:
Hans Verkuil7e996af2011-01-23 12:33:16 -02001303 v4l2_ctrl_handler_free(hdl);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001304 v4l2_device_unregister(&dev->v4l2_dev);
1305free_dev:
1306 kfree(dev);
1307 return ret;
1308}
1309
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001310/* This routine allocates from 1 to n_devs virtual drivers.
1311
1312 The real maximum number of virtual drivers will depend on how many drivers
1313 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001314 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001315 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001316static int __init vivi_init(void)
1317{
Hans Verkuil730947b2010-04-10 04:13:53 -03001318 const struct font_desc *font = find_font("VGA8x16");
Hans Verkuil9185cbf2009-03-06 09:58:12 -03001319 int ret = 0, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001320
Hans Verkuil730947b2010-04-10 04:13:53 -03001321 if (font == NULL) {
1322 printk(KERN_ERR "vivi: could not find font\n");
1323 return -ENODEV;
1324 }
1325 font8x16 = font->data;
1326
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001327 if (n_devs <= 0)
1328 n_devs = 1;
1329
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001330 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001331 ret = vivi_create_instance(i);
1332 if (ret) {
1333 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001334 if (i)
1335 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001336 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001337 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001338 }
1339
1340 if (ret < 0) {
Hans Verkuil730947b2010-04-10 04:13:53 -03001341 printk(KERN_ERR "vivi: error %d while loading driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001342 return ret;
1343 }
1344
1345 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001346 "Capture Board ver %s successfully loaded.\n",
1347 VIVI_VERSION);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001348
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001349 /* n_devs will reflect the actual number of allocated devices */
1350 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001351
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001352 return ret;
1353}
1354
1355static void __exit vivi_exit(void)
1356{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001357 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001358}
1359
1360module_init(vivi_init);
1361module_exit(vivi_exit);