aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/sn9c102
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2006-03-25 07:05:39 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-03-25 07:29:04 -0500
commit9f6933be665ce3b049c274c99810ac754edabf19 (patch)
tree70a670d030c5d5a4175076724e4720a5b967e2bc /drivers/media/video/sn9c102
parent7fa033b103bc3f5c37f934695473f63adf140dba (diff)
V4L/DVB (3599a): Move drivers/usb/media to drivers/media/video
Because of historic reasons, there are two separate directories with V4L stuff. Most drivers are located at driver/media/video. However, some code for USB Webcams were inserted under drivers/usb/media. This makes difficult for module authors to know were things should be. Also, makes Kconfig menu confusing for normal users. This patch moves all V4L content under drivers/usb/media to drivers/media/video, and fixes Kconfig/Makefile entries. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/sn9c102')
-rw-r--r--drivers/media/video/sn9c102/Makefile7
-rw-r--r--drivers/media/video/sn9c102/sn9c102.h218
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c2919
-rw-r--r--drivers/media/video/sn9c102/sn9c102_hv7131d.c271
-rw-r--r--drivers/media/video/sn9c102/sn9c102_mi0343.c363
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7630.c401
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas106b.c307
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas202bca.c238
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas202bcb.c293
-rw-r--r--drivers/media/video/sn9c102/sn9c102_sensor.h389
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5110c1b.c159
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5130d1b.c169
12 files changed, 5734 insertions, 0 deletions
diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile
new file mode 100644
index 000000000000..8bcb0f71d69f
--- /dev/null
+++ b/drivers/media/video/sn9c102/Makefile
@@ -0,0 +1,7 @@
1sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \
2 sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \
3 sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \
4 sn9c102_tas5130d1b.o
5
6obj-$(CONFIG_USB_SN9C102) += sn9c102.o
7
diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h
new file mode 100644
index 000000000000..1d70a62b9f23
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102.h
@@ -0,0 +1,218 @@
1/***************************************************************************
2 * V4L2 driver for SN9C10x PC Camera Controllers *
3 * *
4 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * *
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#ifndef _SN9C102_H_
22#define _SN9C102_H_
23
24#include <linux/version.h>
25#include <linux/usb.h>
26#include <linux/videodev2.h>
27#include <media/v4l2-common.h>
28#include <linux/device.h>
29#include <linux/list.h>
30#include <linux/spinlock.h>
31#include <linux/time.h>
32#include <linux/wait.h>
33#include <linux/types.h>
34#include <linux/param.h>
35#include <linux/rwsem.h>
36#include <linux/mutex.h>
37#include <linux/string.h>
38#include <linux/stddef.h>
39
40#include "sn9c102_sensor.h"
41
42/*****************************************************************************/
43
44#define SN9C102_DEBUG
45#define SN9C102_DEBUG_LEVEL 2
46#define SN9C102_MAX_DEVICES 64
47#define SN9C102_PRESERVE_IMGSCALE 0
48#define SN9C102_FORCE_MUNMAP 0
49#define SN9C102_MAX_FRAMES 32
50#define SN9C102_URBS 2
51#define SN9C102_ISO_PACKETS 7
52#define SN9C102_ALTERNATE_SETTING 8
53#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
54#define SN9C102_CTRL_TIMEOUT 300
55#define SN9C102_FRAME_TIMEOUT 2
56
57/*****************************************************************************/
58
59enum sn9c102_bridge {
60 BRIDGE_SN9C101 = 0x01,
61 BRIDGE_SN9C102 = 0x02,
62 BRIDGE_SN9C103 = 0x04,
63};
64
65SN9C102_ID_TABLE
66SN9C102_SENSOR_TABLE
67
68enum sn9c102_frame_state {
69 F_UNUSED,
70 F_QUEUED,
71 F_GRABBING,
72 F_DONE,
73 F_ERROR,
74};
75
76struct sn9c102_frame_t {
77 void* bufmem;
78 struct v4l2_buffer buf;
79 enum sn9c102_frame_state state;
80 struct list_head frame;
81 unsigned long vma_use_count;
82};
83
84enum sn9c102_dev_state {
85 DEV_INITIALIZED = 0x01,
86 DEV_DISCONNECTED = 0x02,
87 DEV_MISCONFIGURED = 0x04,
88};
89
90enum sn9c102_io_method {
91 IO_NONE,
92 IO_READ,
93 IO_MMAP,
94};
95
96enum sn9c102_stream_state {
97 STREAM_OFF,
98 STREAM_INTERRUPT,
99 STREAM_ON,
100};
101
102typedef char sn9c103_sof_header_t[18];
103typedef char sn9c102_sof_header_t[12];
104typedef char sn9c102_eof_header_t[4];
105
106struct sn9c102_sysfs_attr {
107 u8 reg, i2c_reg;
108 sn9c103_sof_header_t frame_header;
109};
110
111struct sn9c102_module_param {
112 u8 force_munmap;
113 u16 frame_timeout;
114};
115
116static DEFINE_MUTEX(sn9c102_sysfs_lock);
117static DECLARE_RWSEM(sn9c102_disconnect);
118
119struct sn9c102_device {
120 struct video_device* v4ldev;
121
122 enum sn9c102_bridge bridge;
123 struct sn9c102_sensor sensor;
124
125 struct usb_device* usbdev;
126 struct urb* urb[SN9C102_URBS];
127 void* transfer_buffer[SN9C102_URBS];
128 u8* control_buffer;
129
130 struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES];
131 struct list_head inqueue, outqueue;
132 u32 frame_count, nbuffers, nreadbuffers;
133
134 enum sn9c102_io_method io;
135 enum sn9c102_stream_state stream;
136
137 struct v4l2_jpegcompression compression;
138
139 struct sn9c102_sysfs_attr sysfs;
140 sn9c103_sof_header_t sof_header;
141 u16 reg[63];
142
143 struct sn9c102_module_param module_param;
144
145 enum sn9c102_dev_state state;
146 u8 users;
147
148 struct mutex dev_mutex, fileop_mutex;
149 spinlock_t queue_lock;
150 wait_queue_head_t open, wait_frame, wait_stream;
151};
152
153/*****************************************************************************/
154
155struct sn9c102_device*
156sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
157{
158 if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id))
159 return cam;
160
161 return NULL;
162}
163
164
165void
166sn9c102_attach_sensor(struct sn9c102_device* cam,
167 struct sn9c102_sensor* sensor)
168{
169 memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
170}
171
172/*****************************************************************************/
173
174#undef DBG
175#undef KDBG
176#ifdef SN9C102_DEBUG
177# define DBG(level, fmt, args...) \
178do { \
179 if (debug >= (level)) { \
180 if ((level) == 1) \
181 dev_err(&cam->usbdev->dev, fmt "\n", ## args); \
182 else if ((level) == 2) \
183 dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
184 else if ((level) >= 3) \
185 dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
186 __FUNCTION__, __LINE__ , ## args); \
187 } \
188} while (0)
189# define V4LDBG(level, name, cmd) \
190do { \
191 if (debug >= (level)) \
192 v4l_print_ioctl(name, cmd); \
193} while (0)
194# define KDBG(level, fmt, args...) \
195do { \
196 if (debug >= (level)) { \
197 if ((level) == 1 || (level) == 2) \
198 pr_info("sn9c102: " fmt "\n", ## args); \
199 else if ((level) == 3) \
200 pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \
201 __LINE__ , ## args); \
202 } \
203} while (0)
204#else
205# define DBG(level, fmt, args...) do {;} while(0)
206# define V4LDBG(level, name, cmd) do {;} while(0)
207# define KDBG(level, fmt, args...) do {;} while(0)
208#endif
209
210#undef PDBG
211#define PDBG(fmt, args...) \
212dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
213 __FUNCTION__, __LINE__ , ## args)
214
215#undef PDBGG
216#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
217
218#endif /* _SN9C102_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
new file mode 100644
index 000000000000..4c6cc6395723
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -0,0 +1,2919 @@
1/***************************************************************************
2 * V4L2 driver for SN9C10x PC Camera Controllers *
3 * *
4 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * *
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>
25#include <linux/moduleparam.h>
26#include <linux/errno.h>
27#include <linux/slab.h>
28#include <linux/device.h>
29#include <linux/fs.h>
30#include <linux/delay.h>
31#include <linux/compiler.h>
32#include <linux/ioctl.h>
33#include <linux/poll.h>
34#include <linux/stat.h>
35#include <linux/mm.h>
36#include <linux/vmalloc.h>
37#include <linux/page-flags.h>
38#include <linux/byteorder/generic.h>
39#include <asm/page.h>
40#include <asm/uaccess.h>
41
42#include "sn9c102.h"
43
44/*****************************************************************************/
45
46#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers"
47#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia"
48#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
49#define SN9C102_MODULE_LICENSE "GPL"
50#define SN9C102_MODULE_VERSION "1:1.27"
51#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 27)
52
53/*****************************************************************************/
54
55MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
56
57MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
58MODULE_DESCRIPTION(SN9C102_MODULE_NAME);
59MODULE_VERSION(SN9C102_MODULE_VERSION);
60MODULE_LICENSE(SN9C102_MODULE_LICENSE);
61
62static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};
63module_param_array(video_nr, short, NULL, 0444);
64MODULE_PARM_DESC(video_nr,
65 "\n<-1|n[,...]> Specify V4L2 minor mode number."
66 "\n -1 = use next available (default)"
67 "\n n = use minor number n (integer >= 0)"
68 "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
69 " cameras this way."
70 "\nFor example:"
71 "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
72 "\nthe second camera and use auto for the first"
73 "\none and for every other camera."
74 "\n");
75
76static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
77 SN9C102_FORCE_MUNMAP};
78module_param_array(force_munmap, bool, NULL, 0444);
79MODULE_PARM_DESC(force_munmap,
80 "\n<0|1[,...]> Force the application to unmap previously"
81 "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
82 "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
83 "\nthis feature. This parameter is specific for each"
84 "\ndetected camera."
85 "\n 0 = do not force memory unmapping"
86 "\n 1 = force memory unmapping (save memory)"
87 "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
88 "\n");
89
90static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
91 SN9C102_FRAME_TIMEOUT};
92module_param_array(frame_timeout, uint, NULL, 0644);
93MODULE_PARM_DESC(frame_timeout,
94 "\n<n[,...]> Timeout for a video frame in seconds."
95 "\nThis parameter is specific for each detected camera."
96 "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
97 "\n");
98
99#ifdef SN9C102_DEBUG
100static unsigned short debug = SN9C102_DEBUG_LEVEL;
101module_param(debug, ushort, 0644);
102MODULE_PARM_DESC(debug,
103 "\n<n> Debugging information level, from 0 to 3:"
104 "\n0 = none (use carefully)"
105 "\n1 = critical errors"
106 "\n2 = significant informations"
107 "\n3 = more verbose messages"
108 "\nLevel 3 is useful for testing only, when only "
109 "one device is used."
110 "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
111 "\n");
112#endif
113
114/*****************************************************************************/
115
116static sn9c102_sof_header_t sn9c102_sof_header[] = {
117 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00},
118 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01},
119};
120
121static sn9c103_sof_header_t sn9c103_sof_header[] = {
122 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x20},
123};
124
125static sn9c102_eof_header_t sn9c102_eof_header[] = {
126 {0x00, 0x00, 0x00, 0x00},
127 {0x40, 0x00, 0x00, 0x00},
128 {0x80, 0x00, 0x00, 0x00},
129 {0xc0, 0x00, 0x00, 0x00},
130};
131
132/*****************************************************************************/
133
134static u32
135sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
136 enum sn9c102_io_method io)
137{
138 struct v4l2_pix_format* p = &(cam->sensor.pix_format);
139 struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
140 const size_t imagesize = cam->module_param.force_munmap ||
141 io == IO_READ ?
142 (p->width * p->height * p->priv) / 8 :
143 (r->width * r->height * p->priv) / 8;
144 void* buff = NULL;
145 u32 i;
146
147 if (count > SN9C102_MAX_FRAMES)
148 count = SN9C102_MAX_FRAMES;
149
150 cam->nbuffers = count;
151 while (cam->nbuffers > 0) {
152 if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
153 break;
154 cam->nbuffers--;
155 }
156
157 for (i = 0; i < cam->nbuffers; i++) {
158 cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize);
159 cam->frame[i].buf.index = i;
160 cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize);
161 cam->frame[i].buf.length = imagesize;
162 cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
163 cam->frame[i].buf.sequence = 0;
164 cam->frame[i].buf.field = V4L2_FIELD_NONE;
165 cam->frame[i].buf.memory = V4L2_MEMORY_MMAP;
166 cam->frame[i].buf.flags = 0;
167 }
168
169 return cam->nbuffers;
170}
171
172
173static void sn9c102_release_buffers(struct sn9c102_device* cam)
174{
175 if (cam->nbuffers) {
176 vfree(cam->frame[0].bufmem);
177 cam->nbuffers = 0;
178 }
179 cam->frame_current = NULL;
180}
181
182
183static void sn9c102_empty_framequeues(struct sn9c102_device* cam)
184{
185 u32 i;
186
187 INIT_LIST_HEAD(&cam->inqueue);
188 INIT_LIST_HEAD(&cam->outqueue);
189
190 for (i = 0; i < SN9C102_MAX_FRAMES; i++) {
191 cam->frame[i].state = F_UNUSED;
192 cam->frame[i].buf.bytesused = 0;
193 }
194}
195
196
197static void sn9c102_requeue_outqueue(struct sn9c102_device* cam)
198{
199 struct sn9c102_frame_t *i;
200
201 list_for_each_entry(i, &cam->outqueue, frame) {
202 i->state = F_QUEUED;
203 list_add(&i->frame, &cam->inqueue);
204 }
205
206 INIT_LIST_HEAD(&cam->outqueue);
207}
208
209
210static void sn9c102_queue_unusedframes(struct sn9c102_device* cam)
211{
212 unsigned long lock_flags;
213 u32 i;
214
215 for (i = 0; i < cam->nbuffers; i++)
216 if (cam->frame[i].state == F_UNUSED) {
217 cam->frame[i].state = F_QUEUED;
218 spin_lock_irqsave(&cam->queue_lock, lock_flags);
219 list_add_tail(&cam->frame[i].frame, &cam->inqueue);
220 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
221 }
222}
223
224/*****************************************************************************/
225
226int sn9c102_write_regs(struct sn9c102_device* cam, u8* buff, u16 index)
227{
228 struct usb_device* udev = cam->usbdev;
229 int i, res;
230
231 if (index + sizeof(buff) >= ARRAY_SIZE(cam->reg))
232 return -1;
233
234 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
235 index, 0, buff, sizeof(buff),
236 SN9C102_CTRL_TIMEOUT*sizeof(buff));
237 if (res < 0) {
238 DBG(3, "Failed to write registers (index 0x%02X, error %d)",
239 index, res);
240 return -1;
241 }
242
243 for (i = 0; i < sizeof(buff); i++)
244 cam->reg[index+i] = buff[i];
245
246 return 0;
247}
248
249
250int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
251{
252 struct usb_device* udev = cam->usbdev;
253 u8* buff = cam->control_buffer;
254 int res;
255
256 if (index >= ARRAY_SIZE(cam->reg))
257 return -1;
258
259 *buff = value;
260
261 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
262 index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
263 if (res < 0) {
264 DBG(3, "Failed to write a register (value 0x%02X, index "
265 "0x%02X, error %d)", value, index, res);
266 return -1;
267 }
268
269 cam->reg[index] = value;
270
271 return 0;
272}
273
274
275/* NOTE: reading some registers always returns 0 */
276static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
277{
278 struct usb_device* udev = cam->usbdev;
279 u8* buff = cam->control_buffer;
280 int res;
281
282 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
283 index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
284 if (res < 0)
285 DBG(3, "Failed to read a register (index 0x%02X, error %d)",
286 index, res);
287
288 return (res >= 0) ? (int)(*buff) : -1;
289}
290
291
292int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index)
293{
294 if (index >= ARRAY_SIZE(cam->reg))
295 return -1;
296
297 return cam->reg[index];
298}
299
300
301static int
302sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor)
303{
304 int i, r;
305
306 for (i = 1; i <= 5; i++) {
307 r = sn9c102_read_reg(cam, 0x08);
308 if (r < 0)
309 return -EIO;
310 if (r & 0x04)
311 return 0;
312 if (sensor->frequency & SN9C102_I2C_400KHZ)
313 udelay(5*16);
314 else
315 udelay(16*16);
316 }
317 return -EBUSY;
318}
319
320
321static int
322sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
323 struct sn9c102_sensor* sensor)
324{
325 int r;
326 r = sn9c102_read_reg(cam, 0x08);
327 return (r < 0 || (r >= 0 && !(r & 0x08))) ? -EIO : 0;
328}
329
330
331static int
332sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
333 struct sn9c102_sensor* sensor)
334{
335 int r;
336 r = sn9c102_read_reg(cam, 0x08);
337 return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0;
338}
339
340
341int
342sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
343 struct sn9c102_sensor* sensor, u8 data0, u8 data1,
344 u8 n, u8 buffer[])
345{
346 struct usb_device* udev = cam->usbdev;
347 u8* data = cam->control_buffer;
348 int err = 0, res;
349
350 /* Write cycle */
351 data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
352 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10;
353 data[1] = data0; /* I2C slave id */
354 data[2] = data1; /* address */
355 data[7] = 0x10;
356 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
357 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
358 if (res < 0)
359 err += res;
360
361 err += sn9c102_i2c_wait(cam, sensor);
362
363 /* Read cycle - n bytes */
364 data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
365 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) |
366 (n << 4) | 0x02;
367 data[1] = data0;
368 data[7] = 0x10;
369 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
370 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
371 if (res < 0)
372 err += res;
373
374 err += sn9c102_i2c_wait(cam, sensor);
375
376 /* The first read byte will be placed in data[4] */
377 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
378 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT);
379 if (res < 0)
380 err += res;
381
382 err += sn9c102_i2c_detect_read_error(cam, sensor);
383
384 PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1,
385 data[4]);
386
387 if (err) {
388 DBG(3, "I2C read failed for %s image sensor", sensor->name);
389 return -1;
390 }
391
392 if (buffer)
393 memcpy(buffer, data, sizeof(buffer));
394
395 return (int)data[4];
396}
397
398
399int
400sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
401 struct sn9c102_sensor* sensor, u8 n, u8 data0,
402 u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
403{
404 struct usb_device* udev = cam->usbdev;
405 u8* data = cam->control_buffer;
406 int err = 0, res;
407
408 /* Write cycle. It usually is address + value */
409 data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
410 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0)
411 | ((n - 1) << 4);
412 data[1] = data0;
413 data[2] = data1;
414 data[3] = data2;
415 data[4] = data3;
416 data[5] = data4;
417 data[6] = data5;
418 data[7] = 0x14;
419 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
420 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
421 if (res < 0)
422 err += res;
423
424 err += sn9c102_i2c_wait(cam, sensor);
425 err += sn9c102_i2c_detect_write_error(cam, sensor);
426
427 if (err)
428 DBG(3, "I2C write failed for %s image sensor", sensor->name);
429
430 PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, "
431 "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X",
432 n, data0, data1, data2, data3, data4, data5);
433
434 return err ? -1 : 0;
435}
436
437
438int
439sn9c102_i2c_try_read(struct sn9c102_device* cam,
440 struct sn9c102_sensor* sensor, u8 address)
441{
442 return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
443 address, 1, NULL);
444}
445
446
447int
448sn9c102_i2c_try_write(struct sn9c102_device* cam,
449 struct sn9c102_sensor* sensor, u8 address, u8 value)
450{
451 return sn9c102_i2c_try_raw_write(cam, sensor, 3,
452 sensor->i2c_slave_id, address,
453 value, 0, 0, 0);
454}
455
456
457int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address)
458{
459 return sn9c102_i2c_try_read(cam, &cam->sensor, address);
460}
461
462
463int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value)
464{
465 return sn9c102_i2c_try_write(cam, &cam->sensor, address, value);
466}
467
468/*****************************************************************************/
469
470static void*
471sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
472{
473 size_t soflen = 0, i;
474 u8 j, n = 0;
475
476 switch (cam->bridge) {
477 case BRIDGE_SN9C101:
478 case BRIDGE_SN9C102:
479 soflen = sizeof(sn9c102_sof_header_t);
480 n = sizeof(sn9c102_sof_header) / soflen;
481 break;
482 case BRIDGE_SN9C103:
483 soflen = sizeof(sn9c103_sof_header_t);
484 n = sizeof(sn9c103_sof_header) / soflen;
485 }
486
487 for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
488 for (j = 0; j < n; j++)
489 /* The invariable part of the header is 6 bytes long */
490 if ((cam->bridge != BRIDGE_SN9C103 &&
491 !memcmp(mem + i, sn9c102_sof_header[j], 6)) ||
492 (cam->bridge == BRIDGE_SN9C103 &&
493 !memcmp(mem + i, sn9c103_sof_header[j], 6))) {
494 memcpy(cam->sof_header, mem + i, soflen);
495 /* Skip the header */
496 return mem + i + soflen;
497 }
498
499 return NULL;
500}
501
502
503static void*
504sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
505{
506 size_t eoflen = sizeof(sn9c102_eof_header_t), i;
507 unsigned j, n = sizeof(sn9c102_eof_header) / eoflen;
508
509 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
510 return NULL; /* EOF header does not exist in compressed data */
511
512 for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++)
513 for (j = 0; j < n; j++)
514 if (!memcmp(mem + i, sn9c102_eof_header[j], eoflen))
515 return mem + i;
516
517 return NULL;
518}
519
520
521static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
522{
523 struct sn9c102_device* cam = urb->context;
524 struct sn9c102_frame_t** f;
525 size_t imagesize, soflen;
526 u8 i;
527 int err = 0;
528
529 if (urb->status == -ENOENT)
530 return;
531
532 f = &cam->frame_current;
533
534 if (cam->stream == STREAM_INTERRUPT) {
535 cam->stream = STREAM_OFF;
536 if ((*f))
537 (*f)->state = F_QUEUED;
538 DBG(3, "Stream interrupted");
539 wake_up(&cam->wait_stream);
540 }
541
542 if (cam->state & DEV_DISCONNECTED)
543 return;
544
545 if (cam->state & DEV_MISCONFIGURED) {
546 wake_up_interruptible(&cam->wait_frame);
547 return;
548 }
549
550 if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue))
551 goto resubmit_urb;
552
553 if (!(*f))
554 (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
555 frame);
556
557 imagesize = (cam->sensor.pix_format.width *
558 cam->sensor.pix_format.height *
559 cam->sensor.pix_format.priv) / 8;
560
561 soflen = (cam->bridge) == BRIDGE_SN9C103 ?
562 sizeof(sn9c103_sof_header_t) :
563 sizeof(sn9c102_sof_header_t);
564
565 for (i = 0; i < urb->number_of_packets; i++) {
566 unsigned int img, len, status;
567 void *pos, *sof, *eof;
568
569 len = urb->iso_frame_desc[i].actual_length;
570 status = urb->iso_frame_desc[i].status;
571 pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer;
572
573 if (status) {
574 DBG(3, "Error in isochronous frame");
575 (*f)->state = F_ERROR;
576 continue;
577 }
578
579 PDBGG("Isochrnous frame: length %u, #%u i", len, i);
580
581redo:
582 sof = sn9c102_find_sof_header(cam, pos, len);
583 if (likely(!sof)) {
584 eof = sn9c102_find_eof_header(cam, pos, len);
585 if ((*f)->state == F_GRABBING) {
586end_of_frame:
587 img = len;
588
589 if (eof)
590 img = (eof > pos) ? eof - pos - 1 : 0;
591
592 if ((*f)->buf.bytesused+img > imagesize) {
593 u32 b;
594 b = (*f)->buf.bytesused + img -
595 imagesize;
596 img = imagesize - (*f)->buf.bytesused;
597 DBG(3, "Expected EOF not found: "
598 "video frame cut");
599 if (eof)
600 DBG(3, "Exceeded limit: +%u "
601 "bytes", (unsigned)(b));
602 }
603
604 memcpy((*f)->bufmem + (*f)->buf.bytesused, pos,
605 img);
606
607 if ((*f)->buf.bytesused == 0)
608 do_gettimeofday(&(*f)->buf.timestamp);
609
610 (*f)->buf.bytesused += img;
611
612 if ((*f)->buf.bytesused == imagesize ||
613 (cam->sensor.pix_format.pixelformat ==
614 V4L2_PIX_FMT_SN9C10X && eof)) {
615 u32 b;
616 b = (*f)->buf.bytesused;
617 (*f)->state = F_DONE;
618 (*f)->buf.sequence= ++cam->frame_count;
619 spin_lock(&cam->queue_lock);
620 list_move_tail(&(*f)->frame,
621 &cam->outqueue);
622 if (!list_empty(&cam->inqueue))
623 (*f) = list_entry(
624 cam->inqueue.next,
625 struct sn9c102_frame_t,
626 frame );
627 else
628 (*f) = NULL;
629 spin_unlock(&cam->queue_lock);
630 memcpy(cam->sysfs.frame_header,
631 cam->sof_header, soflen);
632 DBG(3, "Video frame captured: %lu "
633 "bytes", (unsigned long)(b));
634
635 if (!(*f))
636 goto resubmit_urb;
637
638 } else if (eof) {
639 (*f)->state = F_ERROR;
640 DBG(3, "Not expected EOF after %lu "
641 "bytes of image data",
642 (unsigned long)
643 ((*f)->buf.bytesused));
644 }
645
646 if (sof) /* (1) */
647 goto start_of_frame;
648
649 } else if (eof) {
650 DBG(3, "EOF without SOF");
651 continue;
652
653 } else {
654 PDBGG("Ignoring pointless isochronous frame");
655 continue;
656 }
657
658 } else if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) {
659start_of_frame:
660 (*f)->state = F_GRABBING;
661 (*f)->buf.bytesused = 0;
662 len -= (sof - pos);
663 pos = sof;
664 DBG(3, "SOF detected: new video frame");
665 if (len)
666 goto redo;
667
668 } else if ((*f)->state == F_GRABBING) {
669 eof = sn9c102_find_eof_header(cam, pos, len);
670 if (eof && eof < sof)
671 goto end_of_frame; /* (1) */
672 else {
673 if (cam->sensor.pix_format.pixelformat ==
674 V4L2_PIX_FMT_SN9C10X) {
675 eof = sof - soflen;
676 goto end_of_frame;
677 } else {
678 DBG(3, "SOF before expected EOF after "
679 "%lu bytes of image data",
680 (unsigned long)
681 ((*f)->buf.bytesused));
682 goto start_of_frame;
683 }
684 }
685 }
686 }
687
688resubmit_urb:
689 urb->dev = cam->usbdev;
690 err = usb_submit_urb(urb, GFP_ATOMIC);
691 if (err < 0 && err != -EPERM) {
692 cam->state |= DEV_MISCONFIGURED;
693 DBG(1, "usb_submit_urb() failed");
694 }
695
696 wake_up_interruptible(&cam->wait_frame);
697}
698
699
700static int sn9c102_start_transfer(struct sn9c102_device* cam)
701{
702 struct usb_device *udev = cam->usbdev;
703 struct urb* urb;
704 const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512,
705 680, 800, 900, 1023};
706 const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512,
707 680, 800, 900, 1003};
708 const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ?
709 sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] :
710 sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING];
711 s8 i, j;
712 int err = 0;
713
714 for (i = 0; i < SN9C102_URBS; i++) {
715 cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz,
716 GFP_KERNEL);
717 if (!cam->transfer_buffer[i]) {
718 err = -ENOMEM;
719 DBG(1, "Not enough memory");
720 goto free_buffers;
721 }
722 }
723
724 for (i = 0; i < SN9C102_URBS; i++) {
725 urb = usb_alloc_urb(SN9C102_ISO_PACKETS, GFP_KERNEL);
726 cam->urb[i] = urb;
727 if (!urb) {
728 err = -ENOMEM;
729 DBG(1, "usb_alloc_urb() failed");
730 goto free_urbs;
731 }
732 urb->dev = udev;
733 urb->context = cam;
734 urb->pipe = usb_rcvisocpipe(udev, 1);
735 urb->transfer_flags = URB_ISO_ASAP;
736 urb->number_of_packets = SN9C102_ISO_PACKETS;
737 urb->complete = sn9c102_urb_complete;
738 urb->transfer_buffer = cam->transfer_buffer[i];
739 urb->transfer_buffer_length = psz * SN9C102_ISO_PACKETS;
740 urb->interval = 1;
741 for (j = 0; j < SN9C102_ISO_PACKETS; j++) {
742 urb->iso_frame_desc[j].offset = psz * j;
743 urb->iso_frame_desc[j].length = psz;
744 }
745 }
746
747 /* Enable video */
748 if (!(cam->reg[0x01] & 0x04)) {
749 err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01);
750 if (err) {
751 err = -EIO;
752 DBG(1, "I/O hardware error");
753 goto free_urbs;
754 }
755 }
756
757 err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING);
758 if (err) {
759 DBG(1, "usb_set_interface() failed");
760 goto free_urbs;
761 }
762
763 cam->frame_current = NULL;
764
765 for (i = 0; i < SN9C102_URBS; i++) {
766 err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
767 if (err) {
768 for (j = i-1; j >= 0; j--)
769 usb_kill_urb(cam->urb[j]);
770 DBG(1, "usb_submit_urb() failed, error %d", err);
771 goto free_urbs;
772 }
773 }
774
775 return 0;
776
777free_urbs:
778 for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++)
779 usb_free_urb(cam->urb[i]);
780
781free_buffers:
782 for (i = 0; (i < SN9C102_URBS) && cam->transfer_buffer[i]; i++)
783 kfree(cam->transfer_buffer[i]);
784
785 return err;
786}
787
788
789static int sn9c102_stop_transfer(struct sn9c102_device* cam)
790{
791 struct usb_device *udev = cam->usbdev;
792 s8 i;
793 int err = 0;
794
795 if (cam->state & DEV_DISCONNECTED)
796 return 0;
797
798 for (i = SN9C102_URBS-1; i >= 0; i--) {
799 usb_kill_urb(cam->urb[i]);
800 usb_free_urb(cam->urb[i]);
801 kfree(cam->transfer_buffer[i]);
802 }
803
804 err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */
805 if (err)
806 DBG(3, "usb_set_interface() failed");
807
808 return err;
809}
810
811
812static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
813{
814 long timeout;
815
816 cam->stream = STREAM_INTERRUPT;
817 timeout = wait_event_timeout(cam->wait_stream,
818 (cam->stream == STREAM_OFF) ||
819 (cam->state & DEV_DISCONNECTED),
820 SN9C102_URB_TIMEOUT);
821 if (cam->state & DEV_DISCONNECTED)
822 return -ENODEV;
823 else if (cam->stream != STREAM_OFF) {
824 cam->state |= DEV_MISCONFIGURED;
825 DBG(1, "URB timeout reached. The camera is misconfigured. "
826 "To use it, close and open /dev/video%d again.",
827 cam->v4ldev->minor);
828 return -EIO;
829 }
830
831 return 0;
832}
833
834/*****************************************************************************/
835
836#ifdef CONFIG_VIDEO_ADV_DEBUG
837static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count)
838{
839 char str[5];
840 char* endp;
841 unsigned long val;
842
843 if (len < 4) {
844 strncpy(str, buff, len);
845 str[len+1] = '\0';
846 } else {
847 strncpy(str, buff, 4);
848 str[4] = '\0';
849 }
850
851 val = simple_strtoul(str, &endp, 0);
852
853 *count = 0;
854 if (val <= 0xff)
855 *count = (ssize_t)(endp - str);
856 if ((*count) && (len == *count+1) && (buff[*count] == '\n'))
857 *count += 1;
858
859 return (u8)val;
860}
861
862/*
863 NOTE 1: being inside one of the following methods implies that the v4l
864 device exists for sure (see kobjects and reference counters)
865 NOTE 2: buffers are PAGE_SIZE long
866*/
867
868static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf)
869{
870 struct sn9c102_device* cam;
871 ssize_t count;
872
873 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
874 return -ERESTARTSYS;
875
876 cam = video_get_drvdata(to_video_device(cd));
877 if (!cam) {
878 mutex_unlock(&sn9c102_sysfs_lock);
879 return -ENODEV;
880 }
881
882 count = sprintf(buf, "%u\n", cam->sysfs.reg);
883
884 mutex_unlock(&sn9c102_sysfs_lock);
885
886 return count;
887}
888
889
890static ssize_t
891sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len)
892{
893 struct sn9c102_device* cam;
894 u8 index;
895 ssize_t count;
896
897 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
898 return -ERESTARTSYS;
899
900 cam = video_get_drvdata(to_video_device(cd));
901 if (!cam) {
902 mutex_unlock(&sn9c102_sysfs_lock);
903 return -ENODEV;
904 }
905
906 index = sn9c102_strtou8(buf, len, &count);
907 if (index > 0x1f || !count) {
908 mutex_unlock(&sn9c102_sysfs_lock);
909 return -EINVAL;
910 }
911
912 cam->sysfs.reg = index;
913
914 DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg);
915 DBG(3, "Written bytes: %zd", count);
916
917 mutex_unlock(&sn9c102_sysfs_lock);
918
919 return count;
920}
921
922
923static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
924{
925 struct sn9c102_device* cam;
926 ssize_t count;
927 int val;
928
929 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
930 return -ERESTARTSYS;
931
932 cam = video_get_drvdata(to_video_device(cd));
933 if (!cam) {
934 mutex_unlock(&sn9c102_sysfs_lock);
935 return -ENODEV;
936 }
937
938 if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) {
939 mutex_unlock(&sn9c102_sysfs_lock);
940 return -EIO;
941 }
942
943 count = sprintf(buf, "%d\n", val);
944
945 DBG(3, "Read bytes: %zd", count);
946
947 mutex_unlock(&sn9c102_sysfs_lock);
948
949 return count;
950}
951
952
953static ssize_t
954sn9c102_store_val(struct class_device* cd, const char* buf, size_t len)
955{
956 struct sn9c102_device* cam;
957 u8 value;
958 ssize_t count;
959 int err;
960
961 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
962 return -ERESTARTSYS;
963
964 cam = video_get_drvdata(to_video_device(cd));
965 if (!cam) {
966 mutex_unlock(&sn9c102_sysfs_lock);
967 return -ENODEV;
968 }
969
970 value = sn9c102_strtou8(buf, len, &count);
971 if (!count) {
972 mutex_unlock(&sn9c102_sysfs_lock);
973 return -EINVAL;
974 }
975
976 err = sn9c102_write_reg(cam, value, cam->sysfs.reg);
977 if (err) {
978 mutex_unlock(&sn9c102_sysfs_lock);
979 return -EIO;
980 }
981
982 DBG(2, "Written SN9C10X reg. 0x%02X, val. 0x%02X",
983 cam->sysfs.reg, value);
984 DBG(3, "Written bytes: %zd", count);
985
986 mutex_unlock(&sn9c102_sysfs_lock);
987
988 return count;
989}
990
991
992static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf)
993{
994 struct sn9c102_device* cam;
995 ssize_t count;
996
997 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
998 return -ERESTARTSYS;
999
1000 cam = video_get_drvdata(to_video_device(cd));
1001 if (!cam) {
1002 mutex_unlock(&sn9c102_sysfs_lock);
1003 return -ENODEV;
1004 }
1005
1006 count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg);
1007
1008 DBG(3, "Read bytes: %zd", count);
1009
1010 mutex_unlock(&sn9c102_sysfs_lock);
1011
1012 return count;
1013}
1014
1015
1016static ssize_t
1017sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len)
1018{
1019 struct sn9c102_device* cam;
1020 u8 index;
1021 ssize_t count;
1022
1023 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1024 return -ERESTARTSYS;
1025
1026 cam = video_get_drvdata(to_video_device(cd));
1027 if (!cam) {
1028 mutex_unlock(&sn9c102_sysfs_lock);
1029 return -ENODEV;
1030 }
1031
1032 index = sn9c102_strtou8(buf, len, &count);
1033 if (!count) {
1034 mutex_unlock(&sn9c102_sysfs_lock);
1035 return -EINVAL;
1036 }
1037
1038 cam->sysfs.i2c_reg = index;
1039
1040 DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
1041 DBG(3, "Written bytes: %zd", count);
1042
1043 mutex_unlock(&sn9c102_sysfs_lock);
1044
1045 return count;
1046}
1047
1048
1049static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
1050{
1051 struct sn9c102_device* cam;
1052 ssize_t count;
1053 int val;
1054
1055 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1056 return -ERESTARTSYS;
1057
1058 cam = video_get_drvdata(to_video_device(cd));
1059 if (!cam) {
1060 mutex_unlock(&sn9c102_sysfs_lock);
1061 return -ENODEV;
1062 }
1063
1064 if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) {
1065 mutex_unlock(&sn9c102_sysfs_lock);
1066 return -ENOSYS;
1067 }
1068
1069 if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) {
1070 mutex_unlock(&sn9c102_sysfs_lock);
1071 return -EIO;
1072 }
1073
1074 count = sprintf(buf, "%d\n", val);
1075
1076 DBG(3, "Read bytes: %zd", count);
1077
1078 mutex_unlock(&sn9c102_sysfs_lock);
1079
1080 return count;
1081}
1082
1083
1084static ssize_t
1085sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
1086{
1087 struct sn9c102_device* cam;
1088 u8 value;
1089 ssize_t count;
1090 int err;
1091
1092 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1093 return -ERESTARTSYS;
1094
1095 cam = video_get_drvdata(to_video_device(cd));
1096 if (!cam) {
1097 mutex_unlock(&sn9c102_sysfs_lock);
1098 return -ENODEV;
1099 }
1100
1101 if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) {
1102 mutex_unlock(&sn9c102_sysfs_lock);
1103 return -ENOSYS;
1104 }
1105
1106 value = sn9c102_strtou8(buf, len, &count);
1107 if (!count) {
1108 mutex_unlock(&sn9c102_sysfs_lock);
1109 return -EINVAL;
1110 }
1111
1112 err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value);
1113 if (err) {
1114 mutex_unlock(&sn9c102_sysfs_lock);
1115 return -EIO;
1116 }
1117
1118 DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X",
1119 cam->sysfs.i2c_reg, value);
1120 DBG(3, "Written bytes: %zd", count);
1121
1122 mutex_unlock(&sn9c102_sysfs_lock);
1123
1124 return count;
1125}
1126
1127
1128static ssize_t
1129sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
1130{
1131 struct sn9c102_device* cam;
1132 enum sn9c102_bridge bridge;
1133 ssize_t res = 0;
1134 u8 value;
1135 ssize_t count;
1136
1137 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1138 return -ERESTARTSYS;
1139
1140 cam = video_get_drvdata(to_video_device(cd));
1141 if (!cam) {
1142 mutex_unlock(&sn9c102_sysfs_lock);
1143 return -ENODEV;
1144 }
1145
1146 bridge = cam->bridge;
1147
1148 mutex_unlock(&sn9c102_sysfs_lock);
1149
1150 value = sn9c102_strtou8(buf, len, &count);
1151 if (!count)
1152 return -EINVAL;
1153
1154 switch (bridge) {
1155 case BRIDGE_SN9C101:
1156 case BRIDGE_SN9C102:
1157 if (value > 0x0f)
1158 return -EINVAL;
1159 if ((res = sn9c102_store_reg(cd, "0x11", 4)) >= 0)
1160 res = sn9c102_store_val(cd, buf, len);
1161 break;
1162 case BRIDGE_SN9C103:
1163 if (value > 0x7f)
1164 return -EINVAL;
1165 if ((res = sn9c102_store_reg(cd, "0x04", 4)) >= 0)
1166 res = sn9c102_store_val(cd, buf, len);
1167 break;
1168 }
1169
1170 return res;
1171}
1172
1173
1174static ssize_t
1175sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len)
1176{
1177 ssize_t res = 0;
1178 u8 value;
1179 ssize_t count;
1180
1181 value = sn9c102_strtou8(buf, len, &count);
1182 if (!count || value > 0x7f)
1183 return -EINVAL;
1184
1185 if ((res = sn9c102_store_reg(cd, "0x06", 4)) >= 0)
1186 res = sn9c102_store_val(cd, buf, len);
1187
1188 return res;
1189}
1190
1191
1192static ssize_t
1193sn9c102_store_red(struct class_device* cd, const char* buf, size_t len)
1194{
1195 ssize_t res = 0;
1196 u8 value;
1197 ssize_t count;
1198
1199 value = sn9c102_strtou8(buf, len, &count);
1200 if (!count || value > 0x7f)
1201 return -EINVAL;
1202
1203 if ((res = sn9c102_store_reg(cd, "0x05", 4)) >= 0)
1204 res = sn9c102_store_val(cd, buf, len);
1205
1206 return res;
1207}
1208
1209
1210static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf)
1211{
1212 struct sn9c102_device* cam;
1213 ssize_t count;
1214
1215 cam = video_get_drvdata(to_video_device(cd));
1216 if (!cam)
1217 return -ENODEV;
1218
1219 count = sizeof(cam->sysfs.frame_header);
1220 memcpy(buf, cam->sysfs.frame_header, count);
1221
1222 DBG(3, "Frame header, read bytes: %zd", count);
1223
1224 return count;
1225}
1226
1227
1228static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,
1229 sn9c102_show_reg, sn9c102_store_reg);
1230static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR,
1231 sn9c102_show_val, sn9c102_store_val);
1232static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
1233 sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
1234static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
1235 sn9c102_show_i2c_val, sn9c102_store_i2c_val);
1236static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
1237static CLASS_DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);
1238static CLASS_DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);
1239static CLASS_DEVICE_ATTR(frame_header, S_IRUGO,
1240 sn9c102_show_frame_header, NULL);
1241
1242
1243static void sn9c102_create_sysfs(struct sn9c102_device* cam)
1244{
1245 struct video_device *v4ldev = cam->v4ldev;
1246
1247 video_device_create_file(v4ldev, &class_device_attr_reg);
1248 video_device_create_file(v4ldev, &class_device_attr_val);
1249 video_device_create_file(v4ldev, &class_device_attr_frame_header);
1250 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
1251 video_device_create_file(v4ldev, &class_device_attr_green);
1252 else if (cam->bridge == BRIDGE_SN9C103) {
1253 video_device_create_file(v4ldev, &class_device_attr_blue);
1254 video_device_create_file(v4ldev, &class_device_attr_red);
1255 }
1256 if (cam->sensor.sysfs_ops) {
1257 video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
1258 video_device_create_file(v4ldev, &class_device_attr_i2c_val);
1259 }
1260}
1261#endif /* CONFIG_VIDEO_ADV_DEBUG */
1262
1263/*****************************************************************************/
1264
1265static int
1266sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix)
1267{
1268 int err = 0;
1269
1270 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
1271 err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18);
1272 else
1273 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18);
1274
1275 return err ? -EIO : 0;
1276}
1277
1278
1279static int
1280sn9c102_set_compression(struct sn9c102_device* cam,
1281 struct v4l2_jpegcompression* compression)
1282{
1283 int err = 0;
1284
1285 if (compression->quality == 0)
1286 err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17);
1287 else if (compression->quality == 1)
1288 err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17);
1289
1290 return err ? -EIO : 0;
1291}
1292
1293
1294static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale)
1295{
1296 u8 r = 0;
1297 int err = 0;
1298
1299 if (scale == 1)
1300 r = cam->reg[0x18] & 0xcf;
1301 else if (scale == 2) {
1302 r = cam->reg[0x18] & 0xcf;
1303 r |= 0x10;
1304 } else if (scale == 4)
1305 r = cam->reg[0x18] | 0x20;
1306
1307 err += sn9c102_write_reg(cam, r, 0x18);
1308 if (err)
1309 return -EIO;
1310
1311 PDBGG("Scaling factor: %u", scale);
1312
1313 return 0;
1314}
1315
1316
1317static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
1318{
1319 struct sn9c102_sensor* s = &cam->sensor;
1320 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left),
1321 v_start = (u8)(rect->top - s->cropcap.bounds.top),
1322 h_size = (u8)(rect->width / 16),
1323 v_size = (u8)(rect->height / 16);
1324 int err = 0;
1325
1326 err += sn9c102_write_reg(cam, h_start, 0x12);
1327 err += sn9c102_write_reg(cam, v_start, 0x13);
1328 err += sn9c102_write_reg(cam, h_size, 0x15);
1329 err += sn9c102_write_reg(cam, v_size, 0x16);
1330 if (err)
1331 return -EIO;
1332
1333 PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
1334 "%u %u %u %u", h_start, v_start, h_size, v_size);
1335
1336 return 0;
1337}
1338
1339
1340static int sn9c102_init(struct sn9c102_device* cam)
1341{
1342 struct sn9c102_sensor* s = &cam->sensor;
1343 struct v4l2_control ctrl;
1344 struct v4l2_queryctrl *qctrl;
1345 struct v4l2_rect* rect;
1346 u8 i = 0;
1347 int err = 0;
1348
1349 if (!(cam->state & DEV_INITIALIZED)) {
1350 init_waitqueue_head(&cam->open);
1351 qctrl = s->qctrl;
1352 rect = &(s->cropcap.defrect);
1353 } else { /* use current values */
1354 qctrl = s->_qctrl;
1355 rect = &(s->_rect);
1356 }
1357
1358 err += sn9c102_set_scale(cam, rect->width / s->pix_format.width);
1359 err += sn9c102_set_crop(cam, rect);
1360 if (err)
1361 return err;
1362
1363 if (s->init) {
1364 err = s->init(cam);
1365 if (err) {
1366 DBG(3, "Sensor initialization failed");
1367 return err;
1368 }
1369 }
1370
1371 if (!(cam->state & DEV_INITIALIZED))
1372 cam->compression.quality = cam->reg[0x17] & 0x01 ? 0 : 1;
1373 else
1374 err += sn9c102_set_compression(cam, &cam->compression);
1375 err += sn9c102_set_pix_format(cam, &s->pix_format);
1376 if (s->set_pix_format)
1377 err += s->set_pix_format(cam, &s->pix_format);
1378 if (err)
1379 return err;
1380
1381 if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
1382 DBG(3, "Compressed video format is active, quality %d",
1383 cam->compression.quality);
1384 else
1385 DBG(3, "Uncompressed video format is active");
1386
1387 if (s->set_crop)
1388 if ((err = s->set_crop(cam, rect))) {
1389 DBG(3, "set_crop() failed");
1390 return err;
1391 }
1392
1393 if (s->set_ctrl) {
1394 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
1395 if (s->qctrl[i].id != 0 &&
1396 !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {
1397 ctrl.id = s->qctrl[i].id;
1398 ctrl.value = qctrl[i].default_value;
1399 err = s->set_ctrl(cam, &ctrl);
1400 if (err) {
1401 DBG(3, "Set %s control failed",
1402 s->qctrl[i].name);
1403 return err;
1404 }
1405 DBG(3, "Image sensor supports '%s' control",
1406 s->qctrl[i].name);
1407 }
1408 }
1409
1410 if (!(cam->state & DEV_INITIALIZED)) {
1411 mutex_init(&cam->fileop_mutex);
1412 spin_lock_init(&cam->queue_lock);
1413 init_waitqueue_head(&cam->wait_frame);
1414 init_waitqueue_head(&cam->wait_stream);
1415 cam->nreadbuffers = 2;
1416 memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));
1417 memcpy(&(s->_rect), &(s->cropcap.defrect),
1418 sizeof(struct v4l2_rect));
1419 cam->state |= DEV_INITIALIZED;
1420 }
1421
1422 DBG(2, "Initialization succeeded");
1423 return 0;
1424}
1425
1426
1427static void sn9c102_release_resources(struct sn9c102_device* cam)
1428{
1429 mutex_lock(&sn9c102_sysfs_lock);
1430
1431 DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
1432 video_set_drvdata(cam->v4ldev, NULL);
1433 video_unregister_device(cam->v4ldev);
1434
1435 usb_put_dev(cam->usbdev);
1436
1437 mutex_unlock(&sn9c102_sysfs_lock);
1438
1439 kfree(cam->control_buffer);
1440}
1441
1442/*****************************************************************************/
1443
1444static int sn9c102_open(struct inode* inode, struct file* filp)
1445{
1446 struct sn9c102_device* cam;
1447 int err = 0;
1448
1449 /*
1450 This is the only safe way to prevent race conditions with
1451 disconnect
1452 */
1453 if (!down_read_trylock(&sn9c102_disconnect))
1454 return -ERESTARTSYS;
1455
1456 cam = video_get_drvdata(video_devdata(filp));
1457
1458 if (mutex_lock_interruptible(&cam->dev_mutex)) {
1459 up_read(&sn9c102_disconnect);
1460 return -ERESTARTSYS;
1461 }
1462
1463 if (cam->users) {
1464 DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);
1465 if ((filp->f_flags & O_NONBLOCK) ||
1466 (filp->f_flags & O_NDELAY)) {
1467 err = -EWOULDBLOCK;
1468 goto out;
1469 }
1470 mutex_unlock(&cam->dev_mutex);
1471 err = wait_event_interruptible_exclusive(cam->open,
1472 cam->state & DEV_DISCONNECTED
1473 || !cam->users);
1474 if (err) {
1475 up_read(&sn9c102_disconnect);
1476 return err;
1477 }
1478 if (cam->state & DEV_DISCONNECTED) {
1479 up_read(&sn9c102_disconnect);
1480 return -ENODEV;
1481 }
1482 mutex_lock(&cam->dev_mutex);
1483 }
1484
1485
1486 if (cam->state & DEV_MISCONFIGURED) {
1487 err = sn9c102_init(cam);
1488 if (err) {
1489 DBG(1, "Initialization failed again. "
1490 "I will retry on next open().");
1491 goto out;
1492 }
1493 cam->state &= ~DEV_MISCONFIGURED;
1494 }
1495
1496 if ((err = sn9c102_start_transfer(cam)))
1497 goto out;
1498
1499 filp->private_data = cam;
1500 cam->users++;
1501 cam->io = IO_NONE;
1502 cam->stream = STREAM_OFF;
1503 cam->nbuffers = 0;
1504 cam->frame_count = 0;
1505 sn9c102_empty_framequeues(cam);
1506
1507 DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
1508
1509out:
1510 mutex_unlock(&cam->dev_mutex);
1511 up_read(&sn9c102_disconnect);
1512 return err;
1513}
1514
1515
1516static int sn9c102_release(struct inode* inode, struct file* filp)
1517{
1518 struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
1519
1520 mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */
1521
1522 sn9c102_stop_transfer(cam);
1523
1524 sn9c102_release_buffers(cam);
1525
1526 if (cam->state & DEV_DISCONNECTED) {
1527 sn9c102_release_resources(cam);
1528 mutex_unlock(&cam->dev_mutex);
1529 kfree(cam);
1530 return 0;
1531 }
1532
1533 cam->users--;
1534 wake_up_interruptible_nr(&cam->open, 1);
1535
1536 DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
1537
1538 mutex_unlock(&cam->dev_mutex);
1539
1540 return 0;
1541}
1542
1543
1544static ssize_t
1545sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
1546{
1547 struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
1548 struct sn9c102_frame_t* f, * i;
1549 unsigned long lock_flags;
1550 long timeout;
1551 int err = 0;
1552
1553 if (mutex_lock_interruptible(&cam->fileop_mutex))
1554 return -ERESTARTSYS;
1555
1556 if (cam->state & DEV_DISCONNECTED) {
1557 DBG(1, "Device not present");
1558 mutex_unlock(&cam->fileop_mutex);
1559 return -ENODEV;
1560 }
1561
1562 if (cam->state & DEV_MISCONFIGURED) {
1563 DBG(1, "The camera is misconfigured. Close and open it "
1564 "again.");
1565 mutex_unlock(&cam->fileop_mutex);
1566 return -EIO;
1567 }
1568
1569 if (cam->io == IO_MMAP) {
1570 DBG(3, "Close and open the device again to choose "
1571 "the read method");
1572 mutex_unlock(&cam->fileop_mutex);
1573 return -EINVAL;
1574 }
1575
1576 if (cam->io == IO_NONE) {
1577 if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) {
1578 DBG(1, "read() failed, not enough memory");
1579 mutex_unlock(&cam->fileop_mutex);
1580 return -ENOMEM;
1581 }
1582 cam->io = IO_READ;
1583 cam->stream = STREAM_ON;
1584 }
1585
1586 if (list_empty(&cam->inqueue)) {
1587 if (!list_empty(&cam->outqueue))
1588 sn9c102_empty_framequeues(cam);
1589 sn9c102_queue_unusedframes(cam);
1590 }
1591
1592 if (!count) {
1593 mutex_unlock(&cam->fileop_mutex);
1594 return 0;
1595 }
1596
1597 if (list_empty(&cam->outqueue)) {
1598 if (filp->f_flags & O_NONBLOCK) {
1599 mutex_unlock(&cam->fileop_mutex);
1600 return -EAGAIN;
1601 }
1602 timeout = wait_event_interruptible_timeout
1603 ( cam->wait_frame,
1604 (!list_empty(&cam->outqueue)) ||
1605 (cam->state & DEV_DISCONNECTED) ||
1606 (cam->state & DEV_MISCONFIGURED),
1607 cam->module_param.frame_timeout *
1608 1000 * msecs_to_jiffies(1) );
1609 if (timeout < 0) {
1610 mutex_unlock(&cam->fileop_mutex);
1611 return timeout;
1612 }
1613 if (cam->state & DEV_DISCONNECTED) {
1614 mutex_unlock(&cam->fileop_mutex);
1615 return -ENODEV;
1616 }
1617 if (!timeout || (cam->state & DEV_MISCONFIGURED)) {
1618 mutex_unlock(&cam->fileop_mutex);
1619 return -EIO;
1620 }
1621 }
1622
1623 f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame);
1624
1625 if (count > f->buf.bytesused)
1626 count = f->buf.bytesused;
1627
1628 if (copy_to_user(buf, f->bufmem, count)) {
1629 err = -EFAULT;
1630 goto exit;
1631 }
1632 *f_pos += count;
1633
1634exit:
1635 spin_lock_irqsave(&cam->queue_lock, lock_flags);
1636 list_for_each_entry(i, &cam->outqueue, frame)
1637 i->state = F_UNUSED;
1638 INIT_LIST_HEAD(&cam->outqueue);
1639 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
1640
1641 sn9c102_queue_unusedframes(cam);
1642
1643 PDBGG("Frame #%lu, bytes read: %zu",
1644 (unsigned long)f->buf.index, count);
1645
1646 mutex_unlock(&cam->fileop_mutex);
1647
1648 return count;
1649}
1650
1651
1652static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
1653{
1654 struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
1655 struct sn9c102_frame_t* f;
1656 unsigned long lock_flags;
1657 unsigned int mask = 0;
1658
1659 if (mutex_lock_interruptible(&cam->fileop_mutex))
1660 return POLLERR;
1661
1662 if (cam->state & DEV_DISCONNECTED) {
1663 DBG(1, "Device not present");
1664 goto error;
1665 }
1666
1667 if (cam->state & DEV_MISCONFIGURED) {
1668 DBG(1, "The camera is misconfigured. Close and open it "
1669 "again.");
1670 goto error;
1671 }
1672
1673 if (cam->io == IO_NONE) {
1674 if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
1675 IO_READ)) {
1676 DBG(1, "poll() failed, not enough memory");
1677 goto error;
1678 }
1679 cam->io = IO_READ;
1680 cam->stream = STREAM_ON;
1681 }
1682
1683 if (cam->io == IO_READ) {
1684 spin_lock_irqsave(&cam->queue_lock, lock_flags);
1685 list_for_each_entry(f, &cam->outqueue, frame)
1686 f->state = F_UNUSED;
1687 INIT_LIST_HEAD(&cam->outqueue);
1688 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
1689 sn9c102_queue_unusedframes(cam);
1690 }
1691
1692 poll_wait(filp, &cam->wait_frame, wait);
1693
1694 if (!list_empty(&cam->outqueue))
1695 mask |= POLLIN | POLLRDNORM;
1696
1697 mutex_unlock(&cam->fileop_mutex);
1698
1699 return mask;
1700
1701error:
1702 mutex_unlock(&cam->fileop_mutex);
1703 return POLLERR;
1704}
1705
1706
1707static void sn9c102_vm_open(struct vm_area_struct* vma)
1708{
1709 struct sn9c102_frame_t* f = vma->vm_private_data;
1710 f->vma_use_count++;
1711}
1712
1713
1714static void sn9c102_vm_close(struct vm_area_struct* vma)
1715{
1716 /* NOTE: buffers are not freed here */
1717 struct sn9c102_frame_t* f = vma->vm_private_data;
1718 f->vma_use_count--;
1719}
1720
1721
1722static struct vm_operations_struct sn9c102_vm_ops = {
1723 .open = sn9c102_vm_open,
1724 .close = sn9c102_vm_close,
1725};
1726
1727
1728static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
1729{
1730 struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
1731 unsigned long size = vma->vm_end - vma->vm_start,
1732 start = vma->vm_start;
1733 void *pos;
1734 u32 i;
1735
1736 if (mutex_lock_interruptible(&cam->fileop_mutex))
1737 return -ERESTARTSYS;
1738
1739 if (cam->state & DEV_DISCONNECTED) {
1740 DBG(1, "Device not present");
1741 mutex_unlock(&cam->fileop_mutex);
1742 return -ENODEV;
1743 }
1744
1745 if (cam->state & DEV_MISCONFIGURED) {
1746 DBG(1, "The camera is misconfigured. Close and open it "
1747 "again.");
1748 mutex_unlock(&cam->fileop_mutex);
1749 return -EIO;
1750 }
1751
1752 if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
1753 size != PAGE_ALIGN(cam->frame[0].buf.length)) {
1754 mutex_unlock(&cam->fileop_mutex);
1755 return -EINVAL;
1756 }
1757
1758 for (i = 0; i < cam->nbuffers; i++) {
1759 if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff)
1760 break;
1761 }
1762 if (i == cam->nbuffers) {
1763 mutex_unlock(&cam->fileop_mutex);
1764 return -EINVAL;
1765 }
1766
1767 vma->vm_flags |= VM_IO;
1768 vma->vm_flags |= VM_RESERVED;
1769
1770 pos = cam->frame[i].bufmem;
1771 while (size > 0) { /* size is page-aligned */
1772 if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
1773 mutex_unlock(&cam->fileop_mutex);
1774 return -EAGAIN;
1775 }
1776 start += PAGE_SIZE;
1777 pos += PAGE_SIZE;
1778 size -= PAGE_SIZE;
1779 }
1780
1781 vma->vm_ops = &sn9c102_vm_ops;
1782 vma->vm_private_data = &cam->frame[i];
1783
1784 sn9c102_vm_open(vma);
1785
1786 mutex_unlock(&cam->fileop_mutex);
1787
1788 return 0;
1789}
1790
1791/*****************************************************************************/
1792
1793static int
1794sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg)
1795{
1796 struct v4l2_capability cap = {
1797 .driver = "sn9c102",
1798 .version = SN9C102_MODULE_VERSION_CODE,
1799 .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
1800 V4L2_CAP_STREAMING,
1801 };
1802
1803 strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
1804 if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
1805 strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
1806 sizeof(cap.bus_info));
1807
1808 if (copy_to_user(arg, &cap, sizeof(cap)))
1809 return -EFAULT;
1810
1811 return 0;
1812}
1813
1814
1815static int
1816sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg)
1817{
1818 struct v4l2_input i;
1819
1820 if (copy_from_user(&i, arg, sizeof(i)))
1821 return -EFAULT;
1822
1823 if (i.index)
1824 return -EINVAL;
1825
1826 memset(&i, 0, sizeof(i));
1827 strcpy(i.name, "Camera");
1828 i.type = V4L2_INPUT_TYPE_CAMERA;
1829
1830 if (copy_to_user(arg, &i, sizeof(i)))
1831 return -EFAULT;
1832
1833 return 0;
1834}
1835
1836
1837static int
1838sn9c102_vidioc_g_input(struct sn9c102_device* cam, void __user * arg)
1839{
1840 int index = 0;
1841
1842 if (copy_to_user(arg, &index, sizeof(index)))
1843 return -EFAULT;
1844
1845 return 0;
1846}
1847
1848
1849static int
1850sn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg)
1851{
1852 int index;
1853
1854 if (copy_from_user(&index, arg, sizeof(index)))
1855 return -EFAULT;
1856
1857 if (index != 0)
1858 return -EINVAL;
1859
1860 return 0;
1861}
1862
1863
1864static int
1865sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg)
1866{
1867 struct sn9c102_sensor* s = &cam->sensor;
1868 struct v4l2_queryctrl qc;
1869 u8 i;
1870
1871 if (copy_from_user(&qc, arg, sizeof(qc)))
1872 return -EFAULT;
1873
1874 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
1875 if (qc.id && qc.id == s->qctrl[i].id) {
1876 memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
1877 if (copy_to_user(arg, &qc, sizeof(qc)))
1878 return -EFAULT;
1879 return 0;
1880 }
1881
1882 return -EINVAL;
1883}
1884
1885
1886static int
1887sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg)
1888{
1889 struct sn9c102_sensor* s = &cam->sensor;
1890 struct v4l2_control ctrl;
1891 int err = 0;
1892 u8 i;
1893
1894 if (!s->get_ctrl && !s->set_ctrl)
1895 return -EINVAL;
1896
1897 if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
1898 return -EFAULT;
1899
1900 if (!s->get_ctrl) {
1901 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
1902 if (ctrl.id && ctrl.id == s->qctrl[i].id) {
1903 ctrl.value = s->_qctrl[i].default_value;
1904 goto exit;
1905 }
1906 return -EINVAL;
1907 } else
1908 err = s->get_ctrl(cam, &ctrl);
1909
1910exit:
1911 if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
1912 return -EFAULT;
1913
1914 return err;
1915}
1916
1917
1918static int
1919sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg)
1920{
1921 struct sn9c102_sensor* s = &cam->sensor;
1922 struct v4l2_control ctrl;
1923 u8 i;
1924 int err = 0;
1925
1926 if (!s->set_ctrl)
1927 return -EINVAL;
1928
1929 if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
1930 return -EFAULT;
1931
1932 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
1933 if (ctrl.id == s->qctrl[i].id) {
1934 if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
1935 return -EINVAL;
1936 if (ctrl.value < s->qctrl[i].minimum ||
1937 ctrl.value > s->qctrl[i].maximum)
1938 return -ERANGE;
1939 ctrl.value -= ctrl.value % s->qctrl[i].step;
1940 break;
1941 }
1942
1943 if ((err = s->set_ctrl(cam, &ctrl)))
1944 return err;
1945
1946 s->_qctrl[i].default_value = ctrl.value;
1947
1948 PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
1949 (unsigned long)ctrl.id, (unsigned long)ctrl.value);
1950
1951 return 0;
1952}
1953
1954
1955static int
1956sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg)
1957{
1958 struct v4l2_cropcap* cc = &(cam->sensor.cropcap);
1959
1960 cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1961 cc->pixelaspect.numerator = 1;
1962 cc->pixelaspect.denominator = 1;
1963
1964 if (copy_to_user(arg, cc, sizeof(*cc)))
1965 return -EFAULT;
1966
1967 return 0;
1968}
1969
1970
1971static int
1972sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg)
1973{
1974 struct sn9c102_sensor* s = &cam->sensor;
1975 struct v4l2_crop crop = {
1976 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
1977 };
1978
1979 memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
1980
1981 if (copy_to_user(arg, &crop, sizeof(crop)))
1982 return -EFAULT;
1983
1984 return 0;
1985}
1986
1987
1988static int
1989sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
1990{
1991 struct sn9c102_sensor* s = &cam->sensor;
1992 struct v4l2_crop crop;
1993 struct v4l2_rect* rect;
1994 struct v4l2_rect* bounds = &(s->cropcap.bounds);
1995 struct v4l2_pix_format* pix_format = &(s->pix_format);
1996 u8 scale;
1997 const enum sn9c102_stream_state stream = cam->stream;
1998 const u32 nbuffers = cam->nbuffers;
1999 u32 i;
2000 int err = 0;
2001
2002 if (copy_from_user(&crop, arg, sizeof(crop)))
2003 return -EFAULT;
2004
2005 rect = &(crop.c);
2006
2007 if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2008 return -EINVAL;
2009
2010 if (cam->module_param.force_munmap)
2011 for (i = 0; i < cam->nbuffers; i++)
2012 if (cam->frame[i].vma_use_count) {
2013 DBG(3, "VIDIOC_S_CROP failed. "
2014 "Unmap the buffers first.");
2015 return -EINVAL;
2016 }
2017
2018 /* Preserve R,G or B origin */
2019 rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
2020 rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
2021
2022 if (rect->width < 16)
2023 rect->width = 16;
2024 if (rect->height < 16)
2025 rect->height = 16;
2026 if (rect->width > bounds->width)
2027 rect->width = bounds->width;
2028 if (rect->height > bounds->height)
2029 rect->height = bounds->height;
2030 if (rect->left < bounds->left)
2031 rect->left = bounds->left;
2032 if (rect->top < bounds->top)
2033 rect->top = bounds->top;
2034 if (rect->left + rect->width > bounds->left + bounds->width)
2035 rect->left = bounds->left+bounds->width - rect->width;
2036 if (rect->top + rect->height > bounds->top + bounds->height)
2037 rect->top = bounds->top+bounds->height - rect->height;
2038
2039 rect->width &= ~15L;
2040 rect->height &= ~15L;
2041
2042 if (SN9C102_PRESERVE_IMGSCALE) {
2043 /* Calculate the actual scaling factor */
2044 u32 a, b;
2045 a = rect->width * rect->height;
2046 b = pix_format->width * pix_format->height;
2047 scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
2048 } else
2049 scale = 1;
2050
2051 if (cam->stream == STREAM_ON)
2052 if ((err = sn9c102_stream_interrupt(cam)))
2053 return err;
2054
2055 if (copy_to_user(arg, &crop, sizeof(crop))) {
2056 cam->stream = stream;
2057 return -EFAULT;
2058 }
2059
2060 if (cam->module_param.force_munmap || cam->io == IO_READ)
2061 sn9c102_release_buffers(cam);
2062
2063 err = sn9c102_set_crop(cam, rect);
2064 if (s->set_crop)
2065 err += s->set_crop(cam, rect);
2066 err += sn9c102_set_scale(cam, scale);
2067
2068 if (err) { /* atomic, no rollback in ioctl() */
2069 cam->state |= DEV_MISCONFIGURED;
2070 DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
2071 "use the camera, close and open /dev/video%d again.",
2072 cam->v4ldev->minor);
2073 return -EIO;
2074 }
2075
2076 s->pix_format.width = rect->width/scale;
2077 s->pix_format.height = rect->height/scale;
2078 memcpy(&(s->_rect), rect, sizeof(*rect));
2079
2080 if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
2081 nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
2082 cam->state |= DEV_MISCONFIGURED;
2083 DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
2084 "use the camera, close and open /dev/video%d again.",
2085 cam->v4ldev->minor);
2086 return -ENOMEM;
2087 }
2088
2089 if (cam->io == IO_READ)
2090 sn9c102_empty_framequeues(cam);
2091 else if (cam->module_param.force_munmap)
2092 sn9c102_requeue_outqueue(cam);
2093
2094 cam->stream = stream;
2095
2096 return 0;
2097}
2098
2099
2100static int
2101sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
2102{
2103 struct v4l2_fmtdesc fmtd;
2104
2105 if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
2106 return -EFAULT;
2107
2108 if (fmtd.index == 0) {
2109 strcpy(fmtd.description, "bayer rgb");
2110 fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
2111 } else if (fmtd.index == 1) {
2112 strcpy(fmtd.description, "compressed");
2113 fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
2114 fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
2115 } else
2116 return -EINVAL;
2117
2118 fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2119 memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
2120
2121 if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
2122 return -EFAULT;
2123
2124 return 0;
2125}
2126
2127
2128static int
2129sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
2130{
2131 struct v4l2_format format;
2132 struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format);
2133
2134 if (copy_from_user(&format, arg, sizeof(format)))
2135 return -EFAULT;
2136
2137 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2138 return -EINVAL;
2139
2140 pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X)
2141 ? 0 : (pfmt->width * pfmt->priv) / 8;
2142 pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
2143 pfmt->field = V4L2_FIELD_NONE;
2144 memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
2145
2146 if (copy_to_user(arg, &format, sizeof(format)))
2147 return -EFAULT;
2148
2149 return 0;
2150}
2151
2152
2153static int
2154sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
2155 void __user * arg)
2156{
2157 struct sn9c102_sensor* s = &cam->sensor;
2158 struct v4l2_format format;
2159 struct v4l2_pix_format* pix;
2160 struct v4l2_pix_format* pfmt = &(s->pix_format);
2161 struct v4l2_rect* bounds = &(s->cropcap.bounds);
2162 struct v4l2_rect rect;
2163 u8 scale;
2164 const enum sn9c102_stream_state stream = cam->stream;
2165 const u32 nbuffers = cam->nbuffers;
2166 u32 i;
2167 int err = 0;
2168
2169 if (copy_from_user(&format, arg, sizeof(format)))
2170 return -EFAULT;
2171
2172 pix = &(format.fmt.pix);
2173
2174 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2175 return -EINVAL;
2176
2177 memcpy(&rect, &(s->_rect), sizeof(rect));
2178
2179 { /* calculate the actual scaling factor */
2180 u32 a, b;
2181 a = rect.width * rect.height;
2182 b = pix->width * pix->height;
2183 scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
2184 }
2185
2186 rect.width = scale * pix->width;
2187 rect.height = scale * pix->height;
2188
2189 if (rect.width < 16)
2190 rect.width = 16;
2191 if (rect.height < 16)
2192 rect.height = 16;
2193 if (rect.width > bounds->left + bounds->width - rect.left)
2194 rect.width = bounds->left + bounds->width - rect.left;
2195 if (rect.height > bounds->top + bounds->height - rect.top)
2196 rect.height = bounds->top + bounds->height - rect.top;
2197
2198 rect.width &= ~15L;
2199 rect.height &= ~15L;
2200
2201 { /* adjust the scaling factor */
2202 u32 a, b;
2203 a = rect.width * rect.height;
2204 b = pix->width * pix->height;
2205 scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
2206 }
2207
2208 pix->width = rect.width / scale;
2209 pix->height = rect.height / scale;
2210
2211 if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
2212 pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
2213 pix->pixelformat = pfmt->pixelformat;
2214 pix->priv = pfmt->priv; /* bpp */
2215 pix->colorspace = pfmt->colorspace;
2216 pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
2217 ? 0 : (pix->width * pix->priv) / 8;
2218 pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
2219 pix->field = V4L2_FIELD_NONE;
2220
2221 if (cmd == VIDIOC_TRY_FMT) {
2222 if (copy_to_user(arg, &format, sizeof(format)))
2223 return -EFAULT;
2224 return 0;
2225 }
2226
2227 if (cam->module_param.force_munmap)
2228 for (i = 0; i < cam->nbuffers; i++)
2229 if (cam->frame[i].vma_use_count) {
2230 DBG(3, "VIDIOC_S_FMT failed. Unmap the "
2231 "buffers first.");
2232 return -EINVAL;
2233 }
2234
2235 if (cam->stream == STREAM_ON)
2236 if ((err = sn9c102_stream_interrupt(cam)))
2237 return err;
2238
2239 if (copy_to_user(arg, &format, sizeof(format))) {
2240 cam->stream = stream;
2241 return -EFAULT;
2242 }
2243
2244 if (cam->module_param.force_munmap || cam->io == IO_READ)
2245 sn9c102_release_buffers(cam);
2246
2247 err += sn9c102_set_pix_format(cam, pix);
2248 err += sn9c102_set_crop(cam, &rect);
2249 if (s->set_pix_format)
2250 err += s->set_pix_format(cam, pix);
2251 if (s->set_crop)
2252 err += s->set_crop(cam, &rect);
2253 err += sn9c102_set_scale(cam, scale);
2254
2255 if (err) { /* atomic, no rollback in ioctl() */
2256 cam->state |= DEV_MISCONFIGURED;
2257 DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
2258 "use the camera, close and open /dev/video%d again.",
2259 cam->v4ldev->minor);
2260 return -EIO;
2261 }
2262
2263 memcpy(pfmt, pix, sizeof(*pix));
2264 memcpy(&(s->_rect), &rect, sizeof(rect));
2265
2266 if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
2267 nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
2268 cam->state |= DEV_MISCONFIGURED;
2269 DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
2270 "use the camera, close and open /dev/video%d again.",
2271 cam->v4ldev->minor);
2272 return -ENOMEM;
2273 }
2274
2275 if (cam->io == IO_READ)
2276 sn9c102_empty_framequeues(cam);
2277 else if (cam->module_param.force_munmap)
2278 sn9c102_requeue_outqueue(cam);
2279
2280 cam->stream = stream;
2281
2282 return 0;
2283}
2284
2285
2286static int
2287sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg)
2288{
2289 if (copy_to_user(arg, &cam->compression,
2290 sizeof(cam->compression)))
2291 return -EFAULT;
2292
2293 return 0;
2294}
2295
2296
2297static int
2298sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg)
2299{
2300 struct v4l2_jpegcompression jc;
2301 const enum sn9c102_stream_state stream = cam->stream;
2302 int err = 0;
2303
2304 if (copy_from_user(&jc, arg, sizeof(jc)))
2305 return -EFAULT;
2306
2307 if (jc.quality != 0 && jc.quality != 1)
2308 return -EINVAL;
2309
2310 if (cam->stream == STREAM_ON)
2311 if ((err = sn9c102_stream_interrupt(cam)))
2312 return err;
2313
2314 err += sn9c102_set_compression(cam, &jc);
2315 if (err) { /* atomic, no rollback in ioctl() */
2316 cam->state |= DEV_MISCONFIGURED;
2317 DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
2318 "problems. To use the camera, close and open "
2319 "/dev/video%d again.", cam->v4ldev->minor);
2320 return -EIO;
2321 }
2322
2323 cam->compression.quality = jc.quality;
2324
2325 cam->stream = stream;
2326
2327 return 0;
2328}
2329
2330
2331static int
2332sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg)
2333{
2334 struct v4l2_requestbuffers rb;
2335 u32 i;
2336 int err;
2337
2338 if (copy_from_user(&rb, arg, sizeof(rb)))
2339 return -EFAULT;
2340
2341 if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
2342 rb.memory != V4L2_MEMORY_MMAP)
2343 return -EINVAL;
2344
2345 if (cam->io == IO_READ) {
2346 DBG(3, "Close and open the device again to choose the mmap "
2347 "I/O method");
2348 return -EINVAL;
2349 }
2350
2351 for (i = 0; i < cam->nbuffers; i++)
2352 if (cam->frame[i].vma_use_count) {
2353 DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
2354 "still mapped.");
2355 return -EINVAL;
2356 }
2357
2358 if (cam->stream == STREAM_ON)
2359 if ((err = sn9c102_stream_interrupt(cam)))
2360 return err;
2361
2362 sn9c102_empty_framequeues(cam);
2363
2364 sn9c102_release_buffers(cam);
2365 if (rb.count)
2366 rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP);
2367
2368 if (copy_to_user(arg, &rb, sizeof(rb))) {
2369 sn9c102_release_buffers(cam);
2370 cam->io = IO_NONE;
2371 return -EFAULT;
2372 }
2373
2374 cam->io = rb.count ? IO_MMAP : IO_NONE;
2375
2376 return 0;
2377}
2378
2379
2380static int
2381sn9c102_vidioc_querybuf(struct sn9c102_device* cam, void __user * arg)
2382{
2383 struct v4l2_buffer b;
2384
2385 if (copy_from_user(&b, arg, sizeof(b)))
2386 return -EFAULT;
2387
2388 if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
2389 b.index >= cam->nbuffers || cam->io != IO_MMAP)
2390 return -EINVAL;
2391
2392 memcpy(&b, &cam->frame[b.index].buf, sizeof(b));
2393
2394 if (cam->frame[b.index].vma_use_count)
2395 b.flags |= V4L2_BUF_FLAG_MAPPED;
2396
2397 if (cam->frame[b.index].state == F_DONE)
2398 b.flags |= V4L2_BUF_FLAG_DONE;
2399 else if (cam->frame[b.index].state != F_UNUSED)
2400 b.flags |= V4L2_BUF_FLAG_QUEUED;
2401
2402 if (copy_to_user(arg, &b, sizeof(b)))
2403 return -EFAULT;
2404
2405 return 0;
2406}
2407
2408
2409static int
2410sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg)
2411{
2412 struct v4l2_buffer b;
2413 unsigned long lock_flags;
2414
2415 if (copy_from_user(&b, arg, sizeof(b)))
2416 return -EFAULT;
2417
2418 if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
2419 b.index >= cam->nbuffers || cam->io != IO_MMAP)
2420 return -EINVAL;
2421
2422 if (cam->frame[b.index].state != F_UNUSED)
2423 return -EINVAL;
2424
2425 cam->frame[b.index].state = F_QUEUED;
2426
2427 spin_lock_irqsave(&cam->queue_lock, lock_flags);
2428 list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
2429 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
2430
2431 PDBGG("Frame #%lu queued", (unsigned long)b.index);
2432
2433 return 0;
2434}
2435
2436
2437static int
2438sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
2439 void __user * arg)
2440{
2441 struct v4l2_buffer b;
2442 struct sn9c102_frame_t *f;
2443 unsigned long lock_flags;
2444 long timeout;
2445
2446 if (copy_from_user(&b, arg, sizeof(b)))
2447 return -EFAULT;
2448
2449 if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
2450 return -EINVAL;
2451
2452 if (list_empty(&cam->outqueue)) {
2453 if (cam->stream == STREAM_OFF)
2454 return -EINVAL;
2455 if (filp->f_flags & O_NONBLOCK)
2456 return -EAGAIN;
2457 timeout = wait_event_interruptible_timeout
2458 ( cam->wait_frame,
2459 (!list_empty(&cam->outqueue)) ||
2460 (cam->state & DEV_DISCONNECTED) ||
2461 (cam->state & DEV_MISCONFIGURED),
2462 cam->module_param.frame_timeout *
2463 1000 * msecs_to_jiffies(1) );
2464 if (timeout < 0)
2465 return timeout;
2466 if (cam->state & DEV_DISCONNECTED)
2467 return -ENODEV;
2468 if (!timeout || (cam->state & DEV_MISCONFIGURED))
2469 return -EIO;
2470 }
2471
2472 spin_lock_irqsave(&cam->queue_lock, lock_flags);
2473 f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame);
2474 list_del(cam->outqueue.next);
2475 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
2476
2477 f->state = F_UNUSED;
2478
2479 memcpy(&b, &f->buf, sizeof(b));
2480 if (f->vma_use_count)
2481 b.flags |= V4L2_BUF_FLAG_MAPPED;
2482
2483 if (copy_to_user(arg, &b, sizeof(b)))
2484 return -EFAULT;
2485
2486 PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index);
2487
2488 return 0;
2489}
2490
2491
2492static int
2493sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg)
2494{
2495 int type;
2496
2497 if (copy_from_user(&type, arg, sizeof(type)))
2498 return -EFAULT;
2499
2500 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
2501 return -EINVAL;
2502
2503 if (list_empty(&cam->inqueue))
2504 return -EINVAL;
2505
2506 cam->stream = STREAM_ON;
2507
2508 DBG(3, "Stream on");
2509
2510 return 0;
2511}
2512
2513
2514static int
2515sn9c102_vidioc_streamoff(struct sn9c102_device* cam, void __user * arg)
2516{
2517 int type, err;
2518
2519 if (copy_from_user(&type, arg, sizeof(type)))
2520 return -EFAULT;
2521
2522 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
2523 return -EINVAL;
2524
2525 if (cam->stream == STREAM_ON)
2526 if ((err = sn9c102_stream_interrupt(cam)))
2527 return err;
2528
2529 sn9c102_empty_framequeues(cam);
2530
2531 DBG(3, "Stream off");
2532
2533 return 0;
2534}
2535
2536
2537static int
2538sn9c102_vidioc_g_parm(struct sn9c102_device* cam, void __user * arg)
2539{
2540 struct v4l2_streamparm sp;
2541
2542 if (copy_from_user(&sp, arg, sizeof(sp)))
2543 return -EFAULT;
2544
2545 if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2546 return -EINVAL;
2547
2548 sp.parm.capture.extendedmode = 0;
2549 sp.parm.capture.readbuffers = cam->nreadbuffers;
2550
2551 if (copy_to_user(arg, &sp, sizeof(sp)))
2552 return -EFAULT;
2553
2554 return 0;
2555}
2556
2557
2558static int
2559sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg)
2560{
2561 struct v4l2_streamparm sp;
2562
2563 if (copy_from_user(&sp, arg, sizeof(sp)))
2564 return -EFAULT;
2565
2566 if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2567 return -EINVAL;
2568
2569 sp.parm.capture.extendedmode = 0;
2570
2571 if (sp.parm.capture.readbuffers == 0)
2572 sp.parm.capture.readbuffers = cam->nreadbuffers;
2573
2574 if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES)
2575 sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES;
2576
2577 if (copy_to_user(arg, &sp, sizeof(sp)))
2578 return -EFAULT;
2579
2580 cam->nreadbuffers = sp.parm.capture.readbuffers;
2581
2582 return 0;
2583}
2584
2585
2586static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
2587 unsigned int cmd, void __user * arg)
2588{
2589 struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
2590
2591 switch (cmd) {
2592
2593 case VIDIOC_QUERYCAP:
2594 return sn9c102_vidioc_querycap(cam, arg);
2595
2596 case VIDIOC_ENUMINPUT:
2597 return sn9c102_vidioc_enuminput(cam, arg);
2598
2599 case VIDIOC_G_INPUT:
2600 return sn9c102_vidioc_g_input(cam, arg);
2601
2602 case VIDIOC_S_INPUT:
2603 return sn9c102_vidioc_s_input(cam, arg);
2604
2605 case VIDIOC_QUERYCTRL:
2606 return sn9c102_vidioc_query_ctrl(cam, arg);
2607
2608 case VIDIOC_G_CTRL:
2609 return sn9c102_vidioc_g_ctrl(cam, arg);
2610
2611 case VIDIOC_S_CTRL_OLD:
2612 case VIDIOC_S_CTRL:
2613 return sn9c102_vidioc_s_ctrl(cam, arg);
2614
2615 case VIDIOC_CROPCAP_OLD:
2616 case VIDIOC_CROPCAP:
2617 return sn9c102_vidioc_cropcap(cam, arg);
2618
2619 case VIDIOC_G_CROP:
2620 return sn9c102_vidioc_g_crop(cam, arg);
2621
2622 case VIDIOC_S_CROP:
2623 return sn9c102_vidioc_s_crop(cam, arg);
2624
2625 case VIDIOC_ENUM_FMT:
2626 return sn9c102_vidioc_enum_fmt(cam, arg);
2627
2628 case VIDIOC_G_FMT:
2629 return sn9c102_vidioc_g_fmt(cam, arg);
2630
2631 case VIDIOC_TRY_FMT:
2632 case VIDIOC_S_FMT:
2633 return sn9c102_vidioc_try_s_fmt(cam, cmd, arg);
2634
2635 case VIDIOC_G_JPEGCOMP:
2636 return sn9c102_vidioc_g_jpegcomp(cam, arg);
2637
2638 case VIDIOC_S_JPEGCOMP:
2639 return sn9c102_vidioc_s_jpegcomp(cam, arg);
2640
2641 case VIDIOC_REQBUFS:
2642 return sn9c102_vidioc_reqbufs(cam, arg);
2643
2644 case VIDIOC_QUERYBUF:
2645 return sn9c102_vidioc_querybuf(cam, arg);
2646
2647 case VIDIOC_QBUF:
2648 return sn9c102_vidioc_qbuf(cam, arg);
2649
2650 case VIDIOC_DQBUF:
2651 return sn9c102_vidioc_dqbuf(cam, filp, arg);
2652
2653 case VIDIOC_STREAMON:
2654 return sn9c102_vidioc_streamon(cam, arg);
2655
2656 case VIDIOC_STREAMOFF:
2657 return sn9c102_vidioc_streamoff(cam, arg);
2658
2659 case VIDIOC_G_PARM:
2660 return sn9c102_vidioc_g_parm(cam, arg);
2661
2662 case VIDIOC_S_PARM_OLD:
2663 case VIDIOC_S_PARM:
2664 return sn9c102_vidioc_s_parm(cam, arg);
2665
2666 case VIDIOC_G_STD:
2667 case VIDIOC_S_STD:
2668 case VIDIOC_QUERYSTD:
2669 case VIDIOC_ENUMSTD:
2670 case VIDIOC_QUERYMENU:
2671 return -EINVAL;
2672
2673 default:
2674 return -EINVAL;
2675
2676 }
2677}
2678
2679
2680static int sn9c102_ioctl(struct inode* inode, struct file* filp,
2681 unsigned int cmd, unsigned long arg)
2682{
2683 struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
2684 int err = 0;
2685
2686 if (mutex_lock_interruptible(&cam->fileop_mutex))
2687 return -ERESTARTSYS;
2688
2689 if (cam->state & DEV_DISCONNECTED) {
2690 DBG(1, "Device not present");
2691 mutex_unlock(&cam->fileop_mutex);
2692 return -ENODEV;
2693 }
2694
2695 if (cam->state & DEV_MISCONFIGURED) {
2696 DBG(1, "The camera is misconfigured. Close and open it "
2697 "again.");
2698 mutex_unlock(&cam->fileop_mutex);
2699 return -EIO;
2700 }
2701
2702 V4LDBG(3, "sn9c102", cmd);
2703
2704 err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
2705
2706 mutex_unlock(&cam->fileop_mutex);
2707
2708 return err;
2709}
2710
2711/*****************************************************************************/
2712
2713static struct file_operations sn9c102_fops = {
2714 .owner = THIS_MODULE,
2715 .open = sn9c102_open,
2716 .release = sn9c102_release,
2717 .ioctl = sn9c102_ioctl,
2718 .read = sn9c102_read,
2719 .poll = sn9c102_poll,
2720 .mmap = sn9c102_mmap,
2721 .llseek = no_llseek,
2722};
2723
2724/*****************************************************************************/
2725
2726/* It exists a single interface only. We do not need to validate anything. */
2727static int
2728sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
2729{
2730 struct usb_device *udev = interface_to_usbdev(intf);
2731 struct sn9c102_device* cam;
2732 static unsigned int dev_nr = 0;
2733 unsigned int i;
2734 int err = 0, r;
2735
2736 if (!(cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL)))
2737 return -ENOMEM;
2738
2739 cam->usbdev = udev;
2740
2741 if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) {
2742 DBG(1, "kmalloc() failed");
2743 err = -ENOMEM;
2744 goto fail;
2745 }
2746
2747 if (!(cam->v4ldev = video_device_alloc())) {
2748 DBG(1, "video_device_alloc() failed");
2749 err = -ENOMEM;
2750 goto fail;
2751 }
2752
2753 mutex_init(&cam->dev_mutex);
2754
2755 r = sn9c102_read_reg(cam, 0x00);
2756 if (r < 0 || r != 0x10) {
2757 DBG(1, "Sorry, this is not a SN9C10x based camera "
2758 "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
2759 err = -ENODEV;
2760 goto fail;
2761 }
2762
2763 cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ?
2764 BRIDGE_SN9C103 : BRIDGE_SN9C102;
2765 switch (cam->bridge) {
2766 case BRIDGE_SN9C101:
2767 case BRIDGE_SN9C102:
2768 DBG(2, "SN9C10[12] PC Camera Controller detected "
2769 "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
2770 break;
2771 case BRIDGE_SN9C103:
2772 DBG(2, "SN9C103 PC Camera Controller detected "
2773 "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct);
2774 break;
2775 }
2776
2777 for (i = 0; sn9c102_sensor_table[i]; i++) {
2778 err = sn9c102_sensor_table[i](cam);
2779 if (!err)
2780 break;
2781 }
2782
2783 if (!err) {
2784 DBG(2, "%s image sensor detected", cam->sensor.name);
2785 DBG(3, "Support for %s maintained by %s",
2786 cam->sensor.name, cam->sensor.maintainer);
2787 } else {
2788 DBG(1, "No supported image sensor detected");
2789 err = -ENODEV;
2790 goto fail;
2791 }
2792
2793 if (sn9c102_init(cam)) {
2794 DBG(1, "Initialization failed. I will retry on open().");
2795 cam->state |= DEV_MISCONFIGURED;
2796 }
2797
2798 strcpy(cam->v4ldev->name, "SN9C10x PC Camera");
2799 cam->v4ldev->owner = THIS_MODULE;
2800 cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
2801 cam->v4ldev->hardware = 0;
2802 cam->v4ldev->fops = &sn9c102_fops;
2803 cam->v4ldev->minor = video_nr[dev_nr];
2804 cam->v4ldev->release = video_device_release;
2805 video_set_drvdata(cam->v4ldev, cam);
2806
2807 mutex_lock(&cam->dev_mutex);
2808
2809 err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
2810 video_nr[dev_nr]);
2811 if (err) {
2812 DBG(1, "V4L2 device registration failed");
2813 if (err == -ENFILE && video_nr[dev_nr] == -1)
2814 DBG(1, "Free /dev/videoX node not found");
2815 video_nr[dev_nr] = -1;
2816 dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
2817 mutex_unlock(&cam->dev_mutex);
2818 goto fail;
2819 }
2820
2821 DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
2822
2823 cam->module_param.force_munmap = force_munmap[dev_nr];
2824 cam->module_param.frame_timeout = frame_timeout[dev_nr];
2825
2826 dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
2827
2828#ifdef CONFIG_VIDEO_ADV_DEBUG
2829 sn9c102_create_sysfs(cam);
2830 DBG(2, "Optional device control through 'sysfs' interface ready");
2831#endif
2832
2833 usb_set_intfdata(intf, cam);
2834
2835 mutex_unlock(&cam->dev_mutex);
2836
2837 return 0;
2838
2839fail:
2840 if (cam) {
2841 kfree(cam->control_buffer);
2842 if (cam->v4ldev)
2843 video_device_release(cam->v4ldev);
2844 kfree(cam);
2845 }
2846 return err;
2847}
2848
2849
2850static void sn9c102_usb_disconnect(struct usb_interface* intf)
2851{
2852 struct sn9c102_device* cam = usb_get_intfdata(intf);
2853
2854 if (!cam)
2855 return;
2856
2857 down_write(&sn9c102_disconnect);
2858
2859 mutex_lock(&cam->dev_mutex);
2860
2861 DBG(2, "Disconnecting %s...", cam->v4ldev->name);
2862
2863 wake_up_interruptible_all(&cam->open);
2864
2865 if (cam->users) {
2866 DBG(2, "Device /dev/video%d is open! Deregistration and "
2867 "memory deallocation are deferred on close.",
2868 cam->v4ldev->minor);
2869 cam->state |= DEV_MISCONFIGURED;
2870 sn9c102_stop_transfer(cam);
2871 cam->state |= DEV_DISCONNECTED;
2872 wake_up_interruptible(&cam->wait_frame);
2873 wake_up(&cam->wait_stream);
2874 usb_get_dev(cam->usbdev);
2875 } else {
2876 cam->state |= DEV_DISCONNECTED;
2877 sn9c102_release_resources(cam);
2878 }
2879
2880 mutex_unlock(&cam->dev_mutex);
2881
2882 if (!cam->users)
2883 kfree(cam);
2884
2885 up_write(&sn9c102_disconnect);
2886}
2887
2888
2889static struct usb_driver sn9c102_usb_driver = {
2890 .name = "sn9c102",
2891 .id_table = sn9c102_id_table,
2892 .probe = sn9c102_usb_probe,
2893 .disconnect = sn9c102_usb_disconnect,
2894};
2895
2896/*****************************************************************************/
2897
2898static int __init sn9c102_module_init(void)
2899{
2900 int err = 0;
2901
2902 KDBG(2, SN9C102_MODULE_NAME " v" SN9C102_MODULE_VERSION);
2903 KDBG(3, SN9C102_MODULE_AUTHOR);
2904
2905 if ((err = usb_register(&sn9c102_usb_driver)))
2906 KDBG(1, "usb_register() failed");
2907
2908 return err;
2909}
2910
2911
2912static void __exit sn9c102_module_exit(void)
2913{
2914 usb_deregister(&sn9c102_usb_driver);
2915}
2916
2917
2918module_init(sn9c102_module_init);
2919module_exit(sn9c102_module_exit);
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
new file mode 100644
index 000000000000..46c12ec3ca62
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
@@ -0,0 +1,271 @@
1/***************************************************************************
2 * Plug-in for HV7131D image sensor connected to the SN9C10x PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
20 ***************************************************************************/
21
22#include "sn9c102_sensor.h"
23
24
25static struct sn9c102_sensor hv7131d;
26
27
28static int hv7131d_init(struct sn9c102_device* cam)
29{
30 int err = 0;
31
32 err += sn9c102_write_reg(cam, 0x00, 0x10);
33 err += sn9c102_write_reg(cam, 0x00, 0x11);
34 err += sn9c102_write_reg(cam, 0x00, 0x14);
35 err += sn9c102_write_reg(cam, 0x60, 0x17);
36 err += sn9c102_write_reg(cam, 0x0e, 0x18);
37 err += sn9c102_write_reg(cam, 0xf2, 0x19);
38
39 err += sn9c102_i2c_write(cam, 0x01, 0x04);
40 err += sn9c102_i2c_write(cam, 0x02, 0x00);
41 err += sn9c102_i2c_write(cam, 0x28, 0x00);
42
43 return err;
44}
45
46
47static int hv7131d_get_ctrl(struct sn9c102_device* cam,
48 struct v4l2_control* ctrl)
49{
50 switch (ctrl->id) {
51 case V4L2_CID_EXPOSURE:
52 {
53 int r1 = sn9c102_i2c_read(cam, 0x26),
54 r2 = sn9c102_i2c_read(cam, 0x27);
55 if (r1 < 0 || r2 < 0)
56 return -EIO;
57 ctrl->value = (r1 << 8) | (r2 & 0xff);
58 }
59 return 0;
60 case V4L2_CID_RED_BALANCE:
61 if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0)
62 return -EIO;
63 ctrl->value = 0x3f - (ctrl->value & 0x3f);
64 return 0;
65 case V4L2_CID_BLUE_BALANCE:
66 if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0)
67 return -EIO;
68 ctrl->value = 0x3f - (ctrl->value & 0x3f);
69 return 0;
70 case SN9C102_V4L2_CID_GREEN_BALANCE:
71 if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0)
72 return -EIO;
73 ctrl->value = 0x3f - (ctrl->value & 0x3f);
74 return 0;
75 case SN9C102_V4L2_CID_RESET_LEVEL:
76 if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0)
77 return -EIO;
78 ctrl->value &= 0x3f;
79 return 0;
80 case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
81 if ((ctrl->value = sn9c102_i2c_read(cam, 0x34)) < 0)
82 return -EIO;
83 ctrl->value &= 0x07;
84 return 0;
85 default:
86 return -EINVAL;
87 }
88}
89
90
91static int hv7131d_set_ctrl(struct sn9c102_device* cam,
92 const struct v4l2_control* ctrl)
93{
94 int err = 0;
95
96 switch (ctrl->id) {
97 case V4L2_CID_EXPOSURE:
98 err += sn9c102_i2c_write(cam, 0x26, ctrl->value >> 8);
99 err += sn9c102_i2c_write(cam, 0x27, ctrl->value & 0xff);
100 break;
101 case V4L2_CID_RED_BALANCE:
102 err += sn9c102_i2c_write(cam, 0x31, 0x3f - ctrl->value);
103 break;
104 case V4L2_CID_BLUE_BALANCE:
105 err += sn9c102_i2c_write(cam, 0x33, 0x3f - ctrl->value);
106 break;
107 case SN9C102_V4L2_CID_GREEN_BALANCE:
108 err += sn9c102_i2c_write(cam, 0x32, 0x3f - ctrl->value);
109 break;
110 case SN9C102_V4L2_CID_RESET_LEVEL:
111 err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
112 break;
113 case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
114 err += sn9c102_i2c_write(cam, 0x34, ctrl->value);
115 break;
116 default:
117 return -EINVAL;
118 }
119
120 return err ? -EIO : 0;
121}
122
123
124static int hv7131d_set_crop(struct sn9c102_device* cam,
125 const struct v4l2_rect* rect)
126{
127 struct sn9c102_sensor* s = &hv7131d;
128 int err = 0;
129 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2,
130 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
131
132 err += sn9c102_write_reg(cam, h_start, 0x12);
133 err += sn9c102_write_reg(cam, v_start, 0x13);
134
135 return err;
136}
137
138
139static int hv7131d_set_pix_format(struct sn9c102_device* cam,
140 const struct v4l2_pix_format* pix)
141{
142 int err = 0;
143
144 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
145 err += sn9c102_write_reg(cam, 0x42, 0x19);
146 else
147 err += sn9c102_write_reg(cam, 0xf2, 0x19);
148
149 return err;
150}
151
152
153static struct sn9c102_sensor hv7131d = {
154 .name = "HV7131D",
155 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
156 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
157 .frequency = SN9C102_I2C_100KHZ,
158 .interface = SN9C102_I2C_2WIRES,
159 .i2c_slave_id = 0x11,
160 .init = &hv7131d_init,
161 .qctrl = {
162 {
163 .id = V4L2_CID_EXPOSURE,
164 .type = V4L2_CTRL_TYPE_INTEGER,
165 .name = "exposure",
166 .minimum = 0x0250,
167 .maximum = 0xffff,
168 .step = 0x0001,
169 .default_value = 0x0250,
170 .flags = 0,
171 },
172 {
173 .id = V4L2_CID_RED_BALANCE,
174 .type = V4L2_CTRL_TYPE_INTEGER,
175 .name = "red balance",
176 .minimum = 0x00,
177 .maximum = 0x3f,
178 .step = 0x01,
179 .default_value = 0x00,
180 .flags = 0,
181 },
182 {
183 .id = V4L2_CID_BLUE_BALANCE,
184 .type = V4L2_CTRL_TYPE_INTEGER,
185 .name = "blue balance",
186 .minimum = 0x00,
187 .maximum = 0x3f,
188 .step = 0x01,
189 .default_value = 0x20,
190 .flags = 0,
191 },
192 {
193 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
194 .type = V4L2_CTRL_TYPE_INTEGER,
195 .name = "green balance",
196 .minimum = 0x00,
197 .maximum = 0x3f,
198 .step = 0x01,
199 .default_value = 0x1e,
200 .flags = 0,
201 },
202 {
203 .id = SN9C102_V4L2_CID_RESET_LEVEL,
204 .type = V4L2_CTRL_TYPE_INTEGER,
205 .name = "reset level",
206 .minimum = 0x19,
207 .maximum = 0x3f,
208 .step = 0x01,
209 .default_value = 0x30,
210 .flags = 0,
211 },
212 {
213 .id = SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE,
214 .type = V4L2_CTRL_TYPE_INTEGER,
215 .name = "pixel bias voltage",
216 .minimum = 0x00,
217 .maximum = 0x07,
218 .step = 0x01,
219 .default_value = 0x02,
220 .flags = 0,
221 },
222 },
223 .get_ctrl = &hv7131d_get_ctrl,
224 .set_ctrl = &hv7131d_set_ctrl,
225 .cropcap = {
226 .bounds = {
227 .left = 0,
228 .top = 0,
229 .width = 640,
230 .height = 480,
231 },
232 .defrect = {
233 .left = 0,
234 .top = 0,
235 .width = 640,
236 .height = 480,
237 },
238 },
239 .set_crop = &hv7131d_set_crop,
240 .pix_format = {
241 .width = 640,
242 .height = 480,
243 .pixelformat = V4L2_PIX_FMT_SBGGR8,
244 .priv = 8,
245 },
246 .set_pix_format = &hv7131d_set_pix_format
247};
248
249
250int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
251{
252 int r0 = 0, r1 = 0, err = 0;
253
254 err += sn9c102_write_reg(cam, 0x01, 0x01);
255 err += sn9c102_write_reg(cam, 0x00, 0x01);
256 err += sn9c102_write_reg(cam, 0x28, 0x17);
257 if (err)
258 return -EIO;
259
260 r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00);
261 r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01);
262 if (r0 < 0 || r1 < 0)
263 return -EIO;
264
265 if (r0 != 0x00 && r1 != 0x04)
266 return -ENODEV;
267
268 sn9c102_attach_sensor(cam, &hv7131d);
269
270 return 0;
271}
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c
new file mode 100644
index 000000000000..d9aa7a61095d
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c
@@ -0,0 +1,363 @@
1/***************************************************************************
2 * Plug-in for MI-0343 image sensor connected to the SN9C10x PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
20 ***************************************************************************/
21
22#include "sn9c102_sensor.h"
23
24
25static struct sn9c102_sensor mi0343;
26static u8 mi0343_i2c_data[5+1];
27
28
29static int mi0343_init(struct sn9c102_device* cam)
30{
31 int err = 0;
32
33 err += sn9c102_write_reg(cam, 0x00, 0x10);
34 err += sn9c102_write_reg(cam, 0x00, 0x11);
35 err += sn9c102_write_reg(cam, 0x0a, 0x14);
36 err += sn9c102_write_reg(cam, 0x40, 0x01);
37 err += sn9c102_write_reg(cam, 0x20, 0x17);
38 err += sn9c102_write_reg(cam, 0x07, 0x18);
39 err += sn9c102_write_reg(cam, 0xa0, 0x19);
40
41 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
42 0x0d, 0x00, 0x01, 0, 0);
43 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
44 0x0d, 0x00, 0x00, 0, 0);
45 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
46 0x03, 0x01, 0xe1, 0, 0);
47 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
48 0x04, 0x02, 0x81, 0, 0);
49 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
50 0x05, 0x00, 0x17, 0, 0);
51 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
52 0x06, 0x00, 0x11, 0, 0);
53 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
54 0x62, 0x04, 0x9a, 0, 0);
55
56 return err;
57}
58
59
60static int mi0343_get_ctrl(struct sn9c102_device* cam,
61 struct v4l2_control* ctrl)
62{
63 switch (ctrl->id) {
64 case V4L2_CID_EXPOSURE:
65 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
66 0x09, 2+1, mi0343_i2c_data) < 0)
67 return -EIO;
68 ctrl->value = mi0343_i2c_data[2];
69 return 0;
70 case V4L2_CID_GAIN:
71 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
72 0x35, 2+1, mi0343_i2c_data) < 0)
73 return -EIO;
74 break;
75 case V4L2_CID_HFLIP:
76 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
77 0x20, 2+1, mi0343_i2c_data) < 0)
78 return -EIO;
79 ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0;
80 return 0;
81 case V4L2_CID_VFLIP:
82 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
83 0x20, 2+1, mi0343_i2c_data) < 0)
84 return -EIO;
85 ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0;
86 return 0;
87 case V4L2_CID_RED_BALANCE:
88 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
89 0x2d, 2+1, mi0343_i2c_data) < 0)
90 return -EIO;
91 break;
92 case V4L2_CID_BLUE_BALANCE:
93 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
94 0x2c, 2+1, mi0343_i2c_data) < 0)
95 return -EIO;
96 break;
97 case SN9C102_V4L2_CID_GREEN_BALANCE:
98 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
99 0x2e, 2+1, mi0343_i2c_data) < 0)
100 return -EIO;
101 break;
102 default:
103 return -EINVAL;
104 }
105
106 switch (ctrl->id) {
107 case V4L2_CID_GAIN:
108 case V4L2_CID_RED_BALANCE:
109 case V4L2_CID_BLUE_BALANCE:
110 case SN9C102_V4L2_CID_GREEN_BALANCE:
111 ctrl->value = mi0343_i2c_data[3] | (mi0343_i2c_data[2] << 8);
112 if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
113 ctrl->value -= 0x10;
114 else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
115 ctrl->value -= 0x60;
116 else if (ctrl->value >= 0xe0 && ctrl->value <= 0xff)
117 ctrl->value -= 0xe0;
118 }
119
120 return 0;
121}
122
123
124static int mi0343_set_ctrl(struct sn9c102_device* cam,
125 const struct v4l2_control* ctrl)
126{
127 u16 reg = 0;
128 int err = 0;
129
130 switch (ctrl->id) {
131 case V4L2_CID_GAIN:
132 case V4L2_CID_RED_BALANCE:
133 case V4L2_CID_BLUE_BALANCE:
134 case SN9C102_V4L2_CID_GREEN_BALANCE:
135 if (ctrl->value <= (0x3f-0x10))
136 reg = 0x10 + ctrl->value;
137 else if (ctrl->value <= ((0x3f-0x10) + (0x7f-0x60)))
138 reg = 0x60 + (ctrl->value - (0x3f-0x10));
139 else
140 reg = 0xe0 + (ctrl->value - (0x3f-0x10) - (0x7f-0x60));
141 break;
142 }
143
144 switch (ctrl->id) {
145 case V4L2_CID_EXPOSURE:
146 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
147 mi0343.i2c_slave_id,
148 0x09, ctrl->value, 0x00,
149 0, 0);
150 break;
151 case V4L2_CID_GAIN:
152 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
153 mi0343.i2c_slave_id,
154 0x35, reg >> 8, reg & 0xff,
155 0, 0);
156 break;
157 case V4L2_CID_HFLIP:
158 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
159 mi0343.i2c_slave_id,
160 0x20, ctrl->value ? 0x40:0x00,
161 ctrl->value ? 0x20:0x00,
162 0, 0);
163 break;
164 case V4L2_CID_VFLIP:
165 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
166 mi0343.i2c_slave_id,
167 0x20, ctrl->value ? 0x80:0x00,
168 ctrl->value ? 0x80:0x00,
169 0, 0);
170 break;
171 case V4L2_CID_RED_BALANCE:
172 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
173 mi0343.i2c_slave_id,
174 0x2d, reg >> 8, reg & 0xff,
175 0, 0);
176 break;
177 case V4L2_CID_BLUE_BALANCE:
178 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
179 mi0343.i2c_slave_id,
180 0x2c, reg >> 8, reg & 0xff,
181 0, 0);
182 break;
183 case SN9C102_V4L2_CID_GREEN_BALANCE:
184 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
185 mi0343.i2c_slave_id,
186 0x2b, reg >> 8, reg & 0xff,
187 0, 0);
188 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
189 mi0343.i2c_slave_id,
190 0x2e, reg >> 8, reg & 0xff,
191 0, 0);
192 break;
193 default:
194 return -EINVAL;
195 }
196
197 return err ? -EIO : 0;
198}
199
200
201static int mi0343_set_crop(struct sn9c102_device* cam,
202 const struct v4l2_rect* rect)
203{
204 struct sn9c102_sensor* s = &mi0343;
205 int err = 0;
206 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
207 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
208
209 err += sn9c102_write_reg(cam, h_start, 0x12);
210 err += sn9c102_write_reg(cam, v_start, 0x13);
211
212 return err;
213}
214
215
216static int mi0343_set_pix_format(struct sn9c102_device* cam,
217 const struct v4l2_pix_format* pix)
218{
219 int err = 0;
220
221 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
222 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
223 mi0343.i2c_slave_id,
224 0x0a, 0x00, 0x03, 0, 0);
225 err += sn9c102_write_reg(cam, 0x20, 0x19);
226 } else {
227 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
228 mi0343.i2c_slave_id,
229 0x0a, 0x00, 0x05, 0, 0);
230 err += sn9c102_write_reg(cam, 0xa0, 0x19);
231 }
232
233 return err;
234}
235
236
237static struct sn9c102_sensor mi0343 = {
238 .name = "MI-0343",
239 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
240 .frequency = SN9C102_I2C_100KHZ,
241 .interface = SN9C102_I2C_2WIRES,
242 .i2c_slave_id = 0x5d,
243 .init = &mi0343_init,
244 .qctrl = {
245 {
246 .id = V4L2_CID_EXPOSURE,
247 .type = V4L2_CTRL_TYPE_INTEGER,
248 .name = "exposure",
249 .minimum = 0x00,
250 .maximum = 0x0f,
251 .step = 0x01,
252 .default_value = 0x06,
253 .flags = 0,
254 },
255 {
256 .id = V4L2_CID_GAIN,
257 .type = V4L2_CTRL_TYPE_INTEGER,
258 .name = "global gain",
259 .minimum = 0x00,
260 .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),/*0x6d*/
261 .step = 0x01,
262 .default_value = 0x00,
263 .flags = 0,
264 },
265 {
266 .id = V4L2_CID_HFLIP,
267 .type = V4L2_CTRL_TYPE_BOOLEAN,
268 .name = "horizontal mirror",
269 .minimum = 0,
270 .maximum = 1,
271 .step = 1,
272 .default_value = 0,
273 .flags = 0,
274 },
275 {
276 .id = V4L2_CID_VFLIP,
277 .type = V4L2_CTRL_TYPE_BOOLEAN,
278 .name = "vertical mirror",
279 .minimum = 0,
280 .maximum = 1,
281 .step = 1,
282 .default_value = 0,
283 .flags = 0,
284 },
285 {
286 .id = V4L2_CID_RED_BALANCE,
287 .type = V4L2_CTRL_TYPE_INTEGER,
288 .name = "red balance",
289 .minimum = 0x00,
290 .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
291 .step = 0x01,
292 .default_value = 0x00,
293 .flags = 0,
294 },
295 {
296 .id = V4L2_CID_BLUE_BALANCE,
297 .type = V4L2_CTRL_TYPE_INTEGER,
298 .name = "blue balance",
299 .minimum = 0x00,
300 .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
301 .step = 0x01,
302 .default_value = 0x00,
303 .flags = 0,
304 },
305 {
306 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
307 .type = V4L2_CTRL_TYPE_INTEGER,
308 .name = "green balance",
309 .minimum = 0x00,
310 .maximum = ((0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0)),
311 .step = 0x01,
312 .default_value = 0x00,
313 .flags = 0,
314 },
315 },
316 .get_ctrl = &mi0343_get_ctrl,
317 .set_ctrl = &mi0343_set_ctrl,
318 .cropcap = {
319 .bounds = {
320 .left = 0,
321 .top = 0,
322 .width = 640,
323 .height = 480,
324 },
325 .defrect = {
326 .left = 0,
327 .top = 0,
328 .width = 640,
329 .height = 480,
330 },
331 },
332 .set_crop = &mi0343_set_crop,
333 .pix_format = {
334 .width = 640,
335 .height = 480,
336 .pixelformat = V4L2_PIX_FMT_SBGGR8,
337 .priv = 8,
338 },
339 .set_pix_format = &mi0343_set_pix_format
340};
341
342
343int sn9c102_probe_mi0343(struct sn9c102_device* cam)
344{
345 int err = 0;
346
347 err += sn9c102_write_reg(cam, 0x01, 0x01);
348 err += sn9c102_write_reg(cam, 0x00, 0x01);
349 err += sn9c102_write_reg(cam, 0x28, 0x17);
350 if (err)
351 return -EIO;
352
353 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
354 2, mi0343_i2c_data) < 0)
355 return -EIO;
356
357 if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3)
358 return -ENODEV;
359
360 sn9c102_attach_sensor(cam, &mi0343);
361
362 return 0;
363}
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c
new file mode 100644
index 000000000000..42852b7cb042
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c
@@ -0,0 +1,401 @@
1/***************************************************************************
2 * Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2005-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
20 ***************************************************************************/
21
22#include "sn9c102_sensor.h"
23
24
25static struct sn9c102_sensor ov7630;
26
27
28static int ov7630_init(struct sn9c102_device* cam)
29{
30 int err = 0;
31
32 err += sn9c102_write_reg(cam, 0x00, 0x14);
33 err += sn9c102_write_reg(cam, 0x60, 0x17);
34 err += sn9c102_write_reg(cam, 0x0f, 0x18);
35 err += sn9c102_write_reg(cam, 0x50, 0x19);
36
37 err += sn9c102_i2c_write(cam, 0x12, 0x80);
38 err += sn9c102_i2c_write(cam, 0x11, 0x01);
39 err += sn9c102_i2c_write(cam, 0x15, 0x34);
40 err += sn9c102_i2c_write(cam, 0x16, 0x03);
41 err += sn9c102_i2c_write(cam, 0x17, 0x1c);
42 err += sn9c102_i2c_write(cam, 0x18, 0xbd);
43 err += sn9c102_i2c_write(cam, 0x19, 0x06);
44 err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
45 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
46 err += sn9c102_i2c_write(cam, 0x20, 0xf6);
47 err += sn9c102_i2c_write(cam, 0x23, 0xee);
48 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
49 err += sn9c102_i2c_write(cam, 0x27, 0x9a);
50 err += sn9c102_i2c_write(cam, 0x28, 0xa0);
51 err += sn9c102_i2c_write(cam, 0x29, 0x30);
52 err += sn9c102_i2c_write(cam, 0x2a, 0xa0);
53 err += sn9c102_i2c_write(cam, 0x2b, 0x1f);
54 err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
55 err += sn9c102_i2c_write(cam, 0x30, 0x24);
56 err += sn9c102_i2c_write(cam, 0x32, 0x86);
57 err += sn9c102_i2c_write(cam, 0x60, 0xa9);
58 err += sn9c102_i2c_write(cam, 0x61, 0x42);
59 err += sn9c102_i2c_write(cam, 0x65, 0x00);
60 err += sn9c102_i2c_write(cam, 0x69, 0x38);
61 err += sn9c102_i2c_write(cam, 0x6f, 0x88);
62 err += sn9c102_i2c_write(cam, 0x70, 0x0b);
63 err += sn9c102_i2c_write(cam, 0x71, 0x00);
64 err += sn9c102_i2c_write(cam, 0x74, 0x21);
65 err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
66
67 return err;
68}
69
70
71static int ov7630_set_ctrl(struct sn9c102_device* cam,
72 const struct v4l2_control* ctrl)
73{
74 int err = 0;
75
76 switch (ctrl->id) {
77 case V4L2_CID_EXPOSURE:
78 err += sn9c102_i2c_write(cam, 0x10, ctrl->value >> 2);
79 err += sn9c102_i2c_write(cam, 0x76, ctrl->value & 0x03);
80 break;
81 case V4L2_CID_RED_BALANCE:
82 err += sn9c102_i2c_write(cam, 0x02, ctrl->value);
83 break;
84 case V4L2_CID_BLUE_BALANCE:
85 err += sn9c102_i2c_write(cam, 0x01, ctrl->value);
86 break;
87 case V4L2_CID_GAIN:
88 err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
89 break;
90 case V4L2_CID_CONTRAST:
91 err += ctrl->value ? sn9c102_i2c_write(cam, 0x05,
92 (ctrl->value-1) | 0x20)
93 : sn9c102_i2c_write(cam, 0x05, 0x00);
94 break;
95 case V4L2_CID_BRIGHTNESS:
96 err += sn9c102_i2c_write(cam, 0x06, ctrl->value);
97 break;
98 case V4L2_CID_SATURATION:
99 err += sn9c102_i2c_write(cam, 0x03, ctrl->value << 4);
100 break;
101 case V4L2_CID_HUE:
102 err += ctrl->value ? sn9c102_i2c_write(cam, 0x04,
103 (ctrl->value-1) | 0x20)
104 : sn9c102_i2c_write(cam, 0x04, 0x00);
105 break;
106 case V4L2_CID_DO_WHITE_BALANCE:
107 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
108 break;
109 case V4L2_CID_WHITENESS:
110 err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
111 break;
112 case V4L2_CID_AUTO_WHITE_BALANCE:
113 err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x78);
114 break;
115 case V4L2_CID_AUTOGAIN:
116 err += sn9c102_i2c_write(cam, 0x13, ctrl->value);
117 break;
118 case V4L2_CID_VFLIP:
119 err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7));
120 break;
121 case V4L2_CID_BLACK_LEVEL:
122 err += sn9c102_i2c_write(cam, 0x25, ctrl->value);
123 break;
124 case SN9C102_V4L2_CID_BRIGHT_LEVEL:
125 err += sn9c102_i2c_write(cam, 0x24, ctrl->value);
126 break;
127 case SN9C102_V4L2_CID_GAMMA:
128 err += sn9c102_i2c_write(cam, 0x14, (ctrl->value << 2) | 0x80);
129 break;
130 case SN9C102_V4L2_CID_BAND_FILTER:
131 err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2);
132 break;
133 default:
134 return -EINVAL;
135 }
136
137 return err ? -EIO : 0;
138}
139
140
141static int ov7630_set_crop(struct sn9c102_device* cam,
142 const struct v4l2_rect* rect)
143{
144 struct sn9c102_sensor* s = &ov7630;
145 int err = 0;
146 u8 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
147
148 err += sn9c102_write_reg(cam, v_start, 0x13);
149
150 return err;
151}
152
153
154static int ov7630_set_pix_format(struct sn9c102_device* cam,
155 const struct v4l2_pix_format* pix)
156{
157 int err = 0;
158
159 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
160 err += sn9c102_write_reg(cam, 0x20, 0x19);
161 else
162 err += sn9c102_write_reg(cam, 0x50, 0x19);
163
164 return err;
165}
166
167
168static struct sn9c102_sensor ov7630 = {
169 .name = "OV7630",
170 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
171 .sysfs_ops = SN9C102_I2C_WRITE,
172 .frequency = SN9C102_I2C_100KHZ,
173 .interface = SN9C102_I2C_2WIRES,
174 .i2c_slave_id = 0x21,
175 .init = &ov7630_init,
176 .qctrl = {
177 {
178 .id = V4L2_CID_GAIN,
179 .type = V4L2_CTRL_TYPE_INTEGER,
180 .name = "global gain",
181 .minimum = 0x00,
182 .maximum = 0x3f,
183 .step = 0x01,
184 .default_value = 0x14,
185 .flags = 0,
186 },
187 {
188 .id = V4L2_CID_HUE,
189 .type = V4L2_CTRL_TYPE_INTEGER,
190 .name = "hue",
191 .minimum = 0x00,
192 .maximum = 0x1f+1,
193 .step = 0x01,
194 .default_value = 0x00,
195 .flags = 0,
196 },
197 {
198 .id = V4L2_CID_SATURATION,
199 .type = V4L2_CTRL_TYPE_INTEGER,
200 .name = "saturation",
201 .minimum = 0x00,
202 .maximum = 0x0f,
203 .step = 0x01,
204 .default_value = 0x08,
205 .flags = 0,
206 },
207 {
208 .id = V4L2_CID_CONTRAST,
209 .type = V4L2_CTRL_TYPE_INTEGER,
210 .name = "contrast",
211 .minimum = 0x00,
212 .maximum = 0x1f+1,
213 .step = 0x01,
214 .default_value = 0x00,
215 .flags = 0,
216 },
217 {
218 .id = V4L2_CID_EXPOSURE,
219 .type = V4L2_CTRL_TYPE_INTEGER,
220 .name = "exposure",
221 .minimum = 0x000,
222 .maximum = 0x3ff,
223 .step = 0x001,
224 .default_value = 0x83<<2,
225 .flags = 0,
226 },
227 {
228 .id = V4L2_CID_RED_BALANCE,
229 .type = V4L2_CTRL_TYPE_INTEGER,
230 .name = "red balance",
231 .minimum = 0x00,
232 .maximum = 0xff,
233 .step = 0x01,
234 .default_value = 0x3a,
235 .flags = 0,
236 },
237 {
238 .id = V4L2_CID_BLUE_BALANCE,
239 .type = V4L2_CTRL_TYPE_INTEGER,
240 .name = "blue balance",
241 .minimum = 0x00,
242 .maximum = 0xff,
243 .step = 0x01,
244 .default_value = 0x77,
245 .flags = 0,
246 },
247 {
248 .id = V4L2_CID_BRIGHTNESS,
249 .type = V4L2_CTRL_TYPE_INTEGER,
250 .name = "brightness",
251 .minimum = 0x00,
252 .maximum = 0xff,
253 .step = 0x01,
254 .default_value = 0xa0,
255 .flags = 0,
256 },
257 {
258 .id = V4L2_CID_DO_WHITE_BALANCE,
259 .type = V4L2_CTRL_TYPE_INTEGER,
260 .name = "white balance background: blue",
261 .minimum = 0x00,
262 .maximum = 0x3f,
263 .step = 0x01,
264 .default_value = 0x20,
265 .flags = 0,
266 },
267 {
268 .id = V4L2_CID_WHITENESS,
269 .type = V4L2_CTRL_TYPE_INTEGER,
270 .name = "white balance background: red",
271 .minimum = 0x00,
272 .maximum = 0x3f,
273 .step = 0x01,
274 .default_value = 0x20,
275 .flags = 0,
276 },
277 {
278 .id = V4L2_CID_AUTO_WHITE_BALANCE,
279 .type = V4L2_CTRL_TYPE_BOOLEAN,
280 .name = "auto white balance",
281 .minimum = 0x00,
282 .maximum = 0x01,
283 .step = 0x01,
284 .default_value = 0x01,
285 .flags = 0,
286 },
287 {
288 .id = V4L2_CID_AUTOGAIN,
289 .type = V4L2_CTRL_TYPE_INTEGER,
290 .name = "gain & exposure mode",
291 .minimum = 0x00,
292 .maximum = 0x03,
293 .step = 0x01,
294 .default_value = 0x00,
295 .flags = 0,
296 },
297 {
298 .id = V4L2_CID_VFLIP,
299 .type = V4L2_CTRL_TYPE_BOOLEAN,
300 .name = "vertical flip",
301 .minimum = 0x00,
302 .maximum = 0x01,
303 .step = 0x01,
304 .default_value = 0x01,
305 .flags = 0,
306 },
307 {
308 .id = V4L2_CID_BLACK_LEVEL,
309 .type = V4L2_CTRL_TYPE_INTEGER,
310 .name = "black pixel ratio",
311 .minimum = 0x01,
312 .maximum = 0x9a,
313 .step = 0x01,
314 .default_value = 0x8a,
315 .flags = 0,
316 },
317 {
318 .id = SN9C102_V4L2_CID_BRIGHT_LEVEL,
319 .type = V4L2_CTRL_TYPE_INTEGER,
320 .name = "bright pixel ratio",
321 .minimum = 0x01,
322 .maximum = 0x9a,
323 .step = 0x01,
324 .default_value = 0x10,
325 .flags = 0,
326 },
327 {
328 .id = SN9C102_V4L2_CID_BAND_FILTER,
329 .type = V4L2_CTRL_TYPE_BOOLEAN,
330 .name = "band filter",
331 .minimum = 0x00,
332 .maximum = 0x01,
333 .step = 0x01,
334 .default_value = 0x00,
335 .flags = 0,
336 },
337 {
338 .id = SN9C102_V4L2_CID_GAMMA,
339 .type = V4L2_CTRL_TYPE_BOOLEAN,
340 .name = "rgb gamma",
341 .minimum = 0x00,
342 .maximum = 0x01,
343 .step = 0x01,
344 .default_value = 0x00,
345 .flags = 0,
346 },
347 },
348 .set_ctrl = &ov7630_set_ctrl,
349 .cropcap = {
350 .bounds = {
351 .left = 0,
352 .top = 0,
353 .width = 640,
354 .height = 480,
355 },
356 .defrect = {
357 .left = 0,
358 .top = 0,
359 .width = 640,
360 .height = 480,
361 },
362 },
363 .set_crop = &ov7630_set_crop,
364 .pix_format = {
365 .width = 640,
366 .height = 480,
367 .pixelformat = V4L2_PIX_FMT_SBGGR8,
368 .priv = 8,
369 },
370 .set_pix_format = &ov7630_set_pix_format
371};
372
373
374int sn9c102_probe_ov7630(struct sn9c102_device* cam)
375{
376 const struct usb_device_id ov7630_id_table[] = {
377 { USB_DEVICE(0x0c45, 0x602c), },
378 { USB_DEVICE(0x0c45, 0x602d), },
379 { USB_DEVICE(0x0c45, 0x608f), },
380 { USB_DEVICE(0x0c45, 0x60b0), },
381 { }
382 };
383 int err = 0;
384
385 if (!sn9c102_match_id(cam, ov7630_id_table))
386 return -ENODEV;
387
388 err += sn9c102_write_reg(cam, 0x01, 0x01);
389 err += sn9c102_write_reg(cam, 0x00, 0x01);
390 err += sn9c102_write_reg(cam, 0x28, 0x17);
391 if (err)
392 return -EIO;
393
394 err += sn9c102_i2c_try_write(cam, &ov7630, 0x0b, 0);
395 if (err)
396 return -ENODEV;
397
398 sn9c102_attach_sensor(cam, &ov7630);
399
400 return 0;
401}
diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c
new file mode 100644
index 000000000000..b1dee78abe04
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c
@@ -0,0 +1,307 @@
1/***************************************************************************
2 * Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
20 ***************************************************************************/
21
22#include <linux/delay.h>
23#include "sn9c102_sensor.h"
24
25
26static struct sn9c102_sensor pas106b;
27
28
29static int pas106b_init(struct sn9c102_device* cam)
30{
31 int err = 0;
32
33 err += sn9c102_write_reg(cam, 0x00, 0x10);
34 err += sn9c102_write_reg(cam, 0x00, 0x11);
35 err += sn9c102_write_reg(cam, 0x00, 0x14);
36 err += sn9c102_write_reg(cam, 0x20, 0x17);
37 err += sn9c102_write_reg(cam, 0x20, 0x19);
38 err += sn9c102_write_reg(cam, 0x09, 0x18);
39
40 err += sn9c102_i2c_write(cam, 0x02, 0x0c);
41 err += sn9c102_i2c_write(cam, 0x05, 0x5a);
42 err += sn9c102_i2c_write(cam, 0x06, 0x88);
43 err += sn9c102_i2c_write(cam, 0x07, 0x80);
44 err += sn9c102_i2c_write(cam, 0x10, 0x06);
45 err += sn9c102_i2c_write(cam, 0x11, 0x06);
46 err += sn9c102_i2c_write(cam, 0x12, 0x00);
47 err += sn9c102_i2c_write(cam, 0x14, 0x02);
48 err += sn9c102_i2c_write(cam, 0x13, 0x01);
49
50 msleep(400);
51
52 return err;
53}
54
55
56static int pas106b_get_ctrl(struct sn9c102_device* cam,
57 struct v4l2_control* ctrl)
58{
59 switch (ctrl->id) {
60 case V4L2_CID_EXPOSURE:
61 {
62 int r1 = sn9c102_i2c_read(cam, 0x03),
63 r2 = sn9c102_i2c_read(cam, 0x04);
64 if (r1 < 0 || r2 < 0)
65 return -EIO;
66 ctrl->value = (r1 << 4) | (r2 & 0x0f);
67 }
68 return 0;
69 case V4L2_CID_RED_BALANCE:
70 if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
71 return -EIO;
72 ctrl->value &= 0x1f;
73 return 0;
74 case V4L2_CID_BLUE_BALANCE:
75 if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
76 return -EIO;
77 ctrl->value &= 0x1f;
78 return 0;
79 case V4L2_CID_GAIN:
80 if ((ctrl->value = sn9c102_i2c_read(cam, 0x0e)) < 0)
81 return -EIO;
82 ctrl->value &= 0x1f;
83 return 0;
84 case V4L2_CID_CONTRAST:
85 if ((ctrl->value = sn9c102_i2c_read(cam, 0x0f)) < 0)
86 return -EIO;
87 ctrl->value &= 0x07;
88 return 0;
89 case SN9C102_V4L2_CID_GREEN_BALANCE:
90 if ((ctrl->value = sn9c102_i2c_read(cam, 0x0a)) < 0)
91 return -EIO;
92 ctrl->value = (ctrl->value & 0x1f) << 1;
93 return 0;
94 case SN9C102_V4L2_CID_DAC_MAGNITUDE:
95 if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0)
96 return -EIO;
97 ctrl->value &= 0xf8;
98 return 0;
99 default:
100 return -EINVAL;
101 }
102}
103
104
105static int pas106b_set_ctrl(struct sn9c102_device* cam,
106 const struct v4l2_control* ctrl)
107{
108 int err = 0;
109
110 switch (ctrl->id) {
111 case V4L2_CID_EXPOSURE:
112 err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4);
113 err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f);
114 break;
115 case V4L2_CID_RED_BALANCE:
116 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
117 break;
118 case V4L2_CID_BLUE_BALANCE:
119 err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
120 break;
121 case V4L2_CID_GAIN:
122 err += sn9c102_i2c_write(cam, 0x0e, ctrl->value);
123 break;
124 case V4L2_CID_CONTRAST:
125 err += sn9c102_i2c_write(cam, 0x0f, ctrl->value);
126 break;
127 case SN9C102_V4L2_CID_GREEN_BALANCE:
128 err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1);
129 err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1);
130 break;
131 case SN9C102_V4L2_CID_DAC_MAGNITUDE:
132 err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3);
133 break;
134 default:
135 return -EINVAL;
136 }
137 err += sn9c102_i2c_write(cam, 0x13, 0x01);
138
139 return err ? -EIO : 0;
140}
141
142
143static int pas106b_set_crop(struct sn9c102_device* cam,
144 const struct v4l2_rect* rect)
145{
146 struct sn9c102_sensor* s = &pas106b;
147 int err = 0;
148 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
149 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
150
151 err += sn9c102_write_reg(cam, h_start, 0x12);
152 err += sn9c102_write_reg(cam, v_start, 0x13);
153
154 return err;
155}
156
157
158static int pas106b_set_pix_format(struct sn9c102_device* cam,
159 const struct v4l2_pix_format* pix)
160{
161 int err = 0;
162
163 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
164 err += sn9c102_write_reg(cam, 0x2c, 0x17);
165 else
166 err += sn9c102_write_reg(cam, 0x20, 0x17);
167
168 return err;
169}
170
171
172static struct sn9c102_sensor pas106b = {
173 .name = "PAS106B",
174 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
175 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
176 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
177 .interface = SN9C102_I2C_2WIRES,
178 .i2c_slave_id = 0x40,
179 .init = &pas106b_init,
180 .qctrl = {
181 {
182 .id = V4L2_CID_EXPOSURE,
183 .type = V4L2_CTRL_TYPE_INTEGER,
184 .name = "exposure",
185 .minimum = 0x125,
186 .maximum = 0xfff,
187 .step = 0x001,
188 .default_value = 0x140,
189 .flags = 0,
190 },
191 {
192 .id = V4L2_CID_GAIN,
193 .type = V4L2_CTRL_TYPE_INTEGER,
194 .name = "global gain",
195 .minimum = 0x00,
196 .maximum = 0x1f,
197 .step = 0x01,
198 .default_value = 0x0d,
199 .flags = 0,
200 },
201 {
202 .id = V4L2_CID_CONTRAST,
203 .type = V4L2_CTRL_TYPE_INTEGER,
204 .name = "contrast",
205 .minimum = 0x00,
206 .maximum = 0x07,
207 .step = 0x01,
208 .default_value = 0x00, /* 0x00~0x03 have same effect */
209 .flags = 0,
210 },
211 {
212 .id = V4L2_CID_RED_BALANCE,
213 .type = V4L2_CTRL_TYPE_INTEGER,
214 .name = "red balance",
215 .minimum = 0x00,
216 .maximum = 0x1f,
217 .step = 0x01,
218 .default_value = 0x04,
219 .flags = 0,
220 },
221 {
222 .id = V4L2_CID_BLUE_BALANCE,
223 .type = V4L2_CTRL_TYPE_INTEGER,
224 .name = "blue balance",
225 .minimum = 0x00,
226 .maximum = 0x1f,
227 .step = 0x01,
228 .default_value = 0x06,
229 .flags = 0,
230 },
231 {
232 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
233 .type = V4L2_CTRL_TYPE_INTEGER,
234 .name = "green balance",
235 .minimum = 0x00,
236 .maximum = 0x3e,
237 .step = 0x02,
238 .default_value = 0x02,
239 .flags = 0,
240 },
241 {
242 .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
243 .type = V4L2_CTRL_TYPE_INTEGER,
244 .name = "DAC magnitude",
245 .minimum = 0x00,
246 .maximum = 0x1f,
247 .step = 0x01,
248 .default_value = 0x01,
249 .flags = 0,
250 },
251 },
252 .get_ctrl = &pas106b_get_ctrl,
253 .set_ctrl = &pas106b_set_ctrl,
254 .cropcap = {
255 .bounds = {
256 .left = 0,
257 .top = 0,
258 .width = 352,
259 .height = 288,
260 },
261 .defrect = {
262 .left = 0,
263 .top = 0,
264 .width = 352,
265 .height = 288,
266 },
267 },
268 .set_crop = &pas106b_set_crop,
269 .pix_format = {
270 .width = 352,
271 .height = 288,
272 .pixelformat = V4L2_PIX_FMT_SBGGR8,
273 .priv = 8, /* we use this field as 'bits per pixel' */
274 },
275 .set_pix_format = &pas106b_set_pix_format
276};
277
278
279int sn9c102_probe_pas106b(struct sn9c102_device* cam)
280{
281 int r0 = 0, r1 = 0, err = 0;
282 unsigned int pid = 0;
283
284 /*
285 Minimal initialization to enable the I2C communication
286 NOTE: do NOT change the values!
287 */
288 err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */
289 err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */
290 err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */
291 if (err)
292 return -EIO;
293
294 r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00);
295 r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01);
296
297 if (r0 < 0 || r1 < 0)
298 return -EIO;
299
300 pid = (r0 << 11) | ((r1 & 0xf0) >> 4);
301 if (pid != 0x007)
302 return -ENODEV;
303
304 sn9c102_attach_sensor(cam, &pas106b);
305
306 return 0;
307}
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bca.c b/drivers/media/video/sn9c102/sn9c102_pas202bca.c
new file mode 100644
index 000000000000..3453237055bb
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_pas202bca.c
@@ -0,0 +1,238 @@
1/***************************************************************************
2 * Plug-in for PAS202BCA image sensor connected to the SN9C10x PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
20 ***************************************************************************/
21
22#include <linux/delay.h>
23#include "sn9c102_sensor.h"
24
25
26static struct sn9c102_sensor pas202bca;
27
28
29static int pas202bca_init(struct sn9c102_device* cam)
30{
31 int err = 0;
32
33 err += sn9c102_write_reg(cam, 0x00, 0x10);
34 err += sn9c102_write_reg(cam, 0x00, 0x11);
35 err += sn9c102_write_reg(cam, 0x00, 0x14);
36 err += sn9c102_write_reg(cam, 0x20, 0x17);
37 err += sn9c102_write_reg(cam, 0x30, 0x19);
38 err += sn9c102_write_reg(cam, 0x09, 0x18);
39
40 err += sn9c102_i2c_write(cam, 0x02, 0x14);
41 err += sn9c102_i2c_write(cam, 0x03, 0x40);
42 err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
43 err += sn9c102_i2c_write(cam, 0x0e, 0x01);
44 err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
45 err += sn9c102_i2c_write(cam, 0x10, 0x08);
46 err += sn9c102_i2c_write(cam, 0x13, 0x63);
47 err += sn9c102_i2c_write(cam, 0x15, 0x70);
48 err += sn9c102_i2c_write(cam, 0x11, 0x01);
49
50 msleep(400);
51
52 return err;
53}
54
55
56static int pas202bca_set_pix_format(struct sn9c102_device* cam,
57 const struct v4l2_pix_format* pix)
58{
59 int err = 0;
60
61 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
62 err += sn9c102_write_reg(cam, 0x24, 0x17);
63 else
64 err += sn9c102_write_reg(cam, 0x20, 0x17);
65
66 return err;
67}
68
69
70static int pas202bca_set_ctrl(struct sn9c102_device* cam,
71 const struct v4l2_control* ctrl)
72{
73 int err = 0;
74
75 switch (ctrl->id) {
76 case V4L2_CID_EXPOSURE:
77 err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
78 err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
79 break;
80 case V4L2_CID_RED_BALANCE:
81 err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
82 break;
83 case V4L2_CID_BLUE_BALANCE:
84 err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
85 break;
86 case V4L2_CID_GAIN:
87 err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
88 break;
89 case SN9C102_V4L2_CID_GREEN_BALANCE:
90 err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
91 break;
92 case SN9C102_V4L2_CID_DAC_MAGNITUDE:
93 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
94 break;
95 default:
96 return -EINVAL;
97 }
98 err += sn9c102_i2c_write(cam, 0x11, 0x01);
99
100 return err ? -EIO : 0;
101}
102
103
104static int pas202bca_set_crop(struct sn9c102_device* cam,
105 const struct v4l2_rect* rect)
106{
107 struct sn9c102_sensor* s = &pas202bca;
108 int err = 0;
109 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3,
110 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
111
112 err += sn9c102_write_reg(cam, h_start, 0x12);
113 err += sn9c102_write_reg(cam, v_start, 0x13);
114
115 return err;
116}
117
118
119static struct sn9c102_sensor pas202bca = {
120 .name = "PAS202BCA",
121 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
122 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
123 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
124 .interface = SN9C102_I2C_2WIRES,
125 .i2c_slave_id = 0x40,
126 .init = &pas202bca_init,
127 .qctrl = {
128 {
129 .id = V4L2_CID_EXPOSURE,
130 .type = V4L2_CTRL_TYPE_INTEGER,
131 .name = "exposure",
132 .minimum = 0x01e5,
133 .maximum = 0x3fff,
134 .step = 0x0001,
135 .default_value = 0x01e5,
136 .flags = 0,
137 },
138 {
139 .id = V4L2_CID_GAIN,
140 .type = V4L2_CTRL_TYPE_INTEGER,
141 .name = "global gain",
142 .minimum = 0x00,
143 .maximum = 0x1f,
144 .step = 0x01,
145 .default_value = 0x0c,
146 .flags = 0,
147 },
148 {
149 .id = V4L2_CID_RED_BALANCE,
150 .type = V4L2_CTRL_TYPE_INTEGER,
151 .name = "red balance",
152 .minimum = 0x00,
153 .maximum = 0x0f,
154 .step = 0x01,
155 .default_value = 0x01,
156 .flags = 0,
157 },
158 {
159 .id = V4L2_CID_BLUE_BALANCE,
160 .type = V4L2_CTRL_TYPE_INTEGER,
161 .name = "blue balance",
162 .minimum = 0x00,
163 .maximum = 0x0f,
164 .step = 0x01,
165 .default_value = 0x05,
166 .flags = 0,
167 },
168 {
169 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
170 .type = V4L2_CTRL_TYPE_INTEGER,
171 .name = "green balance",
172 .minimum = 0x00,
173 .maximum = 0x0f,
174 .step = 0x01,
175 .default_value = 0x00,
176 .flags = 0,
177 },
178 {
179 .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
180 .type = V4L2_CTRL_TYPE_INTEGER,
181 .name = "DAC magnitude",
182 .minimum = 0x00,
183 .maximum = 0xff,
184 .step = 0x01,
185 .default_value = 0x04,
186 .flags = 0,
187 },
188 },
189 .set_ctrl = &pas202bca_set_ctrl,
190 .cropcap = {
191 .bounds = {
192 .left = 0,
193 .top = 0,
194 .width = 640,
195 .height = 480,
196 },
197 .defrect = {
198 .left = 0,
199 .top = 0,
200 .width = 640,
201 .height = 480,
202 },
203 },
204 .set_crop = &pas202bca_set_crop,
205 .pix_format = {
206 .width = 640,
207 .height = 480,
208 .pixelformat = V4L2_PIX_FMT_SBGGR8,
209 .priv = 8,
210 },
211 .set_pix_format = &pas202bca_set_pix_format
212};
213
214
215int sn9c102_probe_pas202bca(struct sn9c102_device* cam)
216{
217 const struct usb_device_id pas202bca_id_table[] = {
218 { USB_DEVICE(0x0c45, 0x60af), },
219 { }
220 };
221 int err = 0;
222
223 if (!sn9c102_match_id(cam,pas202bca_id_table))
224 return -ENODEV;
225
226 err += sn9c102_write_reg(cam, 0x01, 0x01);
227 err += sn9c102_write_reg(cam, 0x40, 0x01);
228 err += sn9c102_write_reg(cam, 0x28, 0x17);
229 if (err)
230 return -EIO;
231
232 if (sn9c102_i2c_try_write(cam, &pas202bca, 0x10, 0)) /* try to write */
233 return -ENODEV;
234
235 sn9c102_attach_sensor(cam, &pas202bca);
236
237 return 0;
238}
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
new file mode 100644
index 000000000000..d068616ab337
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
@@ -0,0 +1,293 @@
1/***************************************************************************
2 * Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio *
6 * <medaglia@undl.org.br> *
7 * http://cadu.homelinux.com:8080/ *
8 * *
9 * DAC Magnitude, exposure and green gain controls added by *
10 * Luca Risolia <luca.risolia@studio.unibo.it> *
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 * This program is distributed in the hope that it will be useful, *
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20 * GNU General Public License for more details. *
21 * *
22 * You should have received a copy of the GNU General Public License *
23 * along with this program; if not, write to the Free Software *
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
25 ***************************************************************************/
26
27#include <linux/delay.h>
28#include "sn9c102_sensor.h"
29
30
31static struct sn9c102_sensor pas202bcb;
32
33
34static int pas202bcb_init(struct sn9c102_device* cam)
35{
36 int err = 0;
37
38 err += sn9c102_write_reg(cam, 0x00, 0x10);
39 err += sn9c102_write_reg(cam, 0x00, 0x11);
40 err += sn9c102_write_reg(cam, 0x00, 0x14);
41 err += sn9c102_write_reg(cam, 0x20, 0x17);
42 err += sn9c102_write_reg(cam, 0x30, 0x19);
43 err += sn9c102_write_reg(cam, 0x09, 0x18);
44
45 err += sn9c102_i2c_write(cam, 0x02, 0x14);
46 err += sn9c102_i2c_write(cam, 0x03, 0x40);
47 err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
48 err += sn9c102_i2c_write(cam, 0x0e, 0x01);
49 err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
50 err += sn9c102_i2c_write(cam, 0x10, 0x08);
51 err += sn9c102_i2c_write(cam, 0x13, 0x63);
52 err += sn9c102_i2c_write(cam, 0x15, 0x70);
53 err += sn9c102_i2c_write(cam, 0x11, 0x01);
54
55 msleep(400);
56
57 return err;
58}
59
60
61static int pas202bcb_get_ctrl(struct sn9c102_device* cam,
62 struct v4l2_control* ctrl)
63{
64 switch (ctrl->id) {
65 case V4L2_CID_EXPOSURE:
66 {
67 int r1 = sn9c102_i2c_read(cam, 0x04),
68 r2 = sn9c102_i2c_read(cam, 0x05);
69 if (r1 < 0 || r2 < 0)
70 return -EIO;
71 ctrl->value = (r1 << 6) | (r2 & 0x3f);
72 }
73 return 0;
74 case V4L2_CID_RED_BALANCE:
75 if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
76 return -EIO;
77 ctrl->value &= 0x0f;
78 return 0;
79 case V4L2_CID_BLUE_BALANCE:
80 if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0)
81 return -EIO;
82 ctrl->value &= 0x0f;
83 return 0;
84 case V4L2_CID_GAIN:
85 if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
86 return -EIO;
87 ctrl->value &= 0x1f;
88 return 0;
89 case SN9C102_V4L2_CID_GREEN_BALANCE:
90 if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0)
91 return -EIO;
92 ctrl->value &= 0x0f;
93 return 0;
94 case SN9C102_V4L2_CID_DAC_MAGNITUDE:
95 if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
96 return -EIO;
97 return 0;
98 default:
99 return -EINVAL;
100 }
101}
102
103
104static int pas202bcb_set_pix_format(struct sn9c102_device* cam,
105 const struct v4l2_pix_format* pix)
106{
107 int err = 0;
108
109 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
110 err += sn9c102_write_reg(cam, 0x24, 0x17);
111 else
112 err += sn9c102_write_reg(cam, 0x20, 0x17);
113
114 return err;
115}
116
117
118static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
119 const struct v4l2_control* ctrl)
120{
121 int err = 0;
122
123 switch (ctrl->id) {
124 case V4L2_CID_EXPOSURE:
125 err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
126 err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
127 break;
128 case V4L2_CID_RED_BALANCE:
129 err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
130 break;
131 case V4L2_CID_BLUE_BALANCE:
132 err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
133 break;
134 case V4L2_CID_GAIN:
135 err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
136 break;
137 case SN9C102_V4L2_CID_GREEN_BALANCE:
138 err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
139 break;
140 case SN9C102_V4L2_CID_DAC_MAGNITUDE:
141 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
142 break;
143 default:
144 return -EINVAL;
145 }
146 err += sn9c102_i2c_write(cam, 0x11, 0x01);
147
148 return err ? -EIO : 0;
149}
150
151
152static int pas202bcb_set_crop(struct sn9c102_device* cam,
153 const struct v4l2_rect* rect)
154{
155 struct sn9c102_sensor* s = &pas202bcb;
156 int err = 0;
157 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
158 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
159
160 err += sn9c102_write_reg(cam, h_start, 0x12);
161 err += sn9c102_write_reg(cam, v_start, 0x13);
162
163 return err;
164}
165
166
167static struct sn9c102_sensor pas202bcb = {
168 .name = "PAS202BCB",
169 .maintainer = "Carlos Eduardo Medaglia Dyonisio "
170 "<medaglia@undl.org.br>",
171 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
172 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
173 .interface = SN9C102_I2C_2WIRES,
174 .i2c_slave_id = 0x40,
175 .init = &pas202bcb_init,
176 .qctrl = {
177 {
178 .id = V4L2_CID_EXPOSURE,
179 .type = V4L2_CTRL_TYPE_INTEGER,
180 .name = "exposure",
181 .minimum = 0x01e5,
182 .maximum = 0x3fff,
183 .step = 0x0001,
184 .default_value = 0x01e5,
185 .flags = 0,
186 },
187 {
188 .id = V4L2_CID_GAIN,
189 .type = V4L2_CTRL_TYPE_INTEGER,
190 .name = "global gain",
191 .minimum = 0x00,
192 .maximum = 0x1f,
193 .step = 0x01,
194 .default_value = 0x0c,
195 .flags = 0,
196 },
197 {
198 .id = V4L2_CID_RED_BALANCE,
199 .type = V4L2_CTRL_TYPE_INTEGER,
200 .name = "red balance",
201 .minimum = 0x00,
202 .maximum = 0x0f,
203 .step = 0x01,
204 .default_value = 0x01,
205 .flags = 0,
206 },
207 {
208 .id = V4L2_CID_BLUE_BALANCE,
209 .type = V4L2_CTRL_TYPE_INTEGER,
210 .name = "blue balance",
211 .minimum = 0x00,
212 .maximum = 0x0f,
213 .step = 0x01,
214 .default_value = 0x05,
215 .flags = 0,
216 },
217 {
218 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
219 .type = V4L2_CTRL_TYPE_INTEGER,
220 .name = "green balance",
221 .minimum = 0x00,
222 .maximum = 0x0f,
223 .step = 0x01,
224 .default_value = 0x00,
225 .flags = 0,
226 },
227 {
228 .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
229 .type = V4L2_CTRL_TYPE_INTEGER,
230 .name = "DAC magnitude",
231 .minimum = 0x00,
232 .maximum = 0xff,
233 .step = 0x01,
234 .default_value = 0x04,
235 .flags = 0,
236 },
237 },
238 .get_ctrl = &pas202bcb_get_ctrl,
239 .set_ctrl = &pas202bcb_set_ctrl,
240 .cropcap = {
241 .bounds = {
242 .left = 0,
243 .top = 0,
244 .width = 640,
245 .height = 480,
246 },
247 .defrect = {
248 .left = 0,
249 .top = 0,
250 .width = 640,
251 .height = 480,
252 },
253 },
254 .set_crop = &pas202bcb_set_crop,
255 .pix_format = {
256 .width = 640,
257 .height = 480,
258 .pixelformat = V4L2_PIX_FMT_SBGGR8,
259 .priv = 8,
260 },
261 .set_pix_format = &pas202bcb_set_pix_format
262};
263
264
265int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
266{
267 int r0 = 0, r1 = 0, err = 0;
268 unsigned int pid = 0;
269
270 /*
271 * Minimal initialization to enable the I2C communication
272 * NOTE: do NOT change the values!
273 */
274 err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */
275 err += sn9c102_write_reg(cam, 0x40, 0x01); /* sensor power on */
276 err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */
277 if (err)
278 return -EIO;
279
280 r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
281 r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
282
283 if (r0 < 0 || r1 < 0)
284 return -EIO;
285
286 pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
287 if (pid != 0x017)
288 return -ENODEV;
289
290 sn9c102_attach_sensor(cam, &pas202bcb);
291
292 return 0;
293}
diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h
new file mode 100644
index 000000000000..2afd9e9d09bb
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_sensor.h
@@ -0,0 +1,389 @@
1/***************************************************************************
2 * API for image sensors connected to the SN9C10x PC Camera Controllers *
3 * *
4 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * *
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#ifndef _SN9C102_SENSOR_H_
22#define _SN9C102_SENSOR_H_
23
24#include <linux/usb.h>
25#include <linux/videodev.h>
26#include <linux/device.h>
27#include <linux/stddef.h>
28#include <linux/errno.h>
29#include <asm/types.h>
30
31struct sn9c102_device;
32struct sn9c102_sensor;
33
34/*****************************************************************************/
35
36/*
37 OVERVIEW.
38 This is a small interface that allows you to add support for any CCD/CMOS
39 image sensors connected to the SN9C10X bridges. The entire API is documented
40 below. In the most general case, to support a sensor there are three steps
41 you have to follow:
42 1) define the main "sn9c102_sensor" structure by setting the basic fields;
43 2) write a probing function to be called by the core module when the USB
44 camera is recognized, then add both the USB ids and the name of that
45 function to the two corresponding tables SENSOR_TABLE and ID_TABLE (see
46 below);
47 3) implement the methods that you want/need (and fill the rest of the main
48 structure accordingly).
49 "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do
50 NOT need to touch the source code of the core module for the things to work
51 properly, unless you find bugs or flaws in it. Finally, do not forget to
52 read the V4L2 API for completeness.
53*/
54
55/*****************************************************************************/
56
57/*
58 Probing functions: on success, you must attach the sensor to the camera
59 by calling sn9c102_attach_sensor() provided below.
60 To enable the I2C communication, you might need to perform a really basic
61 initialization of the SN9C10X chip by using the write function declared
62 ahead.
63 Functions must return 0 on success, the appropriate error otherwise.
64*/
65extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
66extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
67extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
68extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
69extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam);
70extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
71extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
72extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
73
74/*
75 Add the above entries to this table. Be sure to add the entry in the right
76 place, since, on failure, the next probing routine is called according to
77 the order of the list below, from top to bottom.
78*/
79#define SN9C102_SENSOR_TABLE \
80static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { \
81 &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ \
82 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \
83 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \
84 &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \
85 &sn9c102_probe_pas202bca, /* detection mostly based on USB pid/vid */ \
86 &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */ \
87 &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \
88 &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \
89 NULL, \
90};
91
92/* Device identification */
93extern struct sn9c102_device*
94sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id);
95
96/* Attach a probed sensor to the camera. */
97extern void
98sn9c102_attach_sensor(struct sn9c102_device* cam,
99 struct sn9c102_sensor* sensor);
100
101/*
102 Each SN9C10x camera has proper PID/VID identifiers.
103 SN9C103 supports multiple interfaces, but we only handle the video class
104 interface.
105*/
106#define SN9C102_USB_DEVICE(vend, prod, intclass) \
107 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
108 USB_DEVICE_ID_MATCH_INT_CLASS, \
109 .idVendor = (vend), \
110 .idProduct = (prod), \
111 .bInterfaceClass = (intclass)
112
113#define SN9C102_ID_TABLE \
114static const struct usb_device_id sn9c102_id_table[] = { \
115 { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \
116 { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */ \
117 { USB_DEVICE(0x0c45, 0x6007), }, \
118 { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */ \
119 { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */ \
120 { USB_DEVICE(0x0c45, 0x6024), }, \
121 { USB_DEVICE(0x0c45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */ \
122 { USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */ \
123 { USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */ \
124 { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131D */ \
125 { USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \
126 { USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */ \
127 { USB_DEVICE(0x0c45, 0x602d), }, \
128 { USB_DEVICE(0x0c45, 0x602e), }, /* OV7630 */ \
129 { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \
130 { SN9C102_USB_DEVICE(0x0c45, 0x6080, 0xff), }, \
131 { SN9C102_USB_DEVICE(0x0c45, 0x6082, 0xff), }, /* MI0343 & MI0360 */ \
132 { SN9C102_USB_DEVICE(0x0c45, 0x6083, 0xff), }, /* HV7131[D|E1] */ \
133 { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \
134 { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \
135 { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \
136 { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131/R */ \
137 { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \
138 { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \
139 { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \
140 { SN9C102_USB_DEVICE(0x0c45, 0x60a2, 0xff), }, \
141 { SN9C102_USB_DEVICE(0x0c45, 0x60a3, 0xff), }, \
142 { SN9C102_USB_DEVICE(0x0c45, 0x60a8, 0xff), }, /* PAS106B */ \
143 { SN9C102_USB_DEVICE(0x0c45, 0x60aa, 0xff), }, /* TAS5130D1B */ \
144 { SN9C102_USB_DEVICE(0x0c45, 0x60ab, 0xff), }, /* TAS5110C1B */ \
145 { SN9C102_USB_DEVICE(0x0c45, 0x60ac, 0xff), }, \
146 { SN9C102_USB_DEVICE(0x0c45, 0x60ae, 0xff), }, \
147 { SN9C102_USB_DEVICE(0x0c45, 0x60af, 0xff), }, /* PAS202BCB */ \
148 { SN9C102_USB_DEVICE(0x0c45, 0x60b0, 0xff), }, /* OV7630 (?) */ \
149 { SN9C102_USB_DEVICE(0x0c45, 0x60b2, 0xff), }, \
150 { SN9C102_USB_DEVICE(0x0c45, 0x60b3, 0xff), }, \
151 { SN9C102_USB_DEVICE(0x0c45, 0x60b8, 0xff), }, \
152 { SN9C102_USB_DEVICE(0x0c45, 0x60ba, 0xff), }, \
153 { SN9C102_USB_DEVICE(0x0c45, 0x60bb, 0xff), }, \
154 { SN9C102_USB_DEVICE(0x0c45, 0x60bc, 0xff), }, \
155 { SN9C102_USB_DEVICE(0x0c45, 0x60be, 0xff), }, \
156 { } \
157};
158
159/*****************************************************************************/
160
161/*
162 Read/write routines: they always return -1 on error, 0 or the read value
163 otherwise. NOTE that a real read operation is not supported by the SN9C10X
164 chip for some of its registers. To work around this problem, a pseudo-read
165 call is provided instead: it returns the last successfully written value
166 on the register (0 if it has never been written), the usual -1 on error.
167*/
168
169/* The "try" I2C I/O versions are used when probing the sensor */
170extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
171 u8 address, u8 value);
172extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
173 u8 address);
174
175/*
176 These must be used if and only if the sensor doesn't implement the standard
177 I2C protocol. There are a number of good reasons why you must use the
178 single-byte versions of these functions: do not abuse. The first function
179 writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C10X
180 chip. The second one programs the registers 0x09 and 0x10 with data0 and
181 data1, and places the n bytes read from the sensor register table in the
182 buffer pointed by 'buffer'. Both the functions return -1 on error; the write
183 version returns 0 on success, while the read version returns the first read
184 byte.
185*/
186extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
187 struct sn9c102_sensor* sensor, u8 n,
188 u8 data0, u8 data1, u8 data2, u8 data3,
189 u8 data4, u8 data5);
190extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
191 struct sn9c102_sensor* sensor, u8 data0,
192 u8 data1, u8 n, u8 buffer[]);
193
194/* To be used after the sensor struct has been attached to the camera struct */
195extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value);
196extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
197
198/* I/O on registers in the bridge. Could be used by the sensor methods too */
199extern int sn9c102_write_regs(struct sn9c102_device*, u8* buff, u16 index);
200extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
201extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
202
203/*
204 NOTE: there are no exported debugging functions. To uniform the output you
205 must use the dev_info()/dev_warn()/dev_err() macros defined in device.h,
206 already included here, the argument being the struct device '&usbdev->dev'
207 of the sensor structure. Do NOT use these macros before the sensor is
208 attached or the kernel will crash! However, you should not need to notify
209 the user about common errors or other messages, since this is done by the
210 master module.
211*/
212
213/*****************************************************************************/
214
215enum sn9c102_i2c_sysfs_ops {
216 SN9C102_I2C_READ = 0x01,
217 SN9C102_I2C_WRITE = 0x02,
218};
219
220enum sn9c102_i2c_frequency { /* sensors may support both the frequencies */
221 SN9C102_I2C_100KHZ = 0x01,
222 SN9C102_I2C_400KHZ = 0x02,
223};
224
225enum sn9c102_i2c_interface {
226 SN9C102_I2C_2WIRES,
227 SN9C102_I2C_3WIRES,
228};
229
230#define SN9C102_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10
231
232struct sn9c102_sensor {
233 char name[32], /* sensor name */
234 maintainer[64]; /* name of the mantainer <email> */
235
236 /* Supported operations through the 'sysfs' interface */
237 enum sn9c102_i2c_sysfs_ops sysfs_ops;
238
239 /*
240 These sensor capabilities must be provided if the SN9C10X controller
241 needs to communicate through the sensor serial interface by using
242 at least one of the i2c functions available.
243 */
244 enum sn9c102_i2c_frequency frequency;
245 enum sn9c102_i2c_interface interface;
246
247 /*
248 This identifier must be provided if the image sensor implements
249 the standard I2C protocol.
250 */
251 u8 i2c_slave_id; /* reg. 0x09 */
252
253 /*
254 NOTE: Where not noted,most of the functions below are not mandatory.
255 Set to null if you do not implement them. If implemented,
256 they must return 0 on success, the proper error otherwise.
257 */
258
259 int (*init)(struct sn9c102_device* cam);
260 /*
261 This function will be called after the sensor has been attached.
262 It should be used to initialize the sensor only, but may also
263 configure part of the SN9C10X chip if necessary. You don't need to
264 setup picture settings like brightness, contrast, etc.. here, if
265 the corrisponding controls are implemented (see below), since
266 they are adjusted in the core driver by calling the set_ctrl()
267 method after init(), where the arguments are the default values
268 specified in the v4l2_queryctrl list of supported controls;
269 Same suggestions apply for other settings, _if_ the corresponding
270 methods are present; if not, the initialization must configure the
271 sensor according to the default configuration structures below.
272 */
273
274 struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS];
275 /*
276 Optional list of default controls, defined as indicated in the
277 V4L2 API. Menu type controls are not handled by this interface.
278 */
279
280 int (*get_ctrl)(struct sn9c102_device* cam, struct v4l2_control* ctrl);
281 int (*set_ctrl)(struct sn9c102_device* cam,
282 const struct v4l2_control* ctrl);
283 /*
284 You must implement at least the set_ctrl method if you have defined
285 the list above. The returned value must follow the V4L2
286 specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER
287 are not supported by this driver, so do not implement them. Also,
288 you don't have to check whether the passed values are out of bounds,
289 given that this is done by the core module.
290 */
291
292 struct v4l2_cropcap cropcap;
293 /*
294 Think the image sensor as a grid of R,G,B monochromatic pixels
295 disposed according to a particular Bayer pattern, which describes
296 the complete array of pixels, from (0,0) to (xmax, ymax). We will
297 use this coordinate system from now on. It is assumed the sensor
298 chip can be programmed to capture/transmit a subsection of that
299 array of pixels: we will call this subsection "active window".
300 It is not always true that the largest achievable active window can
301 cover the whole array of pixels. The V4L2 API defines another
302 area called "source rectangle", which, in turn, is a subrectangle of
303 the active window. The SN9C10X chip is always programmed to read the
304 source rectangle.
305 The bounds of both the active window and the source rectangle are
306 specified in the cropcap substructures 'bounds' and 'defrect'.
307 By default, the source rectangle should cover the largest possible
308 area. Again, it is not always true that the largest source rectangle
309 can cover the entire active window, although it is a rare case for
310 the hardware we have. The bounds of the source rectangle _must_ be
311 multiple of 16 and must use the same coordinate system as indicated
312 before; their centers shall align initially.
313 If necessary, the sensor chip must be initialized during init() to
314 set the bounds of the active sensor window; however, by default, it
315 usually covers the largest achievable area (maxwidth x maxheight)
316 of pixels, so no particular initialization is needed, if you have
317 defined the correct default bounds in the structures.
318 See the V4L2 API for further details.
319 NOTE: once you have defined the bounds of the active window
320 (struct cropcap.bounds) you must not change them.anymore.
321 Only 'bounds' and 'defrect' fields are mandatory, other fields
322 will be ignored.
323 */
324
325 int (*set_crop)(struct sn9c102_device* cam,
326 const struct v4l2_rect* rect);
327 /*
328 To be called on VIDIOC_C_SETCROP. The core module always calls a
329 default routine which configures the appropriate SN9C10X regs (also
330 scaling), but you may need to override/adjust specific stuff.
331 'rect' contains width and height values that are multiple of 16: in
332 case you override the default function, you always have to program
333 the chip to match those values; on error return the corresponding
334 error code without rolling back.
335 NOTE: in case, you must program the SN9C10X chip to get rid of
336 blank pixels or blank lines at the _start_ of each line or
337 frame after each HSYNC or VSYNC, so that the image starts with
338 real RGB data (see regs 0x12, 0x13) (having set H_SIZE and,
339 V_SIZE you don't have to care about blank pixels or blank
340 lines at the end of each line or frame).
341 */
342
343 struct v4l2_pix_format pix_format;
344 /*
345 What you have to define here are: 1) initial 'width' and 'height' of
346 the target rectangle 2) the initial 'pixelformat', which can be
347 either V4L2_PIX_FMT_SN9C10X (for compressed video) or
348 V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate the
349 number of bits per pixel for uncompressed video, 8 or 9 (despite the
350 current value of 'pixelformat').
351 NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4
352 of cropcap.defrect.width and cropcap.defrect.height. I
353 suggest 1/1.
354 NOTE 2: The initial compression quality is defined by the first bit
355 of reg 0x17 during the initialization of the image sensor.
356 NOTE 3: as said above, you have to program the SN9C10X chip to get
357 rid of any blank pixels, so that the output of the sensor
358 matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
359 */
360
361 int (*set_pix_format)(struct sn9c102_device* cam,
362 const struct v4l2_pix_format* pix);
363 /*
364 To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to
365 SN9C10X pixel format or viceversa. On error return the corresponding
366 error code without rolling back.
367 */
368
369 /*
370 Do NOT write to the data below, it's READ ONLY. It is used by the
371 core module to store successfully updated values of the above
372 settings, for rollbacks..etc..in case of errors during atomic I/O
373 */
374 struct v4l2_queryctrl _qctrl[SN9C102_MAX_CTRLS];
375 struct v4l2_rect _rect;
376};
377
378/*****************************************************************************/
379
380/* Private ioctl's for control settings supported by some image sensors */
381#define SN9C102_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE
382#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1
383#define SN9C102_V4L2_CID_RESET_LEVEL V4L2_CID_PRIVATE_BASE + 2
384#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE V4L2_CID_PRIVATE_BASE + 3
385#define SN9C102_V4L2_CID_GAMMA V4L2_CID_PRIVATE_BASE + 4
386#define SN9C102_V4L2_CID_BAND_FILTER V4L2_CID_PRIVATE_BASE + 5
387#define SN9C102_V4L2_CID_BRIGHT_LEVEL V4L2_CID_PRIVATE_BASE + 6
388
389#endif /* _SN9C102_SENSOR_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
new file mode 100644
index 000000000000..2e08c552f40a
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
@@ -0,0 +1,159 @@
1/***************************************************************************
2 * Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
20 ***************************************************************************/
21
22#include "sn9c102_sensor.h"
23
24
25static struct sn9c102_sensor tas5110c1b;
26
27
28static int tas5110c1b_init(struct sn9c102_device* cam)
29{
30 int err = 0;
31
32 err += sn9c102_write_reg(cam, 0x01, 0x01);
33 err += sn9c102_write_reg(cam, 0x44, 0x01);
34 err += sn9c102_write_reg(cam, 0x00, 0x10);
35 err += sn9c102_write_reg(cam, 0x00, 0x11);
36 err += sn9c102_write_reg(cam, 0x0a, 0x14);
37 err += sn9c102_write_reg(cam, 0x60, 0x17);
38 err += sn9c102_write_reg(cam, 0x06, 0x18);
39 err += sn9c102_write_reg(cam, 0xfb, 0x19);
40
41 err += sn9c102_i2c_write(cam, 0xc0, 0x80);
42
43 return err;
44}
45
46
47static int tas5110c1b_set_ctrl(struct sn9c102_device* cam,
48 const struct v4l2_control* ctrl)
49{
50 int err = 0;
51
52 switch (ctrl->id) {
53 case V4L2_CID_GAIN:
54 err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
55 break;
56 default:
57 return -EINVAL;
58 }
59
60 return err ? -EIO : 0;
61}
62
63
64static int tas5110c1b_set_crop(struct sn9c102_device* cam,
65 const struct v4l2_rect* rect)
66{
67 struct sn9c102_sensor* s = &tas5110c1b;
68 int err = 0;
69 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
70 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
71
72 err += sn9c102_write_reg(cam, h_start, 0x12);
73 err += sn9c102_write_reg(cam, v_start, 0x13);
74
75 /* Don't change ! */
76 err += sn9c102_write_reg(cam, 0x14, 0x1a);
77 err += sn9c102_write_reg(cam, 0x0a, 0x1b);
78 err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
79
80 return err;
81}
82
83
84static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
85 const struct v4l2_pix_format* pix)
86{
87 int err = 0;
88
89 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
90 err += sn9c102_write_reg(cam, 0x2b, 0x19);
91 else
92 err += sn9c102_write_reg(cam, 0xfb, 0x19);
93
94 return err;
95}
96
97
98static struct sn9c102_sensor tas5110c1b = {
99 .name = "TAS5110C1B",
100 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
101 .sysfs_ops = SN9C102_I2C_WRITE,
102 .frequency = SN9C102_I2C_100KHZ,
103 .interface = SN9C102_I2C_3WIRES,
104 .init = &tas5110c1b_init,
105 .qctrl = {
106 {
107 .id = V4L2_CID_GAIN,
108 .type = V4L2_CTRL_TYPE_INTEGER,
109 .name = "global gain",
110 .minimum = 0x00,
111 .maximum = 0xf6,
112 .step = 0x01,
113 .default_value = 0x40,
114 .flags = 0,
115 },
116 },
117 .set_ctrl = &tas5110c1b_set_ctrl,
118 .cropcap = {
119 .bounds = {
120 .left = 0,
121 .top = 0,
122 .width = 352,
123 .height = 288,
124 },
125 .defrect = {
126 .left = 0,
127 .top = 0,
128 .width = 352,
129 .height = 288,
130 },
131 },
132 .set_crop = &tas5110c1b_set_crop,
133 .pix_format = {
134 .width = 352,
135 .height = 288,
136 .pixelformat = V4L2_PIX_FMT_SBGGR8,
137 .priv = 8,
138 },
139 .set_pix_format = &tas5110c1b_set_pix_format
140};
141
142
143int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
144{
145 const struct usb_device_id tas5110c1b_id_table[] = {
146 { USB_DEVICE(0x0c45, 0x6001), },
147 { USB_DEVICE(0x0c45, 0x6005), },
148 { USB_DEVICE(0x0c45, 0x60ab), },
149 { }
150 };
151
152 /* Sensor detection is based on USB pid/vid */
153 if (!sn9c102_match_id(cam, tas5110c1b_id_table))
154 return -ENODEV;
155
156 sn9c102_attach_sensor(cam, &tas5110c1b);
157
158 return 0;
159}
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
new file mode 100644
index 000000000000..c7b339740bbf
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
@@ -0,0 +1,169 @@
1/***************************************************************************
2 * Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
20 ***************************************************************************/
21
22#include "sn9c102_sensor.h"
23
24
25static struct sn9c102_sensor tas5130d1b;
26
27
28static int tas5130d1b_init(struct sn9c102_device* cam)
29{
30 int err = 0;
31
32 err += sn9c102_write_reg(cam, 0x01, 0x01);
33 err += sn9c102_write_reg(cam, 0x20, 0x17);
34 err += sn9c102_write_reg(cam, 0x04, 0x01);
35 err += sn9c102_write_reg(cam, 0x01, 0x10);
36 err += sn9c102_write_reg(cam, 0x00, 0x11);
37 err += sn9c102_write_reg(cam, 0x00, 0x14);
38 err += sn9c102_write_reg(cam, 0x60, 0x17);
39 err += sn9c102_write_reg(cam, 0x07, 0x18);
40
41 return err;
42}
43
44
45static int tas5130d1b_set_ctrl(struct sn9c102_device* cam,
46 const struct v4l2_control* ctrl)
47{
48 int err = 0;
49
50 switch (ctrl->id) {
51 case V4L2_CID_GAIN:
52 err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
53 break;
54 case V4L2_CID_EXPOSURE:
55 err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value);
56 break;
57 default:
58 return -EINVAL;
59 }
60
61 return err ? -EIO : 0;
62}
63
64
65static int tas5130d1b_set_crop(struct sn9c102_device* cam,
66 const struct v4l2_rect* rect)
67{
68 struct sn9c102_sensor* s = &tas5130d1b;
69 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
70 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12;
71 int err = 0;
72
73 err += sn9c102_write_reg(cam, h_start, 0x12);
74 err += sn9c102_write_reg(cam, v_start, 0x13);
75
76 /* Do NOT change! */
77 err += sn9c102_write_reg(cam, 0x1f, 0x1a);
78 err += sn9c102_write_reg(cam, 0x1a, 0x1b);
79 err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
80
81 return err;
82}
83
84
85static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
86 const struct v4l2_pix_format* pix)
87{
88 int err = 0;
89
90 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
91 err += sn9c102_write_reg(cam, 0x63, 0x19);
92 else
93 err += sn9c102_write_reg(cam, 0xf3, 0x19);
94
95 return err;
96}
97
98
99static struct sn9c102_sensor tas5130d1b = {
100 .name = "TAS5130D1B",
101 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
102 .sysfs_ops = SN9C102_I2C_WRITE,
103 .frequency = SN9C102_I2C_100KHZ,
104 .interface = SN9C102_I2C_3WIRES,
105 .init = &tas5130d1b_init,
106 .qctrl = {
107 {
108 .id = V4L2_CID_GAIN,
109 .type = V4L2_CTRL_TYPE_INTEGER,
110 .name = "global gain",
111 .minimum = 0x00,
112 .maximum = 0xf6,
113 .step = 0x02,
114 .default_value = 0x00,
115 .flags = 0,
116 },
117 {
118 .id = V4L2_CID_EXPOSURE,
119 .type = V4L2_CTRL_TYPE_INTEGER,
120 .name = "exposure",
121 .minimum = 0x00,
122 .maximum = 0x47,
123 .step = 0x01,
124 .default_value = 0x00,
125 .flags = 0,
126 },
127 },
128 .set_ctrl = &tas5130d1b_set_ctrl,
129 .cropcap = {
130 .bounds = {
131 .left = 0,
132 .top = 0,
133 .width = 640,
134 .height = 480,
135 },
136 .defrect = {
137 .left = 0,
138 .top = 0,
139 .width = 640,
140 .height = 480,
141 },
142 },
143 .set_crop = &tas5130d1b_set_crop,
144 .pix_format = {
145 .width = 640,
146 .height = 480,
147 .pixelformat = V4L2_PIX_FMT_SBGGR8,
148 .priv = 8,
149 },
150 .set_pix_format = &tas5130d1b_set_pix_format
151};
152
153
154int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam)
155{
156 const struct usb_device_id tas5130d1b_id_table[] = {
157 { USB_DEVICE(0x0c45, 0x6025), },
158 { USB_DEVICE(0x0c45, 0x60aa), },
159 { }
160 };
161
162 /* Sensor detection is based on USB pid/vid */
163 if (!sn9c102_match_id(cam, tas5130d1b_id_table))
164 return -ENODEV;
165
166 sn9c102_attach_sensor(cam, &tas5130d1b);
167
168 return 0;
169}