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