blob: 1e4da5e43a32c3cf573ebc7b85c470de7d0f282a [file] [log] [blame]
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001/*
2 * Virtual Video driver - This code emulates a real video device with v4l2 api
3 *
4 * Copyright (c) 2006 by:
5 * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
6 * Ted Walther <ted--a.t--enumera.com>
7 * John Sokol <sokol--a.t--videotechnology.com>
8 * http://v4l.videotechnology.com/
9 *
Pawel Osciake007a322011-01-19 13:02:29 -020010 * Conversion to videobuf2 by Pawel Osciak & Marek Szyprowski
11 * Copyright (c) 2010 Samsung Electronics
12 *
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030013 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the BSD Licence, GNU General Public License
15 * as published by the Free Software Foundation; either version 2 of the
16 * License, or (at your option) any later version
17 */
18#include <linux/module.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030019#include <linux/errno.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030020#include <linux/kernel.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030021#include <linux/init.h>
22#include <linux/sched.h>
Randy Dunlap6b46c392010-05-07 15:22:26 -030023#include <linux/slab.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030024#include <linux/font.h>
Matthias Kaehlcke51b54022007-07-02 10:19:38 -030025#include <linux/mutex.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030026#include <linux/videodev2.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030027#include <linux/kthread.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080028#include <linux/freezer.h>
Pawel Osciake007a322011-01-19 13:02:29 -020029#include <media/videobuf2-vmalloc.h>
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030030#include <media/v4l2-device.h>
31#include <media/v4l2-ioctl.h>
Hans Verkuil7e996af2011-01-23 12:33:16 -020032#include <media/v4l2-ctrls.h>
Hans Verkuil2e4784d2011-03-11 20:01:54 -030033#include <media/v4l2-fh.h>
Hans Verkuilc7a52f82011-06-07 10:20:23 -030034#include <media/v4l2-event.h>
Hans Verkuil730947b2010-04-10 04:13:53 -030035#include <media/v4l2-common.h>
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030036
Mauro Carvalho Chehab584ce482008-06-10 15:21:49 -030037#define VIVI_MODULE_NAME "vivi"
Carl Karsten745271a2008-06-10 00:02:32 -030038
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030039/* Wake up at about 30 fps */
40#define WAKE_NUMERATOR 30
41#define WAKE_DENOMINATOR 1001
42#define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */
43
Hans Verkuil730947b2010-04-10 04:13:53 -030044#define MAX_WIDTH 1920
45#define MAX_HEIGHT 1200
46
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030047#define VIVI_VERSION "0.8.1"
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030048
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030049MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
50MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
51MODULE_LICENSE("Dual BSD/GPL");
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -030052MODULE_VERSION(VIVI_VERSION);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030053
54static unsigned video_nr = -1;
55module_param(video_nr, uint, 0644);
56MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
57
58static unsigned n_devs = 1;
59module_param(n_devs, uint, 0644);
60MODULE_PARM_DESC(n_devs, "number of video devices to create");
61
62static unsigned debug;
63module_param(debug, uint, 0644);
64MODULE_PARM_DESC(debug, "activates debug info");
65
66static unsigned int vid_limit = 16;
67module_param(vid_limit, uint, 0644);
68MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
69
Hans Verkuil730947b2010-04-10 04:13:53 -030070/* Global font descriptor */
71static const u8 *font8x16;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030072
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -030073#define dprintk(dev, level, fmt, arg...) \
74 v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -030075
76/* ------------------------------------------------------------------
77 Basic structures
78 ------------------------------------------------------------------*/
79
80struct vivi_fmt {
81 char *name;
82 u32 fourcc; /* v4l2 format id */
83 int depth;
84};
85
Magnus Dammd891f472008-10-14 12:47:09 -030086static struct vivi_fmt formats[] = {
87 {
88 .name = "4:2:2, packed, YUYV",
89 .fourcc = V4L2_PIX_FMT_YUYV,
90 .depth = 16,
91 },
Magnus Dammfca36ba2008-10-14 12:47:25 -030092 {
93 .name = "4:2:2, packed, UYVY",
94 .fourcc = V4L2_PIX_FMT_UYVY,
95 .depth = 16,
96 },
Magnus Dammaeadb5d2008-10-14 12:47:35 -030097 {
Hans Verkuil3d51dca2012-05-02 03:15:11 -030098 .name = "4:2:2, packed, YVYU",
99 .fourcc = V4L2_PIX_FMT_YVYU,
100 .depth = 16,
101 },
102 {
103 .name = "4:2:2, packed, VYUY",
104 .fourcc = V4L2_PIX_FMT_VYUY,
105 .depth = 16,
106 },
107 {
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300108 .name = "RGB565 (LE)",
109 .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
110 .depth = 16,
111 },
112 {
113 .name = "RGB565 (BE)",
114 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
115 .depth = 16,
116 },
Magnus Dammdef52392008-10-14 12:47:43 -0300117 {
118 .name = "RGB555 (LE)",
119 .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
120 .depth = 16,
121 },
122 {
123 .name = "RGB555 (BE)",
124 .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
125 .depth = 16,
126 },
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300127 {
128 .name = "RGB24 (LE)",
129 .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */
130 .depth = 24,
131 },
132 {
133 .name = "RGB24 (BE)",
134 .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */
135 .depth = 24,
136 },
137 {
138 .name = "RGB32 (LE)",
139 .fourcc = V4L2_PIX_FMT_RGB32, /* argb */
140 .depth = 32,
141 },
142 {
143 .name = "RGB32 (BE)",
144 .fourcc = V4L2_PIX_FMT_BGR32, /* bgra */
145 .depth = 32,
146 },
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300147};
148
Magnus Dammd891f472008-10-14 12:47:09 -0300149static struct vivi_fmt *get_format(struct v4l2_format *f)
150{
151 struct vivi_fmt *fmt;
152 unsigned int k;
153
154 for (k = 0; k < ARRAY_SIZE(formats); k++) {
155 fmt = &formats[k];
156 if (fmt->fourcc == f->fmt.pix.pixelformat)
157 break;
158 }
159
160 if (k == ARRAY_SIZE(formats))
161 return NULL;
162
163 return &formats[k];
164}
165
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300166/* buffer for one video frame */
167struct vivi_buffer {
168 /* common v4l buffer stuff -- must be first */
Pawel Osciake007a322011-01-19 13:02:29 -0200169 struct vb2_buffer vb;
170 struct list_head list;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300171 struct vivi_fmt *fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300172};
173
174struct vivi_dmaqueue {
175 struct list_head active;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300176
177 /* thread for generating video stream*/
178 struct task_struct *kthread;
179 wait_queue_head_t wq;
180 /* Counters to control fps rate */
181 int frame;
182 int ini_jiffies;
183};
184
185static LIST_HEAD(vivi_devlist);
186
187struct vivi_dev {
188 struct list_head vivi_devlist;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300189 struct v4l2_device v4l2_dev;
Hans Verkuil7e996af2011-01-23 12:33:16 -0200190 struct v4l2_ctrl_handler ctrl_handler;
Hans Verkuil70bd97a2012-06-09 11:27:43 -0300191 struct video_device vdev;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300192
Hans Verkuil730947b2010-04-10 04:13:53 -0300193 /* controls */
Hans Verkuil7e996af2011-01-23 12:33:16 -0200194 struct v4l2_ctrl *brightness;
195 struct v4l2_ctrl *contrast;
196 struct v4l2_ctrl *saturation;
197 struct v4l2_ctrl *hue;
Hans Verkuila1c894f2011-06-07 06:34:41 -0300198 struct {
199 /* autogain/gain cluster */
200 struct v4l2_ctrl *autogain;
201 struct v4l2_ctrl *gain;
202 };
Hans Verkuil7e996af2011-01-23 12:33:16 -0200203 struct v4l2_ctrl *volume;
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300204 struct v4l2_ctrl *alpha;
Hans Verkuil7e996af2011-01-23 12:33:16 -0200205 struct v4l2_ctrl *button;
206 struct v4l2_ctrl *boolean;
207 struct v4l2_ctrl *int32;
208 struct v4l2_ctrl *int64;
209 struct v4l2_ctrl *menu;
210 struct v4l2_ctrl *string;
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300211 struct v4l2_ctrl *bitmask;
Sakari Ailusc5203312011-08-05 06:38:05 -0300212 struct v4l2_ctrl *int_menu;
Hans Verkuil730947b2010-04-10 04:13:53 -0300213
Mauro Carvalho Chehab55862ac2007-12-13 16:13:37 -0300214 spinlock_t slock;
Brandon Philipsaa9dbac2008-04-02 18:10:59 -0300215 struct mutex mutex;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300216
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300217 struct vivi_dmaqueue vidq;
218
219 /* Several counters */
Hans Verkuil730947b2010-04-10 04:13:53 -0300220 unsigned ms;
Mauro Carvalho Chehabdfd8c042008-01-13 19:36:11 -0300221 unsigned long jiffies;
Hans Verkuil7e996af2011-01-23 12:33:16 -0200222 unsigned button_pressed;
Mauro Carvalho Chehab025341d2007-12-10 04:43:38 -0300223
224 int mv_count; /* Controls bars movement */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300225
226 /* Input Number */
227 int input;
Hans Verkuilc41ee242009-02-14 13:43:44 -0300228
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300229 /* video capture */
230 struct vivi_fmt *fmt;
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300231 unsigned int width, height;
Pawel Osciake007a322011-01-19 13:02:29 -0200232 struct vb2_queue vb_vidq;
233 enum v4l2_field field;
234 unsigned int field_count;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300235
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300236 u8 bars[9][3];
237 u8 line[MAX_WIDTH * 8];
238 unsigned int pixelsize;
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300239 u8 alpha_component;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300240};
241
242/* ------------------------------------------------------------------
243 DMA and thread functions
244 ------------------------------------------------------------------*/
245
246/* Bars and Colors should match positions */
247
248enum colors {
249 WHITE,
Hans Verkuil730947b2010-04-10 04:13:53 -0300250 AMBER,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300251 CYAN,
252 GREEN,
253 MAGENTA,
254 RED,
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300255 BLUE,
256 BLACK,
Hans Verkuil730947b2010-04-10 04:13:53 -0300257 TEXT_BLACK,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300258};
259
Hans Verkuil730947b2010-04-10 04:13:53 -0300260/* R G B */
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300261#define COLOR_WHITE {204, 204, 204}
Hans Verkuil730947b2010-04-10 04:13:53 -0300262#define COLOR_AMBER {208, 208, 0}
263#define COLOR_CYAN { 0, 206, 206}
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300264#define COLOR_GREEN { 0, 239, 0}
265#define COLOR_MAGENTA {239, 0, 239}
266#define COLOR_RED {205, 0, 0}
267#define COLOR_BLUE { 0, 0, 255}
268#define COLOR_BLACK { 0, 0, 0}
269
270struct bar_std {
Hans Verkuil730947b2010-04-10 04:13:53 -0300271 u8 bar[9][3];
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300272};
273
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300274/* Maximum number of bars are 10 - otherwise, the input print code
275 should be modified */
276static struct bar_std bars[] = {
277 { /* Standard ITU-R color bar sequence */
Hans Verkuil730947b2010-04-10 04:13:53 -0300278 { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN,
279 COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300280 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300281 { COLOR_WHITE, COLOR_AMBER, COLOR_BLACK, COLOR_WHITE,
282 COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, COLOR_AMBER, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300283 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300284 { COLOR_WHITE, COLOR_CYAN, COLOR_BLACK, COLOR_WHITE,
285 COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, COLOR_CYAN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300286 }, {
Hans Verkuil730947b2010-04-10 04:13:53 -0300287 { COLOR_WHITE, COLOR_GREEN, COLOR_BLACK, COLOR_WHITE,
288 COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, COLOR_GREEN, COLOR_BLACK }
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300289 },
290};
291
292#define NUM_INPUTS ARRAY_SIZE(bars)
293
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300294#define TO_Y(r, g, b) \
295 (((16829 * r + 33039 * g + 6416 * b + 32768) >> 16) + 16)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300296/* RGB to V(Cr) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300297#define TO_V(r, g, b) \
298 (((28784 * r - 24103 * g - 4681 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300299/* RGB to U(Cb) Color transform */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300300#define TO_U(r, g, b) \
301 (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300302
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300303/* precalculate color bar values to speed up rendering */
Hans Verkuil730947b2010-04-10 04:13:53 -0300304static void precalculate_bars(struct vivi_dev *dev)
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300305{
Hans Verkuil730947b2010-04-10 04:13:53 -0300306 u8 r, g, b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300307 int k, is_yuv;
308
Hans Verkuil730947b2010-04-10 04:13:53 -0300309 for (k = 0; k < 9; k++) {
310 r = bars[dev->input].bar[k][0];
311 g = bars[dev->input].bar[k][1];
312 b = bars[dev->input].bar[k][2];
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300313 is_yuv = 0;
314
Hans Verkuil730947b2010-04-10 04:13:53 -0300315 switch (dev->fmt->fourcc) {
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300316 case V4L2_PIX_FMT_YUYV:
317 case V4L2_PIX_FMT_UYVY:
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300318 case V4L2_PIX_FMT_YVYU:
319 case V4L2_PIX_FMT_VYUY:
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300320 is_yuv = 1;
321 break;
322 case V4L2_PIX_FMT_RGB565:
323 case V4L2_PIX_FMT_RGB565X:
324 r >>= 3;
325 g >>= 2;
326 b >>= 3;
327 break;
328 case V4L2_PIX_FMT_RGB555:
329 case V4L2_PIX_FMT_RGB555X:
330 r >>= 3;
331 g >>= 3;
332 b >>= 3;
333 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300334 case V4L2_PIX_FMT_RGB24:
335 case V4L2_PIX_FMT_BGR24:
336 case V4L2_PIX_FMT_RGB32:
337 case V4L2_PIX_FMT_BGR32:
338 break;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300339 }
340
341 if (is_yuv) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300342 dev->bars[k][0] = TO_Y(r, g, b); /* Luma */
343 dev->bars[k][1] = TO_U(r, g, b); /* Cb */
344 dev->bars[k][2] = TO_V(r, g, b); /* Cr */
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300345 } else {
Hans Verkuil730947b2010-04-10 04:13:53 -0300346 dev->bars[k][0] = r;
347 dev->bars[k][1] = g;
348 dev->bars[k][2] = b;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300349 }
350 }
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300351}
352
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300353#define TSTAMP_MIN_Y 24
354#define TSTAMP_MAX_Y (TSTAMP_MIN_Y + 15)
355#define TSTAMP_INPUT_X 10
356#define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300357
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300358/* 'odd' is true for pixels 1, 3, 5, etc. and false for pixels 0, 2, 4, etc. */
359static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos, bool odd)
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300360{
Hans Verkuil730947b2010-04-10 04:13:53 -0300361 u8 r_y, g_u, b_v;
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300362 u8 alpha = dev->alpha_component;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300363 int color;
Hans Verkuil730947b2010-04-10 04:13:53 -0300364 u8 *p;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300365
Hans Verkuil730947b2010-04-10 04:13:53 -0300366 r_y = dev->bars[colorpos][0]; /* R or precalculated Y */
367 g_u = dev->bars[colorpos][1]; /* G or precalculated U */
368 b_v = dev->bars[colorpos][2]; /* B or precalculated V */
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300369
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300370 for (color = 0; color < dev->pixelsize; color++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300371 p = buf + color;
372
Hans Verkuil730947b2010-04-10 04:13:53 -0300373 switch (dev->fmt->fourcc) {
Magnus Dammd891f472008-10-14 12:47:09 -0300374 case V4L2_PIX_FMT_YUYV:
375 switch (color) {
376 case 0:
Magnus Dammd891f472008-10-14 12:47:09 -0300377 *p = r_y;
378 break;
379 case 1:
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300380 *p = odd ? b_v : g_u;
Magnus Dammd891f472008-10-14 12:47:09 -0300381 break;
382 }
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300383 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300384 case V4L2_PIX_FMT_UYVY:
385 switch (color) {
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300386 case 0:
387 *p = odd ? b_v : g_u;
388 break;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300389 case 1:
Magnus Dammfca36ba2008-10-14 12:47:25 -0300390 *p = r_y;
391 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300392 }
393 break;
394 case V4L2_PIX_FMT_YVYU:
395 switch (color) {
Magnus Dammfca36ba2008-10-14 12:47:25 -0300396 case 0:
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300397 *p = r_y;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300398 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300399 case 1:
400 *p = odd ? g_u : b_v;
401 break;
402 }
403 break;
404 case V4L2_PIX_FMT_VYUY:
405 switch (color) {
406 case 0:
407 *p = odd ? g_u : b_v;
408 break;
409 case 1:
410 *p = r_y;
Magnus Dammfca36ba2008-10-14 12:47:25 -0300411 break;
412 }
413 break;
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300414 case V4L2_PIX_FMT_RGB565:
415 switch (color) {
416 case 0:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300417 *p = (g_u << 5) | b_v;
418 break;
419 case 1:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300420 *p = (r_y << 3) | (g_u >> 3);
421 break;
422 }
423 break;
424 case V4L2_PIX_FMT_RGB565X:
425 switch (color) {
426 case 0:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300427 *p = (r_y << 3) | (g_u >> 3);
428 break;
429 case 1:
Magnus Dammaeadb5d2008-10-14 12:47:35 -0300430 *p = (g_u << 5) | b_v;
431 break;
432 }
433 break;
Magnus Dammdef52392008-10-14 12:47:43 -0300434 case V4L2_PIX_FMT_RGB555:
435 switch (color) {
436 case 0:
Magnus Dammdef52392008-10-14 12:47:43 -0300437 *p = (g_u << 5) | b_v;
438 break;
439 case 1:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300440 *p = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
Magnus Dammdef52392008-10-14 12:47:43 -0300441 break;
442 }
443 break;
444 case V4L2_PIX_FMT_RGB555X:
445 switch (color) {
446 case 0:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300447 *p = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
Magnus Dammdef52392008-10-14 12:47:43 -0300448 break;
449 case 1:
Magnus Dammdef52392008-10-14 12:47:43 -0300450 *p = (g_u << 5) | b_v;
451 break;
452 }
453 break;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300454 case V4L2_PIX_FMT_RGB24:
455 switch (color) {
456 case 0:
457 *p = r_y;
458 break;
459 case 1:
460 *p = g_u;
461 break;
462 case 2:
463 *p = b_v;
464 break;
465 }
466 break;
467 case V4L2_PIX_FMT_BGR24:
468 switch (color) {
469 case 0:
470 *p = b_v;
471 break;
472 case 1:
473 *p = g_u;
474 break;
475 case 2:
476 *p = r_y;
477 break;
478 }
479 break;
480 case V4L2_PIX_FMT_RGB32:
481 switch (color) {
482 case 0:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300483 *p = alpha;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300484 break;
485 case 1:
486 *p = r_y;
487 break;
488 case 2:
489 *p = g_u;
490 break;
491 case 3:
492 *p = b_v;
493 break;
494 }
495 break;
496 case V4L2_PIX_FMT_BGR32:
497 switch (color) {
498 case 0:
499 *p = b_v;
500 break;
501 case 1:
502 *p = g_u;
503 break;
504 case 2:
505 *p = r_y;
506 break;
507 case 3:
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300508 *p = alpha;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300509 break;
510 }
511 break;
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300512 }
513 }
514}
515
Hans Verkuil730947b2010-04-10 04:13:53 -0300516static void precalculate_line(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300517{
Hans Verkuil730947b2010-04-10 04:13:53 -0300518 int w;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300519
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300520 for (w = 0; w < dev->width * 2; w++) {
521 int colorpos = w / (dev->width / 8) % 8;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300522
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300523 gen_twopix(dev, dev->line + w * dev->pixelsize, colorpos, w & 1);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300524 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300525}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300526
Hans Verkuil730947b2010-04-10 04:13:53 -0300527static void gen_text(struct vivi_dev *dev, char *basep,
528 int y, int x, char *text)
529{
530 int line;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -0300531
Hans Verkuil730947b2010-04-10 04:13:53 -0300532 /* Checks if it is possible to show string */
533 if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width)
534 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300535
536 /* Print stream time */
Hans Verkuil730947b2010-04-10 04:13:53 -0300537 for (line = y; line < y + 16; line++) {
538 int j = 0;
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300539 char *pos = basep + line * dev->width * dev->pixelsize + x * dev->pixelsize;
Hans Verkuil730947b2010-04-10 04:13:53 -0300540 char *s;
541
542 for (s = text; *s; s++) {
543 u8 chr = font8x16[*s * 16 + line - y];
544 int i;
545
546 for (i = 0; i < 7; i++, j++) {
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300547 /* Draw white font on black background */
Hans Verkuil730947b2010-04-10 04:13:53 -0300548 if (chr & (1 << (7 - i)))
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300549 gen_twopix(dev, pos + j * dev->pixelsize, WHITE, (x+y) & 1);
Magnus Damm74d7c5a2008-10-14 12:46:59 -0300550 else
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300551 gen_twopix(dev, pos + j * dev->pixelsize, TEXT_BLACK, (x+y) & 1);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300552 }
553 }
554 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300555}
Brandon Philips78718e52008-04-02 18:10:59 -0300556
Hans Verkuil730947b2010-04-10 04:13:53 -0300557static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300558{
Pawel Osciake007a322011-01-19 13:02:29 -0200559 int wmax = dev->width;
560 int hmax = dev->height;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300561 struct timeval ts;
Pawel Osciake007a322011-01-19 13:02:29 -0200562 void *vbuf = vb2_plane_vaddr(&buf->vb, 0);
Hans Verkuil730947b2010-04-10 04:13:53 -0300563 unsigned ms;
564 char str[100];
565 int h, line = 1;
Hans Verkuila1c894f2011-06-07 06:34:41 -0300566 s32 gain;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300567
Marcin Slusarz5c554e62008-06-22 09:11:40 -0300568 if (!vbuf)
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300569 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300570
Hans Verkuil730947b2010-04-10 04:13:53 -0300571 for (h = 0; h < hmax; h++)
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300572 memcpy(vbuf + h * wmax * dev->pixelsize,
573 dev->line + (dev->mv_count % wmax) * dev->pixelsize,
574 wmax * dev->pixelsize);
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -0300575
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300576 /* Updates stream time */
577
Hans Verkuil730947b2010-04-10 04:13:53 -0300578 dev->ms += jiffies_to_msecs(jiffies - dev->jiffies);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300579 dev->jiffies = jiffies;
Hans Verkuil730947b2010-04-10 04:13:53 -0300580 ms = dev->ms;
581 snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d ",
582 (ms / (60 * 60 * 1000)) % 24,
583 (ms / (60 * 1000)) % 60,
584 (ms / 1000) % 60,
585 ms % 1000);
586 gen_text(dev, vbuf, line++ * 16, 16, str);
587 snprintf(str, sizeof(str), " %dx%d, input %d ",
588 dev->width, dev->height, dev->input);
589 gen_text(dev, vbuf, line++ * 16, 16, str);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300590
Hans Verkuila1c894f2011-06-07 06:34:41 -0300591 gain = v4l2_ctrl_g_ctrl(dev->gain);
Sakari Ailus77e7c4e2012-01-24 21:05:34 -0300592 mutex_lock(dev->ctrl_handler.lock);
Hans Verkuil730947b2010-04-10 04:13:53 -0300593 snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
Hans Verkuil7e996af2011-01-23 12:33:16 -0200594 dev->brightness->cur.val,
595 dev->contrast->cur.val,
596 dev->saturation->cur.val,
597 dev->hue->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300598 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuil7088f4d2012-05-02 03:33:52 -0300599 snprintf(str, sizeof(str), " autogain %d, gain %3d, volume %3d, alpha 0x%02x ",
600 dev->autogain->cur.val, gain, dev->volume->cur.val,
601 dev->alpha->cur.val);
Hans Verkuil730947b2010-04-10 04:13:53 -0300602 gen_text(dev, vbuf, line++ * 16, 16, str);
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300603 snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
Hans Verkuil7e996af2011-01-23 12:33:16 -0200604 dev->int32->cur.val,
Hans Verkuilb6d17a52011-03-29 16:33:11 -0300605 dev->int64->cur.val64,
606 dev->bitmask->cur.val);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200607 gen_text(dev, vbuf, line++ * 16, 16, str);
608 snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
609 dev->boolean->cur.val,
610 dev->menu->qmenu[dev->menu->cur.val],
611 dev->string->cur.string);
Hans Verkuilf70cfc72012-04-19 11:44:18 -0300612 gen_text(dev, vbuf, line++ * 16, 16, str);
Sakari Ailusc5203312011-08-05 06:38:05 -0300613 snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
614 dev->int_menu->qmenu_int[dev->int_menu->cur.val],
615 dev->int_menu->cur.val);
616 gen_text(dev, vbuf, line++ * 16, 16, str);
Sakari Ailus77e7c4e2012-01-24 21:05:34 -0300617 mutex_unlock(dev->ctrl_handler.lock);
Hans Verkuil7e996af2011-01-23 12:33:16 -0200618 if (dev->button_pressed) {
619 dev->button_pressed--;
620 snprintf(str, sizeof(str), " button pressed!");
621 gen_text(dev, vbuf, line++ * 16, 16, str);
622 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300623
624 dev->mv_count += 2;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300625
Pawel Osciake007a322011-01-19 13:02:29 -0200626 buf->vb.v4l2_buf.field = dev->field;
627 dev->field_count++;
628 buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300629 do_gettimeofday(&ts);
Pawel Osciake007a322011-01-19 13:02:29 -0200630 buf->vb.v4l2_buf.timestamp = ts;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300631}
632
Hans Verkuil730947b2010-04-10 04:13:53 -0300633static void vivi_thread_tick(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300634{
Brandon Philips78718e52008-04-02 18:10:59 -0300635 struct vivi_dmaqueue *dma_q = &dev->vidq;
Hans Verkuil730947b2010-04-10 04:13:53 -0300636 struct vivi_buffer *buf;
Brandon Philips78718e52008-04-02 18:10:59 -0300637 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300638
Brandon Philips78718e52008-04-02 18:10:59 -0300639 dprintk(dev, 1, "Thread tick\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300640
Brandon Philips78718e52008-04-02 18:10:59 -0300641 spin_lock_irqsave(&dev->slock, flags);
642 if (list_empty(&dma_q->active)) {
643 dprintk(dev, 1, "No active queue to serve\n");
Hans Verkuil1de5be52011-07-05 07:19:23 -0300644 spin_unlock_irqrestore(&dev->slock, flags);
645 return;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300646 }
Brandon Philips78718e52008-04-02 18:10:59 -0300647
Pawel Osciake007a322011-01-19 13:02:29 -0200648 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
649 list_del(&buf->list);
Hans Verkuil1de5be52011-07-05 07:19:23 -0300650 spin_unlock_irqrestore(&dev->slock, flags);
Brandon Philips78718e52008-04-02 18:10:59 -0300651
Pawel Osciake007a322011-01-19 13:02:29 -0200652 do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
Brandon Philips78718e52008-04-02 18:10:59 -0300653
654 /* Fill buffer */
Hans Verkuil730947b2010-04-10 04:13:53 -0300655 vivi_fillbuff(dev, buf);
Brandon Philips78718e52008-04-02 18:10:59 -0300656 dprintk(dev, 1, "filled buffer %p\n", buf);
657
Pawel Osciake007a322011-01-19 13:02:29 -0200658 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
659 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300660}
661
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300662#define frames_to_ms(frames) \
663 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
664
Hans Verkuil730947b2010-04-10 04:13:53 -0300665static void vivi_sleep(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300666{
Brandon Philips78718e52008-04-02 18:10:59 -0300667 struct vivi_dmaqueue *dma_q = &dev->vidq;
668 int timeout;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300669 DECLARE_WAITQUEUE(wait, current);
670
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300671 dprintk(dev, 1, "%s dma_q=0x%08lx\n", __func__,
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300672 (unsigned long)dma_q);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300673
674 add_wait_queue(&dma_q->wq, &wait);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300675 if (kthread_should_stop())
676 goto stop_task;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300677
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300678 /* Calculate time to wake up */
Brandon Philips78718e52008-04-02 18:10:59 -0300679 timeout = msecs_to_jiffies(frames_to_ms(1));
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300680
Hans Verkuil730947b2010-04-10 04:13:53 -0300681 vivi_thread_tick(dev);
Mauro Carvalho Chehab6594ad82007-12-13 16:15:41 -0300682
683 schedule_timeout_interruptible(timeout);
684
685stop_task:
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300686 remove_wait_queue(&dma_q->wq, &wait);
687 try_to_freeze();
688}
689
Adrian Bunk972c3512006-04-27 21:06:50 -0300690static int vivi_thread(void *data)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300691{
Hans Verkuil730947b2010-04-10 04:13:53 -0300692 struct vivi_dev *dev = data;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300693
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300694 dprintk(dev, 1, "thread started\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300695
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700696 set_freezable();
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300697
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300698 for (;;) {
Hans Verkuil730947b2010-04-10 04:13:53 -0300699 vivi_sleep(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300700
701 if (kthread_should_stop())
702 break;
703 }
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300704 dprintk(dev, 1, "thread: exit\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300705 return 0;
706}
707
Pawel Osciake007a322011-01-19 13:02:29 -0200708static int vivi_start_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300709{
Brandon Philips78718e52008-04-02 18:10:59 -0300710 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300711
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300712 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300713
Hans Verkuil730947b2010-04-10 04:13:53 -0300714 /* Resets frame counters */
715 dev->ms = 0;
716 dev->mv_count = 0;
717 dev->jiffies = jiffies;
718
719 dma_q->frame = 0;
720 dma_q->ini_jiffies = jiffies;
721 dma_q->kthread = kthread_run(vivi_thread, dev, dev->v4l2_dev.name);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300722
Akinobu Mita054afee2006-12-20 10:04:00 -0300723 if (IS_ERR(dma_q->kthread)) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300724 v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
Pawel Osciake007a322011-01-19 13:02:29 -0200725 return PTR_ERR(dma_q->kthread);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300726 }
Mauro Carvalho Chehab0b600512007-01-14 08:33:24 -0300727 /* Wakes thread */
728 wake_up_interruptible(&dma_q->wq);
729
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300730 dprintk(dev, 1, "returning from %s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200731 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300732}
733
Pawel Osciake007a322011-01-19 13:02:29 -0200734static void vivi_stop_generating(struct vivi_dev *dev)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300735{
Hans Verkuil730947b2010-04-10 04:13:53 -0300736 struct vivi_dmaqueue *dma_q = &dev->vidq;
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300737
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300738 dprintk(dev, 1, "%s\n", __func__);
Hans Verkuil730947b2010-04-10 04:13:53 -0300739
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300740 /* shutdown control thread */
741 if (dma_q->kthread) {
742 kthread_stop(dma_q->kthread);
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300743 dma_q->kthread = NULL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300744 }
Hans Verkuil730947b2010-04-10 04:13:53 -0300745
Pawel Osciake007a322011-01-19 13:02:29 -0200746 /*
747 * Typical driver might need to wait here until dma engine stops.
748 * In this case we can abort imiedetly, so it's just a noop.
749 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300750
Pawel Osciake007a322011-01-19 13:02:29 -0200751 /* Release all active buffers */
752 while (!list_empty(&dma_q->active)) {
753 struct vivi_buffer *buf;
754 buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
755 list_del(&buf->list);
756 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
757 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
758 }
759}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300760/* ------------------------------------------------------------------
761 Videobuf operations
762 ------------------------------------------------------------------*/
Guennadi Liakhovetskifc714e72011-08-24 10:30:21 -0300763static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
764 unsigned int *nbuffers, unsigned int *nplanes,
765 unsigned int sizes[], void *alloc_ctxs[])
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300766{
Pawel Osciake007a322011-01-19 13:02:29 -0200767 struct vivi_dev *dev = vb2_get_drv_priv(vq);
768 unsigned long size;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300769
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300770 size = dev->width * dev->height * dev->pixelsize;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300771
Pawel Osciake007a322011-01-19 13:02:29 -0200772 if (0 == *nbuffers)
773 *nbuffers = 32;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300774
Pawel Osciake007a322011-01-19 13:02:29 -0200775 while (size * *nbuffers > vid_limit * 1024 * 1024)
776 (*nbuffers)--;
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300777
Pawel Osciake007a322011-01-19 13:02:29 -0200778 *nplanes = 1;
779
780 sizes[0] = size;
781
782 /*
783 * videobuf2-vmalloc allocator is context-less so no need to set
784 * alloc_ctxs array.
785 */
786
787 dprintk(dev, 1, "%s, count=%d, size=%ld\n", __func__,
788 *nbuffers, size);
Mauro Carvalho Chehab6bb27902007-08-23 16:41:14 -0300789
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300790 return 0;
791}
792
Pawel Osciake007a322011-01-19 13:02:29 -0200793static int buffer_init(struct vb2_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300794{
Pawel Osciake007a322011-01-19 13:02:29 -0200795 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300796
Hans Verkuil730947b2010-04-10 04:13:53 -0300797 BUG_ON(NULL == dev->fmt);
Brandon Philips78718e52008-04-02 18:10:59 -0300798
Pawel Osciake007a322011-01-19 13:02:29 -0200799 /*
800 * This callback is called once per buffer, after its allocation.
801 *
802 * Vivi does not allow changing format during streaming, but it is
803 * possible to do so when streaming is paused (i.e. in streamoff state).
804 * Buffers however are not freed when going into streamoff and so
805 * buffer size verification has to be done in buffer_prepare, on each
806 * qbuf.
807 * It would be best to move verification code here to buf_init and
808 * s_fmt though.
809 */
810
811 return 0;
812}
813
814static int buffer_prepare(struct vb2_buffer *vb)
815{
816 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
817 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
818 unsigned long size;
819
820 dprintk(dev, 1, "%s, field=%d\n", __func__, vb->v4l2_buf.field);
821
822 BUG_ON(NULL == dev->fmt);
823
824 /*
825 * Theses properties only change when queue is idle, see s_fmt.
826 * The below checks should not be performed here, on each
827 * buffer_prepare (i.e. on each qbuf). Most of the code in this function
828 * should thus be moved to buffer_init and s_fmt.
829 */
Hans Verkuil730947b2010-04-10 04:13:53 -0300830 if (dev->width < 48 || dev->width > MAX_WIDTH ||
831 dev->height < 32 || dev->height > MAX_HEIGHT)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300832 return -EINVAL;
Brandon Philips78718e52008-04-02 18:10:59 -0300833
Hans Verkuil3d51dca2012-05-02 03:15:11 -0300834 size = dev->width * dev->height * dev->pixelsize;
Pawel Osciake007a322011-01-19 13:02:29 -0200835 if (vb2_plane_size(vb, 0) < size) {
836 dprintk(dev, 1, "%s data will not fit into plane (%lu < %lu)\n",
837 __func__, vb2_plane_size(vb, 0), size);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300838 return -EINVAL;
Pawel Osciake007a322011-01-19 13:02:29 -0200839 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300840
Pawel Osciake007a322011-01-19 13:02:29 -0200841 vb2_set_plane_payload(&buf->vb, 0, size);
842
843 buf->fmt = dev->fmt;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300844
Hans Verkuil730947b2010-04-10 04:13:53 -0300845 precalculate_bars(dev);
846 precalculate_line(dev);
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -0300847
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300848 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300849}
850
Pawel Osciake007a322011-01-19 13:02:29 -0200851static int buffer_finish(struct vb2_buffer *vb)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300852{
Pawel Osciake007a322011-01-19 13:02:29 -0200853 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
854 dprintk(dev, 1, "%s\n", __func__);
855 return 0;
856}
857
858static void buffer_cleanup(struct vb2_buffer *vb)
859{
860 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
861 dprintk(dev, 1, "%s\n", __func__);
862
863}
864
865static void buffer_queue(struct vb2_buffer *vb)
866{
867 struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
Hans Verkuil730947b2010-04-10 04:13:53 -0300868 struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
Brandon Philips78718e52008-04-02 18:10:59 -0300869 struct vivi_dmaqueue *vidq = &dev->vidq;
Pawel Osciake007a322011-01-19 13:02:29 -0200870 unsigned long flags = 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300871
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300872 dprintk(dev, 1, "%s\n", __func__);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300873
Pawel Osciake007a322011-01-19 13:02:29 -0200874 spin_lock_irqsave(&dev->slock, flags);
875 list_add_tail(&buf->list, &vidq->active);
876 spin_unlock_irqrestore(&dev->slock, flags);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300877}
878
Marek Szyprowskibd323e22011-08-29 08:51:49 -0300879static int start_streaming(struct vb2_queue *vq, unsigned int count)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300880{
Pawel Osciake007a322011-01-19 13:02:29 -0200881 struct vivi_dev *dev = vb2_get_drv_priv(vq);
Harvey Harrison7e28adb2008-04-08 23:20:00 -0300882 dprintk(dev, 1, "%s\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -0200883 return vivi_start_generating(dev);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300884}
885
Pawel Osciake007a322011-01-19 13:02:29 -0200886/* abort streaming and wait for last buffer */
887static int stop_streaming(struct vb2_queue *vq)
888{
889 struct vivi_dev *dev = vb2_get_drv_priv(vq);
890 dprintk(dev, 1, "%s\n", __func__);
891 vivi_stop_generating(dev);
892 return 0;
893}
894
895static void vivi_lock(struct vb2_queue *vq)
896{
897 struct vivi_dev *dev = vb2_get_drv_priv(vq);
898 mutex_lock(&dev->mutex);
899}
900
901static void vivi_unlock(struct vb2_queue *vq)
902{
903 struct vivi_dev *dev = vb2_get_drv_priv(vq);
904 mutex_unlock(&dev->mutex);
905}
906
907
908static struct vb2_ops vivi_video_qops = {
909 .queue_setup = queue_setup,
910 .buf_init = buffer_init,
911 .buf_prepare = buffer_prepare,
912 .buf_finish = buffer_finish,
913 .buf_cleanup = buffer_cleanup,
914 .buf_queue = buffer_queue,
915 .start_streaming = start_streaming,
916 .stop_streaming = stop_streaming,
917 .wait_prepare = vivi_unlock,
918 .wait_finish = vivi_lock,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300919};
920
921/* ------------------------------------------------------------------
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300922 IOCTL vidioc handling
923 ------------------------------------------------------------------*/
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300924static int vidioc_querycap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300925 struct v4l2_capability *cap)
926{
Hans Verkuil730947b2010-04-10 04:13:53 -0300927 struct vivi_dev *dev = video_drvdata(file);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300928
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300929 strcpy(cap->driver, "vivi");
930 strcpy(cap->card, "vivi");
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -0300931 strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
Hans Verkuil23268ae2012-01-24 05:24:36 -0300932 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
933 V4L2_CAP_READWRITE;
934 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300935 return 0;
936}
937
Hans Verkuil78b526a2008-05-28 12:16:41 -0300938static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300939 struct v4l2_fmtdesc *f)
940{
Magnus Dammd891f472008-10-14 12:47:09 -0300941 struct vivi_fmt *fmt;
942
943 if (f->index >= ARRAY_SIZE(formats))
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300944 return -EINVAL;
945
Magnus Dammd891f472008-10-14 12:47:09 -0300946 fmt = &formats[f->index];
947
948 strlcpy(f->description, fmt->name, sizeof(f->description));
949 f->pixelformat = fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300950 return 0;
951}
952
Hans Verkuil78b526a2008-05-28 12:16:41 -0300953static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300954 struct v4l2_format *f)
955{
Hans Verkuil730947b2010-04-10 04:13:53 -0300956 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300957
Hans Verkuil730947b2010-04-10 04:13:53 -0300958 f->fmt.pix.width = dev->width;
959 f->fmt.pix.height = dev->height;
Pawel Osciake007a322011-01-19 13:02:29 -0200960 f->fmt.pix.field = dev->field;
Hans Verkuil730947b2010-04-10 04:13:53 -0300961 f->fmt.pix.pixelformat = dev->fmt->fourcc;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300962 f->fmt.pix.bytesperline =
Hans Verkuil730947b2010-04-10 04:13:53 -0300963 (f->fmt.pix.width * dev->fmt->depth) >> 3;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300964 f->fmt.pix.sizeimage =
965 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil8c79eec2011-07-29 07:19:46 -0300966 if (dev->fmt->fourcc == V4L2_PIX_FMT_YUYV ||
967 dev->fmt->fourcc == V4L2_PIX_FMT_UYVY)
968 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
969 else
970 f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
Hans Verkuil730947b2010-04-10 04:13:53 -0300971 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -0300972}
973
Hans Verkuil78b526a2008-05-28 12:16:41 -0300974static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300975 struct v4l2_format *f)
976{
Hans Verkuil730947b2010-04-10 04:13:53 -0300977 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300978 struct vivi_fmt *fmt;
979 enum v4l2_field field;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300980
Magnus Dammd891f472008-10-14 12:47:09 -0300981 fmt = get_format(f);
982 if (!fmt) {
983 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
984 f->fmt.pix.pixelformat);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300985 return -EINVAL;
986 }
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300987
988 field = f->fmt.pix.field;
989
990 if (field == V4L2_FIELD_ANY) {
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -0300991 field = V4L2_FIELD_INTERLACED;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300992 } else if (V4L2_FIELD_INTERLACED != field) {
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -0300993 dprintk(dev, 1, "Field type invalid.\n");
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300994 return -EINVAL;
995 }
996
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -0300997 f->fmt.pix.field = field;
Hans Verkuil730947b2010-04-10 04:13:53 -0300998 v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
999 &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001000 f->fmt.pix.bytesperline =
1001 (f->fmt.pix.width * fmt->depth) >> 3;
1002 f->fmt.pix.sizeimage =
1003 f->fmt.pix.height * f->fmt.pix.bytesperline;
Hans Verkuil8c79eec2011-07-29 07:19:46 -03001004 if (fmt->fourcc == V4L2_PIX_FMT_YUYV ||
1005 fmt->fourcc == V4L2_PIX_FMT_UYVY)
1006 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
1007 else
1008 f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001009 return 0;
1010}
1011
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001012static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1013 struct v4l2_format *f)
1014{
Hans Verkuil730947b2010-04-10 04:13:53 -03001015 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -02001016 struct vb2_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001017
Hans Verkuil730947b2010-04-10 04:13:53 -03001018 int ret = vidioc_try_fmt_vid_cap(file, priv, f);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001019 if (ret < 0)
1020 return ret;
1021
Pawel Osciake007a322011-01-19 13:02:29 -02001022 if (vb2_is_streaming(q)) {
Hans Verkuil730947b2010-04-10 04:13:53 -03001023 dprintk(dev, 1, "%s device busy\n", __func__);
Pawel Osciake007a322011-01-19 13:02:29 -02001024 return -EBUSY;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001025 }
1026
Hans Verkuil730947b2010-04-10 04:13:53 -03001027 dev->fmt = get_format(f);
Hans Verkuil3d51dca2012-05-02 03:15:11 -03001028 dev->pixelsize = dev->fmt->depth / 8;
Hans Verkuil730947b2010-04-10 04:13:53 -03001029 dev->width = f->fmt.pix.width;
1030 dev->height = f->fmt.pix.height;
Pawel Osciake007a322011-01-19 13:02:29 -02001031 dev->field = f->fmt.pix.field;
1032
1033 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001034}
1035
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001036static int vidioc_reqbufs(struct file *file, void *priv,
1037 struct v4l2_requestbuffers *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001038{
Hans Verkuil730947b2010-04-10 04:13:53 -03001039 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -02001040 return vb2_reqbufs(&dev->vb_vidq, p);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001041}
1042
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001043static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001044{
Hans Verkuil730947b2010-04-10 04:13:53 -03001045 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -02001046 return vb2_querybuf(&dev->vb_vidq, p);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001047}
1048
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001049static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001050{
Hans Verkuil730947b2010-04-10 04:13:53 -03001051 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -02001052 return vb2_qbuf(&dev->vb_vidq, p);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001053}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001054
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001055static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001056{
Hans Verkuil730947b2010-04-10 04:13:53 -03001057 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -02001058 return vb2_dqbuf(&dev->vb_vidq, p, file->f_flags & O_NONBLOCK);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001059}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001060
Adrian Bunkdc46ace2006-06-23 06:42:44 -03001061static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001062{
Hans Verkuil730947b2010-04-10 04:13:53 -03001063 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -02001064 return vb2_streamon(&dev->vb_vidq, i);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001065}
1066
Adrian Bunkdc46ace2006-06-23 06:42:44 -03001067static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001068{
Hans Verkuil730947b2010-04-10 04:13:53 -03001069 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -02001070 return vb2_streamoff(&dev->vb_vidq, i);
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001071}
1072
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001073/* only one input in this sample driver */
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001074static int vidioc_enum_input(struct file *file, void *priv,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001075 struct v4l2_input *inp)
1076{
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001077 if (inp->index >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001078 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001079
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001080 inp->type = V4L2_INPUT_TYPE_CAMERA;
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001081 sprintf(inp->name, "Camera %u", inp->index);
Hans Verkuil730947b2010-04-10 04:13:53 -03001082 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001083}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001084
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001085static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001086{
Hans Verkuil730947b2010-04-10 04:13:53 -03001087 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001088
1089 *i = dev->input;
Hans Verkuil730947b2010-04-10 04:13:53 -03001090 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001091}
Hans Verkuil730947b2010-04-10 04:13:53 -03001092
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001093static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001094{
Hans Verkuil730947b2010-04-10 04:13:53 -03001095 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001096
1097 if (i >= NUM_INPUTS)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001098 return -EINVAL;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001099
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001100 if (i == dev->input)
1101 return 0;
1102
Mauro Carvalho Chehabe164b582009-01-11 10:29:43 -03001103 dev->input = i;
Hans Verkuil730947b2010-04-10 04:13:53 -03001104 precalculate_bars(dev);
1105 precalculate_line(dev);
1106 return 0;
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001107}
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001108
Hans Verkuil730947b2010-04-10 04:13:53 -03001109/* --- controls ---------------------------------------------- */
Hans Verkuil7e996af2011-01-23 12:33:16 -02001110
Hans Verkuila1c894f2011-06-07 06:34:41 -03001111static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1112{
1113 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
1114
1115 if (ctrl == dev->autogain)
1116 dev->gain->val = jiffies & 0xff;
1117 return 0;
1118}
1119
Hans Verkuil7e996af2011-01-23 12:33:16 -02001120static int vivi_s_ctrl(struct v4l2_ctrl *ctrl)
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001121{
Hans Verkuil7e996af2011-01-23 12:33:16 -02001122 struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001123
Hans Verkuil7088f4d2012-05-02 03:33:52 -03001124 switch (ctrl->id) {
1125 case V4L2_CID_ALPHA_COMPONENT:
1126 dev->alpha_component = ctrl->val;
1127 break;
1128 default:
1129 if (ctrl == dev->button)
1130 dev->button_pressed = 30;
1131 break;
1132 }
Hans Verkuil7e996af2011-01-23 12:33:16 -02001133 return 0;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001134}
1135
1136/* ------------------------------------------------------------------
1137 File operations for the device
1138 ------------------------------------------------------------------*/
1139
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001140static ssize_t
1141vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1142{
Hans Verkuil730947b2010-04-10 04:13:53 -03001143 struct vivi_dev *dev = video_drvdata(file);
Hans Verkuild9762df2012-06-06 02:17:16 -03001144 int err;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001145
Pawel Osciake007a322011-01-19 13:02:29 -02001146 dprintk(dev, 1, "read called\n");
Hans Verkuild9762df2012-06-06 02:17:16 -03001147 mutex_lock(&dev->mutex);
1148 err = vb2_read(&dev->vb_vidq, data, count, ppos,
Pawel Osciake007a322011-01-19 13:02:29 -02001149 file->f_flags & O_NONBLOCK);
Hans Verkuild9762df2012-06-06 02:17:16 -03001150 mutex_unlock(&dev->mutex);
1151 return err;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001152}
1153
1154static unsigned int
1155vivi_poll(struct file *file, struct poll_table_struct *wait)
1156{
Hans Verkuil730947b2010-04-10 04:13:53 -03001157 struct vivi_dev *dev = video_drvdata(file);
Pawel Osciake007a322011-01-19 13:02:29 -02001158 struct vb2_queue *q = &dev->vb_vidq;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001159
Harvey Harrison7e28adb2008-04-08 23:20:00 -03001160 dprintk(dev, 1, "%s\n", __func__);
Hans Verkuil0bf0f712011-07-13 04:28:27 -03001161 return vb2_poll(q, file, wait);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001162}
1163
Hans Verkuilbec43662008-12-30 06:58:20 -03001164static int vivi_close(struct file *file)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001165{
Laurent Pinchart50462eb2009-12-10 11:47:13 -02001166 struct video_device *vdev = video_devdata(file);
Hans Verkuil730947b2010-04-10 04:13:53 -03001167 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001168
Pawel Osciake007a322011-01-19 13:02:29 -02001169 dprintk(dev, 1, "close called (dev=%s), file %p\n",
1170 video_device_node_name(vdev), file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001171
Hans Verkuil2e4784d2011-03-11 20:01:54 -03001172 if (v4l2_fh_is_singular_file(file))
Pawel Osciake007a322011-01-19 13:02:29 -02001173 vb2_queue_release(&dev->vb_vidq);
Hans Verkuil2e4784d2011-03-11 20:01:54 -03001174 return v4l2_fh_release(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001175}
1176
Mauro Carvalho Chehab543323b2007-12-10 09:33:52 -03001177static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001178{
Hans Verkuil730947b2010-04-10 04:13:53 -03001179 struct vivi_dev *dev = video_drvdata(file);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001180 int ret;
1181
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001182 dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001183
Pawel Osciake007a322011-01-19 13:02:29 -02001184 ret = vb2_mmap(&dev->vb_vidq, vma);
Mauro Carvalho Chehab6c2f9902007-12-13 13:30:14 -03001185 dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n",
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001186 (unsigned long)vma->vm_start,
Hans Verkuil730947b2010-04-10 04:13:53 -03001187 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001188 ret);
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001189 return ret;
1190}
1191
Hans Verkuil7e996af2011-01-23 12:33:16 -02001192static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
Hans Verkuila1c894f2011-06-07 06:34:41 -03001193 .g_volatile_ctrl = vivi_g_volatile_ctrl,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001194 .s_ctrl = vivi_s_ctrl,
1195};
1196
1197#define VIVI_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
1198
1199static const struct v4l2_ctrl_config vivi_ctrl_button = {
1200 .ops = &vivi_ctrl_ops,
1201 .id = VIVI_CID_CUSTOM_BASE + 0,
1202 .name = "Button",
1203 .type = V4L2_CTRL_TYPE_BUTTON,
1204};
1205
1206static const struct v4l2_ctrl_config vivi_ctrl_boolean = {
1207 .ops = &vivi_ctrl_ops,
1208 .id = VIVI_CID_CUSTOM_BASE + 1,
1209 .name = "Boolean",
1210 .type = V4L2_CTRL_TYPE_BOOLEAN,
1211 .min = 0,
1212 .max = 1,
1213 .step = 1,
1214 .def = 1,
1215};
1216
1217static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
1218 .ops = &vivi_ctrl_ops,
1219 .id = VIVI_CID_CUSTOM_BASE + 2,
1220 .name = "Integer 32 Bits",
1221 .type = V4L2_CTRL_TYPE_INTEGER,
Hans Verkuil5b283022011-01-11 17:32:28 -03001222 .min = 0x80000000,
1223 .max = 0x7fffffff,
Hans Verkuil7e996af2011-01-23 12:33:16 -02001224 .step = 1,
1225};
1226
1227static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
1228 .ops = &vivi_ctrl_ops,
1229 .id = VIVI_CID_CUSTOM_BASE + 3,
1230 .name = "Integer 64 Bits",
1231 .type = V4L2_CTRL_TYPE_INTEGER64,
1232};
1233
1234static const char * const vivi_ctrl_menu_strings[] = {
1235 "Menu Item 0 (Skipped)",
1236 "Menu Item 1",
1237 "Menu Item 2 (Skipped)",
1238 "Menu Item 3",
1239 "Menu Item 4",
1240 "Menu Item 5 (Skipped)",
1241 NULL,
1242};
1243
1244static const struct v4l2_ctrl_config vivi_ctrl_menu = {
1245 .ops = &vivi_ctrl_ops,
1246 .id = VIVI_CID_CUSTOM_BASE + 4,
1247 .name = "Menu",
1248 .type = V4L2_CTRL_TYPE_MENU,
1249 .min = 1,
1250 .max = 4,
1251 .def = 3,
1252 .menu_skip_mask = 0x04,
1253 .qmenu = vivi_ctrl_menu_strings,
1254};
1255
1256static const struct v4l2_ctrl_config vivi_ctrl_string = {
1257 .ops = &vivi_ctrl_ops,
1258 .id = VIVI_CID_CUSTOM_BASE + 5,
1259 .name = "String",
1260 .type = V4L2_CTRL_TYPE_STRING,
1261 .min = 2,
1262 .max = 4,
1263 .step = 1,
1264};
1265
Hans Verkuilb6d17a52011-03-29 16:33:11 -03001266static const struct v4l2_ctrl_config vivi_ctrl_bitmask = {
1267 .ops = &vivi_ctrl_ops,
1268 .id = VIVI_CID_CUSTOM_BASE + 6,
1269 .name = "Bitmask",
1270 .type = V4L2_CTRL_TYPE_BITMASK,
1271 .def = 0x80002000,
1272 .min = 0,
1273 .max = 0x80402010,
1274 .step = 0,
1275};
1276
Sakari Ailusc5203312011-08-05 06:38:05 -03001277static const s64 vivi_ctrl_int_menu_values[] = {
1278 1, 1, 2, 3, 5, 8, 13, 21, 42,
1279};
1280
1281static const struct v4l2_ctrl_config vivi_ctrl_int_menu = {
1282 .ops = &vivi_ctrl_ops,
1283 .id = VIVI_CID_CUSTOM_BASE + 7,
1284 .name = "Integer menu",
1285 .type = V4L2_CTRL_TYPE_INTEGER_MENU,
1286 .min = 1,
1287 .max = 8,
1288 .def = 4,
1289 .menu_skip_mask = 0x02,
1290 .qmenu_int = vivi_ctrl_int_menu_values,
1291};
1292
Hans Verkuilbec43662008-12-30 06:58:20 -03001293static const struct v4l2_file_operations vivi_fops = {
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001294 .owner = THIS_MODULE,
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001295 .open = v4l2_fh_open,
Mauro Carvalho Chehabf905c442007-12-10 04:07:03 -03001296 .release = vivi_close,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001297 .read = vivi_read,
1298 .poll = vivi_poll,
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001299 .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
Mauro Carvalho Chehab5a037702007-08-02 23:31:54 -03001300 .mmap = vivi_mmap,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001301};
1302
Hans Verkuila3998102008-07-21 02:57:38 -03001303static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001304 .vidioc_querycap = vidioc_querycap,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001305 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1306 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1307 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1308 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001309 .vidioc_reqbufs = vidioc_reqbufs,
1310 .vidioc_querybuf = vidioc_querybuf,
1311 .vidioc_qbuf = vidioc_qbuf,
1312 .vidioc_dqbuf = vidioc_dqbuf,
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001313 .vidioc_enum_input = vidioc_enum_input,
1314 .vidioc_g_input = vidioc_g_input,
1315 .vidioc_s_input = vidioc_s_input,
Hans Verkuil730947b2010-04-10 04:13:53 -03001316 .vidioc_streamon = vidioc_streamon,
1317 .vidioc_streamoff = vidioc_streamoff,
Hans Verkuile2ecb252012-02-02 08:20:53 -03001318 .vidioc_log_status = v4l2_ctrl_log_status,
Hans Verkuil6d6604f2012-01-27 16:21:10 -03001319 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
Hans Verkuilc7a52f82011-06-07 10:20:23 -03001320 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Hans Verkuila3998102008-07-21 02:57:38 -03001321};
1322
1323static struct video_device vivi_template = {
1324 .name = "vivi",
Hans Verkuila3998102008-07-21 02:57:38 -03001325 .fops = &vivi_fops,
1326 .ioctl_ops = &vivi_ioctl_ops,
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001327 .release = video_device_release_empty,
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001328};
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001329
Mauro Carvalho Chehabc820cc42006-06-04 10:34:12 -03001330/* -----------------------------------------------------------------
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001331 Initialization and module stuff
1332 ------------------------------------------------------------------*/
1333
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001334static int vivi_release(void)
1335{
1336 struct vivi_dev *dev;
1337 struct list_head *list;
1338
1339 while (!list_empty(&vivi_devlist)) {
1340 list = vivi_devlist.next;
1341 list_del(list);
1342 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1343
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001344 v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001345 video_device_node_name(&dev->vdev));
1346 video_unregister_device(&dev->vdev);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001347 v4l2_device_unregister(&dev->v4l2_dev);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001348 v4l2_ctrl_handler_free(&dev->ctrl_handler);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001349 kfree(dev);
1350 }
1351
1352 return 0;
1353}
1354
Hans Verkuilc41ee242009-02-14 13:43:44 -03001355static int __init vivi_create_instance(int inst)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001356{
1357 struct vivi_dev *dev;
1358 struct video_device *vfd;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001359 struct v4l2_ctrl_handler *hdl;
Pawel Osciake007a322011-01-19 13:02:29 -02001360 struct vb2_queue *q;
Hans Verkuil730947b2010-04-10 04:13:53 -03001361 int ret;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001362
1363 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1364 if (!dev)
1365 return -ENOMEM;
1366
1367 snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
Hans Verkuilc41ee242009-02-14 13:43:44 -03001368 "%s-%03d", VIVI_MODULE_NAME, inst);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001369 ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1370 if (ret)
1371 goto free_dev;
1372
Hans Verkuil730947b2010-04-10 04:13:53 -03001373 dev->fmt = &formats[0];
1374 dev->width = 640;
1375 dev->height = 480;
Hans Verkuil3d51dca2012-05-02 03:15:11 -03001376 dev->pixelsize = dev->fmt->depth / 8;
Hans Verkuil7e996af2011-01-23 12:33:16 -02001377 hdl = &dev->ctrl_handler;
1378 v4l2_ctrl_handler_init(hdl, 11);
1379 dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1380 V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
1381 dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1382 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1383 dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1384 V4L2_CID_CONTRAST, 0, 255, 1, 16);
1385 dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1386 V4L2_CID_SATURATION, 0, 255, 1, 127);
1387 dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1388 V4L2_CID_HUE, -128, 127, 1, 0);
Hans Verkuila1c894f2011-06-07 06:34:41 -03001389 dev->autogain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1390 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1391 dev->gain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1392 V4L2_CID_GAIN, 0, 255, 1, 100);
Hans Verkuil7088f4d2012-05-02 03:33:52 -03001393 dev->alpha = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
1394 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001395 dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
1396 dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
1397 dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);
1398 dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL);
1399 dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL);
1400 dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL);
Hans Verkuilb6d17a52011-03-29 16:33:11 -03001401 dev->bitmask = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_bitmask, NULL);
Sakari Ailusc5203312011-08-05 06:38:05 -03001402 dev->int_menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int_menu, NULL);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001403 if (hdl->error) {
1404 ret = hdl->error;
1405 goto unreg_dev;
1406 }
Hans Verkuila1c894f2011-06-07 06:34:41 -03001407 v4l2_ctrl_auto_cluster(2, &dev->autogain, 0, true);
Hans Verkuil7e996af2011-01-23 12:33:16 -02001408 dev->v4l2_dev.ctrl_handler = hdl;
Hans Verkuil730947b2010-04-10 04:13:53 -03001409
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001410 /* initialize locks */
1411 spin_lock_init(&dev->slock);
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001412
Pawel Osciake007a322011-01-19 13:02:29 -02001413 /* initialize queue */
1414 q = &dev->vb_vidq;
1415 memset(q, 0, sizeof(dev->vb_vidq));
1416 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1417 q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1418 q->drv_priv = dev;
1419 q->buf_struct_size = sizeof(struct vivi_buffer);
1420 q->ops = &vivi_video_qops;
1421 q->mem_ops = &vb2_vmalloc_memops;
1422
1423 vb2_queue_init(q);
1424
1425 mutex_init(&dev->mutex);
Hans Verkuil730947b2010-04-10 04:13:53 -03001426
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001427 /* init video dma queues */
1428 INIT_LIST_HEAD(&dev->vidq.active);
1429 init_waitqueue_head(&dev->vidq.wq);
1430
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001431 vfd = &dev->vdev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001432 *vfd = vivi_template;
Mauro Carvalho Chehabc285add2009-06-25 16:28:23 -03001433 vfd->debug = debug;
Hans Verkuil730947b2010-04-10 04:13:53 -03001434 vfd->v4l2_dev = &dev->v4l2_dev;
Hans Verkuilb1a873a2011-03-22 10:14:07 -03001435 set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
Pawel Osciake007a322011-01-19 13:02:29 -02001436
1437 /*
1438 * Provide a mutex to v4l2 core. It will be used to protect
1439 * all fops and v4l2 ioctls.
1440 */
Hans Verkuilfedc6c82010-09-20 18:25:55 -03001441 vfd->lock = &dev->mutex;
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001442 video_set_drvdata(vfd, dev);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001443
1444 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1445 if (ret < 0)
Hans Verkuil70bd97a2012-06-09 11:27:43 -03001446 goto unreg_dev;
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001447
1448 /* Now that everything is fine, let's add it to device list */
1449 list_add_tail(&dev->vivi_devlist, &vivi_devlist);
1450
Roel Kluin7de0b872009-12-16 13:06:33 -03001451 if (video_nr != -1)
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001452 video_nr++;
1453
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001454 v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
1455 video_device_node_name(vfd));
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001456 return 0;
1457
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001458unreg_dev:
Hans Verkuil7e996af2011-01-23 12:33:16 -02001459 v4l2_ctrl_handler_free(hdl);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001460 v4l2_device_unregister(&dev->v4l2_dev);
1461free_dev:
1462 kfree(dev);
1463 return ret;
1464}
1465
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001466/* This routine allocates from 1 to n_devs virtual drivers.
1467
1468 The real maximum number of virtual drivers will depend on how many drivers
1469 will succeed. This is limited to the maximum number of devices that
Hans Verkuil62cfdac2009-02-14 11:37:17 -03001470 videodev supports, which is equal to VIDEO_NUM_DEVICES.
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001471 */
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001472static int __init vivi_init(void)
1473{
Hans Verkuil730947b2010-04-10 04:13:53 -03001474 const struct font_desc *font = find_font("VGA8x16");
Hans Verkuil9185cbf2009-03-06 09:58:12 -03001475 int ret = 0, i;
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001476
Hans Verkuil730947b2010-04-10 04:13:53 -03001477 if (font == NULL) {
1478 printk(KERN_ERR "vivi: could not find font\n");
1479 return -ENODEV;
1480 }
1481 font8x16 = font->data;
1482
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001483 if (n_devs <= 0)
1484 n_devs = 1;
1485
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001486 for (i = 0; i < n_devs; i++) {
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001487 ret = vivi_create_instance(i);
1488 if (ret) {
1489 /* If some instantiations succeeded, keep driver */
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001490 if (i)
1491 ret = 0;
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001492 break;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001493 }
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001494 }
1495
1496 if (ret < 0) {
Hans Verkuil730947b2010-04-10 04:13:53 -03001497 printk(KERN_ERR "vivi: error %d while loading driver\n", ret);
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001498 return ret;
1499 }
1500
1501 printk(KERN_INFO "Video Technology Magazine Virtual Video "
Mauro Carvalho Chehab1990d502011-06-24 14:45:49 -03001502 "Capture Board ver %s successfully loaded.\n",
1503 VIVI_VERSION);
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001504
Hans Verkuil5ab6c9a2009-02-14 13:23:12 -03001505 /* n_devs will reflect the actual number of allocated devices */
1506 n_devs = i;
Mauro Carvalho Chehab980d4f12008-09-03 17:11:53 -03001507
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001508 return ret;
1509}
1510
1511static void __exit vivi_exit(void)
1512{
Mauro Carvalho Chehab55712ff2007-12-10 04:38:11 -03001513 vivi_release();
Mauro Carvalho Chehab1e6dd652006-03-10 12:40:10 -03001514}
1515
1516module_init(vivi_init);
1517module_exit(vivi_exit);