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