blob: 7859c43479d7b418c063e6b90510c09edbb893eb [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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090033#include <linux/gfp.h>
Hans Verkuil51270612010-03-22 05:22:34 -030034#include <linux/videodev2.h>
Mauro Carvalho Chehab5e87efa2006-06-05 10:26:32 -030035#include <media/v4l2-common.h>
Hans Verkuil51270612010-03-22 05:22:34 -030036#include <media/v4l2-device.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030037#include <media/v4l2-ioctl.h>
Hans Verkuiled986d12013-01-29 07:21:02 -030038#include <media/v4l2-fh.h>
39#include <media/v4l2-event.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <asm/uaccess.h>
41#include <asm/io.h>
42#include <linux/delay.h>
43#include <linux/interrupt.h>
44#include <linux/vmalloc.h>
Tobias Klauserd013a062005-09-06 15:17:07 -070045#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
47#include "meye.h"
48#include <linux/meye.h>
49
50MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -030051MODULE_DESCRIPTION("v4l2 driver for the MotionEye camera");
Linus Torvalds1da177e2005-04-16 15:20:36 -070052MODULE_LICENSE("GPL");
53MODULE_VERSION(MEYE_DRIVER_VERSION);
54
Linus Torvalds1da177e2005-04-16 15:20:36 -070055/* number of grab buffers */
56static unsigned int gbuffers = 2;
57module_param(gbuffers, int, 0444);
58MODULE_PARM_DESC(gbuffers, "number of capture buffers, default is 2 (32 max)");
59
60/* size of a grab buffer */
61static unsigned int gbufsize = MEYE_MAX_BUFSIZE;
62module_param(gbufsize, int, 0444);
63MODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 614400"
64 " (will be rounded up to a page multiple)");
65
66/* /dev/videoX registration number */
67static int video_nr = -1;
68module_param(video_nr, int, 0444);
69MODULE_PARM_DESC(video_nr, "video device to register (0=/dev/video0, etc)");
70
71/* driver structure - only one possible */
72static struct meye meye;
73
74/****************************************************************************/
75/* Memory allocation routines (stolen from bttv-driver.c) */
76/****************************************************************************/
77static void *rvmalloc(unsigned long size)
78{
79 void *mem;
80 unsigned long adr;
81
82 size = PAGE_ALIGN(size);
83 mem = vmalloc_32(size);
84 if (mem) {
85 memset(mem, 0, size);
86 adr = (unsigned long) mem;
87 while (size > 0) {
88 SetPageReserved(vmalloc_to_page((void *)adr));
89 adr += PAGE_SIZE;
90 size -= PAGE_SIZE;
91 }
92 }
93 return mem;
94}
95
96static void rvfree(void * mem, unsigned long size)
97{
98 unsigned long adr;
99
100 if (mem) {
101 adr = (unsigned long) mem;
102 while ((long) size > 0) {
103 ClearPageReserved(vmalloc_to_page((void *)adr));
104 adr += PAGE_SIZE;
105 size -= PAGE_SIZE;
106 }
107 vfree(mem);
108 }
109}
110
111/*
112 * return a page table pointing to N pages of locked memory
113 *
114 * NOTE: The meye device expects DMA addresses on 32 bits, we build
115 * a table of 1024 entries = 4 bytes * 1024 = 4096 bytes.
116 */
117static int ptable_alloc(void)
118{
119 u32 *pt;
120 int i;
121
122 memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
123
124 /* give only 32 bit DMA addresses */
Yang Hongyang284901a2009-04-06 19:01:15 -0700125 if (dma_set_mask(&meye.mchip_dev->dev, DMA_BIT_MASK(32)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 return -1;
127
128 meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev,
129 PAGE_SIZE,
130 &meye.mchip_dmahandle,
131 GFP_KERNEL);
132 if (!meye.mchip_ptable_toc) {
133 meye.mchip_dmahandle = 0;
134 return -1;
135 }
136
137 pt = meye.mchip_ptable_toc;
138 for (i = 0; i < MCHIP_NB_PAGES; i++) {
139 dma_addr_t dma;
140 meye.mchip_ptable[i] = dma_alloc_coherent(&meye.mchip_dev->dev,
141 PAGE_SIZE,
142 &dma,
143 GFP_KERNEL);
144 if (!meye.mchip_ptable[i]) {
145 int j;
146 pt = meye.mchip_ptable_toc;
147 for (j = 0; j < i; ++j) {
148 dma = (dma_addr_t) *pt;
149 dma_free_coherent(&meye.mchip_dev->dev,
150 PAGE_SIZE,
151 meye.mchip_ptable[j], dma);
152 pt++;
153 }
154 dma_free_coherent(&meye.mchip_dev->dev,
155 PAGE_SIZE,
156 meye.mchip_ptable_toc,
157 meye.mchip_dmahandle);
158 meye.mchip_ptable_toc = NULL;
159 meye.mchip_dmahandle = 0;
160 return -1;
161 }
162 *pt = (u32) dma;
163 pt++;
164 }
165 return 0;
166}
167
168static void ptable_free(void)
169{
170 u32 *pt;
171 int i;
172
173 pt = meye.mchip_ptable_toc;
174 for (i = 0; i < MCHIP_NB_PAGES; i++) {
175 dma_addr_t dma = (dma_addr_t) *pt;
176 if (meye.mchip_ptable[i])
177 dma_free_coherent(&meye.mchip_dev->dev,
178 PAGE_SIZE,
179 meye.mchip_ptable[i], dma);
180 pt++;
181 }
182
183 if (meye.mchip_ptable_toc)
184 dma_free_coherent(&meye.mchip_dev->dev,
185 PAGE_SIZE,
186 meye.mchip_ptable_toc,
187 meye.mchip_dmahandle);
188
189 memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
190 meye.mchip_ptable_toc = NULL;
191 meye.mchip_dmahandle = 0;
192}
193
194/* copy data from ptable into buf */
195static void ptable_copy(u8 *buf, int start, int size, int pt_pages)
196{
197 int i;
198
199 for (i = 0; i < (size / PAGE_SIZE) * PAGE_SIZE; i += PAGE_SIZE) {
200 memcpy(buf + i, meye.mchip_ptable[start++], PAGE_SIZE);
201 if (start >= pt_pages)
202 start = 0;
203 }
204 memcpy(buf + i, meye.mchip_ptable[start], size % PAGE_SIZE);
205}
206
207/****************************************************************************/
208/* JPEG tables at different qualities to load into the VRJ chip */
209/****************************************************************************/
210
211/* return a set of quantisation tables based on a quality from 1 to 10 */
212static u16 *jpeg_quantisation_tables(int *length, int quality)
213{
214 static u16 jpeg_tables[][70] = { {
215 0xdbff, 0x4300, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
216 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
217 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
218 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
219 0xffff, 0xffff, 0xffff,
220 0xdbff, 0x4300, 0xff01, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
221 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
222 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
223 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
224 0xffff, 0xffff, 0xffff,
225 },
226 {
227 0xdbff, 0x4300, 0x5000, 0x3c37, 0x3c46, 0x5032, 0x4146, 0x5a46,
228 0x5055, 0x785f, 0x82c8, 0x6e78, 0x786e, 0xaff5, 0x91b9, 0xffc8,
229 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
230 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
231 0xffff, 0xffff, 0xffff,
232 0xdbff, 0x4300, 0x5501, 0x5a5a, 0x6978, 0xeb78, 0x8282, 0xffeb,
233 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
234 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
235 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
236 0xffff, 0xffff, 0xffff,
237 },
238 {
239 0xdbff, 0x4300, 0x2800, 0x1e1c, 0x1e23, 0x2819, 0x2123, 0x2d23,
240 0x282b, 0x3c30, 0x4164, 0x373c, 0x3c37, 0x587b, 0x495d, 0x9164,
241 0x9980, 0x8f96, 0x8c80, 0xa08a, 0xe6b4, 0xa0c3, 0xdaaa, 0x8aad,
242 0xc88c, 0xcbff, 0xeeda, 0xfff5, 0xffff, 0xc19b, 0xffff, 0xfaff,
243 0xe6ff, 0xfffd, 0xfff8,
244 0xdbff, 0x4300, 0x2b01, 0x2d2d, 0x353c, 0x763c, 0x4141, 0xf876,
245 0x8ca5, 0xf8a5, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
246 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
247 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
248 0xf8f8, 0xf8f8, 0xfff8,
249 },
250 {
251 0xdbff, 0x4300, 0x1b00, 0x1412, 0x1417, 0x1b11, 0x1617, 0x1e17,
252 0x1b1c, 0x2820, 0x2b42, 0x2528, 0x2825, 0x3a51, 0x303d, 0x6042,
253 0x6555, 0x5f64, 0x5d55, 0x6a5b, 0x9978, 0x6a81, 0x9071, 0x5b73,
254 0x855d, 0x86b5, 0x9e90, 0xaba3, 0xabad, 0x8067, 0xc9bc, 0xa6ba,
255 0x99c7, 0xaba8, 0xffa4,
256 0xdbff, 0x4300, 0x1c01, 0x1e1e, 0x2328, 0x4e28, 0x2b2b, 0xa44e,
257 0x5d6e, 0xa46e, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
258 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
259 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
260 0xa4a4, 0xa4a4, 0xffa4,
261 },
262 {
263 0xdbff, 0x4300, 0x1400, 0x0f0e, 0x0f12, 0x140d, 0x1012, 0x1712,
264 0x1415, 0x1e18, 0x2132, 0x1c1e, 0x1e1c, 0x2c3d, 0x242e, 0x4932,
265 0x4c40, 0x474b, 0x4640, 0x5045, 0x735a, 0x5062, 0x6d55, 0x4556,
266 0x6446, 0x6588, 0x776d, 0x817b, 0x8182, 0x604e, 0x978d, 0x7d8c,
267 0x7396, 0x817e, 0xff7c,
268 0xdbff, 0x4300, 0x1501, 0x1717, 0x1a1e, 0x3b1e, 0x2121, 0x7c3b,
269 0x4653, 0x7c53, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
270 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
271 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
272 0x7c7c, 0x7c7c, 0xff7c,
273 },
274 {
275 0xdbff, 0x4300, 0x1000, 0x0c0b, 0x0c0e, 0x100a, 0x0d0e, 0x120e,
276 0x1011, 0x1813, 0x1a28, 0x1618, 0x1816, 0x2331, 0x1d25, 0x3a28,
277 0x3d33, 0x393c, 0x3833, 0x4037, 0x5c48, 0x404e, 0x5744, 0x3745,
278 0x5038, 0x516d, 0x5f57, 0x6762, 0x6768, 0x4d3e, 0x7971, 0x6470,
279 0x5c78, 0x6765, 0xff63,
280 0xdbff, 0x4300, 0x1101, 0x1212, 0x1518, 0x2f18, 0x1a1a, 0x632f,
281 0x3842, 0x6342, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
282 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
283 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
284 0x6363, 0x6363, 0xff63,
285 },
286 {
287 0xdbff, 0x4300, 0x0d00, 0x0a09, 0x0a0b, 0x0d08, 0x0a0b, 0x0e0b,
288 0x0d0e, 0x130f, 0x1520, 0x1213, 0x1312, 0x1c27, 0x171e, 0x2e20,
289 0x3129, 0x2e30, 0x2d29, 0x332c, 0x4a3a, 0x333e, 0x4636, 0x2c37,
290 0x402d, 0x4157, 0x4c46, 0x524e, 0x5253, 0x3e32, 0x615a, 0x505a,
291 0x4a60, 0x5251, 0xff4f,
292 0xdbff, 0x4300, 0x0e01, 0x0e0e, 0x1113, 0x2613, 0x1515, 0x4f26,
293 0x2d35, 0x4f35, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
294 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
295 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
296 0x4f4f, 0x4f4f, 0xff4f,
297 },
298 {
299 0xdbff, 0x4300, 0x0a00, 0x0707, 0x0708, 0x0a06, 0x0808, 0x0b08,
300 0x0a0a, 0x0e0b, 0x1018, 0x0d0e, 0x0e0d, 0x151d, 0x1116, 0x2318,
301 0x251f, 0x2224, 0x221f, 0x2621, 0x372b, 0x262f, 0x3429, 0x2129,
302 0x3022, 0x3141, 0x3934, 0x3e3b, 0x3e3e, 0x2e25, 0x4944, 0x3c43,
303 0x3748, 0x3e3d, 0xff3b,
304 0xdbff, 0x4300, 0x0a01, 0x0b0b, 0x0d0e, 0x1c0e, 0x1010, 0x3b1c,
305 0x2228, 0x3b28, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
306 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
307 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
308 0x3b3b, 0x3b3b, 0xff3b,
309 },
310 {
311 0xdbff, 0x4300, 0x0600, 0x0504, 0x0506, 0x0604, 0x0506, 0x0706,
312 0x0607, 0x0a08, 0x0a10, 0x090a, 0x0a09, 0x0e14, 0x0c0f, 0x1710,
313 0x1814, 0x1718, 0x1614, 0x1a16, 0x251d, 0x1a1f, 0x231b, 0x161c,
314 0x2016, 0x202c, 0x2623, 0x2927, 0x292a, 0x1f19, 0x302d, 0x282d,
315 0x2530, 0x2928, 0xff28,
316 0xdbff, 0x4300, 0x0701, 0x0707, 0x080a, 0x130a, 0x0a0a, 0x2813,
317 0x161a, 0x281a, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
318 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
319 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
320 0x2828, 0x2828, 0xff28,
321 },
322 {
323 0xdbff, 0x4300, 0x0300, 0x0202, 0x0203, 0x0302, 0x0303, 0x0403,
324 0x0303, 0x0504, 0x0508, 0x0405, 0x0504, 0x070a, 0x0607, 0x0c08,
325 0x0c0a, 0x0b0c, 0x0b0a, 0x0d0b, 0x120e, 0x0d10, 0x110e, 0x0b0e,
326 0x100b, 0x1016, 0x1311, 0x1514, 0x1515, 0x0f0c, 0x1817, 0x1416,
327 0x1218, 0x1514, 0xff14,
328 0xdbff, 0x4300, 0x0301, 0x0404, 0x0405, 0x0905, 0x0505, 0x1409,
329 0x0b0d, 0x140d, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
330 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
331 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
332 0x1414, 0x1414, 0xff14,
333 },
334 {
335 0xdbff, 0x4300, 0x0100, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
336 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
337 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
338 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
339 0x0101, 0x0101, 0xff01,
340 0xdbff, 0x4300, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
341 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
342 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
343 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
344 0x0101, 0x0101, 0xff01,
345 } };
346
347 if (quality < 0 || quality > 10) {
348 printk(KERN_WARNING
349 "meye: invalid quality level %d - using 8\n", quality);
350 quality = 8;
351 }
352
353 *length = ARRAY_SIZE(jpeg_tables[quality]);
354 return jpeg_tables[quality];
355}
356
357/* return a generic set of huffman tables */
358static u16 *jpeg_huffman_tables(int *length)
359{
360 static u16 tables[] = {
361 0xC4FF, 0xB500, 0x0010, 0x0102, 0x0303, 0x0402, 0x0503, 0x0405,
362 0x0004, 0x0100, 0x017D, 0x0302, 0x0400, 0x0511, 0x2112, 0x4131,
363 0x1306, 0x6151, 0x2207, 0x1471, 0x8132, 0xA191, 0x2308, 0xB142,
364 0x15C1, 0xD152, 0x24F0, 0x6233, 0x8272, 0x0A09, 0x1716, 0x1918,
365 0x251A, 0x2726, 0x2928, 0x342A, 0x3635, 0x3837, 0x3A39, 0x4443,
366 0x4645, 0x4847, 0x4A49, 0x5453, 0x5655, 0x5857, 0x5A59, 0x6463,
367 0x6665, 0x6867, 0x6A69, 0x7473, 0x7675, 0x7877, 0x7A79, 0x8483,
368 0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998, 0xA29A,
369 0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6, 0xB9B8,
370 0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4, 0xD7D6,
371 0xD9D8, 0xE1DA, 0xE3E2, 0xE5E4, 0xE7E6, 0xE9E8, 0xF1EA, 0xF3F2,
372 0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA,
373 0xC4FF, 0xB500, 0x0011, 0x0102, 0x0402, 0x0304, 0x0704, 0x0405,
374 0x0004, 0x0201, 0x0077, 0x0201, 0x1103, 0x0504, 0x3121, 0x1206,
375 0x5141, 0x6107, 0x1371, 0x3222, 0x0881, 0x4214, 0xA191, 0xC1B1,
376 0x2309, 0x5233, 0x15F0, 0x7262, 0x0AD1, 0x2416, 0xE134, 0xF125,
377 0x1817, 0x1A19, 0x2726, 0x2928, 0x352A, 0x3736, 0x3938, 0x433A,
378 0x4544, 0x4746, 0x4948, 0x534A, 0x5554, 0x5756, 0x5958, 0x635A,
379 0x6564, 0x6766, 0x6968, 0x736A, 0x7574, 0x7776, 0x7978, 0x827A,
380 0x8483, 0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998,
381 0xA29A, 0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6,
382 0xB9B8, 0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4,
383 0xD7D6, 0xD9D8, 0xE2DA, 0xE4E3, 0xE6E5, 0xE8E7, 0xEAE9, 0xF3F2,
384 0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA,
385 0xC4FF, 0x1F00, 0x0000, 0x0501, 0x0101, 0x0101, 0x0101, 0x0000,
386 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09,
387 0xFF0B,
388 0xC4FF, 0x1F00, 0x0001, 0x0103, 0x0101, 0x0101, 0x0101, 0x0101,
389 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09,
390 0xFF0B
391 };
392
393 *length = ARRAY_SIZE(tables);
394 return tables;
395}
396
397/****************************************************************************/
398/* MCHIP low-level functions */
399/****************************************************************************/
400
401/* returns the horizontal capture size */
402static inline int mchip_hsize(void)
403{
404 return meye.params.subsample ? 320 : 640;
405}
406
407/* returns the vertical capture size */
408static inline int mchip_vsize(void)
409{
410 return meye.params.subsample ? 240 : 480;
411}
412
413/* waits for a register to be available */
414static void mchip_sync(int reg)
415{
416 u32 status;
417 int i;
418
419 if (reg == MCHIP_MM_FIFO_DATA) {
420 for (i = 0; i < MCHIP_REG_TIMEOUT; i++) {
421 status = readl(meye.mchip_mmregs +
422 MCHIP_MM_FIFO_STATUS);
423 if (!(status & MCHIP_MM_FIFO_WAIT)) {
424 printk(KERN_WARNING "meye: fifo not ready\n");
425 return;
426 }
427 if (status & MCHIP_MM_FIFO_READY)
428 return;
429 udelay(1);
430 }
431 } else if (reg > 0x80) {
432 u32 mask = (reg < 0x100) ? MCHIP_HIC_STATUS_MCC_RDY
433 : MCHIP_HIC_STATUS_VRJ_RDY;
434 for (i = 0; i < MCHIP_REG_TIMEOUT; i++) {
435 status = readl(meye.mchip_mmregs + MCHIP_HIC_STATUS);
436 if (status & mask)
437 return;
438 udelay(1);
439 }
440 } else
441 return;
442 printk(KERN_WARNING
443 "meye: mchip_sync() timeout on reg 0x%x status=0x%x\n",
444 reg, status);
445}
446
447/* sets a value into the register */
448static inline void mchip_set(int reg, u32 v)
449{
450 mchip_sync(reg);
451 writel(v, meye.mchip_mmregs + reg);
452}
453
454/* get the register value */
455static inline u32 mchip_read(int reg)
456{
457 mchip_sync(reg);
458 return readl(meye.mchip_mmregs + reg);
459}
460
461/* wait for a register to become a particular value */
462static inline int mchip_delay(u32 reg, u32 v)
463{
464 int n = 10;
465 while (--n && mchip_read(reg) != v)
466 udelay(1);
467 return n;
468}
469
470/* setup subsampling */
471static void mchip_subsample(void)
472{
473 mchip_set(MCHIP_MCC_R_SAMPLING, meye.params.subsample);
474 mchip_set(MCHIP_MCC_R_XRANGE, mchip_hsize());
475 mchip_set(MCHIP_MCC_R_YRANGE, mchip_vsize());
476 mchip_set(MCHIP_MCC_B_XRANGE, mchip_hsize());
477 mchip_set(MCHIP_MCC_B_YRANGE, mchip_vsize());
478 mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
479}
480
481/* set the framerate into the mchip */
482static void mchip_set_framerate(void)
483{
484 mchip_set(MCHIP_HIC_S_RATE, meye.params.framerate);
485}
486
487/* load some huffman and quantisation tables into the VRJ chip ready
488 for JPEG compression */
489static void mchip_load_tables(void)
490{
491 int i;
492 int length;
493 u16 *tables;
494
495 tables = jpeg_huffman_tables(&length);
496 for (i = 0; i < length; i++)
497 writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA);
498
499 tables = jpeg_quantisation_tables(&length, meye.params.quality);
500 for (i = 0; i < length; i++)
501 writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA);
502}
503
504/* setup the VRJ parameters in the chip */
505static void mchip_vrj_setup(u8 mode)
506{
507 mchip_set(MCHIP_VRJ_BUS_MODE, 5);
508 mchip_set(MCHIP_VRJ_SIGNAL_ACTIVE_LEVEL, 0x1f);
509 mchip_set(MCHIP_VRJ_PDAT_USE, 1);
510 mchip_set(MCHIP_VRJ_IRQ_FLAG, 0xa0);
511 mchip_set(MCHIP_VRJ_MODE_SPECIFY, mode);
512 mchip_set(MCHIP_VRJ_NUM_LINES, mchip_vsize());
513 mchip_set(MCHIP_VRJ_NUM_PIXELS, mchip_hsize());
514 mchip_set(MCHIP_VRJ_NUM_COMPONENTS, 0x1b);
515 mchip_set(MCHIP_VRJ_LIMIT_COMPRESSED_LO, 0xFFFF);
516 mchip_set(MCHIP_VRJ_LIMIT_COMPRESSED_HI, 0xFFFF);
517 mchip_set(MCHIP_VRJ_COMP_DATA_FORMAT, 0xC);
518 mchip_set(MCHIP_VRJ_RESTART_INTERVAL, 0);
519 mchip_set(MCHIP_VRJ_SOF1, 0x601);
520 mchip_set(MCHIP_VRJ_SOF2, 0x1502);
521 mchip_set(MCHIP_VRJ_SOF3, 0x1503);
522 mchip_set(MCHIP_VRJ_SOF4, 0x1596);
523 mchip_set(MCHIP_VRJ_SOS, 0x0ed0);
524
525 mchip_load_tables();
526}
527
528/* sets the DMA parameters into the chip */
529static void mchip_dma_setup(dma_addr_t dma_addr)
530{
531 int i;
532
533 mchip_set(MCHIP_MM_PT_ADDR, (u32)dma_addr);
534 for (i = 0; i < 4; i++)
535 mchip_set(MCHIP_MM_FIR(i), 0);
536 meye.mchip_fnum = 0;
537}
538
539/* setup for DMA transfers - also zeros the framebuffer */
540static int mchip_dma_alloc(void)
541{
542 if (!meye.mchip_dmahandle)
543 if (ptable_alloc())
544 return -1;
545 return 0;
546}
547
548/* frees the DMA buffer */
549static void mchip_dma_free(void)
550{
551 if (meye.mchip_dmahandle) {
552 mchip_dma_setup(0);
553 ptable_free();
554 }
555}
556
557/* stop any existing HIC action and wait for any dma to complete then
558 reset the dma engine */
559static void mchip_hic_stop(void)
560{
561 int i, j;
562
563 meye.mchip_mode = MCHIP_HIC_MODE_NOOP;
564 if (!(mchip_read(MCHIP_HIC_STATUS) & MCHIP_HIC_STATUS_BUSY))
565 return;
566 for (i = 0; i < 20; ++i) {
567 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_STOP);
568 mchip_delay(MCHIP_HIC_CMD, 0);
569 for (j = 0; j < 100; ++j) {
570 if (mchip_delay(MCHIP_HIC_STATUS,
571 MCHIP_HIC_STATUS_IDLE))
572 return;
573 msleep(1);
574 }
575 printk(KERN_ERR "meye: need to reset HIC!\n");
576
577 mchip_set(MCHIP_HIC_CTL, MCHIP_HIC_CTL_SOFT_RESET);
578 msleep(250);
579 }
580 printk(KERN_ERR "meye: resetting HIC hanged!\n");
581}
582
583/****************************************************************************/
584/* MCHIP frame processing functions */
585/****************************************************************************/
586
587/* get the next ready frame from the dma engine */
588static u32 mchip_get_frame(void)
589{
590 u32 v;
591
592 v = mchip_read(MCHIP_MM_FIR(meye.mchip_fnum));
593 return v;
594}
595
596/* frees the current frame from the dma engine */
597static void mchip_free_frame(void)
598{
599 mchip_set(MCHIP_MM_FIR(meye.mchip_fnum), 0);
600 meye.mchip_fnum++;
601 meye.mchip_fnum %= 4;
602}
603
604/* read one frame from the framebuffer assuming it was captured using
605 a uncompressed transfer */
606static void mchip_cont_read_frame(u32 v, u8 *buf, int size)
607{
608 int pt_id;
609
610 pt_id = (v >> 17) & 0x3FF;
611
612 ptable_copy(buf, pt_id, size, MCHIP_NB_PAGES);
613}
614
615/* read a compressed frame from the framebuffer */
616static int mchip_comp_read_frame(u32 v, u8 *buf, int size)
617{
618 int pt_start, pt_end, trailer;
619 int fsize;
620 int i;
621
622 pt_start = (v >> 19) & 0xFF;
623 pt_end = (v >> 11) & 0xFF;
624 trailer = (v >> 1) & 0x3FF;
625
626 if (pt_end < pt_start)
627 fsize = (MCHIP_NB_PAGES_MJPEG - pt_start) * PAGE_SIZE +
628 pt_end * PAGE_SIZE + trailer * 4;
629 else
630 fsize = (pt_end - pt_start) * PAGE_SIZE + trailer * 4;
631
632 if (fsize > size) {
633 printk(KERN_WARNING "meye: oversized compressed frame %d\n",
634 fsize);
635 return -1;
636 }
637
638 ptable_copy(buf, pt_start, fsize, MCHIP_NB_PAGES_MJPEG);
639
640#ifdef MEYE_JPEG_CORRECTION
641
642 /* Some mchip generated jpeg frames are incorrect. In most
643 * (all ?) of those cases, the final EOI (0xff 0xd9) marker
644 * is not present at the end of the frame.
645 *
646 * Since adding the final marker is not enough to restore
647 * the jpeg integrity, we drop the frame.
648 */
649
650 for (i = fsize - 1; i > 0 && buf[i] == 0xff; i--) ;
651
652 if (i < 2 || buf[i - 1] != 0xff || buf[i] != 0xd9)
653 return -1;
654
655#endif
656
657 return fsize;
658}
659
660/* take a picture into SDRAM */
661static void mchip_take_picture(void)
662{
663 int i;
664
665 mchip_hic_stop();
666 mchip_subsample();
667 mchip_dma_setup(meye.mchip_dmahandle);
668
669 mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_CAP);
670 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
671
672 mchip_delay(MCHIP_HIC_CMD, 0);
673
674 for (i = 0; i < 100; ++i) {
675 if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
676 break;
677 msleep(1);
678 }
679}
680
681/* dma a previously taken picture into a buffer */
682static void mchip_get_picture(u8 *buf, int bufsize)
683{
684 u32 v;
685 int i;
686
687 mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_OUT);
688 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
689
690 mchip_delay(MCHIP_HIC_CMD, 0);
691 for (i = 0; i < 100; ++i) {
692 if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
693 break;
694 msleep(1);
695 }
696 for (i = 0; i < 4; ++i) {
697 v = mchip_get_frame();
698 if (v & MCHIP_MM_FIR_RDY) {
699 mchip_cont_read_frame(v, buf, bufsize);
700 break;
701 }
702 mchip_free_frame();
703 }
704}
705
706/* start continuous dma capture */
707static void mchip_continuous_start(void)
708{
709 mchip_hic_stop();
710 mchip_subsample();
711 mchip_set_framerate();
712 mchip_dma_setup(meye.mchip_dmahandle);
713
714 meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
715
716 mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_CONT_OUT);
717 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
718
719 mchip_delay(MCHIP_HIC_CMD, 0);
720}
721
722/* compress one frame into a buffer */
723static int mchip_compress_frame(u8 *buf, int bufsize)
724{
725 u32 v;
726 int len = -1, i;
727
728 mchip_vrj_setup(0x3f);
729 udelay(50);
730
731 mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_COMP);
732 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
733
734 mchip_delay(MCHIP_HIC_CMD, 0);
735 for (i = 0; i < 100; ++i) {
736 if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
737 break;
738 msleep(1);
739 }
740
741 for (i = 0; i < 4; ++i) {
742 v = mchip_get_frame();
743 if (v & MCHIP_MM_FIR_RDY) {
744 len = mchip_comp_read_frame(v, buf, bufsize);
745 break;
746 }
747 mchip_free_frame();
748 }
749 return len;
750}
751
752#if 0
753/* uncompress one image into a buffer */
754static int mchip_uncompress_frame(u8 *img, int imgsize, u8 *buf, int bufsize)
755{
756 mchip_vrj_setup(0x3f);
757 udelay(50);
758
759 mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_DECOMP);
760 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
761
762 mchip_delay(MCHIP_HIC_CMD, 0);
763
764 return mchip_comp_read_frame(buf, bufsize);
765}
766#endif
767
768/* start continuous compressed capture */
769static void mchip_cont_compression_start(void)
770{
771 mchip_hic_stop();
772 mchip_vrj_setup(0x3f);
773 mchip_subsample();
774 mchip_set_framerate();
775 mchip_dma_setup(meye.mchip_dmahandle);
776
777 meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
778
779 mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_CONT_COMP);
780 mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
781
782 mchip_delay(MCHIP_HIC_CMD, 0);
783}
784
785/****************************************************************************/
786/* Interrupt handling */
787/****************************************************************************/
788
David Howells7d12e782006-10-05 14:55:46 +0100789static irqreturn_t meye_irq(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790{
791 u32 v;
792 int reqnr;
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300793 static int sequence;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
795 v = mchip_read(MCHIP_MM_INTA);
796
797 if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT &&
798 meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
799 return IRQ_NONE;
800
801again:
802 v = mchip_get_frame();
803 if (!(v & MCHIP_MM_FIR_RDY))
804 return IRQ_HANDLED;
805
806 if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) {
Stefani Seibold7acd72e2009-12-21 14:37:28 -0800807 if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr,
Stefani Seiboldc1e13f22009-12-21 14:37:27 -0800808 sizeof(int), &meye.grabq_lock) != sizeof(int)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 mchip_free_frame();
810 return IRQ_HANDLED;
811 }
812 mchip_cont_read_frame(v, meye.grab_fbuffer + gbufsize * reqnr,
813 mchip_hsize() * mchip_vsize() * 2);
814 meye.grab_buffer[reqnr].size = mchip_hsize() * mchip_vsize() * 2;
815 meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300816 v4l2_get_timestamp(&meye.grab_buffer[reqnr].timestamp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 meye.grab_buffer[reqnr].sequence = sequence++;
Stefani Seibold7acd72e2009-12-21 14:37:28 -0800818 kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
Stefani Seiboldc1e13f22009-12-21 14:37:27 -0800819 sizeof(int), &meye.doneq_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 wake_up_interruptible(&meye.proc_list);
821 } else {
822 int size;
823 size = mchip_comp_read_frame(v, meye.grab_temp, gbufsize);
824 if (size == -1) {
825 mchip_free_frame();
826 goto again;
827 }
Stefani Seibold7acd72e2009-12-21 14:37:28 -0800828 if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr,
Stefani Seiboldc1e13f22009-12-21 14:37:27 -0800829 sizeof(int), &meye.grabq_lock) != sizeof(int)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 mchip_free_frame();
831 goto again;
832 }
833 memcpy(meye.grab_fbuffer + gbufsize * reqnr, meye.grab_temp,
834 size);
835 meye.grab_buffer[reqnr].size = size;
836 meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
Sakari Ailus8e6057b2012-09-15 15:14:42 -0300837 v4l2_get_timestamp(&meye.grab_buffer[reqnr].timestamp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 meye.grab_buffer[reqnr].sequence = sequence++;
Stefani Seibold7acd72e2009-12-21 14:37:28 -0800839 kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
Stefani Seiboldc1e13f22009-12-21 14:37:27 -0800840 sizeof(int), &meye.doneq_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 wake_up_interruptible(&meye.proc_list);
842 }
843 mchip_free_frame();
844 goto again;
845}
846
847/****************************************************************************/
848/* video4linux integration */
849/****************************************************************************/
850
Hans Verkuilbec43662008-12-30 06:58:20 -0300851static int meye_open(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852{
Hans Verkuil7d43cd52008-08-23 05:31:47 -0300853 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854
Hans Verkuil7d43cd52008-08-23 05:31:47 -0300855 if (test_and_set_bit(0, &meye.in_use))
856 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
858 mchip_hic_stop();
859
860 if (mchip_dma_alloc()) {
861 printk(KERN_ERR "meye: mchip framebuffer allocation failed\n");
Hans Verkuil7d43cd52008-08-23 05:31:47 -0300862 clear_bit(0, &meye.in_use);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 return -ENOBUFS;
864 }
865
866 for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
867 meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
Stefani Seibold45465482009-12-21 14:37:26 -0800868 kfifo_reset(&meye.grabq);
869 kfifo_reset(&meye.doneq);
Hans Verkuiled986d12013-01-29 07:21:02 -0300870 return v4l2_fh_open(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871}
872
Hans Verkuilbec43662008-12-30 06:58:20 -0300873static int meye_release(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874{
875 mchip_hic_stop();
876 mchip_dma_free();
Hans Verkuil7d43cd52008-08-23 05:31:47 -0300877 clear_bit(0, &meye.in_use);
Hans Verkuiled986d12013-01-29 07:21:02 -0300878 return v4l2_fh_release(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879}
880
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300881static int meyeioc_g_params(struct meye_params *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300883 *p = meye.params;
884 return 0;
885}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300887static int meyeioc_s_params(struct meye_params *jp)
888{
889 if (jp->subsample > 1)
890 return -EINVAL;
891
892 if (jp->quality > 10)
893 return -EINVAL;
894
895 if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
896 return -EINVAL;
897
898 if (jp->framerate > 31)
899 return -EINVAL;
900
901 mutex_lock(&meye.lock);
902
903 if (meye.params.subsample != jp->subsample ||
904 meye.params.quality != jp->quality)
905 mchip_hic_stop(); /* need restart */
906
907 meye.params = *jp;
908 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
909 meye.params.sharpness);
910 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
911 meye.params.agc);
912 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
913 meye.params.picture);
914 mutex_unlock(&meye.lock);
915
916 return 0;
917}
918
919static int meyeioc_qbuf_capt(int *nb)
920{
921 if (!meye.grab_fbuffer)
922 return -EINVAL;
923
924 if (*nb >= gbuffers)
925 return -EINVAL;
926
927 if (*nb < 0) {
928 /* stop capture */
929 mchip_hic_stop();
930 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 }
932
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300933 if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
934 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300936 mutex_lock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300938 if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
939 mchip_cont_compression_start();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300941 meye.grab_buffer[*nb].state = MEYE_BUF_USING;
Stefani Seibold7acd72e2009-12-21 14:37:28 -0800942 kfifo_in_locked(&meye.grabq, (unsigned char *)nb, sizeof(int),
Stefani Seiboldc1e13f22009-12-21 14:37:27 -0800943 &meye.grabq_lock);
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300944 mutex_unlock(&meye.lock);
945
946 return 0;
947}
948
949static int meyeioc_sync(struct file *file, void *fh, int *i)
950{
951 int unused;
952
953 if (*i < 0 || *i >= gbuffers)
954 return -EINVAL;
955
956 mutex_lock(&meye.lock);
957 switch (meye.grab_buffer[*i].state) {
958
959 case MEYE_BUF_UNUSED:
Ingo Molnar3593cab2006-02-07 06:49:14 -0200960 mutex_unlock(&meye.lock);
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300961 return -EINVAL;
962 case MEYE_BUF_USING:
963 if (file->f_flags & O_NONBLOCK) {
Ingo Molnar3593cab2006-02-07 06:49:14 -0200964 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 return -EAGAIN;
966 }
967 if (wait_event_interruptible(meye.proc_list,
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300968 (meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
Ingo Molnar3593cab2006-02-07 06:49:14 -0200969 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 return -EINTR;
971 }
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300972 /* fall through */
973 case MEYE_BUF_DONE:
974 meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
Stefani Seibold9842c382009-12-21 14:37:29 -0800975 if (kfifo_out_locked(&meye.doneq, (unsigned char *)&unused,
976 sizeof(int), &meye.doneq_lock) != sizeof(int))
977 break;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -0300978 }
979 *i = meye.grab_buffer[*i].size;
980 mutex_unlock(&meye.lock);
981 return 0;
982}
983
984static int meyeioc_stillcapt(void)
985{
986 if (!meye.grab_fbuffer)
987 return -EINVAL;
988
989 if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
990 return -EBUSY;
991
992 mutex_lock(&meye.lock);
993 meye.grab_buffer[0].state = MEYE_BUF_USING;
994 mchip_take_picture();
995
996 mchip_get_picture(meye.grab_fbuffer,
997 mchip_hsize() * mchip_vsize() * 2);
998
999 meye.grab_buffer[0].state = MEYE_BUF_DONE;
1000 mutex_unlock(&meye.lock);
1001
1002 return 0;
1003}
1004
1005static int meyeioc_stilljcapt(int *len)
1006{
1007 if (!meye.grab_fbuffer)
1008 return -EINVAL;
1009
1010 if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
1011 return -EBUSY;
1012
1013 mutex_lock(&meye.lock);
1014 meye.grab_buffer[0].state = MEYE_BUF_USING;
1015 *len = -1;
1016
1017 while (*len == -1) {
1018 mchip_take_picture();
1019 *len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 }
1021
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001022 meye.grab_buffer[0].state = MEYE_BUF_DONE;
1023 mutex_unlock(&meye.lock);
1024 return 0;
1025}
1026
1027static int vidioc_querycap(struct file *file, void *fh,
1028 struct v4l2_capability *cap)
1029{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001030 strcpy(cap->driver, "meye");
1031 strcpy(cap->card, "meye");
1032 sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
1033
1034 cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
1035 MEYE_DRIVER_MINORVERSION;
1036
Hans Verkuiled986d12013-01-29 07:21:02 -03001037 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001038 V4L2_CAP_STREAMING;
Hans Verkuiled986d12013-01-29 07:21:02 -03001039 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001040
1041 return 0;
1042}
1043
1044static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
1045{
1046 if (i->index != 0)
1047 return -EINVAL;
1048
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001049 strcpy(i->name, "Camera");
1050 i->type = V4L2_INPUT_TYPE_CAMERA;
1051
1052 return 0;
1053}
1054
1055static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
1056{
1057 *i = 0;
1058 return 0;
1059}
1060
1061static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
1062{
1063 if (i != 0)
1064 return -EINVAL;
1065
1066 return 0;
1067}
1068
Hans Verkuiled986d12013-01-29 07:21:02 -03001069static int meye_s_ctrl(struct v4l2_ctrl *ctrl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001071 mutex_lock(&meye.lock);
Hans Verkuiled986d12013-01-29 07:21:02 -03001072 switch (ctrl->id) {
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001073 case V4L2_CID_BRIGHTNESS:
1074 sony_pic_camera_command(
Hans Verkuiled986d12013-01-29 07:21:02 -03001075 SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, ctrl->val);
1076 meye.brightness = ctrl->val << 10;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001077 break;
1078 case V4L2_CID_HUE:
1079 sony_pic_camera_command(
Hans Verkuiled986d12013-01-29 07:21:02 -03001080 SONY_PIC_COMMAND_SETCAMERAHUE, ctrl->val);
1081 meye.hue = ctrl->val << 10;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001082 break;
1083 case V4L2_CID_CONTRAST:
1084 sony_pic_camera_command(
Hans Verkuiled986d12013-01-29 07:21:02 -03001085 SONY_PIC_COMMAND_SETCAMERACONTRAST, ctrl->val);
1086 meye.contrast = ctrl->val << 10;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001087 break;
1088 case V4L2_CID_SATURATION:
1089 sony_pic_camera_command(
Hans Verkuiled986d12013-01-29 07:21:02 -03001090 SONY_PIC_COMMAND_SETCAMERACOLOR, ctrl->val);
1091 meye.colour = ctrl->val << 10;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001092 break;
Hans Verkuiled986d12013-01-29 07:21:02 -03001093 case V4L2_CID_MEYE_AGC:
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001094 sony_pic_camera_command(
Hans Verkuiled986d12013-01-29 07:21:02 -03001095 SONY_PIC_COMMAND_SETCAMERAAGC, ctrl->val);
1096 meye.params.agc = ctrl->val;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001097 break;
1098 case V4L2_CID_SHARPNESS:
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001099 sony_pic_camera_command(
Hans Verkuiled986d12013-01-29 07:21:02 -03001100 SONY_PIC_COMMAND_SETCAMERASHARPNESS, ctrl->val);
1101 meye.params.sharpness = ctrl->val;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001102 break;
Hans Verkuiled986d12013-01-29 07:21:02 -03001103 case V4L2_CID_MEYE_PICTURE:
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001104 sony_pic_camera_command(
Hans Verkuiled986d12013-01-29 07:21:02 -03001105 SONY_PIC_COMMAND_SETCAMERAPICTURE, ctrl->val);
1106 meye.params.picture = ctrl->val;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001107 break;
Hans Verkuiled986d12013-01-29 07:21:02 -03001108 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
1109 meye.params.quality = ctrl->val;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001110 break;
Hans Verkuiled986d12013-01-29 07:21:02 -03001111 case V4L2_CID_MEYE_FRAMERATE:
1112 meye.params.framerate = ctrl->val;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001113 break;
1114 default:
1115 mutex_unlock(&meye.lock);
1116 return -EINVAL;
1117 }
1118 mutex_unlock(&meye.lock);
1119
1120 return 0;
1121}
1122
Hans Verkuil78b526a2008-05-28 12:16:41 -03001123static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh,
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001124 struct v4l2_fmtdesc *f)
1125{
1126 if (f->index > 1)
1127 return -EINVAL;
1128
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001129 if (f->index == 0) {
1130 /* standard YUV 422 capture */
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001131 f->flags = 0;
1132 strcpy(f->description, "YUV422");
1133 f->pixelformat = V4L2_PIX_FMT_YUYV;
1134 } else {
1135 /* compressed MJPEG capture */
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001136 f->flags = V4L2_FMT_FLAG_COMPRESSED;
1137 strcpy(f->description, "MJPEG");
1138 f->pixelformat = V4L2_PIX_FMT_MJPEG;
1139 }
1140
1141 return 0;
1142}
1143
Hans Verkuil78b526a2008-05-28 12:16:41 -03001144static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001145 struct v4l2_format *f)
1146{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001147 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
1148 f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
1149 return -EINVAL;
1150
1151 if (f->fmt.pix.field != V4L2_FIELD_ANY &&
1152 f->fmt.pix.field != V4L2_FIELD_NONE)
1153 return -EINVAL;
1154
1155 f->fmt.pix.field = V4L2_FIELD_NONE;
1156
1157 if (f->fmt.pix.width <= 320) {
1158 f->fmt.pix.width = 320;
1159 f->fmt.pix.height = 240;
1160 } else {
1161 f->fmt.pix.width = 640;
1162 f->fmt.pix.height = 480;
1163 }
1164
1165 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
1166 f->fmt.pix.sizeimage = f->fmt.pix.height *
1167 f->fmt.pix.bytesperline;
1168 f->fmt.pix.colorspace = 0;
1169 f->fmt.pix.priv = 0;
1170
1171 return 0;
1172}
1173
Hans Verkuil78b526a2008-05-28 12:16:41 -03001174static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
1175 struct v4l2_format *f)
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001176{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001177 switch (meye.mchip_mode) {
1178 case MCHIP_HIC_MODE_CONT_OUT:
1179 default:
1180 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
1181 break;
1182 case MCHIP_HIC_MODE_CONT_COMP:
1183 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
1184 break;
1185 }
1186
1187 f->fmt.pix.field = V4L2_FIELD_NONE;
1188 f->fmt.pix.width = mchip_hsize();
1189 f->fmt.pix.height = mchip_vsize();
1190 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
1191 f->fmt.pix.sizeimage = f->fmt.pix.height *
1192 f->fmt.pix.bytesperline;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001193
1194 return 0;
1195}
1196
Hans Verkuil78b526a2008-05-28 12:16:41 -03001197static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
1198 struct v4l2_format *f)
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001199{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001200 if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
1201 f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
1202 return -EINVAL;
1203
1204 if (f->fmt.pix.field != V4L2_FIELD_ANY &&
1205 f->fmt.pix.field != V4L2_FIELD_NONE)
1206 return -EINVAL;
1207
1208 f->fmt.pix.field = V4L2_FIELD_NONE;
1209 mutex_lock(&meye.lock);
1210
1211 if (f->fmt.pix.width <= 320) {
1212 f->fmt.pix.width = 320;
1213 f->fmt.pix.height = 240;
1214 meye.params.subsample = 1;
1215 } else {
1216 f->fmt.pix.width = 640;
1217 f->fmt.pix.height = 480;
1218 meye.params.subsample = 0;
1219 }
1220
1221 switch (f->fmt.pix.pixelformat) {
1222 case V4L2_PIX_FMT_YUYV:
1223 meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
1224 break;
1225 case V4L2_PIX_FMT_MJPEG:
1226 meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
1227 break;
1228 }
1229
1230 mutex_unlock(&meye.lock);
1231 f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
1232 f->fmt.pix.sizeimage = f->fmt.pix.height *
1233 f->fmt.pix.bytesperline;
1234 f->fmt.pix.colorspace = 0;
1235 f->fmt.pix.priv = 0;
1236
1237 return 0;
1238}
1239
1240static int vidioc_reqbufs(struct file *file, void *fh,
1241 struct v4l2_requestbuffers *req)
1242{
1243 int i;
1244
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001245 if (req->memory != V4L2_MEMORY_MMAP)
1246 return -EINVAL;
1247
1248 if (meye.grab_fbuffer && req->count == gbuffers) {
1249 /* already allocated, no modifications */
1250 return 0;
1251 }
1252
1253 mutex_lock(&meye.lock);
1254 if (meye.grab_fbuffer) {
1255 for (i = 0; i < gbuffers; i++)
1256 if (meye.vma_use_count[i]) {
1257 mutex_unlock(&meye.lock);
1258 return -EINVAL;
1259 }
1260 rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
1261 meye.grab_fbuffer = NULL;
1262 }
1263
1264 gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
1265 req->count = gbuffers;
1266 meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
1267
1268 if (!meye.grab_fbuffer) {
1269 printk(KERN_ERR "meye: v4l framebuffer allocation"
1270 " failed\n");
1271 mutex_unlock(&meye.lock);
1272 return -ENOMEM;
1273 }
1274
1275 for (i = 0; i < gbuffers; i++)
1276 meye.vma_use_count[i] = 0;
1277
1278 mutex_unlock(&meye.lock);
1279
1280 return 0;
1281}
1282
1283static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
1284{
Trent Piepho61745232009-03-28 22:25:36 -03001285 unsigned int index = buf->index;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001286
Trent Piepho61745232009-03-28 22:25:36 -03001287 if (index >= gbuffers)
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001288 return -EINVAL;
1289
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001290 buf->bytesused = meye.grab_buffer[index].size;
Sakari Ailus1b18e7a2012-10-22 17:10:16 -03001291 buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001292
1293 if (meye.grab_buffer[index].state == MEYE_BUF_USING)
1294 buf->flags |= V4L2_BUF_FLAG_QUEUED;
1295
1296 if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
1297 buf->flags |= V4L2_BUF_FLAG_DONE;
1298
1299 buf->field = V4L2_FIELD_NONE;
1300 buf->timestamp = meye.grab_buffer[index].timestamp;
1301 buf->sequence = meye.grab_buffer[index].sequence;
1302 buf->memory = V4L2_MEMORY_MMAP;
1303 buf->m.offset = index * gbufsize;
1304 buf->length = gbufsize;
1305
1306 return 0;
1307}
1308
1309static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
1310{
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001311 if (buf->memory != V4L2_MEMORY_MMAP)
1312 return -EINVAL;
1313
Trent Piepho61745232009-03-28 22:25:36 -03001314 if (buf->index >= gbuffers)
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001315 return -EINVAL;
1316
1317 if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
1318 return -EINVAL;
1319
1320 mutex_lock(&meye.lock);
1321 buf->flags |= V4L2_BUF_FLAG_QUEUED;
1322 buf->flags &= ~V4L2_BUF_FLAG_DONE;
1323 meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
Stefani Seibold7acd72e2009-12-21 14:37:28 -08001324 kfifo_in_locked(&meye.grabq, (unsigned char *)&buf->index,
Stefani Seiboldc1e13f22009-12-21 14:37:27 -08001325 sizeof(int), &meye.grabq_lock);
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001326 mutex_unlock(&meye.lock);
1327
1328 return 0;
1329}
1330
1331static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
1332{
1333 int reqnr;
1334
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001335 if (buf->memory != V4L2_MEMORY_MMAP)
1336 return -EINVAL;
1337
1338 mutex_lock(&meye.lock);
1339
Stefani Seibold45465482009-12-21 14:37:26 -08001340 if (kfifo_len(&meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001341 mutex_unlock(&meye.lock);
1342 return -EAGAIN;
1343 }
1344
1345 if (wait_event_interruptible(meye.proc_list,
Stefani Seibold45465482009-12-21 14:37:26 -08001346 kfifo_len(&meye.doneq) != 0) < 0) {
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001347 mutex_unlock(&meye.lock);
1348 return -EINTR;
1349 }
1350
Stefani Seibold7acd72e2009-12-21 14:37:28 -08001351 if (!kfifo_out_locked(&meye.doneq, (unsigned char *)&reqnr,
Stefani Seiboldc1e13f22009-12-21 14:37:27 -08001352 sizeof(int), &meye.doneq_lock)) {
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001353 mutex_unlock(&meye.lock);
1354 return -EBUSY;
1355 }
1356
1357 if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
1358 mutex_unlock(&meye.lock);
1359 return -EINVAL;
1360 }
1361
1362 buf->index = reqnr;
1363 buf->bytesused = meye.grab_buffer[reqnr].size;
Sakari Ailus1b18e7a2012-10-22 17:10:16 -03001364 buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001365 buf->field = V4L2_FIELD_NONE;
1366 buf->timestamp = meye.grab_buffer[reqnr].timestamp;
1367 buf->sequence = meye.grab_buffer[reqnr].sequence;
1368 buf->memory = V4L2_MEMORY_MMAP;
1369 buf->m.offset = reqnr * gbufsize;
1370 buf->length = gbufsize;
1371 meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
1372 mutex_unlock(&meye.lock);
1373
1374 return 0;
1375}
1376
1377static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
1378{
1379 mutex_lock(&meye.lock);
1380
1381 switch (meye.mchip_mode) {
1382 case MCHIP_HIC_MODE_CONT_OUT:
1383 mchip_continuous_start();
1384 break;
1385 case MCHIP_HIC_MODE_CONT_COMP:
1386 mchip_cont_compression_start();
1387 break;
1388 default:
1389 mutex_unlock(&meye.lock);
1390 return -EINVAL;
1391 }
1392
1393 mutex_unlock(&meye.lock);
1394
1395 return 0;
1396}
1397
1398static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
1399{
1400 mutex_lock(&meye.lock);
1401 mchip_hic_stop();
Stefani Seibold45465482009-12-21 14:37:26 -08001402 kfifo_reset(&meye.grabq);
1403 kfifo_reset(&meye.doneq);
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001404
1405 for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
1406 meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
1407
1408 mutex_unlock(&meye.lock);
1409 return 0;
1410}
1411
Hans Verkuil99cd47bc2011-03-11 19:00:56 -03001412static long vidioc_default(struct file *file, void *fh, bool valid_prio,
1413 int cmd, void *arg)
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001414{
1415 switch (cmd) {
1416 case MEYEIOC_G_PARAMS:
1417 return meyeioc_g_params((struct meye_params *) arg);
1418
1419 case MEYEIOC_S_PARAMS:
1420 return meyeioc_s_params((struct meye_params *) arg);
1421
1422 case MEYEIOC_QBUF_CAPT:
1423 return meyeioc_qbuf_capt((int *) arg);
1424
1425 case MEYEIOC_SYNC:
1426 return meyeioc_sync(file, fh, (int *) arg);
1427
1428 case MEYEIOC_STILLCAPT:
1429 return meyeioc_stillcapt();
1430
1431 case MEYEIOC_STILLJCAPT:
1432 return meyeioc_stilljcapt((int *) arg);
1433
1434 default:
Hans Verkuild1c754a2012-04-19 12:36:03 -03001435 return -ENOTTY;
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001436 }
1437
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438}
1439
1440static unsigned int meye_poll(struct file *file, poll_table *wait)
1441{
Hans Verkuiled986d12013-01-29 07:21:02 -03001442 unsigned int res = v4l2_ctrl_poll(file, wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
Ingo Molnar3593cab2006-02-07 06:49:14 -02001444 mutex_lock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 poll_wait(file, &meye.proc_list, wait);
Stefani Seibold45465482009-12-21 14:37:26 -08001446 if (kfifo_len(&meye.doneq))
Hans Verkuiled986d12013-01-29 07:21:02 -03001447 res |= POLLIN | POLLRDNORM;
Ingo Molnar3593cab2006-02-07 06:49:14 -02001448 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 return res;
1450}
1451
1452static void meye_vm_open(struct vm_area_struct *vma)
1453{
Mauro Carvalho Chehabd6144022006-05-19 13:08:09 -03001454 long idx = (long)vma->vm_private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 meye.vma_use_count[idx]++;
1456}
1457
1458static void meye_vm_close(struct vm_area_struct *vma)
1459{
Mauro Carvalho Chehabd6144022006-05-19 13:08:09 -03001460 long idx = (long)vma->vm_private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 meye.vma_use_count[idx]--;
1462}
1463
Alexey Dobriyanf0f37e22009-09-27 22:29:37 +04001464static const struct vm_operations_struct meye_vm_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 .open = meye_vm_open,
1466 .close = meye_vm_close,
1467};
1468
1469static int meye_mmap(struct file *file, struct vm_area_struct *vma)
1470{
1471 unsigned long start = vma->vm_start;
1472 unsigned long size = vma->vm_end - vma->vm_start;
1473 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
1474 unsigned long page, pos;
1475
Ingo Molnar3593cab2006-02-07 06:49:14 -02001476 mutex_lock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 if (size > gbuffers * gbufsize) {
Ingo Molnar3593cab2006-02-07 06:49:14 -02001478 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 return -EINVAL;
1480 }
1481 if (!meye.grab_fbuffer) {
1482 int i;
1483
1484 /* lazy allocation */
1485 meye.grab_fbuffer = rvmalloc(gbuffers*gbufsize);
1486 if (!meye.grab_fbuffer) {
1487 printk(KERN_ERR "meye: v4l framebuffer allocation failed\n");
Ingo Molnar3593cab2006-02-07 06:49:14 -02001488 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 return -ENOMEM;
1490 }
1491 for (i = 0; i < gbuffers; i++)
1492 meye.vma_use_count[i] = 0;
1493 }
1494 pos = (unsigned long)meye.grab_fbuffer + offset;
1495
1496 while (size > 0) {
1497 page = vmalloc_to_pfn((void *)pos);
1498 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
Ingo Molnar3593cab2006-02-07 06:49:14 -02001499 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 return -EAGAIN;
1501 }
1502 start += PAGE_SIZE;
1503 pos += PAGE_SIZE;
1504 if (size > PAGE_SIZE)
1505 size -= PAGE_SIZE;
1506 else
1507 size = 0;
1508 }
1509
1510 vma->vm_ops = &meye_vm_ops;
1511 vma->vm_flags &= ~VM_IO; /* not I/O memory */
Konstantin Khlebnikov314e51b2012-10-08 16:29:02 -07001512 vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 vma->vm_private_data = (void *) (offset / gbufsize);
1514 meye_vm_open(vma);
1515
Ingo Molnar3593cab2006-02-07 06:49:14 -02001516 mutex_unlock(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 return 0;
1518}
1519
Hans Verkuilbec43662008-12-30 06:58:20 -03001520static const struct v4l2_file_operations meye_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 .owner = THIS_MODULE,
1522 .open = meye_open,
1523 .release = meye_release,
1524 .mmap = meye_mmap,
Hans Verkuil61df3c92010-11-14 10:09:38 -03001525 .unlocked_ioctl = video_ioctl2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 .poll = meye_poll,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527};
1528
Hans Verkuila3998102008-07-21 02:57:38 -03001529static const struct v4l2_ioctl_ops meye_ioctl_ops = {
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001530 .vidioc_querycap = vidioc_querycap,
1531 .vidioc_enum_input = vidioc_enum_input,
1532 .vidioc_g_input = vidioc_g_input,
1533 .vidioc_s_input = vidioc_s_input,
Hans Verkuil78b526a2008-05-28 12:16:41 -03001534 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1535 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1536 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1537 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001538 .vidioc_reqbufs = vidioc_reqbufs,
1539 .vidioc_querybuf = vidioc_querybuf,
1540 .vidioc_qbuf = vidioc_qbuf,
1541 .vidioc_dqbuf = vidioc_dqbuf,
1542 .vidioc_streamon = vidioc_streamon,
1543 .vidioc_streamoff = vidioc_streamoff,
Hans Verkuiled986d12013-01-29 07:21:02 -03001544 .vidioc_log_status = v4l2_ctrl_log_status,
1545 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1546 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
Douglas Schilling Landgraf6ec6e0c2008-04-10 02:07:14 -03001547 .vidioc_default = vidioc_default,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548};
1549
Hans Verkuila3998102008-07-21 02:57:38 -03001550static struct video_device meye_template = {
Hans Verkuila3998102008-07-21 02:57:38 -03001551 .name = "meye",
Hans Verkuila3998102008-07-21 02:57:38 -03001552 .fops = &meye_fops,
1553 .ioctl_ops = &meye_ioctl_ops,
1554 .release = video_device_release,
Hans Verkuila3998102008-07-21 02:57:38 -03001555};
1556
Hans Verkuiled986d12013-01-29 07:21:02 -03001557static const struct v4l2_ctrl_ops meye_ctrl_ops = {
1558 .s_ctrl = meye_s_ctrl,
1559};
1560
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561#ifdef CONFIG_PM
Pavel Macheka2910682005-04-16 15:25:27 -07001562static int meye_suspend(struct pci_dev *pdev, pm_message_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563{
1564 pci_save_state(pdev);
1565 meye.pm_mchip_mode = meye.mchip_mode;
1566 mchip_hic_stop();
1567 mchip_set(MCHIP_MM_INTA, 0x0);
1568 return 0;
1569}
1570
1571static int meye_resume(struct pci_dev *pdev)
1572{
1573 pci_restore_state(pdev);
1574 pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1);
1575
1576 mchip_delay(MCHIP_HIC_CMD, 0);
1577 mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
1578 msleep(1);
1579 mchip_set(MCHIP_VRJ_SOFT_RESET, 1);
1580 msleep(1);
1581 mchip_set(MCHIP_MM_PCI_MODE, 5);
1582 msleep(1);
1583 mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
1584
1585 switch (meye.pm_mchip_mode) {
1586 case MCHIP_HIC_MODE_CONT_OUT:
1587 mchip_continuous_start();
1588 break;
1589 case MCHIP_HIC_MODE_CONT_COMP:
1590 mchip_cont_compression_start();
1591 break;
1592 }
1593 return 0;
1594}
1595#endif
1596
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08001597static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598{
Hans Verkuiled986d12013-01-29 07:21:02 -03001599 static const struct v4l2_ctrl_config ctrl_agc = {
1600 .id = V4L2_CID_MEYE_AGC,
1601 .type = V4L2_CTRL_TYPE_INTEGER,
1602 .ops = &meye_ctrl_ops,
1603 .name = "AGC",
1604 .max = 63,
1605 .step = 1,
1606 .def = 48,
1607 .flags = V4L2_CTRL_FLAG_SLIDER,
1608 };
1609 static const struct v4l2_ctrl_config ctrl_picture = {
1610 .id = V4L2_CID_MEYE_PICTURE,
1611 .type = V4L2_CTRL_TYPE_INTEGER,
1612 .ops = &meye_ctrl_ops,
1613 .name = "Picture",
1614 .max = 63,
1615 .step = 1,
1616 };
1617 static const struct v4l2_ctrl_config ctrl_framerate = {
1618 .id = V4L2_CID_MEYE_FRAMERATE,
1619 .type = V4L2_CTRL_TYPE_INTEGER,
1620 .ops = &meye_ctrl_ops,
1621 .name = "Framerate",
1622 .max = 31,
1623 .step = 1,
1624 };
Hans Verkuil51270612010-03-22 05:22:34 -03001625 struct v4l2_device *v4l2_dev = &meye.v4l2_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 int ret = -EBUSY;
1627 unsigned long mchip_adr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628
1629 if (meye.mchip_dev != NULL) {
1630 printk(KERN_ERR "meye: only one device allowed!\n");
1631 goto outnotdev;
1632 }
1633
Hans Verkuil51270612010-03-22 05:22:34 -03001634 ret = v4l2_device_register(&pcidev->dev, v4l2_dev);
1635 if (ret < 0) {
1636 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
1637 return ret;
1638 }
Henrik Kretzschmaref0e3c22008-08-22 17:13:05 -03001639 ret = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 meye.mchip_dev = pcidev;
Hans Verkuil51270612010-03-22 05:22:34 -03001641 meye.vdev = video_device_alloc();
1642 if (!meye.vdev) {
1643 v4l2_err(v4l2_dev, "video_device_alloc() failed!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 goto outnotdev;
1645 }
1646
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE);
1648 if (!meye.grab_temp) {
Hans Verkuil51270612010-03-22 05:22:34 -03001649 v4l2_err(v4l2_dev, "grab buffer allocation failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 goto outvmalloc;
1651 }
1652
1653 spin_lock_init(&meye.grabq_lock);
Stefani Seiboldc1e13f22009-12-21 14:37:27 -08001654 if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS,
1655 GFP_KERNEL)) {
Hans Verkuil51270612010-03-22 05:22:34 -03001656 v4l2_err(v4l2_dev, "fifo allocation failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 goto outkfifoalloc1;
1658 }
1659 spin_lock_init(&meye.doneq_lock);
Stefani Seiboldc1e13f22009-12-21 14:37:27 -08001660 if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS,
1661 GFP_KERNEL)) {
Hans Verkuil51270612010-03-22 05:22:34 -03001662 v4l2_err(v4l2_dev, "fifo allocation failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 goto outkfifoalloc2;
1664 }
1665
Hans Verkuil51270612010-03-22 05:22:34 -03001666 memcpy(meye.vdev, &meye_template, sizeof(meye_template));
1667 meye.vdev->v4l2_dev = &meye.v4l2_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
Mauro Carvalho Chehab5b5aff82008-09-03 17:11:52 -03001669 ret = -EIO;
malattia@linux.itcbefb762007-04-28 23:36:26 +09001670 if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) {
Hans Verkuil51270612010-03-22 05:22:34 -03001671 v4l2_err(v4l2_dev, "meye: unable to power on the camera\n");
1672 v4l2_err(v4l2_dev, "meye: did you enable the camera in "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 "sonypi using the module options ?\n");
1674 goto outsonypienable;
1675 }
1676
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 if ((ret = pci_enable_device(meye.mchip_dev))) {
Hans Verkuil51270612010-03-22 05:22:34 -03001678 v4l2_err(v4l2_dev, "meye: pci_enable_device failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 goto outenabledev;
1680 }
1681
1682 mchip_adr = pci_resource_start(meye.mchip_dev,0);
1683 if (!mchip_adr) {
Hans Verkuil51270612010-03-22 05:22:34 -03001684 v4l2_err(v4l2_dev, "meye: mchip has no device base address\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 goto outregions;
1686 }
1687 if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0),
1688 pci_resource_len(meye.mchip_dev, 0),
1689 "meye")) {
Hans Verkuil51270612010-03-22 05:22:34 -03001690 v4l2_err(v4l2_dev, "meye: request_mem_region failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 goto outregions;
1692 }
1693 meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS);
1694 if (!meye.mchip_mmregs) {
Hans Verkuil51270612010-03-22 05:22:34 -03001695 v4l2_err(v4l2_dev, "meye: ioremap failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 goto outremap;
1697 }
1698
1699 meye.mchip_irq = pcidev->irq;
1700 if (request_irq(meye.mchip_irq, meye_irq,
Thomas Gleixner8076fe32006-07-01 19:29:37 -07001701 IRQF_DISABLED | IRQF_SHARED, "meye", meye_irq)) {
Hans Verkuil51270612010-03-22 05:22:34 -03001702 v4l2_err(v4l2_dev, "request_irq failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 goto outreqirq;
1704 }
1705
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 pci_write_config_byte(meye.mchip_dev, PCI_CACHE_LINE_SIZE, 8);
1707 pci_write_config_byte(meye.mchip_dev, PCI_LATENCY_TIMER, 64);
1708
1709 pci_set_master(meye.mchip_dev);
1710
1711 /* Ask the camera to perform a soft reset. */
1712 pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1);
1713
1714 mchip_delay(MCHIP_HIC_CMD, 0);
1715 mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
1716
1717 msleep(1);
1718 mchip_set(MCHIP_VRJ_SOFT_RESET, 1);
1719
1720 msleep(1);
1721 mchip_set(MCHIP_MM_PCI_MODE, 5);
1722
1723 msleep(1);
1724 mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
1725
Ingo Molnar3593cab2006-02-07 06:49:14 -02001726 mutex_init(&meye.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 init_waitqueue_head(&meye.proc_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
Hans Verkuiled986d12013-01-29 07:21:02 -03001729 v4l2_ctrl_handler_init(&meye.hdl, 3);
1730 v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops,
1731 V4L2_CID_BRIGHTNESS, 0, 63, 1, 32);
1732 v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops,
1733 V4L2_CID_HUE, 0, 63, 1, 32);
1734 v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops,
1735 V4L2_CID_CONTRAST, 0, 63, 1, 32);
1736 v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops,
1737 V4L2_CID_SATURATION, 0, 63, 1, 32);
1738 v4l2_ctrl_new_custom(&meye.hdl, &ctrl_agc, NULL);
1739 v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops,
1740 V4L2_CID_SHARPNESS, 0, 63, 1, 32);
1741 v4l2_ctrl_new_custom(&meye.hdl, &ctrl_picture, NULL);
1742 v4l2_ctrl_new_std(&meye.hdl, &meye_ctrl_ops,
1743 V4L2_CID_JPEG_COMPRESSION_QUALITY, 0, 10, 1, 8);
1744 v4l2_ctrl_new_custom(&meye.hdl, &ctrl_framerate, NULL);
1745 if (meye.hdl.error) {
1746 v4l2_err(v4l2_dev, "couldn't register controls\n");
1747 goto outvideoreg;
1748 }
1749
1750 v4l2_ctrl_handler_setup(&meye.hdl);
1751 meye.vdev->ctrl_handler = &meye.hdl;
1752 set_bit(V4L2_FL_USE_FH_PRIO, &meye.vdev->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753
Hans Verkuil61df3c92010-11-14 10:09:38 -03001754 if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
1755 video_nr) < 0) {
1756 v4l2_err(v4l2_dev, "video_register_device failed\n");
1757 goto outvideoreg;
1758 }
1759
Hans Verkuil51270612010-03-22 05:22:34 -03001760 v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 MEYE_DRIVER_VERSION);
Hans Verkuil51270612010-03-22 05:22:34 -03001762 v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n",
Auke Kok44c10132007-06-08 15:46:36 -07001763 meye.mchip_dev->revision, mchip_adr, meye.mchip_irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764
1765 return 0;
1766
1767outvideoreg:
Hans Verkuiled986d12013-01-29 07:21:02 -03001768 v4l2_ctrl_handler_free(&meye.hdl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 free_irq(meye.mchip_irq, meye_irq);
1770outreqirq:
1771 iounmap(meye.mchip_mmregs);
1772outremap:
1773 release_mem_region(pci_resource_start(meye.mchip_dev, 0),
1774 pci_resource_len(meye.mchip_dev, 0));
1775outregions:
1776 pci_disable_device(meye.mchip_dev);
1777outenabledev:
malattia@linux.itcbefb762007-04-28 23:36:26 +09001778 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779outsonypienable:
Stefani Seibold45465482009-12-21 14:37:26 -08001780 kfifo_free(&meye.doneq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781outkfifoalloc2:
Stefani Seibold45465482009-12-21 14:37:26 -08001782 kfifo_free(&meye.grabq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783outkfifoalloc1:
1784 vfree(meye.grab_temp);
1785outvmalloc:
Hans Verkuil51270612010-03-22 05:22:34 -03001786 video_device_release(meye.vdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787outnotdev:
1788 return ret;
1789}
1790
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08001791static void meye_remove(struct pci_dev *pcidev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792{
Hans Verkuil51270612010-03-22 05:22:34 -03001793 video_unregister_device(meye.vdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794
1795 mchip_hic_stop();
1796
1797 mchip_dma_free();
1798
1799 /* disable interrupts */
1800 mchip_set(MCHIP_MM_INTA, 0x0);
1801
1802 free_irq(meye.mchip_irq, meye_irq);
1803
1804 iounmap(meye.mchip_mmregs);
1805
1806 release_mem_region(pci_resource_start(meye.mchip_dev, 0),
1807 pci_resource_len(meye.mchip_dev, 0));
1808
1809 pci_disable_device(meye.mchip_dev);
1810
malattia@linux.itcbefb762007-04-28 23:36:26 +09001811 sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
Stefani Seibold45465482009-12-21 14:37:26 -08001813 kfifo_free(&meye.doneq);
1814 kfifo_free(&meye.grabq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
1816 vfree(meye.grab_temp);
1817
1818 if (meye.grab_fbuffer) {
1819 rvfree(meye.grab_fbuffer, gbuffers*gbufsize);
1820 meye.grab_fbuffer = NULL;
1821 }
1822
1823 printk(KERN_INFO "meye: removed\n");
1824}
1825
1826static struct pci_device_id meye_pci_tbl[] = {
Joe Perches76e97412009-07-05 15:59:21 -03001827 { PCI_VDEVICE(KAWASAKI, PCI_DEVICE_ID_MCHIP_KL5A72002), 0 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 { }
1829};
1830
1831MODULE_DEVICE_TABLE(pci, meye_pci_tbl);
1832
1833static struct pci_driver meye_driver = {
1834 .name = "meye",
1835 .id_table = meye_pci_tbl,
1836 .probe = meye_probe,
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08001837 .remove = meye_remove,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838#ifdef CONFIG_PM
1839 .suspend = meye_suspend,
1840 .resume = meye_resume,
1841#endif
1842};
1843
1844static int __init meye_init(void)
1845{
1846 gbuffers = max(2, min((int)gbuffers, MEYE_MAX_BUFNBRS));
Mauro Carvalho Chehab83fa2352012-10-27 16:21:42 -03001847 if (gbufsize > MEYE_MAX_BUFSIZE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 gbufsize = MEYE_MAX_BUFSIZE;
1849 gbufsize = PAGE_ALIGN(gbufsize);
Joe Perchesac9bb7f2007-11-20 09:00:35 -03001850 printk(KERN_INFO "meye: using %d buffers with %dk (%dk total) "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 "for capture\n",
1852 gbuffers,
1853 gbufsize / 1024, gbuffers * gbufsize / 1024);
1854 return pci_register_driver(&meye_driver);
1855}
1856
1857static void __exit meye_exit(void)
1858{
1859 pci_unregister_driver(&meye_driver);
1860}
1861
1862module_init(meye_init);
1863module_exit(meye_exit);