blob: a05494b71b20a7247a8bfb27c05304dcf8ae3272 [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;
Pawel Osciake007a322011-01-19 13:02:29 -0200233 unsigned int field_count;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300234
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300235 u8 bars[9][3];
236 u8 line[MAX_WIDTH * 8];
237 unsigned int pixelsize;
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300238 u8 alpha_component;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300239};
240
241/* ------------------------------------------------------------------
242 DMA and thread functions
243 ------------------------------------------------------------------*/
244
245/* Bars and Colors should match positions */
246
247enum colors {
248 WHITE,
Hans Verkuil730947b2010-04-10 04:13:53 -0300249 AMBER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300250 CYAN,
251 GREEN,
252 MAGENTA,
253 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300254 BLUE,
255 BLACK,
Hans Verkuil730947b2010-04-10 04:13:53 -0300256 TEXT_BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300257};
258
Hans Verkuil730947b2010-04-10 04:13:53 -0300259/* R G B */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300260#define COLOR_WHITE {204, 204, 204}
Hans Verkuil730947b2010-04-10 04:13:53 -0300261#define COLOR_AMBER {208, 208, 0}
262#define COLOR_CYAN { 0, 206, 206}
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300263#define COLOR_GREEN { 0, 239, 0}
264#define COLOR_MAGENTA {239, 0, 239}
265#define COLOR_RED {205, 0, 0}
266#define COLOR_BLUE { 0, 0, 255}
267#define COLOR_BLACK { 0, 0, 0}
268
269struct bar_std {
Hans Verkuil730947b2010-04-10 04:13:53 -0300270 u8 bar[9][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300271};
272
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300273/* Maximum number of bars are 10 - otherwise, the input print code
274 should be modified */
275static struct bar_std bars[] = {
276 { /* Standard ITU-R color bar sequence */
Hans Verkuil730947b2010-04-10 04:13:53 -0300277 { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN,
278 COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300279 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300280 { COLOR_WHITE, COLOR_AMBER, COLOR_BLACK, COLOR_WHITE,
281 COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, COLOR_AMBER, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300282 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300283 { COLOR_WHITE, COLOR_CYAN, COLOR_BLACK, COLOR_WHITE,
284 COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, COLOR_CYAN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300285 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300286 { COLOR_WHITE, COLOR_GREEN, COLOR_BLACK, COLOR_WHITE,
287 COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, COLOR_GREEN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300288 },
289};
290
291#define NUM_INPUTS ARRAY_SIZE(bars)
292
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300293#define TO_Y(r, g, b) \
294 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300295/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300296#define TO_V(r, g, b) \
297 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300298/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300299#define TO_U(r, g, b) \
300 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300301
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300302/* precalculate color bar values to speed up rendering */
Hans Verkuil730947b2010-04-10 04:13:53 -0300303static void precalculate_bars(struct vivi_dev *dev)
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300304{
Hans Verkuil730947b2010-04-10 04:13:53 -0300305 u8 r, g, b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300306 int k, is_yuv;
307
Hans Verkuil730947b2010-04-10 04:13:53 -0300308 for (k = 0; k < 9; k++) {
309 r = bars[dev->input].bar[k][0];
310 g = bars[dev->input].bar[k][1];
311 b = bars[dev->input].bar[k][2];
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300312 is_yuv = 0;
313
Hans Verkuil730947b2010-04-10 04:13:53 -0300314 switch (dev->fmt->fourcc) {
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300315 case V4L2_PIX_FMT_YUYV:
316 case V4L2_PIX_FMT_UYVY:
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300317 case V4L2_PIX_FMT_YVYU:
318 case V4L2_PIX_FMT_VYUY:
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300319 is_yuv = 1;
320 break;
321 case V4L2_PIX_FMT_RGB565:
322 case V4L2_PIX_FMT_RGB565X:
323 r >>= 3;
324 g >>= 2;
325 b >>= 3;
326 break;
327 case V4L2_PIX_FMT_RGB555:
328 case V4L2_PIX_FMT_RGB555X:
329 r >>= 3;
330 g >>= 3;
331 b >>= 3;
332 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300333 case V4L2_PIX_FMT_RGB24:
334 case V4L2_PIX_FMT_BGR24:
335 case V4L2_PIX_FMT_RGB32:
336 case V4L2_PIX_FMT_BGR32:
337 break;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300338 }
339
340 if (is_yuv) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300341 dev->bars[k][0] = TO_Y(r, g, b); /* Luma */
342 dev->bars[k][1] = TO_U(r, g, b); /* Cb */
343 dev->bars[k][2] = TO_V(r, g, b); /* Cr */
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300344 } else {
Hans Verkuil730947b2010-04-10 04:13:53 -0300345 dev->bars[k][0] = r;
346 dev->bars[k][1] = g;
347 dev->bars[k][2] = b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300348 }
349 }
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300350}
351
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300352#define TSTAMP_MIN_Y 24
353#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
354#define TSTAMP_INPUT_X 10
355#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300356
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300357/* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */
358static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos, bool odd)
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300359{
Hans Verkuil730947b2010-04-10 04:13:53 -0300360 u8 r_y, g_u, b_v;
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300361 u8 alpha = dev->alpha_component;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300362 int color;
Hans Verkuil730947b2010-04-10 04:13:53 -0300363 u8 *p;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300364
Hans Verkuil730947b2010-04-10 04:13:53 -0300365 r_y = dev->bars[colorpos][0]; /* R or precalculated Y */
366 g_u = dev->bars[colorpos][1]; /* G or precalculated U */
367 b_v = dev->bars[colorpos][2]; /* B or precalculated V */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300368
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300369 for (color = 0; color < dev->pixelsize; color++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300370 p = buf + color;
371
Hans Verkuil730947b2010-04-10 04:13:53 -0300372 switch (dev->fmt->fourcc) {
Magnus Dammd891f472008-10-14 12:47:09 -0300373 case V4L2_PIX_FMT_YUYV:
374 switch (color) {
375 case 0:
Magnus Dammd891f472008-10-14 12:47:09 -0300376 *p = r_y;
377 break;
378 case 1:
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300379 *p = odd ? b_v : g_u;
Magnus Dammd891f472008-10-14 12:47:09 -0300380 break;
381 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300382 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300383 case V4L2_PIX_FMT_UYVY:
384 switch (color) {
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300385 case 0:
386 *p = odd ? b_v : g_u;
387 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300388 case 1:
Magnus Dammfca36ba2008-10-14 12:47:25 -0300389 *p = r_y;
390 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300391 }
392 break;
393 case V4L2_PIX_FMT_YVYU:
394 switch (color) {
Magnus Dammfca36ba2008-10-14 12:47:25 -0300395 case 0:
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300396 *p = r_y;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300397 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300398 case 1:
399 *p = odd ? g_u : b_v;
400 break;
401 }
402 break;
403 case V4L2_PIX_FMT_VYUY:
404 switch (color) {
405 case 0:
406 *p = odd ? g_u : b_v;
407 break;
408 case 1:
409 *p = r_y;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300410 break;
411 }
412 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300413 case V4L2_PIX_FMT_RGB565:
414 switch (color) {
415 case 0:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300416 *p = (g_u << 5) | b_v;
417 break;
418 case 1:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300419 *p = (r_y << 3) | (g_u >> 3);
420 break;
421 }
422 break;
423 case V4L2_PIX_FMT_RGB565X:
424 switch (color) {
425 case 0:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300426 *p = (r_y << 3) | (g_u >> 3);
427 break;
428 case 1:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300429 *p = (g_u << 5) | b_v;
430 break;
431 }
432 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300433 case V4L2_PIX_FMT_RGB555:
434 switch (color) {
435 case 0:
Magnus Dammdef52392008-10-14 12:47:43 -0300436 *p = (g_u << 5) | b_v;
437 break;
438 case 1:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300439 *p = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
Magnus Dammdef52392008-10-14 12:47:43 -0300440 break;
441 }
442 break;
443 case V4L2_PIX_FMT_RGB555X:
444 switch (color) {
445 case 0:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300446 *p = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
Magnus Dammdef52392008-10-14 12:47:43 -0300447 break;
448 case 1:
Magnus Dammdef52392008-10-14 12:47:43 -0300449 *p = (g_u << 5) | b_v;
450 break;
451 }
452 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300453 case V4L2_PIX_FMT_RGB24:
454 switch (color) {
455 case 0:
456 *p = r_y;
457 break;
458 case 1:
459 *p = g_u;
460 break;
461 case 2:
462 *p = b_v;
463 break;
464 }
465 break;
466 case V4L2_PIX_FMT_BGR24:
467 switch (color) {
468 case 0:
469 *p = b_v;
470 break;
471 case 1:
472 *p = g_u;
473 break;
474 case 2:
475 *p = r_y;
476 break;
477 }
478 break;
479 case V4L2_PIX_FMT_RGB32:
480 switch (color) {
481 case 0:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300482 *p = alpha;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300483 break;
484 case 1:
485 *p = r_y;
486 break;
487 case 2:
488 *p = g_u;
489 break;
490 case 3:
491 *p = b_v;
492 break;
493 }
494 break;
495 case V4L2_PIX_FMT_BGR32:
496 switch (color) {
497 case 0:
498 *p = b_v;
499 break;
500 case 1:
501 *p = g_u;
502 break;
503 case 2:
504 *p = r_y;
505 break;
506 case 3:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300507 *p = alpha;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300508 break;
509 }
510 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300511 }
512 }
513}
514
Hans Verkuil730947b2010-04-10 04:13:53 -0300515static void precalculate_line(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300516{
Hans Verkuil730947b2010-04-10 04:13:53 -0300517 int w;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300518
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300519 for (w = 0; w < dev->width * 2; w++) {
520 int colorpos = w / (dev->width / 8) % 8;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300521
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300522 gen_twopix(dev, dev->line + w * dev->pixelsize, colorpos, w & 1);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300523 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300524}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300525
Hans Verkuil730947b2010-04-10 04:13:53 -0300526static void gen_text(struct vivi_dev *dev, char *basep,
527 int y, int x, char *text)
528{
529 int line;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300530
Hans Verkuil730947b2010-04-10 04:13:53 -0300531 /* Checks if it is possible to show string */
532 if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width)
533 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300534
535 /* Print stream time */
Hans Verkuil730947b2010-04-10 04:13:53 -0300536 for (line = y; line < y + 16; line++) {
537 int j = 0;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300538 char *pos = basep + line * dev->width * dev->pixelsize + x * dev->pixelsize;
Hans Verkuil730947b2010-04-10 04:13:53 -0300539 char *s;
540
541 for (s = text; *s; s++) {
542 u8 chr = font8x16[*s * 16 + line - y];
543 int i;
544
545 for (i = 0; i < 7; i++, j++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300546 /* Draw white font on black background */
Hans Verkuil730947b2010-04-10 04:13:53 -0300547 if (chr & (1 << (7 - i)))
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300548 gen_twopix(dev, pos + j * dev->pixelsize, WHITE, (x+y) & 1);
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300549 else
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300550 gen_twopix(dev, pos + j * dev->pixelsize, TEXT_BLACK, (x+y) & 1);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300551 }
552 }
553 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300554}
Brandon Philips78718e52008-04-02 18:10:59 -0300555
Hans Verkuil730947b2010-04-10 04:13:53 -0300556static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300557{
Pawel Osciake007a322011-01-19 13:02:29 -0200558 int wmax = dev->width;
559 int hmax = dev->height;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300560 struct timeval ts;
Pawel Osciake007a322011-01-19 13:02:29 -0200561 void *vbuf = vb2_plane_vaddr(&buf->vb, 0);
Hans Verkuil730947b2010-04-10 04:13:53 -0300562 unsigned ms;
563 char str[100];
564 int h, line = 1;
Hans Verkuila1c894f2011-06-07 06:34:41 -0300565 s32 gain;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300566
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300567 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300568 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300569
Hans Verkuil730947b2010-04-10 04:13:53 -0300570 for (h = 0; h < hmax; h++)
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300571 memcpy(vbuf + h * wmax * dev->pixelsize,
572 dev->line + (dev->mv_count % wmax) * dev->pixelsize,
573 wmax * dev->pixelsize);
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300574
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300575 /* Updates stream time */
576
Hans Verkuil730947b2010-04-10 04:13:53 -0300577 dev->ms += jiffies_to_msecs(jiffies - dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300578 dev->jiffies = jiffies;
Hans Verkuil730947b2010-04-10 04:13:53 -0300579 ms = dev->ms;
580 snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d ",
581 (ms / (60 * 60 * 1000)) % 24,
582 (ms / (60 * 1000)) % 60,
583 (ms / 1000) % 60,
584 ms % 1000);
585 gen_text(dev, vbuf, line++ * 16, 16, str);
586 snprintf(str, sizeof(str), " %dx%d, input %d ",
587 dev->width, dev->height, dev->input);
588 gen_text(dev, vbuf, line++ * 16, 16, str);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300589
Hans Verkuila1c894f2011-06-07 06:34:41 -0300590 gain = v4l2_ctrl_g_ctrl(dev->gain);
Sakari Ailus77e7c4e2012-01-24 21:05:34 -0300591 mutex_lock(dev->ctrl_handler.lock);
Hans Verkuil730947b2010-04-10 04:13:53 -0300592 snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
Hans Verkuil7e996af2011-01-23 12:33:16 -0200593 dev->brightness->cur.val,
594 dev->contrast->cur.val,
595 dev->saturation->cur.val,
596 dev->hue->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300597 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300598 snprintf(str, sizeof(str), " autogain %d, gain %3d, volume %3d, alpha 0x%02x ",
599 dev->autogain->cur.val, gain, dev->volume->cur.val,
600 dev->alpha->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300601 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300602 snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
Hans Verkuil7e996af2011-01-23 12:33:16 -0200603 dev->int32->cur.val,
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300604 dev->int64->cur.val64,
605 dev->bitmask->cur.val);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200606 gen_text(dev, vbuf, line++ * 16, 16, str);
607 snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
608 dev->boolean->cur.val,
609 dev->menu->qmenu[dev->menu->cur.val],
610 dev->string->cur.string);
Hans Verkuilf70cfc72012-04-19 11:44:18 -0300611 gen_text(dev, vbuf, line++ * 16, 16, str);
Sakari Ailusc5203312011-08-05 06:38:05 -0300612 snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
613 dev->int_menu->qmenu_int[dev->int_menu->cur.val],
614 dev->int_menu->cur.val);
615 gen_text(dev, vbuf, line++ * 16, 16, str);
Sakari Ailus77e7c4e2012-01-24 21:05:34 -0300616 mutex_unlock(dev->ctrl_handler.lock);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200617 if (dev->button_pressed) {
618 dev->button_pressed--;
619 snprintf(str, sizeof(str), " button pressed!");
620 gen_text(dev, vbuf, line++ * 16, 16, str);
621 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300622
623 dev->mv_count += 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300624
Hans Verkuilcd779252012-07-25 11:48:53 -0300625 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
Pawel Osciake007a322011-01-19 13:02:29 -0200626 dev->field_count++;
627 buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300628 do_gettimeofday(&ts);
Pawel Osciake007a322011-01-19 13:02:29 -0200629 buf->vb.v4l2_buf.timestamp = ts;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300630}
631
Hans Verkuil730947b2010-04-10 04:13:53 -0300632static void vivi_thread_tick(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300633{
Brandon Philips78718e52008-04-02 18:10:59 -0300634 struct vivi_dmaqueue *dma_q = &dev->vidq;
Hans Verkuil730947b2010-04-10 04:13:53 -0300635 struct vivi_buffer *buf;
Brandon Philips78718e52008-04-02 18:10:59 -0300636 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300637
Brandon Philips78718e52008-04-02 18:10:59 -0300638 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300639
Brandon Philips78718e52008-04-02 18:10:59 -0300640 spin_lock_irqsave(&dev->slock, flags);
641 if (list_empty(&dma_q->active)) {
642 dprintk(dev, 1, "No active queue to serve\n");
Hans Verkuil1de5be52011-07-05 07:19:23 -0300643 spin_unlock_irqrestore(&dev->slock, flags);
644 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300645 }
Brandon Philips78718e52008-04-02 18:10:59 -0300646
Pawel Osciake007a322011-01-19 13:02:29 -0200647 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
648 list_del(&buf->list);
Hans Verkuil1de5be52011-07-05 07:19:23 -0300649 spin_unlock_irqrestore(&dev->slock, flags);
Brandon Philips78718e52008-04-02 18:10:59 -0300650
Pawel Osciake007a322011-01-19 13:02:29 -0200651 do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
Brandon Philips78718e52008-04-02 18:10:59 -0300652
653 /* Fill buffer */
Hans Verkuil730947b2010-04-10 04:13:53 -0300654 vivi_fillbuff(dev, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300655 dprintk(dev, 1, "filled buffer %p\n", buf);
656
Pawel Osciake007a322011-01-19 13:02:29 -0200657 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
658 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300659}
660
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300661#define frames_to_ms(frames) \
662 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
663
Hans Verkuil730947b2010-04-10 04:13:53 -0300664static void vivi_sleep(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300665{
Brandon Philips78718e52008-04-02 18:10:59 -0300666 struct vivi_dmaqueue *dma_q = &dev->vidq;
667 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300668 DECLARE_WAITQUEUE(wait, current);
669
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300670 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300671 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300672
673 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300674 if (kthread_should_stop())
675 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300676
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300677 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300678 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300679
Hans Verkuil730947b2010-04-10 04:13:53 -0300680 vivi_thread_tick(dev);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300681
682 schedule_timeout_interruptible(timeout);
683
684stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300685 remove_wait_queue(&dma_q->wq, &wait);
686 try_to_freeze();
687}
688
Adrian Bunk972c3512006-04-27 21:06:50 -0300689static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300690{
Hans Verkuil730947b2010-04-10 04:13:53 -0300691 struct vivi_dev *dev = data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300692
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300693 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300694
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700695 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300696
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300697 for (;;) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300698 vivi_sleep(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300699
700 if (kthread_should_stop())
701 break;
702 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300703 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300704 return 0;
705}
706
Pawel Osciake007a322011-01-19 13:02:29 -0200707static int vivi_start_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300708{
Brandon Philips78718e52008-04-02 18:10:59 -0300709 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300710
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300711 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300712
Hans Verkuil730947b2010-04-10 04:13:53 -0300713 /* Resets frame counters */
714 dev->ms = 0;
715 dev->mv_count = 0;
716 dev->jiffies = jiffies;
717
718 dma_q->frame = 0;
719 dma_q->ini_jiffies = jiffies;
720 dma_q->kthread = kthread_run(vivi_thread, dev, dev->v4l2_dev.name);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300721
Akinobu Mita054afee2006-12-20 10:04:00 -0300722 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300723 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Pawel Osciake007a322011-01-19 13:02:29 -0200724 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300725 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300726 /* Wakes thread */
727 wake_up_interruptible(&dma_q->wq);
728
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300729 dprintk(dev, 1, "returning from %s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200730 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300731}
732
Pawel Osciake007a322011-01-19 13:02:29 -0200733static void vivi_stop_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300734{
Hans Verkuil730947b2010-04-10 04:13:53 -0300735 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300736
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300737 dprintk(dev, 1, "%s\n", __func__);
Hans Verkuil730947b2010-04-10 04:13:53 -0300738
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300739 /* shutdown control thread */
740 if (dma_q->kthread) {
741 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300742 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300743 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300744
Pawel Osciake007a322011-01-19 13:02:29 -0200745 /*
746 * Typical driver might need to wait here until dma engine stops.
747 * In this case we can abort imiedetly, so it's just a noop.
748 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300749
Pawel Osciake007a322011-01-19 13:02:29 -0200750 /* Release all active buffers */
751 while (!list_empty(&dma_q->active)) {
752 struct vivi_buffer *buf;
753 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
754 list_del(&buf->list);
755 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
756 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
757 }
758}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300759/* ------------------------------------------------------------------
760 Videobuf operations
761 ------------------------------------------------------------------*/
Guennadi Liakhovetskifc714e702011-08-24 10:30:21 -0300762static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
763 unsigned int *nbuffers, unsigned int *nplanes,
764 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300765{
Pawel Osciake007a322011-01-19 13:02:29 -0200766 struct vivi_dev *dev = vb2_get_drv_priv(vq);
767 unsigned long size;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300768
Hans Verkuil2e90c6c2012-06-22 05:53:31 -0300769 if (fmt)
770 size = fmt->fmt.pix.sizeimage;
771 else
772 size = dev->width * dev->height * dev->pixelsize;
773
774 if (size == 0)
775 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300776
Pawel Osciake007a322011-01-19 13:02:29 -0200777 if (0 == *nbuffers)
778 *nbuffers = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300779
Pawel Osciake007a322011-01-19 13:02:29 -0200780 while (size * *nbuffers > vid_limit * 1024 * 1024)
781 (*nbuffers)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300782
Pawel Osciake007a322011-01-19 13:02:29 -0200783 *nplanes = 1;
784
785 sizes[0] = size;
786
787 /*
788 * videobuf2-vmalloc allocator is context-less so no need to set
789 * alloc_ctxs array.
790 */
791
792 dprintk(dev, 1, "%s, count=%d, size=%ld\n", __func__,
793 *nbuffers, size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300794
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300795 return 0;
796}
797
Pawel Osciake007a322011-01-19 13:02:29 -0200798static int buffer_prepare(struct vb2_buffer *vb)
799{
800 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
801 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
802 unsigned long size;
803
804 dprintk(dev, 1, "%s, field=%d\n", __func__, vb->v4l2_buf.field);
805
806 BUG_ON(NULL == dev->fmt);
807
808 /*
809 * Theses properties only change when queue is idle, see s_fmt.
810 * The below checks should not be performed here, on each
811 * buffer_prepare (i.e. on each qbuf). Most of the code in this function
812 * should thus be moved to buffer_init and s_fmt.
813 */
Hans Verkuil730947b2010-04-10 04:13:53 -0300814 if (dev->width < 48 || dev->width > MAX_WIDTH ||
815 dev->height < 32 || dev->height > MAX_HEIGHT)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300816 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300817
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300818 size = dev->width * dev->height * dev->pixelsize;
Pawel Osciake007a322011-01-19 13:02:29 -0200819 if (vb2_plane_size(vb, 0) < size) {
820 dprintk(dev, 1, "%s data will not fit into plane (%lu < %lu)\n",
821 __func__, vb2_plane_size(vb, 0), size);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300822 return -EINVAL;
Pawel Osciake007a322011-01-19 13:02:29 -0200823 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300824
Pawel Osciake007a322011-01-19 13:02:29 -0200825 vb2_set_plane_payload(&buf->vb, 0, size);
826
827 buf->fmt = dev->fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300828
Hans Verkuil730947b2010-04-10 04:13:53 -0300829 precalculate_bars(dev);
830 precalculate_line(dev);
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300831
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300832 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300833}
834
Pawel Osciake007a322011-01-19 13:02:29 -0200835static void buffer_queue(struct vb2_buffer *vb)
836{
837 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
Hans Verkuil730947b2010-04-10 04:13:53 -0300838 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300839 struct vivi_dmaqueue *vidq = &dev->vidq;
Pawel Osciake007a322011-01-19 13:02:29 -0200840 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300841
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300842 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300843
Pawel Osciake007a322011-01-19 13:02:29 -0200844 spin_lock_irqsave(&dev->slock, flags);
845 list_add_tail(&buf->list, &vidq->active);
846 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300847}
848
Marek Szyprowskibd323e22011-08-29 08:51:49 -0300849static int start_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300850{
Pawel Osciake007a322011-01-19 13:02:29 -0200851 struct vivi_dev *dev = vb2_get_drv_priv(vq);
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300852 dprintk(dev, 1, "%s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200853 return vivi_start_generating(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300854}
855
Pawel Osciake007a322011-01-19 13:02:29 -0200856/* abort streaming and wait for last buffer */
857static int stop_streaming(struct vb2_queue *vq)
858{
859 struct vivi_dev *dev = vb2_get_drv_priv(vq);
860 dprintk(dev, 1, "%s\n", __func__);
861 vivi_stop_generating(dev);
862 return 0;
863}
864
865static void vivi_lock(struct vb2_queue *vq)
866{
867 struct vivi_dev *dev = vb2_get_drv_priv(vq);
868 mutex_lock(&dev->mutex);
869}
870
871static void vivi_unlock(struct vb2_queue *vq)
872{
873 struct vivi_dev *dev = vb2_get_drv_priv(vq);
874 mutex_unlock(&dev->mutex);
875}
876
877
878static struct vb2_ops vivi_video_qops = {
879 .queue_setup = queue_setup,
Pawel Osciake007a322011-01-19 13:02:29 -0200880 .buf_prepare = buffer_prepare,
Pawel Osciake007a322011-01-19 13:02:29 -0200881 .buf_queue = buffer_queue,
882 .start_streaming = start_streaming,
883 .stop_streaming = stop_streaming,
884 .wait_prepare = vivi_unlock,
885 .wait_finish = vivi_lock,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300886};
887
888/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300889 IOCTL vidioc handling
890 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300891static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300892 struct v4l2_capability *cap)
893{
Hans Verkuil730947b2010-04-10 04:13:53 -0300894 struct vivi_dev *dev = video_drvdata(file);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300895
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300896 strcpy(cap->driver, "vivi");
897 strcpy(cap->card, "vivi");
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300898 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Hans Verkuil23268ae2012-01-24 05:24:36 -0300899 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
900 V4L2_CAP_READWRITE;
901 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300902 return 0;
903}
904
Hans Verkuil78b526a2008-05-28 12:16:41 -0300905static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300906 struct v4l2_fmtdesc *f)
907{
Magnus Dammd891f472008-10-14 12:47:09 -0300908 struct vivi_fmt *fmt;
909
910 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300911 return -EINVAL;
912
Magnus Dammd891f472008-10-14 12:47:09 -0300913 fmt = &formats[f->index];
914
915 strlcpy(f->description, fmt->name, sizeof(f->description));
916 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300917 return 0;
918}
919
Hans Verkuil78b526a2008-05-28 12:16:41 -0300920static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300921 struct v4l2_format *f)
922{
Hans Verkuil730947b2010-04-10 04:13:53 -0300923 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300924
Hans Verkuil730947b2010-04-10 04:13:53 -0300925 f->fmt.pix.width = dev->width;
926 f->fmt.pix.height = dev->height;
Hans Verkuilcd779252012-07-25 11:48:53 -0300927 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
Hans Verkuil730947b2010-04-10 04:13:53 -0300928 f->fmt.pix.pixelformat = dev->fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300929 f->fmt.pix.bytesperline =
Hans Verkuil730947b2010-04-10 04:13:53 -0300930 (f->fmt.pix.width * dev->fmt->depth) >> 3;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300931 f->fmt.pix.sizeimage =
932 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil8c79eec2011-07-29 07:19:46 -0300933 if (dev->fmt->fourcc == V4L2_PIX_FMT_YUYV ||
934 dev->fmt->fourcc == V4L2_PIX_FMT_UYVY)
935 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
936 else
937 f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
Hans Verkuil730947b2010-04-10 04:13:53 -0300938 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300939}
940
Hans Verkuil78b526a2008-05-28 12:16:41 -0300941static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300942 struct v4l2_format *f)
943{
Hans Verkuil730947b2010-04-10 04:13:53 -0300944 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300945 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300946
Magnus Dammd891f472008-10-14 12:47:09 -0300947 fmt = get_format(f);
948 if (!fmt) {
Hans Verkuilcd779252012-07-25 11:48:53 -0300949 dprintk(dev, 1, "Fourcc format (0x%08x) unknown.\n",
Magnus Dammd891f472008-10-14 12:47:09 -0300950 f->fmt.pix.pixelformat);
Hans Verkuilcd779252012-07-25 11:48:53 -0300951 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
952 fmt = get_format(f);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300953 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300954
Hans Verkuilcd779252012-07-25 11:48:53 -0300955 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
Hans Verkuil730947b2010-04-10 04:13:53 -0300956 v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
957 &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300958 f->fmt.pix.bytesperline =
959 (f->fmt.pix.width * fmt->depth) >> 3;
960 f->fmt.pix.sizeimage =
961 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil8c79eec2011-07-29 07:19:46 -0300962 if (fmt->fourcc == V4L2_PIX_FMT_YUYV ||
963 fmt->fourcc == V4L2_PIX_FMT_UYVY)
964 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
965 else
966 f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300967 return 0;
968}
969
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300970static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
971 struct v4l2_format *f)
972{
Hans Verkuil730947b2010-04-10 04:13:53 -0300973 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200974 struct vb2_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300975
Hans Verkuil730947b2010-04-10 04:13:53 -0300976 int ret = vidioc_try_fmt_vid_cap(file, priv, f);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300977 if (ret < 0)
978 return ret;
979
Hans Verkuilf2ba5a02012-06-22 05:53:02 -0300980 if (vb2_is_busy(q)) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300981 dprintk(dev, 1, "%s device busy\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200982 return -EBUSY;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300983 }
984
Hans Verkuil730947b2010-04-10 04:13:53 -0300985 dev->fmt = get_format(f);
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300986 dev->pixelsize = dev->fmt->depth / 8;
Hans Verkuil730947b2010-04-10 04:13:53 -0300987 dev->width = f->fmt.pix.width;
988 dev->height = f->fmt.pix.height;
Pawel Osciake007a322011-01-19 13:02:29 -0200989
990 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300991}
992
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300993/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300994static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300995 struct v4l2_input *inp)
996{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300997 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300998 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300999
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001000 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001001 sprintf(inp->name, "Camera %u", inp->index);
Hans Verkuil730947b2010-04-10 04:13:53 -03001002 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001003}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001004
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001005static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001006{
Hans Verkuil730947b2010-04-10 04:13:53 -03001007 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001008
1009 *i = dev->input;
Hans Verkuil730947b2010-04-10 04:13:53 -03001010 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001011}
Hans Verkuil730947b2010-04-10 04:13:53 -03001012
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001013static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001014{
Hans Verkuil730947b2010-04-10 04:13:53 -03001015 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001016
1017 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001018 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001019
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001020 if (i == dev->input)
1021 return 0;
1022
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001023 dev->input = i;
Hans Verkuil730947b2010-04-10 04:13:53 -03001024 precalculate_bars(dev);
1025 precalculate_line(dev);
1026 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001027}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001028
Hans Verkuil730947b2010-04-10 04:13:53 -03001029/* --- controls ---------------------------------------------- */
Hans Verkuil7e996af2011-01-23 12:33:16 -02001030
Hans Verkuila1c894f2011-06-07 06:34:41 -03001031static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1032{
1033 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
1034
1035 if (ctrl == dev->autogain)
1036 dev->gain->val = jiffies & 0xff;
1037 return 0;
1038}
1039
Hans Verkuil7e996af2011-01-23 12:33:16 -02001040static int vivi_s_ctrl(struct v4l2_ctrl *ctrl)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001041{
Hans Verkuil7e996af2011-01-23 12:33:16 -02001042 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001043
Hans Verkuil7088f4d2012-05-02 03:33:52 -03001044 switch (ctrl->id) {
1045 case V4L2_CID_ALPHA_COMPONENT:
1046 dev->alpha_component = ctrl->val;
1047 break;
1048 default:
1049 if (ctrl == dev->button)
1050 dev->button_pressed = 30;
1051 break;
1052 }
Hans Verkuil7e996af2011-01-23 12:33:16 -02001053 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001054}
1055
1056/* ------------------------------------------------------------------
1057 File operations for the device
1058 ------------------------------------------------------------------*/
1059
Hans Verkuil7e996af2011-01-23 12:33:16 -02001060static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
Hans Verkuila1c894f2011-06-07 06:34:41 -03001061 .g_volatile_ctrl = vivi_g_volatile_ctrl,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001062 .s_ctrl = vivi_s_ctrl,
1063};
1064
1065#define VIVI_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
1066
1067static const struct v4l2_ctrl_config vivi_ctrl_button = {
1068 .ops = &vivi_ctrl_ops,
1069 .id = VIVI_CID_CUSTOM_BASE + 0,
1070 .name = "Button",
1071 .type = V4L2_CTRL_TYPE_BUTTON,
1072};
1073
1074static const struct v4l2_ctrl_config vivi_ctrl_boolean = {
1075 .ops = &vivi_ctrl_ops,
1076 .id = VIVI_CID_CUSTOM_BASE + 1,
1077 .name = "Boolean",
1078 .type = V4L2_CTRL_TYPE_BOOLEAN,
1079 .min = 0,
1080 .max = 1,
1081 .step = 1,
1082 .def = 1,
1083};
1084
1085static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
1086 .ops = &vivi_ctrl_ops,
1087 .id = VIVI_CID_CUSTOM_BASE + 2,
1088 .name = "Integer 32 Bits",
1089 .type = V4L2_CTRL_TYPE_INTEGER,
Hans Verkuil5b283022011-01-11 17:32:28 -03001090 .min = 0x80000000,
1091 .max = 0x7fffffff,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001092 .step = 1,
1093};
1094
1095static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
1096 .ops = &vivi_ctrl_ops,
1097 .id = VIVI_CID_CUSTOM_BASE + 3,
1098 .name = "Integer 64 Bits",
1099 .type = V4L2_CTRL_TYPE_INTEGER64,
1100};
1101
1102static const char * const vivi_ctrl_menu_strings[] = {
1103 "Menu Item 0 (Skipped)",
1104 "Menu Item 1",
1105 "Menu Item 2 (Skipped)",
1106 "Menu Item 3",
1107 "Menu Item 4",
1108 "Menu Item 5 (Skipped)",
1109 NULL,
1110};
1111
1112static const struct v4l2_ctrl_config vivi_ctrl_menu = {
1113 .ops = &vivi_ctrl_ops,
1114 .id = VIVI_CID_CUSTOM_BASE + 4,
1115 .name = "Menu",
1116 .type = V4L2_CTRL_TYPE_MENU,
1117 .min = 1,
1118 .max = 4,
1119 .def = 3,
1120 .menu_skip_mask = 0x04,
1121 .qmenu = vivi_ctrl_menu_strings,
1122};
1123
1124static const struct v4l2_ctrl_config vivi_ctrl_string = {
1125 .ops = &vivi_ctrl_ops,
1126 .id = VIVI_CID_CUSTOM_BASE + 5,
1127 .name = "String",
1128 .type = V4L2_CTRL_TYPE_STRING,
1129 .min = 2,
1130 .max = 4,
1131 .step = 1,
1132};
1133
Hans Verkuilb6d17a52011-03-29 16:33:11 -03001134static const struct v4l2_ctrl_config vivi_ctrl_bitmask = {
1135 .ops = &vivi_ctrl_ops,
1136 .id = VIVI_CID_CUSTOM_BASE + 6,
1137 .name = "Bitmask",
1138 .type = V4L2_CTRL_TYPE_BITMASK,
1139 .def = 0x80002000,
1140 .min = 0,
1141 .max = 0x80402010,
1142 .step = 0,
1143};
1144
Sakari Ailusc5203312011-08-05 06:38:05 -03001145static const s64 vivi_ctrl_int_menu_values[] = {
1146 1, 1, 2, 3, 5, 8, 13, 21, 42,
1147};
1148
1149static const struct v4l2_ctrl_config vivi_ctrl_int_menu = {
1150 .ops = &vivi_ctrl_ops,
1151 .id = VIVI_CID_CUSTOM_BASE + 7,
1152 .name = "Integer menu",
1153 .type = V4L2_CTRL_TYPE_INTEGER_MENU,
1154 .min = 1,
1155 .max = 8,
1156 .def = 4,
1157 .menu_skip_mask = 0x02,
1158 .qmenu_int = vivi_ctrl_int_menu_values,
1159};
1160
Hans Verkuilbec43662008-12-30 06:58:20 -03001161static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001162 .owner = THIS_MODULE,
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001163 .open = v4l2_fh_open,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001164 .release = vb2_fop_release,
1165 .read = vb2_fop_read,
1166 .poll = vb2_fop_poll,
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001167 .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001168 .mmap = vb2_fop_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001169};
1170
Hans Verkuila3998102008-07-21 02:57:38 -03001171static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001172 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001173 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1174 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1175 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1176 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001177 .vidioc_reqbufs = vb2_ioctl_reqbufs,
Hans Verkuil2e90c6c2012-06-22 05:53:31 -03001178 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1179 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001180 .vidioc_querybuf = vb2_ioctl_querybuf,
1181 .vidioc_qbuf = vb2_ioctl_qbuf,
1182 .vidioc_dqbuf = vb2_ioctl_dqbuf,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001183 .vidioc_enum_input = vidioc_enum_input,
1184 .vidioc_g_input = vidioc_g_input,
1185 .vidioc_s_input = vidioc_s_input,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001186 .vidioc_streamon = vb2_ioctl_streamon,
1187 .vidioc_streamoff = vb2_ioctl_streamoff,
Hans Verkuile2ecb252012-02-02 08:20:53 -03001188 .vidioc_log_status = v4l2_ctrl_log_status,
Hans Verkuil6d6604f2012-01-27 16:21:10 -03001189 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001190 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Hans Verkuila3998102008-07-21 02:57:38 -03001191};
1192
1193static struct video_device vivi_template = {
1194 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001195 .fops = &vivi_fops,
1196 .ioctl_ops = &vivi_ioctl_ops,
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001197 .release = video_device_release_empty,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001198};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001199
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001200/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001201 Initialization and module stuff
1202 ------------------------------------------------------------------*/
1203
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001204static int vivi_release(void)
1205{
1206 struct vivi_dev *dev;
1207 struct list_head *list;
1208
1209 while (!list_empty(&vivi_devlist)) {
1210 list = vivi_devlist.next;
1211 list_del(list);
1212 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1213
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001214 v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001215 video_device_node_name(&dev->vdev));
1216 video_unregister_device(&dev->vdev);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001217 v4l2_device_unregister(&dev->v4l2_dev);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001218 v4l2_ctrl_handler_free(&dev->ctrl_handler);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001219 kfree(dev);
1220 }
1221
1222 return 0;
1223}
1224
Hans Verkuilc41ee242009-02-14 13:43:44 -03001225static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001226{
1227 struct vivi_dev *dev;
1228 struct video_device *vfd;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001229 struct v4l2_ctrl_handler *hdl;
Pawel Osciake007a322011-01-19 13:02:29 -02001230 struct vb2_queue *q;
Hans Verkuil730947b2010-04-10 04:13:53 -03001231 int ret;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001232
1233 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1234 if (!dev)
1235 return -ENOMEM;
1236
1237 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001238 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001239 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1240 if (ret)
1241 goto free_dev;
1242
Hans Verkuil730947b2010-04-10 04:13:53 -03001243 dev->fmt = &formats[0];
1244 dev->width = 640;
1245 dev->height = 480;
Hans Verkuil3d51dca2012-05-02 03:15:11 -03001246 dev->pixelsize = dev->fmt->depth / 8;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001247 hdl = &dev->ctrl_handler;
1248 v4l2_ctrl_handler_init(hdl, 11);
1249 dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1250 V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
1251 dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1252 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1253 dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1254 V4L2_CID_CONTRAST, 0, 255, 1, 16);
1255 dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1256 V4L2_CID_SATURATION, 0, 255, 1, 127);
1257 dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1258 V4L2_CID_HUE, -128, 127, 1, 0);
Hans Verkuila1c894f2011-06-07 06:34:41 -03001259 dev->autogain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1260 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1261 dev->gain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1262 V4L2_CID_GAIN, 0, 255, 1, 100);
Hans Verkuil7088f4d2012-05-02 03:33:52 -03001263 dev->alpha = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1264 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001265 dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
1266 dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
1267 dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);
1268 dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL);
1269 dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL);
1270 dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL);
Hans Verkuilb6d17a52011-03-29 16:33:11 -03001271 dev->bitmask = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_bitmask, NULL);
Sakari Ailusc5203312011-08-05 06:38:05 -03001272 dev->int_menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int_menu, NULL);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001273 if (hdl->error) {
1274 ret = hdl->error;
1275 goto unreg_dev;
1276 }
Hans Verkuila1c894f2011-06-07 06:34:41 -03001277 v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001278 dev->v4l2_dev.ctrl_handler = hdl;
Hans Verkuil730947b2010-04-10 04:13:53 -03001279
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001280 /* initialize locks */
1281 spin_lock_init(&dev->slock);
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001282
Pawel Osciake007a322011-01-19 13:02:29 -02001283 /* initialize queue */
1284 q = &dev->vb_vidq;
1285 memset(q, 0, sizeof(dev->vb_vidq));
1286 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1287 q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1288 q->drv_priv = dev;
1289 q->buf_struct_size = sizeof(struct vivi_buffer);
1290 q->ops = &vivi_video_qops;
1291 q->mem_ops = &vb2_vmalloc_memops;
1292
1293 vb2_queue_init(q);
1294
1295 mutex_init(&dev->mutex);
Hans Verkuil730947b2010-04-10 04:13:53 -03001296
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001297 /* init video dma queues */
1298 INIT_LIST_HEAD(&dev->vidq.active);
1299 init_waitqueue_head(&dev->vidq.wq);
1300
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001301 vfd = &dev->vdev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001302 *vfd = vivi_template;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -03001303 vfd->debug = debug;
Hans Verkuil730947b2010-04-10 04:13:53 -03001304 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001305 vfd->queue = q;
Hans Verkuilb1a873a2011-03-22 10:14:07 -03001306 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Pawel Osciake007a322011-01-19 13:02:29 -02001307
1308 /*
1309 * Provide a mutex to v4l2 core. It will be used to protect
1310 * all fops and v4l2 ioctls.
1311 */
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001312 vfd->lock = &dev->mutex;
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001313 video_set_drvdata(vfd, dev);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001314
1315 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1316 if (ret < 0)
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001317 goto unreg_dev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001318
1319 /* Now that everything is fine, let's add it to device list */
1320 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1321
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001322 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
1323 video_device_node_name(vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001324 return 0;
1325
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001326unreg_dev:
Hans Verkuil7e996af2011-01-23 12:33:16 -02001327 v4l2_ctrl_handler_free(hdl);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001328 v4l2_device_unregister(&dev->v4l2_dev);
1329free_dev:
1330 kfree(dev);
1331 return ret;
1332}
1333
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001334/* This routine allocates from 1 to n_devs virtual drivers.
1335
1336 The real maximum number of virtual drivers will depend on how many drivers
1337 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001338 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001339 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001340static int __init vivi_init(void)
1341{
Hans Verkuil730947b2010-04-10 04:13:53 -03001342 const struct font_desc *font = find_font("VGA8x16");
Hans Verkuil9185cbf2009-03-06 09:58:12 -03001343 int ret = 0, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001344
Hans Verkuil730947b2010-04-10 04:13:53 -03001345 if (font == NULL) {
1346 printk(KERN_ERR "vivi: could not find font\n");
1347 return -ENODEV;
1348 }
1349 font8x16 = font->data;
1350
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001351 if (n_devs <= 0)
1352 n_devs = 1;
1353
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001354 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001355 ret = vivi_create_instance(i);
1356 if (ret) {
1357 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001358 if (i)
1359 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001360 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001361 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001362 }
1363
1364 if (ret < 0) {
Hans Verkuil730947b2010-04-10 04:13:53 -03001365 printk(KERN_ERR "vivi: error %d while loading driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001366 return ret;
1367 }
1368
1369 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001370 "Capture Board ver %s successfully loaded.\n",
1371 VIVI_VERSION);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001372
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001373 /* n_devs will reflect the actual number of allocated devices */
1374 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001375
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001376 return ret;
1377}
1378
1379static void __exit vivi_exit(void)
1380{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001381 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001382}
1383
1384module_init(vivi_init);
1385module_exit(vivi_exit);