aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorBrian Johnson <brijohn@gmail.com>2009-07-19 04:52:58 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-07-24 13:03:30 -0400
commit26e744b6b61066203fd57de0d3962353621e06f8 (patch)
treeb8f6941a2b37ee46594bd336ca100916ece8ac38 /drivers/media
parentaf1d9afa75082663ea9e2b67b9381d1af403f52b (diff)
V4L/DVB (12283): gspca - sn9c20x: New subdriver for sn9c201 and sn9c202 bridges.
Signed-off-by: Brian Johnson <brijohn@gmail.com> Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/gspca/Kconfig16
-rw-r--r--drivers/media/video/gspca/Makefile2
-rw-r--r--drivers/media/video/gspca/sn9c20x.c2433
3 files changed, 2451 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
index 578dc4ffc965..34f46f2bc040 100644
--- a/drivers/media/video/gspca/Kconfig
+++ b/drivers/media/video/gspca/Kconfig
@@ -102,6 +102,22 @@ config USB_GSPCA_PAC7311
102 To compile this driver as a module, choose M here: the 102 To compile this driver as a module, choose M here: the
103 module will be called gspca_pac7311. 103 module will be called gspca_pac7311.
104 104
105config USB_GSPCA_SN9C20X
106 tristate "SN9C20X USB Camera Driver"
107 depends on VIDEO_V4L2 && USB_GSPCA
108 help
109 Say Y here if you want support for cameras based on the
110 sn9c20x chips (SN9C201 and SN9C202).
111
112 To compile this driver as a module, choose M here: the
113 module will be called gspca_sn9c20x.
114
115config USB_GSPCA_SN9C20X_EVDEV
116 bool "Enable evdev support"
117 depends on USB_GSPCA_SN9C20X
118 ---help---
119 Say Y here in order to enable evdev support for sn9c20x webcam button.
120
105config USB_GSPCA_SONIXB 121config USB_GSPCA_SONIXB
106 tristate "SONIX Bayer USB Camera Driver" 122 tristate "SONIX Bayer USB Camera Driver"
107 depends on VIDEO_V4L2 && USB_GSPCA 123 depends on VIDEO_V4L2 && USB_GSPCA
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
index 8a6643e8eb96..f6d3b86e9ad5 100644
--- a/drivers/media/video/gspca/Makefile
+++ b/drivers/media/video/gspca/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o
8obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o 8obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o
9obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o 9obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o
10obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o 10obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o
11obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o
11obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o 12obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o
12obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o 13obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o
13obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o 14obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o
@@ -35,6 +36,7 @@ gspca_ov519-objs := ov519.o
35gspca_ov534-objs := ov534.o 36gspca_ov534-objs := ov534.o
36gspca_pac207-objs := pac207.o 37gspca_pac207-objs := pac207.o
37gspca_pac7311-objs := pac7311.o 38gspca_pac7311-objs := pac7311.o
39gspca_sn9c20x-objs := sn9c20x.o
38gspca_sonixb-objs := sonixb.o 40gspca_sonixb-objs := sonixb.o
39gspca_sonixj-objs := sonixj.o 41gspca_sonixj-objs := sonixj.o
40gspca_spca500-objs := spca500.o 42gspca_spca500-objs := spca500.o
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
new file mode 100644
index 000000000000..78ab26ceb90e
--- /dev/null
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -0,0 +1,2433 @@
1/*
2 * Sonix sn9c201 sn9c202 library
3 * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
4 * Copyright (C) 2009 Brian Johnson <brijohn@gmail.com>
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 * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "gspca.h"
22#include "jpeg.h"
23
24#include <media/v4l2-chip-ident.h>
25#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
26#include <linux/kthread.h>
27#include <linux/freezer.h>
28#include <linux/usb/input.h>
29#include <linux/input.h>
30#endif
31
32MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
33 "microdia project <microdia@googlegroups.com>");
34MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
35MODULE_LICENSE("GPL");
36
37#define MODULE_NAME "sn9c20x"
38
39#define MODE_RAW 0x10
40#define MODE_JPEG 0x20
41#define MODE_SXGA 0x80
42
43#define SENSOR_OV9650 0
44#define SENSOR_OV9655 1
45#define SENSOR_SOI968 2
46#define SENSOR_OV7660 3
47#define SENSOR_OV7670 4
48#define SENSOR_MT9V011 5
49#define SENSOR_MT9V111 6
50#define SENSOR_MT9V112 7
51#define SENSOR_MT9M001 8
52#define SENSOR_MT9M111 9
53#define SENSOR_HV7131R 10
54#define SENSOR_MT9VPRB 20
55
56/* specific webcam descriptor */
57struct sd {
58 struct gspca_dev gspca_dev;
59
60#define MIN_AVG_LUM 80
61#define MAX_AVG_LUM 130
62 atomic_t avg_lum;
63 u8 old_step;
64 u8 older_step;
65 u8 exposure_step;
66
67 u8 brightness;
68 u8 contrast;
69 u8 saturation;
70 s16 hue;
71 u8 gamma;
72 u8 red;
73 u8 blue;
74
75 u8 hflip;
76 u8 vflip;
77 u8 gain;
78 u16 exposure;
79 u8 auto_exposure;
80
81 u8 i2c_addr;
82 u8 sensor;
83 u8 hstart;
84 u8 vstart;
85
86 u8 *jpeg_hdr;
87 u8 quality;
88
89#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
90 struct input_dev *input_dev;
91 u8 input_gpio;
92 struct task_struct *input_task;
93#endif
94};
95
96static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val);
97static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val);
98static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val);
99static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val);
100static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val);
101static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val);
102static int sd_sethue(struct gspca_dev *gspca_dev, s32 val);
103static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val);
104static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val);
105static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val);
106static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val);
107static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val);
108static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val);
109static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val);
110static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val);
111static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val);
112static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val);
113static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val);
114static int sd_setgain(struct gspca_dev *gspca_dev, s32 val);
115static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val);
116static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val);
117static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val);
118static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val);
119static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val);
120
121static struct ctrl sd_ctrls[] = {
122 {
123#define BRIGHTNESS_IDX 0
124 {
125 .id = V4L2_CID_BRIGHTNESS,
126 .type = V4L2_CTRL_TYPE_INTEGER,
127 .name = "Brightness",
128 .minimum = 0,
129 .maximum = 0xff,
130 .step = 1,
131#define BRIGHTNESS_DEFAULT 0x7f
132 .default_value = BRIGHTNESS_DEFAULT,
133 },
134 .set = sd_setbrightness,
135 .get = sd_getbrightness,
136 },
137 {
138#define CONTRAST_IDX 1
139 {
140 .id = V4L2_CID_CONTRAST,
141 .type = V4L2_CTRL_TYPE_INTEGER,
142 .name = "Contrast",
143 .minimum = 0,
144 .maximum = 0xff,
145 .step = 1,
146#define CONTRAST_DEFAULT 0x7f
147 .default_value = CONTRAST_DEFAULT,
148 },
149 .set = sd_setcontrast,
150 .get = sd_getcontrast,
151 },
152 {
153#define SATURATION_IDX 2
154 {
155 .id = V4L2_CID_SATURATION,
156 .type = V4L2_CTRL_TYPE_INTEGER,
157 .name = "Saturation",
158 .minimum = 0,
159 .maximum = 0xff,
160 .step = 1,
161#define SATURATION_DEFAULT 0x7f
162 .default_value = SATURATION_DEFAULT,
163 },
164 .set = sd_setsaturation,
165 .get = sd_getsaturation,
166 },
167 {
168#define HUE_IDX 3
169 {
170 .id = V4L2_CID_HUE,
171 .type = V4L2_CTRL_TYPE_INTEGER,
172 .name = "Hue",
173 .minimum = -180,
174 .maximum = 180,
175 .step = 1,
176#define HUE_DEFAULT 0
177 .default_value = HUE_DEFAULT,
178 },
179 .set = sd_sethue,
180 .get = sd_gethue,
181 },
182 {
183#define GAMMA_IDX 4
184 {
185 .id = V4L2_CID_GAMMA,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "Gamma",
188 .minimum = 0,
189 .maximum = 0xff,
190 .step = 1,
191#define GAMMA_DEFAULT 0x10
192 .default_value = GAMMA_DEFAULT,
193 },
194 .set = sd_setgamma,
195 .get = sd_getgamma,
196 },
197 {
198#define BLUE_IDX 5
199 {
200 .id = V4L2_CID_BLUE_BALANCE,
201 .type = V4L2_CTRL_TYPE_INTEGER,
202 .name = "Blue Balance",
203 .minimum = 0,
204 .maximum = 0x7f,
205 .step = 1,
206#define BLUE_DEFAULT 0x28
207 .default_value = BLUE_DEFAULT,
208 },
209 .set = sd_setbluebalance,
210 .get = sd_getbluebalance,
211 },
212 {
213#define RED_IDX 6
214 {
215 .id = V4L2_CID_RED_BALANCE,
216 .type = V4L2_CTRL_TYPE_INTEGER,
217 .name = "Red Balance",
218 .minimum = 0,
219 .maximum = 0x7f,
220 .step = 1,
221#define RED_DEFAULT 0x28
222 .default_value = RED_DEFAULT,
223 },
224 .set = sd_setredbalance,
225 .get = sd_getredbalance,
226 },
227 {
228#define HFLIP_IDX 7
229 {
230 .id = V4L2_CID_HFLIP,
231 .type = V4L2_CTRL_TYPE_BOOLEAN,
232 .name = "Horizontal Flip",
233 .minimum = 0,
234 .maximum = 1,
235 .step = 1,
236#define HFLIP_DEFAULT 0
237 .default_value = HFLIP_DEFAULT,
238 },
239 .set = sd_sethflip,
240 .get = sd_gethflip,
241 },
242 {
243#define VFLIP_IDX 8
244 {
245 .id = V4L2_CID_VFLIP,
246 .type = V4L2_CTRL_TYPE_BOOLEAN,
247 .name = "Vertical Flip",
248 .minimum = 0,
249 .maximum = 1,
250 .step = 1,
251#define VFLIP_DEFAULT 0
252 .default_value = VFLIP_DEFAULT,
253 },
254 .set = sd_setvflip,
255 .get = sd_getvflip,
256 },
257 {
258#define EXPOSURE_IDX 9
259 {
260 .id = V4L2_CID_EXPOSURE,
261 .type = V4L2_CTRL_TYPE_INTEGER,
262 .name = "Exposure",
263 .minimum = 0,
264 .maximum = 0x1780,
265 .step = 1,
266#define EXPOSURE_DEFAULT 0x33
267 .default_value = EXPOSURE_DEFAULT,
268 },
269 .set = sd_setexposure,
270 .get = sd_getexposure,
271 },
272 {
273#define GAIN_IDX 10
274 {
275 .id = V4L2_CID_GAIN,
276 .type = V4L2_CTRL_TYPE_INTEGER,
277 .name = "Gain",
278 .minimum = 0,
279 .maximum = 28,
280 .step = 1,
281#define GAIN_DEFAULT 0x00
282 .default_value = GAIN_DEFAULT,
283 },
284 .set = sd_setgain,
285 .get = sd_getgain,
286 },
287 {
288#define AUTOGAIN_IDX 11
289 {
290 .id = V4L2_CID_AUTOGAIN,
291 .type = V4L2_CTRL_TYPE_BOOLEAN,
292 .name = "Auto Exposure",
293 .minimum = 0,
294 .maximum = 1,
295 .step = 1,
296#define AUTO_EXPOSURE_DEFAULT 1
297 .default_value = AUTO_EXPOSURE_DEFAULT,
298 },
299 .set = sd_setautoexposure,
300 .get = sd_getautoexposure,
301 },
302};
303
304static const struct v4l2_pix_format vga_mode[] = {
305 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
306 .bytesperline = 240,
307 .sizeimage = 240 * 120,
308 .colorspace = V4L2_COLORSPACE_JPEG,
309 .priv = 0 | MODE_JPEG},
310 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
311 .bytesperline = 160,
312 .sizeimage = 160 * 120,
313 .colorspace = V4L2_COLORSPACE_SRGB,
314 .priv = 0 | MODE_RAW},
315 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
316 .bytesperline = 240,
317 .sizeimage = 240 * 120,
318 .colorspace = V4L2_COLORSPACE_SRGB,
319 .priv = 0},
320 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
321 .bytesperline = 480,
322 .sizeimage = 480 * 240 ,
323 .colorspace = V4L2_COLORSPACE_JPEG,
324 .priv = 1 | MODE_JPEG},
325 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
326 .bytesperline = 320,
327 .sizeimage = 320 * 240 ,
328 .colorspace = V4L2_COLORSPACE_SRGB,
329 .priv = 1 | MODE_RAW},
330 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
331 .bytesperline = 480,
332 .sizeimage = 480 * 240 ,
333 .colorspace = V4L2_COLORSPACE_SRGB,
334 .priv = 1},
335 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
336 .bytesperline = 960,
337 .sizeimage = 960 * 480,
338 .colorspace = V4L2_COLORSPACE_JPEG,
339 .priv = 2 | MODE_JPEG},
340 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
341 .bytesperline = 640,
342 .sizeimage = 640 * 480,
343 .colorspace = V4L2_COLORSPACE_SRGB,
344 .priv = 2 | MODE_RAW},
345 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
346 .bytesperline = 960,
347 .sizeimage = 960 * 480,
348 .colorspace = V4L2_COLORSPACE_SRGB,
349 .priv = 2},
350};
351
352static const struct v4l2_pix_format sxga_mode[] = {
353 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
354 .bytesperline = 240,
355 .sizeimage = 240 * 120,
356 .colorspace = V4L2_COLORSPACE_JPEG,
357 .priv = 0 | MODE_JPEG},
358 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
359 .bytesperline = 160,
360 .sizeimage = 160 * 120,
361 .colorspace = V4L2_COLORSPACE_SRGB,
362 .priv = 0 | MODE_RAW},
363 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
364 .bytesperline = 240,
365 .sizeimage = 240 * 120,
366 .colorspace = V4L2_COLORSPACE_SRGB,
367 .priv = 0},
368 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
369 .bytesperline = 480,
370 .sizeimage = 480 * 240 ,
371 .colorspace = V4L2_COLORSPACE_JPEG,
372 .priv = 1 | MODE_JPEG},
373 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
374 .bytesperline = 320,
375 .sizeimage = 320 * 240 ,
376 .colorspace = V4L2_COLORSPACE_SRGB,
377 .priv = 1 | MODE_RAW},
378 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
379 .bytesperline = 480,
380 .sizeimage = 480 * 240 ,
381 .colorspace = V4L2_COLORSPACE_SRGB,
382 .priv = 1},
383 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
384 .bytesperline = 960,
385 .sizeimage = 960 * 480,
386 .colorspace = V4L2_COLORSPACE_JPEG,
387 .priv = 2 | MODE_JPEG},
388 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
389 .bytesperline = 640,
390 .sizeimage = 640 * 480,
391 .colorspace = V4L2_COLORSPACE_SRGB,
392 .priv = 2 | MODE_RAW},
393 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
394 .bytesperline = 960,
395 .sizeimage = 960 * 480,
396 .colorspace = V4L2_COLORSPACE_SRGB,
397 .priv = 2},
398 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
399 .bytesperline = 1280,
400 .sizeimage = (1280 * 1024) + 64,
401 .colorspace = V4L2_COLORSPACE_SRGB,
402 .priv = 3 | MODE_RAW | MODE_SXGA},
403};
404
405static const int hsv_red_x[] = {
406 41, 44, 46, 48, 50, 52, 54, 56,
407 58, 60, 62, 64, 66, 68, 70, 72,
408 74, 76, 78, 80, 81, 83, 85, 87,
409 88, 90, 92, 93, 95, 97, 98, 100,
410 101, 102, 104, 105, 107, 108, 109, 110,
411 112, 113, 114, 115, 116, 117, 118, 119,
412 120, 121, 122, 123, 123, 124, 125, 125,
413 126, 127, 127, 128, 128, 129, 129, 129,
414 130, 130, 130, 130, 131, 131, 131, 131,
415 131, 131, 131, 131, 130, 130, 130, 130,
416 129, 129, 129, 128, 128, 127, 127, 126,
417 125, 125, 124, 123, 122, 122, 121, 120,
418 119, 118, 117, 116, 115, 114, 112, 111,
419 110, 109, 107, 106, 105, 103, 102, 101,
420 99, 98, 96, 94, 93, 91, 90, 88,
421 86, 84, 83, 81, 79, 77, 75, 74,
422 72, 70, 68, 66, 64, 62, 60, 58,
423 56, 54, 52, 49, 47, 45, 43, 41,
424 39, 36, 34, 32, 30, 28, 25, 23,
425 21, 19, 16, 14, 12, 9, 7, 5,
426 3, 0, -1, -3, -6, -8, -10, -12,
427 -15, -17, -19, -22, -24, -26, -28, -30,
428 -33, -35, -37, -39, -41, -44, -46, -48,
429 -50, -52, -54, -56, -58, -60, -62, -64,
430 -66, -68, -70, -72, -74, -76, -78, -80,
431 -81, -83, -85, -87, -88, -90, -92, -93,
432 -95, -97, -98, -100, -101, -102, -104, -105,
433 -107, -108, -109, -110, -112, -113, -114, -115,
434 -116, -117, -118, -119, -120, -121, -122, -123,
435 -123, -124, -125, -125, -126, -127, -127, -128,
436 -128, -128, -128, -128, -128, -128, -128, -128,
437 -128, -128, -128, -128, -128, -128, -128, -128,
438 -128, -128, -128, -128, -128, -128, -128, -128,
439 -128, -127, -127, -126, -125, -125, -124, -123,
440 -122, -122, -121, -120, -119, -118, -117, -116,
441 -115, -114, -112, -111, -110, -109, -107, -106,
442 -105, -103, -102, -101, -99, -98, -96, -94,
443 -93, -91, -90, -88, -86, -84, -83, -81,
444 -79, -77, -75, -74, -72, -70, -68, -66,
445 -64, -62, -60, -58, -56, -54, -52, -49,
446 -47, -45, -43, -41, -39, -36, -34, -32,
447 -30, -28, -25, -23, -21, -19, -16, -14,
448 -12, -9, -7, -5, -3, 0, 1, 3,
449 6, 8, 10, 12, 15, 17, 19, 22,
450 24, 26, 28, 30, 33, 35, 37, 39, 41
451};
452
453static const int hsv_red_y[] = {
454 82, 80, 78, 76, 74, 73, 71, 69,
455 67, 65, 63, 61, 58, 56, 54, 52,
456 50, 48, 46, 44, 41, 39, 37, 35,
457 32, 30, 28, 26, 23, 21, 19, 16,
458 14, 12, 10, 7, 5, 3, 0, -1,
459 -3, -6, -8, -10, -13, -15, -17, -19,
460 -22, -24, -26, -29, -31, -33, -35, -38,
461 -40, -42, -44, -46, -48, -51, -53, -55,
462 -57, -59, -61, -63, -65, -67, -69, -71,
463 -73, -75, -77, -79, -81, -82, -84, -86,
464 -88, -89, -91, -93, -94, -96, -98, -99,
465 -101, -102, -104, -105, -106, -108, -109, -110,
466 -112, -113, -114, -115, -116, -117, -119, -120,
467 -120, -121, -122, -123, -124, -125, -126, -126,
468 -127, -128, -128, -128, -128, -128, -128, -128,
469 -128, -128, -128, -128, -128, -128, -128, -128,
470 -128, -128, -128, -128, -128, -128, -128, -128,
471 -128, -128, -128, -128, -128, -128, -128, -128,
472 -127, -127, -126, -125, -125, -124, -123, -122,
473 -121, -120, -119, -118, -117, -116, -115, -114,
474 -113, -111, -110, -109, -107, -106, -105, -103,
475 -102, -100, -99, -97, -96, -94, -92, -91,
476 -89, -87, -85, -84, -82, -80, -78, -76,
477 -74, -73, -71, -69, -67, -65, -63, -61,
478 -58, -56, -54, -52, -50, -48, -46, -44,
479 -41, -39, -37, -35, -32, -30, -28, -26,
480 -23, -21, -19, -16, -14, -12, -10, -7,
481 -5, -3, 0, 1, 3, 6, 8, 10,
482 13, 15, 17, 19, 22, 24, 26, 29,
483 31, 33, 35, 38, 40, 42, 44, 46,
484 48, 51, 53, 55, 57, 59, 61, 63,
485 65, 67, 69, 71, 73, 75, 77, 79,
486 81, 82, 84, 86, 88, 89, 91, 93,
487 94, 96, 98, 99, 101, 102, 104, 105,
488 106, 108, 109, 110, 112, 113, 114, 115,
489 116, 117, 119, 120, 120, 121, 122, 123,
490 124, 125, 126, 126, 127, 128, 128, 129,
491 129, 130, 130, 131, 131, 131, 131, 132,
492 132, 132, 132, 132, 132, 132, 132, 132,
493 132, 132, 132, 131, 131, 131, 130, 130,
494 130, 129, 129, 128, 127, 127, 126, 125,
495 125, 124, 123, 122, 121, 120, 119, 118,
496 117, 116, 115, 114, 113, 111, 110, 109,
497 107, 106, 105, 103, 102, 100, 99, 97,
498 96, 94, 92, 91, 89, 87, 85, 84, 82
499};
500
501static const int hsv_green_x[] = {
502 -124, -124, -125, -125, -125, -125, -125, -125,
503 -125, -126, -126, -125, -125, -125, -125, -125,
504 -125, -124, -124, -124, -123, -123, -122, -122,
505 -121, -121, -120, -120, -119, -118, -117, -117,
506 -116, -115, -114, -113, -112, -111, -110, -109,
507 -108, -107, -105, -104, -103, -102, -100, -99,
508 -98, -96, -95, -93, -92, -91, -89, -87,
509 -86, -84, -83, -81, -79, -77, -76, -74,
510 -72, -70, -69, -67, -65, -63, -61, -59,
511 -57, -55, -53, -51, -49, -47, -45, -43,
512 -41, -39, -37, -35, -33, -30, -28, -26,
513 -24, -22, -20, -18, -15, -13, -11, -9,
514 -7, -4, -2, 0, 1, 3, 6, 8,
515 10, 12, 14, 17, 19, 21, 23, 25,
516 27, 29, 32, 34, 36, 38, 40, 42,
517 44, 46, 48, 50, 52, 54, 56, 58,
518 60, 62, 64, 66, 68, 70, 71, 73,
519 75, 77, 78, 80, 82, 83, 85, 87,
520 88, 90, 91, 93, 94, 96, 97, 98,
521 100, 101, 102, 104, 105, 106, 107, 108,
522 109, 111, 112, 113, 113, 114, 115, 116,
523 117, 118, 118, 119, 120, 120, 121, 122,
524 122, 123, 123, 124, 124, 124, 125, 125,
525 125, 125, 125, 125, 125, 126, 126, 125,
526 125, 125, 125, 125, 125, 124, 124, 124,
527 123, 123, 122, 122, 121, 121, 120, 120,
528 119, 118, 117, 117, 116, 115, 114, 113,
529 112, 111, 110, 109, 108, 107, 105, 104,
530 103, 102, 100, 99, 98, 96, 95, 93,
531 92, 91, 89, 87, 86, 84, 83, 81,
532 79, 77, 76, 74, 72, 70, 69, 67,
533 65, 63, 61, 59, 57, 55, 53, 51,
534 49, 47, 45, 43, 41, 39, 37, 35,
535 33, 30, 28, 26, 24, 22, 20, 18,
536 15, 13, 11, 9, 7, 4, 2, 0,
537 -1, -3, -6, -8, -10, -12, -14, -17,
538 -19, -21, -23, -25, -27, -29, -32, -34,
539 -36, -38, -40, -42, -44, -46, -48, -50,
540 -52, -54, -56, -58, -60, -62, -64, -66,
541 -68, -70, -71, -73, -75, -77, -78, -80,
542 -82, -83, -85, -87, -88, -90, -91, -93,
543 -94, -96, -97, -98, -100, -101, -102, -104,
544 -105, -106, -107, -108, -109, -111, -112, -113,
545 -113, -114, -115, -116, -117, -118, -118, -119,
546 -120, -120, -121, -122, -122, -123, -123, -124, -124
547};
548
549static const int hsv_green_y[] = {
550 -100, -99, -98, -97, -95, -94, -93, -91,
551 -90, -89, -87, -86, -84, -83, -81, -80,
552 -78, -76, -75, -73, -71, -70, -68, -66,
553 -64, -63, -61, -59, -57, -55, -53, -51,
554 -49, -48, -46, -44, -42, -40, -38, -36,
555 -34, -32, -30, -27, -25, -23, -21, -19,
556 -17, -15, -13, -11, -9, -7, -4, -2,
557 0, 1, 3, 5, 7, 9, 11, 14,
558 16, 18, 20, 22, 24, 26, 28, 30,
559 32, 34, 36, 38, 40, 42, 44, 46,
560 48, 50, 52, 54, 56, 58, 59, 61,
561 63, 65, 67, 68, 70, 72, 74, 75,
562 77, 78, 80, 82, 83, 85, 86, 88,
563 89, 90, 92, 93, 95, 96, 97, 98,
564 100, 101, 102, 103, 104, 105, 106, 107,
565 108, 109, 110, 111, 112, 112, 113, 114,
566 115, 115, 116, 116, 117, 117, 118, 118,
567 119, 119, 119, 120, 120, 120, 120, 120,
568 121, 121, 121, 121, 121, 121, 120, 120,
569 120, 120, 120, 119, 119, 119, 118, 118,
570 117, 117, 116, 116, 115, 114, 114, 113,
571 112, 111, 111, 110, 109, 108, 107, 106,
572 105, 104, 103, 102, 100, 99, 98, 97,
573 95, 94, 93, 91, 90, 89, 87, 86,
574 84, 83, 81, 80, 78, 76, 75, 73,
575 71, 70, 68, 66, 64, 63, 61, 59,
576 57, 55, 53, 51, 49, 48, 46, 44,
577 42, 40, 38, 36, 34, 32, 30, 27,
578 25, 23, 21, 19, 17, 15, 13, 11,
579 9, 7, 4, 2, 0, -1, -3, -5,
580 -7, -9, -11, -14, -16, -18, -20, -22,
581 -24, -26, -28, -30, -32, -34, -36, -38,
582 -40, -42, -44, -46, -48, -50, -52, -54,
583 -56, -58, -59, -61, -63, -65, -67, -68,
584 -70, -72, -74, -75, -77, -78, -80, -82,
585 -83, -85, -86, -88, -89, -90, -92, -93,
586 -95, -96, -97, -98, -100, -101, -102, -103,
587 -104, -105, -106, -107, -108, -109, -110, -111,
588 -112, -112, -113, -114, -115, -115, -116, -116,
589 -117, -117, -118, -118, -119, -119, -119, -120,
590 -120, -120, -120, -120, -121, -121, -121, -121,
591 -121, -121, -120, -120, -120, -120, -120, -119,
592 -119, -119, -118, -118, -117, -117, -116, -116,
593 -115, -114, -114, -113, -112, -111, -111, -110,
594 -109, -108, -107, -106, -105, -104, -103, -102, -100
595};
596
597static const int hsv_blue_x[] = {
598 112, 113, 114, 114, 115, 116, 117, 117,
599 118, 118, 119, 119, 120, 120, 120, 121,
600 121, 121, 122, 122, 122, 122, 122, 122,
601 122, 122, 122, 122, 122, 122, 121, 121,
602 121, 120, 120, 120, 119, 119, 118, 118,
603 117, 116, 116, 115, 114, 113, 113, 112,
604 111, 110, 109, 108, 107, 106, 105, 104,
605 103, 102, 100, 99, 98, 97, 95, 94,
606 93, 91, 90, 88, 87, 85, 84, 82,
607 80, 79, 77, 76, 74, 72, 70, 69,
608 67, 65, 63, 61, 60, 58, 56, 54,
609 52, 50, 48, 46, 44, 42, 40, 38,
610 36, 34, 32, 30, 28, 26, 24, 22,
611 19, 17, 15, 13, 11, 9, 7, 5,
612 2, 0, -1, -3, -5, -7, -9, -12,
613 -14, -16, -18, -20, -22, -24, -26, -28,
614 -31, -33, -35, -37, -39, -41, -43, -45,
615 -47, -49, -51, -53, -54, -56, -58, -60,
616 -62, -64, -66, -67, -69, -71, -73, -74,
617 -76, -78, -79, -81, -83, -84, -86, -87,
618 -89, -90, -92, -93, -94, -96, -97, -98,
619 -99, -101, -102, -103, -104, -105, -106, -107,
620 -108, -109, -110, -111, -112, -113, -114, -114,
621 -115, -116, -117, -117, -118, -118, -119, -119,
622 -120, -120, -120, -121, -121, -121, -122, -122,
623 -122, -122, -122, -122, -122, -122, -122, -122,
624 -122, -122, -121, -121, -121, -120, -120, -120,
625 -119, -119, -118, -118, -117, -116, -116, -115,
626 -114, -113, -113, -112, -111, -110, -109, -108,
627 -107, -106, -105, -104, -103, -102, -100, -99,
628 -98, -97, -95, -94, -93, -91, -90, -88,
629 -87, -85, -84, -82, -80, -79, -77, -76,
630 -74, -72, -70, -69, -67, -65, -63, -61,
631 -60, -58, -56, -54, -52, -50, -48, -46,
632 -44, -42, -40, -38, -36, -34, -32, -30,
633 -28, -26, -24, -22, -19, -17, -15, -13,
634 -11, -9, -7, -5, -2, 0, 1, 3,
635 5, 7, 9, 12, 14, 16, 18, 20,
636 22, 24, 26, 28, 31, 33, 35, 37,
637 39, 41, 43, 45, 47, 49, 51, 53,
638 54, 56, 58, 60, 62, 64, 66, 67,
639 69, 71, 73, 74, 76, 78, 79, 81,
640 83, 84, 86, 87, 89, 90, 92, 93,
641 94, 96, 97, 98, 99, 101, 102, 103,
642 104, 105, 106, 107, 108, 109, 110, 111, 112
643};
644
645static const int hsv_blue_y[] = {
646 -11, -13, -15, -17, -19, -21, -23, -25,
647 -27, -29, -31, -33, -35, -37, -39, -41,
648 -43, -45, -46, -48, -50, -52, -54, -55,
649 -57, -59, -61, -62, -64, -66, -67, -69,
650 -71, -72, -74, -75, -77, -78, -80, -81,
651 -83, -84, -86, -87, -88, -90, -91, -92,
652 -93, -95, -96, -97, -98, -99, -100, -101,
653 -102, -103, -104, -105, -106, -106, -107, -108,
654 -109, -109, -110, -111, -111, -112, -112, -113,
655 -113, -114, -114, -114, -115, -115, -115, -115,
656 -116, -116, -116, -116, -116, -116, -116, -116,
657 -116, -115, -115, -115, -115, -114, -114, -114,
658 -113, -113, -112, -112, -111, -111, -110, -110,
659 -109, -108, -108, -107, -106, -105, -104, -103,
660 -102, -101, -100, -99, -98, -97, -96, -95,
661 -94, -93, -91, -90, -89, -88, -86, -85,
662 -84, -82, -81, -79, -78, -76, -75, -73,
663 -71, -70, -68, -67, -65, -63, -62, -60,
664 -58, -56, -55, -53, -51, -49, -47, -45,
665 -44, -42, -40, -38, -36, -34, -32, -30,
666 -28, -26, -24, -22, -20, -18, -16, -14,
667 -12, -10, -8, -6, -4, -2, 0, 1,
668 3, 5, 7, 9, 11, 13, 15, 17,
669 19, 21, 23, 25, 27, 29, 31, 33,
670 35, 37, 39, 41, 43, 45, 46, 48,
671 50, 52, 54, 55, 57, 59, 61, 62,
672 64, 66, 67, 69, 71, 72, 74, 75,
673 77, 78, 80, 81, 83, 84, 86, 87,
674 88, 90, 91, 92, 93, 95, 96, 97,
675 98, 99, 100, 101, 102, 103, 104, 105,
676 106, 106, 107, 108, 109, 109, 110, 111,
677 111, 112, 112, 113, 113, 114, 114, 114,
678 115, 115, 115, 115, 116, 116, 116, 116,
679 116, 116, 116, 116, 116, 115, 115, 115,
680 115, 114, 114, 114, 113, 113, 112, 112,
681 111, 111, 110, 110, 109, 108, 108, 107,
682 106, 105, 104, 103, 102, 101, 100, 99,
683 98, 97, 96, 95, 94, 93, 91, 90,
684 89, 88, 86, 85, 84, 82, 81, 79,
685 78, 76, 75, 73, 71, 70, 68, 67,
686 65, 63, 62, 60, 58, 56, 55, 53,
687 51, 49, 47, 45, 44, 42, 40, 38,
688 36, 34, 32, 30, 28, 26, 24, 22,
689 20, 18, 16, 14, 12, 10, 8, 6,
690 4, 2, 0, -1, -3, -5, -7, -9, -11
691};
692
693static u16 i2c_ident[] = {
694 V4L2_IDENT_OV9650,
695 V4L2_IDENT_OV9655,
696 V4L2_IDENT_SOI968,
697 V4L2_IDENT_OV7660,
698 V4L2_IDENT_OV7670,
699 V4L2_IDENT_MT9V011,
700 V4L2_IDENT_MT9V111,
701 V4L2_IDENT_MT9V112,
702 V4L2_IDENT_MT9M001C12ST,
703 V4L2_IDENT_MT9M111,
704 V4L2_IDENT_HV7131R,
705};
706
707static u16 bridge_init[][2] = {
708 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
709 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
710 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
711 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
712 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
713 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
714 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
715 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
716 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
717 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
718 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
719 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
720 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
721 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
722 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
723 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
724 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
725 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
726 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80}
727};
728
729/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
730static u8 ov_gain[] = {
731 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
732 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
733 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
734 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
735 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
736 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
737 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
738 0x70 /* 8x */
739};
740
741/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
742static u16 micron1_gain[] = {
743 /* 1x 1.25x 1.5x 1.75x */
744 0x0020, 0x0028, 0x0030, 0x0038,
745 /* 2x 2.25x 2.5x 2.75x */
746 0x00a0, 0x00a4, 0x00a8, 0x00ac,
747 /* 3x 3.25x 3.5x 3.75x */
748 0x00b0, 0x00b4, 0x00b8, 0x00bc,
749 /* 4x 4.25x 4.5x 4.75x */
750 0x00c0, 0x00c4, 0x00c8, 0x00cc,
751 /* 5x 5.25x 5.5x 5.75x */
752 0x00d0, 0x00d4, 0x00d8, 0x00dc,
753 /* 6x 6.25x 6.5x 6.75x */
754 0x00e0, 0x00e4, 0x00e8, 0x00ec,
755 /* 7x 7.25x 7.5x 7.75x */
756 0x00f0, 0x00f4, 0x00f8, 0x00fc,
757 /* 8x */
758 0x01c0
759};
760
761/* mt9m001 sensor uses a different gain formula then other micron sensors */
762/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
763static u16 micron2_gain[] = {
764 /* 1x 1.25x 1.5x 1.75x */
765 0x0008, 0x000a, 0x000c, 0x000e,
766 /* 2x 2.25x 2.5x 2.75x */
767 0x0010, 0x0012, 0x0014, 0x0016,
768 /* 3x 3.25x 3.5x 3.75x */
769 0x0018, 0x001a, 0x001c, 0x001e,
770 /* 4x 4.25x 4.5x 4.75x */
771 0x0020, 0x0051, 0x0052, 0x0053,
772 /* 5x 5.25x 5.5x 5.75x */
773 0x0054, 0x0055, 0x0056, 0x0057,
774 /* 6x 6.25x 6.5x 6.75x */
775 0x0058, 0x0059, 0x005a, 0x005b,
776 /* 7x 7.25x 7.5x 7.75x */
777 0x005c, 0x005d, 0x005e, 0x005f,
778 /* 8x */
779 0x0060
780};
781
782/* Gain = .5 + bit[7:0] / 16 */
783static u8 hv7131r_gain[] = {
784 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
785 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
786 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
787 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
788 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
789 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
790 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
791 0x78 /* 8x */
792};
793
794static u8 soi968_init[][2] = {
795 {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
796 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
797 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
798 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
799 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
800 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
801 {0x13, 0x8a}, {0x12, 0x40}, {0x17, 0x13},
802 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
803 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
804 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
805 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
806};
807
808static u8 ov7660_init[][2] = {
809 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
810 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
811 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
812 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
813 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
814 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
815};
816
817static u8 ov7670_init[][2] = {
818 {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
819 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
820 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
821 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
822 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
823 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
824 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
825 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
826 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
827 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
828 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
829 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
830 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
831 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
832 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
833 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
834 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
835 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
836 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
837 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
838 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
839 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
840 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
841 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
842 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
843 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
844 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
845 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
846 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
847 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
848 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
849 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
850 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
851 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
852 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
853 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
854 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
855 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
856 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
857 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
858 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
859 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
860 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
861 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
862 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
863 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
864 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
865 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
866 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
867 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
868 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
869 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
870 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
871 {0x93, 0x00},
872};
873
874static u8 ov9650_init[][2] = {
875 {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
876 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
877 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
878 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
879 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
880 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
881 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
882 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
883 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
884 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
885 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
886 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
887 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
888 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
889 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
890 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
891 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
892 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
893 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
894 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
895 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
896 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
897 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
898 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
899 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
900 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
901 {0xaa, 0x92}, {0xab, 0x0a},
902};
903
904static u8 ov9655_init[][2] = {
905 {0x12, 0x80}, {0x12, 0x01}, {0x0d, 0x00}, {0x0e, 0x61},
906 {0x11, 0x80}, {0x13, 0xba}, {0x14, 0x2e}, {0x16, 0x24},
907 {0x1e, 0x04}, {0x1e, 0x04}, {0x1e, 0x04}, {0x27, 0x08},
908 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x32, 0xbf},
909 {0x34, 0x3d}, {0x35, 0x00}, {0x36, 0xf8}, {0x38, 0x12},
910 {0x39, 0x57}, {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c},
911 {0x3d, 0x19}, {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40},
912 {0x42, 0x80}, {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a},
913 {0x48, 0x3c}, {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc},
914 {0x4d, 0xdc}, {0x4e, 0xdc}, {0x69, 0x02}, {0x6c, 0x04},
915 {0x6f, 0x9e}, {0x70, 0x05}, {0x71, 0x78}, {0x77, 0x02},
916 {0x8a, 0x23}, {0x8c, 0x0d}, {0x90, 0x7e}, {0x91, 0x7c},
917 {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, {0xa6, 0x60},
918 {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, {0xab, 0x04},
919 {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, {0xaf, 0x80},
920 {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, {0xb6, 0xaf},
921 {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, {0xbe, 0x3b},
922 {0xbf, 0x3a}, {0xc0, 0xe2}, {0xc1, 0xc8}, {0xc2, 0x01},
923 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
924 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x12, 0x61},
925 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
926 {0x03, 0x12}, {0x17, 0x14}, {0x18, 0x00}, {0x19, 0x01},
927 {0x1a, 0x3d}, {0x32, 0xbf}, {0x11, 0x80}, {0x2a, 0x10},
928 {0x2b, 0x0a}, {0x92, 0x00}, {0x93, 0x00}, {0x1e, 0x04},
929 {0x1e, 0x04}, {0x10, 0x7c}, {0x04, 0x03}, {0xa1, 0x00},
930 {0x2d, 0x00}, {0x2e, 0x00}, {0x00, 0x00}, {0x01, 0x80},
931 {0x02, 0x80}, {0x12, 0x61}, {0x36, 0xfa}, {0x8c, 0x8d},
932 {0xc0, 0xaa}, {0x69, 0x0a}, {0x03, 0x12}, {0x17, 0x14},
933 {0x18, 0x00}, {0x19, 0x01}, {0x1a, 0x3d}, {0x32, 0xbf},
934 {0x11, 0x80}, {0x2a, 0x10}, {0x2b, 0x0a}, {0x92, 0x00},
935 {0x93, 0x00}, {0x04, 0x01}, {0x10, 0x1f}, {0xa1, 0x00},
936 {0x00, 0x0a}, {0xa1, 0x00}, {0x10, 0x5d}, {0x04, 0x03},
937 {0x00, 0x01}, {0xa1, 0x00}, {0x10, 0x7c}, {0x04, 0x03},
938 {0x00, 0x03}, {0x00, 0x0a}, {0x00, 0x10}, {0x00, 0x13},
939};
940
941static u16 mt9v112_init[][2] = {
942 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
943 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
944 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
945 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
946 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
947 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
948 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
949 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
950 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
951 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
952 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
953 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
954 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
955 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
956 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
957 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
958};
959
960static u16 mt9v111_init[][2] = {
961 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
962 {0x01, 0x0001}, {0x02, 0x0016}, {0x03, 0x01e1},
963 {0x04, 0x0281}, {0x05, 0x0004}, {0x07, 0x3002},
964 {0x21, 0x0000}, {0x25, 0x4024}, {0x26, 0xff03},
965 {0x27, 0xff10}, {0x2b, 0x7828}, {0x2c, 0xb43c},
966 {0x2d, 0xf0a0}, {0x2e, 0x0c64}, {0x2f, 0x0064},
967 {0x67, 0x4010}, {0x06, 0x301e}, {0x08, 0x0480},
968 {0x01, 0x0004}, {0x02, 0x0016}, {0x03, 0x01e6},
969 {0x04, 0x0286}, {0x05, 0x0004}, {0x06, 0x0000},
970 {0x07, 0x3002}, {0x08, 0x0008}, {0x0c, 0x0000},
971 {0x0d, 0x0000}, {0x0e, 0x0000}, {0x0f, 0x0000},
972 {0x10, 0x0000}, {0x11, 0x0000}, {0x12, 0x00b0},
973 {0x13, 0x007c}, {0x14, 0x0000}, {0x15, 0x0000},
974 {0x16, 0x0000}, {0x17, 0x0000}, {0x18, 0x0000},
975 {0x19, 0x0000}, {0x1a, 0x0000}, {0x1b, 0x0000},
976 {0x1c, 0x0000}, {0x1d, 0x0000}, {0x30, 0x0000},
977 {0x30, 0x0005}, {0x31, 0x0000}, {0x02, 0x0016},
978 {0x03, 0x01e1}, {0x04, 0x0281}, {0x05, 0x0004},
979 {0x06, 0x0000}, {0x07, 0x3002}, {0x06, 0x002d},
980 {0x05, 0x0004}, {0x09, 0x0064}, {0x2b, 0x00a0},
981 {0x2c, 0x00a0}, {0x2d, 0x00a0}, {0x2e, 0x00a0},
982 {0x02, 0x0016}, {0x03, 0x01e1}, {0x04, 0x0281},
983 {0x05, 0x0004}, {0x06, 0x002d}, {0x07, 0x3002},
984 {0x0e, 0x0008}, {0x06, 0x002d}, {0x05, 0x0004},
985};
986
987static u16 mt9v011_init[][2] = {
988 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
989 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
990 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
991 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
992 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
993 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
994 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
995 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
996 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
997 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
998 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
999 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1000 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1001 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1002 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1003 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1004 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1005 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1006 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1007 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1008 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1009 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1010 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1011 {0x06, 0x0029}, {0x05, 0x0009},
1012};
1013
1014static u16 mt9m001_init[][2] = {
1015 {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e},
1016 {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501},
1017 {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002},
1018 {0x0a, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000},
1019 {0x1e, 0x8000}, {0x5f, 0x8904}, {0x60, 0x0000},
1020 {0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000},
1021 {0x64, 0x0000}, {0x20, 0x111d}, {0x06, 0x00f2},
1022 {0x05, 0x0013}, {0x09, 0x10f2}, {0x07, 0x0003},
1023 {0x2b, 0x002a}, {0x2d, 0x002a}, {0x2c, 0x002a},
1024 {0x2e, 0x0029}, {0x07, 0x0002},
1025};
1026
1027static u16 mt9m111_init[][2] = {
1028 {0xf0, 0x0000}, {0x0d, 0x0008}, {0x0d, 0x0009},
1029 {0x0d, 0x0008}, {0xf0, 0x0001}, {0x3a, 0x4300},
1030 {0x9b, 0x4300}, {0xa1, 0x0280}, {0xa4, 0x0200},
1031 {0x06, 0x308e}, {0xf0, 0x0000},
1032};
1033
1034static u8 hv7131r_init[][2] = {
1035 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1036 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1037 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1038 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1039 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1040 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1041 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1042 {0x23, 0x09}, {0x01, 0x08},
1043};
1044
1045int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
1046{
1047 struct usb_device *dev = gspca_dev->dev;
1048 int result;
1049 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1050 0x00,
1051 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1052 reg,
1053 0x00,
1054 gspca_dev->usb_buf,
1055 length,
1056 500);
1057 if (unlikely(result < 0 || result != length)) {
1058 err("Read register failed 0x%02X", reg);
1059 return -EIO;
1060 }
1061 return 0;
1062}
1063
1064int reg_w(struct gspca_dev *gspca_dev, u16 reg, const u8 *buffer, int length)
1065{
1066 struct usb_device *dev = gspca_dev->dev;
1067 int result;
1068 memcpy(gspca_dev->usb_buf, buffer, length);
1069 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1070 0x08,
1071 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1072 reg,
1073 0x00,
1074 gspca_dev->usb_buf,
1075 length,
1076 500);
1077 if (unlikely(result < 0 || result != length)) {
1078 err("Write register failed index 0x%02X", reg);
1079 return -EIO;
1080 }
1081 return 0;
1082}
1083
1084int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
1085{
1086 u8 data[1] = {value};
1087 return reg_w(gspca_dev, reg, data, 1);
1088}
1089
1090int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
1091{
1092 int i;
1093 reg_w(gspca_dev, 0x10c0, buffer, 8);
1094 for (i = 0; i < 5; i++) {
1095 reg_r(gspca_dev, 0x10c0, 1);
1096 if (gspca_dev->usb_buf[0] & 0x04) {
1097 if (gspca_dev->usb_buf[0] & 0x08)
1098 return -1;
1099 return 0;
1100 }
1101 msleep(1);
1102 }
1103 return -1;
1104}
1105
1106int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
1107{
1108 struct sd *sd = (struct sd *) gspca_dev;
1109
1110 u8 row[8];
1111
1112 /*
1113 * from the point of view of the bridge, the length
1114 * includes the address
1115 */
1116 row[0] = 0x81 | (2 << 4);
1117 row[1] = sd->i2c_addr;
1118 row[2] = reg;
1119 row[3] = val;
1120 row[4] = 0x00;
1121 row[5] = 0x00;
1122 row[6] = 0x00;
1123 row[7] = 0x10;
1124
1125 return i2c_w(gspca_dev, row);
1126}
1127
1128int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
1129{
1130 struct sd *sd = (struct sd *) gspca_dev;
1131 u8 row[8];
1132
1133 /*
1134 * from the point of view of the bridge, the length
1135 * includes the address
1136 */
1137 row[0] = 0x81 | (3 << 4);
1138 row[1] = sd->i2c_addr;
1139 row[2] = reg;
1140 row[3] = (val >> 8) & 0xff;
1141 row[4] = val & 0xff;
1142 row[5] = 0x00;
1143 row[6] = 0x00;
1144 row[7] = 0x10;
1145
1146 return i2c_w(gspca_dev, row);
1147}
1148
1149int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
1150{
1151 struct sd *sd = (struct sd *) gspca_dev;
1152 u8 row[8];
1153
1154 row[0] = 0x81 | 0x10;
1155 row[1] = sd->i2c_addr;
1156 row[2] = reg;
1157 row[3] = 0;
1158 row[4] = 0;
1159 row[5] = 0;
1160 row[6] = 0;
1161 row[7] = 0x10;
1162 reg_w(gspca_dev, 0x10c0, row, 8);
1163 msleep(1);
1164 row[0] = 0x81 | (2 << 4) | 0x02;
1165 row[2] = 0;
1166 reg_w(gspca_dev, 0x10c0, row, 8);
1167 msleep(1);
1168 reg_r(gspca_dev, 0x10c2, 5);
1169 *val = gspca_dev->usb_buf[3];
1170 return 0;
1171}
1172
1173int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
1174{
1175 struct sd *sd = (struct sd *) gspca_dev;
1176 u8 row[8];
1177
1178 row[0] = 0x81 | 0x10;
1179 row[1] = sd->i2c_addr;
1180 row[2] = reg;
1181 row[3] = 0;
1182 row[4] = 0;
1183 row[5] = 0;
1184 row[6] = 0;
1185 row[7] = 0x10;
1186 reg_w(gspca_dev, 0x10c0, row, 8);
1187 msleep(1);
1188 row[0] = 0x81 | (3 << 4) | 0x02;
1189 row[2] = 0;
1190 reg_w(gspca_dev, 0x10c0, row, 8);
1191 msleep(1);
1192 reg_r(gspca_dev, 0x10c2, 5);
1193 *val = (gspca_dev->usb_buf[2] << 8) | gspca_dev->usb_buf[3];
1194 return 0;
1195}
1196
1197static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
1198{
1199 int i;
1200 struct sd *sd = (struct sd *) gspca_dev;
1201
1202 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
1203 if (i2c_w1(gspca_dev, ov9650_init[i][0],
1204 ov9650_init[i][1]) < 0) {
1205 err("OV9650 sensor initialization failed");
1206 return -ENODEV;
1207 }
1208 }
1209 sd->hstart = 1;
1210 sd->vstart = 7;
1211 return 0;
1212}
1213
1214static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
1215{
1216 int i;
1217 struct sd *sd = (struct sd *) gspca_dev;
1218
1219 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
1220 if (i2c_w1(gspca_dev, ov9655_init[i][0],
1221 ov9655_init[i][1]) < 0) {
1222 err("OV9655 sensor initialization failed");
1223 return -ENODEV;
1224 }
1225 }
1226 /* disable hflip and vflip */
1227 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1228 sd->hstart = 0;
1229 sd->vstart = 7;
1230 return 0;
1231}
1232
1233static int soi968_init_sensor(struct gspca_dev *gspca_dev)
1234{
1235 int i;
1236 struct sd *sd = (struct sd *) gspca_dev;
1237
1238 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
1239 if (i2c_w1(gspca_dev, soi968_init[i][0],
1240 soi968_init[i][1]) < 0) {
1241 err("SOI968 sensor initialization failed");
1242 return -ENODEV;
1243 }
1244 }
1245 /* disable hflip and vflip */
1246 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1247 sd->hstart = 60;
1248 sd->vstart = 11;
1249 return 0;
1250}
1251
1252static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
1253{
1254 int i;
1255 struct sd *sd = (struct sd *) gspca_dev;
1256
1257 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
1258 if (i2c_w1(gspca_dev, ov7660_init[i][0],
1259 ov7660_init[i][1]) < 0) {
1260 err("OV7660 sensor initialization failed");
1261 return -ENODEV;
1262 }
1263 }
1264 /* disable hflip and vflip */
1265 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1266 sd->hstart = 1;
1267 sd->vstart = 1;
1268 return 0;
1269}
1270
1271static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
1272{
1273 int i;
1274 struct sd *sd = (struct sd *) gspca_dev;
1275
1276 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
1277 if (i2c_w1(gspca_dev, ov7670_init[i][0],
1278 ov7670_init[i][1]) < 0) {
1279 err("OV7670 sensor initialization failed");
1280 return -ENODEV;
1281 }
1282 }
1283 /* disable hflip and vflip */
1284 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1285 sd->hstart = 0;
1286 sd->vstart = 1;
1287 return 0;
1288}
1289
1290static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
1291{
1292 struct sd *sd = (struct sd *) gspca_dev;
1293 int i;
1294 u16 value;
1295 int ret;
1296
1297 sd->i2c_addr = 0x5d;
1298 ret = i2c_r2(gspca_dev, 0xff, &value);
1299 if ((ret == 0) && (value == 0x8243)) {
1300 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
1301 if (i2c_w2(gspca_dev, mt9v011_init[i][0],
1302 mt9v011_init[i][1]) < 0) {
1303 err("MT9V011 sensor initialization failed");
1304 return -ENODEV;
1305 }
1306 }
1307 sd->hstart = 2;
1308 sd->vstart = 2;
1309 sd->sensor = SENSOR_MT9V011;
1310 info("MT9V011 sensor detected");
1311 return 0;
1312 }
1313
1314 sd->i2c_addr = 0x5c;
1315 i2c_w2(gspca_dev, 0x01, 0x0004);
1316 ret = i2c_r2(gspca_dev, 0xff, &value);
1317 if ((ret == 0) && (value == 0x823a)) {
1318 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
1319 if (i2c_w2(gspca_dev, mt9v111_init[i][0],
1320 mt9v111_init[i][1]) < 0) {
1321 err("MT9V111 sensor initialization failed");
1322 return -ENODEV;
1323 }
1324 }
1325 sd->hstart = 2;
1326 sd->vstart = 2;
1327 sd->sensor = SENSOR_MT9V111;
1328 info("MT9V111 sensor detected");
1329 return 0;
1330 }
1331
1332 sd->i2c_addr = 0x5d;
1333 ret = i2c_w2(gspca_dev, 0xf0, 0x0000);
1334 if (ret < 0) {
1335 sd->i2c_addr = 0x48;
1336 i2c_w2(gspca_dev, 0xf0, 0x0000);
1337 }
1338 ret = i2c_r2(gspca_dev, 0x00, &value);
1339 if ((ret == 0) && (value == 0x1229)) {
1340 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
1341 if (i2c_w2(gspca_dev, mt9v112_init[i][0],
1342 mt9v112_init[i][1]) < 0) {
1343 err("MT9V112 sensor initialization failed");
1344 return -ENODEV;
1345 }
1346 }
1347 sd->hstart = 6;
1348 sd->vstart = 2;
1349 sd->sensor = SENSOR_MT9V112;
1350 info("MT9V112 sensor detected");
1351 return 0;
1352 }
1353
1354 return -ENODEV;
1355}
1356
1357static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
1358{
1359 struct sd *sd = (struct sd *) gspca_dev;
1360 int i;
1361 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
1362 if (i2c_w2(gspca_dev, mt9m111_init[i][0],
1363 mt9m111_init[i][1]) < 0) {
1364 err("MT9M111 sensor initialization failed");
1365 return -ENODEV;
1366 }
1367 }
1368 sd->hstart = 0;
1369 sd->vstart = 2;
1370 return 0;
1371}
1372
1373static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1374{
1375 struct sd *sd = (struct sd *) gspca_dev;
1376 int i;
1377 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
1378 if (i2c_w2(gspca_dev, mt9m001_init[i][0],
1379 mt9m001_init[i][1]) < 0) {
1380 err("MT9M001 sensor initialization failed");
1381 return -ENODEV;
1382 }
1383 }
1384 /* disable hflip and vflip */
1385 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1386 sd->hstart = 2;
1387 sd->vstart = 2;
1388 return 0;
1389}
1390
1391static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
1392{
1393 int i;
1394 struct sd *sd = (struct sd *) gspca_dev;
1395
1396 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
1397 if (i2c_w1(gspca_dev, hv7131r_init[i][0],
1398 hv7131r_init[i][1]) < 0) {
1399 err("HV7131R Sensor initialization failed");
1400 return -ENODEV;
1401 }
1402 }
1403 sd->hstart = 0;
1404 sd->vstart = 1;
1405 return 0;
1406}
1407
1408#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
1409static int input_kthread(void *data)
1410{
1411 struct gspca_dev *gspca_dev = (struct gspca_dev *)data;
1412 struct sd *sd = (struct sd *) gspca_dev;
1413
1414 DECLARE_WAIT_QUEUE_HEAD(wait);
1415 set_freezable();
1416 for (;;) {
1417 if (kthread_should_stop())
1418 break;
1419
1420 if (reg_r(gspca_dev, 0x1005, 1) < 0)
1421 continue;
1422
1423 input_report_key(sd->input_dev,
1424 KEY_CAMERA,
1425 gspca_dev->usb_buf[0] & sd->input_gpio);
1426 input_sync(sd->input_dev);
1427
1428 wait_event_freezable_timeout(wait,
1429 kthread_should_stop(),
1430 msecs_to_jiffies(100));
1431 }
1432 return 0;
1433}
1434
1435
1436static int sn9c20x_input_init(struct gspca_dev *gspca_dev)
1437{
1438 struct sd *sd = (struct sd *) gspca_dev;
1439 if (sd->input_gpio == 0)
1440 return 0;
1441
1442 sd->input_dev = input_allocate_device();
1443 if (!sd->input_dev)
1444 return -ENOMEM;
1445
1446 sd->input_dev->name = "SN9C20X Webcam";
1447
1448 sd->input_dev->phys = kasprintf(GFP_KERNEL, "usb-%s-%s",
1449 gspca_dev->dev->bus->bus_name,
1450 gspca_dev->dev->devpath);
1451
1452 if (!sd->input_dev->phys)
1453 return -ENOMEM;
1454
1455 usb_to_input_id(gspca_dev->dev, &sd->input_dev->id);
1456 sd->input_dev->dev.parent = &gspca_dev->dev->dev;
1457
1458 set_bit(EV_KEY, sd->input_dev->evbit);
1459 set_bit(KEY_CAMERA, sd->input_dev->keybit);
1460
1461 if (input_register_device(sd->input_dev))
1462 return -EINVAL;
1463
1464 sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%d",
1465 gspca_dev->vdev.minor);
1466
1467 if (IS_ERR(sd->input_task))
1468 return -EINVAL;
1469
1470 return 0;
1471}
1472
1473static void sn9c20x_input_cleanup(struct gspca_dev *gspca_dev)
1474{
1475 struct sd *sd = (struct sd *) gspca_dev;
1476 if (sd->input_task != NULL && !IS_ERR(sd->input_task))
1477 kthread_stop(sd->input_task);
1478
1479 if (sd->input_dev != NULL) {
1480 input_unregister_device(sd->input_dev);
1481 kfree(sd->input_dev->phys);
1482 input_free_device(sd->input_dev);
1483 sd->input_dev = NULL;
1484 }
1485}
1486#endif
1487
1488static int set_cmatrix(struct gspca_dev *gspca_dev)
1489{
1490 struct sd *sd = (struct sd *) gspca_dev;
1491 s32 hue_coord, hue_index = 180 + sd->hue;
1492 u8 cmatrix[21];
1493 memset(cmatrix, 0, 21);
1494
1495 cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
1496 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1497 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
1498 cmatrix[18] = sd->brightness - 0x80;
1499
1500 hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
1501 cmatrix[6] = (unsigned char)(hue_coord & 0xff);
1502 cmatrix[7] = (unsigned char)((hue_coord >> 8) & 0x0f);
1503
1504 hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
1505 cmatrix[8] = (unsigned char)(hue_coord & 0xff);
1506 cmatrix[9] = (unsigned char)((hue_coord >> 8) & 0x0f);
1507
1508 hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
1509 cmatrix[10] = (unsigned char)(hue_coord & 0xff);
1510 cmatrix[11] = (unsigned char)((hue_coord >> 8) & 0x0f);
1511
1512 hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
1513 cmatrix[12] = (unsigned char)(hue_coord & 0xff);
1514 cmatrix[13] = (unsigned char)((hue_coord >> 8) & 0x0f);
1515
1516 hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
1517 cmatrix[14] = (unsigned char)(hue_coord & 0xff);
1518 cmatrix[15] = (unsigned char)((hue_coord >> 8) & 0x0f);
1519
1520 hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
1521 cmatrix[16] = (unsigned char)(hue_coord & 0xff);
1522 cmatrix[17] = (unsigned char)((hue_coord >> 8) & 0x0f);
1523
1524 return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
1525}
1526
1527static int set_gamma(struct gspca_dev *gspca_dev)
1528{
1529 struct sd *sd = (struct sd *) gspca_dev;
1530 u8 gamma[17];
1531 u8 gval = sd->gamma * 0xb8 / 0x100;
1532
1533
1534 gamma[0] = 0x0a;
1535 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1536 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1537 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1538 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1539 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1540 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1541 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1542 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1543 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1544 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1545 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1546 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1547 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1548 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1549 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1550 gamma[16] = 0xf5;
1551
1552 return reg_w(gspca_dev, 0x1190, gamma, 17);
1553}
1554
1555static int set_redblue(struct gspca_dev *gspca_dev)
1556{
1557 struct sd *sd = (struct sd *) gspca_dev;
1558 reg_w1(gspca_dev, 0x118c, sd->red);
1559 reg_w1(gspca_dev, 0x118f, sd->blue);
1560 return 0;
1561}
1562
1563static int set_hvflip(struct gspca_dev *gspca_dev)
1564{
1565 u8 value, tslb;
1566 u16 value2;
1567 struct sd *sd = (struct sd *) gspca_dev;
1568 switch (sd->sensor) {
1569 case SENSOR_OV9650:
1570 i2c_r1(gspca_dev, 0x1e, &value);
1571 value &= ~0x30;
1572 tslb = 0x01;
1573 if (sd->hflip)
1574 value |= 0x20;
1575 if (sd->vflip) {
1576 value |= 0x10;
1577 tslb = 0x49;
1578 }
1579 i2c_w1(gspca_dev, 0x1e, value);
1580 i2c_w1(gspca_dev, 0x3a, tslb);
1581 break;
1582 case SENSOR_MT9V111:
1583 case SENSOR_MT9V011:
1584 i2c_r2(gspca_dev, 0x20, &value2);
1585 value2 &= ~0xc0a0;
1586 if (sd->hflip)
1587 value2 |= 0x8080;
1588 if (sd->vflip)
1589 value2 |= 0x4020;
1590 i2c_w2(gspca_dev, 0x20, value2);
1591 break;
1592 case SENSOR_MT9M111:
1593 case SENSOR_MT9V112:
1594 i2c_r2(gspca_dev, 0x20, &value2);
1595 value2 &= ~0x0003;
1596 if (sd->hflip)
1597 value2 |= 0x0002;
1598 if (sd->vflip)
1599 value2 |= 0x0001;
1600 i2c_w2(gspca_dev, 0x20, value2);
1601 break;
1602 case SENSOR_HV7131R:
1603 i2c_r1(gspca_dev, 0x01, &value);
1604 value &= ~0x03;
1605 if (sd->vflip)
1606 value |= 0x01;
1607 if (sd->hflip)
1608 value |= 0x02;
1609 i2c_w1(gspca_dev, 0x01, value);
1610 break;
1611 }
1612 return 0;
1613}
1614
1615static int set_exposure(struct gspca_dev *gspca_dev)
1616{
1617 struct sd *sd = (struct sd *) gspca_dev;
1618 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
1619 switch (sd->sensor) {
1620 case SENSOR_OV7660:
1621 case SENSOR_OV7670:
1622 case SENSOR_SOI968:
1623 case SENSOR_OV9655:
1624 case SENSOR_OV9650:
1625 exp[0] |= (3 << 4);
1626 exp[2] = 0x2d;
1627 exp[3] = sd->exposure & 0xff;
1628 exp[4] = sd->exposure >> 8;
1629 break;
1630 case SENSOR_MT9M001:
1631 case SENSOR_MT9M111:
1632 case SENSOR_MT9V112:
1633 case SENSOR_MT9V111:
1634 case SENSOR_MT9V011:
1635 exp[0] |= (3 << 4);
1636 exp[2] = 0x09;
1637 exp[3] = sd->exposure >> 8;
1638 exp[4] = sd->exposure & 0xff;
1639 break;
1640 case SENSOR_HV7131R:
1641 exp[0] |= (4 << 4);
1642 exp[2] = 0x25;
1643 exp[3] = ((sd->exposure * 0xffffff) / 0xffff) >> 16;
1644 exp[4] = ((sd->exposure * 0xffffff) / 0xffff) >> 8;
1645 exp[5] = ((sd->exposure * 0xffffff) / 0xffff) & 0xff;
1646 break;
1647 }
1648 i2c_w(gspca_dev, exp);
1649 return 0;
1650}
1651
1652static int set_gain(struct gspca_dev *gspca_dev)
1653{
1654 struct sd *sd = (struct sd *) gspca_dev;
1655 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
1656 switch (sd->sensor) {
1657 case SENSOR_OV7660:
1658 case SENSOR_OV7670:
1659 case SENSOR_SOI968:
1660 case SENSOR_OV9655:
1661 case SENSOR_OV9650:
1662 gain[0] |= (2 << 4);
1663 gain[3] = ov_gain[sd->gain];
1664 break;
1665 case SENSOR_MT9V011:
1666 case SENSOR_MT9V111:
1667 gain[0] |= (3 << 4);
1668 gain[2] = 0x35;
1669 gain[3] = micron1_gain[sd->gain] >> 8;
1670 gain[4] = micron1_gain[sd->gain] & 0xff;
1671 break;
1672 case SENSOR_MT9V112:
1673 case SENSOR_MT9M111:
1674 gain[0] |= (3 << 4);
1675 gain[2] = 0x2f;
1676 gain[3] = micron1_gain[sd->gain] >> 8;
1677 gain[4] = micron1_gain[sd->gain] & 0xff;
1678 break;
1679 case SENSOR_MT9M001:
1680 gain[0] |= (3 << 4);
1681 gain[2] = 0x2f;
1682 gain[3] = micron2_gain[sd->gain] >> 8;
1683 gain[4] = micron2_gain[sd->gain] & 0xff;
1684 break;
1685 case SENSOR_HV7131R:
1686 gain[0] |= (2 << 4);
1687 gain[2] = 0x30;
1688 gain[3] = hv7131r_gain[sd->gain];
1689 break;
1690 }
1691 i2c_w(gspca_dev, gain);
1692 return 0;
1693}
1694
1695static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val)
1696{
1697 struct sd *sd = (struct sd *) gspca_dev;
1698
1699 sd->brightness = val;
1700 if (gspca_dev->streaming)
1701 return set_cmatrix(gspca_dev);
1702 return 0;
1703}
1704
1705static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val)
1706{
1707 struct sd *sd = (struct sd *) gspca_dev;
1708 *val = sd->brightness;
1709 return 0;
1710}
1711
1712
1713static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val)
1714{
1715 struct sd *sd = (struct sd *) gspca_dev;
1716
1717 sd->contrast = val;
1718 if (gspca_dev->streaming)
1719 return set_cmatrix(gspca_dev);
1720 return 0;
1721}
1722
1723static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val)
1724{
1725 struct sd *sd = (struct sd *) gspca_dev;
1726 *val = sd->contrast;
1727 return 0;
1728}
1729
1730static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val)
1731{
1732 struct sd *sd = (struct sd *) gspca_dev;
1733
1734 sd->saturation = val;
1735 if (gspca_dev->streaming)
1736 return set_cmatrix(gspca_dev);
1737 return 0;
1738}
1739
1740static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val)
1741{
1742 struct sd *sd = (struct sd *) gspca_dev;
1743 *val = sd->saturation;
1744 return 0;
1745}
1746
1747static int sd_sethue(struct gspca_dev *gspca_dev, s32 val)
1748{
1749 struct sd *sd = (struct sd *) gspca_dev;
1750
1751 sd->hue = val;
1752 if (gspca_dev->streaming)
1753 return set_cmatrix(gspca_dev);
1754 return 0;
1755}
1756
1757static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val)
1758{
1759 struct sd *sd = (struct sd *) gspca_dev;
1760 *val = sd->hue;
1761 return 0;
1762}
1763
1764static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val)
1765{
1766 struct sd *sd = (struct sd *) gspca_dev;
1767
1768 sd->gamma = val;
1769 if (gspca_dev->streaming)
1770 return set_gamma(gspca_dev);
1771 return 0;
1772}
1773
1774static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val)
1775{
1776 struct sd *sd = (struct sd *) gspca_dev;
1777 *val = sd->gamma;
1778 return 0;
1779}
1780
1781static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val)
1782{
1783 struct sd *sd = (struct sd *) gspca_dev;
1784
1785 sd->red = val;
1786 if (gspca_dev->streaming)
1787 return set_redblue(gspca_dev);
1788 return 0;
1789}
1790
1791static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val)
1792{
1793 struct sd *sd = (struct sd *) gspca_dev;
1794 *val = sd->red;
1795 return 0;
1796}
1797
1798static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val)
1799{
1800 struct sd *sd = (struct sd *) gspca_dev;
1801
1802 sd->blue = val;
1803 if (gspca_dev->streaming)
1804 return set_redblue(gspca_dev);
1805 return 0;
1806}
1807
1808static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val)
1809{
1810 struct sd *sd = (struct sd *) gspca_dev;
1811 *val = sd->blue;
1812 return 0;
1813}
1814
1815static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val)
1816{
1817 struct sd *sd = (struct sd *) gspca_dev;
1818
1819 sd->hflip = val;
1820 if (gspca_dev->streaming)
1821 return set_hvflip(gspca_dev);
1822 return 0;
1823}
1824
1825static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val)
1826{
1827 struct sd *sd = (struct sd *) gspca_dev;
1828 *val = sd->hflip;
1829 return 0;
1830}
1831
1832static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val)
1833{
1834 struct sd *sd = (struct sd *) gspca_dev;
1835
1836 sd->vflip = val;
1837 if (gspca_dev->streaming)
1838 return set_hvflip(gspca_dev);
1839 return 0;
1840}
1841
1842static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val)
1843{
1844 struct sd *sd = (struct sd *) gspca_dev;
1845 *val = sd->vflip;
1846 return 0;
1847}
1848
1849static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val)
1850{
1851 struct sd *sd = (struct sd *) gspca_dev;
1852
1853 sd->exposure = val;
1854 if (gspca_dev->streaming)
1855 return set_exposure(gspca_dev);
1856 return 0;
1857}
1858
1859static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val)
1860{
1861 struct sd *sd = (struct sd *) gspca_dev;
1862 *val = sd->exposure;
1863 return 0;
1864}
1865
1866static int sd_setgain(struct gspca_dev *gspca_dev, s32 val)
1867{
1868 struct sd *sd = (struct sd *) gspca_dev;
1869
1870 sd->gain = val;
1871 if (gspca_dev->streaming)
1872 return set_gain(gspca_dev);
1873 return 0;
1874}
1875
1876static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val)
1877{
1878 struct sd *sd = (struct sd *) gspca_dev;
1879 *val = sd->gain;
1880 return 0;
1881}
1882
1883static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val)
1884{
1885 struct sd *sd = (struct sd *) gspca_dev;
1886 sd->auto_exposure = val;
1887 return 0;
1888}
1889
1890static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val)
1891{
1892 struct sd *sd = (struct sd *) gspca_dev;
1893 *val = sd->auto_exposure;
1894 return 0;
1895}
1896
1897#ifdef CONFIG_VIDEO_ADV_DEBUG
1898static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1899 struct v4l2_dbg_register *reg)
1900{
1901 struct sd *sd = (struct sd *) gspca_dev;
1902 switch (reg->match.type) {
1903 case V4L2_CHIP_MATCH_HOST:
1904 if (reg->match.addr != 0)
1905 return -EINVAL;
1906 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1907 return -EINVAL;
1908 if (reg_r(gspca_dev, reg->reg, 1) < 0)
1909 return -EINVAL;
1910 reg->val = gspca_dev->usb_buf[0];
1911 return 0;
1912 case V4L2_CHIP_MATCH_I2C_ADDR:
1913 if (reg->match.addr != sd->i2c_addr)
1914 return -EINVAL;
1915 if (sd->sensor >= SENSOR_MT9V011 &&
1916 sd->sensor <= SENSOR_MT9M111) {
1917 if (i2c_r2(gspca_dev, reg->reg, (u16 *)&reg->val) < 0)
1918 return -EINVAL;
1919 } else {
1920 if (i2c_r1(gspca_dev, reg->reg, (u8 *)&reg->val) < 0)
1921 return -EINVAL;
1922 }
1923 return 0;
1924 }
1925 return -EINVAL;
1926}
1927
1928static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1929 struct v4l2_dbg_register *reg)
1930{
1931 struct sd *sd = (struct sd *) gspca_dev;
1932 switch (reg->match.type) {
1933 case V4L2_CHIP_MATCH_HOST:
1934 if (reg->match.addr != 0)
1935 return -EINVAL;
1936 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1937 return -EINVAL;
1938 if (reg_w1(gspca_dev, reg->reg, reg->val) < 0)
1939 return -EINVAL;
1940 return 0;
1941 case V4L2_CHIP_MATCH_I2C_ADDR:
1942 if (reg->match.addr != sd->i2c_addr)
1943 return -EINVAL;
1944 if (sd->sensor >= SENSOR_MT9V011 &&
1945 sd->sensor <= SENSOR_MT9M111) {
1946 if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0)
1947 return -EINVAL;
1948 } else {
1949 if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0)
1950 return -EINVAL;
1951 }
1952 return 0;
1953 }
1954 return -EINVAL;
1955}
1956#endif
1957
1958static int sd_chip_ident(struct gspca_dev *gspca_dev,
1959 struct v4l2_dbg_chip_ident *chip)
1960{
1961 struct sd *sd = (struct sd *) gspca_dev;
1962
1963 switch (chip->match.type) {
1964 case V4L2_CHIP_MATCH_HOST:
1965 if (chip->match.addr != 0)
1966 return -EINVAL;
1967 chip->revision = 0;
1968 chip->ident = V4L2_IDENT_SN9C20X;
1969 return 0;
1970 case V4L2_CHIP_MATCH_I2C_ADDR:
1971 if (chip->match.addr != sd->i2c_addr)
1972 return -EINVAL;
1973 chip->revision = 0;
1974 chip->ident = i2c_ident[sd->sensor];
1975 return 0;
1976 }
1977 return -EINVAL;
1978}
1979
1980static int sd_config(struct gspca_dev *gspca_dev,
1981 const struct usb_device_id *id)
1982{
1983 struct sd *sd = (struct sd *) gspca_dev;
1984 struct cam *cam;
1985
1986 cam = &gspca_dev->cam;
1987
1988 sd->sensor = (id->driver_info >> 8) & 0xff;
1989 sd->i2c_addr = id->driver_info & 0xff;
1990
1991 switch (sd->sensor) {
1992 case SENSOR_OV9650:
1993 cam->cam_mode = sxga_mode;
1994 cam->nmodes = ARRAY_SIZE(sxga_mode);
1995 break;
1996 default:
1997 cam->cam_mode = vga_mode;
1998 cam->nmodes = ARRAY_SIZE(vga_mode);
1999 }
2000
2001 sd->old_step = 0;
2002 sd->older_step = 0;
2003 sd->exposure_step = 16;
2004
2005 sd->brightness = BRIGHTNESS_DEFAULT;
2006 sd->contrast = CONTRAST_DEFAULT;
2007 sd->saturation = SATURATION_DEFAULT;
2008 sd->hue = HUE_DEFAULT;
2009 sd->gamma = GAMMA_DEFAULT;
2010 sd->red = RED_DEFAULT;
2011 sd->blue = BLUE_DEFAULT;
2012
2013 sd->hflip = HFLIP_DEFAULT;
2014 sd->vflip = VFLIP_DEFAULT;
2015 sd->exposure = EXPOSURE_DEFAULT;
2016 sd->gain = GAIN_DEFAULT;
2017 sd->auto_exposure = AUTO_EXPOSURE_DEFAULT;
2018
2019 sd->quality = 95;
2020
2021#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
2022 sd->input_gpio = (id->driver_info >> 16) & 0xff;
2023 if (sn9c20x_input_init(gspca_dev) < 0)
2024 return -ENODEV;
2025#endif
2026 return 0;
2027}
2028
2029static int sd_init(struct gspca_dev *gspca_dev)
2030{
2031 struct sd *sd = (struct sd *) gspca_dev;
2032 int i;
2033 u8 value;
2034 u8 i2c_init[9] =
2035 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
2036
2037 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
2038 value = bridge_init[i][1];
2039 if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
2040 err("Device initialization failed");
2041 return -ENODEV;
2042 }
2043 }
2044
2045 if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
2046 err("Device initialization failed");
2047 return -ENODEV;
2048 }
2049
2050 switch (sd->sensor) {
2051 case SENSOR_OV9650:
2052 if (ov9650_init_sensor(gspca_dev) < 0)
2053 return -ENODEV;
2054 info("OV9650 sensor detected");
2055 break;
2056 case SENSOR_OV9655:
2057 if (ov9655_init_sensor(gspca_dev) < 0)
2058 return -ENODEV;
2059 info("OV9655 sensor detected");
2060 break;
2061 case SENSOR_SOI968:
2062 if (soi968_init_sensor(gspca_dev) < 0)
2063 return -ENODEV;
2064 info("SOI968 sensor detected");
2065 break;
2066 case SENSOR_OV7660:
2067 if (ov7660_init_sensor(gspca_dev) < 0)
2068 return -ENODEV;
2069 info("OV7660 sensor detected");
2070 break;
2071 case SENSOR_OV7670:
2072 if (ov7670_init_sensor(gspca_dev) < 0)
2073 return -ENODEV;
2074 info("OV7670 sensor detected");
2075 break;
2076 case SENSOR_MT9VPRB:
2077 if (mt9v_init_sensor(gspca_dev) < 0)
2078 return -ENODEV;
2079 break;
2080 case SENSOR_MT9M111:
2081 if (mt9m111_init_sensor(gspca_dev) < 0)
2082 return -ENODEV;
2083 info("MT9M111 sensor detected");
2084 break;
2085 case SENSOR_MT9M001:
2086 if (mt9m001_init_sensor(gspca_dev) < 0)
2087 return -ENODEV;
2088 info("MT9M001 sensor detected");
2089 break;
2090 case SENSOR_HV7131R:
2091 if (hv7131r_init_sensor(gspca_dev) < 0)
2092 return -ENODEV;
2093 info("HV7131R sensor detected");
2094 break;
2095 default:
2096 info("Unsupported Sensor");
2097 return -ENODEV;
2098 }
2099
2100 return 0;
2101}
2102
2103static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
2104{
2105 struct sd *sd = (struct sd *) gspca_dev;
2106 u8 value;
2107 switch (sd->sensor) {
2108 case SENSOR_OV9650:
2109 if (mode & MODE_SXGA) {
2110 i2c_w1(gspca_dev, 0x17, 0x1b);
2111 i2c_w1(gspca_dev, 0x18, 0xbc);
2112 i2c_w1(gspca_dev, 0x19, 0x01);
2113 i2c_w1(gspca_dev, 0x1a, 0x82);
2114 i2c_r1(gspca_dev, 0x12, &value);
2115 i2c_w1(gspca_dev, 0x12, value & 0x07);
2116 } else {
2117 i2c_w1(gspca_dev, 0x17, 0x24);
2118 i2c_w1(gspca_dev, 0x18, 0xc5);
2119 i2c_w1(gspca_dev, 0x19, 0x00);
2120 i2c_w1(gspca_dev, 0x1a, 0x3c);
2121 i2c_r1(gspca_dev, 0x12, &value);
2122 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
2123 }
2124 break;
2125 }
2126}
2127
2128#define HW_WIN(mode, hstart, vstart) \
2129((const u8 []){hstart & 0xff, hstart >> 8, \
2130vstart & 0xff, vstart >> 8, \
2131(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2132(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2133
2134#define CLR_WIN(width, height) \
2135((const u8 [])\
2136{0, width >> 2, 0, height >> 1,\
2137((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2138
2139static int sd_start(struct gspca_dev *gspca_dev)
2140{
2141 struct sd *sd = (struct sd *) gspca_dev;
2142 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2143 int width = gspca_dev->width;
2144 int height = gspca_dev->height;
2145 u8 fmt, scale = 0;
2146
2147 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
2148 if (sd->jpeg_hdr == NULL)
2149 return -ENOMEM;
2150
2151 jpeg_define(sd->jpeg_hdr, height, width,
2152 0x21);
2153 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2154
2155 if (mode & MODE_RAW)
2156 fmt = 0x2d;
2157 else if (mode & MODE_JPEG)
2158 fmt = 0x2c;
2159 else
2160 fmt = 0x2f;
2161
2162 switch (mode & 0x0f) {
2163 case 3:
2164 scale = 0xc0;
2165 info("Set 1280x1024");
2166 break;
2167 case 2:
2168 scale = 0x80;
2169 info("Set 640x480");
2170 break;
2171 case 1:
2172 scale = 0x90;
2173 info("Set 320x240");
2174 break;
2175 case 0:
2176 scale = 0xa0;
2177 info("Set 160x120");
2178 break;
2179 }
2180
2181 configure_sensor_output(gspca_dev, mode);
2182 reg_w(gspca_dev, 0x1100, sd->jpeg_hdr + JPEG_QT0_OFFSET, 64);
2183 reg_w(gspca_dev, 0x1140, sd->jpeg_hdr + JPEG_QT1_OFFSET, 64);
2184 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2185 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2186 reg_w1(gspca_dev, 0x1189, scale);
2187 reg_w1(gspca_dev, 0x10e0, fmt);
2188
2189 set_cmatrix(gspca_dev);
2190 set_gamma(gspca_dev);
2191 set_redblue(gspca_dev);
2192 set_gain(gspca_dev);
2193 set_exposure(gspca_dev);
2194 set_hvflip(gspca_dev);
2195
2196 reg_r(gspca_dev, 0x1061, 1);
2197 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
2198 return 0;
2199}
2200
2201static void sd_stopN(struct gspca_dev *gspca_dev)
2202{
2203 reg_r(gspca_dev, 0x1061, 1);
2204 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2205}
2206
2207static void sd_stop0(struct gspca_dev *gspca_dev)
2208{
2209 struct sd *sd = (struct sd *) gspca_dev;
2210 kfree(sd->jpeg_hdr);
2211}
2212
2213static void do_autoexposure(struct gspca_dev *gspca_dev)
2214{
2215 struct sd *sd = (struct sd *) gspca_dev;
2216 int avg_lum, new_exp;
2217
2218 if (!sd->auto_exposure)
2219 return;
2220
2221 avg_lum = atomic_read(&sd->avg_lum);
2222
2223 /*
2224 * some hardcoded values are present
2225 * like those for maximal/minimal exposure
2226 * and exposure steps
2227 */
2228 if (avg_lum < MIN_AVG_LUM) {
2229 if (sd->exposure > 0x1770)
2230 return;
2231
2232 new_exp = sd->exposure + sd->exposure_step;
2233 if (new_exp > 0x1770)
2234 new_exp = 0x1770;
2235 if (new_exp < 0x10)
2236 new_exp = 0x10;
2237 sd->exposure = new_exp;
2238 set_exposure(gspca_dev);
2239
2240 sd->older_step = sd->old_step;
2241 sd->old_step = 1;
2242
2243 if (sd->old_step ^ sd->older_step)
2244 sd->exposure_step /= 2;
2245 else
2246 sd->exposure_step += 2;
2247 }
2248 if (avg_lum > MAX_AVG_LUM) {
2249 if (sd->exposure < 0x10)
2250 return;
2251 new_exp = sd->exposure - sd->exposure_step;
2252 if (new_exp > 0x1700)
2253 new_exp = 0x1770;
2254 if (new_exp < 0x10)
2255 new_exp = 0x10;
2256 sd->exposure = new_exp;
2257 set_exposure(gspca_dev);
2258 sd->older_step = sd->old_step;
2259 sd->old_step = 0;
2260
2261 if (sd->old_step ^ sd->older_step)
2262 sd->exposure_step /= 2;
2263 else
2264 sd->exposure_step += 2;
2265 }
2266}
2267
2268static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2269 struct gspca_frame *frame, /* target */
2270 u8 *data, /* isoc packet */
2271 int len) /* iso packet length */
2272{
2273 struct sd *sd = (struct sd *) gspca_dev;
2274 int avg_lum;
2275 static unsigned char frame_header[] =
2276 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
2277 if (len == 64 && memcmp(data, frame_header, 6) == 0) {
2278 avg_lum = ((data[35] >> 2) & 3) |
2279 (data[20] << 2) |
2280 (data[19] << 10);
2281 avg_lum += ((data[35] >> 4) & 3) |
2282 (data[22] << 2) |
2283 (data[21] << 10);
2284 avg_lum += ((data[35] >> 6) & 3) |
2285 (data[24] << 2) |
2286 (data[23] << 10);
2287 avg_lum += (data[36] & 3) |
2288 (data[26] << 2) |
2289 (data[25] << 10);
2290 avg_lum += ((data[36] >> 2) & 3) |
2291 (data[28] << 2) |
2292 (data[27] << 10);
2293 avg_lum += ((data[36] >> 4) & 3) |
2294 (data[30] << 2) |
2295 (data[29] << 10);
2296 avg_lum += ((data[36] >> 6) & 3) |
2297 (data[32] << 2) |
2298 (data[31] << 10);
2299 avg_lum += ((data[44] >> 4) & 3) |
2300 (data[34] << 2) |
2301 (data[33] << 10);
2302 avg_lum >>= 9;
2303 atomic_set(&sd->avg_lum, avg_lum);
2304 gspca_frame_add(gspca_dev, LAST_PACKET,
2305 frame, data, len);
2306 return;
2307 }
2308 if (gspca_dev->last_packet_type == LAST_PACKET) {
2309 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2310 & MODE_JPEG) {
2311 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
2312 sd->jpeg_hdr, JPEG_HDR_SZ);
2313 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
2314 data, len);
2315 } else {
2316 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
2317 data, len);
2318 }
2319 } else {
2320 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
2321 }
2322}
2323
2324/* sub-driver description */
2325static const struct sd_desc sd_desc = {
2326 .name = MODULE_NAME,
2327 .ctrls = sd_ctrls,
2328 .nctrls = ARRAY_SIZE(sd_ctrls),
2329 .config = sd_config,
2330 .init = sd_init,
2331 .start = sd_start,
2332 .stopN = sd_stopN,
2333 .stop0 = sd_stop0,
2334 .pkt_scan = sd_pkt_scan,
2335 .dq_callback = do_autoexposure,
2336#ifdef CONFIG_VIDEO_ADV_DEBUG
2337 .set_register = sd_dbg_s_register,
2338 .get_register = sd_dbg_g_register,
2339#endif
2340 .get_chip_ident = sd_chip_ident,
2341};
2342
2343#define SN9C20X(sensor, i2c_addr, button_mask) \
2344 .driver_info = (button_mask << 16) \
2345 | (SENSOR_ ## sensor << 8) \
2346 | (i2c_addr)
2347
2348static const __devinitdata struct usb_device_id device_table[] = {
2349 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2350 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2351 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
2352 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, 0x10)},
2353 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, 0)},
2354 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2355 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2356 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2357 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
2358 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, 0)},
2359 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2360 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2361 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2362 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
2363 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
2364 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2365 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2366 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2367 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
2368 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
2369 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, 0)},
2370 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2371 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2372 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2373 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
2374 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2375 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2376 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2377 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
2378 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
2379 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2380 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2381 {}
2382};
2383MODULE_DEVICE_TABLE(usb, device_table);
2384
2385/* -- device connect -- */
2386static int sd_probe(struct usb_interface *intf,
2387 const struct usb_device_id *id)
2388{
2389 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2390 THIS_MODULE);
2391}
2392
2393static void sd_disconnect(struct usb_interface *intf)
2394{
2395#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
2396 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
2397
2398 sn9c20x_input_cleanup(gspca_dev);
2399#endif
2400
2401 gspca_disconnect(intf);
2402}
2403
2404static struct usb_driver sd_driver = {
2405 .name = MODULE_NAME,
2406 .id_table = device_table,
2407 .probe = sd_probe,
2408 .disconnect = sd_disconnect,
2409#ifdef CONFIG_PM
2410 .suspend = gspca_suspend,
2411 .resume = gspca_resume,
2412 .reset_resume = gspca_resume,
2413#endif
2414};
2415
2416/* -- module insert / remove -- */
2417static int __init sd_mod_init(void)
2418{
2419 int ret;
2420 ret = usb_register(&sd_driver);
2421 if (ret < 0)
2422 return ret;
2423 info("registered");
2424 return 0;
2425}
2426static void __exit sd_mod_exit(void)
2427{
2428 usb_deregister(&sd_driver);
2429 info("deregistered");
2430}
2431
2432module_init(sd_mod_init);
2433module_exit(sd_mod_exit);