blob: c2f424f32450b37dcabe340e367a1006227f93d1 [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
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030042
Hans Verkuil730947b2010-04-10 04:13:53 -030043#define MAX_WIDTH 1920
44#define MAX_HEIGHT 1200
45
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030046#define VIVI_VERSION "0.8.1"
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030047
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030048MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
49MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
50MODULE_LICENSE("Dual BSD/GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030051MODULE_VERSION(VIVI_VERSION);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030052
53static unsigned video_nr = -1;
54module_param(video_nr, uint, 0644);
55MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
56
57static unsigned n_devs = 1;
58module_param(n_devs, uint, 0644);
59MODULE_PARM_DESC(n_devs, "number of video devices to create");
60
61static unsigned debug;
62module_param(debug, uint, 0644);
63MODULE_PARM_DESC(debug, "activates debug info");
64
65static unsigned int vid_limit = 16;
66module_param(vid_limit, uint, 0644);
67MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
68
Hans Verkuil730947b2010-04-10 04:13:53 -030069/* Global font descriptor */
70static const u8 *font8x16;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030071
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030072#define dprintk(dev, level, fmt, arg...) \
73 v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030074
75/* ------------------------------------------------------------------
76 Basic structures
77 ------------------------------------------------------------------*/
78
79struct vivi_fmt {
80 char *name;
81 u32 fourcc; /* v4l2 format id */
Hans Verkuil0a3a8a32012-08-06 10:36:18 -030082 u8 depth;
83 bool is_yuv;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030084};
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,
Hans Verkuil0a3a8a32012-08-06 10:36:18 -030091 .is_yuv = true,
Magnus Dammd891f472008-10-14 12:47:09 -030092 },
Magnus Dammfca36ba2008-10-14 12:47:25 -030093 {
94 .name = "4:2:2, packed, UYVY",
95 .fourcc = V4L2_PIX_FMT_UYVY,
96 .depth = 16,
Hans Verkuil0a3a8a32012-08-06 10:36:18 -030097 .is_yuv = true,
Magnus Dammfca36ba2008-10-14 12:47:25 -030098 },
Magnus Dammaeadb5d2008-10-14 12:47:35 -030099 {
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300100 .name = "4:2:2, packed, YVYU",
101 .fourcc = V4L2_PIX_FMT_YVYU,
102 .depth = 16,
Hans Verkuil0a3a8a32012-08-06 10:36:18 -0300103 .is_yuv = true,
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300104 },
105 {
106 .name = "4:2:2, packed, VYUY",
107 .fourcc = V4L2_PIX_FMT_VYUY,
108 .depth = 16,
Hans Verkuil0a3a8a32012-08-06 10:36:18 -0300109 .is_yuv = true,
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300110 },
111 {
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300112 .name = "RGB565 (LE)",
113 .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
114 .depth = 16,
115 },
116 {
117 .name = "RGB565 (BE)",
118 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
119 .depth = 16,
120 },
Magnus Dammdef52392008-10-14 12:47:43 -0300121 {
122 .name = "RGB555 (LE)",
123 .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
124 .depth = 16,
125 },
126 {
127 .name = "RGB555 (BE)",
128 .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
129 .depth = 16,
130 },
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300131 {
132 .name = "RGB24 (LE)",
133 .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */
134 .depth = 24,
135 },
136 {
137 .name = "RGB24 (BE)",
138 .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */
139 .depth = 24,
140 },
141 {
142 .name = "RGB32 (LE)",
143 .fourcc = V4L2_PIX_FMT_RGB32, /* argb */
144 .depth = 32,
145 },
146 {
147 .name = "RGB32 (BE)",
148 .fourcc = V4L2_PIX_FMT_BGR32, /* bgra */
149 .depth = 32,
150 },
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300151};
152
Magnus Dammd891f472008-10-14 12:47:09 -0300153static struct vivi_fmt *get_format(struct v4l2_format *f)
154{
155 struct vivi_fmt *fmt;
156 unsigned int k;
157
158 for (k = 0; k < ARRAY_SIZE(formats); k++) {
159 fmt = &formats[k];
160 if (fmt->fourcc == f->fmt.pix.pixelformat)
161 break;
162 }
163
164 if (k == ARRAY_SIZE(formats))
165 return NULL;
166
167 return &formats[k];
168}
169
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300170/* buffer for one video frame */
171struct vivi_buffer {
172 /* common v4l buffer stuff -- must be first */
Pawel Osciake007a322011-01-19 13:02:29 -0200173 struct vb2_buffer vb;
174 struct list_head list;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300175 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300176};
177
178struct vivi_dmaqueue {
179 struct list_head active;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300180
181 /* thread for generating video stream*/
182 struct task_struct *kthread;
183 wait_queue_head_t wq;
184 /* Counters to control fps rate */
185 int frame;
186 int ini_jiffies;
187};
188
189static LIST_HEAD(vivi_devlist);
190
191struct vivi_dev {
192 struct list_head vivi_devlist;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300193 struct v4l2_device v4l2_dev;
Hans Verkuil7e996af2011-01-23 12:33:16 -0200194 struct v4l2_ctrl_handler ctrl_handler;
Hans Verkuil70bd97a2012-06-09 11:27:43 -0300195 struct video_device vdev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300196
Hans Verkuil730947b2010-04-10 04:13:53 -0300197 /* controls */
Hans Verkuil7e996af2011-01-23 12:33:16 -0200198 struct v4l2_ctrl *brightness;
199 struct v4l2_ctrl *contrast;
200 struct v4l2_ctrl *saturation;
201 struct v4l2_ctrl *hue;
Hans Verkuila1c894f2011-06-07 06:34:41 -0300202 struct {
203 /* autogain/gain cluster */
204 struct v4l2_ctrl *autogain;
205 struct v4l2_ctrl *gain;
206 };
Hans Verkuil7e996af2011-01-23 12:33:16 -0200207 struct v4l2_ctrl *volume;
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300208 struct v4l2_ctrl *alpha;
Hans Verkuil7e996af2011-01-23 12:33:16 -0200209 struct v4l2_ctrl *button;
210 struct v4l2_ctrl *boolean;
211 struct v4l2_ctrl *int32;
212 struct v4l2_ctrl *int64;
213 struct v4l2_ctrl *menu;
214 struct v4l2_ctrl *string;
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300215 struct v4l2_ctrl *bitmask;
Sakari Ailusc5203312011-08-05 06:38:05 -0300216 struct v4l2_ctrl *int_menu;
Hans Verkuil730947b2010-04-10 04:13:53 -0300217
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300218 spinlock_t slock;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300219 struct mutex mutex;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300220
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300221 struct vivi_dmaqueue vidq;
222
223 /* Several counters */
Hans Verkuil730947b2010-04-10 04:13:53 -0300224 unsigned ms;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300225 unsigned long jiffies;
Hans Verkuil7e996af2011-01-23 12:33:16 -0200226 unsigned button_pressed;
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300227
228 int mv_count; /* Controls bars movement */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300229
230 /* Input Number */
231 int input;
Hans Verkuilc41ee242009-02-14 13:43:44 -0300232
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300233 /* video capture */
234 struct vivi_fmt *fmt;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300235 unsigned int width, height;
Pawel Osciake007a322011-01-19 13:02:29 -0200236 struct vb2_queue vb_vidq;
Pawel Osciake007a322011-01-19 13:02:29 -0200237 unsigned int field_count;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300238
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300239 u8 bars[9][3];
240 u8 line[MAX_WIDTH * 8];
241 unsigned int pixelsize;
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300242 u8 alpha_component;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300243};
244
245/* ------------------------------------------------------------------
246 DMA and thread functions
247 ------------------------------------------------------------------*/
248
249/* Bars and Colors should match positions */
250
251enum colors {
252 WHITE,
Hans Verkuil730947b2010-04-10 04:13:53 -0300253 AMBER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300254 CYAN,
255 GREEN,
256 MAGENTA,
257 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300258 BLUE,
259 BLACK,
Hans Verkuil730947b2010-04-10 04:13:53 -0300260 TEXT_BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300261};
262
Hans Verkuil730947b2010-04-10 04:13:53 -0300263/* R G B */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300264#define COLOR_WHITE {204, 204, 204}
Hans Verkuil730947b2010-04-10 04:13:53 -0300265#define COLOR_AMBER {208, 208, 0}
266#define COLOR_CYAN { 0, 206, 206}
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300267#define COLOR_GREEN { 0, 239, 0}
268#define COLOR_MAGENTA {239, 0, 239}
269#define COLOR_RED {205, 0, 0}
270#define COLOR_BLUE { 0, 0, 255}
271#define COLOR_BLACK { 0, 0, 0}
272
273struct bar_std {
Hans Verkuil730947b2010-04-10 04:13:53 -0300274 u8 bar[9][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300275};
276
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300277/* Maximum number of bars are 10 - otherwise, the input print code
278 should be modified */
279static struct bar_std bars[] = {
280 { /* Standard ITU-R color bar sequence */
Hans Verkuil730947b2010-04-10 04:13:53 -0300281 { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN,
282 COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300283 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300284 { COLOR_WHITE, COLOR_AMBER, COLOR_BLACK, COLOR_WHITE,
285 COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, COLOR_AMBER, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300286 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300287 { COLOR_WHITE, COLOR_CYAN, COLOR_BLACK, COLOR_WHITE,
288 COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, COLOR_CYAN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300289 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300290 { COLOR_WHITE, COLOR_GREEN, COLOR_BLACK, COLOR_WHITE,
291 COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, COLOR_GREEN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300292 },
293};
294
295#define NUM_INPUTS ARRAY_SIZE(bars)
296
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300297#define TO_Y(r, g, b) \
298 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300299/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300300#define TO_V(r, g, b) \
301 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300302/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300303#define TO_U(r, g, b) \
304 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300305
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300306/* precalculate color bar values to speed up rendering */
Hans Verkuil730947b2010-04-10 04:13:53 -0300307static void precalculate_bars(struct vivi_dev *dev)
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300308{
Hans Verkuil730947b2010-04-10 04:13:53 -0300309 u8 r, g, b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300310 int k, is_yuv;
311
Hans Verkuil730947b2010-04-10 04:13:53 -0300312 for (k = 0; k < 9; k++) {
313 r = bars[dev->input].bar[k][0];
314 g = bars[dev->input].bar[k][1];
315 b = bars[dev->input].bar[k][2];
Hans Verkuil0a3a8a32012-08-06 10:36:18 -0300316 is_yuv = dev->fmt->is_yuv;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300317
Hans Verkuil730947b2010-04-10 04:13:53 -0300318 switch (dev->fmt->fourcc) {
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300319 case V4L2_PIX_FMT_RGB565:
320 case V4L2_PIX_FMT_RGB565X:
321 r >>= 3;
322 g >>= 2;
323 b >>= 3;
324 break;
325 case V4L2_PIX_FMT_RGB555:
326 case V4L2_PIX_FMT_RGB555X:
327 r >>= 3;
328 g >>= 3;
329 b >>= 3;
330 break;
Hans Verkuil0a3a8a32012-08-06 10:36:18 -0300331 case V4L2_PIX_FMT_YUYV:
332 case V4L2_PIX_FMT_UYVY:
333 case V4L2_PIX_FMT_YVYU:
334 case V4L2_PIX_FMT_VYUY:
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300335 case V4L2_PIX_FMT_RGB24:
336 case V4L2_PIX_FMT_BGR24:
337 case V4L2_PIX_FMT_RGB32:
338 case V4L2_PIX_FMT_BGR32:
339 break;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300340 }
341
342 if (is_yuv) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300343 dev->bars[k][0] = TO_Y(r, g, b); /* Luma */
344 dev->bars[k][1] = TO_U(r, g, b); /* Cb */
345 dev->bars[k][2] = TO_V(r, g, b); /* Cr */
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300346 } else {
Hans Verkuil730947b2010-04-10 04:13:53 -0300347 dev->bars[k][0] = r;
348 dev->bars[k][1] = g;
349 dev->bars[k][2] = b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300350 }
351 }
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300352}
353
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300354/* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */
355static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos, bool odd)
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300356{
Hans Verkuil730947b2010-04-10 04:13:53 -0300357 u8 r_y, g_u, b_v;
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300358 u8 alpha = dev->alpha_component;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300359 int color;
Hans Verkuil730947b2010-04-10 04:13:53 -0300360 u8 *p;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300361
Hans Verkuil730947b2010-04-10 04:13:53 -0300362 r_y = dev->bars[colorpos][0]; /* R or precalculated Y */
363 g_u = dev->bars[colorpos][1]; /* G or precalculated U */
364 b_v = dev->bars[colorpos][2]; /* B or precalculated V */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300365
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300366 for (color = 0; color < dev->pixelsize; color++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300367 p = buf + color;
368
Hans Verkuil730947b2010-04-10 04:13:53 -0300369 switch (dev->fmt->fourcc) {
Magnus Dammd891f472008-10-14 12:47:09 -0300370 case V4L2_PIX_FMT_YUYV:
371 switch (color) {
372 case 0:
Magnus Dammd891f472008-10-14 12:47:09 -0300373 *p = r_y;
374 break;
375 case 1:
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300376 *p = odd ? b_v : g_u;
Magnus Dammd891f472008-10-14 12:47:09 -0300377 break;
378 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300379 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300380 case V4L2_PIX_FMT_UYVY:
381 switch (color) {
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300382 case 0:
383 *p = odd ? b_v : g_u;
384 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300385 case 1:
Magnus Dammfca36ba2008-10-14 12:47:25 -0300386 *p = r_y;
387 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300388 }
389 break;
390 case V4L2_PIX_FMT_YVYU:
391 switch (color) {
Magnus Dammfca36ba2008-10-14 12:47:25 -0300392 case 0:
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300393 *p = r_y;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300394 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300395 case 1:
396 *p = odd ? g_u : b_v;
397 break;
398 }
399 break;
400 case V4L2_PIX_FMT_VYUY:
401 switch (color) {
402 case 0:
403 *p = odd ? g_u : b_v;
404 break;
405 case 1:
406 *p = r_y;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300407 break;
408 }
409 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300410 case V4L2_PIX_FMT_RGB565:
411 switch (color) {
412 case 0:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300413 *p = (g_u << 5) | b_v;
414 break;
415 case 1:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300416 *p = (r_y << 3) | (g_u >> 3);
417 break;
418 }
419 break;
420 case V4L2_PIX_FMT_RGB565X:
421 switch (color) {
422 case 0:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300423 *p = (r_y << 3) | (g_u >> 3);
424 break;
425 case 1:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300426 *p = (g_u << 5) | b_v;
427 break;
428 }
429 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300430 case V4L2_PIX_FMT_RGB555:
431 switch (color) {
432 case 0:
Magnus Dammdef52392008-10-14 12:47:43 -0300433 *p = (g_u << 5) | b_v;
434 break;
435 case 1:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300436 *p = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
Magnus Dammdef52392008-10-14 12:47:43 -0300437 break;
438 }
439 break;
440 case V4L2_PIX_FMT_RGB555X:
441 switch (color) {
442 case 0:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300443 *p = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
Magnus Dammdef52392008-10-14 12:47:43 -0300444 break;
445 case 1:
Magnus Dammdef52392008-10-14 12:47:43 -0300446 *p = (g_u << 5) | b_v;
447 break;
448 }
449 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300450 case V4L2_PIX_FMT_RGB24:
451 switch (color) {
452 case 0:
453 *p = r_y;
454 break;
455 case 1:
456 *p = g_u;
457 break;
458 case 2:
459 *p = b_v;
460 break;
461 }
462 break;
463 case V4L2_PIX_FMT_BGR24:
464 switch (color) {
465 case 0:
466 *p = b_v;
467 break;
468 case 1:
469 *p = g_u;
470 break;
471 case 2:
472 *p = r_y;
473 break;
474 }
475 break;
476 case V4L2_PIX_FMT_RGB32:
477 switch (color) {
478 case 0:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300479 *p = alpha;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300480 break;
481 case 1:
482 *p = r_y;
483 break;
484 case 2:
485 *p = g_u;
486 break;
487 case 3:
488 *p = b_v;
489 break;
490 }
491 break;
492 case V4L2_PIX_FMT_BGR32:
493 switch (color) {
494 case 0:
495 *p = b_v;
496 break;
497 case 1:
498 *p = g_u;
499 break;
500 case 2:
501 *p = r_y;
502 break;
503 case 3:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300504 *p = alpha;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300505 break;
506 }
507 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300508 }
509 }
510}
511
Hans Verkuil730947b2010-04-10 04:13:53 -0300512static void precalculate_line(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300513{
Hans Verkuil730947b2010-04-10 04:13:53 -0300514 int w;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300515
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300516 for (w = 0; w < dev->width * 2; w++) {
517 int colorpos = w / (dev->width / 8) % 8;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300518
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300519 gen_twopix(dev, dev->line + w * dev->pixelsize, colorpos, w & 1);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300520 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300521}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300522
Hans Verkuil730947b2010-04-10 04:13:53 -0300523static void gen_text(struct vivi_dev *dev, char *basep,
524 int y, int x, char *text)
525{
526 int line;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300527
Hans Verkuil730947b2010-04-10 04:13:53 -0300528 /* Checks if it is possible to show string */
529 if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width)
530 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300531
532 /* Print stream time */
Hans Verkuil730947b2010-04-10 04:13:53 -0300533 for (line = y; line < y + 16; line++) {
534 int j = 0;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300535 char *pos = basep + line * dev->width * dev->pixelsize + x * dev->pixelsize;
Hans Verkuil730947b2010-04-10 04:13:53 -0300536 char *s;
537
538 for (s = text; *s; s++) {
539 u8 chr = font8x16[*s * 16 + line - y];
540 int i;
541
542 for (i = 0; i < 7; i++, j++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300543 /* Draw white font on black background */
Hans Verkuil730947b2010-04-10 04:13:53 -0300544 if (chr & (1 << (7 - i)))
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300545 gen_twopix(dev, pos + j * dev->pixelsize, WHITE, (x+y) & 1);
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300546 else
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300547 gen_twopix(dev, pos + j * dev->pixelsize, TEXT_BLACK, (x+y) & 1);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300548 }
549 }
550 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300551}
Brandon Philips78718e52008-04-02 18:10:59 -0300552
Hans Verkuil730947b2010-04-10 04:13:53 -0300553static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300554{
Pawel Osciake007a322011-01-19 13:02:29 -0200555 int wmax = dev->width;
556 int hmax = dev->height;
Pawel Osciake007a322011-01-19 13:02:29 -0200557 void *vbuf = vb2_plane_vaddr(&buf->vb, 0);
Hans Verkuil730947b2010-04-10 04:13:53 -0300558 unsigned ms;
559 char str[100];
560 int h, line = 1;
Hans Verkuila1c894f2011-06-07 06:34:41 -0300561 s32 gain;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300562
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300563 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300564 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300565
Hans Verkuil730947b2010-04-10 04:13:53 -0300566 for (h = 0; h < hmax; h++)
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300567 memcpy(vbuf + h * wmax * dev->pixelsize,
568 dev->line + (dev->mv_count % wmax) * dev->pixelsize,
569 wmax * dev->pixelsize);
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300570
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300571 /* Updates stream time */
572
Hans Verkuil730947b2010-04-10 04:13:53 -0300573 dev->ms += jiffies_to_msecs(jiffies - dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300574 dev->jiffies = jiffies;
Hans Verkuil730947b2010-04-10 04:13:53 -0300575 ms = dev->ms;
576 snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d ",
577 (ms / (60 * 60 * 1000)) % 24,
578 (ms / (60 * 1000)) % 60,
579 (ms / 1000) % 60,
580 ms % 1000);
581 gen_text(dev, vbuf, line++ * 16, 16, str);
582 snprintf(str, sizeof(str), " %dx%d, input %d ",
583 dev->width, dev->height, dev->input);
584 gen_text(dev, vbuf, line++ * 16, 16, str);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300585
Hans Verkuila1c894f2011-06-07 06:34:41 -0300586 gain = v4l2_ctrl_g_ctrl(dev->gain);
Sakari Ailus77e7c4e2012-01-24 21:05:34 -0300587 mutex_lock(dev->ctrl_handler.lock);
Hans Verkuil730947b2010-04-10 04:13:53 -0300588 snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
Hans Verkuil7e996af2011-01-23 12:33:16 -0200589 dev->brightness->cur.val,
590 dev->contrast->cur.val,
591 dev->saturation->cur.val,
592 dev->hue->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300593 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300594 snprintf(str, sizeof(str), " autogain %d, gain %3d, volume %3d, alpha 0x%02x ",
595 dev->autogain->cur.val, gain, dev->volume->cur.val,
596 dev->alpha->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300597 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300598 snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
Hans Verkuil7e996af2011-01-23 12:33:16 -0200599 dev->int32->cur.val,
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300600 dev->int64->cur.val64,
601 dev->bitmask->cur.val);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200602 gen_text(dev, vbuf, line++ * 16, 16, str);
603 snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
604 dev->boolean->cur.val,
605 dev->menu->qmenu[dev->menu->cur.val],
606 dev->string->cur.string);
Hans Verkuilf70cfc72012-04-19 11:44:18 -0300607 gen_text(dev, vbuf, line++ * 16, 16, str);
Sakari Ailusc5203312011-08-05 06:38:05 -0300608 snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
609 dev->int_menu->qmenu_int[dev->int_menu->cur.val],
610 dev->int_menu->cur.val);
611 gen_text(dev, vbuf, line++ * 16, 16, str);
Sakari Ailus77e7c4e2012-01-24 21:05:34 -0300612 mutex_unlock(dev->ctrl_handler.lock);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200613 if (dev->button_pressed) {
614 dev->button_pressed--;
615 snprintf(str, sizeof(str), " button pressed!");
616 gen_text(dev, vbuf, line++ * 16, 16, str);
617 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300618
619 dev->mv_count += 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300620
Hans Verkuilcd779252012-07-25 11:48:53 -0300621 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
Pawel Osciake007a322011-01-19 13:02:29 -0200622 dev->field_count++;
623 buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300624 v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300625}
626
Hans Verkuil730947b2010-04-10 04:13:53 -0300627static void vivi_thread_tick(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300628{
Brandon Philips78718e52008-04-02 18:10:59 -0300629 struct vivi_dmaqueue *dma_q = &dev->vidq;
Hans Verkuil730947b2010-04-10 04:13:53 -0300630 struct vivi_buffer *buf;
Brandon Philips78718e52008-04-02 18:10:59 -0300631 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300632
Brandon Philips78718e52008-04-02 18:10:59 -0300633 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300634
Brandon Philips78718e52008-04-02 18:10:59 -0300635 spin_lock_irqsave(&dev->slock, flags);
636 if (list_empty(&dma_q->active)) {
637 dprintk(dev, 1, "No active queue to serve\n");
Hans Verkuil1de5be52011-07-05 07:19:23 -0300638 spin_unlock_irqrestore(&dev->slock, flags);
639 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300640 }
Brandon Philips78718e52008-04-02 18:10:59 -0300641
Pawel Osciake007a322011-01-19 13:02:29 -0200642 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
643 list_del(&buf->list);
Hans Verkuil1de5be52011-07-05 07:19:23 -0300644 spin_unlock_irqrestore(&dev->slock, flags);
Brandon Philips78718e52008-04-02 18:10:59 -0300645
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300646 v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
Brandon Philips78718e52008-04-02 18:10:59 -0300647
648 /* Fill buffer */
Hans Verkuil730947b2010-04-10 04:13:53 -0300649 vivi_fillbuff(dev, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300650 dprintk(dev, 1, "filled buffer %p\n", buf);
651
Pawel Osciake007a322011-01-19 13:02:29 -0200652 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
653 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300654}
655
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300656#define frames_to_ms(frames) \
657 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
658
Hans Verkuil730947b2010-04-10 04:13:53 -0300659static void vivi_sleep(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300660{
Brandon Philips78718e52008-04-02 18:10:59 -0300661 struct vivi_dmaqueue *dma_q = &dev->vidq;
662 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300663 DECLARE_WAITQUEUE(wait, current);
664
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300665 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300666 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300667
668 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300669 if (kthread_should_stop())
670 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300671
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300672 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300673 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300674
Hans Verkuil730947b2010-04-10 04:13:53 -0300675 vivi_thread_tick(dev);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300676
677 schedule_timeout_interruptible(timeout);
678
679stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300680 remove_wait_queue(&dma_q->wq, &wait);
681 try_to_freeze();
682}
683
Adrian Bunk972c3512006-04-27 21:06:50 -0300684static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300685{
Hans Verkuil730947b2010-04-10 04:13:53 -0300686 struct vivi_dev *dev = data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300687
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300688 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300689
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700690 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300691
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300692 for (;;) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300693 vivi_sleep(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300694
695 if (kthread_should_stop())
696 break;
697 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300698 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300699 return 0;
700}
701
Pawel Osciake007a322011-01-19 13:02:29 -0200702static int vivi_start_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300703{
Brandon Philips78718e52008-04-02 18:10:59 -0300704 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300705
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300706 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300707
Hans Verkuil730947b2010-04-10 04:13:53 -0300708 /* Resets frame counters */
709 dev->ms = 0;
710 dev->mv_count = 0;
711 dev->jiffies = jiffies;
712
713 dma_q->frame = 0;
714 dma_q->ini_jiffies = jiffies;
715 dma_q->kthread = kthread_run(vivi_thread, dev, dev->v4l2_dev.name);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300716
Akinobu Mita054afee2006-12-20 10:04:00 -0300717 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300718 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Pawel Osciake007a322011-01-19 13:02:29 -0200719 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300720 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300721 /* Wakes thread */
722 wake_up_interruptible(&dma_q->wq);
723
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300724 dprintk(dev, 1, "returning from %s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200725 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300726}
727
Pawel Osciake007a322011-01-19 13:02:29 -0200728static void vivi_stop_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300729{
Hans Verkuil730947b2010-04-10 04:13:53 -0300730 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300731
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300732 dprintk(dev, 1, "%s\n", __func__);
Hans Verkuil730947b2010-04-10 04:13:53 -0300733
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300734 /* shutdown control thread */
735 if (dma_q->kthread) {
736 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300737 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300738 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300739
Pawel Osciake007a322011-01-19 13:02:29 -0200740 /*
741 * Typical driver might need to wait here until dma engine stops.
742 * In this case we can abort imiedetly, so it's just a noop.
743 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300744
Pawel Osciake007a322011-01-19 13:02:29 -0200745 /* Release all active buffers */
746 while (!list_empty(&dma_q->active)) {
747 struct vivi_buffer *buf;
748 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
749 list_del(&buf->list);
750 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
751 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
752 }
753}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300754/* ------------------------------------------------------------------
755 Videobuf operations
756 ------------------------------------------------------------------*/
Guennadi Liakhovetskifc714e72011-08-24 10:30:21 -0300757static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
758 unsigned int *nbuffers, unsigned int *nplanes,
759 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300760{
Pawel Osciake007a322011-01-19 13:02:29 -0200761 struct vivi_dev *dev = vb2_get_drv_priv(vq);
762 unsigned long size;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300763
Hans Verkuil2e90c6c2012-06-22 05:53:31 -0300764 if (fmt)
765 size = fmt->fmt.pix.sizeimage;
766 else
767 size = dev->width * dev->height * dev->pixelsize;
768
769 if (size == 0)
770 return -EINVAL;
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 Verkuil72c2af62012-09-14 06:23:12 -0300893 snprintf(cap->bus_info, sizeof(cap->bus_info),
894 "platform:%s", dev->v4l2_dev.name);
Hans Verkuil23268ae2012-01-24 05:24:36 -0300895 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
896 V4L2_CAP_READWRITE;
897 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300898 return 0;
899}
900
Hans Verkuil78b526a2008-05-28 12:16:41 -0300901static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300902 struct v4l2_fmtdesc *f)
903{
Magnus Dammd891f472008-10-14 12:47:09 -0300904 struct vivi_fmt *fmt;
905
906 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300907 return -EINVAL;
908
Magnus Dammd891f472008-10-14 12:47:09 -0300909 fmt = &formats[f->index];
910
911 strlcpy(f->description, fmt->name, sizeof(f->description));
912 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300913 return 0;
914}
915
Hans Verkuil78b526a2008-05-28 12:16:41 -0300916static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300917 struct v4l2_format *f)
918{
Hans Verkuil730947b2010-04-10 04:13:53 -0300919 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300920
Hans Verkuil730947b2010-04-10 04:13:53 -0300921 f->fmt.pix.width = dev->width;
922 f->fmt.pix.height = dev->height;
Hans Verkuilcd779252012-07-25 11:48:53 -0300923 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
Hans Verkuil730947b2010-04-10 04:13:53 -0300924 f->fmt.pix.pixelformat = dev->fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300925 f->fmt.pix.bytesperline =
Hans Verkuil730947b2010-04-10 04:13:53 -0300926 (f->fmt.pix.width * dev->fmt->depth) >> 3;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300927 f->fmt.pix.sizeimage =
928 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil0a3a8a32012-08-06 10:36:18 -0300929 if (dev->fmt->is_yuv)
Hans Verkuil8c79eec2011-07-29 07:19:46 -0300930 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;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300941
Magnus Dammd891f472008-10-14 12:47:09 -0300942 fmt = get_format(f);
943 if (!fmt) {
Hans Verkuilcd779252012-07-25 11:48:53 -0300944 dprintk(dev, 1, "Fourcc format (0x%08x) unknown.\n",
Magnus Dammd891f472008-10-14 12:47:09 -0300945 f->fmt.pix.pixelformat);
Hans Verkuilcd779252012-07-25 11:48:53 -0300946 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
947 fmt = get_format(f);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300948 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300949
Hans Verkuilcd779252012-07-25 11:48:53 -0300950 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
Hans Verkuil730947b2010-04-10 04:13:53 -0300951 v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
952 &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300953 f->fmt.pix.bytesperline =
954 (f->fmt.pix.width * fmt->depth) >> 3;
955 f->fmt.pix.sizeimage =
956 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil0a3a8a32012-08-06 10:36:18 -0300957 if (fmt->is_yuv)
Hans Verkuil8c79eec2011-07-29 07:19:46 -0300958 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
959 else
960 f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
Hans Verkuil2f65f462012-08-06 10:43:13 -0300961 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300962 return 0;
963}
964
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300965static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
966 struct v4l2_format *f)
967{
Hans Verkuil730947b2010-04-10 04:13:53 -0300968 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200969 struct vb2_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300970
Hans Verkuil730947b2010-04-10 04:13:53 -0300971 int ret = vidioc_try_fmt_vid_cap(file, priv, f);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300972 if (ret < 0)
973 return ret;
974
Hans Verkuilf2ba5a02012-06-22 05:53:02 -0300975 if (vb2_is_busy(q)) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300976 dprintk(dev, 1, "%s device busy\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200977 return -EBUSY;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300978 }
979
Hans Verkuil730947b2010-04-10 04:13:53 -0300980 dev->fmt = get_format(f);
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300981 dev->pixelsize = dev->fmt->depth / 8;
Hans Verkuil730947b2010-04-10 04:13:53 -0300982 dev->width = f->fmt.pix.width;
983 dev->height = f->fmt.pix.height;
Pawel Osciake007a322011-01-19 13:02:29 -0200984
985 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300986}
987
Hans Verkuil77747f72012-08-06 10:37:18 -0300988static int vidioc_enum_framesizes(struct file *file, void *fh,
989 struct v4l2_frmsizeenum *fsize)
990{
991 static const struct v4l2_frmsize_stepwise sizes = {
992 48, MAX_WIDTH, 4,
993 32, MAX_HEIGHT, 1
994 };
995 int i;
996
997 if (fsize->index)
998 return -EINVAL;
999 for (i = 0; i < ARRAY_SIZE(formats); i++)
1000 if (formats[i].fourcc == fsize->pixel_format)
1001 break;
1002 if (i == ARRAY_SIZE(formats))
1003 return -EINVAL;
1004 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
1005 fsize->stepwise = sizes;
1006 return 0;
1007}
1008
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001009/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001010static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001011 struct v4l2_input *inp)
1012{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001013 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001014 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001015
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001016 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001017 sprintf(inp->name, "Camera %u", inp->index);
Hans Verkuil730947b2010-04-10 04:13:53 -03001018 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001019}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001020
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001021static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001022{
Hans Verkuil730947b2010-04-10 04:13:53 -03001023 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001024
1025 *i = dev->input;
Hans Verkuil730947b2010-04-10 04:13:53 -03001026 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001027}
Hans Verkuil730947b2010-04-10 04:13:53 -03001028
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001029static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001030{
Hans Verkuil730947b2010-04-10 04:13:53 -03001031 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001032
1033 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001034 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001035
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001036 if (i == dev->input)
1037 return 0;
1038
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001039 dev->input = i;
Hans Verkuil730947b2010-04-10 04:13:53 -03001040 precalculate_bars(dev);
1041 precalculate_line(dev);
1042 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001043}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001044
Hans Verkuil730947b2010-04-10 04:13:53 -03001045/* --- controls ---------------------------------------------- */
Hans Verkuil7e996af2011-01-23 12:33:16 -02001046
Hans Verkuila1c894f2011-06-07 06:34:41 -03001047static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1048{
1049 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
1050
1051 if (ctrl == dev->autogain)
1052 dev->gain->val = jiffies & 0xff;
1053 return 0;
1054}
1055
Hans Verkuil7e996af2011-01-23 12:33:16 -02001056static int vivi_s_ctrl(struct v4l2_ctrl *ctrl)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001057{
Hans Verkuil7e996af2011-01-23 12:33:16 -02001058 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001059
Hans Verkuil7088f4d2012-05-02 03:33:52 -03001060 switch (ctrl->id) {
1061 case V4L2_CID_ALPHA_COMPONENT:
1062 dev->alpha_component = ctrl->val;
1063 break;
1064 default:
1065 if (ctrl == dev->button)
1066 dev->button_pressed = 30;
1067 break;
1068 }
Hans Verkuil7e996af2011-01-23 12:33:16 -02001069 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001070}
1071
1072/* ------------------------------------------------------------------
1073 File operations for the device
1074 ------------------------------------------------------------------*/
1075
Hans Verkuil7e996af2011-01-23 12:33:16 -02001076static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
Hans Verkuila1c894f2011-06-07 06:34:41 -03001077 .g_volatile_ctrl = vivi_g_volatile_ctrl,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001078 .s_ctrl = vivi_s_ctrl,
1079};
1080
1081#define VIVI_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
1082
1083static const struct v4l2_ctrl_config vivi_ctrl_button = {
1084 .ops = &vivi_ctrl_ops,
1085 .id = VIVI_CID_CUSTOM_BASE + 0,
1086 .name = "Button",
1087 .type = V4L2_CTRL_TYPE_BUTTON,
1088};
1089
1090static const struct v4l2_ctrl_config vivi_ctrl_boolean = {
1091 .ops = &vivi_ctrl_ops,
1092 .id = VIVI_CID_CUSTOM_BASE + 1,
1093 .name = "Boolean",
1094 .type = V4L2_CTRL_TYPE_BOOLEAN,
1095 .min = 0,
1096 .max = 1,
1097 .step = 1,
1098 .def = 1,
1099};
1100
1101static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
1102 .ops = &vivi_ctrl_ops,
1103 .id = VIVI_CID_CUSTOM_BASE + 2,
1104 .name = "Integer 32 Bits",
1105 .type = V4L2_CTRL_TYPE_INTEGER,
Hans Verkuil5b283022011-01-11 17:32:28 -03001106 .min = 0x80000000,
1107 .max = 0x7fffffff,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001108 .step = 1,
1109};
1110
1111static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
1112 .ops = &vivi_ctrl_ops,
1113 .id = VIVI_CID_CUSTOM_BASE + 3,
1114 .name = "Integer 64 Bits",
1115 .type = V4L2_CTRL_TYPE_INTEGER64,
1116};
1117
1118static const char * const vivi_ctrl_menu_strings[] = {
1119 "Menu Item 0 (Skipped)",
1120 "Menu Item 1",
1121 "Menu Item 2 (Skipped)",
1122 "Menu Item 3",
1123 "Menu Item 4",
1124 "Menu Item 5 (Skipped)",
1125 NULL,
1126};
1127
1128static const struct v4l2_ctrl_config vivi_ctrl_menu = {
1129 .ops = &vivi_ctrl_ops,
1130 .id = VIVI_CID_CUSTOM_BASE + 4,
1131 .name = "Menu",
1132 .type = V4L2_CTRL_TYPE_MENU,
1133 .min = 1,
1134 .max = 4,
1135 .def = 3,
1136 .menu_skip_mask = 0x04,
1137 .qmenu = vivi_ctrl_menu_strings,
1138};
1139
1140static const struct v4l2_ctrl_config vivi_ctrl_string = {
1141 .ops = &vivi_ctrl_ops,
1142 .id = VIVI_CID_CUSTOM_BASE + 5,
1143 .name = "String",
1144 .type = V4L2_CTRL_TYPE_STRING,
1145 .min = 2,
1146 .max = 4,
1147 .step = 1,
1148};
1149
Hans Verkuilb6d17a52011-03-29 16:33:11 -03001150static const struct v4l2_ctrl_config vivi_ctrl_bitmask = {
1151 .ops = &vivi_ctrl_ops,
1152 .id = VIVI_CID_CUSTOM_BASE + 6,
1153 .name = "Bitmask",
1154 .type = V4L2_CTRL_TYPE_BITMASK,
1155 .def = 0x80002000,
1156 .min = 0,
1157 .max = 0x80402010,
1158 .step = 0,
1159};
1160
Sakari Ailusc5203312011-08-05 06:38:05 -03001161static const s64 vivi_ctrl_int_menu_values[] = {
1162 1, 1, 2, 3, 5, 8, 13, 21, 42,
1163};
1164
1165static const struct v4l2_ctrl_config vivi_ctrl_int_menu = {
1166 .ops = &vivi_ctrl_ops,
1167 .id = VIVI_CID_CUSTOM_BASE + 7,
1168 .name = "Integer menu",
1169 .type = V4L2_CTRL_TYPE_INTEGER_MENU,
1170 .min = 1,
1171 .max = 8,
1172 .def = 4,
1173 .menu_skip_mask = 0x02,
1174 .qmenu_int = vivi_ctrl_int_menu_values,
1175};
1176
Hans Verkuilbec43662008-12-30 06:58:20 -03001177static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001178 .owner = THIS_MODULE,
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001179 .open = v4l2_fh_open,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001180 .release = vb2_fop_release,
1181 .read = vb2_fop_read,
1182 .poll = vb2_fop_poll,
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001183 .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001184 .mmap = vb2_fop_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001185};
1186
Hans Verkuila3998102008-07-21 02:57:38 -03001187static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001188 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001189 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1190 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1191 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1192 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Hans Verkuil77747f72012-08-06 10:37:18 -03001193 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001194 .vidioc_reqbufs = vb2_ioctl_reqbufs,
Hans Verkuil2e90c6c2012-06-22 05:53:31 -03001195 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1196 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001197 .vidioc_querybuf = vb2_ioctl_querybuf,
1198 .vidioc_qbuf = vb2_ioctl_qbuf,
1199 .vidioc_dqbuf = vb2_ioctl_dqbuf,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001200 .vidioc_enum_input = vidioc_enum_input,
1201 .vidioc_g_input = vidioc_g_input,
1202 .vidioc_s_input = vidioc_s_input,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001203 .vidioc_streamon = vb2_ioctl_streamon,
1204 .vidioc_streamoff = vb2_ioctl_streamoff,
Hans Verkuile2ecb252012-02-02 08:20:53 -03001205 .vidioc_log_status = v4l2_ctrl_log_status,
Hans Verkuil6d6604f2012-01-27 16:21:10 -03001206 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001207 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Hans Verkuila3998102008-07-21 02:57:38 -03001208};
1209
1210static struct video_device vivi_template = {
1211 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001212 .fops = &vivi_fops,
1213 .ioctl_ops = &vivi_ioctl_ops,
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001214 .release = video_device_release_empty,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001215};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001216
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001217/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001218 Initialization and module stuff
1219 ------------------------------------------------------------------*/
1220
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001221static int vivi_release(void)
1222{
1223 struct vivi_dev *dev;
1224 struct list_head *list;
1225
1226 while (!list_empty(&vivi_devlist)) {
1227 list = vivi_devlist.next;
1228 list_del(list);
1229 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1230
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001231 v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001232 video_device_node_name(&dev->vdev));
1233 video_unregister_device(&dev->vdev);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001234 v4l2_device_unregister(&dev->v4l2_dev);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001235 v4l2_ctrl_handler_free(&dev->ctrl_handler);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001236 kfree(dev);
1237 }
1238
1239 return 0;
1240}
1241
Hans Verkuilc41ee242009-02-14 13:43:44 -03001242static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001243{
1244 struct vivi_dev *dev;
1245 struct video_device *vfd;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001246 struct v4l2_ctrl_handler *hdl;
Pawel Osciake007a322011-01-19 13:02:29 -02001247 struct vb2_queue *q;
Hans Verkuil730947b2010-04-10 04:13:53 -03001248 int ret;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001249
1250 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1251 if (!dev)
1252 return -ENOMEM;
1253
1254 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001255 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001256 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1257 if (ret)
1258 goto free_dev;
1259
Hans Verkuil730947b2010-04-10 04:13:53 -03001260 dev->fmt = &formats[0];
1261 dev->width = 640;
1262 dev->height = 480;
Hans Verkuil3d51dca2012-05-02 03:15:11 -03001263 dev->pixelsize = dev->fmt->depth / 8;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001264 hdl = &dev->ctrl_handler;
1265 v4l2_ctrl_handler_init(hdl, 11);
1266 dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1267 V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
1268 dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1269 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1270 dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1271 V4L2_CID_CONTRAST, 0, 255, 1, 16);
1272 dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1273 V4L2_CID_SATURATION, 0, 255, 1, 127);
1274 dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1275 V4L2_CID_HUE, -128, 127, 1, 0);
Hans Verkuila1c894f2011-06-07 06:34:41 -03001276 dev->autogain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1277 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1278 dev->gain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1279 V4L2_CID_GAIN, 0, 255, 1, 100);
Hans Verkuil7088f4d2012-05-02 03:33:52 -03001280 dev->alpha = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1281 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001282 dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
1283 dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
1284 dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);
1285 dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL);
1286 dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL);
1287 dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL);
Hans Verkuilb6d17a52011-03-29 16:33:11 -03001288 dev->bitmask = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_bitmask, NULL);
Sakari Ailusc5203312011-08-05 06:38:05 -03001289 dev->int_menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int_menu, NULL);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001290 if (hdl->error) {
1291 ret = hdl->error;
1292 goto unreg_dev;
1293 }
Hans Verkuila1c894f2011-06-07 06:34:41 -03001294 v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001295 dev->v4l2_dev.ctrl_handler = hdl;
Hans Verkuil730947b2010-04-10 04:13:53 -03001296
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001297 /* initialize locks */
1298 spin_lock_init(&dev->slock);
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001299
Pawel Osciake007a322011-01-19 13:02:29 -02001300 /* initialize queue */
1301 q = &dev->vb_vidq;
Pawel Osciake007a322011-01-19 13:02:29 -02001302 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Tomasz Stanislawskia626f0a2012-06-14 10:37:47 -03001303 q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
Pawel Osciake007a322011-01-19 13:02:29 -02001304 q->drv_priv = dev;
1305 q->buf_struct_size = sizeof(struct vivi_buffer);
1306 q->ops = &vivi_video_qops;
1307 q->mem_ops = &vb2_vmalloc_memops;
1308
Ezequiel Garcia4195ec72012-09-17 09:49:38 -03001309 ret = vb2_queue_init(q);
1310 if (ret)
1311 goto unreg_dev;
Pawel Osciake007a322011-01-19 13:02:29 -02001312
1313 mutex_init(&dev->mutex);
Hans Verkuil730947b2010-04-10 04:13:53 -03001314
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001315 /* init video dma queues */
1316 INIT_LIST_HEAD(&dev->vidq.active);
1317 init_waitqueue_head(&dev->vidq.wq);
1318
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001319 vfd = &dev->vdev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001320 *vfd = vivi_template;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -03001321 vfd->debug = debug;
Hans Verkuil730947b2010-04-10 04:13:53 -03001322 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001323 vfd->queue = q;
Hans Verkuilb1a873a2011-03-22 10:14:07 -03001324 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Pawel Osciake007a322011-01-19 13:02:29 -02001325
1326 /*
1327 * Provide a mutex to v4l2 core. It will be used to protect
1328 * all fops and v4l2 ioctls.
1329 */
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001330 vfd->lock = &dev->mutex;
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001331 video_set_drvdata(vfd, dev);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001332
1333 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1334 if (ret < 0)
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001335 goto unreg_dev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001336
1337 /* Now that everything is fine, let's add it to device list */
1338 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1339
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001340 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
1341 video_device_node_name(vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001342 return 0;
1343
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001344unreg_dev:
Hans Verkuil7e996af2011-01-23 12:33:16 -02001345 v4l2_ctrl_handler_free(hdl);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001346 v4l2_device_unregister(&dev->v4l2_dev);
1347free_dev:
1348 kfree(dev);
1349 return ret;
1350}
1351
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001352/* This routine allocates from 1 to n_devs virtual drivers.
1353
1354 The real maximum number of virtual drivers will depend on how many drivers
1355 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001356 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001357 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001358static int __init vivi_init(void)
1359{
Hans Verkuil730947b2010-04-10 04:13:53 -03001360 const struct font_desc *font = find_font("VGA8x16");
Hans Verkuil9185cbf2009-03-06 09:58:12 -03001361 int ret = 0, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001362
Hans Verkuil730947b2010-04-10 04:13:53 -03001363 if (font == NULL) {
1364 printk(KERN_ERR "vivi: could not find font\n");
1365 return -ENODEV;
1366 }
1367 font8x16 = font->data;
1368
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001369 if (n_devs <= 0)
1370 n_devs = 1;
1371
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001372 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001373 ret = vivi_create_instance(i);
1374 if (ret) {
1375 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001376 if (i)
1377 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001378 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001379 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001380 }
1381
1382 if (ret < 0) {
Hans Verkuil730947b2010-04-10 04:13:53 -03001383 printk(KERN_ERR "vivi: error %d while loading driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001384 return ret;
1385 }
1386
1387 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001388 "Capture Board ver %s successfully loaded.\n",
1389 VIVI_VERSION);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001390
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001391 /* n_devs will reflect the actual number of allocated devices */
1392 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001393
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001394 return ret;
1395}
1396
1397static void __exit vivi_exit(void)
1398{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001399 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001400}
1401
1402module_init(vivi_init);
1403module_exit(vivi_exit);