blob: 1e8c4f3ab60244a89bc4321a30a03c2947e9b50d [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 Verkuilc7a52f82011-06-07 10:20:23 -030034#include <media/v4l2-event.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030035#include <media/v4l2-common.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030036
Mauro Carvalho Chehab584ce482008-06-10 15:21:49 -030037#define VIVI_MODULE_NAME "vivi"
Carl Karsten745271a2008-06-10 00:02:32 -030038
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030039/* Wake up at about 30 fps */
40#define WAKE_NUMERATOR 30
41#define WAKE_DENOMINATOR 1001
42#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
43
Hans Verkuil730947b2010-04-10 04:13:53 -030044#define MAX_WIDTH 1920
45#define MAX_HEIGHT 1200
46
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030047#define VIVI_VERSION "0.8.1"
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030048
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030049MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
50MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
51MODULE_LICENSE("Dual BSD/GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030052MODULE_VERSION(VIVI_VERSION);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030053
54static unsigned video_nr = -1;
55module_param(video_nr, uint, 0644);
56MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
57
58static unsigned n_devs = 1;
59module_param(n_devs, uint, 0644);
60MODULE_PARM_DESC(n_devs, "number of video devices to create");
61
62static unsigned debug;
63module_param(debug, uint, 0644);
64MODULE_PARM_DESC(debug, "activates debug info");
65
66static unsigned int vid_limit = 16;
67module_param(vid_limit, uint, 0644);
68MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
69
Hans Verkuil730947b2010-04-10 04:13:53 -030070/* Global font descriptor */
71static const u8 *font8x16;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030072
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030073#define dprintk(dev, level, fmt, arg...) \
74 v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030075
76/* ------------------------------------------------------------------
77 Basic structures
78 ------------------------------------------------------------------*/
79
80struct vivi_fmt {
81 char *name;
82 u32 fourcc; /* v4l2 format id */
83 int depth;
84};
85
Magnus Dammd891f472008-10-14 12:47:09 -030086static struct vivi_fmt formats[] = {
87 {
88 .name = "4:2:2, packed, YUYV",
89 .fourcc = V4L2_PIX_FMT_YUYV,
90 .depth = 16,
91 },
Magnus Dammfca36ba2008-10-14 12:47:25 -030092 {
93 .name = "4:2:2, packed, UYVY",
94 .fourcc = V4L2_PIX_FMT_UYVY,
95 .depth = 16,
96 },
Magnus Dammaeadb5d2008-10-14 12:47:35 -030097 {
Hans Verkuil3d51dca2012-05-02 03:15:11 -030098 .name = "4:2:2, packed, YVYU",
99 .fourcc = V4L2_PIX_FMT_YVYU,
100 .depth = 16,
101 },
102 {
103 .name = "4:2:2, packed, VYUY",
104 .fourcc = V4L2_PIX_FMT_VYUY,
105 .depth = 16,
106 },
107 {
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300108 .name = "RGB565 (LE)",
109 .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
110 .depth = 16,
111 },
112 {
113 .name = "RGB565 (BE)",
114 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
115 .depth = 16,
116 },
Magnus Dammdef52392008-10-14 12:47:43 -0300117 {
118 .name = "RGB555 (LE)",
119 .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
120 .depth = 16,
121 },
122 {
123 .name = "RGB555 (BE)",
124 .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
125 .depth = 16,
126 },
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300127 {
128 .name = "RGB24 (LE)",
129 .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */
130 .depth = 24,
131 },
132 {
133 .name = "RGB24 (BE)",
134 .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */
135 .depth = 24,
136 },
137 {
138 .name = "RGB32 (LE)",
139 .fourcc = V4L2_PIX_FMT_RGB32, /* argb */
140 .depth = 32,
141 },
142 {
143 .name = "RGB32 (BE)",
144 .fourcc = V4L2_PIX_FMT_BGR32, /* bgra */
145 .depth = 32,
146 },
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300147};
148
Magnus Dammd891f472008-10-14 12:47:09 -0300149static struct vivi_fmt *get_format(struct v4l2_format *f)
150{
151 struct vivi_fmt *fmt;
152 unsigned int k;
153
154 for (k = 0; k < ARRAY_SIZE(formats); k++) {
155 fmt = &formats[k];
156 if (fmt->fourcc == f->fmt.pix.pixelformat)
157 break;
158 }
159
160 if (k == ARRAY_SIZE(formats))
161 return NULL;
162
163 return &formats[k];
164}
165
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300166/* buffer for one video frame */
167struct vivi_buffer {
168 /* common v4l buffer stuff -- must be first */
Pawel Osciake007a322011-01-19 13:02:29 -0200169 struct vb2_buffer vb;
170 struct list_head list;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300171 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300172};
173
174struct vivi_dmaqueue {
175 struct list_head active;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300176
177 /* thread for generating video stream*/
178 struct task_struct *kthread;
179 wait_queue_head_t wq;
180 /* Counters to control fps rate */
181 int frame;
182 int ini_jiffies;
183};
184
185static LIST_HEAD(vivi_devlist);
186
187struct vivi_dev {
188 struct list_head vivi_devlist;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300189 struct v4l2_device v4l2_dev;
Hans Verkuil7e996af2011-01-23 12:33:16 -0200190 struct v4l2_ctrl_handler ctrl_handler;
Hans Verkuil70bd97a2012-06-09 11:27:43 -0300191 struct video_device vdev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300192
Hans Verkuil730947b2010-04-10 04:13:53 -0300193 /* controls */
Hans Verkuil7e996af2011-01-23 12:33:16 -0200194 struct v4l2_ctrl *brightness;
195 struct v4l2_ctrl *contrast;
196 struct v4l2_ctrl *saturation;
197 struct v4l2_ctrl *hue;
Hans Verkuila1c894f2011-06-07 06:34:41 -0300198 struct {
199 /* autogain/gain cluster */
200 struct v4l2_ctrl *autogain;
201 struct v4l2_ctrl *gain;
202 };
Hans Verkuil7e996af2011-01-23 12:33:16 -0200203 struct v4l2_ctrl *volume;
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300204 struct v4l2_ctrl *alpha;
Hans Verkuil7e996af2011-01-23 12:33:16 -0200205 struct v4l2_ctrl *button;
206 struct v4l2_ctrl *boolean;
207 struct v4l2_ctrl *int32;
208 struct v4l2_ctrl *int64;
209 struct v4l2_ctrl *menu;
210 struct v4l2_ctrl *string;
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300211 struct v4l2_ctrl *bitmask;
Sakari Ailusc5203312011-08-05 06:38:05 -0300212 struct v4l2_ctrl *int_menu;
Hans Verkuil730947b2010-04-10 04:13:53 -0300213
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300214 spinlock_t slock;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300215 struct mutex mutex;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300216
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300217 struct vivi_dmaqueue vidq;
218
219 /* Several counters */
Hans Verkuil730947b2010-04-10 04:13:53 -0300220 unsigned ms;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300221 unsigned long jiffies;
Hans Verkuil7e996af2011-01-23 12:33:16 -0200222 unsigned button_pressed;
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300223
224 int mv_count; /* Controls bars movement */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300225
226 /* Input Number */
227 int input;
Hans Verkuilc41ee242009-02-14 13:43:44 -0300228
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300229 /* video capture */
230 struct vivi_fmt *fmt;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300231 unsigned int width, height;
Pawel Osciake007a322011-01-19 13:02:29 -0200232 struct vb2_queue vb_vidq;
233 enum v4l2_field field;
234 unsigned int field_count;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300235
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300236 u8 bars[9][3];
237 u8 line[MAX_WIDTH * 8];
238 unsigned int pixelsize;
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300239 u8 alpha_component;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300240};
241
242/* ------------------------------------------------------------------
243 DMA and thread functions
244 ------------------------------------------------------------------*/
245
246/* Bars and Colors should match positions */
247
248enum colors {
249 WHITE,
Hans Verkuil730947b2010-04-10 04:13:53 -0300250 AMBER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300251 CYAN,
252 GREEN,
253 MAGENTA,
254 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300255 BLUE,
256 BLACK,
Hans Verkuil730947b2010-04-10 04:13:53 -0300257 TEXT_BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300258};
259
Hans Verkuil730947b2010-04-10 04:13:53 -0300260/* R G B */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300261#define COLOR_WHITE {204, 204, 204}
Hans Verkuil730947b2010-04-10 04:13:53 -0300262#define COLOR_AMBER {208, 208, 0}
263#define COLOR_CYAN { 0, 206, 206}
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300264#define COLOR_GREEN { 0, 239, 0}
265#define COLOR_MAGENTA {239, 0, 239}
266#define COLOR_RED {205, 0, 0}
267#define COLOR_BLUE { 0, 0, 255}
268#define COLOR_BLACK { 0, 0, 0}
269
270struct bar_std {
Hans Verkuil730947b2010-04-10 04:13:53 -0300271 u8 bar[9][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300272};
273
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300274/* Maximum number of bars are 10 - otherwise, the input print code
275 should be modified */
276static struct bar_std bars[] = {
277 { /* Standard ITU-R color bar sequence */
Hans Verkuil730947b2010-04-10 04:13:53 -0300278 { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN,
279 COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300280 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300281 { COLOR_WHITE, COLOR_AMBER, COLOR_BLACK, COLOR_WHITE,
282 COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, COLOR_AMBER, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300283 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300284 { COLOR_WHITE, COLOR_CYAN, COLOR_BLACK, COLOR_WHITE,
285 COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, COLOR_CYAN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300286 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300287 { COLOR_WHITE, COLOR_GREEN, COLOR_BLACK, COLOR_WHITE,
288 COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, COLOR_GREEN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300289 },
290};
291
292#define NUM_INPUTS ARRAY_SIZE(bars)
293
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300294#define TO_Y(r, g, b) \
295 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300296/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300297#define TO_V(r, g, b) \
298 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300299/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300300#define TO_U(r, g, b) \
301 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300302
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300303/* precalculate color bar values to speed up rendering */
Hans Verkuil730947b2010-04-10 04:13:53 -0300304static void precalculate_bars(struct vivi_dev *dev)
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300305{
Hans Verkuil730947b2010-04-10 04:13:53 -0300306 u8 r, g, b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300307 int k, is_yuv;
308
Hans Verkuil730947b2010-04-10 04:13:53 -0300309 for (k = 0; k < 9; k++) {
310 r = bars[dev->input].bar[k][0];
311 g = bars[dev->input].bar[k][1];
312 b = bars[dev->input].bar[k][2];
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300313 is_yuv = 0;
314
Hans Verkuil730947b2010-04-10 04:13:53 -0300315 switch (dev->fmt->fourcc) {
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300316 case V4L2_PIX_FMT_YUYV:
317 case V4L2_PIX_FMT_UYVY:
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300318 case V4L2_PIX_FMT_YVYU:
319 case V4L2_PIX_FMT_VYUY:
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300320 is_yuv = 1;
321 break;
322 case V4L2_PIX_FMT_RGB565:
323 case V4L2_PIX_FMT_RGB565X:
324 r >>= 3;
325 g >>= 2;
326 b >>= 3;
327 break;
328 case V4L2_PIX_FMT_RGB555:
329 case V4L2_PIX_FMT_RGB555X:
330 r >>= 3;
331 g >>= 3;
332 b >>= 3;
333 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300334 case V4L2_PIX_FMT_RGB24:
335 case V4L2_PIX_FMT_BGR24:
336 case V4L2_PIX_FMT_RGB32:
337 case V4L2_PIX_FMT_BGR32:
338 break;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300339 }
340
341 if (is_yuv) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300342 dev->bars[k][0] = TO_Y(r, g, b); /* Luma */
343 dev->bars[k][1] = TO_U(r, g, b); /* Cb */
344 dev->bars[k][2] = TO_V(r, g, b); /* Cr */
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300345 } else {
Hans Verkuil730947b2010-04-10 04:13:53 -0300346 dev->bars[k][0] = r;
347 dev->bars[k][1] = g;
348 dev->bars[k][2] = b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300349 }
350 }
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300351}
352
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300353#define TSTAMP_MIN_Y 24
354#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
355#define TSTAMP_INPUT_X 10
356#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300357
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300358/* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */
359static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos, bool odd)
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300360{
Hans Verkuil730947b2010-04-10 04:13:53 -0300361 u8 r_y, g_u, b_v;
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300362 u8 alpha = dev->alpha_component;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300363 int color;
Hans Verkuil730947b2010-04-10 04:13:53 -0300364 u8 *p;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300365
Hans Verkuil730947b2010-04-10 04:13:53 -0300366 r_y = dev->bars[colorpos][0]; /* R or precalculated Y */
367 g_u = dev->bars[colorpos][1]; /* G or precalculated U */
368 b_v = dev->bars[colorpos][2]; /* B or precalculated V */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300369
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300370 for (color = 0; color < dev->pixelsize; color++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300371 p = buf + color;
372
Hans Verkuil730947b2010-04-10 04:13:53 -0300373 switch (dev->fmt->fourcc) {
Magnus Dammd891f472008-10-14 12:47:09 -0300374 case V4L2_PIX_FMT_YUYV:
375 switch (color) {
376 case 0:
Magnus Dammd891f472008-10-14 12:47:09 -0300377 *p = r_y;
378 break;
379 case 1:
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300380 *p = odd ? b_v : g_u;
Magnus Dammd891f472008-10-14 12:47:09 -0300381 break;
382 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300383 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300384 case V4L2_PIX_FMT_UYVY:
385 switch (color) {
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300386 case 0:
387 *p = odd ? b_v : g_u;
388 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300389 case 1:
Magnus Dammfca36ba2008-10-14 12:47:25 -0300390 *p = r_y;
391 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300392 }
393 break;
394 case V4L2_PIX_FMT_YVYU:
395 switch (color) {
Magnus Dammfca36ba2008-10-14 12:47:25 -0300396 case 0:
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300397 *p = r_y;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300398 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300399 case 1:
400 *p = odd ? g_u : b_v;
401 break;
402 }
403 break;
404 case V4L2_PIX_FMT_VYUY:
405 switch (color) {
406 case 0:
407 *p = odd ? g_u : b_v;
408 break;
409 case 1:
410 *p = r_y;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300411 break;
412 }
413 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300414 case V4L2_PIX_FMT_RGB565:
415 switch (color) {
416 case 0:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300417 *p = (g_u << 5) | b_v;
418 break;
419 case 1:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300420 *p = (r_y << 3) | (g_u >> 3);
421 break;
422 }
423 break;
424 case V4L2_PIX_FMT_RGB565X:
425 switch (color) {
426 case 0:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300427 *p = (r_y << 3) | (g_u >> 3);
428 break;
429 case 1:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300430 *p = (g_u << 5) | b_v;
431 break;
432 }
433 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300434 case V4L2_PIX_FMT_RGB555:
435 switch (color) {
436 case 0:
Magnus Dammdef52392008-10-14 12:47:43 -0300437 *p = (g_u << 5) | b_v;
438 break;
439 case 1:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300440 *p = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
Magnus Dammdef52392008-10-14 12:47:43 -0300441 break;
442 }
443 break;
444 case V4L2_PIX_FMT_RGB555X:
445 switch (color) {
446 case 0:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300447 *p = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
Magnus Dammdef52392008-10-14 12:47:43 -0300448 break;
449 case 1:
Magnus Dammdef52392008-10-14 12:47:43 -0300450 *p = (g_u << 5) | b_v;
451 break;
452 }
453 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300454 case V4L2_PIX_FMT_RGB24:
455 switch (color) {
456 case 0:
457 *p = r_y;
458 break;
459 case 1:
460 *p = g_u;
461 break;
462 case 2:
463 *p = b_v;
464 break;
465 }
466 break;
467 case V4L2_PIX_FMT_BGR24:
468 switch (color) {
469 case 0:
470 *p = b_v;
471 break;
472 case 1:
473 *p = g_u;
474 break;
475 case 2:
476 *p = r_y;
477 break;
478 }
479 break;
480 case V4L2_PIX_FMT_RGB32:
481 switch (color) {
482 case 0:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300483 *p = alpha;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300484 break;
485 case 1:
486 *p = r_y;
487 break;
488 case 2:
489 *p = g_u;
490 break;
491 case 3:
492 *p = b_v;
493 break;
494 }
495 break;
496 case V4L2_PIX_FMT_BGR32:
497 switch (color) {
498 case 0:
499 *p = b_v;
500 break;
501 case 1:
502 *p = g_u;
503 break;
504 case 2:
505 *p = r_y;
506 break;
507 case 3:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300508 *p = alpha;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300509 break;
510 }
511 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300512 }
513 }
514}
515
Hans Verkuil730947b2010-04-10 04:13:53 -0300516static void precalculate_line(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300517{
Hans Verkuil730947b2010-04-10 04:13:53 -0300518 int w;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300519
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300520 for (w = 0; w < dev->width * 2; w++) {
521 int colorpos = w / (dev->width / 8) % 8;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300522
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300523 gen_twopix(dev, dev->line + w * dev->pixelsize, colorpos, w & 1);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300524 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300525}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300526
Hans Verkuil730947b2010-04-10 04:13:53 -0300527static void gen_text(struct vivi_dev *dev, char *basep,
528 int y, int x, char *text)
529{
530 int line;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300531
Hans Verkuil730947b2010-04-10 04:13:53 -0300532 /* Checks if it is possible to show string */
533 if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width)
534 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300535
536 /* Print stream time */
Hans Verkuil730947b2010-04-10 04:13:53 -0300537 for (line = y; line < y + 16; line++) {
538 int j = 0;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300539 char *pos = basep + line * dev->width * dev->pixelsize + x * dev->pixelsize;
Hans Verkuil730947b2010-04-10 04:13:53 -0300540 char *s;
541
542 for (s = text; *s; s++) {
543 u8 chr = font8x16[*s * 16 + line - y];
544 int i;
545
546 for (i = 0; i < 7; i++, j++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300547 /* Draw white font on black background */
Hans Verkuil730947b2010-04-10 04:13:53 -0300548 if (chr & (1 << (7 - i)))
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300549 gen_twopix(dev, pos + j * dev->pixelsize, WHITE, (x+y) & 1);
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300550 else
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300551 gen_twopix(dev, pos + j * dev->pixelsize, TEXT_BLACK, (x+y) & 1);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300552 }
553 }
554 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300555}
Brandon Philips78718e52008-04-02 18:10:59 -0300556
Hans Verkuil730947b2010-04-10 04:13:53 -0300557static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300558{
Pawel Osciake007a322011-01-19 13:02:29 -0200559 int wmax = dev->width;
560 int hmax = dev->height;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300561 struct timeval ts;
Pawel Osciake007a322011-01-19 13:02:29 -0200562 void *vbuf = vb2_plane_vaddr(&buf->vb, 0);
Hans Verkuil730947b2010-04-10 04:13:53 -0300563 unsigned ms;
564 char str[100];
565 int h, line = 1;
Hans Verkuila1c894f2011-06-07 06:34:41 -0300566 s32 gain;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300567
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300568 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300569 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300570
Hans Verkuil730947b2010-04-10 04:13:53 -0300571 for (h = 0; h < hmax; h++)
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300572 memcpy(vbuf + h * wmax * dev->pixelsize,
573 dev->line + (dev->mv_count % wmax) * dev->pixelsize,
574 wmax * dev->pixelsize);
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300575
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300576 /* Updates stream time */
577
Hans Verkuil730947b2010-04-10 04:13:53 -0300578 dev->ms += jiffies_to_msecs(jiffies - dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300579 dev->jiffies = jiffies;
Hans Verkuil730947b2010-04-10 04:13:53 -0300580 ms = dev->ms;
581 snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d ",
582 (ms / (60 * 60 * 1000)) % 24,
583 (ms / (60 * 1000)) % 60,
584 (ms / 1000) % 60,
585 ms % 1000);
586 gen_text(dev, vbuf, line++ * 16, 16, str);
587 snprintf(str, sizeof(str), " %dx%d, input %d ",
588 dev->width, dev->height, dev->input);
589 gen_text(dev, vbuf, line++ * 16, 16, str);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300590
Hans Verkuila1c894f2011-06-07 06:34:41 -0300591 gain = v4l2_ctrl_g_ctrl(dev->gain);
Sakari Ailus77e7c4e2012-01-24 21:05:34 -0300592 mutex_lock(dev->ctrl_handler.lock);
Hans Verkuil730947b2010-04-10 04:13:53 -0300593 snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
Hans Verkuil7e996af2011-01-23 12:33:16 -0200594 dev->brightness->cur.val,
595 dev->contrast->cur.val,
596 dev->saturation->cur.val,
597 dev->hue->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300598 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300599 snprintf(str, sizeof(str), " autogain %d, gain %3d, volume %3d, alpha 0x%02x ",
600 dev->autogain->cur.val, gain, dev->volume->cur.val,
601 dev->alpha->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300602 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300603 snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
Hans Verkuil7e996af2011-01-23 12:33:16 -0200604 dev->int32->cur.val,
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300605 dev->int64->cur.val64,
606 dev->bitmask->cur.val);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200607 gen_text(dev, vbuf, line++ * 16, 16, str);
608 snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
609 dev->boolean->cur.val,
610 dev->menu->qmenu[dev->menu->cur.val],
611 dev->string->cur.string);
Hans Verkuilf70cfc72012-04-19 11:44:18 -0300612 gen_text(dev, vbuf, line++ * 16, 16, str);
Sakari Ailusc5203312011-08-05 06:38:05 -0300613 snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
614 dev->int_menu->qmenu_int[dev->int_menu->cur.val],
615 dev->int_menu->cur.val);
616 gen_text(dev, vbuf, line++ * 16, 16, str);
Sakari Ailus77e7c4e2012-01-24 21:05:34 -0300617 mutex_unlock(dev->ctrl_handler.lock);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200618 if (dev->button_pressed) {
619 dev->button_pressed--;
620 snprintf(str, sizeof(str), " button pressed!");
621 gen_text(dev, vbuf, line++ * 16, 16, str);
622 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300623
624 dev->mv_count += 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300625
Pawel Osciake007a322011-01-19 13:02:29 -0200626 buf->vb.v4l2_buf.field = dev->field;
627 dev->field_count++;
628 buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300629 do_gettimeofday(&ts);
Pawel Osciake007a322011-01-19 13:02:29 -0200630 buf->vb.v4l2_buf.timestamp = ts;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300631}
632
Hans Verkuil730947b2010-04-10 04:13:53 -0300633static void vivi_thread_tick(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300634{
Brandon Philips78718e52008-04-02 18:10:59 -0300635 struct vivi_dmaqueue *dma_q = &dev->vidq;
Hans Verkuil730947b2010-04-10 04:13:53 -0300636 struct vivi_buffer *buf;
Brandon Philips78718e52008-04-02 18:10:59 -0300637 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300638
Brandon Philips78718e52008-04-02 18:10:59 -0300639 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300640
Brandon Philips78718e52008-04-02 18:10:59 -0300641 spin_lock_irqsave(&dev->slock, flags);
642 if (list_empty(&dma_q->active)) {
643 dprintk(dev, 1, "No active queue to serve\n");
Hans Verkuil1de5be52011-07-05 07:19:23 -0300644 spin_unlock_irqrestore(&dev->slock, flags);
645 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300646 }
Brandon Philips78718e52008-04-02 18:10:59 -0300647
Pawel Osciake007a322011-01-19 13:02:29 -0200648 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
649 list_del(&buf->list);
Hans Verkuil1de5be52011-07-05 07:19:23 -0300650 spin_unlock_irqrestore(&dev->slock, flags);
Brandon Philips78718e52008-04-02 18:10:59 -0300651
Pawel Osciake007a322011-01-19 13:02:29 -0200652 do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
Brandon Philips78718e52008-04-02 18:10:59 -0300653
654 /* Fill buffer */
Hans Verkuil730947b2010-04-10 04:13:53 -0300655 vivi_fillbuff(dev, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300656 dprintk(dev, 1, "filled buffer %p\n", buf);
657
Pawel Osciake007a322011-01-19 13:02:29 -0200658 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
659 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300660}
661
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300662#define frames_to_ms(frames) \
663 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
664
Hans Verkuil730947b2010-04-10 04:13:53 -0300665static void vivi_sleep(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300666{
Brandon Philips78718e52008-04-02 18:10:59 -0300667 struct vivi_dmaqueue *dma_q = &dev->vidq;
668 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300669 DECLARE_WAITQUEUE(wait, current);
670
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300671 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300672 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300673
674 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300675 if (kthread_should_stop())
676 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300677
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300678 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300679 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300680
Hans Verkuil730947b2010-04-10 04:13:53 -0300681 vivi_thread_tick(dev);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300682
683 schedule_timeout_interruptible(timeout);
684
685stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300686 remove_wait_queue(&dma_q->wq, &wait);
687 try_to_freeze();
688}
689
Adrian Bunk972c3512006-04-27 21:06:50 -0300690static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300691{
Hans Verkuil730947b2010-04-10 04:13:53 -0300692 struct vivi_dev *dev = data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300693
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300694 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300695
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700696 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300697
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300698 for (;;) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300699 vivi_sleep(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300700
701 if (kthread_should_stop())
702 break;
703 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300704 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300705 return 0;
706}
707
Pawel Osciake007a322011-01-19 13:02:29 -0200708static int vivi_start_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300709{
Brandon Philips78718e52008-04-02 18:10:59 -0300710 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300711
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300712 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300713
Hans Verkuil730947b2010-04-10 04:13:53 -0300714 /* Resets frame counters */
715 dev->ms = 0;
716 dev->mv_count = 0;
717 dev->jiffies = jiffies;
718
719 dma_q->frame = 0;
720 dma_q->ini_jiffies = jiffies;
721 dma_q->kthread = kthread_run(vivi_thread, dev, dev->v4l2_dev.name);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300722
Akinobu Mita054afee2006-12-20 10:04:00 -0300723 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300724 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Pawel Osciake007a322011-01-19 13:02:29 -0200725 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300726 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300727 /* Wakes thread */
728 wake_up_interruptible(&dma_q->wq);
729
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300730 dprintk(dev, 1, "returning from %s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200731 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300732}
733
Pawel Osciake007a322011-01-19 13:02:29 -0200734static void vivi_stop_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300735{
Hans Verkuil730947b2010-04-10 04:13:53 -0300736 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300737
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300738 dprintk(dev, 1, "%s\n", __func__);
Hans Verkuil730947b2010-04-10 04:13:53 -0300739
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300740 /* shutdown control thread */
741 if (dma_q->kthread) {
742 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300743 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300744 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300745
Pawel Osciake007a322011-01-19 13:02:29 -0200746 /*
747 * Typical driver might need to wait here until dma engine stops.
748 * In this case we can abort imiedetly, so it's just a noop.
749 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300750
Pawel Osciake007a322011-01-19 13:02:29 -0200751 /* Release all active buffers */
752 while (!list_empty(&dma_q->active)) {
753 struct vivi_buffer *buf;
754 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
755 list_del(&buf->list);
756 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
757 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
758 }
759}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300760/* ------------------------------------------------------------------
761 Videobuf operations
762 ------------------------------------------------------------------*/
Guennadi Liakhovetskifc714e72011-08-24 10:30:21 -0300763static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
764 unsigned int *nbuffers, unsigned int *nplanes,
765 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300766{
Pawel Osciake007a322011-01-19 13:02:29 -0200767 struct vivi_dev *dev = vb2_get_drv_priv(vq);
768 unsigned long size;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300769
Hans Verkuil2e90c6c2012-06-22 05:53:31 -0300770 if (fmt)
771 size = fmt->fmt.pix.sizeimage;
772 else
773 size = dev->width * dev->height * dev->pixelsize;
774
775 if (size == 0)
776 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300777
Pawel Osciake007a322011-01-19 13:02:29 -0200778 if (0 == *nbuffers)
779 *nbuffers = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300780
Pawel Osciake007a322011-01-19 13:02:29 -0200781 while (size * *nbuffers > vid_limit * 1024 * 1024)
782 (*nbuffers)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300783
Pawel Osciake007a322011-01-19 13:02:29 -0200784 *nplanes = 1;
785
786 sizes[0] = size;
787
788 /*
789 * videobuf2-vmalloc allocator is context-less so no need to set
790 * alloc_ctxs array.
791 */
792
793 dprintk(dev, 1, "%s, count=%d, size=%ld\n", __func__,
794 *nbuffers, size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300795
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300796 return 0;
797}
798
Pawel Osciake007a322011-01-19 13:02:29 -0200799static int buffer_prepare(struct vb2_buffer *vb)
800{
801 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
802 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
803 unsigned long size;
804
805 dprintk(dev, 1, "%s, field=%d\n", __func__, vb->v4l2_buf.field);
806
807 BUG_ON(NULL == dev->fmt);
808
809 /*
810 * Theses properties only change when queue is idle, see s_fmt.
811 * The below checks should not be performed here, on each
812 * buffer_prepare (i.e. on each qbuf). Most of the code in this function
813 * should thus be moved to buffer_init and s_fmt.
814 */
Hans Verkuil730947b2010-04-10 04:13:53 -0300815 if (dev->width < 48 || dev->width > MAX_WIDTH ||
816 dev->height < 32 || dev->height > MAX_HEIGHT)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300817 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300818
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300819 size = dev->width * dev->height * dev->pixelsize;
Pawel Osciake007a322011-01-19 13:02:29 -0200820 if (vb2_plane_size(vb, 0) < size) {
821 dprintk(dev, 1, "%s data will not fit into plane (%lu < %lu)\n",
822 __func__, vb2_plane_size(vb, 0), size);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300823 return -EINVAL;
Pawel Osciake007a322011-01-19 13:02:29 -0200824 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300825
Pawel Osciake007a322011-01-19 13:02:29 -0200826 vb2_set_plane_payload(&buf->vb, 0, size);
827
828 buf->fmt = dev->fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300829
Hans Verkuil730947b2010-04-10 04:13:53 -0300830 precalculate_bars(dev);
831 precalculate_line(dev);
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300832
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300833 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300834}
835
Pawel Osciake007a322011-01-19 13:02:29 -0200836static void buffer_queue(struct vb2_buffer *vb)
837{
838 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
Hans Verkuil730947b2010-04-10 04:13:53 -0300839 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300840 struct vivi_dmaqueue *vidq = &dev->vidq;
Pawel Osciake007a322011-01-19 13:02:29 -0200841 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300842
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300843 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300844
Pawel Osciake007a322011-01-19 13:02:29 -0200845 spin_lock_irqsave(&dev->slock, flags);
846 list_add_tail(&buf->list, &vidq->active);
847 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300848}
849
Marek Szyprowskibd323e22011-08-29 08:51:49 -0300850static int start_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300851{
Pawel Osciake007a322011-01-19 13:02:29 -0200852 struct vivi_dev *dev = vb2_get_drv_priv(vq);
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300853 dprintk(dev, 1, "%s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200854 return vivi_start_generating(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300855}
856
Pawel Osciake007a322011-01-19 13:02:29 -0200857/* abort streaming and wait for last buffer */
858static int stop_streaming(struct vb2_queue *vq)
859{
860 struct vivi_dev *dev = vb2_get_drv_priv(vq);
861 dprintk(dev, 1, "%s\n", __func__);
862 vivi_stop_generating(dev);
863 return 0;
864}
865
866static void vivi_lock(struct vb2_queue *vq)
867{
868 struct vivi_dev *dev = vb2_get_drv_priv(vq);
869 mutex_lock(&dev->mutex);
870}
871
872static void vivi_unlock(struct vb2_queue *vq)
873{
874 struct vivi_dev *dev = vb2_get_drv_priv(vq);
875 mutex_unlock(&dev->mutex);
876}
877
878
879static struct vb2_ops vivi_video_qops = {
880 .queue_setup = queue_setup,
Pawel Osciake007a322011-01-19 13:02:29 -0200881 .buf_prepare = buffer_prepare,
Pawel Osciake007a322011-01-19 13:02:29 -0200882 .buf_queue = buffer_queue,
883 .start_streaming = start_streaming,
884 .stop_streaming = stop_streaming,
885 .wait_prepare = vivi_unlock,
886 .wait_finish = vivi_lock,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300887};
888
889/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300890 IOCTL vidioc handling
891 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300892static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300893 struct v4l2_capability *cap)
894{
Hans Verkuil730947b2010-04-10 04:13:53 -0300895 struct vivi_dev *dev = video_drvdata(file);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300896
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300897 strcpy(cap->driver, "vivi");
898 strcpy(cap->card, "vivi");
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300899 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Hans Verkuil23268ae2012-01-24 05:24:36 -0300900 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
901 V4L2_CAP_READWRITE;
902 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300903 return 0;
904}
905
Hans Verkuil78b526a2008-05-28 12:16:41 -0300906static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300907 struct v4l2_fmtdesc *f)
908{
Magnus Dammd891f472008-10-14 12:47:09 -0300909 struct vivi_fmt *fmt;
910
911 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300912 return -EINVAL;
913
Magnus Dammd891f472008-10-14 12:47:09 -0300914 fmt = &formats[f->index];
915
916 strlcpy(f->description, fmt->name, sizeof(f->description));
917 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300918 return 0;
919}
920
Hans Verkuil78b526a2008-05-28 12:16:41 -0300921static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300922 struct v4l2_format *f)
923{
Hans Verkuil730947b2010-04-10 04:13:53 -0300924 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300925
Hans Verkuil730947b2010-04-10 04:13:53 -0300926 f->fmt.pix.width = dev->width;
927 f->fmt.pix.height = dev->height;
Pawel Osciake007a322011-01-19 13:02:29 -0200928 f->fmt.pix.field = dev->field;
Hans Verkuil730947b2010-04-10 04:13:53 -0300929 f->fmt.pix.pixelformat = dev->fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300930 f->fmt.pix.bytesperline =
Hans Verkuil730947b2010-04-10 04:13:53 -0300931 (f->fmt.pix.width * dev->fmt->depth) >> 3;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300932 f->fmt.pix.sizeimage =
933 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil8c79eec2011-07-29 07:19:46 -0300934 if (dev->fmt->fourcc == V4L2_PIX_FMT_YUYV ||
935 dev->fmt->fourcc == V4L2_PIX_FMT_UYVY)
936 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
937 else
938 f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
Hans Verkuil730947b2010-04-10 04:13:53 -0300939 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300940}
941
Hans Verkuil78b526a2008-05-28 12:16:41 -0300942static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300943 struct v4l2_format *f)
944{
Hans Verkuil730947b2010-04-10 04:13:53 -0300945 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300946 struct vivi_fmt *fmt;
947 enum v4l2_field field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300948
Magnus Dammd891f472008-10-14 12:47:09 -0300949 fmt = get_format(f);
950 if (!fmt) {
951 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
952 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300953 return -EINVAL;
954 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300955
956 field = f->fmt.pix.field;
957
958 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300959 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300960 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300961 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300962 return -EINVAL;
963 }
964
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300965 f->fmt.pix.field = field;
Hans Verkuil730947b2010-04-10 04:13:53 -0300966 v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
967 &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300968 f->fmt.pix.bytesperline =
969 (f->fmt.pix.width * fmt->depth) >> 3;
970 f->fmt.pix.sizeimage =
971 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil8c79eec2011-07-29 07:19:46 -0300972 if (fmt->fourcc == V4L2_PIX_FMT_YUYV ||
973 fmt->fourcc == V4L2_PIX_FMT_UYVY)
974 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
975 else
976 f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300977 return 0;
978}
979
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300980static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
981 struct v4l2_format *f)
982{
Hans Verkuil730947b2010-04-10 04:13:53 -0300983 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200984 struct vb2_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300985
Hans Verkuil730947b2010-04-10 04:13:53 -0300986 int ret = vidioc_try_fmt_vid_cap(file, priv, f);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300987 if (ret < 0)
988 return ret;
989
Hans Verkuilf2ba5a02012-06-22 05:53:02 -0300990 if (vb2_is_busy(q)) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300991 dprintk(dev, 1, "%s device busy\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200992 return -EBUSY;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300993 }
994
Hans Verkuil730947b2010-04-10 04:13:53 -0300995 dev->fmt = get_format(f);
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300996 dev->pixelsize = dev->fmt->depth / 8;
Hans Verkuil730947b2010-04-10 04:13:53 -0300997 dev->width = f->fmt.pix.width;
998 dev->height = f->fmt.pix.height;
Pawel Osciake007a322011-01-19 13:02:29 -0200999 dev->field = f->fmt.pix.field;
1000
1001 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001002}
1003
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001004/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001005static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001006 struct v4l2_input *inp)
1007{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001008 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001009 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001010
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001011 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001012 sprintf(inp->name, "Camera %u", inp->index);
Hans Verkuil730947b2010-04-10 04:13:53 -03001013 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001014}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001015
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001016static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001017{
Hans Verkuil730947b2010-04-10 04:13:53 -03001018 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001019
1020 *i = dev->input;
Hans Verkuil730947b2010-04-10 04:13:53 -03001021 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001022}
Hans Verkuil730947b2010-04-10 04:13:53 -03001023
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001024static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001025{
Hans Verkuil730947b2010-04-10 04:13:53 -03001026 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001027
1028 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001029 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001030
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001031 if (i == dev->input)
1032 return 0;
1033
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001034 dev->input = i;
Hans Verkuil730947b2010-04-10 04:13:53 -03001035 precalculate_bars(dev);
1036 precalculate_line(dev);
1037 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001038}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001039
Hans Verkuil730947b2010-04-10 04:13:53 -03001040/* --- controls ---------------------------------------------- */
Hans Verkuil7e996af2011-01-23 12:33:16 -02001041
Hans Verkuila1c894f2011-06-07 06:34:41 -03001042static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1043{
1044 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
1045
1046 if (ctrl == dev->autogain)
1047 dev->gain->val = jiffies & 0xff;
1048 return 0;
1049}
1050
Hans Verkuil7e996af2011-01-23 12:33:16 -02001051static int vivi_s_ctrl(struct v4l2_ctrl *ctrl)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001052{
Hans Verkuil7e996af2011-01-23 12:33:16 -02001053 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001054
Hans Verkuil7088f4d2012-05-02 03:33:52 -03001055 switch (ctrl->id) {
1056 case V4L2_CID_ALPHA_COMPONENT:
1057 dev->alpha_component = ctrl->val;
1058 break;
1059 default:
1060 if (ctrl == dev->button)
1061 dev->button_pressed = 30;
1062 break;
1063 }
Hans Verkuil7e996af2011-01-23 12:33:16 -02001064 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001065}
1066
1067/* ------------------------------------------------------------------
1068 File operations for the device
1069 ------------------------------------------------------------------*/
1070
Hans Verkuil7e996af2011-01-23 12:33:16 -02001071static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
Hans Verkuila1c894f2011-06-07 06:34:41 -03001072 .g_volatile_ctrl = vivi_g_volatile_ctrl,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001073 .s_ctrl = vivi_s_ctrl,
1074};
1075
1076#define VIVI_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
1077
1078static const struct v4l2_ctrl_config vivi_ctrl_button = {
1079 .ops = &vivi_ctrl_ops,
1080 .id = VIVI_CID_CUSTOM_BASE + 0,
1081 .name = "Button",
1082 .type = V4L2_CTRL_TYPE_BUTTON,
1083};
1084
1085static const struct v4l2_ctrl_config vivi_ctrl_boolean = {
1086 .ops = &vivi_ctrl_ops,
1087 .id = VIVI_CID_CUSTOM_BASE + 1,
1088 .name = "Boolean",
1089 .type = V4L2_CTRL_TYPE_BOOLEAN,
1090 .min = 0,
1091 .max = 1,
1092 .step = 1,
1093 .def = 1,
1094};
1095
1096static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
1097 .ops = &vivi_ctrl_ops,
1098 .id = VIVI_CID_CUSTOM_BASE + 2,
1099 .name = "Integer 32 Bits",
1100 .type = V4L2_CTRL_TYPE_INTEGER,
Hans Verkuil5b283022011-01-11 17:32:28 -03001101 .min = 0x80000000,
1102 .max = 0x7fffffff,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001103 .step = 1,
1104};
1105
1106static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
1107 .ops = &vivi_ctrl_ops,
1108 .id = VIVI_CID_CUSTOM_BASE + 3,
1109 .name = "Integer 64 Bits",
1110 .type = V4L2_CTRL_TYPE_INTEGER64,
1111};
1112
1113static const char * const vivi_ctrl_menu_strings[] = {
1114 "Menu Item 0 (Skipped)",
1115 "Menu Item 1",
1116 "Menu Item 2 (Skipped)",
1117 "Menu Item 3",
1118 "Menu Item 4",
1119 "Menu Item 5 (Skipped)",
1120 NULL,
1121};
1122
1123static const struct v4l2_ctrl_config vivi_ctrl_menu = {
1124 .ops = &vivi_ctrl_ops,
1125 .id = VIVI_CID_CUSTOM_BASE + 4,
1126 .name = "Menu",
1127 .type = V4L2_CTRL_TYPE_MENU,
1128 .min = 1,
1129 .max = 4,
1130 .def = 3,
1131 .menu_skip_mask = 0x04,
1132 .qmenu = vivi_ctrl_menu_strings,
1133};
1134
1135static const struct v4l2_ctrl_config vivi_ctrl_string = {
1136 .ops = &vivi_ctrl_ops,
1137 .id = VIVI_CID_CUSTOM_BASE + 5,
1138 .name = "String",
1139 .type = V4L2_CTRL_TYPE_STRING,
1140 .min = 2,
1141 .max = 4,
1142 .step = 1,
1143};
1144
Hans Verkuilb6d17a52011-03-29 16:33:11 -03001145static const struct v4l2_ctrl_config vivi_ctrl_bitmask = {
1146 .ops = &vivi_ctrl_ops,
1147 .id = VIVI_CID_CUSTOM_BASE + 6,
1148 .name = "Bitmask",
1149 .type = V4L2_CTRL_TYPE_BITMASK,
1150 .def = 0x80002000,
1151 .min = 0,
1152 .max = 0x80402010,
1153 .step = 0,
1154};
1155
Sakari Ailusc5203312011-08-05 06:38:05 -03001156static const s64 vivi_ctrl_int_menu_values[] = {
1157 1, 1, 2, 3, 5, 8, 13, 21, 42,
1158};
1159
1160static const struct v4l2_ctrl_config vivi_ctrl_int_menu = {
1161 .ops = &vivi_ctrl_ops,
1162 .id = VIVI_CID_CUSTOM_BASE + 7,
1163 .name = "Integer menu",
1164 .type = V4L2_CTRL_TYPE_INTEGER_MENU,
1165 .min = 1,
1166 .max = 8,
1167 .def = 4,
1168 .menu_skip_mask = 0x02,
1169 .qmenu_int = vivi_ctrl_int_menu_values,
1170};
1171
Hans Verkuilbec43662008-12-30 06:58:20 -03001172static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001173 .owner = THIS_MODULE,
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001174 .open = v4l2_fh_open,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001175 .release = vb2_fop_release,
1176 .read = vb2_fop_read,
1177 .poll = vb2_fop_poll,
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001178 .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001179 .mmap = vb2_fop_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001180};
1181
Hans Verkuila3998102008-07-21 02:57:38 -03001182static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001183 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001184 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1185 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1186 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1187 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001188 .vidioc_reqbufs = vb2_ioctl_reqbufs,
Hans Verkuil2e90c6c2012-06-22 05:53:31 -03001189 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1190 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001191 .vidioc_querybuf = vb2_ioctl_querybuf,
1192 .vidioc_qbuf = vb2_ioctl_qbuf,
1193 .vidioc_dqbuf = vb2_ioctl_dqbuf,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001194 .vidioc_enum_input = vidioc_enum_input,
1195 .vidioc_g_input = vidioc_g_input,
1196 .vidioc_s_input = vidioc_s_input,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001197 .vidioc_streamon = vb2_ioctl_streamon,
1198 .vidioc_streamoff = vb2_ioctl_streamoff,
Hans Verkuile2ecb252012-02-02 08:20:53 -03001199 .vidioc_log_status = v4l2_ctrl_log_status,
Hans Verkuil6d6604f2012-01-27 16:21:10 -03001200 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001201 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Hans Verkuila3998102008-07-21 02:57:38 -03001202};
1203
1204static struct video_device vivi_template = {
1205 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001206 .fops = &vivi_fops,
1207 .ioctl_ops = &vivi_ioctl_ops,
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001208 .release = video_device_release_empty,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001209};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001210
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001211/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001212 Initialization and module stuff
1213 ------------------------------------------------------------------*/
1214
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001215static int vivi_release(void)
1216{
1217 struct vivi_dev *dev;
1218 struct list_head *list;
1219
1220 while (!list_empty(&vivi_devlist)) {
1221 list = vivi_devlist.next;
1222 list_del(list);
1223 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1224
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001225 v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001226 video_device_node_name(&dev->vdev));
1227 video_unregister_device(&dev->vdev);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001228 v4l2_device_unregister(&dev->v4l2_dev);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001229 v4l2_ctrl_handler_free(&dev->ctrl_handler);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001230 kfree(dev);
1231 }
1232
1233 return 0;
1234}
1235
Hans Verkuilc41ee242009-02-14 13:43:44 -03001236static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001237{
1238 struct vivi_dev *dev;
1239 struct video_device *vfd;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001240 struct v4l2_ctrl_handler *hdl;
Pawel Osciake007a322011-01-19 13:02:29 -02001241 struct vb2_queue *q;
Hans Verkuil730947b2010-04-10 04:13:53 -03001242 int ret;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001243
1244 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1245 if (!dev)
1246 return -ENOMEM;
1247
1248 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001249 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001250 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1251 if (ret)
1252 goto free_dev;
1253
Hans Verkuil730947b2010-04-10 04:13:53 -03001254 dev->fmt = &formats[0];
1255 dev->width = 640;
1256 dev->height = 480;
Hans Verkuil3d51dca2012-05-02 03:15:11 -03001257 dev->pixelsize = dev->fmt->depth / 8;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001258 hdl = &dev->ctrl_handler;
1259 v4l2_ctrl_handler_init(hdl, 11);
1260 dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1261 V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
1262 dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1263 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1264 dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1265 V4L2_CID_CONTRAST, 0, 255, 1, 16);
1266 dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1267 V4L2_CID_SATURATION, 0, 255, 1, 127);
1268 dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1269 V4L2_CID_HUE, -128, 127, 1, 0);
Hans Verkuila1c894f2011-06-07 06:34:41 -03001270 dev->autogain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1271 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1272 dev->gain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1273 V4L2_CID_GAIN, 0, 255, 1, 100);
Hans Verkuil7088f4d2012-05-02 03:33:52 -03001274 dev->alpha = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1275 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001276 dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
1277 dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
1278 dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);
1279 dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL);
1280 dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL);
1281 dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL);
Hans Verkuilb6d17a52011-03-29 16:33:11 -03001282 dev->bitmask = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_bitmask, NULL);
Sakari Ailusc5203312011-08-05 06:38:05 -03001283 dev->int_menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int_menu, NULL);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001284 if (hdl->error) {
1285 ret = hdl->error;
1286 goto unreg_dev;
1287 }
Hans Verkuila1c894f2011-06-07 06:34:41 -03001288 v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001289 dev->v4l2_dev.ctrl_handler = hdl;
Hans Verkuil730947b2010-04-10 04:13:53 -03001290
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001291 /* initialize locks */
1292 spin_lock_init(&dev->slock);
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001293
Pawel Osciake007a322011-01-19 13:02:29 -02001294 /* initialize queue */
1295 q = &dev->vb_vidq;
1296 memset(q, 0, sizeof(dev->vb_vidq));
1297 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1298 q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1299 q->drv_priv = dev;
1300 q->buf_struct_size = sizeof(struct vivi_buffer);
1301 q->ops = &vivi_video_qops;
1302 q->mem_ops = &vb2_vmalloc_memops;
1303
1304 vb2_queue_init(q);
1305
1306 mutex_init(&dev->mutex);
Hans Verkuil730947b2010-04-10 04:13:53 -03001307
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001308 /* init video dma queues */
1309 INIT_LIST_HEAD(&dev->vidq.active);
1310 init_waitqueue_head(&dev->vidq.wq);
1311
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001312 vfd = &dev->vdev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001313 *vfd = vivi_template;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -03001314 vfd->debug = debug;
Hans Verkuil730947b2010-04-10 04:13:53 -03001315 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001316 vfd->queue = q;
Hans Verkuilb1a873a2011-03-22 10:14:07 -03001317 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Pawel Osciake007a322011-01-19 13:02:29 -02001318
1319 /*
1320 * Provide a mutex to v4l2 core. It will be used to protect
1321 * all fops and v4l2 ioctls.
1322 */
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001323 vfd->lock = &dev->mutex;
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001324 video_set_drvdata(vfd, dev);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001325
1326 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1327 if (ret < 0)
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001328 goto unreg_dev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001329
1330 /* Now that everything is fine, let's add it to device list */
1331 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1332
Roel Kluin7de0b872009-12-16 13:06:33 -03001333 if (video_nr != -1)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001334 video_nr++;
1335
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001336 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
1337 video_device_node_name(vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001338 return 0;
1339
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001340unreg_dev:
Hans Verkuil7e996af2011-01-23 12:33:16 -02001341 v4l2_ctrl_handler_free(hdl);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001342 v4l2_device_unregister(&dev->v4l2_dev);
1343free_dev:
1344 kfree(dev);
1345 return ret;
1346}
1347
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001348/* This routine allocates from 1 to n_devs virtual drivers.
1349
1350 The real maximum number of virtual drivers will depend on how many drivers
1351 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001352 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001353 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001354static int __init vivi_init(void)
1355{
Hans Verkuil730947b2010-04-10 04:13:53 -03001356 const struct font_desc *font = find_font("VGA8x16");
Hans Verkuil9185cbf2009-03-06 09:58:12 -03001357 int ret = 0, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001358
Hans Verkuil730947b2010-04-10 04:13:53 -03001359 if (font == NULL) {
1360 printk(KERN_ERR "vivi: could not find font\n");
1361 return -ENODEV;
1362 }
1363 font8x16 = font->data;
1364
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001365 if (n_devs <= 0)
1366 n_devs = 1;
1367
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001368 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001369 ret = vivi_create_instance(i);
1370 if (ret) {
1371 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001372 if (i)
1373 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001374 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001375 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001376 }
1377
1378 if (ret < 0) {
Hans Verkuil730947b2010-04-10 04:13:53 -03001379 printk(KERN_ERR "vivi: error %d while loading driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001380 return ret;
1381 }
1382
1383 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001384 "Capture Board ver %s successfully loaded.\n",
1385 VIVI_VERSION);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001386
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001387 /* n_devs will reflect the actual number of allocated devices */
1388 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001389
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001390 return ret;
1391}
1392
1393static void __exit vivi_exit(void)
1394{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001395 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001396}
1397
1398module_init(vivi_init);
1399module_exit(vivi_exit);