blob: 4404e5ef818fdc92159cdbb527a83c3dce576593 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Motion Eye video4linux driver for Sony Vaio PictureBook
3 *
4 * Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
5 *
Jan Engelhardt96de0e22007-10-19 23:21:04 +02006 * Copyright (C) 2001-2002 AlcĂ´ve <www.alcove.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 *
8 * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
9 *
10 * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
11 *
12 * Some parts borrowed from various video4linux drivers, especially
13 * bttv-driver.c and zoran.c, see original files for credits.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30#include <linux/pci.h>
Alexey Dobriyand43c36d2009-10-07 17:09:06 +040031#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/init.h>
33#include <linux/videodev.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090034#include <linux/gfp.h>
Mauro Carvalho Chehab5e87efa2006-06-05 10:26:32 -030035#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030036#include <media/v4l2-ioctl.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <asm/uaccess.h>
38#include <asm/io.h>
39#include <linux/delay.h>
40#include <linux/interrupt.h>
41#include <linux/vmalloc.h>
Tobias Klauserd013a062005-09-06 15:17:07 -070042#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
44#include "meye.h"
45#include <linux/meye.h>
46
47MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -030048MODULE_DESCRIPTION("v4l2 driver for the MotionEye camera");
Linus Torvalds1da177e2005-04-16 15:20:36 -070049MODULE_LICENSE("GPL");
50MODULE_VERSION(MEYE_DRIVER_VERSION);
51
Linus Torvalds1da177e2005-04-16 15:20:36 -070052/* number of grab buffers */
53static unsigned int gbuffers = 2;
54module_param(gbuffers, int, 0444);
55MODULE_PARM_DESC(gbuffers, "number of capture buffers, default is 2 (32 max)");
56
57/* size of a grab buffer */
58static unsigned int gbufsize = MEYE_MAX_BUFSIZE;
59module_param(gbufsize, int, 0444);
60MODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 614400"
61 " (will be rounded up to a page multiple)");
62
63/* /dev/videoX registration number */
64static int video_nr = -1;
65module_param(video_nr, int, 0444);
66MODULE_PARM_DESC(video_nr, "video device to register (0=/dev/video0, etc)");
67
68/* driver structure - only one possible */
69static struct meye meye;
70
71/****************************************************************************/
72/* Memory allocation routines (stolen from bttv-driver.c) */
73/****************************************************************************/
74static void *rvmalloc(unsigned long size)
75{
76 void *mem;
77 unsigned long adr;
78
79 size = PAGE_ALIGN(size);
80 mem = vmalloc_32(size);
81 if (mem) {
82 memset(mem, 0, size);
83 adr = (unsigned long) mem;
84 while (size > 0) {
85 SetPageReserved(vmalloc_to_page((void *)adr));
86 adr += PAGE_SIZE;
87 size -= PAGE_SIZE;
88 }
89 }
90 return mem;
91}
92
93static void rvfree(void * mem, unsigned long size)
94{
95 unsigned long adr;
96
97 if (mem) {
98 adr = (unsigned long) mem;
99 while ((long) size > 0) {
100 ClearPageReserved(vmalloc_to_page((void *)adr));
101 adr += PAGE_SIZE;
102 size -= PAGE_SIZE;
103 }
104 vfree(mem);
105 }
106}
107
108/*
109 * return a page table pointing to N pages of locked memory
110 *
111 * NOTE: The meye device expects DMA addresses on 32 bits, we build
112 * a table of 1024 entries = 4 bytes * 1024 = 4096 bytes.
113 */
114static int ptable_alloc(void)
115{
116 u32 *pt;
117 int i;
118
119 memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
120
121 /* give only 32 bit DMA addresses */
Yang Hongyang284901a2009-04-06 19:01:15 -0700122 if (dma_set_mask(&meye.mchip_dev->dev, DMA_BIT_MASK(32)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 return -1;
124
125 meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev,
126 PAGE_SIZE,
127 &meye.mchip_dmahandle,
128 GFP_KERNEL);
129 if (!meye.mchip_ptable_toc) {
130 meye.mchip_dmahandle = 0;
131 return -1;
132 }
133
134 pt = meye.mchip_ptable_toc;
135 for (i = 0; i < MCHIP_NB_PAGES; i++) {
136 dma_addr_t dma;
137 meye.mchip_ptable[i] = dma_alloc_coherent(&meye.mchip_dev->dev,
138 PAGE_SIZE,
139 &dma,
140 GFP_KERNEL);
141 if (!meye.mchip_ptable[i]) {
142 int j;
143 pt = meye.mchip_ptable_toc;
144 for (j = 0; j < i; ++j) {
145 dma = (dma_addr_t) *pt;
146 dma_free_coherent(&meye.mchip_dev->dev,
147 PAGE_SIZE,
148 meye.mchip_ptable[j], dma);
149 pt++;
150 }
151 dma_free_coherent(&meye.mchip_dev->dev,
152 PAGE_SIZE,
153 meye.mchip_ptable_toc,
154 meye.mchip_dmahandle);
155 meye.mchip_ptable_toc = NULL;
156 meye.mchip_dmahandle = 0;
157 return -1;
158 }
159 *pt = (u32) dma;
160 pt++;
161 }
162 return 0;
163}
164
165static void ptable_free(void)
166{
167 u32 *pt;
168 int i;
169
170 pt = meye.mchip_ptable_toc;
171 for (i = 0; i < MCHIP_NB_PAGES; i++) {
172 dma_addr_t dma = (dma_addr_t) *pt;
173 if (meye.mchip_ptable[i])
174 dma_free_coherent(&meye.mchip_dev->dev,
175 PAGE_SIZE,
176 meye.mchip_ptable[i], dma);
177 pt++;
178 }
179
180 if (meye.mchip_ptable_toc)
181 dma_free_coherent(&meye.mchip_dev->dev,
182 PAGE_SIZE,
183 meye.mchip_ptable_toc,
184 meye.mchip_dmahandle);
185
186 memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
187 meye.mchip_ptable_toc = NULL;
188 meye.mchip_dmahandle = 0;
189}
190
191/* copy data from ptable into buf */
192static void ptable_copy(u8 *buf, int start, int size, int pt_pages)
193{
194 int i;
195
196 for (i = 0; i < (size / PAGE_SIZE) * PAGE_SIZE; i += PAGE_SIZE) {
197 memcpy(buf + i, meye.mchip_ptable[start++], PAGE_SIZE);
198 if (start >= pt_pages)
199 start = 0;
200 }
201 memcpy(buf + i, meye.mchip_ptable[start], size % PAGE_SIZE);
202}
203
204/****************************************************************************/
205/* JPEG tables at different qualities to load into the VRJ chip */
206/****************************************************************************/
207
208/* return a set of quantisation tables based on a quality from 1 to 10 */
209static u16 *jpeg_quantisation_tables(int *length, int quality)
210{
211 static u16 jpeg_tables[][70] = { {
212 0xdbff, 0x4300, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
213 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
214 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
215 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
216 0xffff, 0xffff, 0xffff,
217 0xdbff, 0x4300, 0xff01, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
218 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
219 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
220 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
221 0xffff, 0xffff, 0xffff,
222 },
223 {
224 0xdbff, 0x4300, 0x5000, 0x3c37, 0x3c46, 0x5032, 0x4146, 0x5a46,
225 0x5055, 0x785f, 0x82c8, 0x6e78, 0x786e, 0xaff5, 0x91b9, 0xffc8,
226 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
227 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
228 0xffff, 0xffff, 0xffff,
229 0xdbff, 0x4300, 0x5501, 0x5a5a, 0x6978, 0xeb78, 0x8282, 0xffeb,
230 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
231 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
232 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
233 0xffff, 0xffff, 0xffff,
234 },
235 {
236 0xdbff, 0x4300, 0x2800, 0x1e1c, 0x1e23, 0x2819, 0x2123, 0x2d23,
237 0x282b, 0x3c30, 0x4164, 0x373c, 0x3c37, 0x587b, 0x495d, 0x9164,
238 0x9980, 0x8f96, 0x8c80, 0xa08a, 0xe6b4, 0xa0c3, 0xdaaa, 0x8aad,
239 0xc88c, 0xcbff, 0xeeda, 0xfff5, 0xffff, 0xc19b, 0xffff, 0xfaff,
240 0xe6ff, 0xfffd, 0xfff8,
241 0xdbff, 0x4300, 0x2b01, 0x2d2d, 0x353c, 0x763c, 0x4141, 0xf876,
242 0x8ca5, 0xf8a5, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
243 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
244 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
245 0xf8f8, 0xf8f8, 0xfff8,
246 },
247 {
248 0xdbff, 0x4300, 0x1b00, 0x1412, 0x1417, 0x1b11, 0x1617, 0x1e17,
249 0x1b1c, 0x2820, 0x2b42, 0x2528, 0x2825, 0x3a51, 0x303d, 0x6042,
250 0x6555, 0x5f64, 0x5d55, 0x6a5b, 0x9978, 0x6a81, 0x9071, 0x5b73,
251 0x855d, 0x86b5, 0x9e90, 0xaba3, 0xabad, 0x8067, 0xc9bc, 0xa6ba,
252 0x99c7, 0xaba8, 0xffa4,
253 0xdbff, 0x4300, 0x1c01, 0x1e1e, 0x2328, 0x4e28, 0x2b2b, 0xa44e,
254 0x5d6e, 0xa46e, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
255 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
256 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
257 0xa4a4, 0xa4a4, 0xffa4,
258 },
259 {
260 0xdbff, 0x4300, 0x1400, 0x0f0e, 0x0f12, 0x140d, 0x1012, 0x1712,
261 0x1415, 0x1e18, 0x2132, 0x1c1e, 0x1e1c, 0x2c3d, 0x242e, 0x4932,
262 0x4c40, 0x474b, 0x4640, 0x5045, 0x735a, 0x5062, 0x6d55, 0x4556,
263 0x6446, 0x6588, 0x776d, 0x817b, 0x8182, 0x604e, 0x978d, 0x7d8c,
264 0x7396, 0x817e, 0xff7c,
265 0xdbff, 0x4300, 0x1501, 0x1717, 0x1a1e, 0x3b1e, 0x2121, 0x7c3b,
266 0x4653, 0x7c53, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
267 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
268 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
269 0x7c7c, 0x7c7c, 0xff7c,
270 },
271 {
272 0xdbff, 0x4300, 0x1000, 0x0c0b, 0x0c0e, 0x100a, 0x0d0e, 0x120e,
273 0x1011, 0x1813, 0x1a28, 0x1618, 0x1816, 0x2331, 0x1d25, 0x3a28,
274 0x3d33, 0x393c, 0x3833, 0x4037, 0x5c48, 0x404e, 0x5744, 0x3745,
275 0x5038, 0x516d, 0x5f57, 0x6762, 0x6768, 0x4d3e, 0x7971, 0x6470,
276 0x5c78, 0x6765, 0xff63,
277 0xdbff, 0x4300, 0x1101, 0x1212, 0x1518, 0x2f18, 0x1a1a, 0x632f,
278 0x3842, 0x6342, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
279 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
280 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
281 0x6363, 0x6363, 0xff63,
282 },
283 {
284 0xdbff, 0x4300, 0x0d00, 0x0a09, 0x0a0b, 0x0d08, 0x0a0b, 0x0e0b,
285 0x0d0e, 0x130f, 0x1520, 0x1213, 0x1312, 0x1c27, 0x171e, 0x2e20,
286 0x3129, 0x2e30, 0x2d29, 0x332c, 0x4a3a, 0x333e, 0x4636, 0x2c37,
287 0x402d, 0x4157, 0x4c46, 0x524e, 0x5253, 0x3e32, 0x615a, 0x505a,
288 0x4a60, 0x5251, 0xff4f,
289 0xdbff, 0x4300, 0x0e01, 0x0e0e, 0x1113, 0x2613, 0x1515, 0x4f26,
290 0x2d35, 0x4f35, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
291 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
292 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
293 0x4f4f, 0x4f4f, 0xff4f,
294 },
295 {
296 0xdbff, 0x4300, 0x0a00, 0x0707, 0x0708, 0x0a06, 0x0808, 0x0b08,
297 0x0a0a, 0x0e0b, 0x1018, 0x0d0e, 0x0e0d, 0x151d, 0x1116, 0x2318,
298 0x251f, 0x2224, 0x221f, 0x2621, 0x372b, 0x262f, 0x3429, 0x2129,
299 0x3022, 0x3141, 0x3934, 0x3e3b, 0x3e3e, 0x2e25, 0x4944, 0x3c43,
300 0x3748, 0x3e3d, 0xff3b,
301 0xdbff, 0x4300, 0x0a01, 0x0b0b, 0x0d0e, 0x1c0e, 0x1010, 0x3b1c,
302 0x2228, 0x3b28, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
303 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
304 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
305 0x3b3b, 0x3b3b, 0xff3b,
306 },
307 {
308 0xdbff, 0x4300, 0x0600, 0x0504, 0x0506, 0x0604, 0x0506, 0x0706,
309 0x0607, 0x0a08, 0x0a10, 0x090a, 0x0a09, 0x0e14, 0x0c0f, 0x1710,
310 0x1814, 0x1718, 0x1614, 0x1a16, 0x251d, 0x1a1f, 0x231b, 0x161c,
311 0x2016, 0x202c, 0x2623, 0x2927, 0x292a, 0x1f19, 0x302d, 0x282d,
312 0x2530, 0x2928, 0xff28,
313 0xdbff, 0x4300, 0x0701, 0x0707, 0x080a, 0x130a, 0x0a0a, 0x2813,
314 0x161a, 0x281a, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
315 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
316 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
317 0x2828, 0x2828, 0xff28,
318 },
319 {
320 0xdbff, 0x4300, 0x0300, 0x0202, 0x0203, 0x0302, 0x0303, 0x0403,
321 0x0303, 0x0504, 0x0508, 0x0405, 0x0504, 0x070a, 0x0607, 0x0c08,
322 0x0c0a, 0x0b0c, 0x0b0a, 0x0d0b, 0x120e, 0x0d10, 0x110e, 0x0b0e,
323 0x100b, 0x1016, 0x1311, 0x1514, 0x1515, 0x0f0c, 0x1817, 0x1416,
324 0x1218, 0x1514, 0xff14,
325 0xdbff, 0x4300, 0x0301, 0x0404, 0x0405, 0x0905, 0x0505, 0x1409,
326 0x0b0d, 0x140d, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
327 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
328 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
329 0x1414, 0x1414, 0xff14,
330 },
331 {
332 0xdbff, 0x4300, 0x0100, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
333 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
334 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
335 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
336 0x0101, 0x0101, 0xff01,
337 0xdbff, 0x4300, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
338 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
339 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
340 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
341 0x0101, 0x0101, 0xff01,
342 } };
343
344 if (quality < 0 || quality > 10) {
345 printk(KERN_WARNING
346 "meye: invalid quality level %d - using 8\n", quality);
347 quality = 8;
348 }
349
350 *length = ARRAY_SIZE(jpeg_tables[quality]);
351 return jpeg_tables[quality];
352}
353
354/* return a generic set of huffman tables */
355static u16 *jpeg_huffman_tables(int *length)
356{
357 static u16 tables[] = {
358 0xC4FF, 0xB500, 0x0010, 0x0102, 0x0303, 0x0402, 0x0503, 0x0405,
359 0x0004, 0x0100, 0x017D, 0x0302, 0x0400, 0x0511, 0x2112, 0x4131,
360 0x1306, 0x6151, 0x2207, 0x1471, 0x8132, 0xA191, 0x2308, 0xB142,
361 0x15C1, 0xD152, 0x24F0, 0x6233, 0x8272, 0x0A09, 0x1716, 0x1918,
362 0x251A, 0x2726, 0x2928, 0x342A, 0x3635, 0x3837, 0x3A39, 0x4443,
363 0x4645, 0x4847, 0x4A49, 0x5453, 0x5655, 0x5857, 0x5A59, 0x6463,
364 0x6665, 0x6867, 0x6A69, 0x7473, 0x7675, 0x7877, 0x7A79, 0x8483,
365 0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998, 0xA29A,
366 0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6, 0xB9B8,
367 0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4, 0xD7D6,
368 0xD9D8, 0xE1DA, 0xE3E2, 0xE5E4, 0xE7E6, 0xE9E8, 0xF1EA, 0xF3F2,
369 0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA,
370 0xC4FF, 0xB500, 0x0011, 0x0102, 0x0402, 0x0304, 0x0704, 0x0405,
371 0x0004, 0x0201, 0x0077, 0x0201, 0x1103, 0x0504, 0x3121, 0x1206,
372 0x5141, 0x6107, 0x1371, 0x3222, 0x0881, 0x4214, 0xA191, 0xC1B1,
373 0x2309, 0x5233, 0x15F0, 0x7262, 0x0AD1, 0x2416, 0xE134, 0xF125,
374 0x1817, 0x1A19, 0x2726, 0x2928, 0x352A, 0x3736, 0x3938, 0x433A,
375 0x4544, 0x4746, 0x4948, 0x534A, 0x5554, 0x5756, 0x5958, 0x635A,
376 0x6564, 0x6766, 0x6968, 0x736A, 0x7574, 0x7776, 0x7978, 0x827A,
377 0x8483, 0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998,
378 0xA29A, 0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6,
379 0xB9B8, 0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4,
380 0xD7D6, 0xD9D8, 0xE2DA, 0xE4E3, 0xE6E5, 0xE8E7, 0xEAE9, 0xF3F2,
381 0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA,
382 0xC4FF, 0x1F00, 0x0000, 0x0501, 0x0101, 0x0101, 0x0101, 0x0000,
383 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09,
384 0xFF0B,
385 0xC4FF, 0x1F00, 0x0001, 0x0103, 0x0101, 0x0101, 0x0101, 0x0101,
386 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09,
387 0xFF0B
388 };
389
390 *length = ARRAY_SIZE(tables);
391 return tables;
392}
393
394/****************************************************************************/
395/* MCHIP low-level functions */
396/****************************************************************************/
397
398/* returns the horizontal capture size */
399static inline int mchip_hsize(void)
400{
401 return meye.params.subsample ? 320 : 640;
402}
403
404/* returns the vertical capture size */
405static inline int mchip_vsize(void)
406{
407 return meye.params.subsample ? 240 : 480;
408}
409
410/* waits for a register to be available */
411static void mchip_sync(int reg)
412{
413 u32 status;
414 int i;
415
416 if (reg == MCHIP_MM_FIFO_DATA) {
417 for (i = 0; i < MCHIP_REG_TIMEOUT; i++) {
418 status = readl(meye.mchip_mmregs +
419 MCHIP_MM_FIFO_STATUS);
420 if (!(status & MCHIP_MM_FIFO_WAIT)) {
421 printk(KERN_WARNING "meye: fifo not ready\n");
422 return;
423 }
424 if (status & MCHIP_MM_FIFO_READY)
425 return;
426 udelay(1);
427 }
428 } else if (reg > 0x80) {
429 u32 mask = (reg < 0x100) ? MCHIP_HIC_STATUS_MCC_RDY
430 : MCHIP_HIC_STATUS_VRJ_RDY;
431 for (i = 0; i < MCHIP_REG_TIMEOUT; i++) {
432 status = readl(meye.mchip_mmregs + MCHIP_HIC_STATUS);
433 if (status & mask)
434 return;
435 udelay(1);
436 }
437 } else
438 return;
439 printk(KERN_WARNING
440 "meye: mchip_sync() timeout on reg 0x%x status=0x%x\n",
441 reg, status);
442}
443
444/* sets a value into the register */
445static inline void mchip_set(int reg, u32 v)
446{
447 mchip_sync(reg);
448 writel(v, meye.mchip_mmregs + reg);
449}
450
451/* get the register value */
452static inline u32 mchip_read(int reg)
453{
454 mchip_sync(reg);
455 return readl(meye.mchip_mmregs + reg);
456}
457
458/* wait for a register to become a particular value */
459static inline int mchip_delay(u32 reg, u32 v)
460{
461 int n = 10;
462 while (--n && mchip_read(reg) != v)
463 udelay(1);
464 return n;
465}
466
467/* setup subsampling */
468static void mchip_subsample(void)
469{
470 mchip_set(MCHIP_MCC_R_SAMPLING, meye.params.subsample);
471 mchip_set(MCHIP_MCC_R_XRANGE, mchip_hsize());
472 mchip_set(MCHIP_MCC_R_YRANGE, mchip_vsize());
473 mchip_set(MCHIP_MCC_B_XRANGE, mchip_hsize());
474 mchip_set(MCHIP_MCC_B_YRANGE, mchip_vsize());
475 mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
476}
477
478/* set the framerate into the mchip */
479static void mchip_set_framerate(void)
480{
481 mchip_set(MCHIP_HIC_S_RATE, meye.params.framerate);
482}
483
484/* load some huffman and quantisation tables into the VRJ chip ready
485 for JPEG compression */
486static void mchip_load_tables(void)
487{
488 int i;
489 int length;
490 u16 *tables;
491
492 tables = jpeg_huffman_tables(&length);
493 for (i = 0; i < length; i++)
494 writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA);
495
496 tables = jpeg_quantisation_tables(&length, meye.params.quality);
497 for (i = 0; i < length; i++)
498 writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA);
499}
500
501/* setup the VRJ parameters in the chip */
502static void mchip_vrj_setup(u8 mode)
503{
504 mchip_set(MCHIP_VRJ_BUS_MODE, 5);
505 mchip_set(MCHIP_VRJ_SIGNAL_ACTIVE_LEVEL, 0x1f);
506 mchip_set(MCHIP_VRJ_PDAT_USE, 1);
507 mchip_set(MCHIP_VRJ_IRQ_FLAG, 0xa0);
508 mchip_set(MCHIP_VRJ_MODE_SPECIFY, mode);
509 mchip_set(MCHIP_VRJ_NUM_LINES, mchip_vsize());
510 mchip_set(MCHIP_VRJ_NUM_PIXELS, mchip_hsize());
511 mchip_set(MCHIP_VRJ_NUM_COMPONENTS, 0x1b);
512 mchip_set(MCHIP_VRJ_LIMIT_COMPRESSED_LO, 0xFFFF);
513 mchip_set(MCHIP_VRJ_LIMIT_COMPRESSED_HI, 0xFFFF);
514 mchip_set(MCHIP_VRJ_COMP_DATA_FORMAT, 0xC);
515 mchip_set(MCHIP_VRJ_RESTART_INTERVAL, 0);
516 mchip_set(MCHIP_VRJ_SOF1, 0x601);
517 mchip_set(MCHIP_VRJ_SOF2, 0x1502);
518 mchip_set(MCHIP_VRJ_SOF3, 0x1503);
519 mchip_set(MCHIP_VRJ_SOF4, 0x1596);
520 mchip_set(MCHIP_VRJ_SOS, 0x0ed0);
521
522 mchip_load_tables();
523}
524
525/* sets the DMA parameters into the chip */
526static void mchip_dma_setup(dma_addr_t dma_addr)
527{
528 int i;
529
530 mchip_set(MCHIP_MM_PT_ADDR, (u32)dma_addr);
531 for (i = 0; i < 4; i++)
532 mchip_set(MCHIP_MM_FIR(i), 0);
533 meye.mchip_fnum = 0;
534}
535
536/* setup for DMA transfers - also zeros the framebuffer */
537static int mchip_dma_alloc(void)
538{
539 if (!meye.mchip_dmahandle)
540 if (ptable_alloc())
541 return -1;
542 return 0;
543}
544
545/* frees the DMA buffer */
546static void mchip_dma_free(void)
547{
548 if (meye.mchip_dmahandle) {
549 mchip_dma_setup(0);
550 ptable_free();
551 }
552}
553
554/* stop any existing HIC action and wait for any dma to complete then
555 reset the dma engine */
556static void mchip_hic_stop(void)
557{
558 int i, j;
559
560 meye.mchip_mode = MCHIP_HIC_MODE_NOOP;
561 if (!(mchip_read(MCHIP_HIC_STATUS) & MCHIP_HIC_STATUS_BUSY))
562 return;
563 for (i = 0; i < 20; ++i) {
564 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_STOP);
565 mchip_delay(MCHIP_HIC_CMD, 0);
566 for (j = 0; j < 100; ++j) {
567 if (mchip_delay(MCHIP_HIC_STATUS,
568 MCHIP_HIC_STATUS_IDLE))
569 return;
570 msleep(1);
571 }
572 printk(KERN_ERR "meye: need to reset HIC!\n");
573
574 mchip_set(MCHIP_HIC_CTL, MCHIP_HIC_CTL_SOFT_RESET);
575 msleep(250);
576 }
577 printk(KERN_ERR "meye: resetting HIC hanged!\n");
578}
579
580/****************************************************************************/
581/* MCHIP frame processing functions */
582/****************************************************************************/
583
584/* get the next ready frame from the dma engine */
585static u32 mchip_get_frame(void)
586{
587 u32 v;
588
589 v = mchip_read(MCHIP_MM_FIR(meye.mchip_fnum));
590 return v;
591}
592
593/* frees the current frame from the dma engine */
594static void mchip_free_frame(void)
595{
596 mchip_set(MCHIP_MM_FIR(meye.mchip_fnum), 0);
597 meye.mchip_fnum++;
598 meye.mchip_fnum %= 4;
599}
600
601/* read one frame from the framebuffer assuming it was captured using
602 a uncompressed transfer */
603static void mchip_cont_read_frame(u32 v, u8 *buf, int size)
604{
605 int pt_id;
606
607 pt_id = (v >> 17) & 0x3FF;
608
609 ptable_copy(buf, pt_id, size, MCHIP_NB_PAGES);
610}
611
612/* read a compressed frame from the framebuffer */
613static int mchip_comp_read_frame(u32 v, u8 *buf, int size)
614{
615 int pt_start, pt_end, trailer;
616 int fsize;
617 int i;
618
619 pt_start = (v >> 19) & 0xFF;
620 pt_end = (v >> 11) & 0xFF;
621 trailer = (v >> 1) & 0x3FF;
622
623 if (pt_end < pt_start)
624 fsize = (MCHIP_NB_PAGES_MJPEG - pt_start) * PAGE_SIZE +
625 pt_end * PAGE_SIZE + trailer * 4;
626 else
627 fsize = (pt_end - pt_start) * PAGE_SIZE + trailer * 4;
628
629 if (fsize > size) {
630 printk(KERN_WARNING "meye: oversized compressed frame %d\n",
631 fsize);
632 return -1;
633 }
634
635 ptable_copy(buf, pt_start, fsize, MCHIP_NB_PAGES_MJPEG);
636
637#ifdef MEYE_JPEG_CORRECTION
638
639 /* Some mchip generated jpeg frames are incorrect. In most
640 * (all ?) of those cases, the final EOI (0xff 0xd9) marker
641 * is not present at the end of the frame.
642 *
643 * Since adding the final marker is not enough to restore
644 * the jpeg integrity, we drop the frame.
645 */
646
647 for (i = fsize - 1; i > 0 && buf[i] == 0xff; i--) ;
648
649 if (i < 2 || buf[i - 1] != 0xff || buf[i] != 0xd9)
650 return -1;
651
652#endif
653
654 return fsize;
655}
656
657/* take a picture into SDRAM */
658static void mchip_take_picture(void)
659{
660 int i;
661
662 mchip_hic_stop();
663 mchip_subsample();
664 mchip_dma_setup(meye.mchip_dmahandle);
665
666 mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_CAP);
667 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
668
669 mchip_delay(MCHIP_HIC_CMD, 0);
670
671 for (i = 0; i < 100; ++i) {
672 if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
673 break;
674 msleep(1);
675 }
676}
677
678/* dma a previously taken picture into a buffer */
679static void mchip_get_picture(u8 *buf, int bufsize)
680{
681 u32 v;
682 int i;
683
684 mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_OUT);
685 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
686
687 mchip_delay(MCHIP_HIC_CMD, 0);
688 for (i = 0; i < 100; ++i) {
689 if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
690 break;
691 msleep(1);
692 }
693 for (i = 0; i < 4; ++i) {
694 v = mchip_get_frame();
695 if (v & MCHIP_MM_FIR_RDY) {
696 mchip_cont_read_frame(v, buf, bufsize);
697 break;
698 }
699 mchip_free_frame();
700 }
701}
702
703/* start continuous dma capture */
704static void mchip_continuous_start(void)
705{
706 mchip_hic_stop();
707 mchip_subsample();
708 mchip_set_framerate();
709 mchip_dma_setup(meye.mchip_dmahandle);
710
711 meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
712
713 mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_CONT_OUT);
714 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
715
716 mchip_delay(MCHIP_HIC_CMD, 0);
717}
718
719/* compress one frame into a buffer */
720static int mchip_compress_frame(u8 *buf, int bufsize)
721{
722 u32 v;
723 int len = -1, i;
724
725 mchip_vrj_setup(0x3f);
726 udelay(50);
727
728 mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_COMP);
729 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
730
731 mchip_delay(MCHIP_HIC_CMD, 0);
732 for (i = 0; i < 100; ++i) {
733 if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
734 break;
735 msleep(1);
736 }
737
738 for (i = 0; i < 4; ++i) {
739 v = mchip_get_frame();
740 if (v & MCHIP_MM_FIR_RDY) {
741 len = mchip_comp_read_frame(v, buf, bufsize);
742 break;
743 }
744 mchip_free_frame();
745 }
746 return len;
747}
748
749#if 0
750/* uncompress one image into a buffer */
751static int mchip_uncompress_frame(u8 *img, int imgsize, u8 *buf, int bufsize)
752{
753 mchip_vrj_setup(0x3f);
754 udelay(50);
755
756 mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_DECOMP);
757 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
758
759 mchip_delay(MCHIP_HIC_CMD, 0);
760
761 return mchip_comp_read_frame(buf, bufsize);
762}
763#endif
764
765/* start continuous compressed capture */
766static void mchip_cont_compression_start(void)
767{
768 mchip_hic_stop();
769 mchip_vrj_setup(0x3f);
770 mchip_subsample();
771 mchip_set_framerate();
772 mchip_dma_setup(meye.mchip_dmahandle);
773
774 meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
775
776 mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_CONT_COMP);
777 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
778
779 mchip_delay(MCHIP_HIC_CMD, 0);
780}
781
782/****************************************************************************/
783/* Interrupt handling */
784/****************************************************************************/
785
David Howells7d12e782006-10-05 14:55:46 +0100786static irqreturn_t meye_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787{
788 u32 v;
789 int reqnr;
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300790 static int sequence;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
792 v = mchip_read(MCHIP_MM_INTA);
793
794 if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT &&
795 meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
796 return IRQ_NONE;
797
798again:
799 v = mchip_get_frame();
800 if (!(v & MCHIP_MM_FIR_RDY))
801 return IRQ_HANDLED;
802
803 if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) {
Stefani Seibold7acd72e2009-12-21 14:37:28 -0800804 if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr,
Stefani Seiboldc1e13f22009-12-21 14:37:27 -0800805 sizeof(int), &meye.grabq_lock) != sizeof(int)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 mchip_free_frame();
807 return IRQ_HANDLED;
808 }
809 mchip_cont_read_frame(v, meye.grab_fbuffer + gbufsize * reqnr,
810 mchip_hsize() * mchip_vsize() * 2);
811 meye.grab_buffer[reqnr].size = mchip_hsize() * mchip_vsize() * 2;
812 meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
813 do_gettimeofday(&meye.grab_buffer[reqnr].timestamp);
814 meye.grab_buffer[reqnr].sequence = sequence++;
Stefani Seibold7acd72e2009-12-21 14:37:28 -0800815 kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
Stefani Seiboldc1e13f22009-12-21 14:37:27 -0800816 sizeof(int), &meye.doneq_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 wake_up_interruptible(&meye.proc_list);
818 } else {
819 int size;
820 size = mchip_comp_read_frame(v, meye.grab_temp, gbufsize);
821 if (size == -1) {
822 mchip_free_frame();
823 goto again;
824 }
Stefani Seibold7acd72e2009-12-21 14:37:28 -0800825 if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr,
Stefani Seiboldc1e13f22009-12-21 14:37:27 -0800826 sizeof(int), &meye.grabq_lock) != sizeof(int)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 mchip_free_frame();
828 goto again;
829 }
830 memcpy(meye.grab_fbuffer + gbufsize * reqnr, meye.grab_temp,
831 size);
832 meye.grab_buffer[reqnr].size = size;
833 meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
834 do_gettimeofday(&meye.grab_buffer[reqnr].timestamp);
835 meye.grab_buffer[reqnr].sequence = sequence++;
Stefani Seibold7acd72e2009-12-21 14:37:28 -0800836 kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
Stefani Seiboldc1e13f22009-12-21 14:37:27 -0800837 sizeof(int), &meye.doneq_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 wake_up_interruptible(&meye.proc_list);
839 }
840 mchip_free_frame();
841 goto again;
842}
843
844/****************************************************************************/
845/* video4linux integration */
846/****************************************************************************/
847
Hans Verkuilbec43662008-12-30 06:58:20 -0300848static int meye_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849{
Hans Verkuil7d43cd52008-08-23 05:31:47 -0300850 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851
Hans Verkuil7d43cd52008-08-23 05:31:47 -0300852 if (test_and_set_bit(0, &meye.in_use))
853 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854
855 mchip_hic_stop();
856
857 if (mchip_dma_alloc()) {
858 printk(KERN_ERR "meye: mchip framebuffer allocation failed\n");
Hans Verkuil7d43cd52008-08-23 05:31:47 -0300859 clear_bit(0, &meye.in_use);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 return -ENOBUFS;
861 }
862
863 for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
864 meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
Stefani Seibold45465482009-12-21 14:37:26 -0800865 kfifo_reset(&meye.grabq);
866 kfifo_reset(&meye.doneq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 return 0;
868}
869
Hans Verkuilbec43662008-12-30 06:58:20 -0300870static int meye_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871{
872 mchip_hic_stop();
873 mchip_dma_free();
Hans Verkuil7d43cd52008-08-23 05:31:47 -0300874 clear_bit(0, &meye.in_use);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 return 0;
876}
877
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300878static int meyeioc_g_params(struct meye_params *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300880 *p = meye.params;
881 return 0;
882}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300884static int meyeioc_s_params(struct meye_params *jp)
885{
886 if (jp->subsample > 1)
887 return -EINVAL;
888
889 if (jp->quality > 10)
890 return -EINVAL;
891
892 if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
893 return -EINVAL;
894
895 if (jp->framerate > 31)
896 return -EINVAL;
897
898 mutex_lock(&meye.lock);
899
900 if (meye.params.subsample != jp->subsample ||
901 meye.params.quality != jp->quality)
902 mchip_hic_stop(); /* need restart */
903
904 meye.params = *jp;
905 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
906 meye.params.sharpness);
907 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
908 meye.params.agc);
909 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
910 meye.params.picture);
911 mutex_unlock(&meye.lock);
912
913 return 0;
914}
915
916static int meyeioc_qbuf_capt(int *nb)
917{
918 if (!meye.grab_fbuffer)
919 return -EINVAL;
920
921 if (*nb >= gbuffers)
922 return -EINVAL;
923
924 if (*nb < 0) {
925 /* stop capture */
926 mchip_hic_stop();
927 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 }
929
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300930 if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
931 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300933 mutex_lock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300935 if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
936 mchip_cont_compression_start();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300938 meye.grab_buffer[*nb].state = MEYE_BUF_USING;
Stefani Seibold7acd72e2009-12-21 14:37:28 -0800939 kfifo_in_locked(&meye.grabq, (unsigned char *)nb, sizeof(int),
Stefani Seiboldc1e13f22009-12-21 14:37:27 -0800940 &meye.grabq_lock);
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300941 mutex_unlock(&meye.lock);
942
943 return 0;
944}
945
946static int meyeioc_sync(struct file *file, void *fh, int *i)
947{
948 int unused;
949
950 if (*i < 0 || *i >= gbuffers)
951 return -EINVAL;
952
953 mutex_lock(&meye.lock);
954 switch (meye.grab_buffer[*i].state) {
955
956 case MEYE_BUF_UNUSED:
Ingo Molnar3593cab2006-02-07 06:49:14 -0200957 mutex_unlock(&meye.lock);
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300958 return -EINVAL;
959 case MEYE_BUF_USING:
960 if (file->f_flags & O_NONBLOCK) {
Ingo Molnar3593cab2006-02-07 06:49:14 -0200961 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 return -EAGAIN;
963 }
964 if (wait_event_interruptible(meye.proc_list,
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300965 (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
Ingo Molnar3593cab2006-02-07 06:49:14 -0200966 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 return -EINTR;
968 }
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300969 /* fall through */
970 case MEYE_BUF_DONE:
971 meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
Stefani Seibold9842c382009-12-21 14:37:29 -0800972 if (kfifo_out_locked(&meye.doneq, (unsigned char *)&unused,
973 sizeof(int), &meye.doneq_lock) != sizeof(int))
974 break;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300975 }
976 *i = meye.grab_buffer[*i].size;
977 mutex_unlock(&meye.lock);
978 return 0;
979}
980
981static int meyeioc_stillcapt(void)
982{
983 if (!meye.grab_fbuffer)
984 return -EINVAL;
985
986 if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
987 return -EBUSY;
988
989 mutex_lock(&meye.lock);
990 meye.grab_buffer[0].state = MEYE_BUF_USING;
991 mchip_take_picture();
992
993 mchip_get_picture(meye.grab_fbuffer,
994 mchip_hsize() * mchip_vsize() * 2);
995
996 meye.grab_buffer[0].state = MEYE_BUF_DONE;
997 mutex_unlock(&meye.lock);
998
999 return 0;
1000}
1001
1002static int meyeioc_stilljcapt(int *len)
1003{
1004 if (!meye.grab_fbuffer)
1005 return -EINVAL;
1006
1007 if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
1008 return -EBUSY;
1009
1010 mutex_lock(&meye.lock);
1011 meye.grab_buffer[0].state = MEYE_BUF_USING;
1012 *len = -1;
1013
1014 while (*len == -1) {
1015 mchip_take_picture();
1016 *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 }
1018
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001019 meye.grab_buffer[0].state = MEYE_BUF_DONE;
1020 mutex_unlock(&meye.lock);
1021 return 0;
1022}
1023
1024static int vidioc_querycap(struct file *file, void *fh,
1025 struct v4l2_capability *cap)
1026{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001027 strcpy(cap->driver, "meye");
1028 strcpy(cap->card, "meye");
1029 sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
1030
1031 cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
1032 MEYE_DRIVER_MINORVERSION;
1033
1034 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
1035 V4L2_CAP_STREAMING;
1036
1037 return 0;
1038}
1039
1040static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
1041{
1042 if (i->index != 0)
1043 return -EINVAL;
1044
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001045 strcpy(i->name, "Camera");
1046 i->type = V4L2_INPUT_TYPE_CAMERA;
1047
1048 return 0;
1049}
1050
1051static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
1052{
1053 *i = 0;
1054 return 0;
1055}
1056
1057static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
1058{
1059 if (i != 0)
1060 return -EINVAL;
1061
1062 return 0;
1063}
1064
1065static int vidioc_queryctrl(struct file *file, void *fh,
1066 struct v4l2_queryctrl *c)
1067{
1068 switch (c->id) {
1069
1070 case V4L2_CID_BRIGHTNESS:
1071 c->type = V4L2_CTRL_TYPE_INTEGER;
1072 strcpy(c->name, "Brightness");
1073 c->minimum = 0;
1074 c->maximum = 63;
1075 c->step = 1;
1076 c->default_value = 32;
1077 c->flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 break;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001079 case V4L2_CID_HUE:
1080 c->type = V4L2_CTRL_TYPE_INTEGER;
1081 strcpy(c->name, "Hue");
1082 c->minimum = 0;
1083 c->maximum = 63;
1084 c->step = 1;
1085 c->default_value = 32;
1086 c->flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 break;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001088 case V4L2_CID_CONTRAST:
1089 c->type = V4L2_CTRL_TYPE_INTEGER;
1090 strcpy(c->name, "Contrast");
1091 c->minimum = 0;
1092 c->maximum = 63;
1093 c->step = 1;
1094 c->default_value = 32;
1095 c->flags = 0;
1096 break;
1097 case V4L2_CID_SATURATION:
1098 c->type = V4L2_CTRL_TYPE_INTEGER;
1099 strcpy(c->name, "Saturation");
1100 c->minimum = 0;
1101 c->maximum = 63;
1102 c->step = 1;
1103 c->default_value = 32;
1104 c->flags = 0;
1105 break;
1106 case V4L2_CID_AGC:
1107 c->type = V4L2_CTRL_TYPE_INTEGER;
1108 strcpy(c->name, "Agc");
1109 c->minimum = 0;
1110 c->maximum = 63;
1111 c->step = 1;
1112 c->default_value = 48;
1113 c->flags = 0;
1114 break;
1115 case V4L2_CID_MEYE_SHARPNESS:
1116 case V4L2_CID_SHARPNESS:
1117 c->type = V4L2_CTRL_TYPE_INTEGER;
1118 strcpy(c->name, "Sharpness");
1119 c->minimum = 0;
1120 c->maximum = 63;
1121 c->step = 1;
1122 c->default_value = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001124 /* Continue to report legacy private SHARPNESS ctrl but
1125 * say it is disabled in preference to ctrl in the spec
1126 */
1127 c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 :
1128 V4L2_CTRL_FLAG_DISABLED;
1129 break;
1130 case V4L2_CID_PICTURE:
1131 c->type = V4L2_CTRL_TYPE_INTEGER;
1132 strcpy(c->name, "Picture");
1133 c->minimum = 0;
1134 c->maximum = 63;
1135 c->step = 1;
1136 c->default_value = 0;
1137 c->flags = 0;
1138 break;
1139 case V4L2_CID_JPEGQUAL:
1140 c->type = V4L2_CTRL_TYPE_INTEGER;
1141 strcpy(c->name, "JPEG quality");
1142 c->minimum = 0;
1143 c->maximum = 10;
1144 c->step = 1;
1145 c->default_value = 8;
1146 c->flags = 0;
1147 break;
1148 case V4L2_CID_FRAMERATE:
1149 c->type = V4L2_CTRL_TYPE_INTEGER;
1150 strcpy(c->name, "Framerate");
1151 c->minimum = 0;
1152 c->maximum = 31;
1153 c->step = 1;
1154 c->default_value = 0;
1155 c->flags = 0;
1156 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 default:
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001158 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 }
1160
1161 return 0;
1162}
1163
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001164static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001166 mutex_lock(&meye.lock);
1167 switch (c->id) {
1168 case V4L2_CID_BRIGHTNESS:
1169 sony_pic_camera_command(
1170 SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
1171 meye.picture.brightness = c->value << 10;
1172 break;
1173 case V4L2_CID_HUE:
1174 sony_pic_camera_command(
1175 SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
1176 meye.picture.hue = c->value << 10;
1177 break;
1178 case V4L2_CID_CONTRAST:
1179 sony_pic_camera_command(
1180 SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
1181 meye.picture.contrast = c->value << 10;
1182 break;
1183 case V4L2_CID_SATURATION:
1184 sony_pic_camera_command(
1185 SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
1186 meye.picture.colour = c->value << 10;
1187 break;
1188 case V4L2_CID_AGC:
1189 sony_pic_camera_command(
1190 SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
1191 meye.params.agc = c->value;
1192 break;
1193 case V4L2_CID_SHARPNESS:
1194 case V4L2_CID_MEYE_SHARPNESS:
1195 sony_pic_camera_command(
1196 SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
1197 meye.params.sharpness = c->value;
1198 break;
1199 case V4L2_CID_PICTURE:
1200 sony_pic_camera_command(
1201 SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
1202 meye.params.picture = c->value;
1203 break;
1204 case V4L2_CID_JPEGQUAL:
1205 meye.params.quality = c->value;
1206 break;
1207 case V4L2_CID_FRAMERATE:
1208 meye.params.framerate = c->value;
1209 break;
1210 default:
1211 mutex_unlock(&meye.lock);
1212 return -EINVAL;
1213 }
1214 mutex_unlock(&meye.lock);
1215
1216 return 0;
1217}
1218
1219static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
1220{
1221 mutex_lock(&meye.lock);
1222 switch (c->id) {
1223 case V4L2_CID_BRIGHTNESS:
1224 c->value = meye.picture.brightness >> 10;
1225 break;
1226 case V4L2_CID_HUE:
1227 c->value = meye.picture.hue >> 10;
1228 break;
1229 case V4L2_CID_CONTRAST:
1230 c->value = meye.picture.contrast >> 10;
1231 break;
1232 case V4L2_CID_SATURATION:
1233 c->value = meye.picture.colour >> 10;
1234 break;
1235 case V4L2_CID_AGC:
1236 c->value = meye.params.agc;
1237 break;
1238 case V4L2_CID_SHARPNESS:
1239 case V4L2_CID_MEYE_SHARPNESS:
1240 c->value = meye.params.sharpness;
1241 break;
1242 case V4L2_CID_PICTURE:
1243 c->value = meye.params.picture;
1244 break;
1245 case V4L2_CID_JPEGQUAL:
1246 c->value = meye.params.quality;
1247 break;
1248 case V4L2_CID_FRAMERATE:
1249 c->value = meye.params.framerate;
1250 break;
1251 default:
1252 mutex_unlock(&meye.lock);
1253 return -EINVAL;
1254 }
1255 mutex_unlock(&meye.lock);
1256
1257 return 0;
1258}
1259
Hans Verkuil78b526a2008-05-28 12:16:41 -03001260static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh,
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001261 struct v4l2_fmtdesc *f)
1262{
1263 if (f->index > 1)
1264 return -EINVAL;
1265
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001266 if (f->index == 0) {
1267 /* standard YUV 422 capture */
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001268 f->flags = 0;
1269 strcpy(f->description, "YUV422");
1270 f->pixelformat = V4L2_PIX_FMT_YUYV;
1271 } else {
1272 /* compressed MJPEG capture */
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001273 f->flags = V4L2_FMT_FLAG_COMPRESSED;
1274 strcpy(f->description, "MJPEG");
1275 f->pixelformat = V4L2_PIX_FMT_MJPEG;
1276 }
1277
1278 return 0;
1279}
1280
Hans Verkuil78b526a2008-05-28 12:16:41 -03001281static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001282 struct v4l2_format *f)
1283{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001284 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
1285 f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
1286 return -EINVAL;
1287
1288 if (f->fmt.pix.field != V4L2_FIELD_ANY &&
1289 f->fmt.pix.field != V4L2_FIELD_NONE)
1290 return -EINVAL;
1291
1292 f->fmt.pix.field = V4L2_FIELD_NONE;
1293
1294 if (f->fmt.pix.width <= 320) {
1295 f->fmt.pix.width = 320;
1296 f->fmt.pix.height = 240;
1297 } else {
1298 f->fmt.pix.width = 640;
1299 f->fmt.pix.height = 480;
1300 }
1301
1302 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
1303 f->fmt.pix.sizeimage = f->fmt.pix.height *
1304 f->fmt.pix.bytesperline;
1305 f->fmt.pix.colorspace = 0;
1306 f->fmt.pix.priv = 0;
1307
1308 return 0;
1309}
1310
Hans Verkuil78b526a2008-05-28 12:16:41 -03001311static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
1312 struct v4l2_format *f)
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001313{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001314 switch (meye.mchip_mode) {
1315 case MCHIP_HIC_MODE_CONT_OUT:
1316 default:
1317 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
1318 break;
1319 case MCHIP_HIC_MODE_CONT_COMP:
1320 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
1321 break;
1322 }
1323
1324 f->fmt.pix.field = V4L2_FIELD_NONE;
1325 f->fmt.pix.width = mchip_hsize();
1326 f->fmt.pix.height = mchip_vsize();
1327 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
1328 f->fmt.pix.sizeimage = f->fmt.pix.height *
1329 f->fmt.pix.bytesperline;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001330
1331 return 0;
1332}
1333
Hans Verkuil78b526a2008-05-28 12:16:41 -03001334static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
1335 struct v4l2_format *f)
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001336{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001337 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
1338 f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
1339 return -EINVAL;
1340
1341 if (f->fmt.pix.field != V4L2_FIELD_ANY &&
1342 f->fmt.pix.field != V4L2_FIELD_NONE)
1343 return -EINVAL;
1344
1345 f->fmt.pix.field = V4L2_FIELD_NONE;
1346 mutex_lock(&meye.lock);
1347
1348 if (f->fmt.pix.width <= 320) {
1349 f->fmt.pix.width = 320;
1350 f->fmt.pix.height = 240;
1351 meye.params.subsample = 1;
1352 } else {
1353 f->fmt.pix.width = 640;
1354 f->fmt.pix.height = 480;
1355 meye.params.subsample = 0;
1356 }
1357
1358 switch (f->fmt.pix.pixelformat) {
1359 case V4L2_PIX_FMT_YUYV:
1360 meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
1361 break;
1362 case V4L2_PIX_FMT_MJPEG:
1363 meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
1364 break;
1365 }
1366
1367 mutex_unlock(&meye.lock);
1368 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
1369 f->fmt.pix.sizeimage = f->fmt.pix.height *
1370 f->fmt.pix.bytesperline;
1371 f->fmt.pix.colorspace = 0;
1372 f->fmt.pix.priv = 0;
1373
1374 return 0;
1375}
1376
1377static int vidioc_reqbufs(struct file *file, void *fh,
1378 struct v4l2_requestbuffers *req)
1379{
1380 int i;
1381
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001382 if (req->memory != V4L2_MEMORY_MMAP)
1383 return -EINVAL;
1384
1385 if (meye.grab_fbuffer && req->count == gbuffers) {
1386 /* already allocated, no modifications */
1387 return 0;
1388 }
1389
1390 mutex_lock(&meye.lock);
1391 if (meye.grab_fbuffer) {
1392 for (i = 0; i < gbuffers; i++)
1393 if (meye.vma_use_count[i]) {
1394 mutex_unlock(&meye.lock);
1395 return -EINVAL;
1396 }
1397 rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
1398 meye.grab_fbuffer = NULL;
1399 }
1400
1401 gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
1402 req->count = gbuffers;
1403 meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
1404
1405 if (!meye.grab_fbuffer) {
1406 printk(KERN_ERR "meye: v4l framebuffer allocation"
1407 " failed\n");
1408 mutex_unlock(&meye.lock);
1409 return -ENOMEM;
1410 }
1411
1412 for (i = 0; i < gbuffers; i++)
1413 meye.vma_use_count[i] = 0;
1414
1415 mutex_unlock(&meye.lock);
1416
1417 return 0;
1418}
1419
1420static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
1421{
Trent Piepho61745232009-03-28 22:25:36 -03001422 unsigned int index = buf->index;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001423
Trent Piepho61745232009-03-28 22:25:36 -03001424 if (index >= gbuffers)
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001425 return -EINVAL;
1426
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001427 buf->bytesused = meye.grab_buffer[index].size;
1428 buf->flags = V4L2_BUF_FLAG_MAPPED;
1429
1430 if (meye.grab_buffer[index].state == MEYE_BUF_USING)
1431 buf->flags |= V4L2_BUF_FLAG_QUEUED;
1432
1433 if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
1434 buf->flags |= V4L2_BUF_FLAG_DONE;
1435
1436 buf->field = V4L2_FIELD_NONE;
1437 buf->timestamp = meye.grab_buffer[index].timestamp;
1438 buf->sequence = meye.grab_buffer[index].sequence;
1439 buf->memory = V4L2_MEMORY_MMAP;
1440 buf->m.offset = index * gbufsize;
1441 buf->length = gbufsize;
1442
1443 return 0;
1444}
1445
1446static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
1447{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001448 if (buf->memory != V4L2_MEMORY_MMAP)
1449 return -EINVAL;
1450
Trent Piepho61745232009-03-28 22:25:36 -03001451 if (buf->index >= gbuffers)
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001452 return -EINVAL;
1453
1454 if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
1455 return -EINVAL;
1456
1457 mutex_lock(&meye.lock);
1458 buf->flags |= V4L2_BUF_FLAG_QUEUED;
1459 buf->flags &= ~V4L2_BUF_FLAG_DONE;
1460 meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
Stefani Seibold7acd72e2009-12-21 14:37:28 -08001461 kfifo_in_locked(&meye.grabq, (unsigned char *)&buf->index,
Stefani Seiboldc1e13f22009-12-21 14:37:27 -08001462 sizeof(int), &meye.grabq_lock);
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001463 mutex_unlock(&meye.lock);
1464
1465 return 0;
1466}
1467
1468static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
1469{
1470 int reqnr;
1471
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001472 if (buf->memory != V4L2_MEMORY_MMAP)
1473 return -EINVAL;
1474
1475 mutex_lock(&meye.lock);
1476
Stefani Seibold45465482009-12-21 14:37:26 -08001477 if (kfifo_len(&meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001478 mutex_unlock(&meye.lock);
1479 return -EAGAIN;
1480 }
1481
1482 if (wait_event_interruptible(meye.proc_list,
Stefani Seibold45465482009-12-21 14:37:26 -08001483 kfifo_len(&meye.doneq) != 0) < 0) {
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001484 mutex_unlock(&meye.lock);
1485 return -EINTR;
1486 }
1487
Stefani Seibold7acd72e2009-12-21 14:37:28 -08001488 if (!kfifo_out_locked(&meye.doneq, (unsigned char *)&reqnr,
Stefani Seiboldc1e13f22009-12-21 14:37:27 -08001489 sizeof(int), &meye.doneq_lock)) {
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001490 mutex_unlock(&meye.lock);
1491 return -EBUSY;
1492 }
1493
1494 if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
1495 mutex_unlock(&meye.lock);
1496 return -EINVAL;
1497 }
1498
1499 buf->index = reqnr;
1500 buf->bytesused = meye.grab_buffer[reqnr].size;
1501 buf->flags = V4L2_BUF_FLAG_MAPPED;
1502 buf->field = V4L2_FIELD_NONE;
1503 buf->timestamp = meye.grab_buffer[reqnr].timestamp;
1504 buf->sequence = meye.grab_buffer[reqnr].sequence;
1505 buf->memory = V4L2_MEMORY_MMAP;
1506 buf->m.offset = reqnr * gbufsize;
1507 buf->length = gbufsize;
1508 meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
1509 mutex_unlock(&meye.lock);
1510
1511 return 0;
1512}
1513
1514static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
1515{
1516 mutex_lock(&meye.lock);
1517
1518 switch (meye.mchip_mode) {
1519 case MCHIP_HIC_MODE_CONT_OUT:
1520 mchip_continuous_start();
1521 break;
1522 case MCHIP_HIC_MODE_CONT_COMP:
1523 mchip_cont_compression_start();
1524 break;
1525 default:
1526 mutex_unlock(&meye.lock);
1527 return -EINVAL;
1528 }
1529
1530 mutex_unlock(&meye.lock);
1531
1532 return 0;
1533}
1534
1535static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
1536{
1537 mutex_lock(&meye.lock);
1538 mchip_hic_stop();
Stefani Seibold45465482009-12-21 14:37:26 -08001539 kfifo_reset(&meye.grabq);
1540 kfifo_reset(&meye.doneq);
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001541
1542 for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
1543 meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
1544
1545 mutex_unlock(&meye.lock);
1546 return 0;
1547}
1548
Hans Verkuil069b7472008-12-30 07:04:34 -03001549static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001550{
1551 switch (cmd) {
1552 case MEYEIOC_G_PARAMS:
1553 return meyeioc_g_params((struct meye_params *) arg);
1554
1555 case MEYEIOC_S_PARAMS:
1556 return meyeioc_s_params((struct meye_params *) arg);
1557
1558 case MEYEIOC_QBUF_CAPT:
1559 return meyeioc_qbuf_capt((int *) arg);
1560
1561 case MEYEIOC_SYNC:
1562 return meyeioc_sync(file, fh, (int *) arg);
1563
1564 case MEYEIOC_STILLCAPT:
1565 return meyeioc_stillcapt();
1566
1567 case MEYEIOC_STILLJCAPT:
1568 return meyeioc_stilljcapt((int *) arg);
1569
1570 default:
1571 return -EINVAL;
1572 }
1573
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574}
1575
1576static unsigned int meye_poll(struct file *file, poll_table *wait)
1577{
1578 unsigned int res = 0;
1579
Ingo Molnar3593cab2006-02-07 06:49:14 -02001580 mutex_lock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 poll_wait(file, &meye.proc_list, wait);
Stefani Seibold45465482009-12-21 14:37:26 -08001582 if (kfifo_len(&meye.doneq))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 res = POLLIN | POLLRDNORM;
Ingo Molnar3593cab2006-02-07 06:49:14 -02001584 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 return res;
1586}
1587
1588static void meye_vm_open(struct vm_area_struct *vma)
1589{
Mauro Carvalho Chehabd6144022006-05-19 13:08:09 -03001590 long idx = (long)vma->vm_private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 meye.vma_use_count[idx]++;
1592}
1593
1594static void meye_vm_close(struct vm_area_struct *vma)
1595{
Mauro Carvalho Chehabd6144022006-05-19 13:08:09 -03001596 long idx = (long)vma->vm_private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 meye.vma_use_count[idx]--;
1598}
1599
Alexey Dobriyanf0f37e22009-09-27 22:29:37 +04001600static const struct vm_operations_struct meye_vm_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 .open = meye_vm_open,
1602 .close = meye_vm_close,
1603};
1604
1605static int meye_mmap(struct file *file, struct vm_area_struct *vma)
1606{
1607 unsigned long start = vma->vm_start;
1608 unsigned long size = vma->vm_end - vma->vm_start;
1609 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
1610 unsigned long page, pos;
1611
Ingo Molnar3593cab2006-02-07 06:49:14 -02001612 mutex_lock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 if (size > gbuffers * gbufsize) {
Ingo Molnar3593cab2006-02-07 06:49:14 -02001614 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 return -EINVAL;
1616 }
1617 if (!meye.grab_fbuffer) {
1618 int i;
1619
1620 /* lazy allocation */
1621 meye.grab_fbuffer = rvmalloc(gbuffers*gbufsize);
1622 if (!meye.grab_fbuffer) {
1623 printk(KERN_ERR "meye: v4l framebuffer allocation failed\n");
Ingo Molnar3593cab2006-02-07 06:49:14 -02001624 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 return -ENOMEM;
1626 }
1627 for (i = 0; i < gbuffers; i++)
1628 meye.vma_use_count[i] = 0;
1629 }
1630 pos = (unsigned long)meye.grab_fbuffer + offset;
1631
1632 while (size > 0) {
1633 page = vmalloc_to_pfn((void *)pos);
1634 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
Ingo Molnar3593cab2006-02-07 06:49:14 -02001635 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 return -EAGAIN;
1637 }
1638 start += PAGE_SIZE;
1639 pos += PAGE_SIZE;
1640 if (size > PAGE_SIZE)
1641 size -= PAGE_SIZE;
1642 else
1643 size = 0;
1644 }
1645
1646 vma->vm_ops = &meye_vm_ops;
1647 vma->vm_flags &= ~VM_IO; /* not I/O memory */
1648 vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
1649 vma->vm_private_data = (void *) (offset / gbufsize);
1650 meye_vm_open(vma);
1651
Ingo Molnar3593cab2006-02-07 06:49:14 -02001652 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 return 0;
1654}
1655
Hans Verkuilbec43662008-12-30 06:58:20 -03001656static const struct v4l2_file_operations meye_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 .owner = THIS_MODULE,
1658 .open = meye_open,
1659 .release = meye_release,
1660 .mmap = meye_mmap,
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001661 .ioctl = video_ioctl2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 .poll = meye_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663};
1664
Hans Verkuila3998102008-07-21 02:57:38 -03001665static const struct v4l2_ioctl_ops meye_ioctl_ops = {
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001666 .vidioc_querycap = vidioc_querycap,
1667 .vidioc_enum_input = vidioc_enum_input,
1668 .vidioc_g_input = vidioc_g_input,
1669 .vidioc_s_input = vidioc_s_input,
1670 .vidioc_queryctrl = vidioc_queryctrl,
1671 .vidioc_s_ctrl = vidioc_s_ctrl,
1672 .vidioc_g_ctrl = vidioc_g_ctrl,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001673 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1674 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1675 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1676 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001677 .vidioc_reqbufs = vidioc_reqbufs,
1678 .vidioc_querybuf = vidioc_querybuf,
1679 .vidioc_qbuf = vidioc_qbuf,
1680 .vidioc_dqbuf = vidioc_dqbuf,
1681 .vidioc_streamon = vidioc_streamon,
1682 .vidioc_streamoff = vidioc_streamoff,
1683 .vidioc_default = vidioc_default,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684};
1685
Hans Verkuila3998102008-07-21 02:57:38 -03001686static struct video_device meye_template = {
Hans Verkuila3998102008-07-21 02:57:38 -03001687 .name = "meye",
Hans Verkuila3998102008-07-21 02:57:38 -03001688 .fops = &meye_fops,
1689 .ioctl_ops = &meye_ioctl_ops,
1690 .release = video_device_release,
Hans Verkuila3998102008-07-21 02:57:38 -03001691};
1692
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693#ifdef CONFIG_PM
Pavel Macheka2910682005-04-16 15:25:27 -07001694static int meye_suspend(struct pci_dev *pdev, pm_message_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695{
1696 pci_save_state(pdev);
1697 meye.pm_mchip_mode = meye.mchip_mode;
1698 mchip_hic_stop();
1699 mchip_set(MCHIP_MM_INTA, 0x0);
1700 return 0;
1701}
1702
1703static int meye_resume(struct pci_dev *pdev)
1704{
1705 pci_restore_state(pdev);
1706 pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1);
1707
1708 mchip_delay(MCHIP_HIC_CMD, 0);
1709 mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
1710 msleep(1);
1711 mchip_set(MCHIP_VRJ_SOFT_RESET, 1);
1712 msleep(1);
1713 mchip_set(MCHIP_MM_PCI_MODE, 5);
1714 msleep(1);
1715 mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
1716
1717 switch (meye.pm_mchip_mode) {
1718 case MCHIP_HIC_MODE_CONT_OUT:
1719 mchip_continuous_start();
1720 break;
1721 case MCHIP_HIC_MODE_CONT_COMP:
1722 mchip_cont_compression_start();
1723 break;
1724 }
1725 return 0;
1726}
1727#endif
1728
1729static int __devinit meye_probe(struct pci_dev *pcidev,
1730 const struct pci_device_id *ent)
1731{
1732 int ret = -EBUSY;
1733 unsigned long mchip_adr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734
1735 if (meye.mchip_dev != NULL) {
1736 printk(KERN_ERR "meye: only one device allowed!\n");
1737 goto outnotdev;
1738 }
1739
Henrik Kretzschmaref0e3c22008-08-22 17:13:05 -03001740 ret = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 meye.mchip_dev = pcidev;
1742 meye.video_dev = video_device_alloc();
1743 if (!meye.video_dev) {
1744 printk(KERN_ERR "meye: video_device_alloc() failed!\n");
1745 goto outnotdev;
1746 }
1747
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE);
1749 if (!meye.grab_temp) {
1750 printk(KERN_ERR "meye: grab buffer allocation failed\n");
1751 goto outvmalloc;
1752 }
1753
1754 spin_lock_init(&meye.grabq_lock);
Stefani Seiboldc1e13f22009-12-21 14:37:27 -08001755 if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS,
1756 GFP_KERNEL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 printk(KERN_ERR "meye: fifo allocation failed\n");
1758 goto outkfifoalloc1;
1759 }
1760 spin_lock_init(&meye.doneq_lock);
Stefani Seiboldc1e13f22009-12-21 14:37:27 -08001761 if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS,
1762 GFP_KERNEL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 printk(KERN_ERR "meye: fifo allocation failed\n");
1764 goto outkfifoalloc2;
1765 }
1766
1767 memcpy(meye.video_dev, &meye_template, sizeof(meye_template));
Hans Verkuil5e85e732008-07-20 06:31:39 -03001768 meye.video_dev->parent = &meye.mchip_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
Mauro Carvalho Chehab5b5aff82008-09-03 17:11:52 -03001770 ret = -EIO;
malattia@linux.itcbefb762007-04-28 23:36:26 +09001771 if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 printk(KERN_ERR "meye: unable to power on the camera\n");
1773 printk(KERN_ERR "meye: did you enable the camera in "
1774 "sonypi using the module options ?\n");
1775 goto outsonypienable;
1776 }
1777
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 if ((ret = pci_enable_device(meye.mchip_dev))) {
1779 printk(KERN_ERR "meye: pci_enable_device failed\n");
1780 goto outenabledev;
1781 }
1782
1783 mchip_adr = pci_resource_start(meye.mchip_dev,0);
1784 if (!mchip_adr) {
1785 printk(KERN_ERR "meye: mchip has no device base address\n");
1786 goto outregions;
1787 }
1788 if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0),
1789 pci_resource_len(meye.mchip_dev, 0),
1790 "meye")) {
1791 printk(KERN_ERR "meye: request_mem_region failed\n");
1792 goto outregions;
1793 }
1794 meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS);
1795 if (!meye.mchip_mmregs) {
1796 printk(KERN_ERR "meye: ioremap failed\n");
1797 goto outremap;
1798 }
1799
1800 meye.mchip_irq = pcidev->irq;
1801 if (request_irq(meye.mchip_irq, meye_irq,
Thomas Gleixner8076fe32006-07-01 19:29:37 -07001802 IRQF_DISABLED | IRQF_SHARED, "meye", meye_irq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 printk(KERN_ERR "meye: request_irq failed\n");
1804 goto outreqirq;
1805 }
1806
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 pci_write_config_byte(meye.mchip_dev, PCI_CACHE_LINE_SIZE, 8);
1808 pci_write_config_byte(meye.mchip_dev, PCI_LATENCY_TIMER, 64);
1809
1810 pci_set_master(meye.mchip_dev);
1811
1812 /* Ask the camera to perform a soft reset. */
1813 pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1);
1814
1815 mchip_delay(MCHIP_HIC_CMD, 0);
1816 mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
1817
1818 msleep(1);
1819 mchip_set(MCHIP_VRJ_SOFT_RESET, 1);
1820
1821 msleep(1);
1822 mchip_set(MCHIP_MM_PCI_MODE, 5);
1823
1824 msleep(1);
1825 mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
1826
1827 if (video_register_device(meye.video_dev, VFL_TYPE_GRABBER,
1828 video_nr) < 0) {
1829 printk(KERN_ERR "meye: video_register_device failed\n");
1830 goto outvideoreg;
1831 }
1832
Ingo Molnar3593cab2006-02-07 06:49:14 -02001833 mutex_init(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 init_waitqueue_head(&meye.proc_list);
1835 meye.picture.depth = 16;
1836 meye.picture.palette = VIDEO_PALETTE_YUV422;
1837 meye.picture.brightness = 32 << 10;
1838 meye.picture.hue = 32 << 10;
1839 meye.picture.colour = 32 << 10;
1840 meye.picture.contrast = 32 << 10;
1841 meye.picture.whiteness = 0;
1842 meye.params.subsample = 0;
1843 meye.params.quality = 8;
1844 meye.params.sharpness = 32;
1845 meye.params.agc = 48;
1846 meye.params.picture = 0;
1847 meye.params.framerate = 0;
1848
malattia@linux.itcbefb762007-04-28 23:36:26 +09001849 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, 32);
1850 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE, 32);
1851 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR, 32);
1852 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST, 32);
1853 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS, 32);
1854 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0);
1855 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856
1857 printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n",
1858 MEYE_DRIVER_VERSION);
1859 printk(KERN_INFO "meye: mchip KL5A72002 rev. %d, base %lx, irq %d\n",
Auke Kok44c10132007-06-08 15:46:36 -07001860 meye.mchip_dev->revision, mchip_adr, meye.mchip_irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861
1862 return 0;
1863
1864outvideoreg:
1865 free_irq(meye.mchip_irq, meye_irq);
1866outreqirq:
1867 iounmap(meye.mchip_mmregs);
1868outremap:
1869 release_mem_region(pci_resource_start(meye.mchip_dev, 0),
1870 pci_resource_len(meye.mchip_dev, 0));
1871outregions:
1872 pci_disable_device(meye.mchip_dev);
1873outenabledev:
malattia@linux.itcbefb762007-04-28 23:36:26 +09001874 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875outsonypienable:
Stefani Seibold45465482009-12-21 14:37:26 -08001876 kfifo_free(&meye.doneq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877outkfifoalloc2:
Stefani Seibold45465482009-12-21 14:37:26 -08001878 kfifo_free(&meye.grabq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879outkfifoalloc1:
1880 vfree(meye.grab_temp);
1881outvmalloc:
1882 video_device_release(meye.video_dev);
1883outnotdev:
1884 return ret;
1885}
1886
1887static void __devexit meye_remove(struct pci_dev *pcidev)
1888{
1889 video_unregister_device(meye.video_dev);
1890
1891 mchip_hic_stop();
1892
1893 mchip_dma_free();
1894
1895 /* disable interrupts */
1896 mchip_set(MCHIP_MM_INTA, 0x0);
1897
1898 free_irq(meye.mchip_irq, meye_irq);
1899
1900 iounmap(meye.mchip_mmregs);
1901
1902 release_mem_region(pci_resource_start(meye.mchip_dev, 0),
1903 pci_resource_len(meye.mchip_dev, 0));
1904
1905 pci_disable_device(meye.mchip_dev);
1906
malattia@linux.itcbefb762007-04-28 23:36:26 +09001907 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
Stefani Seibold45465482009-12-21 14:37:26 -08001909 kfifo_free(&meye.doneq);
1910 kfifo_free(&meye.grabq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911
1912 vfree(meye.grab_temp);
1913
1914 if (meye.grab_fbuffer) {
1915 rvfree(meye.grab_fbuffer, gbuffers*gbufsize);
1916 meye.grab_fbuffer = NULL;
1917 }
1918
1919 printk(KERN_INFO "meye: removed\n");
1920}
1921
1922static struct pci_device_id meye_pci_tbl[] = {
Joe Perches76e97412009-07-05 15:59:21 -03001923 { PCI_VDEVICE(KAWASAKI, PCI_DEVICE_ID_MCHIP_KL5A72002), 0 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 { }
1925};
1926
1927MODULE_DEVICE_TABLE(pci, meye_pci_tbl);
1928
1929static struct pci_driver meye_driver = {
1930 .name = "meye",
1931 .id_table = meye_pci_tbl,
1932 .probe = meye_probe,
1933 .remove = __devexit_p(meye_remove),
1934#ifdef CONFIG_PM
1935 .suspend = meye_suspend,
1936 .resume = meye_resume,
1937#endif
1938};
1939
1940static int __init meye_init(void)
1941{
1942 gbuffers = max(2, min((int)gbuffers, MEYE_MAX_BUFNBRS));
1943 if (gbufsize < 0 || gbufsize > MEYE_MAX_BUFSIZE)
1944 gbufsize = MEYE_MAX_BUFSIZE;
1945 gbufsize = PAGE_ALIGN(gbufsize);
Joe Perchesac9bb7f2007-11-20 09:00:35 -03001946 printk(KERN_INFO "meye: using %d buffers with %dk (%dk total) "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 "for capture\n",
1948 gbuffers,
1949 gbufsize / 1024, gbuffers * gbufsize / 1024);
1950 return pci_register_driver(&meye_driver);
1951}
1952
1953static void __exit meye_exit(void)
1954{
1955 pci_unregister_driver(&meye_driver);
1956}
1957
1958module_init(meye_init);
1959module_exit(meye_exit);