blob: f6d7c6e3390ebb7619fef4b80a8981e49f12075d [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 Verkuil3d51dca2012-05-02 03:15:11 -0300770 size = dev->width * dev->height * dev->pixelsize;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300771
Pawel Osciake007a322011-01-19 13:02:29 -0200772 if (0 == *nbuffers)
773 *nbuffers = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300774
Pawel Osciake007a322011-01-19 13:02:29 -0200775 while (size * *nbuffers > vid_limit * 1024 * 1024)
776 (*nbuffers)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300777
Pawel Osciake007a322011-01-19 13:02:29 -0200778 *nplanes = 1;
779
780 sizes[0] = size;
781
782 /*
783 * videobuf2-vmalloc allocator is context-less so no need to set
784 * alloc_ctxs array.
785 */
786
787 dprintk(dev, 1, "%s, count=%d, size=%ld\n", __func__,
788 *nbuffers, size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300789
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300790 return 0;
791}
792
Pawel Osciake007a322011-01-19 13:02:29 -0200793static int buffer_prepare(struct vb2_buffer *vb)
794{
795 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
796 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
797 unsigned long size;
798
799 dprintk(dev, 1, "%s, field=%d\n", __func__, vb->v4l2_buf.field);
800
801 BUG_ON(NULL == dev->fmt);
802
803 /*
804 * Theses properties only change when queue is idle, see s_fmt.
805 * The below checks should not be performed here, on each
806 * buffer_prepare (i.e. on each qbuf). Most of the code in this function
807 * should thus be moved to buffer_init and s_fmt.
808 */
Hans Verkuil730947b2010-04-10 04:13:53 -0300809 if (dev->width < 48 || dev->width > MAX_WIDTH ||
810 dev->height < 32 || dev->height > MAX_HEIGHT)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300811 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300812
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300813 size = dev->width * dev->height * dev->pixelsize;
Pawel Osciake007a322011-01-19 13:02:29 -0200814 if (vb2_plane_size(vb, 0) < size) {
815 dprintk(dev, 1, "%s data will not fit into plane (%lu < %lu)\n",
816 __func__, vb2_plane_size(vb, 0), size);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300817 return -EINVAL;
Pawel Osciake007a322011-01-19 13:02:29 -0200818 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300819
Pawel Osciake007a322011-01-19 13:02:29 -0200820 vb2_set_plane_payload(&buf->vb, 0, size);
821
822 buf->fmt = dev->fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300823
Hans Verkuil730947b2010-04-10 04:13:53 -0300824 precalculate_bars(dev);
825 precalculate_line(dev);
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300826
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300827 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300828}
829
Pawel Osciake007a322011-01-19 13:02:29 -0200830static void buffer_queue(struct vb2_buffer *vb)
831{
832 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
Hans Verkuil730947b2010-04-10 04:13:53 -0300833 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300834 struct vivi_dmaqueue *vidq = &dev->vidq;
Pawel Osciake007a322011-01-19 13:02:29 -0200835 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300836
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300837 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300838
Pawel Osciake007a322011-01-19 13:02:29 -0200839 spin_lock_irqsave(&dev->slock, flags);
840 list_add_tail(&buf->list, &vidq->active);
841 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300842}
843
Marek Szyprowskibd323e22011-08-29 08:51:49 -0300844static int start_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300845{
Pawel Osciake007a322011-01-19 13:02:29 -0200846 struct vivi_dev *dev = vb2_get_drv_priv(vq);
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300847 dprintk(dev, 1, "%s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200848 return vivi_start_generating(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300849}
850
Pawel Osciake007a322011-01-19 13:02:29 -0200851/* abort streaming and wait for last buffer */
852static int stop_streaming(struct vb2_queue *vq)
853{
854 struct vivi_dev *dev = vb2_get_drv_priv(vq);
855 dprintk(dev, 1, "%s\n", __func__);
856 vivi_stop_generating(dev);
857 return 0;
858}
859
860static void vivi_lock(struct vb2_queue *vq)
861{
862 struct vivi_dev *dev = vb2_get_drv_priv(vq);
863 mutex_lock(&dev->mutex);
864}
865
866static void vivi_unlock(struct vb2_queue *vq)
867{
868 struct vivi_dev *dev = vb2_get_drv_priv(vq);
869 mutex_unlock(&dev->mutex);
870}
871
872
873static struct vb2_ops vivi_video_qops = {
874 .queue_setup = queue_setup,
Pawel Osciake007a322011-01-19 13:02:29 -0200875 .buf_prepare = buffer_prepare,
Pawel Osciake007a322011-01-19 13:02:29 -0200876 .buf_queue = buffer_queue,
877 .start_streaming = start_streaming,
878 .stop_streaming = stop_streaming,
879 .wait_prepare = vivi_unlock,
880 .wait_finish = vivi_lock,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300881};
882
883/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300884 IOCTL vidioc handling
885 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300886static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300887 struct v4l2_capability *cap)
888{
Hans Verkuil730947b2010-04-10 04:13:53 -0300889 struct vivi_dev *dev = video_drvdata(file);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300890
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300891 strcpy(cap->driver, "vivi");
892 strcpy(cap->card, "vivi");
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300893 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Hans Verkuil23268ae2012-01-24 05:24:36 -0300894 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
895 V4L2_CAP_READWRITE;
896 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300897 return 0;
898}
899
Hans Verkuil78b526a2008-05-28 12:16:41 -0300900static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300901 struct v4l2_fmtdesc *f)
902{
Magnus Dammd891f472008-10-14 12:47:09 -0300903 struct vivi_fmt *fmt;
904
905 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300906 return -EINVAL;
907
Magnus Dammd891f472008-10-14 12:47:09 -0300908 fmt = &formats[f->index];
909
910 strlcpy(f->description, fmt->name, sizeof(f->description));
911 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300912 return 0;
913}
914
Hans Verkuil78b526a2008-05-28 12:16:41 -0300915static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300916 struct v4l2_format *f)
917{
Hans Verkuil730947b2010-04-10 04:13:53 -0300918 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300919
Hans Verkuil730947b2010-04-10 04:13:53 -0300920 f->fmt.pix.width = dev->width;
921 f->fmt.pix.height = dev->height;
Pawel Osciake007a322011-01-19 13:02:29 -0200922 f->fmt.pix.field = dev->field;
Hans Verkuil730947b2010-04-10 04:13:53 -0300923 f->fmt.pix.pixelformat = dev->fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300924 f->fmt.pix.bytesperline =
Hans Verkuil730947b2010-04-10 04:13:53 -0300925 (f->fmt.pix.width * dev->fmt->depth) >> 3;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300926 f->fmt.pix.sizeimage =
927 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil8c79eec2011-07-29 07:19:46 -0300928 if (dev->fmt->fourcc == V4L2_PIX_FMT_YUYV ||
929 dev->fmt->fourcc == V4L2_PIX_FMT_UYVY)
930 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
931 else
932 f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
Hans Verkuil730947b2010-04-10 04:13:53 -0300933 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300934}
935
Hans Verkuil78b526a2008-05-28 12:16:41 -0300936static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300937 struct v4l2_format *f)
938{
Hans Verkuil730947b2010-04-10 04:13:53 -0300939 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300940 struct vivi_fmt *fmt;
941 enum v4l2_field field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300942
Magnus Dammd891f472008-10-14 12:47:09 -0300943 fmt = get_format(f);
944 if (!fmt) {
945 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
946 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300947 return -EINVAL;
948 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300949
950 field = f->fmt.pix.field;
951
952 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300953 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300954 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300955 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300956 return -EINVAL;
957 }
958
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300959 f->fmt.pix.field = field;
Hans Verkuil730947b2010-04-10 04:13:53 -0300960 v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
961 &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300962 f->fmt.pix.bytesperline =
963 (f->fmt.pix.width * fmt->depth) >> 3;
964 f->fmt.pix.sizeimage =
965 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil8c79eec2011-07-29 07:19:46 -0300966 if (fmt->fourcc == V4L2_PIX_FMT_YUYV ||
967 fmt->fourcc == V4L2_PIX_FMT_UYVY)
968 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
969 else
970 f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300971 return 0;
972}
973
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300974static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
975 struct v4l2_format *f)
976{
Hans Verkuil730947b2010-04-10 04:13:53 -0300977 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200978 struct vb2_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300979
Hans Verkuil730947b2010-04-10 04:13:53 -0300980 int ret = vidioc_try_fmt_vid_cap(file, priv, f);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300981 if (ret < 0)
982 return ret;
983
Hans Verkuilf2ba5a02012-06-22 05:53:02 -0300984 if (vb2_is_busy(q)) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300985 dprintk(dev, 1, "%s device busy\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200986 return -EBUSY;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300987 }
988
Hans Verkuil730947b2010-04-10 04:13:53 -0300989 dev->fmt = get_format(f);
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300990 dev->pixelsize = dev->fmt->depth / 8;
Hans Verkuil730947b2010-04-10 04:13:53 -0300991 dev->width = f->fmt.pix.width;
992 dev->height = f->fmt.pix.height;
Pawel Osciake007a322011-01-19 13:02:29 -0200993 dev->field = f->fmt.pix.field;
994
995 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300996}
997
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300998/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300999static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001000 struct v4l2_input *inp)
1001{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001002 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001003 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001004
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001005 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001006 sprintf(inp->name, "Camera %u", inp->index);
Hans Verkuil730947b2010-04-10 04:13:53 -03001007 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001008}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001009
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001010static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001011{
Hans Verkuil730947b2010-04-10 04:13:53 -03001012 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001013
1014 *i = dev->input;
Hans Verkuil730947b2010-04-10 04:13:53 -03001015 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001016}
Hans Verkuil730947b2010-04-10 04:13:53 -03001017
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001018static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001019{
Hans Verkuil730947b2010-04-10 04:13:53 -03001020 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001021
1022 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001023 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001024
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001025 if (i == dev->input)
1026 return 0;
1027
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001028 dev->input = i;
Hans Verkuil730947b2010-04-10 04:13:53 -03001029 precalculate_bars(dev);
1030 precalculate_line(dev);
1031 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001032}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001033
Hans Verkuil730947b2010-04-10 04:13:53 -03001034/* --- controls ---------------------------------------------- */
Hans Verkuil7e996af2011-01-23 12:33:16 -02001035
Hans Verkuila1c894f2011-06-07 06:34:41 -03001036static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1037{
1038 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
1039
1040 if (ctrl == dev->autogain)
1041 dev->gain->val = jiffies & 0xff;
1042 return 0;
1043}
1044
Hans Verkuil7e996af2011-01-23 12:33:16 -02001045static int vivi_s_ctrl(struct v4l2_ctrl *ctrl)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001046{
Hans Verkuil7e996af2011-01-23 12:33:16 -02001047 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001048
Hans Verkuil7088f4d2012-05-02 03:33:52 -03001049 switch (ctrl->id) {
1050 case V4L2_CID_ALPHA_COMPONENT:
1051 dev->alpha_component = ctrl->val;
1052 break;
1053 default:
1054 if (ctrl == dev->button)
1055 dev->button_pressed = 30;
1056 break;
1057 }
Hans Verkuil7e996af2011-01-23 12:33:16 -02001058 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001059}
1060
1061/* ------------------------------------------------------------------
1062 File operations for the device
1063 ------------------------------------------------------------------*/
1064
Hans Verkuil7e996af2011-01-23 12:33:16 -02001065static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
Hans Verkuila1c894f2011-06-07 06:34:41 -03001066 .g_volatile_ctrl = vivi_g_volatile_ctrl,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001067 .s_ctrl = vivi_s_ctrl,
1068};
1069
1070#define VIVI_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
1071
1072static const struct v4l2_ctrl_config vivi_ctrl_button = {
1073 .ops = &vivi_ctrl_ops,
1074 .id = VIVI_CID_CUSTOM_BASE + 0,
1075 .name = "Button",
1076 .type = V4L2_CTRL_TYPE_BUTTON,
1077};
1078
1079static const struct v4l2_ctrl_config vivi_ctrl_boolean = {
1080 .ops = &vivi_ctrl_ops,
1081 .id = VIVI_CID_CUSTOM_BASE + 1,
1082 .name = "Boolean",
1083 .type = V4L2_CTRL_TYPE_BOOLEAN,
1084 .min = 0,
1085 .max = 1,
1086 .step = 1,
1087 .def = 1,
1088};
1089
1090static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
1091 .ops = &vivi_ctrl_ops,
1092 .id = VIVI_CID_CUSTOM_BASE + 2,
1093 .name = "Integer 32 Bits",
1094 .type = V4L2_CTRL_TYPE_INTEGER,
Hans Verkuil5b283022011-01-11 17:32:28 -03001095 .min = 0x80000000,
1096 .max = 0x7fffffff,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001097 .step = 1,
1098};
1099
1100static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
1101 .ops = &vivi_ctrl_ops,
1102 .id = VIVI_CID_CUSTOM_BASE + 3,
1103 .name = "Integer 64 Bits",
1104 .type = V4L2_CTRL_TYPE_INTEGER64,
1105};
1106
1107static const char * const vivi_ctrl_menu_strings[] = {
1108 "Menu Item 0 (Skipped)",
1109 "Menu Item 1",
1110 "Menu Item 2 (Skipped)",
1111 "Menu Item 3",
1112 "Menu Item 4",
1113 "Menu Item 5 (Skipped)",
1114 NULL,
1115};
1116
1117static const struct v4l2_ctrl_config vivi_ctrl_menu = {
1118 .ops = &vivi_ctrl_ops,
1119 .id = VIVI_CID_CUSTOM_BASE + 4,
1120 .name = "Menu",
1121 .type = V4L2_CTRL_TYPE_MENU,
1122 .min = 1,
1123 .max = 4,
1124 .def = 3,
1125 .menu_skip_mask = 0x04,
1126 .qmenu = vivi_ctrl_menu_strings,
1127};
1128
1129static const struct v4l2_ctrl_config vivi_ctrl_string = {
1130 .ops = &vivi_ctrl_ops,
1131 .id = VIVI_CID_CUSTOM_BASE + 5,
1132 .name = "String",
1133 .type = V4L2_CTRL_TYPE_STRING,
1134 .min = 2,
1135 .max = 4,
1136 .step = 1,
1137};
1138
Hans Verkuilb6d17a52011-03-29 16:33:11 -03001139static const struct v4l2_ctrl_config vivi_ctrl_bitmask = {
1140 .ops = &vivi_ctrl_ops,
1141 .id = VIVI_CID_CUSTOM_BASE + 6,
1142 .name = "Bitmask",
1143 .type = V4L2_CTRL_TYPE_BITMASK,
1144 .def = 0x80002000,
1145 .min = 0,
1146 .max = 0x80402010,
1147 .step = 0,
1148};
1149
Sakari Ailusc5203312011-08-05 06:38:05 -03001150static const s64 vivi_ctrl_int_menu_values[] = {
1151 1, 1, 2, 3, 5, 8, 13, 21, 42,
1152};
1153
1154static const struct v4l2_ctrl_config vivi_ctrl_int_menu = {
1155 .ops = &vivi_ctrl_ops,
1156 .id = VIVI_CID_CUSTOM_BASE + 7,
1157 .name = "Integer menu",
1158 .type = V4L2_CTRL_TYPE_INTEGER_MENU,
1159 .min = 1,
1160 .max = 8,
1161 .def = 4,
1162 .menu_skip_mask = 0x02,
1163 .qmenu_int = vivi_ctrl_int_menu_values,
1164};
1165
Hans Verkuilbec43662008-12-30 06:58:20 -03001166static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001167 .owner = THIS_MODULE,
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001168 .open = v4l2_fh_open,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001169 .release = vb2_fop_release,
1170 .read = vb2_fop_read,
1171 .poll = vb2_fop_poll,
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001172 .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001173 .mmap = vb2_fop_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001174};
1175
Hans Verkuila3998102008-07-21 02:57:38 -03001176static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001177 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001178 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1179 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1180 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1181 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001182 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1183 .vidioc_querybuf = vb2_ioctl_querybuf,
1184 .vidioc_qbuf = vb2_ioctl_qbuf,
1185 .vidioc_dqbuf = vb2_ioctl_dqbuf,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001186 .vidioc_enum_input = vidioc_enum_input,
1187 .vidioc_g_input = vidioc_g_input,
1188 .vidioc_s_input = vidioc_s_input,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001189 .vidioc_streamon = vb2_ioctl_streamon,
1190 .vidioc_streamoff = vb2_ioctl_streamoff,
Hans Verkuile2ecb252012-02-02 08:20:53 -03001191 .vidioc_log_status = v4l2_ctrl_log_status,
Hans Verkuil6d6604f2012-01-27 16:21:10 -03001192 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001193 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Hans Verkuila3998102008-07-21 02:57:38 -03001194};
1195
1196static struct video_device vivi_template = {
1197 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001198 .fops = &vivi_fops,
1199 .ioctl_ops = &vivi_ioctl_ops,
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001200 .release = video_device_release_empty,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001201};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001202
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001203/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001204 Initialization and module stuff
1205 ------------------------------------------------------------------*/
1206
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001207static int vivi_release(void)
1208{
1209 struct vivi_dev *dev;
1210 struct list_head *list;
1211
1212 while (!list_empty(&vivi_devlist)) {
1213 list = vivi_devlist.next;
1214 list_del(list);
1215 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1216
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001217 v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001218 video_device_node_name(&dev->vdev));
1219 video_unregister_device(&dev->vdev);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001220 v4l2_device_unregister(&dev->v4l2_dev);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001221 v4l2_ctrl_handler_free(&dev->ctrl_handler);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001222 kfree(dev);
1223 }
1224
1225 return 0;
1226}
1227
Hans Verkuilc41ee242009-02-14 13:43:44 -03001228static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001229{
1230 struct vivi_dev *dev;
1231 struct video_device *vfd;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001232 struct v4l2_ctrl_handler *hdl;
Pawel Osciake007a322011-01-19 13:02:29 -02001233 struct vb2_queue *q;
Hans Verkuil730947b2010-04-10 04:13:53 -03001234 int ret;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001235
1236 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1237 if (!dev)
1238 return -ENOMEM;
1239
1240 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001241 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001242 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1243 if (ret)
1244 goto free_dev;
1245
Hans Verkuil730947b2010-04-10 04:13:53 -03001246 dev->fmt = &formats[0];
1247 dev->width = 640;
1248 dev->height = 480;
Hans Verkuil3d51dca2012-05-02 03:15:11 -03001249 dev->pixelsize = dev->fmt->depth / 8;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001250 hdl = &dev->ctrl_handler;
1251 v4l2_ctrl_handler_init(hdl, 11);
1252 dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1253 V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
1254 dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1255 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1256 dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1257 V4L2_CID_CONTRAST, 0, 255, 1, 16);
1258 dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1259 V4L2_CID_SATURATION, 0, 255, 1, 127);
1260 dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1261 V4L2_CID_HUE, -128, 127, 1, 0);
Hans Verkuila1c894f2011-06-07 06:34:41 -03001262 dev->autogain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1263 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1264 dev->gain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1265 V4L2_CID_GAIN, 0, 255, 1, 100);
Hans Verkuil7088f4d2012-05-02 03:33:52 -03001266 dev->alpha = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1267 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001268 dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
1269 dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
1270 dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);
1271 dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL);
1272 dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL);
1273 dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL);
Hans Verkuilb6d17a52011-03-29 16:33:11 -03001274 dev->bitmask = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_bitmask, NULL);
Sakari Ailusc5203312011-08-05 06:38:05 -03001275 dev->int_menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int_menu, NULL);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001276 if (hdl->error) {
1277 ret = hdl->error;
1278 goto unreg_dev;
1279 }
Hans Verkuila1c894f2011-06-07 06:34:41 -03001280 v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001281 dev->v4l2_dev.ctrl_handler = hdl;
Hans Verkuil730947b2010-04-10 04:13:53 -03001282
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001283 /* initialize locks */
1284 spin_lock_init(&dev->slock);
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001285
Pawel Osciake007a322011-01-19 13:02:29 -02001286 /* initialize queue */
1287 q = &dev->vb_vidq;
1288 memset(q, 0, sizeof(dev->vb_vidq));
1289 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1290 q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1291 q->drv_priv = dev;
1292 q->buf_struct_size = sizeof(struct vivi_buffer);
1293 q->ops = &vivi_video_qops;
1294 q->mem_ops = &vb2_vmalloc_memops;
1295
1296 vb2_queue_init(q);
1297
1298 mutex_init(&dev->mutex);
Hans Verkuil730947b2010-04-10 04:13:53 -03001299
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001300 /* init video dma queues */
1301 INIT_LIST_HEAD(&dev->vidq.active);
1302 init_waitqueue_head(&dev->vidq.wq);
1303
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001304 vfd = &dev->vdev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001305 *vfd = vivi_template;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -03001306 vfd->debug = debug;
Hans Verkuil730947b2010-04-10 04:13:53 -03001307 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001308 vfd->queue = q;
Hans Verkuilb1a873a2011-03-22 10:14:07 -03001309 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Pawel Osciake007a322011-01-19 13:02:29 -02001310
1311 /*
1312 * Provide a mutex to v4l2 core. It will be used to protect
1313 * all fops and v4l2 ioctls.
1314 */
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001315 vfd->lock = &dev->mutex;
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001316 video_set_drvdata(vfd, dev);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001317
1318 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1319 if (ret < 0)
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001320 goto unreg_dev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001321
1322 /* Now that everything is fine, let's add it to device list */
1323 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1324
Roel Kluin7de0b872009-12-16 13:06:33 -03001325 if (video_nr != -1)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001326 video_nr++;
1327
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001328 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
1329 video_device_node_name(vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001330 return 0;
1331
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001332unreg_dev:
Hans Verkuil7e996af2011-01-23 12:33:16 -02001333 v4l2_ctrl_handler_free(hdl);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001334 v4l2_device_unregister(&dev->v4l2_dev);
1335free_dev:
1336 kfree(dev);
1337 return ret;
1338}
1339
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001340/* This routine allocates from 1 to n_devs virtual drivers.
1341
1342 The real maximum number of virtual drivers will depend on how many drivers
1343 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001344 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001345 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001346static int __init vivi_init(void)
1347{
Hans Verkuil730947b2010-04-10 04:13:53 -03001348 const struct font_desc *font = find_font("VGA8x16");
Hans Verkuil9185cbf2009-03-06 09:58:12 -03001349 int ret = 0, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001350
Hans Verkuil730947b2010-04-10 04:13:53 -03001351 if (font == NULL) {
1352 printk(KERN_ERR "vivi: could not find font\n");
1353 return -ENODEV;
1354 }
1355 font8x16 = font->data;
1356
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001357 if (n_devs <= 0)
1358 n_devs = 1;
1359
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001360 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001361 ret = vivi_create_instance(i);
1362 if (ret) {
1363 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001364 if (i)
1365 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001366 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001367 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001368 }
1369
1370 if (ret < 0) {
Hans Verkuil730947b2010-04-10 04:13:53 -03001371 printk(KERN_ERR "vivi: error %d while loading driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001372 return ret;
1373 }
1374
1375 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001376 "Capture Board ver %s successfully loaded.\n",
1377 VIVI_VERSION);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001378
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001379 /* n_devs will reflect the actual number of allocated devices */
1380 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001381
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001382 return ret;
1383}
1384
1385static void __exit vivi_exit(void)
1386{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001387 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001388}
1389
1390module_init(vivi_init);
1391module_exit(vivi_exit);