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