blob: 73605864fffadb98ce9e780cf8499bee83a1704c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/***************************************************************************
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002 * V4L2 driver for SN9C1xx PC Camera Controllers *
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 * *
Luca Risoliaf327ebb2007-01-08 10:43:56 -03004 * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 ***************************************************************************/
20
21#include <linux/module.h>
22#include <linux/init.h>
23#include <linux/kernel.h>
24#include <linux/param.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/errno.h>
26#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/device.h>
28#include <linux/fs.h>
29#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/compiler.h>
31#include <linux/ioctl.h>
32#include <linux/poll.h>
33#include <linux/stat.h>
34#include <linux/mm.h>
35#include <linux/vmalloc.h>
Mauro Carvalho Chehab6c13b452011-06-25 13:43:22 -030036#include <linux/version.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/page-flags.h>
Harvey Harrison9a6ab762008-05-16 11:20:25 -070038#include <asm/byteorder.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <asm/page.h>
40#include <asm/uaccess.h>
41
42#include "sn9c102.h"
43
44/*****************************************************************************/
45
Luca Risoliaf327ebb2007-01-08 10:43:56 -030046#define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers"
Luca Risoliaf423b9a2007-03-26 16:12:04 -030047#define SN9C102_MODULE_ALIAS "sn9c1xx"
48#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"
Luca Risoliacd6fcc52006-01-13 17:19:43 +000049#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
50#define SN9C102_MODULE_LICENSE "GPL"
Mauro Carvalho Chehab6c13b452011-06-25 13:43:22 -030051#define SN9C102_MODULE_VERSION "1:1.48"
Luca Risoliacd6fcc52006-01-13 17:19:43 +000052
53/*****************************************************************************/
54
Linus Torvalds1da177e2005-04-16 15:20:36 -070055MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
56
57MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
58MODULE_DESCRIPTION(SN9C102_MODULE_NAME);
Luca Risoliaf423b9a2007-03-26 16:12:04 -030059MODULE_ALIAS(SN9C102_MODULE_ALIAS);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060MODULE_VERSION(SN9C102_MODULE_VERSION);
61MODULE_LICENSE(SN9C102_MODULE_LICENSE);
62
63static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};
64module_param_array(video_nr, short, NULL, 0444);
65MODULE_PARM_DESC(video_nr,
Luca Risolia3770be32007-06-13 14:37:50 -030066 " <-1|n[,...]>"
67 "\nSpecify V4L2 minor mode number."
68 "\n-1 = use next available (default)"
69 "\n n = use minor number n (integer >= 0)"
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030070 "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
71 " cameras this way."
72 "\nFor example:"
73 "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
74 "\nthe second camera and use auto for the first"
75 "\none and for every other camera."
76 "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
Rusty Russellbafeafe2012-01-13 09:32:16 +103078static bool force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
79 SN9C102_FORCE_MUNMAP};
Linus Torvalds1da177e2005-04-16 15:20:36 -070080module_param_array(force_munmap, bool, NULL, 0444);
81MODULE_PARM_DESC(force_munmap,
Luca Risolia3770be32007-06-13 14:37:50 -030082 " <0|1[,...]>"
83 "\nForce the application to unmap previously"
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030084 "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
85 "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
86 "\nthis feature. This parameter is specific for each"
87 "\ndetected camera."
Luca Risolia3770be32007-06-13 14:37:50 -030088 "\n0 = do not force memory unmapping"
89 "\n1 = force memory unmapping (save memory)"
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030090 "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
91 "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
Luca Risolia2ffab022006-02-25 06:50:47 +000093static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -030094 SN9C102_FRAME_TIMEOUT};
Luca Risolia2ffab022006-02-25 06:50:47 +000095module_param_array(frame_timeout, uint, NULL, 0644);
96MODULE_PARM_DESC(frame_timeout,
Luca Risolia3770be32007-06-13 14:37:50 -030097 " <0|n[,...]>"
98 "\nTimeout for a video frame in seconds before"
Luca Risoliaf327ebb2007-01-08 10:43:56 -030099 "\nreturning an I/O error; 0 for infinity."
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300100 "\nThis parameter is specific for each detected camera."
101 "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
102 "\n");
Luca Risolia2ffab022006-02-25 06:50:47 +0000103
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104#ifdef SN9C102_DEBUG
105static unsigned short debug = SN9C102_DEBUG_LEVEL;
106module_param(debug, ushort, 0644);
107MODULE_PARM_DESC(debug,
Luca Risolia3770be32007-06-13 14:37:50 -0300108 " <n>"
109 "\nDebugging information level, from 0 to 3:"
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300110 "\n0 = none (use carefully)"
111 "\n1 = critical errors"
112 "\n2 = significant informations"
113 "\n3 = more verbose messages"
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300114 "\nLevel 3 is useful for testing only."
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300115 "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
116 "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117#endif
118
Hans Verkuild45b9b82008-09-04 03:33:43 -0300119/*
120 Add the probe entries to this table. Be sure to add the entry in the right
121 place, since, on failure, the next probing routine is called according to
122 the order of the list below, from top to bottom.
123*/
124static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = {
125 &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
126 &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
127 &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
128 &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
129 &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */
130 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
131 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
132 &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
133 &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
134 &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
135 &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
136 &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
137};
138
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139/*****************************************************************************/
140
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300141static u32
142sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
143 enum sn9c102_io_method io)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144{
Luca Risolia2ffab022006-02-25 06:50:47 +0000145 struct v4l2_pix_format* p = &(cam->sensor.pix_format);
146 struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300147 size_t imagesize = cam->module_param.force_munmap || io == IO_READ ?
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300148 (p->width * p->height * p->priv) / 8 :
149 (r->width * r->height * p->priv) / 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 void* buff = NULL;
151 u32 i;
152
153 if (count > SN9C102_MAX_FRAMES)
154 count = SN9C102_MAX_FRAMES;
155
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300156 if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120)
157 imagesize += 589 + 2; /* length of JPEG header + EOI marker */
158
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 cam->nbuffers = count;
160 while (cam->nbuffers > 0) {
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300161 if ((buff = vmalloc_32_user(cam->nbuffers *
162 PAGE_ALIGN(imagesize))))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 break;
164 cam->nbuffers--;
165 }
166
167 for (i = 0; i < cam->nbuffers; i++) {
168 cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize);
169 cam->frame[i].buf.index = i;
170 cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize);
171 cam->frame[i].buf.length = imagesize;
172 cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
173 cam->frame[i].buf.sequence = 0;
174 cam->frame[i].buf.field = V4L2_FIELD_NONE;
175 cam->frame[i].buf.memory = V4L2_MEMORY_MMAP;
176 cam->frame[i].buf.flags = 0;
177 }
178
179 return cam->nbuffers;
180}
181
182
183static void sn9c102_release_buffers(struct sn9c102_device* cam)
184{
185 if (cam->nbuffers) {
Luca Risoliacd6fcc52006-01-13 17:19:43 +0000186 vfree(cam->frame[0].bufmem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 cam->nbuffers = 0;
188 }
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000189 cam->frame_current = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190}
191
192
193static void sn9c102_empty_framequeues(struct sn9c102_device* cam)
194{
195 u32 i;
196
197 INIT_LIST_HEAD(&cam->inqueue);
198 INIT_LIST_HEAD(&cam->outqueue);
199
200 for (i = 0; i < SN9C102_MAX_FRAMES; i++) {
201 cam->frame[i].state = F_UNUSED;
202 cam->frame[i].buf.bytesused = 0;
203 }
204}
205
206
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000207static void sn9c102_requeue_outqueue(struct sn9c102_device* cam)
208{
209 struct sn9c102_frame_t *i;
210
211 list_for_each_entry(i, &cam->outqueue, frame) {
212 i->state = F_QUEUED;
213 list_add(&i->frame, &cam->inqueue);
214 }
215
216 INIT_LIST_HEAD(&cam->outqueue);
217}
218
219
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220static void sn9c102_queue_unusedframes(struct sn9c102_device* cam)
221{
222 unsigned long lock_flags;
223 u32 i;
224
225 for (i = 0; i < cam->nbuffers; i++)
226 if (cam->frame[i].state == F_UNUSED) {
227 cam->frame[i].state = F_QUEUED;
228 spin_lock_irqsave(&cam->queue_lock, lock_flags);
229 list_add_tail(&cam->frame[i].frame, &cam->inqueue);
230 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
231 }
232}
233
234/*****************************************************************************/
Luca Risolia480b55c22007-05-02 10:04:03 -0300235
Trent Piephoc680dd62007-04-04 17:11:04 -0300236/*
Luca Risolia480b55c22007-05-02 10:04:03 -0300237 Write a sequence of count value/register pairs. Returns -1 after the first
238 failed write, or 0 for no errors.
239*/
Trent Piephoc680dd62007-04-04 17:11:04 -0300240int sn9c102_write_regs(struct sn9c102_device* cam, const u8 valreg[][2],
241 int count)
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000242{
243 struct usb_device* udev = cam->usbdev;
Luca Risolia480b55c22007-05-02 10:04:03 -0300244 u8* buff = cam->control_buffer;
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000245 int i, res;
246
Trent Piephoc680dd62007-04-04 17:11:04 -0300247 for (i = 0; i < count; i++) {
248 u8 index = valreg[i][1];
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000249
Trent Piephoc680dd62007-04-04 17:11:04 -0300250 /*
Luca Risolia480b55c22007-05-02 10:04:03 -0300251 index is a u8, so it must be <256 and can't be out of range.
252 If we put in a check anyway, gcc annoys us with a warning
253 hat our check is useless. People get all uppity when they
254 see warnings in the kernel compile.
255 */
Trent Piephoc680dd62007-04-04 17:11:04 -0300256
Luca Risolia480b55c22007-05-02 10:04:03 -0300257 *buff = valreg[i][0];
258
259 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08,
260 0x41, index, 0, buff, 1,
261 SN9C102_CTRL_TIMEOUT);
262
Trent Piephoc680dd62007-04-04 17:11:04 -0300263 if (res < 0) {
264 DBG(3, "Failed to write a register (value 0x%02X, "
Luca Risolia480b55c22007-05-02 10:04:03 -0300265 "index 0x%02X, error %d)", *buff, index, res);
Trent Piephoc680dd62007-04-04 17:11:04 -0300266 return -1;
267 }
268
Luca Risolia480b55c22007-05-02 10:04:03 -0300269 cam->reg[index] = *buff;
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000270 }
271
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000272 return 0;
273}
274
275
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
277{
278 struct usb_device* udev = cam->usbdev;
279 u8* buff = cam->control_buffer;
280 int res;
281
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000282 if (index >= ARRAY_SIZE(cam->reg))
283 return -1;
284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 *buff = value;
286
287 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300288 index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 if (res < 0) {
290 DBG(3, "Failed to write a register (value 0x%02X, index "
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000291 "0x%02X, error %d)", value, index, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 return -1;
293 }
294
295 cam->reg[index] = value;
296
297 return 0;
298}
299
300
Luca Risolia480b55c22007-05-02 10:04:03 -0300301/* NOTE: with the SN9C10[123] reading some registers always returns 0 */
302int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303{
304 struct usb_device* udev = cam->usbdev;
305 u8* buff = cam->control_buffer;
306 int res;
307
308 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300309 index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 if (res < 0)
311 DBG(3, "Failed to read a register (index 0x%02X, error %d)",
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000312 index, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
314 return (res >= 0) ? (int)(*buff) : -1;
315}
316
317
318int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index)
319{
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000320 if (index >= ARRAY_SIZE(cam->reg))
321 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
323 return cam->reg[index];
324}
325
326
327static int
Luca Risolia480b55c22007-05-02 10:04:03 -0300328sn9c102_i2c_wait(struct sn9c102_device* cam,
329 const struct sn9c102_sensor* sensor)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330{
331 int i, r;
332
333 for (i = 1; i <= 5; i++) {
334 r = sn9c102_read_reg(cam, 0x08);
335 if (r < 0)
336 return -EIO;
337 if (r & 0x04)
338 return 0;
339 if (sensor->frequency & SN9C102_I2C_400KHZ)
340 udelay(5*16);
341 else
342 udelay(16*16);
343 }
344 return -EBUSY;
345}
346
347
348static int
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300349sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
Luca Risolia480b55c22007-05-02 10:04:03 -0300350 const struct sn9c102_sensor* sensor)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351{
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300352 int r , err = 0;
353
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 r = sn9c102_read_reg(cam, 0x08);
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300355 if (r < 0)
356 err += r;
357
358 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
359 if (!(r & 0x08))
360 err += -1;
361 } else {
362 if (r & 0x08)
363 err += -1;
364 }
365
366 return err ? -EIO : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367}
368
369
370static int
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300371sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
Luca Risolia480b55c22007-05-02 10:04:03 -0300372 const struct sn9c102_sensor* sensor)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
374 int r;
375 r = sn9c102_read_reg(cam, 0x08);
376 return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0;
377}
378
379
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300380int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
Luca Risolia480b55c22007-05-02 10:04:03 -0300382 const struct sn9c102_sensor* sensor, u8 data0,
383 u8 data1, u8 n, u8 buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384{
385 struct usb_device* udev = cam->usbdev;
386 u8* data = cam->control_buffer;
Luca Risolia480b55c22007-05-02 10:04:03 -0300387 int i = 0, err = 0, res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
389 /* Write cycle */
390 data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300391 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 data[1] = data0; /* I2C slave id */
393 data[2] = data1; /* address */
394 data[7] = 0x10;
395 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300396 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 if (res < 0)
398 err += res;
399
400 err += sn9c102_i2c_wait(cam, sensor);
401
402 /* Read cycle - n bytes */
403 data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300404 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) |
405 (n << 4) | 0x02;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 data[1] = data0;
407 data[7] = 0x10;
408 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300409 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 if (res < 0)
411 err += res;
412
413 err += sn9c102_i2c_wait(cam, sensor);
414
415 /* The first read byte will be placed in data[4] */
416 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300417 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 if (res < 0)
419 err += res;
420
421 err += sn9c102_i2c_detect_read_error(cam, sensor);
422
423 PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1,
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000424 data[4]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
426 if (err) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000427 DBG(3, "I2C read failed for %s image sensor", sensor->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 return -1;
429 }
430
431 if (buffer)
Luca Risolia480b55c22007-05-02 10:04:03 -0300432 for (i = 0; i < n && i < 5; i++)
433 buffer[n-i-1] = data[4-i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
435 return (int)data[4];
436}
437
438
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300439int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
Luca Risolia480b55c22007-05-02 10:04:03 -0300441 const struct sn9c102_sensor* sensor, u8 n, u8 data0,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300442 u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443{
444 struct usb_device* udev = cam->usbdev;
445 u8* data = cam->control_buffer;
446 int err = 0, res;
447
448 /* Write cycle. It usually is address + value */
449 data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300450 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0)
451 | ((n - 1) << 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 data[1] = data0;
453 data[2] = data1;
454 data[3] = data2;
455 data[4] = data3;
456 data[5] = data4;
457 data[6] = data5;
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300458 data[7] = 0x17;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300460 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 if (res < 0)
462 err += res;
463
464 err += sn9c102_i2c_wait(cam, sensor);
465 err += sn9c102_i2c_detect_write_error(cam, sensor);
466
467 if (err)
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000468 DBG(3, "I2C write failed for %s image sensor", sensor->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470 PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, "
471 "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X",
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000472 n, data0, data1, data2, data3, data4, data5);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
474 return err ? -1 : 0;
475}
476
477
478int
479sn9c102_i2c_try_read(struct sn9c102_device* cam,
Luca Risolia480b55c22007-05-02 10:04:03 -0300480 const struct sn9c102_sensor* sensor, u8 address)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481{
482 return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300483 address, 1, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484}
485
486
Adrian Bunk762250f2008-03-30 23:29:02 -0300487static int sn9c102_i2c_try_write(struct sn9c102_device* cam,
488 const struct sn9c102_sensor* sensor,
489 u8 address, u8 value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490{
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300491 return sn9c102_i2c_try_raw_write(cam, sensor, 3,
492 sensor->i2c_slave_id, address,
493 value, 0, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494}
495
496
497int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address)
498{
Luca Risolia2ffab022006-02-25 06:50:47 +0000499 return sn9c102_i2c_try_read(cam, &cam->sensor, address);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500}
501
502
503int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value)
504{
Luca Risolia2ffab022006-02-25 06:50:47 +0000505 return sn9c102_i2c_try_write(cam, &cam->sensor, address, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506}
507
508/*****************************************************************************/
509
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300510static size_t sn9c102_sof_length(struct sn9c102_device* cam)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511{
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000512 switch (cam->bridge) {
513 case BRIDGE_SN9C101:
514 case BRIDGE_SN9C102:
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300515 return 12;
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000516 case BRIDGE_SN9C103:
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300517 return 18;
518 case BRIDGE_SN9C105:
519 case BRIDGE_SN9C120:
520 return 62;
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000521 }
522
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300523 return 0;
524}
525
526
527static void*
528sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
529{
Trent Piepho7e81d822007-04-04 17:11:05 -0300530 static const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300531 const char *m = mem;
532 size_t soflen = 0, i, j;
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300533
534 soflen = sn9c102_sof_length(cam);
535
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300536 for (i = 0; i < len; i++) {
537 size_t b;
538
539 /* Read the variable part of the header */
540 if (unlikely(cam->sof.bytesread >= sizeof(marker))) {
541 cam->sof.header[cam->sof.bytesread] = *(m+i);
542 if (++cam->sof.bytesread == soflen) {
543 cam->sof.bytesread = 0;
544 return mem + i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 }
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300546 continue;
547 }
548
549 /* Search for the SOF marker (fixed part) in the header */
550 for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) {
Roel Kluin05b20792008-04-22 14:42:08 -0300551 if (unlikely(i+j == len))
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300552 return NULL;
553 if (*(m+i+j) == marker[cam->sof.bytesread]) {
554 cam->sof.header[cam->sof.bytesread] = *(m+i+j);
555 if (++cam->sof.bytesread == sizeof(marker)) {
556 PDBGG("Bytes to analyze: %zd. SOF "
557 "starts at byte #%zd", len, i);
558 i += j+1;
559 break;
560 }
561 } else {
562 cam->sof.bytesread = 0;
563 break;
564 }
565 }
566 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
568 return NULL;
569}
570
571
572static void*
573sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
574{
Trent Piepho7e81d822007-04-04 17:11:05 -0300575 static const u8 eof_header[4][4] = {
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300576 {0x00, 0x00, 0x00, 0x00},
577 {0x40, 0x00, 0x00, 0x00},
578 {0x80, 0x00, 0x00, 0x00},
579 {0xc0, 0x00, 0x00, 0x00},
580 };
581 size_t i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300583 /* The EOF header does not exist in compressed data */
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300584 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
585 cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300586 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300588 /*
589 The EOF header might cross the packet boundary, but this is not a
590 problem, since the end of a frame is determined by checking its size
591 in the first place.
592 */
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300593 for (i = 0; (len >= 4) && (i <= len - 4); i++)
594 for (j = 0; j < ARRAY_SIZE(eof_header); j++)
595 if (!memcmp(mem + i, eof_header[j], 4))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 return mem + i;
597
598 return NULL;
599}
600
601
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300602static void
603sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
604{
Trent Piepho7e81d822007-04-04 17:11:05 -0300605 static const u8 jpeg_header[589] = {
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300606 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05,
607 0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06,
608 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e,
609 0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16,
610 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16,
611 0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29,
612 0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29,
613 0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
614 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28,
615 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
616 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
617 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
618 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
619 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2,
620 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
622 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01,
623 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
624 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
625 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00,
626 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
627 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
628 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
629 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
630 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
631 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
632 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
633 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
634 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
635 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
636 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
637 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
638 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
639 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
640 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3,
641 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
642 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
643 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
644 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
645 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
646 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
647 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
648 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1,
649 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19,
650 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
651 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
652 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
653 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
654 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
655 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
656 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
657 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
658 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
659 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
660 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
661 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11,
662 0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02,
663 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03,
664 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
665 };
666 u8 *pos = f->bufmem;
667
668 memcpy(pos, jpeg_header, sizeof(jpeg_header));
669 *(pos + 6) = 0x00;
670 *(pos + 7 + 64) = 0x01;
671 if (cam->compression.quality == 0) {
672 memcpy(pos + 7, SN9C102_Y_QTABLE0, 64);
673 memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64);
674 } else if (cam->compression.quality == 1) {
675 memcpy(pos + 7, SN9C102_Y_QTABLE1, 64);
676 memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64);
677 }
678 *(pos + 564) = cam->sensor.pix_format.width & 0xFF;
679 *(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF;
680 *(pos + 562) = cam->sensor.pix_format.height & 0xFF;
681 *(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF;
682 *(pos + 567) = 0x21;
683
684 f->buf.bytesused += sizeof(jpeg_header);
685}
686
687
David Howells7d12e782006-10-05 14:55:46 +0100688static void sn9c102_urb_complete(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689{
690 struct sn9c102_device* cam = urb->context;
691 struct sn9c102_frame_t** f;
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000692 size_t imagesize, soflen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 u8 i;
694 int err = 0;
695
696 if (urb->status == -ENOENT)
697 return;
698
699 f = &cam->frame_current;
700
701 if (cam->stream == STREAM_INTERRUPT) {
702 cam->stream = STREAM_OFF;
703 if ((*f))
704 (*f)->state = F_QUEUED;
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300705 cam->sof.bytesread = 0;
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300706 DBG(3, "Stream interrupted by application");
Luca Risolia2ffab022006-02-25 06:50:47 +0000707 wake_up(&cam->wait_stream);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 }
709
710 if (cam->state & DEV_DISCONNECTED)
711 return;
712
713 if (cam->state & DEV_MISCONFIGURED) {
714 wake_up_interruptible(&cam->wait_frame);
715 return;
716 }
717
718 if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue))
719 goto resubmit_urb;
720
721 if (!(*f))
722 (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300723 frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
Luca Risolia2ffab022006-02-25 06:50:47 +0000725 imagesize = (cam->sensor.pix_format.width *
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300726 cam->sensor.pix_format.height *
727 cam->sensor.pix_format.priv) / 8;
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300728 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
729 imagesize += 589; /* length of jpeg header */
730 soflen = sn9c102_sof_length(cam);
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000731
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 for (i = 0; i < urb->number_of_packets; i++) {
733 unsigned int img, len, status;
734 void *pos, *sof, *eof;
735
736 len = urb->iso_frame_desc[i].actual_length;
737 status = urb->iso_frame_desc[i].status;
738 pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer;
739
740 if (status) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000741 DBG(3, "Error in isochronous frame");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 (*f)->state = F_ERROR;
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300743 cam->sof.bytesread = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 continue;
745 }
746
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000747 PDBGG("Isochrnous frame: length %u, #%u i", len, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
749redo:
750 sof = sn9c102_find_sof_header(cam, pos, len);
Luca Risolia2ffab022006-02-25 06:50:47 +0000751 if (likely(!sof)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 eof = sn9c102_find_eof_header(cam, pos, len);
753 if ((*f)->state == F_GRABBING) {
754end_of_frame:
755 img = len;
756
757 if (eof)
758 img = (eof > pos) ? eof - pos - 1 : 0;
759
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300760 if ((*f)->buf.bytesused + img > imagesize) {
Luca Risolia2ffab022006-02-25 06:50:47 +0000761 u32 b;
762 b = (*f)->buf.bytesused + img -
763 imagesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 img = imagesize - (*f)->buf.bytesused;
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300765 PDBGG("Expected EOF not found: video "
766 "frame cut");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 if (eof)
768 DBG(3, "Exceeded limit: +%u "
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000769 "bytes", (unsigned)(b));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 }
771
772 memcpy((*f)->bufmem + (*f)->buf.bytesused, pos,
773 img);
774
775 if ((*f)->buf.bytesused == 0)
776 do_gettimeofday(&(*f)->buf.timestamp);
777
778 (*f)->buf.bytesused += img;
779
780 if ((*f)->buf.bytesused == imagesize ||
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300781 ((cam->sensor.pix_format.pixelformat ==
782 V4L2_PIX_FMT_SN9C10X ||
783 cam->sensor.pix_format.pixelformat ==
784 V4L2_PIX_FMT_JPEG) && eof)) {
Luca Risolia2ffab022006-02-25 06:50:47 +0000785 u32 b;
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300786
Luca Risolia2ffab022006-02-25 06:50:47 +0000787 b = (*f)->buf.bytesused;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 (*f)->state = F_DONE;
789 (*f)->buf.sequence= ++cam->frame_count;
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300790
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000791 spin_lock(&cam->queue_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 list_move_tail(&(*f)->frame,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300793 &cam->outqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 if (!list_empty(&cam->inqueue))
795 (*f) = list_entry(
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300796 cam->inqueue.next,
797 struct sn9c102_frame_t,
798 frame );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 else
800 (*f) = NULL;
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000801 spin_unlock(&cam->queue_lock);
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300802
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 memcpy(cam->sysfs.frame_header,
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300804 cam->sof.header, soflen);
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300805
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000806 DBG(3, "Video frame captured: %lu "
807 "bytes", (unsigned long)(b));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
809 if (!(*f))
810 goto resubmit_urb;
811
812 } else if (eof) {
813 (*f)->state = F_ERROR;
814 DBG(3, "Not expected EOF after %lu "
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300815 "bytes of image data",
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000816 (unsigned long)
817 ((*f)->buf.bytesused));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 }
819
820 if (sof) /* (1) */
821 goto start_of_frame;
822
823 } else if (eof) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000824 DBG(3, "EOF without SOF");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 continue;
826
827 } else {
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000828 PDBGG("Ignoring pointless isochronous frame");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 continue;
830 }
831
832 } else if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) {
833start_of_frame:
834 (*f)->state = F_GRABBING;
835 (*f)->buf.bytesused = 0;
836 len -= (sof - pos);
837 pos = sof;
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300838 if (cam->sensor.pix_format.pixelformat ==
839 V4L2_PIX_FMT_JPEG)
840 sn9c102_write_jpegheader(cam, (*f));
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000841 DBG(3, "SOF detected: new video frame");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 if (len)
843 goto redo;
844
845 } else if ((*f)->state == F_GRABBING) {
846 eof = sn9c102_find_eof_header(cam, pos, len);
847 if (eof && eof < sof)
848 goto end_of_frame; /* (1) */
849 else {
Luca Risolia2ffab022006-02-25 06:50:47 +0000850 if (cam->sensor.pix_format.pixelformat ==
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300851 V4L2_PIX_FMT_SN9C10X ||
852 cam->sensor.pix_format.pixelformat ==
853 V4L2_PIX_FMT_JPEG) {
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300854 if (sof - pos >= soflen) {
855 eof = sof - soflen;
856 } else { /* remove header */
857 eof = pos;
858 (*f)->buf.bytesused -=
859 (soflen - (sof - pos));
860 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 goto end_of_frame;
862 } else {
863 DBG(3, "SOF before expected EOF after "
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300864 "%lu bytes of image data",
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000865 (unsigned long)
866 ((*f)->buf.bytesused));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 goto start_of_frame;
868 }
869 }
870 }
871 }
872
873resubmit_urb:
874 urb->dev = cam->usbdev;
875 err = usb_submit_urb(urb, GFP_ATOMIC);
876 if (err < 0 && err != -EPERM) {
877 cam->state |= DEV_MISCONFIGURED;
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000878 DBG(1, "usb_submit_urb() failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 }
880
881 wake_up_interruptible(&cam->wait_frame);
882}
883
884
885static int sn9c102_start_transfer(struct sn9c102_device* cam)
886{
887 struct usb_device *udev = cam->usbdev;
888 struct urb* urb;
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300889 struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
890 usb_ifnum_to_if(udev, 0),
891 SN9C102_ALTERNATE_SETTING);
892 const unsigned int psz = le16_to_cpu(altsetting->
893 endpoint[0].desc.wMaxPacketSize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 s8 i, j;
895 int err = 0;
896
897 for (i = 0; i < SN9C102_URBS; i++) {
Luca Risoliacd6fcc52006-01-13 17:19:43 +0000898 cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -0300899 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 if (!cam->transfer_buffer[i]) {
901 err = -ENOMEM;
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000902 DBG(1, "Not enough memory");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 goto free_buffers;
904 }
905 }
906
907 for (i = 0; i < SN9C102_URBS; i++) {
908 urb = usb_alloc_urb(SN9C102_ISO_PACKETS, GFP_KERNEL);
909 cam->urb[i] = urb;
910 if (!urb) {
911 err = -ENOMEM;
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000912 DBG(1, "usb_alloc_urb() failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 goto free_urbs;
914 }
915 urb->dev = udev;
916 urb->context = cam;
917 urb->pipe = usb_rcvisocpipe(udev, 1);
918 urb->transfer_flags = URB_ISO_ASAP;
919 urb->number_of_packets = SN9C102_ISO_PACKETS;
920 urb->complete = sn9c102_urb_complete;
921 urb->transfer_buffer = cam->transfer_buffer[i];
922 urb->transfer_buffer_length = psz * SN9C102_ISO_PACKETS;
923 urb->interval = 1;
924 for (j = 0; j < SN9C102_ISO_PACKETS; j++) {
925 urb->iso_frame_desc[j].offset = psz * j;
926 urb->iso_frame_desc[j].length = psz;
927 }
928 }
929
930 /* Enable video */
931 if (!(cam->reg[0x01] & 0x04)) {
932 err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01);
933 if (err) {
934 err = -EIO;
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000935 DBG(1, "I/O hardware error");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 goto free_urbs;
937 }
938 }
939
940 err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING);
941 if (err) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000942 DBG(1, "usb_set_interface() failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 goto free_urbs;
944 }
945
946 cam->frame_current = NULL;
Luca Risoliaf423b9a2007-03-26 16:12:04 -0300947 cam->sof.bytesread = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
949 for (i = 0; i < SN9C102_URBS; i++) {
950 err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
951 if (err) {
952 for (j = i-1; j >= 0; j--)
953 usb_kill_urb(cam->urb[j]);
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000954 DBG(1, "usb_submit_urb() failed, error %d", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 goto free_urbs;
956 }
957 }
958
959 return 0;
960
961free_urbs:
Luca Risoliaf327ebb2007-01-08 10:43:56 -0300962 for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 usb_free_urb(cam->urb[i]);
964
965free_buffers:
966 for (i = 0; (i < SN9C102_URBS) && cam->transfer_buffer[i]; i++)
967 kfree(cam->transfer_buffer[i]);
968
969 return err;
970}
971
972
973static int sn9c102_stop_transfer(struct sn9c102_device* cam)
974{
975 struct usb_device *udev = cam->usbdev;
976 s8 i;
977 int err = 0;
978
979 if (cam->state & DEV_DISCONNECTED)
980 return 0;
981
982 for (i = SN9C102_URBS-1; i >= 0; i--) {
983 usb_kill_urb(cam->urb[i]);
984 usb_free_urb(cam->urb[i]);
985 kfree(cam->transfer_buffer[i]);
986 }
987
988 err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */
989 if (err)
Luca Risoliaa966f3e2006-01-05 18:14:04 +0000990 DBG(3, "usb_set_interface() failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
992 return err;
993}
994
995
Adrian Bunk71076272005-04-22 15:07:00 -0700996static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 cam->stream = STREAM_INTERRUPT;
Hans Verkuile92ba282012-05-14 10:17:35 -0300999 wait_event_timeout(cam->wait_stream,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001000 (cam->stream == STREAM_OFF) ||
1001 (cam->state & DEV_DISCONNECTED),
1002 SN9C102_URB_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 if (cam->state & DEV_DISCONNECTED)
1004 return -ENODEV;
Luca Risolia2ffab022006-02-25 06:50:47 +00001005 else if (cam->stream != STREAM_OFF) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 cam->state |= DEV_MISCONFIGURED;
Luca Risolia2ffab022006-02-25 06:50:47 +00001007 DBG(1, "URB timeout reached. The camera is misconfigured. "
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001008 "To use it, close and open %s again.",
1009 video_device_node_name(cam->v4ldev));
Luca Risolia2ffab022006-02-25 06:50:47 +00001010 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 }
1012
1013 return 0;
1014}
1015
1016/*****************************************************************************/
1017
Luca Risoliacd6fcc52006-01-13 17:19:43 +00001018#ifdef CONFIG_VIDEO_ADV_DEBUG
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001019static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020{
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001021 char str[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 char* endp;
1023 unsigned long val;
1024
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001025 if (len < 6) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 strncpy(str, buff, len);
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001027 str[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 } else {
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001029 strncpy(str, buff, 6);
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001030 str[6] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 }
1032
1033 val = simple_strtoul(str, &endp, 0);
1034
1035 *count = 0;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001036 if (val <= 0xffff)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 *count = (ssize_t)(endp - str);
1038 if ((*count) && (len == *count+1) && (buff[*count] == '\n'))
1039 *count += 1;
1040
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001041 return (u16)val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042}
1043
1044/*
1045 NOTE 1: being inside one of the following methods implies that the v4l
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001046 device exists for sure (see kobjects and reference counters)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 NOTE 2: buffers are PAGE_SIZE long
1048*/
1049
Kay Sievers54bd5b62007-10-08 16:26:13 -03001050static ssize_t sn9c102_show_reg(struct device* cd,
1051 struct device_attribute *attr, char* buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052{
1053 struct sn9c102_device* cam;
1054 ssize_t count;
1055
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001056 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 return -ERESTARTSYS;
1058
Hans Verkuil22a04f12008-07-20 06:35:02 -03001059 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 if (!cam) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001061 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 return -ENODEV;
1063 }
1064
1065 count = sprintf(buf, "%u\n", cam->sysfs.reg);
1066
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001067 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
1069 return count;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001070}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
1072
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001073static ssize_t
Kay Sievers54bd5b62007-10-08 16:26:13 -03001074sn9c102_store_reg(struct device* cd, struct device_attribute *attr,
1075 const char* buf, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076{
1077 struct sn9c102_device* cam;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001078 u16 index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 ssize_t count;
1080
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001081 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 return -ERESTARTSYS;
1083
Hans Verkuil22a04f12008-07-20 06:35:02 -03001084 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 if (!cam) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001086 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 return -ENODEV;
1088 }
1089
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001090 index = sn9c102_strtou16(buf, len, &count);
1091 if (index >= ARRAY_SIZE(cam->reg) || !count) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001092 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 return -EINVAL;
1094 }
1095
1096 cam->sysfs.reg = index;
1097
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001098 DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg);
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001099 DBG(3, "Written bytes: %zd", count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001101 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
1103 return count;
1104}
1105
1106
Kay Sievers54bd5b62007-10-08 16:26:13 -03001107static ssize_t sn9c102_show_val(struct device* cd,
1108 struct device_attribute *attr, char* buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109{
1110 struct sn9c102_device* cam;
1111 ssize_t count;
1112 int val;
1113
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001114 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 return -ERESTARTSYS;
1116
Hans Verkuil22a04f12008-07-20 06:35:02 -03001117 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 if (!cam) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001119 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 return -ENODEV;
1121 }
1122
1123 if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001124 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 return -EIO;
1126 }
1127
1128 count = sprintf(buf, "%d\n", val);
1129
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001130 DBG(3, "Read bytes: %zd, value: %d", count, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001132 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
1134 return count;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001135}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136
1137
1138static ssize_t
Kay Sievers54bd5b62007-10-08 16:26:13 -03001139sn9c102_store_val(struct device* cd, struct device_attribute *attr,
1140 const char* buf, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141{
1142 struct sn9c102_device* cam;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001143 u16 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 ssize_t count;
1145 int err;
1146
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001147 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 return -ERESTARTSYS;
1149
Hans Verkuil22a04f12008-07-20 06:35:02 -03001150 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 if (!cam) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001152 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 return -ENODEV;
1154 }
1155
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001156 value = sn9c102_strtou16(buf, len, &count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 if (!count) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001158 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 return -EINVAL;
1160 }
1161
1162 err = sn9c102_write_reg(cam, value, cam->sysfs.reg);
1163 if (err) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001164 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 return -EIO;
1166 }
1167
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001168 DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X",
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001169 cam->sysfs.reg, value);
1170 DBG(3, "Written bytes: %zd", count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001172 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173
1174 return count;
1175}
1176
1177
Kay Sievers54bd5b62007-10-08 16:26:13 -03001178static ssize_t sn9c102_show_i2c_reg(struct device* cd,
1179 struct device_attribute *attr, char* buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180{
1181 struct sn9c102_device* cam;
1182 ssize_t count;
1183
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001184 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 return -ERESTARTSYS;
1186
Hans Verkuil22a04f12008-07-20 06:35:02 -03001187 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 if (!cam) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001189 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 return -ENODEV;
1191 }
1192
1193 count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg);
1194
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001195 DBG(3, "Read bytes: %zd", count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001197 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198
1199 return count;
1200}
1201
1202
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001203static ssize_t
Kay Sievers54bd5b62007-10-08 16:26:13 -03001204sn9c102_store_i2c_reg(struct device* cd, struct device_attribute *attr,
1205 const char* buf, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206{
1207 struct sn9c102_device* cam;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001208 u16 index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 ssize_t count;
1210
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001211 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 return -ERESTARTSYS;
1213
Hans Verkuil22a04f12008-07-20 06:35:02 -03001214 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 if (!cam) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001216 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 return -ENODEV;
1218 }
1219
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001220 index = sn9c102_strtou16(buf, len, &count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 if (!count) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001222 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 return -EINVAL;
1224 }
1225
1226 cam->sysfs.i2c_reg = index;
1227
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001228 DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
1229 DBG(3, "Written bytes: %zd", count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001231 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
1233 return count;
1234}
1235
1236
Kay Sievers54bd5b62007-10-08 16:26:13 -03001237static ssize_t sn9c102_show_i2c_val(struct device* cd,
1238 struct device_attribute *attr, char* buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239{
1240 struct sn9c102_device* cam;
1241 ssize_t count;
1242 int val;
1243
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001244 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 return -ERESTARTSYS;
1246
Hans Verkuil22a04f12008-07-20 06:35:02 -03001247 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 if (!cam) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001249 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 return -ENODEV;
1251 }
1252
Luca Risolia2ffab022006-02-25 06:50:47 +00001253 if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001254 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 return -ENOSYS;
1256 }
1257
1258 if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001259 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 return -EIO;
1261 }
1262
1263 count = sprintf(buf, "%d\n", val);
1264
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001265 DBG(3, "Read bytes: %zd, value: %d", count, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001267 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268
1269 return count;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001270}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271
1272
1273static ssize_t
Kay Sievers54bd5b62007-10-08 16:26:13 -03001274sn9c102_store_i2c_val(struct device* cd, struct device_attribute *attr,
1275 const char* buf, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276{
1277 struct sn9c102_device* cam;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001278 u16 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 ssize_t count;
1280 int err;
1281
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001282 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 return -ERESTARTSYS;
1284
Hans Verkuil22a04f12008-07-20 06:35:02 -03001285 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 if (!cam) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001287 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 return -ENODEV;
1289 }
1290
Luca Risolia2ffab022006-02-25 06:50:47 +00001291 if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001292 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 return -ENOSYS;
1294 }
1295
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001296 value = sn9c102_strtou16(buf, len, &count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 if (!count) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001298 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 return -EINVAL;
1300 }
1301
1302 err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value);
1303 if (err) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001304 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 return -EIO;
1306 }
1307
1308 DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X",
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001309 cam->sysfs.i2c_reg, value);
1310 DBG(3, "Written bytes: %zd", count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001312 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
1314 return count;
1315}
1316
1317
1318static ssize_t
Kay Sievers54bd5b62007-10-08 16:26:13 -03001319sn9c102_store_green(struct device* cd, struct device_attribute *attr,
1320 const char* buf, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321{
1322 struct sn9c102_device* cam;
1323 enum sn9c102_bridge bridge;
1324 ssize_t res = 0;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001325 u16 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 ssize_t count;
1327
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001328 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 return -ERESTARTSYS;
1330
Hans Verkuil22a04f12008-07-20 06:35:02 -03001331 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 if (!cam) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001333 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 return -ENODEV;
1335 }
1336
1337 bridge = cam->bridge;
1338
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001339 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001341 value = sn9c102_strtou16(buf, len, &count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 if (!count)
1343 return -EINVAL;
1344
1345 switch (bridge) {
1346 case BRIDGE_SN9C101:
1347 case BRIDGE_SN9C102:
1348 if (value > 0x0f)
1349 return -EINVAL;
Kay Sievers54bd5b62007-10-08 16:26:13 -03001350 if ((res = sn9c102_store_reg(cd, attr, "0x11", 4)) >= 0)
1351 res = sn9c102_store_val(cd, attr, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 break;
1353 case BRIDGE_SN9C103:
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001354 case BRIDGE_SN9C105:
1355 case BRIDGE_SN9C120:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 if (value > 0x7f)
1357 return -EINVAL;
Kay Sievers54bd5b62007-10-08 16:26:13 -03001358 if ((res = sn9c102_store_reg(cd, attr, "0x07", 4)) >= 0)
1359 res = sn9c102_store_val(cd, attr, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 break;
1361 }
1362
1363 return res;
1364}
1365
1366
1367static ssize_t
Kay Sievers54bd5b62007-10-08 16:26:13 -03001368sn9c102_store_blue(struct device* cd, struct device_attribute *attr,
1369 const char* buf, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370{
1371 ssize_t res = 0;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001372 u16 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 ssize_t count;
1374
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001375 value = sn9c102_strtou16(buf, len, &count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 if (!count || value > 0x7f)
1377 return -EINVAL;
1378
Kay Sievers54bd5b62007-10-08 16:26:13 -03001379 if ((res = sn9c102_store_reg(cd, attr, "0x06", 4)) >= 0)
1380 res = sn9c102_store_val(cd, attr, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381
1382 return res;
1383}
1384
1385
1386static ssize_t
Kay Sievers54bd5b62007-10-08 16:26:13 -03001387sn9c102_store_red(struct device* cd, struct device_attribute *attr,
1388 const char* buf, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389{
1390 ssize_t res = 0;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001391 u16 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 ssize_t count;
1393
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001394 value = sn9c102_strtou16(buf, len, &count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 if (!count || value > 0x7f)
1396 return -EINVAL;
1397
Kay Sievers54bd5b62007-10-08 16:26:13 -03001398 if ((res = sn9c102_store_reg(cd, attr, "0x05", 4)) >= 0)
1399 res = sn9c102_store_val(cd, attr, buf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
1401 return res;
1402}
1403
1404
Kay Sievers54bd5b62007-10-08 16:26:13 -03001405static ssize_t sn9c102_show_frame_header(struct device* cd,
1406 struct device_attribute *attr,
1407 char* buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408{
1409 struct sn9c102_device* cam;
1410 ssize_t count;
1411
Hans Verkuil22a04f12008-07-20 06:35:02 -03001412 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 if (!cam)
1414 return -ENODEV;
1415
1416 count = sizeof(cam->sysfs.frame_header);
1417 memcpy(buf, cam->sysfs.frame_header, count);
1418
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001419 DBG(3, "Frame header, read bytes: %zd", count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420
1421 return count;
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001422}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
1424
Kay Sievers54bd5b62007-10-08 16:26:13 -03001425static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, sn9c102_show_reg, sn9c102_store_reg);
1426static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, sn9c102_show_val, sn9c102_store_val);
1427static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
1428 sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
1429static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
1430 sn9c102_show_i2c_val, sn9c102_store_i2c_val);
Vasiliy Kulikov14ddc312011-02-04 09:23:33 -03001431static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green);
1432static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue);
1433static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red);
Kay Sievers54bd5b62007-10-08 16:26:13 -03001434static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
1436
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001437static int sn9c102_create_sysfs(struct sn9c102_device* cam)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438{
Hans Verkuil22a04f12008-07-20 06:35:02 -03001439 struct device *dev = &(cam->v4ldev->dev);
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001440 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
Hans Verkuil22a04f12008-07-20 06:35:02 -03001442 if ((err = device_create_file(dev, &dev_attr_reg)))
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001443 goto err_out;
Hans Verkuil22a04f12008-07-20 06:35:02 -03001444 if ((err = device_create_file(dev, &dev_attr_val)))
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001445 goto err_reg;
Hans Verkuil22a04f12008-07-20 06:35:02 -03001446 if ((err = device_create_file(dev, &dev_attr_frame_header)))
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001447 goto err_val;
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001448
Luca Risolia2ffab022006-02-25 06:50:47 +00001449 if (cam->sensor.sysfs_ops) {
Hans Verkuil22a04f12008-07-20 06:35:02 -03001450 if ((err = device_create_file(dev, &dev_attr_i2c_reg)))
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001451 goto err_frame_header;
Hans Verkuil22a04f12008-07-20 06:35:02 -03001452 if ((err = device_create_file(dev, &dev_attr_i2c_val)))
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001453 goto err_i2c_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 }
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001455
1456 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
Hans Verkuil22a04f12008-07-20 06:35:02 -03001457 if ((err = device_create_file(dev, &dev_attr_green)))
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001458 goto err_i2c_val;
1459 } else {
Hans Verkuil22a04f12008-07-20 06:35:02 -03001460 if ((err = device_create_file(dev, &dev_attr_blue)))
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001461 goto err_i2c_val;
Hans Verkuil22a04f12008-07-20 06:35:02 -03001462 if ((err = device_create_file(dev, &dev_attr_red)))
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001463 goto err_blue;
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001464 }
1465
1466 return 0;
1467
1468err_blue:
Hans Verkuil22a04f12008-07-20 06:35:02 -03001469 device_remove_file(dev, &dev_attr_blue);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001470err_i2c_val:
1471 if (cam->sensor.sysfs_ops)
Hans Verkuil22a04f12008-07-20 06:35:02 -03001472 device_remove_file(dev, &dev_attr_i2c_val);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001473err_i2c_reg:
1474 if (cam->sensor.sysfs_ops)
Hans Verkuil22a04f12008-07-20 06:35:02 -03001475 device_remove_file(dev, &dev_attr_i2c_reg);
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001476err_frame_header:
Hans Verkuil22a04f12008-07-20 06:35:02 -03001477 device_remove_file(dev, &dev_attr_frame_header);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001478err_val:
Hans Verkuil22a04f12008-07-20 06:35:02 -03001479 device_remove_file(dev, &dev_attr_val);
Jeff Garzikc12e3be2006-10-13 07:17:32 -03001480err_reg:
Hans Verkuil22a04f12008-07-20 06:35:02 -03001481 device_remove_file(dev, &dev_attr_reg);
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001482err_out:
1483 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484}
Luca Risoliacd6fcc52006-01-13 17:19:43 +00001485#endif /* CONFIG_VIDEO_ADV_DEBUG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
1487/*****************************************************************************/
1488
1489static int
1490sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix)
1491{
1492 int err = 0;
1493
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001494 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
1495 pix->pixelformat == V4L2_PIX_FMT_JPEG) {
1496 switch (cam->bridge) {
1497 case BRIDGE_SN9C101:
1498 case BRIDGE_SN9C102:
1499 case BRIDGE_SN9C103:
1500 err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
1501 0x18);
1502 break;
1503 case BRIDGE_SN9C105:
1504 case BRIDGE_SN9C120:
1505 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
1506 0x18);
1507 break;
1508 }
1509 } else {
1510 switch (cam->bridge) {
1511 case BRIDGE_SN9C101:
1512 case BRIDGE_SN9C102:
1513 case BRIDGE_SN9C103:
1514 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
1515 0x18);
1516 break;
1517 case BRIDGE_SN9C105:
1518 case BRIDGE_SN9C120:
1519 err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
1520 0x18);
1521 break;
1522 }
1523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524
1525 return err ? -EIO : 0;
1526}
1527
1528
1529static int
1530sn9c102_set_compression(struct sn9c102_device* cam,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001531 struct v4l2_jpegcompression* compression)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532{
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001533 int i, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001535 switch (cam->bridge) {
1536 case BRIDGE_SN9C101:
1537 case BRIDGE_SN9C102:
1538 case BRIDGE_SN9C103:
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001539 if (compression->quality == 0)
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001540 err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
1541 0x17);
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001542 else if (compression->quality == 1)
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001543 err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
1544 0x17);
1545 break;
1546 case BRIDGE_SN9C105:
1547 case BRIDGE_SN9C120:
1548 if (compression->quality == 0) {
1549 for (i = 0; i <= 63; i++) {
1550 err += sn9c102_write_reg(cam,
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001551 SN9C102_Y_QTABLE1[i],
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001552 0x100 + i);
1553 err += sn9c102_write_reg(cam,
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001554 SN9C102_UV_QTABLE1[i],
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001555 0x140 + i);
1556 }
1557 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
1558 0x18);
1559 } else if (compression->quality == 1) {
1560 for (i = 0; i <= 63; i++) {
1561 err += sn9c102_write_reg(cam,
1562 SN9C102_Y_QTABLE1[i],
1563 0x100 + i);
1564 err += sn9c102_write_reg(cam,
1565 SN9C102_UV_QTABLE1[i],
1566 0x140 + i);
1567 }
1568 err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40,
1569 0x18);
1570 }
1571 break;
1572 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573
1574 return err ? -EIO : 0;
1575}
1576
1577
1578static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale)
1579{
1580 u8 r = 0;
1581 int err = 0;
1582
1583 if (scale == 1)
1584 r = cam->reg[0x18] & 0xcf;
1585 else if (scale == 2) {
1586 r = cam->reg[0x18] & 0xcf;
1587 r |= 0x10;
1588 } else if (scale == 4)
1589 r = cam->reg[0x18] | 0x20;
1590
1591 err += sn9c102_write_reg(cam, r, 0x18);
1592 if (err)
1593 return -EIO;
1594
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001595 PDBGG("Scaling factor: %u", scale);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
1597 return 0;
1598}
1599
1600
1601static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
1602{
Luca Risolia2ffab022006-02-25 06:50:47 +00001603 struct sn9c102_sensor* s = &cam->sensor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left),
1605 v_start = (u8)(rect->top - s->cropcap.bounds.top),
1606 h_size = (u8)(rect->width / 16),
1607 v_size = (u8)(rect->height / 16);
1608 int err = 0;
1609
1610 err += sn9c102_write_reg(cam, h_start, 0x12);
1611 err += sn9c102_write_reg(cam, v_start, 0x13);
1612 err += sn9c102_write_reg(cam, h_size, 0x15);
1613 err += sn9c102_write_reg(cam, v_size, 0x16);
1614 if (err)
1615 return -EIO;
1616
1617 PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001618 "%u %u %u %u", h_start, v_start, h_size, v_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619
1620 return 0;
1621}
1622
1623
1624static int sn9c102_init(struct sn9c102_device* cam)
1625{
Luca Risolia2ffab022006-02-25 06:50:47 +00001626 struct sn9c102_sensor* s = &cam->sensor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 struct v4l2_control ctrl;
1628 struct v4l2_queryctrl *qctrl;
1629 struct v4l2_rect* rect;
Tobias Klauser52950ed2005-12-11 16:20:08 +01001630 u8 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 int err = 0;
1632
1633 if (!(cam->state & DEV_INITIALIZED)) {
Luca Risolia3770be32007-06-13 14:37:50 -03001634 mutex_init(&cam->open_mutex);
1635 init_waitqueue_head(&cam->wait_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 qctrl = s->qctrl;
1637 rect = &(s->cropcap.defrect);
1638 } else { /* use current values */
1639 qctrl = s->_qctrl;
1640 rect = &(s->_rect);
1641 }
1642
1643 err += sn9c102_set_scale(cam, rect->width / s->pix_format.width);
1644 err += sn9c102_set_crop(cam, rect);
1645 if (err)
1646 return err;
1647
1648 if (s->init) {
1649 err = s->init(cam);
1650 if (err) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001651 DBG(3, "Sensor initialization failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 return err;
1653 }
1654 }
1655
1656 if (!(cam->state & DEV_INITIALIZED))
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001657 if (cam->bridge == BRIDGE_SN9C101 ||
1658 cam->bridge == BRIDGE_SN9C102 ||
1659 cam->bridge == BRIDGE_SN9C103) {
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001660 if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
1661 s->pix_format.pixelformat= V4L2_PIX_FMT_SBGGR8;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001662 cam->compression.quality = cam->reg[0x17] & 0x01 ?
1663 0 : 1;
1664 } else {
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001665 if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
1666 s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001667 cam->compression.quality = cam->reg[0x18] & 0x40 ?
1668 0 : 1;
1669 err += sn9c102_set_compression(cam, &cam->compression);
1670 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 else
1672 err += sn9c102_set_compression(cam, &cam->compression);
1673 err += sn9c102_set_pix_format(cam, &s->pix_format);
1674 if (s->set_pix_format)
1675 err += s->set_pix_format(cam, &s->pix_format);
1676 if (err)
1677 return err;
1678
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001679 if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
1680 s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
Tobias Klauser52950ed2005-12-11 16:20:08 +01001681 DBG(3, "Compressed video format is active, quality %d",
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001682 cam->compression.quality);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 else
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001684 DBG(3, "Uncompressed video format is active");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685
1686 if (s->set_crop)
1687 if ((err = s->set_crop(cam, rect))) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001688 DBG(3, "set_crop() failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 return err;
1690 }
1691
1692 if (s->set_ctrl) {
Tobias Klauser52950ed2005-12-11 16:20:08 +01001693 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
1694 if (s->qctrl[i].id != 0 &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {
1696 ctrl.id = s->qctrl[i].id;
1697 ctrl.value = qctrl[i].default_value;
1698 err = s->set_ctrl(cam, &ctrl);
1699 if (err) {
1700 DBG(3, "Set %s control failed",
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001701 s->qctrl[i].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 return err;
1703 }
1704 DBG(3, "Image sensor supports '%s' control",
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001705 s->qctrl[i].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 }
1707 }
1708
1709 if (!(cam->state & DEV_INITIALIZED)) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001710 mutex_init(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 spin_lock_init(&cam->queue_lock);
1712 init_waitqueue_head(&cam->wait_frame);
1713 init_waitqueue_head(&cam->wait_stream);
1714 cam->nreadbuffers = 2;
1715 memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));
Tobias Klauser52950ed2005-12-11 16:20:08 +01001716 memcpy(&(s->_rect), &(s->cropcap.defrect),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 sizeof(struct v4l2_rect));
1718 cam->state |= DEV_INITIALIZED;
1719 }
1720
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001721 DBG(2, "Initialization succeeded");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 return 0;
1723}
1724
Luca Risolia3770be32007-06-13 14:37:50 -03001725/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
Luca Risolia3770be32007-06-13 14:37:50 -03001727static void sn9c102_release_resources(struct kref *kref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728{
Luca Risolia3770be32007-06-13 14:37:50 -03001729 struct sn9c102_device *cam;
1730
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001731 mutex_lock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732
Luca Risolia3770be32007-06-13 14:37:50 -03001733 cam = container_of(kref, struct sn9c102_device, kref);
1734
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001735 DBG(2, "V4L2 device %s deregistered",
1736 video_device_node_name(cam->v4ldev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 video_set_drvdata(cam->v4ldev, NULL);
1738 video_unregister_device(cam->v4ldev);
Luca Risolia3770be32007-06-13 14:37:50 -03001739 usb_put_dev(cam->usbdev);
1740 kfree(cam->control_buffer);
1741 kfree(cam);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001743 mutex_unlock(&sn9c102_sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745}
1746
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747
Hans Verkuilbec43662008-12-30 06:58:20 -03001748static int sn9c102_open(struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749{
1750 struct sn9c102_device* cam;
1751 int err = 0;
1752
1753 /*
Luca Risolia3770be32007-06-13 14:37:50 -03001754 A read_trylock() in open() is the only safe way to prevent race
1755 conditions with disconnect(), one close() and multiple (not
1756 necessarily simultaneous) attempts to open(). For example, it
1757 prevents from waiting for a second access, while the device
1758 structure is being deallocated, after a possible disconnect() and
1759 during a following close() holding the write lock: given that, after
1760 this deallocation, no access will be possible anymore, using the
1761 non-trylock version would have let open() gain the access to the
1762 device structure improperly.
1763 For this reason the lock must also not be per-device.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 */
Luca Risolia3770be32007-06-13 14:37:50 -03001765 if (!down_read_trylock(&sn9c102_dev_lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 return -ERESTARTSYS;
1767
Hans Verkuilc170ecf2008-08-23 08:32:09 -03001768 cam = video_drvdata(filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
Luca Risolia3770be32007-06-13 14:37:50 -03001770 if (wait_for_completion_interruptible(&cam->probe)) {
1771 up_read(&sn9c102_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 return -ERESTARTSYS;
1773 }
1774
Luca Risolia3770be32007-06-13 14:37:50 -03001775 kref_get(&cam->kref);
1776
1777 /*
1778 Make sure to isolate all the simultaneous opens.
1779 */
1780 if (mutex_lock_interruptible(&cam->open_mutex)) {
1781 kref_put(&cam->kref, sn9c102_release_resources);
1782 up_read(&sn9c102_dev_lock);
1783 return -ERESTARTSYS;
1784 }
1785
1786 if (cam->state & DEV_DISCONNECTED) {
1787 DBG(1, "Device not present");
1788 err = -ENODEV;
1789 goto out;
1790 }
1791
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 if (cam->users) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001793 DBG(2, "Device %s is already in use",
1794 video_device_node_name(cam->v4ldev));
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001795 DBG(3, "Simultaneous opens are not supported");
Luca Risolia3770be32007-06-13 14:37:50 -03001796 /*
1797 open() must follow the open flags and should block
1798 eventually while the device is in use.
1799 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 if ((filp->f_flags & O_NONBLOCK) ||
1801 (filp->f_flags & O_NDELAY)) {
1802 err = -EWOULDBLOCK;
1803 goto out;
1804 }
Luca Risolia3770be32007-06-13 14:37:50 -03001805 DBG(2, "A blocking open() has been requested. Wait for the "
1806 "device to be released...");
1807 up_read(&sn9c102_dev_lock);
1808 /*
1809 We will not release the "open_mutex" lock, so that only one
1810 process can be in the wait queue below. This way the process
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001811 will be sleeping while holding the lock, without losing its
Luca Risolia3770be32007-06-13 14:37:50 -03001812 priority after any wake_up().
1813 */
1814 err = wait_event_interruptible_exclusive(cam->wait_open,
1815 (cam->state & DEV_DISCONNECTED)
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03001816 || !cam->users);
Luca Risolia3770be32007-06-13 14:37:50 -03001817 down_read(&sn9c102_dev_lock);
1818 if (err)
1819 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 if (cam->state & DEV_DISCONNECTED) {
Luca Risolia3770be32007-06-13 14:37:50 -03001821 err = -ENODEV;
1822 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 }
1825
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 if (cam->state & DEV_MISCONFIGURED) {
1827 err = sn9c102_init(cam);
1828 if (err) {
1829 DBG(1, "Initialization failed again. "
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001830 "I will retry on next open().");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 goto out;
1832 }
1833 cam->state &= ~DEV_MISCONFIGURED;
1834 }
1835
1836 if ((err = sn9c102_start_transfer(cam)))
1837 goto out;
1838
1839 filp->private_data = cam;
1840 cam->users++;
1841 cam->io = IO_NONE;
1842 cam->stream = STREAM_OFF;
1843 cam->nbuffers = 0;
1844 cam->frame_count = 0;
1845 sn9c102_empty_framequeues(cam);
1846
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001847 DBG(3, "Video device %s is open", video_device_node_name(cam->v4ldev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848
1849out:
Luca Risolia3770be32007-06-13 14:37:50 -03001850 mutex_unlock(&cam->open_mutex);
1851 if (err)
1852 kref_put(&cam->kref, sn9c102_release_resources);
1853
1854 up_read(&sn9c102_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 return err;
1856}
1857
1858
Hans Verkuilbec43662008-12-30 06:58:20 -03001859static int sn9c102_release(struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860{
Luca Risolia3770be32007-06-13 14:37:50 -03001861 struct sn9c102_device* cam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
Luca Risolia3770be32007-06-13 14:37:50 -03001863 down_write(&sn9c102_dev_lock);
1864
Hans Verkuilc170ecf2008-08-23 08:32:09 -03001865 cam = video_drvdata(filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
1867 sn9c102_stop_transfer(cam);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 sn9c102_release_buffers(cam);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 cam->users--;
Luca Risolia3770be32007-06-13 14:37:50 -03001870 wake_up_interruptible_nr(&cam->wait_open, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001872 DBG(3, "Video device %s closed", video_device_node_name(cam->v4ldev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873
Luca Risolia3770be32007-06-13 14:37:50 -03001874 kref_put(&cam->kref, sn9c102_release_resources);
1875
1876 up_write(&sn9c102_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
1878 return 0;
1879}
1880
1881
1882static ssize_t
1883sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
1884{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03001885 struct sn9c102_device *cam = video_drvdata(filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 struct sn9c102_frame_t* f, * i;
1887 unsigned long lock_flags;
Luca Risolia2ffab022006-02-25 06:50:47 +00001888 long timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 int err = 0;
1890
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001891 if (mutex_lock_interruptible(&cam->fileop_mutex))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 return -ERESTARTSYS;
1893
1894 if (cam->state & DEV_DISCONNECTED) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001895 DBG(1, "Device not present");
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001896 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 return -ENODEV;
1898 }
1899
1900 if (cam->state & DEV_MISCONFIGURED) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001901 DBG(1, "The camera is misconfigured. Close and open it "
1902 "again.");
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001903 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 return -EIO;
1905 }
1906
1907 if (cam->io == IO_MMAP) {
1908 DBG(3, "Close and open the device again to choose "
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001909 "the read method");
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001910 mutex_unlock(&cam->fileop_mutex);
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001911 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 }
1913
1914 if (cam->io == IO_NONE) {
1915 if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001916 DBG(1, "read() failed, not enough memory");
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001917 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 return -ENOMEM;
1919 }
1920 cam->io = IO_READ;
1921 cam->stream = STREAM_ON;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001922 }
1923
1924 if (list_empty(&cam->inqueue)) {
1925 if (!list_empty(&cam->outqueue))
1926 sn9c102_empty_framequeues(cam);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 sn9c102_queue_unusedframes(cam);
1928 }
1929
1930 if (!count) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001931 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 return 0;
1933 }
1934
1935 if (list_empty(&cam->outqueue)) {
1936 if (filp->f_flags & O_NONBLOCK) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001937 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 return -EAGAIN;
1939 }
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001940 if (!cam->module_param.frame_timeout) {
1941 err = wait_event_interruptible
1942 ( cam->wait_frame,
1943 (!list_empty(&cam->outqueue)) ||
1944 (cam->state & DEV_DISCONNECTED) ||
1945 (cam->state & DEV_MISCONFIGURED) );
1946 if (err) {
1947 mutex_unlock(&cam->fileop_mutex);
1948 return err;
1949 }
1950 } else {
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001951 timeout = wait_event_interruptible_timeout
1952 ( cam->wait_frame,
1953 (!list_empty(&cam->outqueue)) ||
1954 (cam->state & DEV_DISCONNECTED) ||
1955 (cam->state & DEV_MISCONFIGURED),
Andreas Mohr607cfab2009-09-14 19:13:29 -03001956 msecs_to_jiffies(
1957 cam->module_param.frame_timeout * 1000
1958 )
1959 );
Luca Risoliaf423b9a2007-03-26 16:12:04 -03001960 if (timeout < 0) {
1961 mutex_unlock(&cam->fileop_mutex);
1962 return timeout;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001963 } else if (timeout == 0 &&
1964 !(cam->state & DEV_DISCONNECTED)) {
1965 DBG(1, "Video frame timeout elapsed");
1966 mutex_unlock(&cam->fileop_mutex);
1967 return -EIO;
1968 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 }
1970 if (cam->state & DEV_DISCONNECTED) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001971 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 return -ENODEV;
1973 }
Luca Risoliaf327ebb2007-01-08 10:43:56 -03001974 if (cam->state & DEV_MISCONFIGURED) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01001975 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 return -EIO;
1977 }
1978 }
1979
1980 f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame);
1981
Luca Risoliaa966f3e2006-01-05 18:14:04 +00001982 if (count > f->buf.bytesused)
1983 count = f->buf.bytesused;
1984
1985 if (copy_to_user(buf, f->bufmem, count)) {
1986 err = -EFAULT;
1987 goto exit;
1988 }
1989 *f_pos += count;
1990
1991exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 spin_lock_irqsave(&cam->queue_lock, lock_flags);
1993 list_for_each_entry(i, &cam->outqueue, frame)
1994 i->state = F_UNUSED;
1995 INIT_LIST_HEAD(&cam->outqueue);
1996 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
1997
1998 sn9c102_queue_unusedframes(cam);
1999
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002000 PDBGG("Frame #%lu, bytes read: %zu",
2001 (unsigned long)f->buf.index, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01002003 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004
2005 return count;
2006}
2007
2008
2009static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
2010{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03002011 struct sn9c102_device *cam = video_drvdata(filp);
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002012 struct sn9c102_frame_t* f;
2013 unsigned long lock_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 unsigned int mask = 0;
2015
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01002016 if (mutex_lock_interruptible(&cam->fileop_mutex))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 return POLLERR;
2018
2019 if (cam->state & DEV_DISCONNECTED) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002020 DBG(1, "Device not present");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 goto error;
2022 }
2023
2024 if (cam->state & DEV_MISCONFIGURED) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002025 DBG(1, "The camera is misconfigured. Close and open it "
2026 "again.");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 goto error;
2028 }
2029
2030 if (cam->io == IO_NONE) {
2031 if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03002032 IO_READ)) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002033 DBG(1, "poll() failed, not enough memory");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 goto error;
2035 }
2036 cam->io = IO_READ;
2037 cam->stream = STREAM_ON;
2038 }
2039
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002040 if (cam->io == IO_READ) {
2041 spin_lock_irqsave(&cam->queue_lock, lock_flags);
2042 list_for_each_entry(f, &cam->outqueue, frame)
2043 f->state = F_UNUSED;
2044 INIT_LIST_HEAD(&cam->outqueue);
2045 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 sn9c102_queue_unusedframes(cam);
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048
2049 poll_wait(filp, &cam->wait_frame, wait);
2050
2051 if (!list_empty(&cam->outqueue))
2052 mask |= POLLIN | POLLRDNORM;
2053
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01002054 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055
2056 return mask;
2057
2058error:
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01002059 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 return POLLERR;
2061}
2062
2063
2064static void sn9c102_vm_open(struct vm_area_struct* vma)
2065{
2066 struct sn9c102_frame_t* f = vma->vm_private_data;
2067 f->vma_use_count++;
2068}
2069
2070
2071static void sn9c102_vm_close(struct vm_area_struct* vma)
2072{
2073 /* NOTE: buffers are not freed here */
2074 struct sn9c102_frame_t* f = vma->vm_private_data;
2075 f->vma_use_count--;
2076}
2077
2078
Alexey Dobriyanf0f37e22009-09-27 22:29:37 +04002079static const struct vm_operations_struct sn9c102_vm_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 .open = sn9c102_vm_open,
2081 .close = sn9c102_vm_close,
2082};
2083
2084
2085static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
2086{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03002087 struct sn9c102_device *cam = video_drvdata(filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 unsigned long size = vma->vm_end - vma->vm_start,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03002089 start = vma->vm_start;
Luca Risoliacd6fcc52006-01-13 17:19:43 +00002090 void *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 u32 i;
2092
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01002093 if (mutex_lock_interruptible(&cam->fileop_mutex))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 return -ERESTARTSYS;
2095
2096 if (cam->state & DEV_DISCONNECTED) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002097 DBG(1, "Device not present");
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01002098 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 return -ENODEV;
2100 }
2101
2102 if (cam->state & DEV_MISCONFIGURED) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002103 DBG(1, "The camera is misconfigured. Close and open it "
2104 "again.");
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01002105 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 return -EIO;
2107 }
2108
Luca Risoliaf423b9a2007-03-26 16:12:04 -03002109 if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
2110 mutex_unlock(&cam->fileop_mutex);
2111 return -EACCES;
2112 }
2113
2114 if (cam->io != IO_MMAP ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 size != PAGE_ALIGN(cam->frame[0].buf.length)) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01002116 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 return -EINVAL;
2118 }
2119
2120 for (i = 0; i < cam->nbuffers; i++) {
2121 if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff)
2122 break;
2123 }
2124 if (i == cam->nbuffers) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01002125 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 return -EINVAL;
2127 }
2128
Konstantin Khlebnikov314e51b2012-10-08 16:29:02 -07002129 vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130
Luca Risoliacd6fcc52006-01-13 17:19:43 +00002131 pos = cam->frame[i].bufmem;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 while (size > 0) { /* size is page-aligned */
Luca Risoliacd6fcc52006-01-13 17:19:43 +00002133 if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01002134 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 return -EAGAIN;
2136 }
2137 start += PAGE_SIZE;
2138 pos += PAGE_SIZE;
2139 size -= PAGE_SIZE;
2140 }
2141
2142 vma->vm_ops = &sn9c102_vm_ops;
2143 vma->vm_private_data = &cam->frame[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 sn9c102_vm_open(vma);
2145
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01002146 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147
2148 return 0;
2149}
2150
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002151/*****************************************************************************/
2152
2153static int
2154sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg)
2155{
2156 struct v4l2_capability cap = {
2157 .driver = "sn9c102",
Mauro Carvalho Chehab6c13b452011-06-25 13:43:22 -03002158 .version = LINUX_VERSION_CODE,
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002159 .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03002160 V4L2_CAP_STREAMING,
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002161 };
2162
2163 strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
2164 if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
Kay Sieversaf128a12008-10-30 00:51:46 -03002165 strlcpy(cap.bus_info, dev_name(&cam->usbdev->dev),
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03002166 sizeof(cap.bus_info));
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002167
2168 if (copy_to_user(arg, &cap, sizeof(cap)))
2169 return -EFAULT;
2170
2171 return 0;
2172}
2173
2174
2175static int
2176sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg)
2177{
2178 struct v4l2_input i;
2179
2180 if (copy_from_user(&i, arg, sizeof(i)))
2181 return -EFAULT;
2182
2183 if (i.index)
2184 return -EINVAL;
2185
2186 memset(&i, 0, sizeof(i));
Luca Risoliacd6fcc52006-01-13 17:19:43 +00002187 strcpy(i.name, "Camera");
Luca Risolia2ffab022006-02-25 06:50:47 +00002188 i.type = V4L2_INPUT_TYPE_CAMERA;
Hans Verkuil657f2272010-12-29 14:29:55 -03002189 i.capabilities = V4L2_IN_CAP_STD;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002190
2191 if (copy_to_user(arg, &i, sizeof(i)))
2192 return -EFAULT;
2193
2194 return 0;
2195}
2196
2197
2198static int
Luca Risolia2ffab022006-02-25 06:50:47 +00002199sn9c102_vidioc_g_input(struct sn9c102_device* cam, void __user * arg)
2200{
2201 int index = 0;
2202
2203 if (copy_to_user(arg, &index, sizeof(index)))
2204 return -EFAULT;
2205
2206 return 0;
2207}
2208
2209
2210static int
2211sn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg)
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002212{
2213 int index;
2214
2215 if (copy_from_user(&index, arg, sizeof(index)))
2216 return -EFAULT;
2217
2218 if (index != 0)
2219 return -EINVAL;
2220
2221 return 0;
2222}
2223
2224
2225static int
2226sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg)
2227{
Luca Risolia2ffab022006-02-25 06:50:47 +00002228 struct sn9c102_sensor* s = &cam->sensor;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002229 struct v4l2_queryctrl qc;
2230 u8 i;
2231
2232 if (copy_from_user(&qc, arg, sizeof(qc)))
2233 return -EFAULT;
2234
2235 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
2236 if (qc.id && qc.id == s->qctrl[i].id) {
2237 memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
2238 if (copy_to_user(arg, &qc, sizeof(qc)))
2239 return -EFAULT;
2240 return 0;
2241 }
2242
2243 return -EINVAL;
2244}
2245
2246
2247static int
2248sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg)
2249{
Luca Risolia2ffab022006-02-25 06:50:47 +00002250 struct sn9c102_sensor* s = &cam->sensor;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002251 struct v4l2_control ctrl;
2252 int err = 0;
2253 u8 i;
2254
2255 if (!s->get_ctrl && !s->set_ctrl)
2256 return -EINVAL;
2257
2258 if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
2259 return -EFAULT;
2260
2261 if (!s->get_ctrl) {
2262 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
2263 if (ctrl.id && ctrl.id == s->qctrl[i].id) {
2264 ctrl.value = s->_qctrl[i].default_value;
2265 goto exit;
2266 }
2267 return -EINVAL;
2268 } else
2269 err = s->get_ctrl(cam, &ctrl);
2270
2271exit:
2272 if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
2273 return -EFAULT;
2274
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002275 PDBGG("VIDIOC_G_CTRL: id %lu, value %lu",
2276 (unsigned long)ctrl.id, (unsigned long)ctrl.value);
2277
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002278 return err;
2279}
2280
2281
2282static int
2283sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg)
2284{
Luca Risolia2ffab022006-02-25 06:50:47 +00002285 struct sn9c102_sensor* s = &cam->sensor;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002286 struct v4l2_control ctrl;
2287 u8 i;
2288 int err = 0;
2289
2290 if (!s->set_ctrl)
2291 return -EINVAL;
2292
2293 if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
2294 return -EFAULT;
2295
Dan Carpenter124371e2010-03-28 08:50:05 -03002296 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002297 if (ctrl.id == s->qctrl[i].id) {
Luca Risolia2ffab022006-02-25 06:50:47 +00002298 if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
2299 return -EINVAL;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002300 if (ctrl.value < s->qctrl[i].minimum ||
2301 ctrl.value > s->qctrl[i].maximum)
2302 return -ERANGE;
2303 ctrl.value -= ctrl.value % s->qctrl[i].step;
2304 break;
2305 }
Dan Carpenter124371e2010-03-28 08:50:05 -03002306 }
2307 if (i == ARRAY_SIZE(s->qctrl))
2308 return -EINVAL;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002309 if ((err = s->set_ctrl(cam, &ctrl)))
2310 return err;
2311
2312 s->_qctrl[i].default_value = ctrl.value;
2313
2314 PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
2315 (unsigned long)ctrl.id, (unsigned long)ctrl.value);
2316
2317 return 0;
2318}
2319
2320
2321static int
2322sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg)
2323{
Luca Risolia2ffab022006-02-25 06:50:47 +00002324 struct v4l2_cropcap* cc = &(cam->sensor.cropcap);
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002325
2326 cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2327 cc->pixelaspect.numerator = 1;
2328 cc->pixelaspect.denominator = 1;
2329
2330 if (copy_to_user(arg, cc, sizeof(*cc)))
2331 return -EFAULT;
2332
2333 return 0;
2334}
2335
2336
2337static int
2338sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg)
2339{
Luca Risolia2ffab022006-02-25 06:50:47 +00002340 struct sn9c102_sensor* s = &cam->sensor;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002341 struct v4l2_crop crop = {
2342 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
2343 };
2344
2345 memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
2346
2347 if (copy_to_user(arg, &crop, sizeof(crop)))
2348 return -EFAULT;
2349
2350 return 0;
2351}
2352
2353
2354static int
2355sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
2356{
Luca Risolia2ffab022006-02-25 06:50:47 +00002357 struct sn9c102_sensor* s = &cam->sensor;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002358 struct v4l2_crop crop;
2359 struct v4l2_rect* rect;
2360 struct v4l2_rect* bounds = &(s->cropcap.bounds);
2361 struct v4l2_pix_format* pix_format = &(s->pix_format);
2362 u8 scale;
2363 const enum sn9c102_stream_state stream = cam->stream;
2364 const u32 nbuffers = cam->nbuffers;
2365 u32 i;
2366 int err = 0;
2367
2368 if (copy_from_user(&crop, arg, sizeof(crop)))
2369 return -EFAULT;
2370
2371 rect = &(crop.c);
2372
2373 if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2374 return -EINVAL;
2375
2376 if (cam->module_param.force_munmap)
2377 for (i = 0; i < cam->nbuffers; i++)
2378 if (cam->frame[i].vma_use_count) {
2379 DBG(3, "VIDIOC_S_CROP failed. "
2380 "Unmap the buffers first.");
Luca Risoliaf423b9a2007-03-26 16:12:04 -03002381 return -EBUSY;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002382 }
2383
2384 /* Preserve R,G or B origin */
2385 rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
2386 rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
2387
2388 if (rect->width < 16)
2389 rect->width = 16;
2390 if (rect->height < 16)
2391 rect->height = 16;
2392 if (rect->width > bounds->width)
2393 rect->width = bounds->width;
2394 if (rect->height > bounds->height)
2395 rect->height = bounds->height;
2396 if (rect->left < bounds->left)
2397 rect->left = bounds->left;
2398 if (rect->top < bounds->top)
2399 rect->top = bounds->top;
2400 if (rect->left + rect->width > bounds->left + bounds->width)
2401 rect->left = bounds->left+bounds->width - rect->width;
2402 if (rect->top + rect->height > bounds->top + bounds->height)
2403 rect->top = bounds->top+bounds->height - rect->height;
2404
2405 rect->width &= ~15L;
2406 rect->height &= ~15L;
2407
2408 if (SN9C102_PRESERVE_IMGSCALE) {
2409 /* Calculate the actual scaling factor */
2410 u32 a, b;
2411 a = rect->width * rect->height;
2412 b = pix_format->width * pix_format->height;
2413 scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
2414 } else
2415 scale = 1;
2416
2417 if (cam->stream == STREAM_ON)
2418 if ((err = sn9c102_stream_interrupt(cam)))
2419 return err;
2420
2421 if (copy_to_user(arg, &crop, sizeof(crop))) {
2422 cam->stream = stream;
2423 return -EFAULT;
2424 }
2425
2426 if (cam->module_param.force_munmap || cam->io == IO_READ)
2427 sn9c102_release_buffers(cam);
2428
2429 err = sn9c102_set_crop(cam, rect);
2430 if (s->set_crop)
2431 err += s->set_crop(cam, rect);
2432 err += sn9c102_set_scale(cam, scale);
2433
2434 if (err) { /* atomic, no rollback in ioctl() */
2435 cam->state |= DEV_MISCONFIGURED;
2436 DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002437 "use the camera, close and open %s again.",
2438 video_device_node_name(cam->v4ldev));
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002439 return -EIO;
2440 }
2441
2442 s->pix_format.width = rect->width/scale;
2443 s->pix_format.height = rect->height/scale;
2444 memcpy(&(s->_rect), rect, sizeof(*rect));
2445
2446 if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
2447 nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
2448 cam->state |= DEV_MISCONFIGURED;
2449 DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002450 "use the camera, close and open %s again.",
2451 video_device_node_name(cam->v4ldev));
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002452 return -ENOMEM;
2453 }
2454
2455 if (cam->io == IO_READ)
2456 sn9c102_empty_framequeues(cam);
2457 else if (cam->module_param.force_munmap)
2458 sn9c102_requeue_outqueue(cam);
2459
2460 cam->stream = stream;
2461
2462 return 0;
2463}
2464
2465
2466static int
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002467sn9c102_vidioc_enum_framesizes(struct sn9c102_device* cam, void __user * arg)
2468{
2469 struct v4l2_frmsizeenum frmsize;
2470
2471 if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
2472 return -EFAULT;
2473
2474 if (frmsize.index != 0)
2475 return -EINVAL;
2476
2477 switch (cam->bridge) {
2478 case BRIDGE_SN9C101:
2479 case BRIDGE_SN9C102:
2480 case BRIDGE_SN9C103:
2481 if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X &&
2482 frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
2483 return -EINVAL;
Alan Cox9001a4b2012-10-25 10:39:33 -03002484 break;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002485 case BRIDGE_SN9C105:
2486 case BRIDGE_SN9C120:
2487 if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG &&
2488 frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
2489 return -EINVAL;
Alan Cox9001a4b2012-10-25 10:39:33 -03002490 break;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002491 }
2492
2493 frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
2494 frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16;
2495 frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16;
2496 frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width;
2497 frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height;
2498 memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
2499
2500 if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
2501 return -EFAULT;
2502
2503 return 0;
2504}
2505
2506
2507static int
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002508sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
2509{
2510 struct v4l2_fmtdesc fmtd;
2511
2512 if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
2513 return -EFAULT;
2514
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002515 if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2516 return -EINVAL;
2517
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002518 if (fmtd.index == 0) {
2519 strcpy(fmtd.description, "bayer rgb");
2520 fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
2521 } else if (fmtd.index == 1) {
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002522 switch (cam->bridge) {
2523 case BRIDGE_SN9C101:
2524 case BRIDGE_SN9C102:
2525 case BRIDGE_SN9C103:
Luca Risoliaf423b9a2007-03-26 16:12:04 -03002526 strcpy(fmtd.description, "compressed");
2527 fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002528 break;
2529 case BRIDGE_SN9C105:
2530 case BRIDGE_SN9C120:
2531 strcpy(fmtd.description, "JPEG");
2532 fmtd.pixelformat = V4L2_PIX_FMT_JPEG;
2533 break;
2534 }
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002535 fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
2536 } else
2537 return -EINVAL;
2538
2539 fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2540 memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
2541
2542 if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
2543 return -EFAULT;
2544
2545 return 0;
2546}
2547
2548
2549static int
2550sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
2551{
2552 struct v4l2_format format;
Luca Risolia2ffab022006-02-25 06:50:47 +00002553 struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format);
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002554
2555 if (copy_from_user(&format, arg, sizeof(format)))
2556 return -EFAULT;
2557
2558 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2559 return -EINVAL;
2560
Luca Risoliaf423b9a2007-03-26 16:12:04 -03002561 pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ?
2562 V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
2563 pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X ||
2564 pfmt->pixelformat == V4L2_PIX_FMT_JPEG)
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03002565 ? 0 : (pfmt->width * pfmt->priv) / 8;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002566 pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
2567 pfmt->field = V4L2_FIELD_NONE;
2568 memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
2569
2570 if (copy_to_user(arg, &format, sizeof(format)))
2571 return -EFAULT;
2572
2573 return 0;
2574}
2575
2576
2577static int
2578sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03002579 void __user * arg)
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002580{
Luca Risolia2ffab022006-02-25 06:50:47 +00002581 struct sn9c102_sensor* s = &cam->sensor;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002582 struct v4l2_format format;
2583 struct v4l2_pix_format* pix;
2584 struct v4l2_pix_format* pfmt = &(s->pix_format);
2585 struct v4l2_rect* bounds = &(s->cropcap.bounds);
2586 struct v4l2_rect rect;
2587 u8 scale;
2588 const enum sn9c102_stream_state stream = cam->stream;
2589 const u32 nbuffers = cam->nbuffers;
2590 u32 i;
2591 int err = 0;
2592
2593 if (copy_from_user(&format, arg, sizeof(format)))
2594 return -EFAULT;
2595
2596 pix = &(format.fmt.pix);
2597
2598 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2599 return -EINVAL;
2600
2601 memcpy(&rect, &(s->_rect), sizeof(rect));
2602
2603 { /* calculate the actual scaling factor */
2604 u32 a, b;
2605 a = rect.width * rect.height;
2606 b = pix->width * pix->height;
2607 scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
2608 }
2609
2610 rect.width = scale * pix->width;
2611 rect.height = scale * pix->height;
2612
2613 if (rect.width < 16)
2614 rect.width = 16;
2615 if (rect.height < 16)
2616 rect.height = 16;
2617 if (rect.width > bounds->left + bounds->width - rect.left)
2618 rect.width = bounds->left + bounds->width - rect.left;
2619 if (rect.height > bounds->top + bounds->height - rect.top)
2620 rect.height = bounds->top + bounds->height - rect.top;
2621
2622 rect.width &= ~15L;
2623 rect.height &= ~15L;
2624
2625 { /* adjust the scaling factor */
2626 u32 a, b;
2627 a = rect.width * rect.height;
2628 b = pix->width * pix->height;
2629 scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
2630 }
2631
2632 pix->width = rect.width / scale;
2633 pix->height = rect.height / scale;
2634
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002635 switch (cam->bridge) {
2636 case BRIDGE_SN9C101:
2637 case BRIDGE_SN9C102:
2638 case BRIDGE_SN9C103:
Luca Risoliaf423b9a2007-03-26 16:12:04 -03002639 if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
2640 pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
2641 pix->pixelformat = pfmt->pixelformat;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002642 break;
2643 case BRIDGE_SN9C105:
2644 case BRIDGE_SN9C120:
2645 if (pix->pixelformat != V4L2_PIX_FMT_JPEG &&
2646 pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
2647 pix->pixelformat = pfmt->pixelformat;
2648 break;
2649 }
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002650 pix->priv = pfmt->priv; /* bpp */
Luca Risoliaf423b9a2007-03-26 16:12:04 -03002651 pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ?
2652 V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002653 pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
2654 pix->pixelformat == V4L2_PIX_FMT_JPEG)
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03002655 ? 0 : (pix->width * pix->priv) / 8;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002656 pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
2657 pix->field = V4L2_FIELD_NONE;
2658
2659 if (cmd == VIDIOC_TRY_FMT) {
2660 if (copy_to_user(arg, &format, sizeof(format)))
2661 return -EFAULT;
2662 return 0;
2663 }
2664
2665 if (cam->module_param.force_munmap)
2666 for (i = 0; i < cam->nbuffers; i++)
2667 if (cam->frame[i].vma_use_count) {
2668 DBG(3, "VIDIOC_S_FMT failed. Unmap the "
2669 "buffers first.");
Luca Risoliaf423b9a2007-03-26 16:12:04 -03002670 return -EBUSY;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002671 }
2672
2673 if (cam->stream == STREAM_ON)
2674 if ((err = sn9c102_stream_interrupt(cam)))
2675 return err;
2676
2677 if (copy_to_user(arg, &format, sizeof(format))) {
2678 cam->stream = stream;
2679 return -EFAULT;
2680 }
2681
2682 if (cam->module_param.force_munmap || cam->io == IO_READ)
2683 sn9c102_release_buffers(cam);
2684
2685 err += sn9c102_set_pix_format(cam, pix);
2686 err += sn9c102_set_crop(cam, &rect);
2687 if (s->set_pix_format)
2688 err += s->set_pix_format(cam, pix);
2689 if (s->set_crop)
2690 err += s->set_crop(cam, &rect);
2691 err += sn9c102_set_scale(cam, scale);
2692
2693 if (err) { /* atomic, no rollback in ioctl() */
2694 cam->state |= DEV_MISCONFIGURED;
2695 DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002696 "use the camera, close and open %s again.",
2697 video_device_node_name(cam->v4ldev));
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002698 return -EIO;
2699 }
2700
2701 memcpy(pfmt, pix, sizeof(*pix));
2702 memcpy(&(s->_rect), &rect, sizeof(rect));
2703
2704 if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
2705 nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
2706 cam->state |= DEV_MISCONFIGURED;
2707 DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002708 "use the camera, close and open %s again.",
2709 video_device_node_name(cam->v4ldev));
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002710 return -ENOMEM;
2711 }
2712
2713 if (cam->io == IO_READ)
2714 sn9c102_empty_framequeues(cam);
2715 else if (cam->module_param.force_munmap)
2716 sn9c102_requeue_outqueue(cam);
2717
2718 cam->stream = stream;
2719
2720 return 0;
2721}
2722
2723
2724static int
2725sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg)
2726{
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002727 if (copy_to_user(arg, &cam->compression, sizeof(cam->compression)))
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002728 return -EFAULT;
2729
2730 return 0;
2731}
2732
2733
2734static int
2735sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg)
2736{
2737 struct v4l2_jpegcompression jc;
2738 const enum sn9c102_stream_state stream = cam->stream;
2739 int err = 0;
2740
2741 if (copy_from_user(&jc, arg, sizeof(jc)))
2742 return -EFAULT;
2743
2744 if (jc.quality != 0 && jc.quality != 1)
2745 return -EINVAL;
2746
2747 if (cam->stream == STREAM_ON)
2748 if ((err = sn9c102_stream_interrupt(cam)))
2749 return err;
2750
2751 err += sn9c102_set_compression(cam, &jc);
2752 if (err) { /* atomic, no rollback in ioctl() */
2753 cam->state |= DEV_MISCONFIGURED;
Laurent Pinchart38c7c032009-11-27 13:57:15 -03002754 DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware problems. "
2755 "To use the camera, close and open %s again.",
2756 video_device_node_name(cam->v4ldev));
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002757 return -EIO;
2758 }
2759
2760 cam->compression.quality = jc.quality;
2761
2762 cam->stream = stream;
2763
2764 return 0;
2765}
2766
2767
2768static int
2769sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg)
2770{
2771 struct v4l2_requestbuffers rb;
2772 u32 i;
2773 int err;
2774
2775 if (copy_from_user(&rb, arg, sizeof(rb)))
2776 return -EFAULT;
2777
2778 if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
2779 rb.memory != V4L2_MEMORY_MMAP)
2780 return -EINVAL;
2781
2782 if (cam->io == IO_READ) {
2783 DBG(3, "Close and open the device again to choose the mmap "
2784 "I/O method");
Luca Risoliaf423b9a2007-03-26 16:12:04 -03002785 return -EBUSY;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002786 }
2787
2788 for (i = 0; i < cam->nbuffers; i++)
2789 if (cam->frame[i].vma_use_count) {
2790 DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
2791 "still mapped.");
Luca Risoliaf423b9a2007-03-26 16:12:04 -03002792 return -EBUSY;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002793 }
2794
2795 if (cam->stream == STREAM_ON)
2796 if ((err = sn9c102_stream_interrupt(cam)))
2797 return err;
2798
2799 sn9c102_empty_framequeues(cam);
2800
2801 sn9c102_release_buffers(cam);
2802 if (rb.count)
2803 rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP);
2804
2805 if (copy_to_user(arg, &rb, sizeof(rb))) {
2806 sn9c102_release_buffers(cam);
2807 cam->io = IO_NONE;
2808 return -EFAULT;
2809 }
2810
2811 cam->io = rb.count ? IO_MMAP : IO_NONE;
2812
2813 return 0;
2814}
2815
2816
2817static int
2818sn9c102_vidioc_querybuf(struct sn9c102_device* cam, void __user * arg)
2819{
2820 struct v4l2_buffer b;
2821
2822 if (copy_from_user(&b, arg, sizeof(b)))
2823 return -EFAULT;
2824
2825 if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
2826 b.index >= cam->nbuffers || cam->io != IO_MMAP)
2827 return -EINVAL;
2828
2829 memcpy(&b, &cam->frame[b.index].buf, sizeof(b));
2830
2831 if (cam->frame[b.index].vma_use_count)
2832 b.flags |= V4L2_BUF_FLAG_MAPPED;
2833
2834 if (cam->frame[b.index].state == F_DONE)
2835 b.flags |= V4L2_BUF_FLAG_DONE;
2836 else if (cam->frame[b.index].state != F_UNUSED)
2837 b.flags |= V4L2_BUF_FLAG_QUEUED;
2838
2839 if (copy_to_user(arg, &b, sizeof(b)))
2840 return -EFAULT;
2841
2842 return 0;
2843}
2844
2845
2846static int
2847sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg)
2848{
2849 struct v4l2_buffer b;
2850 unsigned long lock_flags;
2851
2852 if (copy_from_user(&b, arg, sizeof(b)))
2853 return -EFAULT;
2854
2855 if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
2856 b.index >= cam->nbuffers || cam->io != IO_MMAP)
2857 return -EINVAL;
2858
2859 if (cam->frame[b.index].state != F_UNUSED)
2860 return -EINVAL;
2861
2862 cam->frame[b.index].state = F_QUEUED;
2863
2864 spin_lock_irqsave(&cam->queue_lock, lock_flags);
2865 list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
2866 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
2867
2868 PDBGG("Frame #%lu queued", (unsigned long)b.index);
2869
2870 return 0;
2871}
2872
2873
2874static int
2875sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03002876 void __user * arg)
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002877{
2878 struct v4l2_buffer b;
2879 struct sn9c102_frame_t *f;
2880 unsigned long lock_flags;
Luca Risolia2ffab022006-02-25 06:50:47 +00002881 long timeout;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002882 int err = 0;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002883
2884 if (copy_from_user(&b, arg, sizeof(b)))
2885 return -EFAULT;
2886
2887 if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
2888 return -EINVAL;
2889
2890 if (list_empty(&cam->outqueue)) {
2891 if (cam->stream == STREAM_OFF)
2892 return -EINVAL;
2893 if (filp->f_flags & O_NONBLOCK)
2894 return -EAGAIN;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002895 if (!cam->module_param.frame_timeout) {
2896 err = wait_event_interruptible
2897 ( cam->wait_frame,
2898 (!list_empty(&cam->outqueue)) ||
2899 (cam->state & DEV_DISCONNECTED) ||
2900 (cam->state & DEV_MISCONFIGURED) );
2901 if (err)
2902 return err;
2903 } else {
Luca Risoliaf423b9a2007-03-26 16:12:04 -03002904 timeout = wait_event_interruptible_timeout
2905 ( cam->wait_frame,
2906 (!list_empty(&cam->outqueue)) ||
2907 (cam->state & DEV_DISCONNECTED) ||
2908 (cam->state & DEV_MISCONFIGURED),
2909 cam->module_param.frame_timeout *
2910 1000 * msecs_to_jiffies(1) );
2911 if (timeout < 0)
2912 return timeout;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002913 else if (timeout == 0 &&
2914 !(cam->state & DEV_DISCONNECTED)) {
2915 DBG(1, "Video frame timeout elapsed");
2916 return -EIO;
2917 }
2918 }
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002919 if (cam->state & DEV_DISCONNECTED)
2920 return -ENODEV;
Luca Risoliaf327ebb2007-01-08 10:43:56 -03002921 if (cam->state & DEV_MISCONFIGURED)
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002922 return -EIO;
2923 }
2924
2925 spin_lock_irqsave(&cam->queue_lock, lock_flags);
2926 f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame);
2927 list_del(cam->outqueue.next);
2928 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
2929
2930 f->state = F_UNUSED;
2931
2932 memcpy(&b, &f->buf, sizeof(b));
2933 if (f->vma_use_count)
2934 b.flags |= V4L2_BUF_FLAG_MAPPED;
2935
2936 if (copy_to_user(arg, &b, sizeof(b)))
2937 return -EFAULT;
2938
2939 PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index);
2940
2941 return 0;
2942}
2943
2944
2945static int
2946sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg)
2947{
2948 int type;
2949
2950 if (copy_from_user(&type, arg, sizeof(type)))
2951 return -EFAULT;
2952
2953 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
2954 return -EINVAL;
2955
Luca Risoliaa966f3e2006-01-05 18:14:04 +00002956 cam->stream = STREAM_ON;
2957
2958 DBG(3, "Stream on");
2959
2960 return 0;
2961}
2962
2963
2964static int
2965sn9c102_vidioc_streamoff(struct sn9c102_device* cam, void __user * arg)
2966{
2967 int type, err;
2968
2969 if (copy_from_user(&type, arg, sizeof(type)))
2970 return -EFAULT;
2971
2972 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
2973 return -EINVAL;
2974
2975 if (cam->stream == STREAM_ON)
2976 if ((err = sn9c102_stream_interrupt(cam)))
2977 return err;
2978
2979 sn9c102_empty_framequeues(cam);
2980
2981 DBG(3, "Stream off");
2982
2983 return 0;
2984}
2985
2986
2987static int
2988sn9c102_vidioc_g_parm(struct sn9c102_device* cam, void __user * arg)
2989{
2990 struct v4l2_streamparm sp;
2991
2992 if (copy_from_user(&sp, arg, sizeof(sp)))
2993 return -EFAULT;
2994
2995 if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2996 return -EINVAL;
2997
2998 sp.parm.capture.extendedmode = 0;
2999 sp.parm.capture.readbuffers = cam->nreadbuffers;
3000
3001 if (copy_to_user(arg, &sp, sizeof(sp)))
3002 return -EFAULT;
3003
3004 return 0;
3005}
3006
3007
3008static int
3009sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg)
3010{
3011 struct v4l2_streamparm sp;
3012
3013 if (copy_from_user(&sp, arg, sizeof(sp)))
3014 return -EFAULT;
3015
3016 if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
3017 return -EINVAL;
3018
3019 sp.parm.capture.extendedmode = 0;
3020
3021 if (sp.parm.capture.readbuffers == 0)
3022 sp.parm.capture.readbuffers = cam->nreadbuffers;
3023
3024 if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES)
3025 sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES;
3026
3027 if (copy_to_user(arg, &sp, sizeof(sp)))
3028 return -EFAULT;
3029
3030 cam->nreadbuffers = sp.parm.capture.readbuffers;
3031
3032 return 0;
3033}
3034
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003036static int
3037sn9c102_vidioc_enumaudio(struct sn9c102_device* cam, void __user * arg)
3038{
3039 struct v4l2_audio audio;
3040
3041 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
3042 return -EINVAL;
3043
3044 if (copy_from_user(&audio, arg, sizeof(audio)))
3045 return -EFAULT;
3046
3047 if (audio.index != 0)
3048 return -EINVAL;
3049
3050 strcpy(audio.name, "Microphone");
3051 audio.capability = 0;
3052 audio.mode = 0;
3053
3054 if (copy_to_user(arg, &audio, sizeof(audio)))
3055 return -EFAULT;
3056
3057 return 0;
3058}
3059
3060
3061static int
3062sn9c102_vidioc_g_audio(struct sn9c102_device* cam, void __user * arg)
3063{
3064 struct v4l2_audio audio;
3065
3066 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
3067 return -EINVAL;
3068
3069 if (copy_from_user(&audio, arg, sizeof(audio)))
3070 return -EFAULT;
3071
3072 memset(&audio, 0, sizeof(audio));
3073 strcpy(audio.name, "Microphone");
3074
3075 if (copy_to_user(arg, &audio, sizeof(audio)))
3076 return -EFAULT;
3077
3078 return 0;
3079}
3080
3081
3082static int
3083sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg)
3084{
3085 struct v4l2_audio audio;
3086
3087 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
3088 return -EINVAL;
3089
3090 if (copy_from_user(&audio, arg, sizeof(audio)))
3091 return -EFAULT;
3092
3093 if (audio.index != 0)
3094 return -EINVAL;
3095
3096 return 0;
3097}
3098
3099
Hans Verkuil069b7472008-12-30 07:04:34 -03003100static long sn9c102_ioctl_v4l2(struct file *filp,
Hans Verkuilbec43662008-12-30 06:58:20 -03003101 unsigned int cmd, void __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003103 struct sn9c102_device *cam = video_drvdata(filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104
3105 switch (cmd) {
3106
3107 case VIDIOC_QUERYCAP:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003108 return sn9c102_vidioc_querycap(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109
3110 case VIDIOC_ENUMINPUT:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003111 return sn9c102_vidioc_enuminput(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112
3113 case VIDIOC_G_INPUT:
Luca Risolia2ffab022006-02-25 06:50:47 +00003114 return sn9c102_vidioc_g_input(cam, arg);
3115
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 case VIDIOC_S_INPUT:
Luca Risolia2ffab022006-02-25 06:50:47 +00003117 return sn9c102_vidioc_s_input(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118
3119 case VIDIOC_QUERYCTRL:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003120 return sn9c102_vidioc_query_ctrl(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121
3122 case VIDIOC_G_CTRL:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003123 return sn9c102_vidioc_g_ctrl(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 case VIDIOC_S_CTRL:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003126 return sn9c102_vidioc_s_ctrl(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 case VIDIOC_CROPCAP:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003129 return sn9c102_vidioc_cropcap(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130
3131 case VIDIOC_G_CROP:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003132 return sn9c102_vidioc_g_crop(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133
3134 case VIDIOC_S_CROP:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003135 return sn9c102_vidioc_s_crop(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003137 case VIDIOC_ENUM_FRAMESIZES:
3138 return sn9c102_vidioc_enum_framesizes(cam, arg);
3139
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 case VIDIOC_ENUM_FMT:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003141 return sn9c102_vidioc_enum_fmt(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142
3143 case VIDIOC_G_FMT:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003144 return sn9c102_vidioc_g_fmt(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145
3146 case VIDIOC_TRY_FMT:
3147 case VIDIOC_S_FMT:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003148 return sn9c102_vidioc_try_s_fmt(cam, cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149
3150 case VIDIOC_G_JPEGCOMP:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003151 return sn9c102_vidioc_g_jpegcomp(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152
3153 case VIDIOC_S_JPEGCOMP:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003154 return sn9c102_vidioc_s_jpegcomp(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155
3156 case VIDIOC_REQBUFS:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003157 return sn9c102_vidioc_reqbufs(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158
3159 case VIDIOC_QUERYBUF:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003160 return sn9c102_vidioc_querybuf(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161
3162 case VIDIOC_QBUF:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003163 return sn9c102_vidioc_qbuf(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
3165 case VIDIOC_DQBUF:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003166 return sn9c102_vidioc_dqbuf(cam, filp, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167
3168 case VIDIOC_STREAMON:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003169 return sn9c102_vidioc_streamon(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170
3171 case VIDIOC_STREAMOFF:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003172 return sn9c102_vidioc_streamoff(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173
3174 case VIDIOC_G_PARM:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003175 return sn9c102_vidioc_g_parm(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 case VIDIOC_S_PARM:
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003178 return sn9c102_vidioc_s_parm(cam, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003180 case VIDIOC_ENUMAUDIO:
3181 return sn9c102_vidioc_enumaudio(cam, arg);
3182
3183 case VIDIOC_G_AUDIO:
3184 return sn9c102_vidioc_g_audio(cam, arg);
3185
3186 case VIDIOC_S_AUDIO:
3187 return sn9c102_vidioc_s_audio(cam, arg);
3188
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189 default:
Mauro Carvalho Chehab7a286cc2011-06-26 10:18:03 -03003190 return -ENOTTY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191
3192 }
3193}
3194
3195
Hans Verkuil069b7472008-12-30 07:04:34 -03003196static long sn9c102_ioctl(struct file *filp,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03003197 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198{
Hans Verkuilc170ecf2008-08-23 08:32:09 -03003199 struct sn9c102_device *cam = video_drvdata(filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 int err = 0;
3201
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01003202 if (mutex_lock_interruptible(&cam->fileop_mutex))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203 return -ERESTARTSYS;
3204
3205 if (cam->state & DEV_DISCONNECTED) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003206 DBG(1, "Device not present");
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01003207 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208 return -ENODEV;
3209 }
3210
3211 if (cam->state & DEV_MISCONFIGURED) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003212 DBG(1, "The camera is misconfigured. Close and open it "
3213 "again.");
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01003214 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215 return -EIO;
3216 }
3217
Luca Risoliacd6fcc52006-01-13 17:19:43 +00003218 V4LDBG(3, "sn9c102", cmd);
3219
Hans Verkuilbec43662008-12-30 06:58:20 -03003220 err = sn9c102_ioctl_v4l2(filp, cmd, (void __user *)arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221
Arjan van de Ven4186ecf2006-01-11 15:55:29 +01003222 mutex_unlock(&cam->fileop_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223
3224 return err;
3225}
3226
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003227/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228
Hans Verkuilbec43662008-12-30 06:58:20 -03003229static const struct v4l2_file_operations sn9c102_fops = {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003230 .owner = THIS_MODULE,
Luca Risolia480b55c22007-05-02 10:04:03 -03003231 .open = sn9c102_open,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 .release = sn9c102_release,
Hans Verkuilfeecf932010-11-14 11:13:39 -03003233 .unlocked_ioctl = sn9c102_ioctl,
Luca Risolia480b55c22007-05-02 10:04:03 -03003234 .read = sn9c102_read,
3235 .poll = sn9c102_poll,
3236 .mmap = sn9c102_mmap,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237};
3238
3239/*****************************************************************************/
3240
3241/* It exists a single interface only. We do not need to validate anything. */
3242static int
3243sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3244{
3245 struct usb_device *udev = interface_to_usbdev(intf);
3246 struct sn9c102_device* cam;
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -03003247 static unsigned int dev_nr;
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003248 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249 int err = 0, r;
3250
Luca Risoliacd6fcc52006-01-13 17:19:43 +00003251 if (!(cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253
3254 cam->usbdev = udev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255
Luca Risoliacd6fcc52006-01-13 17:19:43 +00003256 if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) {
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003257 DBG(1, "kzalloc() failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258 err = -ENOMEM;
3259 goto fail;
3260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261
3262 if (!(cam->v4ldev = video_device_alloc())) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003263 DBG(1, "video_device_alloc() failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264 err = -ENOMEM;
3265 goto fail;
3266 }
3267
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268 r = sn9c102_read_reg(cam, 0x00);
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003269 if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
Luca Risoliaf423b9a2007-03-26 16:12:04 -03003270 DBG(1, "Sorry, this is not a SN9C1xx-based camera "
3271 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 err = -ENODEV;
3273 goto fail;
3274 }
3275
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003276 cam->bridge = id->driver_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277 switch (cam->bridge) {
3278 case BRIDGE_SN9C101:
3279 case BRIDGE_SN9C102:
3280 DBG(2, "SN9C10[12] PC Camera Controller detected "
Luca Risoliaf423b9a2007-03-26 16:12:04 -03003281 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282 break;
3283 case BRIDGE_SN9C103:
3284 DBG(2, "SN9C103 PC Camera Controller detected "
Luca Risoliaf423b9a2007-03-26 16:12:04 -03003285 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003286 break;
3287 case BRIDGE_SN9C105:
3288 DBG(2, "SN9C105 PC Camera Controller detected "
Luca Risoliaf423b9a2007-03-26 16:12:04 -03003289 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003290 break;
3291 case BRIDGE_SN9C120:
3292 DBG(2, "SN9C120 PC Camera Controller detected "
Luca Risoliaf423b9a2007-03-26 16:12:04 -03003293 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294 break;
3295 }
3296
Luca Risolia480b55c22007-05-02 10:04:03 -03003297 for (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 err = sn9c102_sensor_table[i](cam);
3299 if (!err)
3300 break;
3301 }
3302
Luca Risolia2ffab022006-02-25 06:50:47 +00003303 if (!err) {
3304 DBG(2, "%s image sensor detected", cam->sensor.name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305 DBG(3, "Support for %s maintained by %s",
Luca Risolia2ffab022006-02-25 06:50:47 +00003306 cam->sensor.name, cam->sensor.maintainer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307 } else {
Luca Risolia480b55c22007-05-02 10:04:03 -03003308 DBG(1, "No supported image sensor detected for this bridge");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003309 err = -ENODEV;
3310 goto fail;
3311 }
3312
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003313 if (!(cam->bridge & cam->sensor.supported_bridge)) {
3314 DBG(1, "Bridge not supported");
3315 err = -ENODEV;
3316 goto fail;
3317 }
3318
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319 if (sn9c102_init(cam)) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003320 DBG(1, "Initialization failed. I will retry on open().");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321 cam->state |= DEV_MISCONFIGURED;
3322 }
3323
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003324 strcpy(cam->v4ldev->name, "SN9C1xx PC Camera");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325 cam->v4ldev->fops = &sn9c102_fops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326 cam->v4ldev->release = video_device_release;
Hans de Goede748c7f82008-09-01 15:28:23 -03003327 cam->v4ldev->parent = &udev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328
Luca Risolia3770be32007-06-13 14:37:50 -03003329 init_completion(&cam->probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330
3331 err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
Mauro Carvalho Chehabd56410e2006-03-25 09:19:53 -03003332 video_nr[dev_nr]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333 if (err) {
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003334 DBG(1, "V4L2 device registration failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335 if (err == -ENFILE && video_nr[dev_nr] == -1)
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003336 DBG(1, "Free /dev/videoX node not found");
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003337 video_nr[dev_nr] = -1;
3338 dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
Luca Risolia3770be32007-06-13 14:37:50 -03003339 complete_all(&cam->probe);
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003340 goto fail;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341 }
3342
Laurent Pinchart38c7c032009-11-27 13:57:15 -03003343 DBG(2, "V4L2 device registered as %s",
3344 video_device_node_name(cam->v4ldev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345
Luca Risoliaddef2dc2007-11-12 11:42:54 -03003346 video_set_drvdata(cam->v4ldev, cam);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347 cam->module_param.force_munmap = force_munmap[dev_nr];
Luca Risolia2ffab022006-02-25 06:50:47 +00003348 cam->module_param.frame_timeout = frame_timeout[dev_nr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349
3350 dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
3351
Luca Risoliacd6fcc52006-01-13 17:19:43 +00003352#ifdef CONFIG_VIDEO_ADV_DEBUG
Jeff Garzikc12e3be2006-10-13 07:17:32 -03003353 err = sn9c102_create_sysfs(cam);
Luca Risoliaf327ebb2007-01-08 10:43:56 -03003354 if (!err)
3355 DBG(2, "Optional device control through 'sysfs' "
3356 "interface ready");
3357 else
3358 DBG(2, "Failed to create optional 'sysfs' interface for "
3359 "device controlling. Error #%d", err);
3360#else
3361 DBG(2, "Optional device control through 'sysfs' interface disabled");
Luca Risoliaf423b9a2007-03-26 16:12:04 -03003362 DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' "
3363 "configuration option to enable it.");
Luca Risoliacd6fcc52006-01-13 17:19:43 +00003364#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365
3366 usb_set_intfdata(intf, cam);
Luca Risolia3770be32007-06-13 14:37:50 -03003367 kref_init(&cam->kref);
3368 usb_get_dev(cam->usbdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369
Luca Risolia3770be32007-06-13 14:37:50 -03003370 complete_all(&cam->probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371
3372 return 0;
3373
3374fail:
3375 if (cam) {
3376 kfree(cam->control_buffer);
3377 if (cam->v4ldev)
3378 video_device_release(cam->v4ldev);
3379 kfree(cam);
3380 }
3381 return err;
3382}
3383
3384
3385static void sn9c102_usb_disconnect(struct usb_interface* intf)
3386{
Luca Risolia3770be32007-06-13 14:37:50 -03003387 struct sn9c102_device* cam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388
Luca Risolia3770be32007-06-13 14:37:50 -03003389 down_write(&sn9c102_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390
Luca Risolia3770be32007-06-13 14:37:50 -03003391 cam = usb_get_intfdata(intf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392
Luca Risoliaa966f3e2006-01-05 18:14:04 +00003393 DBG(2, "Disconnecting %s...", cam->v4ldev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395 if (cam->users) {
Laurent Pinchart38c7c032009-11-27 13:57:15 -03003396 DBG(2, "Device %s is open! Deregistration and memory "
3397 "deallocation are deferred.",
3398 video_device_node_name(cam->v4ldev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 cam->state |= DEV_MISCONFIGURED;
3400 sn9c102_stop_transfer(cam);
3401 cam->state |= DEV_DISCONNECTED;
3402 wake_up_interruptible(&cam->wait_frame);
Luca Risolia2ffab022006-02-25 06:50:47 +00003403 wake_up(&cam->wait_stream);
Luca Risolia3770be32007-06-13 14:37:50 -03003404 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 cam->state |= DEV_DISCONNECTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406
Luca Risolia3770be32007-06-13 14:37:50 -03003407 wake_up_interruptible_all(&cam->wait_open);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408
Luca Risolia3770be32007-06-13 14:37:50 -03003409 kref_put(&cam->kref, sn9c102_release_resources);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410
Luca Risolia3770be32007-06-13 14:37:50 -03003411 up_write(&sn9c102_dev_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412}
3413
3414
3415static struct usb_driver sn9c102_usb_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 .name = "sn9c102",
3417 .id_table = sn9c102_id_table,
3418 .probe = sn9c102_usb_probe,
3419 .disconnect = sn9c102_usb_disconnect,
3420};
3421
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08003422module_usb_driver(sn9c102_usb_driver);