blob: 0d59b9db83cb90b4d2ec1f38482111cdadbb77f5 [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;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300557 struct timeval ts;
Pawel Osciake007a322011-01-19 13:02:29 -0200558 void *vbuf = vb2_plane_vaddr(&buf->vb, 0);
Hans Verkuil730947b2010-04-10 04:13:53 -0300559 unsigned ms;
560 char str[100];
561 int h, line = 1;
Hans Verkuila1c894f2011-06-07 06:34:41 -0300562 s32 gain;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300563
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300564 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300565 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300566
Hans Verkuil730947b2010-04-10 04:13:53 -0300567 for (h = 0; h < hmax; h++)
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300568 memcpy(vbuf + h * wmax * dev->pixelsize,
569 dev->line + (dev->mv_count % wmax) * dev->pixelsize,
570 wmax * dev->pixelsize);
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300571
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300572 /* Updates stream time */
573
Hans Verkuil730947b2010-04-10 04:13:53 -0300574 dev->ms += jiffies_to_msecs(jiffies - dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300575 dev->jiffies = jiffies;
Hans Verkuil730947b2010-04-10 04:13:53 -0300576 ms = dev->ms;
577 snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d ",
578 (ms / (60 * 60 * 1000)) % 24,
579 (ms / (60 * 1000)) % 60,
580 (ms / 1000) % 60,
581 ms % 1000);
582 gen_text(dev, vbuf, line++ * 16, 16, str);
583 snprintf(str, sizeof(str), " %dx%d, input %d ",
584 dev->width, dev->height, dev->input);
585 gen_text(dev, vbuf, line++ * 16, 16, str);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300586
Hans Verkuila1c894f2011-06-07 06:34:41 -0300587 gain = v4l2_ctrl_g_ctrl(dev->gain);
Sakari Ailus77e7c4e2012-01-24 21:05:34 -0300588 mutex_lock(dev->ctrl_handler.lock);
Hans Verkuil730947b2010-04-10 04:13:53 -0300589 snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
Hans Verkuil7e996af2011-01-23 12:33:16 -0200590 dev->brightness->cur.val,
591 dev->contrast->cur.val,
592 dev->saturation->cur.val,
593 dev->hue->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300594 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300595 snprintf(str, sizeof(str), " autogain %d, gain %3d, volume %3d, alpha 0x%02x ",
596 dev->autogain->cur.val, gain, dev->volume->cur.val,
597 dev->alpha->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300598 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300599 snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
Hans Verkuil7e996af2011-01-23 12:33:16 -0200600 dev->int32->cur.val,
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300601 dev->int64->cur.val64,
602 dev->bitmask->cur.val);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200603 gen_text(dev, vbuf, line++ * 16, 16, str);
604 snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
605 dev->boolean->cur.val,
606 dev->menu->qmenu[dev->menu->cur.val],
607 dev->string->cur.string);
Hans Verkuilf70cfc72012-04-19 11:44:18 -0300608 gen_text(dev, vbuf, line++ * 16, 16, str);
Sakari Ailusc5203312011-08-05 06:38:05 -0300609 snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
610 dev->int_menu->qmenu_int[dev->int_menu->cur.val],
611 dev->int_menu->cur.val);
612 gen_text(dev, vbuf, line++ * 16, 16, str);
Sakari Ailus77e7c4e2012-01-24 21:05:34 -0300613 mutex_unlock(dev->ctrl_handler.lock);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200614 if (dev->button_pressed) {
615 dev->button_pressed--;
616 snprintf(str, sizeof(str), " button pressed!");
617 gen_text(dev, vbuf, line++ * 16, 16, str);
618 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300619
620 dev->mv_count += 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300621
Hans Verkuilcd779252012-07-25 11:48:53 -0300622 buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
Pawel Osciake007a322011-01-19 13:02:29 -0200623 dev->field_count++;
624 buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300625 do_gettimeofday(&ts);
Pawel Osciake007a322011-01-19 13:02:29 -0200626 buf->vb.v4l2_buf.timestamp = ts;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300627}
628
Hans Verkuil730947b2010-04-10 04:13:53 -0300629static void vivi_thread_tick(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300630{
Brandon Philips78718e52008-04-02 18:10:59 -0300631 struct vivi_dmaqueue *dma_q = &dev->vidq;
Hans Verkuil730947b2010-04-10 04:13:53 -0300632 struct vivi_buffer *buf;
Brandon Philips78718e52008-04-02 18:10:59 -0300633 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300634
Brandon Philips78718e52008-04-02 18:10:59 -0300635 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300636
Brandon Philips78718e52008-04-02 18:10:59 -0300637 spin_lock_irqsave(&dev->slock, flags);
638 if (list_empty(&dma_q->active)) {
639 dprintk(dev, 1, "No active queue to serve\n");
Hans Verkuil1de5be52011-07-05 07:19:23 -0300640 spin_unlock_irqrestore(&dev->slock, flags);
641 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300642 }
Brandon Philips78718e52008-04-02 18:10:59 -0300643
Pawel Osciake007a322011-01-19 13:02:29 -0200644 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
645 list_del(&buf->list);
Hans Verkuil1de5be52011-07-05 07:19:23 -0300646 spin_unlock_irqrestore(&dev->slock, flags);
Brandon Philips78718e52008-04-02 18:10:59 -0300647
Pawel Osciake007a322011-01-19 13:02:29 -0200648 do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
Brandon Philips78718e52008-04-02 18:10:59 -0300649
650 /* Fill buffer */
Hans Verkuil730947b2010-04-10 04:13:53 -0300651 vivi_fillbuff(dev, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300652 dprintk(dev, 1, "filled buffer %p\n", buf);
653
Pawel Osciake007a322011-01-19 13:02:29 -0200654 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
655 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300656}
657
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300658#define frames_to_ms(frames) \
659 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
660
Hans Verkuil730947b2010-04-10 04:13:53 -0300661static void vivi_sleep(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300662{
Brandon Philips78718e52008-04-02 18:10:59 -0300663 struct vivi_dmaqueue *dma_q = &dev->vidq;
664 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300665 DECLARE_WAITQUEUE(wait, current);
666
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300667 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300668 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300669
670 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300671 if (kthread_should_stop())
672 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300673
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300674 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300675 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300676
Hans Verkuil730947b2010-04-10 04:13:53 -0300677 vivi_thread_tick(dev);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300678
679 schedule_timeout_interruptible(timeout);
680
681stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300682 remove_wait_queue(&dma_q->wq, &wait);
683 try_to_freeze();
684}
685
Adrian Bunk972c3512006-04-27 21:06:50 -0300686static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300687{
Hans Verkuil730947b2010-04-10 04:13:53 -0300688 struct vivi_dev *dev = data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300689
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300690 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300691
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700692 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300693
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300694 for (;;) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300695 vivi_sleep(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300696
697 if (kthread_should_stop())
698 break;
699 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300700 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300701 return 0;
702}
703
Pawel Osciake007a322011-01-19 13:02:29 -0200704static int vivi_start_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300705{
Brandon Philips78718e52008-04-02 18:10:59 -0300706 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300707
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300708 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300709
Hans Verkuil730947b2010-04-10 04:13:53 -0300710 /* Resets frame counters */
711 dev->ms = 0;
712 dev->mv_count = 0;
713 dev->jiffies = jiffies;
714
715 dma_q->frame = 0;
716 dma_q->ini_jiffies = jiffies;
717 dma_q->kthread = kthread_run(vivi_thread, dev, dev->v4l2_dev.name);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300718
Akinobu Mita054afee2006-12-20 10:04:00 -0300719 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300720 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Pawel Osciake007a322011-01-19 13:02:29 -0200721 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300722 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300723 /* Wakes thread */
724 wake_up_interruptible(&dma_q->wq);
725
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300726 dprintk(dev, 1, "returning from %s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200727 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300728}
729
Pawel Osciake007a322011-01-19 13:02:29 -0200730static void vivi_stop_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300731{
Hans Verkuil730947b2010-04-10 04:13:53 -0300732 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300733
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300734 dprintk(dev, 1, "%s\n", __func__);
Hans Verkuil730947b2010-04-10 04:13:53 -0300735
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300736 /* shutdown control thread */
737 if (dma_q->kthread) {
738 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300739 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300740 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300741
Pawel Osciake007a322011-01-19 13:02:29 -0200742 /*
743 * Typical driver might need to wait here until dma engine stops.
744 * In this case we can abort imiedetly, so it's just a noop.
745 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300746
Pawel Osciake007a322011-01-19 13:02:29 -0200747 /* Release all active buffers */
748 while (!list_empty(&dma_q->active)) {
749 struct vivi_buffer *buf;
750 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
751 list_del(&buf->list);
752 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
753 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
754 }
755}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300756/* ------------------------------------------------------------------
757 Videobuf operations
758 ------------------------------------------------------------------*/
Guennadi Liakhovetskifc714e702011-08-24 10:30:21 -0300759static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
760 unsigned int *nbuffers, unsigned int *nplanes,
761 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300762{
Pawel Osciake007a322011-01-19 13:02:29 -0200763 struct vivi_dev *dev = vb2_get_drv_priv(vq);
764 unsigned long size;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300765
Hans Verkuil2e90c6c2012-06-22 05:53:31 -0300766 if (fmt)
767 size = fmt->fmt.pix.sizeimage;
768 else
769 size = dev->width * dev->height * dev->pixelsize;
770
771 if (size == 0)
772 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300773
Pawel Osciake007a322011-01-19 13:02:29 -0200774 if (0 == *nbuffers)
775 *nbuffers = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300776
Pawel Osciake007a322011-01-19 13:02:29 -0200777 while (size * *nbuffers > vid_limit * 1024 * 1024)
778 (*nbuffers)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300779
Pawel Osciake007a322011-01-19 13:02:29 -0200780 *nplanes = 1;
781
782 sizes[0] = size;
783
784 /*
785 * videobuf2-vmalloc allocator is context-less so no need to set
786 * alloc_ctxs array.
787 */
788
789 dprintk(dev, 1, "%s, count=%d, size=%ld\n", __func__,
790 *nbuffers, size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300791
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300792 return 0;
793}
794
Pawel Osciake007a322011-01-19 13:02:29 -0200795static int buffer_prepare(struct vb2_buffer *vb)
796{
797 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
798 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
799 unsigned long size;
800
801 dprintk(dev, 1, "%s, field=%d\n", __func__, vb->v4l2_buf.field);
802
803 BUG_ON(NULL == dev->fmt);
804
805 /*
806 * Theses properties only change when queue is idle, see s_fmt.
807 * The below checks should not be performed here, on each
808 * buffer_prepare (i.e. on each qbuf). Most of the code in this function
809 * should thus be moved to buffer_init and s_fmt.
810 */
Hans Verkuil730947b2010-04-10 04:13:53 -0300811 if (dev->width < 48 || dev->width > MAX_WIDTH ||
812 dev->height < 32 || dev->height > MAX_HEIGHT)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300813 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300814
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300815 size = dev->width * dev->height * dev->pixelsize;
Pawel Osciake007a322011-01-19 13:02:29 -0200816 if (vb2_plane_size(vb, 0) < size) {
817 dprintk(dev, 1, "%s data will not fit into plane (%lu < %lu)\n",
818 __func__, vb2_plane_size(vb, 0), size);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300819 return -EINVAL;
Pawel Osciake007a322011-01-19 13:02:29 -0200820 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300821
Pawel Osciake007a322011-01-19 13:02:29 -0200822 vb2_set_plane_payload(&buf->vb, 0, size);
823
824 buf->fmt = dev->fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300825
Hans Verkuil730947b2010-04-10 04:13:53 -0300826 precalculate_bars(dev);
827 precalculate_line(dev);
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300828
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300829 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300830}
831
Pawel Osciake007a322011-01-19 13:02:29 -0200832static void buffer_queue(struct vb2_buffer *vb)
833{
834 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
Hans Verkuil730947b2010-04-10 04:13:53 -0300835 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300836 struct vivi_dmaqueue *vidq = &dev->vidq;
Pawel Osciake007a322011-01-19 13:02:29 -0200837 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300838
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300839 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300840
Pawel Osciake007a322011-01-19 13:02:29 -0200841 spin_lock_irqsave(&dev->slock, flags);
842 list_add_tail(&buf->list, &vidq->active);
843 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300844}
845
Marek Szyprowskibd323e22011-08-29 08:51:49 -0300846static int start_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300847{
Pawel Osciake007a322011-01-19 13:02:29 -0200848 struct vivi_dev *dev = vb2_get_drv_priv(vq);
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300849 dprintk(dev, 1, "%s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200850 return vivi_start_generating(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300851}
852
Pawel Osciake007a322011-01-19 13:02:29 -0200853/* abort streaming and wait for last buffer */
854static int stop_streaming(struct vb2_queue *vq)
855{
856 struct vivi_dev *dev = vb2_get_drv_priv(vq);
857 dprintk(dev, 1, "%s\n", __func__);
858 vivi_stop_generating(dev);
859 return 0;
860}
861
862static void vivi_lock(struct vb2_queue *vq)
863{
864 struct vivi_dev *dev = vb2_get_drv_priv(vq);
865 mutex_lock(&dev->mutex);
866}
867
868static void vivi_unlock(struct vb2_queue *vq)
869{
870 struct vivi_dev *dev = vb2_get_drv_priv(vq);
871 mutex_unlock(&dev->mutex);
872}
873
874
875static struct vb2_ops vivi_video_qops = {
876 .queue_setup = queue_setup,
Pawel Osciake007a322011-01-19 13:02:29 -0200877 .buf_prepare = buffer_prepare,
Pawel Osciake007a322011-01-19 13:02:29 -0200878 .buf_queue = buffer_queue,
879 .start_streaming = start_streaming,
880 .stop_streaming = stop_streaming,
881 .wait_prepare = vivi_unlock,
882 .wait_finish = vivi_lock,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300883};
884
885/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300886 IOCTL vidioc handling
887 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300888static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300889 struct v4l2_capability *cap)
890{
Hans Verkuil730947b2010-04-10 04:13:53 -0300891 struct vivi_dev *dev = video_drvdata(file);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300892
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300893 strcpy(cap->driver, "vivi");
894 strcpy(cap->card, "vivi");
Hans Verkuil72c2af62012-09-14 06:23:12 -0300895 snprintf(cap->bus_info, sizeof(cap->bus_info),
896 "platform:%s", dev->v4l2_dev.name);
Hans Verkuil23268ae2012-01-24 05:24:36 -0300897 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
898 V4L2_CAP_READWRITE;
899 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300900 return 0;
901}
902
Hans Verkuil78b526a2008-05-28 12:16:41 -0300903static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300904 struct v4l2_fmtdesc *f)
905{
Magnus Dammd891f472008-10-14 12:47:09 -0300906 struct vivi_fmt *fmt;
907
908 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300909 return -EINVAL;
910
Magnus Dammd891f472008-10-14 12:47:09 -0300911 fmt = &formats[f->index];
912
913 strlcpy(f->description, fmt->name, sizeof(f->description));
914 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300915 return 0;
916}
917
Hans Verkuil78b526a2008-05-28 12:16:41 -0300918static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300919 struct v4l2_format *f)
920{
Hans Verkuil730947b2010-04-10 04:13:53 -0300921 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300922
Hans Verkuil730947b2010-04-10 04:13:53 -0300923 f->fmt.pix.width = dev->width;
924 f->fmt.pix.height = dev->height;
Hans Verkuilcd779252012-07-25 11:48:53 -0300925 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
Hans Verkuil730947b2010-04-10 04:13:53 -0300926 f->fmt.pix.pixelformat = dev->fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300927 f->fmt.pix.bytesperline =
Hans Verkuil730947b2010-04-10 04:13:53 -0300928 (f->fmt.pix.width * dev->fmt->depth) >> 3;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300929 f->fmt.pix.sizeimage =
930 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil0a3a8a32012-08-06 10:36:18 -0300931 if (dev->fmt->is_yuv)
Hans Verkuil8c79eec2011-07-29 07:19:46 -0300932 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
933 else
934 f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
Hans Verkuil730947b2010-04-10 04:13:53 -0300935 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300936}
937
Hans Verkuil78b526a2008-05-28 12:16:41 -0300938static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300939 struct v4l2_format *f)
940{
Hans Verkuil730947b2010-04-10 04:13:53 -0300941 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300942 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300943
Magnus Dammd891f472008-10-14 12:47:09 -0300944 fmt = get_format(f);
945 if (!fmt) {
Hans Verkuilcd779252012-07-25 11:48:53 -0300946 dprintk(dev, 1, "Fourcc format (0x%08x) unknown.\n",
Magnus Dammd891f472008-10-14 12:47:09 -0300947 f->fmt.pix.pixelformat);
Hans Verkuilcd779252012-07-25 11:48:53 -0300948 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
949 fmt = get_format(f);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300950 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300951
Hans Verkuilcd779252012-07-25 11:48:53 -0300952 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
Hans Verkuil730947b2010-04-10 04:13:53 -0300953 v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
954 &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300955 f->fmt.pix.bytesperline =
956 (f->fmt.pix.width * fmt->depth) >> 3;
957 f->fmt.pix.sizeimage =
958 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil0a3a8a32012-08-06 10:36:18 -0300959 if (fmt->is_yuv)
Hans Verkuil8c79eec2011-07-29 07:19:46 -0300960 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
961 else
962 f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
Hans Verkuil2f65f462012-08-06 10:43:13 -0300963 f->fmt.pix.priv = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300964 return 0;
965}
966
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300967static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
968 struct v4l2_format *f)
969{
Hans Verkuil730947b2010-04-10 04:13:53 -0300970 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -0200971 struct vb2_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300972
Hans Verkuil730947b2010-04-10 04:13:53 -0300973 int ret = vidioc_try_fmt_vid_cap(file, priv, f);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300974 if (ret < 0)
975 return ret;
976
Hans Verkuilf2ba5a02012-06-22 05:53:02 -0300977 if (vb2_is_busy(q)) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300978 dprintk(dev, 1, "%s device busy\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200979 return -EBUSY;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300980 }
981
Hans Verkuil730947b2010-04-10 04:13:53 -0300982 dev->fmt = get_format(f);
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300983 dev->pixelsize = dev->fmt->depth / 8;
Hans Verkuil730947b2010-04-10 04:13:53 -0300984 dev->width = f->fmt.pix.width;
985 dev->height = f->fmt.pix.height;
Pawel Osciake007a322011-01-19 13:02:29 -0200986
987 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300988}
989
Hans Verkuil77747f72012-08-06 10:37:18 -0300990static int vidioc_enum_framesizes(struct file *file, void *fh,
991 struct v4l2_frmsizeenum *fsize)
992{
993 static const struct v4l2_frmsize_stepwise sizes = {
994 48, MAX_WIDTH, 4,
995 32, MAX_HEIGHT, 1
996 };
997 int i;
998
999 if (fsize->index)
1000 return -EINVAL;
1001 for (i = 0; i < ARRAY_SIZE(formats); i++)
1002 if (formats[i].fourcc == fsize->pixel_format)
1003 break;
1004 if (i == ARRAY_SIZE(formats))
1005 return -EINVAL;
1006 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
1007 fsize->stepwise = sizes;
1008 return 0;
1009}
1010
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001011/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001012static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001013 struct v4l2_input *inp)
1014{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001015 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001016 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001017
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001018 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001019 sprintf(inp->name, "Camera %u", inp->index);
Hans Verkuil730947b2010-04-10 04:13:53 -03001020 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001021}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001022
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001023static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001024{
Hans Verkuil730947b2010-04-10 04:13:53 -03001025 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001026
1027 *i = dev->input;
Hans Verkuil730947b2010-04-10 04:13:53 -03001028 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001029}
Hans Verkuil730947b2010-04-10 04:13:53 -03001030
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001031static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001032{
Hans Verkuil730947b2010-04-10 04:13:53 -03001033 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001034
1035 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001036 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001037
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001038 if (i == dev->input)
1039 return 0;
1040
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001041 dev->input = i;
Hans Verkuil730947b2010-04-10 04:13:53 -03001042 precalculate_bars(dev);
1043 precalculate_line(dev);
1044 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001045}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001046
Hans Verkuil730947b2010-04-10 04:13:53 -03001047/* --- controls ---------------------------------------------- */
Hans Verkuil7e996af2011-01-23 12:33:16 -02001048
Hans Verkuila1c894f2011-06-07 06:34:41 -03001049static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1050{
1051 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
1052
1053 if (ctrl == dev->autogain)
1054 dev->gain->val = jiffies & 0xff;
1055 return 0;
1056}
1057
Hans Verkuil7e996af2011-01-23 12:33:16 -02001058static int vivi_s_ctrl(struct v4l2_ctrl *ctrl)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001059{
Hans Verkuil7e996af2011-01-23 12:33:16 -02001060 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001061
Hans Verkuil7088f4d2012-05-02 03:33:52 -03001062 switch (ctrl->id) {
1063 case V4L2_CID_ALPHA_COMPONENT:
1064 dev->alpha_component = ctrl->val;
1065 break;
1066 default:
1067 if (ctrl == dev->button)
1068 dev->button_pressed = 30;
1069 break;
1070 }
Hans Verkuil7e996af2011-01-23 12:33:16 -02001071 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001072}
1073
1074/* ------------------------------------------------------------------
1075 File operations for the device
1076 ------------------------------------------------------------------*/
1077
Hans Verkuil7e996af2011-01-23 12:33:16 -02001078static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
Hans Verkuila1c894f2011-06-07 06:34:41 -03001079 .g_volatile_ctrl = vivi_g_volatile_ctrl,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001080 .s_ctrl = vivi_s_ctrl,
1081};
1082
1083#define VIVI_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
1084
1085static const struct v4l2_ctrl_config vivi_ctrl_button = {
1086 .ops = &vivi_ctrl_ops,
1087 .id = VIVI_CID_CUSTOM_BASE + 0,
1088 .name = "Button",
1089 .type = V4L2_CTRL_TYPE_BUTTON,
1090};
1091
1092static const struct v4l2_ctrl_config vivi_ctrl_boolean = {
1093 .ops = &vivi_ctrl_ops,
1094 .id = VIVI_CID_CUSTOM_BASE + 1,
1095 .name = "Boolean",
1096 .type = V4L2_CTRL_TYPE_BOOLEAN,
1097 .min = 0,
1098 .max = 1,
1099 .step = 1,
1100 .def = 1,
1101};
1102
1103static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
1104 .ops = &vivi_ctrl_ops,
1105 .id = VIVI_CID_CUSTOM_BASE + 2,
1106 .name = "Integer 32 Bits",
1107 .type = V4L2_CTRL_TYPE_INTEGER,
Hans Verkuil5b283022011-01-11 17:32:28 -03001108 .min = 0x80000000,
1109 .max = 0x7fffffff,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001110 .step = 1,
1111};
1112
1113static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
1114 .ops = &vivi_ctrl_ops,
1115 .id = VIVI_CID_CUSTOM_BASE + 3,
1116 .name = "Integer 64 Bits",
1117 .type = V4L2_CTRL_TYPE_INTEGER64,
1118};
1119
1120static const char * const vivi_ctrl_menu_strings[] = {
1121 "Menu Item 0 (Skipped)",
1122 "Menu Item 1",
1123 "Menu Item 2 (Skipped)",
1124 "Menu Item 3",
1125 "Menu Item 4",
1126 "Menu Item 5 (Skipped)",
1127 NULL,
1128};
1129
1130static const struct v4l2_ctrl_config vivi_ctrl_menu = {
1131 .ops = &vivi_ctrl_ops,
1132 .id = VIVI_CID_CUSTOM_BASE + 4,
1133 .name = "Menu",
1134 .type = V4L2_CTRL_TYPE_MENU,
1135 .min = 1,
1136 .max = 4,
1137 .def = 3,
1138 .menu_skip_mask = 0x04,
1139 .qmenu = vivi_ctrl_menu_strings,
1140};
1141
1142static const struct v4l2_ctrl_config vivi_ctrl_string = {
1143 .ops = &vivi_ctrl_ops,
1144 .id = VIVI_CID_CUSTOM_BASE + 5,
1145 .name = "String",
1146 .type = V4L2_CTRL_TYPE_STRING,
1147 .min = 2,
1148 .max = 4,
1149 .step = 1,
1150};
1151
Hans Verkuilb6d17a52011-03-29 16:33:11 -03001152static const struct v4l2_ctrl_config vivi_ctrl_bitmask = {
1153 .ops = &vivi_ctrl_ops,
1154 .id = VIVI_CID_CUSTOM_BASE + 6,
1155 .name = "Bitmask",
1156 .type = V4L2_CTRL_TYPE_BITMASK,
1157 .def = 0x80002000,
1158 .min = 0,
1159 .max = 0x80402010,
1160 .step = 0,
1161};
1162
Sakari Ailusc5203312011-08-05 06:38:05 -03001163static const s64 vivi_ctrl_int_menu_values[] = {
1164 1, 1, 2, 3, 5, 8, 13, 21, 42,
1165};
1166
1167static const struct v4l2_ctrl_config vivi_ctrl_int_menu = {
1168 .ops = &vivi_ctrl_ops,
1169 .id = VIVI_CID_CUSTOM_BASE + 7,
1170 .name = "Integer menu",
1171 .type = V4L2_CTRL_TYPE_INTEGER_MENU,
1172 .min = 1,
1173 .max = 8,
1174 .def = 4,
1175 .menu_skip_mask = 0x02,
1176 .qmenu_int = vivi_ctrl_int_menu_values,
1177};
1178
Hans Verkuilbec43662008-12-30 06:58:20 -03001179static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001180 .owner = THIS_MODULE,
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001181 .open = v4l2_fh_open,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001182 .release = vb2_fop_release,
1183 .read = vb2_fop_read,
1184 .poll = vb2_fop_poll,
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001185 .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001186 .mmap = vb2_fop_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001187};
1188
Hans Verkuila3998102008-07-21 02:57:38 -03001189static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001190 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001191 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1192 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1193 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1194 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Hans Verkuil77747f72012-08-06 10:37:18 -03001195 .vidioc_enum_framesizes = vidioc_enum_framesizes,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001196 .vidioc_reqbufs = vb2_ioctl_reqbufs,
Hans Verkuil2e90c6c2012-06-22 05:53:31 -03001197 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1198 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001199 .vidioc_querybuf = vb2_ioctl_querybuf,
1200 .vidioc_qbuf = vb2_ioctl_qbuf,
1201 .vidioc_dqbuf = vb2_ioctl_dqbuf,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001202 .vidioc_enum_input = vidioc_enum_input,
1203 .vidioc_g_input = vidioc_g_input,
1204 .vidioc_s_input = vidioc_s_input,
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001205 .vidioc_streamon = vb2_ioctl_streamon,
1206 .vidioc_streamoff = vb2_ioctl_streamoff,
Hans Verkuile2ecb252012-02-02 08:20:53 -03001207 .vidioc_log_status = v4l2_ctrl_log_status,
Hans Verkuil6d6604f2012-01-27 16:21:10 -03001208 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001209 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Hans Verkuila3998102008-07-21 02:57:38 -03001210};
1211
1212static struct video_device vivi_template = {
1213 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001214 .fops = &vivi_fops,
1215 .ioctl_ops = &vivi_ioctl_ops,
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001216 .release = video_device_release_empty,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001217};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001218
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001219/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001220 Initialization and module stuff
1221 ------------------------------------------------------------------*/
1222
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001223static int vivi_release(void)
1224{
1225 struct vivi_dev *dev;
1226 struct list_head *list;
1227
1228 while (!list_empty(&vivi_devlist)) {
1229 list = vivi_devlist.next;
1230 list_del(list);
1231 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1232
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001233 v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001234 video_device_node_name(&dev->vdev));
1235 video_unregister_device(&dev->vdev);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001236 v4l2_device_unregister(&dev->v4l2_dev);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001237 v4l2_ctrl_handler_free(&dev->ctrl_handler);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001238 kfree(dev);
1239 }
1240
1241 return 0;
1242}
1243
Hans Verkuilc41ee242009-02-14 13:43:44 -03001244static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001245{
1246 struct vivi_dev *dev;
1247 struct video_device *vfd;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001248 struct v4l2_ctrl_handler *hdl;
Pawel Osciake007a322011-01-19 13:02:29 -02001249 struct vb2_queue *q;
Hans Verkuil730947b2010-04-10 04:13:53 -03001250 int ret;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001251
1252 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1253 if (!dev)
1254 return -ENOMEM;
1255
1256 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001257 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001258 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1259 if (ret)
1260 goto free_dev;
1261
Hans Verkuil730947b2010-04-10 04:13:53 -03001262 dev->fmt = &formats[0];
1263 dev->width = 640;
1264 dev->height = 480;
Hans Verkuil3d51dca2012-05-02 03:15:11 -03001265 dev->pixelsize = dev->fmt->depth / 8;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001266 hdl = &dev->ctrl_handler;
1267 v4l2_ctrl_handler_init(hdl, 11);
1268 dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1269 V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
1270 dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1271 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1272 dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1273 V4L2_CID_CONTRAST, 0, 255, 1, 16);
1274 dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1275 V4L2_CID_SATURATION, 0, 255, 1, 127);
1276 dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1277 V4L2_CID_HUE, -128, 127, 1, 0);
Hans Verkuila1c894f2011-06-07 06:34:41 -03001278 dev->autogain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1279 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1280 dev->gain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1281 V4L2_CID_GAIN, 0, 255, 1, 100);
Hans Verkuil7088f4d2012-05-02 03:33:52 -03001282 dev->alpha = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1283 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001284 dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
1285 dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
1286 dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);
1287 dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL);
1288 dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL);
1289 dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL);
Hans Verkuilb6d17a52011-03-29 16:33:11 -03001290 dev->bitmask = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_bitmask, NULL);
Sakari Ailusc5203312011-08-05 06:38:05 -03001291 dev->int_menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int_menu, NULL);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001292 if (hdl->error) {
1293 ret = hdl->error;
1294 goto unreg_dev;
1295 }
Hans Verkuila1c894f2011-06-07 06:34:41 -03001296 v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001297 dev->v4l2_dev.ctrl_handler = hdl;
Hans Verkuil730947b2010-04-10 04:13:53 -03001298
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001299 /* initialize locks */
1300 spin_lock_init(&dev->slock);
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001301
Pawel Osciake007a322011-01-19 13:02:29 -02001302 /* initialize queue */
1303 q = &dev->vb_vidq;
Pawel Osciake007a322011-01-19 13:02:29 -02001304 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Tomasz Stanislawskia626f0a2012-06-14 10:37:47 -03001305 q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
Pawel Osciake007a322011-01-19 13:02:29 -02001306 q->drv_priv = dev;
1307 q->buf_struct_size = sizeof(struct vivi_buffer);
1308 q->ops = &vivi_video_qops;
1309 q->mem_ops = &vb2_vmalloc_memops;
1310
Ezequiel Garcia4195ec72012-09-17 09:49:38 -03001311 ret = vb2_queue_init(q);
1312 if (ret)
1313 goto unreg_dev;
Pawel Osciake007a322011-01-19 13:02:29 -02001314
1315 mutex_init(&dev->mutex);
Hans Verkuil730947b2010-04-10 04:13:53 -03001316
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001317 /* init video dma queues */
1318 INIT_LIST_HEAD(&dev->vidq.active);
1319 init_waitqueue_head(&dev->vidq.wq);
1320
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001321 vfd = &dev->vdev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001322 *vfd = vivi_template;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -03001323 vfd->debug = debug;
Hans Verkuil730947b2010-04-10 04:13:53 -03001324 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuilf2ba5a02012-06-22 05:53:02 -03001325 vfd->queue = q;
Hans Verkuilb1a873a2011-03-22 10:14:07 -03001326 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Pawel Osciake007a322011-01-19 13:02:29 -02001327
1328 /*
1329 * Provide a mutex to v4l2 core. It will be used to protect
1330 * all fops and v4l2 ioctls.
1331 */
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001332 vfd->lock = &dev->mutex;
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001333 video_set_drvdata(vfd, dev);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001334
1335 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1336 if (ret < 0)
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001337 goto unreg_dev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001338
1339 /* Now that everything is fine, let's add it to device list */
1340 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1341
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001342 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
1343 video_device_node_name(vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001344 return 0;
1345
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001346unreg_dev:
Hans Verkuil7e996af2011-01-23 12:33:16 -02001347 v4l2_ctrl_handler_free(hdl);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001348 v4l2_device_unregister(&dev->v4l2_dev);
1349free_dev:
1350 kfree(dev);
1351 return ret;
1352}
1353
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001354/* This routine allocates from 1 to n_devs virtual drivers.
1355
1356 The real maximum number of virtual drivers will depend on how many drivers
1357 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001358 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001359 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001360static int __init vivi_init(void)
1361{
Hans Verkuil730947b2010-04-10 04:13:53 -03001362 const struct font_desc *font = find_font("VGA8x16");
Hans Verkuil9185cbf2009-03-06 09:58:12 -03001363 int ret = 0, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001364
Hans Verkuil730947b2010-04-10 04:13:53 -03001365 if (font == NULL) {
1366 printk(KERN_ERR "vivi: could not find font\n");
1367 return -ENODEV;
1368 }
1369 font8x16 = font->data;
1370
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001371 if (n_devs <= 0)
1372 n_devs = 1;
1373
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001374 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001375 ret = vivi_create_instance(i);
1376 if (ret) {
1377 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001378 if (i)
1379 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001380 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001381 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001382 }
1383
1384 if (ret < 0) {
Hans Verkuil730947b2010-04-10 04:13:53 -03001385 printk(KERN_ERR "vivi: error %d while loading driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001386 return ret;
1387 }
1388
1389 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001390 "Capture Board ver %s successfully loaded.\n",
1391 VIVI_VERSION);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001392
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001393 /* n_devs will reflect the actual number of allocated devices */
1394 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001395
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001396 return ret;
1397}
1398
1399static void __exit vivi_exit(void)
1400{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001401 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001402}
1403
1404module_init(vivi_init);
1405module_exit(vivi_exit);