blob: c5f6ff3f70b4d776cdb966e56587004a1d130355 [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
Brian Johnsone99ac542010-03-16 13:58:28 -030053#define SENSOR_MT9M112 10
54#define SENSOR_HV7131R 11
Brian Johnson26e744b2009-07-19 05:52:58 -030055#define SENSOR_MT9VPRB 20
56
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030057/* camera flags */
58#define HAS_BUTTON 0x1
Brian Johnson0c045eb2010-03-16 13:58:27 -030059#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */
Brian Johnson7ddaac72010-03-16 13:58:27 -030060#define FLIP_DETECT 0x4
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030061
Brian Johnson26e744b2009-07-19 05:52:58 -030062/* specific webcam descriptor */
63struct sd {
64 struct gspca_dev gspca_dev;
65
66#define MIN_AVG_LUM 80
67#define MAX_AVG_LUM 130
68 atomic_t avg_lum;
69 u8 old_step;
70 u8 older_step;
71 u8 exposure_step;
72
73 u8 brightness;
74 u8 contrast;
75 u8 saturation;
76 s16 hue;
77 u8 gamma;
78 u8 red;
79 u8 blue;
80
81 u8 hflip;
82 u8 vflip;
83 u8 gain;
84 u16 exposure;
85 u8 auto_exposure;
86
87 u8 i2c_addr;
88 u8 sensor;
89 u8 hstart;
90 u8 vstart;
91
92 u8 *jpeg_hdr;
93 u8 quality;
94
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -030095 u8 flags;
Brian Johnson26e744b2009-07-19 05:52:58 -030096};
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
Brian Johnson7ddaac72010-03-16 13:58:27 -0300133static const struct dmi_system_id flip_dmi_table[] = {
134 {
135 .ident = "MSI MS-1034",
136 .matches = {
137 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
138 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
139 DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
140 }
141 },
142 {
143 .ident = "MSI MS-1632",
144 .matches = {
145 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
146 DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
147 }
148 },
Brian Johnsone077f862010-04-05 20:52:52 -0300149 {
150 .ident = "ASUSTeK W7J",
151 .matches = {
152 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
153 DMI_MATCH(DMI_BOARD_NAME, "W7J ")
154 }
155 },
Brian Johnson7ddaac72010-03-16 13:58:27 -0300156 {}
157};
158
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300159static const struct ctrl sd_ctrls[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300160 {
161#define BRIGHTNESS_IDX 0
162 {
163 .id = V4L2_CID_BRIGHTNESS,
164 .type = V4L2_CTRL_TYPE_INTEGER,
165 .name = "Brightness",
166 .minimum = 0,
167 .maximum = 0xff,
168 .step = 1,
169#define BRIGHTNESS_DEFAULT 0x7f
170 .default_value = BRIGHTNESS_DEFAULT,
171 },
172 .set = sd_setbrightness,
173 .get = sd_getbrightness,
174 },
175 {
176#define CONTRAST_IDX 1
177 {
178 .id = V4L2_CID_CONTRAST,
179 .type = V4L2_CTRL_TYPE_INTEGER,
180 .name = "Contrast",
181 .minimum = 0,
182 .maximum = 0xff,
183 .step = 1,
184#define CONTRAST_DEFAULT 0x7f
185 .default_value = CONTRAST_DEFAULT,
186 },
187 .set = sd_setcontrast,
188 .get = sd_getcontrast,
189 },
190 {
191#define SATURATION_IDX 2
192 {
193 .id = V4L2_CID_SATURATION,
194 .type = V4L2_CTRL_TYPE_INTEGER,
195 .name = "Saturation",
196 .minimum = 0,
197 .maximum = 0xff,
198 .step = 1,
199#define SATURATION_DEFAULT 0x7f
200 .default_value = SATURATION_DEFAULT,
201 },
202 .set = sd_setsaturation,
203 .get = sd_getsaturation,
204 },
205 {
206#define HUE_IDX 3
207 {
208 .id = V4L2_CID_HUE,
209 .type = V4L2_CTRL_TYPE_INTEGER,
210 .name = "Hue",
211 .minimum = -180,
212 .maximum = 180,
213 .step = 1,
214#define HUE_DEFAULT 0
215 .default_value = HUE_DEFAULT,
216 },
217 .set = sd_sethue,
218 .get = sd_gethue,
219 },
220 {
221#define GAMMA_IDX 4
222 {
223 .id = V4L2_CID_GAMMA,
224 .type = V4L2_CTRL_TYPE_INTEGER,
225 .name = "Gamma",
226 .minimum = 0,
227 .maximum = 0xff,
228 .step = 1,
229#define GAMMA_DEFAULT 0x10
230 .default_value = GAMMA_DEFAULT,
231 },
232 .set = sd_setgamma,
233 .get = sd_getgamma,
234 },
235 {
236#define BLUE_IDX 5
237 {
238 .id = V4L2_CID_BLUE_BALANCE,
239 .type = V4L2_CTRL_TYPE_INTEGER,
240 .name = "Blue Balance",
241 .minimum = 0,
242 .maximum = 0x7f,
243 .step = 1,
244#define BLUE_DEFAULT 0x28
245 .default_value = BLUE_DEFAULT,
246 },
247 .set = sd_setbluebalance,
248 .get = sd_getbluebalance,
249 },
250 {
251#define RED_IDX 6
252 {
253 .id = V4L2_CID_RED_BALANCE,
254 .type = V4L2_CTRL_TYPE_INTEGER,
255 .name = "Red Balance",
256 .minimum = 0,
257 .maximum = 0x7f,
258 .step = 1,
259#define RED_DEFAULT 0x28
260 .default_value = RED_DEFAULT,
261 },
262 .set = sd_setredbalance,
263 .get = sd_getredbalance,
264 },
265 {
266#define HFLIP_IDX 7
267 {
268 .id = V4L2_CID_HFLIP,
269 .type = V4L2_CTRL_TYPE_BOOLEAN,
270 .name = "Horizontal Flip",
271 .minimum = 0,
272 .maximum = 1,
273 .step = 1,
274#define HFLIP_DEFAULT 0
275 .default_value = HFLIP_DEFAULT,
276 },
277 .set = sd_sethflip,
278 .get = sd_gethflip,
279 },
280 {
281#define VFLIP_IDX 8
282 {
283 .id = V4L2_CID_VFLIP,
284 .type = V4L2_CTRL_TYPE_BOOLEAN,
285 .name = "Vertical Flip",
286 .minimum = 0,
287 .maximum = 1,
288 .step = 1,
289#define VFLIP_DEFAULT 0
290 .default_value = VFLIP_DEFAULT,
291 },
292 .set = sd_setvflip,
293 .get = sd_getvflip,
294 },
295 {
296#define EXPOSURE_IDX 9
297 {
298 .id = V4L2_CID_EXPOSURE,
299 .type = V4L2_CTRL_TYPE_INTEGER,
300 .name = "Exposure",
301 .minimum = 0,
302 .maximum = 0x1780,
303 .step = 1,
304#define EXPOSURE_DEFAULT 0x33
305 .default_value = EXPOSURE_DEFAULT,
306 },
307 .set = sd_setexposure,
308 .get = sd_getexposure,
309 },
310 {
311#define GAIN_IDX 10
312 {
313 .id = V4L2_CID_GAIN,
314 .type = V4L2_CTRL_TYPE_INTEGER,
315 .name = "Gain",
316 .minimum = 0,
317 .maximum = 28,
318 .step = 1,
319#define GAIN_DEFAULT 0x00
320 .default_value = GAIN_DEFAULT,
321 },
322 .set = sd_setgain,
323 .get = sd_getgain,
324 },
325 {
326#define AUTOGAIN_IDX 11
327 {
328 .id = V4L2_CID_AUTOGAIN,
329 .type = V4L2_CTRL_TYPE_BOOLEAN,
330 .name = "Auto Exposure",
331 .minimum = 0,
332 .maximum = 1,
333 .step = 1,
334#define AUTO_EXPOSURE_DEFAULT 1
335 .default_value = AUTO_EXPOSURE_DEFAULT,
336 },
337 .set = sd_setautoexposure,
338 .get = sd_getautoexposure,
339 },
340};
341
342static const struct v4l2_pix_format vga_mode[] = {
343 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
344 .bytesperline = 240,
345 .sizeimage = 240 * 120,
346 .colorspace = V4L2_COLORSPACE_JPEG,
347 .priv = 0 | MODE_JPEG},
348 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
349 .bytesperline = 160,
350 .sizeimage = 160 * 120,
351 .colorspace = V4L2_COLORSPACE_SRGB,
352 .priv = 0 | MODE_RAW},
353 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
354 .bytesperline = 240,
355 .sizeimage = 240 * 120,
356 .colorspace = V4L2_COLORSPACE_SRGB,
357 .priv = 0},
358 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
359 .bytesperline = 480,
360 .sizeimage = 480 * 240 ,
361 .colorspace = V4L2_COLORSPACE_JPEG,
362 .priv = 1 | MODE_JPEG},
363 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
364 .bytesperline = 320,
365 .sizeimage = 320 * 240 ,
366 .colorspace = V4L2_COLORSPACE_SRGB,
367 .priv = 1 | MODE_RAW},
368 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
369 .bytesperline = 480,
370 .sizeimage = 480 * 240 ,
371 .colorspace = V4L2_COLORSPACE_SRGB,
372 .priv = 1},
373 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
374 .bytesperline = 960,
375 .sizeimage = 960 * 480,
376 .colorspace = V4L2_COLORSPACE_JPEG,
377 .priv = 2 | MODE_JPEG},
378 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
379 .bytesperline = 640,
380 .sizeimage = 640 * 480,
381 .colorspace = V4L2_COLORSPACE_SRGB,
382 .priv = 2 | MODE_RAW},
383 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
384 .bytesperline = 960,
385 .sizeimage = 960 * 480,
386 .colorspace = V4L2_COLORSPACE_SRGB,
387 .priv = 2},
388};
389
390static const struct v4l2_pix_format sxga_mode[] = {
391 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
392 .bytesperline = 240,
393 .sizeimage = 240 * 120,
394 .colorspace = V4L2_COLORSPACE_JPEG,
395 .priv = 0 | MODE_JPEG},
396 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
397 .bytesperline = 160,
398 .sizeimage = 160 * 120,
399 .colorspace = V4L2_COLORSPACE_SRGB,
400 .priv = 0 | MODE_RAW},
401 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
402 .bytesperline = 240,
403 .sizeimage = 240 * 120,
404 .colorspace = V4L2_COLORSPACE_SRGB,
405 .priv = 0},
406 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
407 .bytesperline = 480,
408 .sizeimage = 480 * 240 ,
409 .colorspace = V4L2_COLORSPACE_JPEG,
410 .priv = 1 | MODE_JPEG},
411 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
412 .bytesperline = 320,
413 .sizeimage = 320 * 240 ,
414 .colorspace = V4L2_COLORSPACE_SRGB,
415 .priv = 1 | MODE_RAW},
416 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
417 .bytesperline = 480,
418 .sizeimage = 480 * 240 ,
419 .colorspace = V4L2_COLORSPACE_SRGB,
420 .priv = 1},
421 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
422 .bytesperline = 960,
423 .sizeimage = 960 * 480,
424 .colorspace = V4L2_COLORSPACE_JPEG,
425 .priv = 2 | MODE_JPEG},
426 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
427 .bytesperline = 640,
428 .sizeimage = 640 * 480,
429 .colorspace = V4L2_COLORSPACE_SRGB,
430 .priv = 2 | MODE_RAW},
431 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
432 .bytesperline = 960,
433 .sizeimage = 960 * 480,
434 .colorspace = V4L2_COLORSPACE_SRGB,
435 .priv = 2},
436 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
437 .bytesperline = 1280,
438 .sizeimage = (1280 * 1024) + 64,
439 .colorspace = V4L2_COLORSPACE_SRGB,
440 .priv = 3 | MODE_RAW | MODE_SXGA},
441};
442
Joe Perches58aa68c2009-09-02 01:12:13 -0300443static const s16 hsv_red_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300444 41, 44, 46, 48, 50, 52, 54, 56,
445 58, 60, 62, 64, 66, 68, 70, 72,
446 74, 76, 78, 80, 81, 83, 85, 87,
447 88, 90, 92, 93, 95, 97, 98, 100,
448 101, 102, 104, 105, 107, 108, 109, 110,
449 112, 113, 114, 115, 116, 117, 118, 119,
450 120, 121, 122, 123, 123, 124, 125, 125,
451 126, 127, 127, 128, 128, 129, 129, 129,
452 130, 130, 130, 130, 131, 131, 131, 131,
453 131, 131, 131, 131, 130, 130, 130, 130,
454 129, 129, 129, 128, 128, 127, 127, 126,
455 125, 125, 124, 123, 122, 122, 121, 120,
456 119, 118, 117, 116, 115, 114, 112, 111,
457 110, 109, 107, 106, 105, 103, 102, 101,
458 99, 98, 96, 94, 93, 91, 90, 88,
459 86, 84, 83, 81, 79, 77, 75, 74,
460 72, 70, 68, 66, 64, 62, 60, 58,
461 56, 54, 52, 49, 47, 45, 43, 41,
462 39, 36, 34, 32, 30, 28, 25, 23,
463 21, 19, 16, 14, 12, 9, 7, 5,
464 3, 0, -1, -3, -6, -8, -10, -12,
465 -15, -17, -19, -22, -24, -26, -28, -30,
466 -33, -35, -37, -39, -41, -44, -46, -48,
467 -50, -52, -54, -56, -58, -60, -62, -64,
468 -66, -68, -70, -72, -74, -76, -78, -80,
469 -81, -83, -85, -87, -88, -90, -92, -93,
470 -95, -97, -98, -100, -101, -102, -104, -105,
471 -107, -108, -109, -110, -112, -113, -114, -115,
472 -116, -117, -118, -119, -120, -121, -122, -123,
473 -123, -124, -125, -125, -126, -127, -127, -128,
474 -128, -128, -128, -128, -128, -128, -128, -128,
475 -128, -128, -128, -128, -128, -128, -128, -128,
476 -128, -128, -128, -128, -128, -128, -128, -128,
477 -128, -127, -127, -126, -125, -125, -124, -123,
478 -122, -122, -121, -120, -119, -118, -117, -116,
479 -115, -114, -112, -111, -110, -109, -107, -106,
480 -105, -103, -102, -101, -99, -98, -96, -94,
481 -93, -91, -90, -88, -86, -84, -83, -81,
482 -79, -77, -75, -74, -72, -70, -68, -66,
483 -64, -62, -60, -58, -56, -54, -52, -49,
484 -47, -45, -43, -41, -39, -36, -34, -32,
485 -30, -28, -25, -23, -21, -19, -16, -14,
486 -12, -9, -7, -5, -3, 0, 1, 3,
487 6, 8, 10, 12, 15, 17, 19, 22,
488 24, 26, 28, 30, 33, 35, 37, 39, 41
489};
490
Joe Perches58aa68c2009-09-02 01:12:13 -0300491static const s16 hsv_red_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300492 82, 80, 78, 76, 74, 73, 71, 69,
493 67, 65, 63, 61, 58, 56, 54, 52,
494 50, 48, 46, 44, 41, 39, 37, 35,
495 32, 30, 28, 26, 23, 21, 19, 16,
496 14, 12, 10, 7, 5, 3, 0, -1,
497 -3, -6, -8, -10, -13, -15, -17, -19,
498 -22, -24, -26, -29, -31, -33, -35, -38,
499 -40, -42, -44, -46, -48, -51, -53, -55,
500 -57, -59, -61, -63, -65, -67, -69, -71,
501 -73, -75, -77, -79, -81, -82, -84, -86,
502 -88, -89, -91, -93, -94, -96, -98, -99,
503 -101, -102, -104, -105, -106, -108, -109, -110,
504 -112, -113, -114, -115, -116, -117, -119, -120,
505 -120, -121, -122, -123, -124, -125, -126, -126,
506 -127, -128, -128, -128, -128, -128, -128, -128,
507 -128, -128, -128, -128, -128, -128, -128, -128,
508 -128, -128, -128, -128, -128, -128, -128, -128,
509 -128, -128, -128, -128, -128, -128, -128, -128,
510 -127, -127, -126, -125, -125, -124, -123, -122,
511 -121, -120, -119, -118, -117, -116, -115, -114,
512 -113, -111, -110, -109, -107, -106, -105, -103,
513 -102, -100, -99, -97, -96, -94, -92, -91,
514 -89, -87, -85, -84, -82, -80, -78, -76,
515 -74, -73, -71, -69, -67, -65, -63, -61,
516 -58, -56, -54, -52, -50, -48, -46, -44,
517 -41, -39, -37, -35, -32, -30, -28, -26,
518 -23, -21, -19, -16, -14, -12, -10, -7,
519 -5, -3, 0, 1, 3, 6, 8, 10,
520 13, 15, 17, 19, 22, 24, 26, 29,
521 31, 33, 35, 38, 40, 42, 44, 46,
522 48, 51, 53, 55, 57, 59, 61, 63,
523 65, 67, 69, 71, 73, 75, 77, 79,
524 81, 82, 84, 86, 88, 89, 91, 93,
525 94, 96, 98, 99, 101, 102, 104, 105,
526 106, 108, 109, 110, 112, 113, 114, 115,
527 116, 117, 119, 120, 120, 121, 122, 123,
528 124, 125, 126, 126, 127, 128, 128, 129,
529 129, 130, 130, 131, 131, 131, 131, 132,
530 132, 132, 132, 132, 132, 132, 132, 132,
531 132, 132, 132, 131, 131, 131, 130, 130,
532 130, 129, 129, 128, 127, 127, 126, 125,
533 125, 124, 123, 122, 121, 120, 119, 118,
534 117, 116, 115, 114, 113, 111, 110, 109,
535 107, 106, 105, 103, 102, 100, 99, 97,
536 96, 94, 92, 91, 89, 87, 85, 84, 82
537};
538
Joe Perches58aa68c2009-09-02 01:12:13 -0300539static const s16 hsv_green_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300540 -124, -124, -125, -125, -125, -125, -125, -125,
541 -125, -126, -126, -125, -125, -125, -125, -125,
542 -125, -124, -124, -124, -123, -123, -122, -122,
543 -121, -121, -120, -120, -119, -118, -117, -117,
544 -116, -115, -114, -113, -112, -111, -110, -109,
545 -108, -107, -105, -104, -103, -102, -100, -99,
546 -98, -96, -95, -93, -92, -91, -89, -87,
547 -86, -84, -83, -81, -79, -77, -76, -74,
548 -72, -70, -69, -67, -65, -63, -61, -59,
549 -57, -55, -53, -51, -49, -47, -45, -43,
550 -41, -39, -37, -35, -33, -30, -28, -26,
551 -24, -22, -20, -18, -15, -13, -11, -9,
552 -7, -4, -2, 0, 1, 3, 6, 8,
553 10, 12, 14, 17, 19, 21, 23, 25,
554 27, 29, 32, 34, 36, 38, 40, 42,
555 44, 46, 48, 50, 52, 54, 56, 58,
556 60, 62, 64, 66, 68, 70, 71, 73,
557 75, 77, 78, 80, 82, 83, 85, 87,
558 88, 90, 91, 93, 94, 96, 97, 98,
559 100, 101, 102, 104, 105, 106, 107, 108,
560 109, 111, 112, 113, 113, 114, 115, 116,
561 117, 118, 118, 119, 120, 120, 121, 122,
562 122, 123, 123, 124, 124, 124, 125, 125,
563 125, 125, 125, 125, 125, 126, 126, 125,
564 125, 125, 125, 125, 125, 124, 124, 124,
565 123, 123, 122, 122, 121, 121, 120, 120,
566 119, 118, 117, 117, 116, 115, 114, 113,
567 112, 111, 110, 109, 108, 107, 105, 104,
568 103, 102, 100, 99, 98, 96, 95, 93,
569 92, 91, 89, 87, 86, 84, 83, 81,
570 79, 77, 76, 74, 72, 70, 69, 67,
571 65, 63, 61, 59, 57, 55, 53, 51,
572 49, 47, 45, 43, 41, 39, 37, 35,
573 33, 30, 28, 26, 24, 22, 20, 18,
574 15, 13, 11, 9, 7, 4, 2, 0,
575 -1, -3, -6, -8, -10, -12, -14, -17,
576 -19, -21, -23, -25, -27, -29, -32, -34,
577 -36, -38, -40, -42, -44, -46, -48, -50,
578 -52, -54, -56, -58, -60, -62, -64, -66,
579 -68, -70, -71, -73, -75, -77, -78, -80,
580 -82, -83, -85, -87, -88, -90, -91, -93,
581 -94, -96, -97, -98, -100, -101, -102, -104,
582 -105, -106, -107, -108, -109, -111, -112, -113,
583 -113, -114, -115, -116, -117, -118, -118, -119,
584 -120, -120, -121, -122, -122, -123, -123, -124, -124
585};
586
Joe Perches58aa68c2009-09-02 01:12:13 -0300587static const s16 hsv_green_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300588 -100, -99, -98, -97, -95, -94, -93, -91,
589 -90, -89, -87, -86, -84, -83, -81, -80,
590 -78, -76, -75, -73, -71, -70, -68, -66,
591 -64, -63, -61, -59, -57, -55, -53, -51,
592 -49, -48, -46, -44, -42, -40, -38, -36,
593 -34, -32, -30, -27, -25, -23, -21, -19,
594 -17, -15, -13, -11, -9, -7, -4, -2,
595 0, 1, 3, 5, 7, 9, 11, 14,
596 16, 18, 20, 22, 24, 26, 28, 30,
597 32, 34, 36, 38, 40, 42, 44, 46,
598 48, 50, 52, 54, 56, 58, 59, 61,
599 63, 65, 67, 68, 70, 72, 74, 75,
600 77, 78, 80, 82, 83, 85, 86, 88,
601 89, 90, 92, 93, 95, 96, 97, 98,
602 100, 101, 102, 103, 104, 105, 106, 107,
603 108, 109, 110, 111, 112, 112, 113, 114,
604 115, 115, 116, 116, 117, 117, 118, 118,
605 119, 119, 119, 120, 120, 120, 120, 120,
606 121, 121, 121, 121, 121, 121, 120, 120,
607 120, 120, 120, 119, 119, 119, 118, 118,
608 117, 117, 116, 116, 115, 114, 114, 113,
609 112, 111, 111, 110, 109, 108, 107, 106,
610 105, 104, 103, 102, 100, 99, 98, 97,
611 95, 94, 93, 91, 90, 89, 87, 86,
612 84, 83, 81, 80, 78, 76, 75, 73,
613 71, 70, 68, 66, 64, 63, 61, 59,
614 57, 55, 53, 51, 49, 48, 46, 44,
615 42, 40, 38, 36, 34, 32, 30, 27,
616 25, 23, 21, 19, 17, 15, 13, 11,
617 9, 7, 4, 2, 0, -1, -3, -5,
618 -7, -9, -11, -14, -16, -18, -20, -22,
619 -24, -26, -28, -30, -32, -34, -36, -38,
620 -40, -42, -44, -46, -48, -50, -52, -54,
621 -56, -58, -59, -61, -63, -65, -67, -68,
622 -70, -72, -74, -75, -77, -78, -80, -82,
623 -83, -85, -86, -88, -89, -90, -92, -93,
624 -95, -96, -97, -98, -100, -101, -102, -103,
625 -104, -105, -106, -107, -108, -109, -110, -111,
626 -112, -112, -113, -114, -115, -115, -116, -116,
627 -117, -117, -118, -118, -119, -119, -119, -120,
628 -120, -120, -120, -120, -121, -121, -121, -121,
629 -121, -121, -120, -120, -120, -120, -120, -119,
630 -119, -119, -118, -118, -117, -117, -116, -116,
631 -115, -114, -114, -113, -112, -111, -111, -110,
632 -109, -108, -107, -106, -105, -104, -103, -102, -100
633};
634
Joe Perches58aa68c2009-09-02 01:12:13 -0300635static const s16 hsv_blue_x[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300636 112, 113, 114, 114, 115, 116, 117, 117,
637 118, 118, 119, 119, 120, 120, 120, 121,
638 121, 121, 122, 122, 122, 122, 122, 122,
639 122, 122, 122, 122, 122, 122, 121, 121,
640 121, 120, 120, 120, 119, 119, 118, 118,
641 117, 116, 116, 115, 114, 113, 113, 112,
642 111, 110, 109, 108, 107, 106, 105, 104,
643 103, 102, 100, 99, 98, 97, 95, 94,
644 93, 91, 90, 88, 87, 85, 84, 82,
645 80, 79, 77, 76, 74, 72, 70, 69,
646 67, 65, 63, 61, 60, 58, 56, 54,
647 52, 50, 48, 46, 44, 42, 40, 38,
648 36, 34, 32, 30, 28, 26, 24, 22,
649 19, 17, 15, 13, 11, 9, 7, 5,
650 2, 0, -1, -3, -5, -7, -9, -12,
651 -14, -16, -18, -20, -22, -24, -26, -28,
652 -31, -33, -35, -37, -39, -41, -43, -45,
653 -47, -49, -51, -53, -54, -56, -58, -60,
654 -62, -64, -66, -67, -69, -71, -73, -74,
655 -76, -78, -79, -81, -83, -84, -86, -87,
656 -89, -90, -92, -93, -94, -96, -97, -98,
657 -99, -101, -102, -103, -104, -105, -106, -107,
658 -108, -109, -110, -111, -112, -113, -114, -114,
659 -115, -116, -117, -117, -118, -118, -119, -119,
660 -120, -120, -120, -121, -121, -121, -122, -122,
661 -122, -122, -122, -122, -122, -122, -122, -122,
662 -122, -122, -121, -121, -121, -120, -120, -120,
663 -119, -119, -118, -118, -117, -116, -116, -115,
664 -114, -113, -113, -112, -111, -110, -109, -108,
665 -107, -106, -105, -104, -103, -102, -100, -99,
666 -98, -97, -95, -94, -93, -91, -90, -88,
667 -87, -85, -84, -82, -80, -79, -77, -76,
668 -74, -72, -70, -69, -67, -65, -63, -61,
669 -60, -58, -56, -54, -52, -50, -48, -46,
670 -44, -42, -40, -38, -36, -34, -32, -30,
671 -28, -26, -24, -22, -19, -17, -15, -13,
672 -11, -9, -7, -5, -2, 0, 1, 3,
673 5, 7, 9, 12, 14, 16, 18, 20,
674 22, 24, 26, 28, 31, 33, 35, 37,
675 39, 41, 43, 45, 47, 49, 51, 53,
676 54, 56, 58, 60, 62, 64, 66, 67,
677 69, 71, 73, 74, 76, 78, 79, 81,
678 83, 84, 86, 87, 89, 90, 92, 93,
679 94, 96, 97, 98, 99, 101, 102, 103,
680 104, 105, 106, 107, 108, 109, 110, 111, 112
681};
682
Joe Perches58aa68c2009-09-02 01:12:13 -0300683static const s16 hsv_blue_y[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300684 -11, -13, -15, -17, -19, -21, -23, -25,
685 -27, -29, -31, -33, -35, -37, -39, -41,
686 -43, -45, -46, -48, -50, -52, -54, -55,
687 -57, -59, -61, -62, -64, -66, -67, -69,
688 -71, -72, -74, -75, -77, -78, -80, -81,
689 -83, -84, -86, -87, -88, -90, -91, -92,
690 -93, -95, -96, -97, -98, -99, -100, -101,
691 -102, -103, -104, -105, -106, -106, -107, -108,
692 -109, -109, -110, -111, -111, -112, -112, -113,
693 -113, -114, -114, -114, -115, -115, -115, -115,
694 -116, -116, -116, -116, -116, -116, -116, -116,
695 -116, -115, -115, -115, -115, -114, -114, -114,
696 -113, -113, -112, -112, -111, -111, -110, -110,
697 -109, -108, -108, -107, -106, -105, -104, -103,
698 -102, -101, -100, -99, -98, -97, -96, -95,
699 -94, -93, -91, -90, -89, -88, -86, -85,
700 -84, -82, -81, -79, -78, -76, -75, -73,
701 -71, -70, -68, -67, -65, -63, -62, -60,
702 -58, -56, -55, -53, -51, -49, -47, -45,
703 -44, -42, -40, -38, -36, -34, -32, -30,
704 -28, -26, -24, -22, -20, -18, -16, -14,
705 -12, -10, -8, -6, -4, -2, 0, 1,
706 3, 5, 7, 9, 11, 13, 15, 17,
707 19, 21, 23, 25, 27, 29, 31, 33,
708 35, 37, 39, 41, 43, 45, 46, 48,
709 50, 52, 54, 55, 57, 59, 61, 62,
710 64, 66, 67, 69, 71, 72, 74, 75,
711 77, 78, 80, 81, 83, 84, 86, 87,
712 88, 90, 91, 92, 93, 95, 96, 97,
713 98, 99, 100, 101, 102, 103, 104, 105,
714 106, 106, 107, 108, 109, 109, 110, 111,
715 111, 112, 112, 113, 113, 114, 114, 114,
716 115, 115, 115, 115, 116, 116, 116, 116,
717 116, 116, 116, 116, 116, 115, 115, 115,
718 115, 114, 114, 114, 113, 113, 112, 112,
719 111, 111, 110, 110, 109, 108, 108, 107,
720 106, 105, 104, 103, 102, 101, 100, 99,
721 98, 97, 96, 95, 94, 93, 91, 90,
722 89, 88, 86, 85, 84, 82, 81, 79,
723 78, 76, 75, 73, 71, 70, 68, 67,
724 65, 63, 62, 60, 58, 56, 55, 53,
725 51, 49, 47, 45, 44, 42, 40, 38,
726 36, 34, 32, 30, 28, 26, 24, 22,
727 20, 18, 16, 14, 12, 10, 8, 6,
728 4, 2, 0, -1, -3, -5, -7, -9, -11
729};
730
731static u16 i2c_ident[] = {
732 V4L2_IDENT_OV9650,
733 V4L2_IDENT_OV9655,
734 V4L2_IDENT_SOI968,
735 V4L2_IDENT_OV7660,
736 V4L2_IDENT_OV7670,
737 V4L2_IDENT_MT9V011,
738 V4L2_IDENT_MT9V111,
739 V4L2_IDENT_MT9V112,
740 V4L2_IDENT_MT9M001C12ST,
741 V4L2_IDENT_MT9M111,
Brian Johnsone99ac542010-03-16 13:58:28 -0300742 V4L2_IDENT_MT9M112,
Brian Johnson26e744b2009-07-19 05:52:58 -0300743 V4L2_IDENT_HV7131R,
744};
745
746static u16 bridge_init[][2] = {
747 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
748 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
749 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
750 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
751 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
752 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
753 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
754 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
755 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
756 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
757 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
758 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
759 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
760 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
761 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
762 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
763 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
764 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
Brian Johnson0c045eb2010-03-16 13:58:27 -0300765 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
766 {0x1007, 0x00}
Brian Johnson26e744b2009-07-19 05:52:58 -0300767};
768
769/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
770static u8 ov_gain[] = {
771 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
772 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
773 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
774 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
775 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
776 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
777 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
778 0x70 /* 8x */
779};
780
781/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
782static u16 micron1_gain[] = {
783 /* 1x 1.25x 1.5x 1.75x */
784 0x0020, 0x0028, 0x0030, 0x0038,
785 /* 2x 2.25x 2.5x 2.75x */
786 0x00a0, 0x00a4, 0x00a8, 0x00ac,
787 /* 3x 3.25x 3.5x 3.75x */
788 0x00b0, 0x00b4, 0x00b8, 0x00bc,
789 /* 4x 4.25x 4.5x 4.75x */
790 0x00c0, 0x00c4, 0x00c8, 0x00cc,
791 /* 5x 5.25x 5.5x 5.75x */
792 0x00d0, 0x00d4, 0x00d8, 0x00dc,
793 /* 6x 6.25x 6.5x 6.75x */
794 0x00e0, 0x00e4, 0x00e8, 0x00ec,
795 /* 7x 7.25x 7.5x 7.75x */
796 0x00f0, 0x00f4, 0x00f8, 0x00fc,
797 /* 8x */
798 0x01c0
799};
800
801/* mt9m001 sensor uses a different gain formula then other micron sensors */
802/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
803static u16 micron2_gain[] = {
804 /* 1x 1.25x 1.5x 1.75x */
805 0x0008, 0x000a, 0x000c, 0x000e,
806 /* 2x 2.25x 2.5x 2.75x */
807 0x0010, 0x0012, 0x0014, 0x0016,
808 /* 3x 3.25x 3.5x 3.75x */
809 0x0018, 0x001a, 0x001c, 0x001e,
810 /* 4x 4.25x 4.5x 4.75x */
811 0x0020, 0x0051, 0x0052, 0x0053,
812 /* 5x 5.25x 5.5x 5.75x */
813 0x0054, 0x0055, 0x0056, 0x0057,
814 /* 6x 6.25x 6.5x 6.75x */
815 0x0058, 0x0059, 0x005a, 0x005b,
816 /* 7x 7.25x 7.5x 7.75x */
817 0x005c, 0x005d, 0x005e, 0x005f,
818 /* 8x */
819 0x0060
820};
821
822/* Gain = .5 + bit[7:0] / 16 */
823static u8 hv7131r_gain[] = {
824 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
825 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
826 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
827 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
828 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
829 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
830 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
831 0x78 /* 8x */
832};
833
Joe Perches58aa68c2009-09-02 01:12:13 -0300834static struct i2c_reg_u8 soi968_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300835 {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
836 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
837 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
838 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
839 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
840 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
Brian Johnsone1430472009-09-02 12:39:41 -0300841 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300842 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
843 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
844 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
845 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
846};
847
Joe Perches58aa68c2009-09-02 01:12:13 -0300848static struct i2c_reg_u8 ov7660_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300849 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
850 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
851 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
852 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
853 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
854 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
855};
856
Joe Perches58aa68c2009-09-02 01:12:13 -0300857static struct i2c_reg_u8 ov7670_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300858 {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
859 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
860 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
861 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
862 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
863 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
864 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
865 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
866 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
867 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
868 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
869 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
870 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
871 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
872 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
873 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
874 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
875 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
876 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
877 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
878 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
879 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
880 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
881 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
882 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
883 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
884 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
885 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
886 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
887 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
888 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
889 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
890 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
891 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
892 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
893 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
894 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
895 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
896 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
897 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
898 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
899 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
900 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
901 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
902 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
903 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
904 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
905 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
906 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
907 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
908 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
909 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
910 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
911 {0x93, 0x00},
912};
913
Joe Perches58aa68c2009-09-02 01:12:13 -0300914static struct i2c_reg_u8 ov9650_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300915 {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
916 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
917 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
918 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
919 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
920 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
921 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
922 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
923 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
924 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
925 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
926 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
927 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
928 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
929 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
930 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
931 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
932 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
933 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
934 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
935 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
936 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
937 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
938 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
939 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
940 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
941 {0xaa, 0x92}, {0xab, 0x0a},
942};
943
Joe Perches58aa68c2009-09-02 01:12:13 -0300944static struct i2c_reg_u8 ov9655_init[] = {
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300945 {0x12, 0x80}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
946 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
947 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
948 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
949 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
950 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
951 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
952 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
953 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
954 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
955 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
956 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
957 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
958 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
959 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
960 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
Brian Johnson26e744b2009-07-19 05:52:58 -0300961 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300962 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
963 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
Brian Johnson26e744b2009-07-19 05:52:58 -0300964 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
Brian Johnsoncc2a8332010-03-16 13:58:28 -0300965 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
966 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
967 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
968 {0x04, 0x03}, {0x00, 0x13},
Brian Johnson26e744b2009-07-19 05:52:58 -0300969};
970
Joe Perches58aa68c2009-09-02 01:12:13 -0300971static struct i2c_reg_u16 mt9v112_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300972 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
973 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
974 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
975 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
976 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
977 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
978 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
979 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
980 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
981 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
982 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
983 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
984 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
985 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
986 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
987 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
988};
989
Joe Perches58aa68c2009-09-02 01:12:13 -0300990static struct i2c_reg_u16 mt9v111_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -0300991 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
992 {0x01, 0x0001}, {0x02, 0x0016}, {0x03, 0x01e1},
993 {0x04, 0x0281}, {0x05, 0x0004}, {0x07, 0x3002},
994 {0x21, 0x0000}, {0x25, 0x4024}, {0x26, 0xff03},
995 {0x27, 0xff10}, {0x2b, 0x7828}, {0x2c, 0xb43c},
996 {0x2d, 0xf0a0}, {0x2e, 0x0c64}, {0x2f, 0x0064},
997 {0x67, 0x4010}, {0x06, 0x301e}, {0x08, 0x0480},
998 {0x01, 0x0004}, {0x02, 0x0016}, {0x03, 0x01e6},
999 {0x04, 0x0286}, {0x05, 0x0004}, {0x06, 0x0000},
1000 {0x07, 0x3002}, {0x08, 0x0008}, {0x0c, 0x0000},
1001 {0x0d, 0x0000}, {0x0e, 0x0000}, {0x0f, 0x0000},
1002 {0x10, 0x0000}, {0x11, 0x0000}, {0x12, 0x00b0},
1003 {0x13, 0x007c}, {0x14, 0x0000}, {0x15, 0x0000},
1004 {0x16, 0x0000}, {0x17, 0x0000}, {0x18, 0x0000},
1005 {0x19, 0x0000}, {0x1a, 0x0000}, {0x1b, 0x0000},
1006 {0x1c, 0x0000}, {0x1d, 0x0000}, {0x30, 0x0000},
1007 {0x30, 0x0005}, {0x31, 0x0000}, {0x02, 0x0016},
1008 {0x03, 0x01e1}, {0x04, 0x0281}, {0x05, 0x0004},
1009 {0x06, 0x0000}, {0x07, 0x3002}, {0x06, 0x002d},
1010 {0x05, 0x0004}, {0x09, 0x0064}, {0x2b, 0x00a0},
1011 {0x2c, 0x00a0}, {0x2d, 0x00a0}, {0x2e, 0x00a0},
1012 {0x02, 0x0016}, {0x03, 0x01e1}, {0x04, 0x0281},
1013 {0x05, 0x0004}, {0x06, 0x002d}, {0x07, 0x3002},
1014 {0x0e, 0x0008}, {0x06, 0x002d}, {0x05, 0x0004},
1015};
1016
Joe Perches58aa68c2009-09-02 01:12:13 -03001017static struct i2c_reg_u16 mt9v011_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001018 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
1019 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
1020 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
1021 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
1022 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
1023 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
1024 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
1025 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
1026 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
1027 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
1028 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1029 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1030 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1031 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1032 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1033 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1034 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1035 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1036 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1037 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1038 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1039 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1040 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1041 {0x06, 0x0029}, {0x05, 0x0009},
1042};
1043
Joe Perches58aa68c2009-09-02 01:12:13 -03001044static struct i2c_reg_u16 mt9m001_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001045 {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e},
1046 {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501},
1047 {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002},
1048 {0x0a, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000},
1049 {0x1e, 0x8000}, {0x5f, 0x8904}, {0x60, 0x0000},
1050 {0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000},
1051 {0x64, 0x0000}, {0x20, 0x111d}, {0x06, 0x00f2},
1052 {0x05, 0x0013}, {0x09, 0x10f2}, {0x07, 0x0003},
1053 {0x2b, 0x002a}, {0x2d, 0x002a}, {0x2c, 0x002a},
1054 {0x2e, 0x0029}, {0x07, 0x0002},
1055};
1056
Joe Perches58aa68c2009-09-02 01:12:13 -03001057static struct i2c_reg_u16 mt9m111_init[] = {
Brian Johnson13a84fa2009-09-03 19:07:13 -03001058 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1059 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
Brian Johnson4d708a52009-09-03 19:10:15 -03001060 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1061 {0xf0, 0x0000},
Brian Johnson26e744b2009-07-19 05:52:58 -03001062};
1063
Brian Johnsone99ac542010-03-16 13:58:28 -03001064static struct i2c_reg_u16 mt9m112_init[] = {
1065 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1066 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1067 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1068 {0xf0, 0x0000},
1069};
1070
Joe Perches58aa68c2009-09-02 01:12:13 -03001071static struct i2c_reg_u8 hv7131r_init[] = {
Brian Johnson26e744b2009-07-19 05:52:58 -03001072 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1073 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1074 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1075 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1076 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1077 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1078 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1079 {0x23, 0x09}, {0x01, 0x08},
1080};
1081
Joe Perches58aa68c2009-09-02 01:12:13 -03001082static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001083{
1084 struct usb_device *dev = gspca_dev->dev;
1085 int result;
1086 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1087 0x00,
1088 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1089 reg,
1090 0x00,
1091 gspca_dev->usb_buf,
1092 length,
1093 500);
1094 if (unlikely(result < 0 || result != length)) {
1095 err("Read register failed 0x%02X", reg);
1096 return -EIO;
1097 }
1098 return 0;
1099}
1100
Joe Perches58aa68c2009-09-02 01:12:13 -03001101static int reg_w(struct gspca_dev *gspca_dev, u16 reg,
1102 const u8 *buffer, int length)
Brian Johnson26e744b2009-07-19 05:52:58 -03001103{
1104 struct usb_device *dev = gspca_dev->dev;
1105 int result;
1106 memcpy(gspca_dev->usb_buf, buffer, length);
1107 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1108 0x08,
1109 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1110 reg,
1111 0x00,
1112 gspca_dev->usb_buf,
1113 length,
1114 500);
1115 if (unlikely(result < 0 || result != length)) {
1116 err("Write register failed index 0x%02X", reg);
1117 return -EIO;
1118 }
1119 return 0;
1120}
1121
Joe Perches58aa68c2009-09-02 01:12:13 -03001122static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
Brian Johnson26e744b2009-07-19 05:52:58 -03001123{
1124 u8 data[1] = {value};
1125 return reg_w(gspca_dev, reg, data, 1);
1126}
1127
Joe Perches58aa68c2009-09-02 01:12:13 -03001128static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
Brian Johnson26e744b2009-07-19 05:52:58 -03001129{
1130 int i;
1131 reg_w(gspca_dev, 0x10c0, buffer, 8);
1132 for (i = 0; i < 5; i++) {
1133 reg_r(gspca_dev, 0x10c0, 1);
1134 if (gspca_dev->usb_buf[0] & 0x04) {
1135 if (gspca_dev->usb_buf[0] & 0x08)
Brian Johnson00b581e2009-07-23 05:55:43 -03001136 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001137 return 0;
1138 }
1139 msleep(1);
1140 }
Brian Johnson00b581e2009-07-23 05:55:43 -03001141 return -EIO;
Brian Johnson26e744b2009-07-19 05:52:58 -03001142}
1143
Joe Perches58aa68c2009-09-02 01:12:13 -03001144static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001145{
1146 struct sd *sd = (struct sd *) gspca_dev;
1147
1148 u8 row[8];
1149
1150 /*
1151 * from the point of view of the bridge, the length
1152 * includes the address
1153 */
1154 row[0] = 0x81 | (2 << 4);
1155 row[1] = sd->i2c_addr;
1156 row[2] = reg;
1157 row[3] = val;
1158 row[4] = 0x00;
1159 row[5] = 0x00;
1160 row[6] = 0x00;
1161 row[7] = 0x10;
1162
1163 return i2c_w(gspca_dev, row);
1164}
1165
Joe Perches58aa68c2009-09-02 01:12:13 -03001166static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001167{
1168 struct sd *sd = (struct sd *) gspca_dev;
1169 u8 row[8];
1170
1171 /*
1172 * from the point of view of the bridge, the length
1173 * includes the address
1174 */
1175 row[0] = 0x81 | (3 << 4);
1176 row[1] = sd->i2c_addr;
1177 row[2] = reg;
1178 row[3] = (val >> 8) & 0xff;
1179 row[4] = val & 0xff;
1180 row[5] = 0x00;
1181 row[6] = 0x00;
1182 row[7] = 0x10;
1183
1184 return i2c_w(gspca_dev, row);
1185}
1186
Jean-Francois Moine83955552009-12-12 06:58:01 -03001187static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *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 | (1 << 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[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001209 return 0;
1210}
1211
Jean-Francois Moine83955552009-12-12 06:58:01 -03001212static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
Brian Johnson26e744b2009-07-19 05:52:58 -03001213{
1214 struct sd *sd = (struct sd *) gspca_dev;
1215 u8 row[8];
1216
Brian Johnson00b581e2009-07-23 05:55:43 -03001217 row[0] = 0x81 | (1 << 4);
Brian Johnson26e744b2009-07-19 05:52:58 -03001218 row[1] = sd->i2c_addr;
1219 row[2] = reg;
1220 row[3] = 0;
1221 row[4] = 0;
1222 row[5] = 0;
1223 row[6] = 0;
1224 row[7] = 0x10;
Brian Johnson00b581e2009-07-23 05:55:43 -03001225 if (i2c_w(gspca_dev, row) < 0)
1226 return -EIO;
1227 row[0] = 0x81 | (2 << 4) | 0x02;
Brian Johnson26e744b2009-07-19 05:52:58 -03001228 row[2] = 0;
Brian Johnson00b581e2009-07-23 05:55:43 -03001229 if (i2c_w(gspca_dev, row) < 0)
1230 return -EIO;
1231 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1232 return -EIO;
1233 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
Brian Johnson26e744b2009-07-19 05:52:58 -03001234 return 0;
1235}
1236
1237static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
1238{
1239 int i;
1240 struct sd *sd = (struct sd *) gspca_dev;
1241
1242 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001243 if (i2c_w1(gspca_dev, ov9650_init[i].reg,
1244 ov9650_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001245 err("OV9650 sensor initialization failed");
1246 return -ENODEV;
1247 }
1248 }
1249 sd->hstart = 1;
1250 sd->vstart = 7;
1251 return 0;
1252}
1253
1254static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
1255{
1256 int i;
1257 struct sd *sd = (struct sd *) gspca_dev;
1258
1259 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001260 if (i2c_w1(gspca_dev, ov9655_init[i].reg,
1261 ov9655_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001262 err("OV9655 sensor initialization failed");
1263 return -ENODEV;
1264 }
1265 }
1266 /* disable hflip and vflip */
1267 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
Brian Johnsoncc2a8332010-03-16 13:58:28 -03001268 sd->hstart = 1;
1269 sd->vstart = 2;
Brian Johnson26e744b2009-07-19 05:52:58 -03001270 return 0;
1271}
1272
1273static int soi968_init_sensor(struct gspca_dev *gspca_dev)
1274{
1275 int i;
1276 struct sd *sd = (struct sd *) gspca_dev;
1277
1278 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001279 if (i2c_w1(gspca_dev, soi968_init[i].reg,
1280 soi968_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001281 err("SOI968 sensor initialization failed");
1282 return -ENODEV;
1283 }
1284 }
1285 /* disable hflip and vflip */
Brian Johnsone1430472009-09-02 12:39:41 -03001286 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << EXPOSURE_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001287 sd->hstart = 60;
1288 sd->vstart = 11;
1289 return 0;
1290}
1291
1292static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
1293{
1294 int i;
1295 struct sd *sd = (struct sd *) gspca_dev;
1296
1297 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001298 if (i2c_w1(gspca_dev, ov7660_init[i].reg,
1299 ov7660_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001300 err("OV7660 sensor initialization failed");
1301 return -ENODEV;
1302 }
1303 }
1304 /* disable hflip and vflip */
1305 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1306 sd->hstart = 1;
1307 sd->vstart = 1;
1308 return 0;
1309}
1310
1311static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
1312{
1313 int i;
1314 struct sd *sd = (struct sd *) gspca_dev;
1315
1316 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001317 if (i2c_w1(gspca_dev, ov7670_init[i].reg,
1318 ov7670_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001319 err("OV7670 sensor initialization failed");
1320 return -ENODEV;
1321 }
1322 }
1323 /* disable hflip and vflip */
1324 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1325 sd->hstart = 0;
1326 sd->vstart = 1;
1327 return 0;
1328}
1329
1330static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
1331{
1332 struct sd *sd = (struct sd *) gspca_dev;
1333 int i;
1334 u16 value;
1335 int ret;
1336
1337 sd->i2c_addr = 0x5d;
1338 ret = i2c_r2(gspca_dev, 0xff, &value);
1339 if ((ret == 0) && (value == 0x8243)) {
1340 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001341 if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
1342 mt9v011_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001343 err("MT9V011 sensor initialization failed");
1344 return -ENODEV;
1345 }
1346 }
1347 sd->hstart = 2;
1348 sd->vstart = 2;
1349 sd->sensor = SENSOR_MT9V011;
1350 info("MT9V011 sensor detected");
1351 return 0;
1352 }
1353
1354 sd->i2c_addr = 0x5c;
1355 i2c_w2(gspca_dev, 0x01, 0x0004);
1356 ret = i2c_r2(gspca_dev, 0xff, &value);
1357 if ((ret == 0) && (value == 0x823a)) {
1358 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001359 if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
1360 mt9v111_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001361 err("MT9V111 sensor initialization failed");
1362 return -ENODEV;
1363 }
1364 }
1365 sd->hstart = 2;
1366 sd->vstart = 2;
1367 sd->sensor = SENSOR_MT9V111;
1368 info("MT9V111 sensor detected");
1369 return 0;
1370 }
1371
1372 sd->i2c_addr = 0x5d;
1373 ret = i2c_w2(gspca_dev, 0xf0, 0x0000);
1374 if (ret < 0) {
1375 sd->i2c_addr = 0x48;
1376 i2c_w2(gspca_dev, 0xf0, 0x0000);
1377 }
1378 ret = i2c_r2(gspca_dev, 0x00, &value);
1379 if ((ret == 0) && (value == 0x1229)) {
1380 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001381 if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
1382 mt9v112_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001383 err("MT9V112 sensor initialization failed");
1384 return -ENODEV;
1385 }
1386 }
1387 sd->hstart = 6;
1388 sd->vstart = 2;
1389 sd->sensor = SENSOR_MT9V112;
1390 info("MT9V112 sensor detected");
1391 return 0;
1392 }
1393
1394 return -ENODEV;
1395}
1396
Brian Johnsone99ac542010-03-16 13:58:28 -03001397static int mt9m112_init_sensor(struct gspca_dev *gspca_dev)
1398{
1399 struct sd *sd = (struct sd *) gspca_dev;
1400 int i;
1401 for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
1402 if (i2c_w2(gspca_dev, mt9m112_init[i].reg,
1403 mt9m112_init[i].val) < 0) {
1404 err("MT9M112 sensor initialization failed");
1405 return -ENODEV;
1406 }
1407 }
1408 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << GAIN_IDX);
1409 sd->hstart = 0;
1410 sd->vstart = 2;
1411 return 0;
1412}
1413
Brian Johnson26e744b2009-07-19 05:52:58 -03001414static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
1415{
1416 struct sd *sd = (struct sd *) gspca_dev;
1417 int i;
1418 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001419 if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
1420 mt9m111_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001421 err("MT9M111 sensor initialization failed");
1422 return -ENODEV;
1423 }
1424 }
Brian Johnson13a84fa2009-09-03 19:07:13 -03001425 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << GAIN_IDX);
Brian Johnson26e744b2009-07-19 05:52:58 -03001426 sd->hstart = 0;
1427 sd->vstart = 2;
1428 return 0;
1429}
1430
1431static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1432{
1433 struct sd *sd = (struct sd *) gspca_dev;
1434 int i;
1435 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001436 if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
1437 mt9m001_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001438 err("MT9M001 sensor initialization failed");
1439 return -ENODEV;
1440 }
1441 }
1442 /* disable hflip and vflip */
1443 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1444 sd->hstart = 2;
1445 sd->vstart = 2;
1446 return 0;
1447}
1448
1449static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
1450{
1451 int i;
1452 struct sd *sd = (struct sd *) gspca_dev;
1453
1454 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
Joe Perches58aa68c2009-09-02 01:12:13 -03001455 if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
1456 hv7131r_init[i].val) < 0) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001457 err("HV7131R Sensor initialization failed");
1458 return -ENODEV;
1459 }
1460 }
1461 sd->hstart = 0;
1462 sd->vstart = 1;
1463 return 0;
1464}
1465
Brian Johnson26e744b2009-07-19 05:52:58 -03001466static int set_cmatrix(struct gspca_dev *gspca_dev)
1467{
1468 struct sd *sd = (struct sd *) gspca_dev;
1469 s32 hue_coord, hue_index = 180 + sd->hue;
1470 u8 cmatrix[21];
Brian Johnson26e744b2009-07-19 05:52:58 -03001471
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001472 memset(cmatrix, 0, sizeof cmatrix);
Brian Johnson26e744b2009-07-19 05:52:58 -03001473 cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
1474 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1475 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
1476 cmatrix[18] = sd->brightness - 0x80;
1477
1478 hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001479 cmatrix[6] = hue_coord;
1480 cmatrix[7] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001481
1482 hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001483 cmatrix[8] = hue_coord;
1484 cmatrix[9] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001485
1486 hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001487 cmatrix[10] = hue_coord;
1488 cmatrix[11] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001489
1490 hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001491 cmatrix[12] = hue_coord;
1492 cmatrix[13] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001493
1494 hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001495 cmatrix[14] = hue_coord;
1496 cmatrix[15] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001497
1498 hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001499 cmatrix[16] = hue_coord;
1500 cmatrix[17] = (hue_coord >> 8) & 0x0f;
Brian Johnson26e744b2009-07-19 05:52:58 -03001501
1502 return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
1503}
1504
1505static int set_gamma(struct gspca_dev *gspca_dev)
1506{
1507 struct sd *sd = (struct sd *) gspca_dev;
1508 u8 gamma[17];
1509 u8 gval = sd->gamma * 0xb8 / 0x100;
1510
1511
1512 gamma[0] = 0x0a;
1513 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1514 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1515 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1516 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1517 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1518 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1519 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1520 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1521 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1522 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1523 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1524 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1525 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1526 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1527 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1528 gamma[16] = 0xf5;
1529
1530 return reg_w(gspca_dev, 0x1190, gamma, 17);
1531}
1532
1533static int set_redblue(struct gspca_dev *gspca_dev)
1534{
1535 struct sd *sd = (struct sd *) gspca_dev;
1536 reg_w1(gspca_dev, 0x118c, sd->red);
1537 reg_w1(gspca_dev, 0x118f, sd->blue);
1538 return 0;
1539}
1540
1541static int set_hvflip(struct gspca_dev *gspca_dev)
1542{
Brian Johnson7ddaac72010-03-16 13:58:27 -03001543 u8 value, tslb, hflip, vflip;
Brian Johnson26e744b2009-07-19 05:52:58 -03001544 u16 value2;
1545 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001546
1547 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
1548 hflip = !sd->hflip;
1549 vflip = !sd->vflip;
1550 } else {
1551 hflip = sd->hflip;
1552 vflip = sd->vflip;
1553 }
1554
Brian Johnson26e744b2009-07-19 05:52:58 -03001555 switch (sd->sensor) {
1556 case SENSOR_OV9650:
1557 i2c_r1(gspca_dev, 0x1e, &value);
1558 value &= ~0x30;
1559 tslb = 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001560 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001561 value |= 0x20;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001562 if (vflip) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001563 value |= 0x10;
1564 tslb = 0x49;
1565 }
1566 i2c_w1(gspca_dev, 0x1e, value);
1567 i2c_w1(gspca_dev, 0x3a, tslb);
1568 break;
1569 case SENSOR_MT9V111:
1570 case SENSOR_MT9V011:
1571 i2c_r2(gspca_dev, 0x20, &value2);
1572 value2 &= ~0xc0a0;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001573 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001574 value2 |= 0x8080;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001575 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001576 value2 |= 0x4020;
1577 i2c_w2(gspca_dev, 0x20, value2);
1578 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03001579 case SENSOR_MT9M112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001580 case SENSOR_MT9M111:
1581 case SENSOR_MT9V112:
1582 i2c_r2(gspca_dev, 0x20, &value2);
1583 value2 &= ~0x0003;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001584 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001585 value2 |= 0x0002;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001586 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001587 value2 |= 0x0001;
1588 i2c_w2(gspca_dev, 0x20, value2);
1589 break;
1590 case SENSOR_HV7131R:
1591 i2c_r1(gspca_dev, 0x01, &value);
1592 value &= ~0x03;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001593 if (vflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001594 value |= 0x01;
Brian Johnson7ddaac72010-03-16 13:58:27 -03001595 if (hflip)
Brian Johnson26e744b2009-07-19 05:52:58 -03001596 value |= 0x02;
1597 i2c_w1(gspca_dev, 0x01, value);
1598 break;
1599 }
1600 return 0;
1601}
1602
1603static int set_exposure(struct gspca_dev *gspca_dev)
1604{
1605 struct sd *sd = (struct sd *) gspca_dev;
1606 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
1607 switch (sd->sensor) {
1608 case SENSOR_OV7660:
1609 case SENSOR_OV7670:
Brian Johnson26e744b2009-07-19 05:52:58 -03001610 case SENSOR_OV9655:
1611 case SENSOR_OV9650:
1612 exp[0] |= (3 << 4);
1613 exp[2] = 0x2d;
1614 exp[3] = sd->exposure & 0xff;
1615 exp[4] = sd->exposure >> 8;
1616 break;
1617 case SENSOR_MT9M001:
Brian Johnson26e744b2009-07-19 05:52:58 -03001618 case SENSOR_MT9V112:
1619 case SENSOR_MT9V111:
1620 case SENSOR_MT9V011:
1621 exp[0] |= (3 << 4);
1622 exp[2] = 0x09;
1623 exp[3] = sd->exposure >> 8;
1624 exp[4] = sd->exposure & 0xff;
1625 break;
1626 case SENSOR_HV7131R:
1627 exp[0] |= (4 << 4);
1628 exp[2] = 0x25;
German Galkine10f7312010-03-07 06:19:02 -03001629 exp[3] = (sd->exposure >> 5) & 0xff;
1630 exp[4] = (sd->exposure << 3) & 0xff;
1631 exp[5] = 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001632 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001633 default:
1634 return 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001635 }
1636 i2c_w(gspca_dev, exp);
1637 return 0;
1638}
1639
1640static int set_gain(struct gspca_dev *gspca_dev)
1641{
1642 struct sd *sd = (struct sd *) gspca_dev;
1643 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
1644 switch (sd->sensor) {
1645 case SENSOR_OV7660:
1646 case SENSOR_OV7670:
1647 case SENSOR_SOI968:
1648 case SENSOR_OV9655:
1649 case SENSOR_OV9650:
1650 gain[0] |= (2 << 4);
1651 gain[3] = ov_gain[sd->gain];
1652 break;
1653 case SENSOR_MT9V011:
1654 case SENSOR_MT9V111:
1655 gain[0] |= (3 << 4);
1656 gain[2] = 0x35;
1657 gain[3] = micron1_gain[sd->gain] >> 8;
1658 gain[4] = micron1_gain[sd->gain] & 0xff;
1659 break;
1660 case SENSOR_MT9V112:
Brian Johnson26e744b2009-07-19 05:52:58 -03001661 gain[0] |= (3 << 4);
1662 gain[2] = 0x2f;
1663 gain[3] = micron1_gain[sd->gain] >> 8;
1664 gain[4] = micron1_gain[sd->gain] & 0xff;
1665 break;
1666 case SENSOR_MT9M001:
1667 gain[0] |= (3 << 4);
1668 gain[2] = 0x2f;
1669 gain[3] = micron2_gain[sd->gain] >> 8;
1670 gain[4] = micron2_gain[sd->gain] & 0xff;
1671 break;
1672 case SENSOR_HV7131R:
1673 gain[0] |= (2 << 4);
1674 gain[2] = 0x30;
1675 gain[3] = hv7131r_gain[sd->gain];
1676 break;
Brian Johnsone1430472009-09-02 12:39:41 -03001677 default:
1678 return 0;
Brian Johnson26e744b2009-07-19 05:52:58 -03001679 }
1680 i2c_w(gspca_dev, gain);
1681 return 0;
1682}
1683
1684static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val)
1685{
1686 struct sd *sd = (struct sd *) gspca_dev;
1687
1688 sd->brightness = val;
1689 if (gspca_dev->streaming)
1690 return set_cmatrix(gspca_dev);
1691 return 0;
1692}
1693
1694static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val)
1695{
1696 struct sd *sd = (struct sd *) gspca_dev;
1697 *val = sd->brightness;
1698 return 0;
1699}
1700
1701
1702static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val)
1703{
1704 struct sd *sd = (struct sd *) gspca_dev;
1705
1706 sd->contrast = val;
1707 if (gspca_dev->streaming)
1708 return set_cmatrix(gspca_dev);
1709 return 0;
1710}
1711
1712static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val)
1713{
1714 struct sd *sd = (struct sd *) gspca_dev;
1715 *val = sd->contrast;
1716 return 0;
1717}
1718
1719static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val)
1720{
1721 struct sd *sd = (struct sd *) gspca_dev;
1722
1723 sd->saturation = val;
1724 if (gspca_dev->streaming)
1725 return set_cmatrix(gspca_dev);
1726 return 0;
1727}
1728
1729static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val)
1730{
1731 struct sd *sd = (struct sd *) gspca_dev;
1732 *val = sd->saturation;
1733 return 0;
1734}
1735
1736static int sd_sethue(struct gspca_dev *gspca_dev, s32 val)
1737{
1738 struct sd *sd = (struct sd *) gspca_dev;
1739
1740 sd->hue = val;
1741 if (gspca_dev->streaming)
1742 return set_cmatrix(gspca_dev);
1743 return 0;
1744}
1745
1746static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val)
1747{
1748 struct sd *sd = (struct sd *) gspca_dev;
1749 *val = sd->hue;
1750 return 0;
1751}
1752
1753static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val)
1754{
1755 struct sd *sd = (struct sd *) gspca_dev;
1756
1757 sd->gamma = val;
1758 if (gspca_dev->streaming)
1759 return set_gamma(gspca_dev);
1760 return 0;
1761}
1762
1763static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val)
1764{
1765 struct sd *sd = (struct sd *) gspca_dev;
1766 *val = sd->gamma;
1767 return 0;
1768}
1769
1770static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val)
1771{
1772 struct sd *sd = (struct sd *) gspca_dev;
1773
1774 sd->red = val;
1775 if (gspca_dev->streaming)
1776 return set_redblue(gspca_dev);
1777 return 0;
1778}
1779
1780static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val)
1781{
1782 struct sd *sd = (struct sd *) gspca_dev;
1783 *val = sd->red;
1784 return 0;
1785}
1786
1787static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val)
1788{
1789 struct sd *sd = (struct sd *) gspca_dev;
1790
1791 sd->blue = val;
1792 if (gspca_dev->streaming)
1793 return set_redblue(gspca_dev);
1794 return 0;
1795}
1796
1797static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val)
1798{
1799 struct sd *sd = (struct sd *) gspca_dev;
1800 *val = sd->blue;
1801 return 0;
1802}
1803
1804static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val)
1805{
1806 struct sd *sd = (struct sd *) gspca_dev;
1807
1808 sd->hflip = val;
1809 if (gspca_dev->streaming)
1810 return set_hvflip(gspca_dev);
1811 return 0;
1812}
1813
1814static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val)
1815{
1816 struct sd *sd = (struct sd *) gspca_dev;
1817 *val = sd->hflip;
1818 return 0;
1819}
1820
1821static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val)
1822{
1823 struct sd *sd = (struct sd *) gspca_dev;
1824
1825 sd->vflip = val;
1826 if (gspca_dev->streaming)
1827 return set_hvflip(gspca_dev);
1828 return 0;
1829}
1830
1831static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val)
1832{
1833 struct sd *sd = (struct sd *) gspca_dev;
1834 *val = sd->vflip;
1835 return 0;
1836}
1837
1838static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val)
1839{
1840 struct sd *sd = (struct sd *) gspca_dev;
1841
1842 sd->exposure = val;
1843 if (gspca_dev->streaming)
1844 return set_exposure(gspca_dev);
1845 return 0;
1846}
1847
1848static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val)
1849{
1850 struct sd *sd = (struct sd *) gspca_dev;
1851 *val = sd->exposure;
1852 return 0;
1853}
1854
1855static int sd_setgain(struct gspca_dev *gspca_dev, s32 val)
1856{
1857 struct sd *sd = (struct sd *) gspca_dev;
1858
1859 sd->gain = val;
1860 if (gspca_dev->streaming)
1861 return set_gain(gspca_dev);
1862 return 0;
1863}
1864
1865static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val)
1866{
1867 struct sd *sd = (struct sd *) gspca_dev;
1868 *val = sd->gain;
1869 return 0;
1870}
1871
1872static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val)
1873{
1874 struct sd *sd = (struct sd *) gspca_dev;
1875 sd->auto_exposure = val;
1876 return 0;
1877}
1878
1879static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val)
1880{
1881 struct sd *sd = (struct sd *) gspca_dev;
1882 *val = sd->auto_exposure;
1883 return 0;
1884}
1885
1886#ifdef CONFIG_VIDEO_ADV_DEBUG
1887static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1888 struct v4l2_dbg_register *reg)
1889{
1890 struct sd *sd = (struct sd *) gspca_dev;
1891 switch (reg->match.type) {
1892 case V4L2_CHIP_MATCH_HOST:
1893 if (reg->match.addr != 0)
1894 return -EINVAL;
1895 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1896 return -EINVAL;
1897 if (reg_r(gspca_dev, reg->reg, 1) < 0)
1898 return -EINVAL;
1899 reg->val = gspca_dev->usb_buf[0];
1900 return 0;
1901 case V4L2_CHIP_MATCH_I2C_ADDR:
1902 if (reg->match.addr != sd->i2c_addr)
1903 return -EINVAL;
1904 if (sd->sensor >= SENSOR_MT9V011 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001905 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001906 if (i2c_r2(gspca_dev, reg->reg, (u16 *)&reg->val) < 0)
1907 return -EINVAL;
1908 } else {
1909 if (i2c_r1(gspca_dev, reg->reg, (u8 *)&reg->val) < 0)
1910 return -EINVAL;
1911 }
1912 return 0;
1913 }
1914 return -EINVAL;
1915}
1916
1917static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1918 struct v4l2_dbg_register *reg)
1919{
1920 struct sd *sd = (struct sd *) gspca_dev;
1921 switch (reg->match.type) {
1922 case V4L2_CHIP_MATCH_HOST:
1923 if (reg->match.addr != 0)
1924 return -EINVAL;
1925 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1926 return -EINVAL;
1927 if (reg_w1(gspca_dev, reg->reg, reg->val) < 0)
1928 return -EINVAL;
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 &&
Brian Johnsone99ac542010-03-16 13:58:28 -03001934 sd->sensor <= SENSOR_MT9M112) {
Brian Johnson26e744b2009-07-19 05:52:58 -03001935 if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0)
1936 return -EINVAL;
1937 } else {
1938 if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0)
1939 return -EINVAL;
1940 }
1941 return 0;
1942 }
1943 return -EINVAL;
1944}
1945#endif
1946
1947static int sd_chip_ident(struct gspca_dev *gspca_dev,
1948 struct v4l2_dbg_chip_ident *chip)
1949{
1950 struct sd *sd = (struct sd *) gspca_dev;
1951
1952 switch (chip->match.type) {
1953 case V4L2_CHIP_MATCH_HOST:
1954 if (chip->match.addr != 0)
1955 return -EINVAL;
1956 chip->revision = 0;
1957 chip->ident = V4L2_IDENT_SN9C20X;
1958 return 0;
1959 case V4L2_CHIP_MATCH_I2C_ADDR:
1960 if (chip->match.addr != sd->i2c_addr)
1961 return -EINVAL;
1962 chip->revision = 0;
1963 chip->ident = i2c_ident[sd->sensor];
1964 return 0;
1965 }
1966 return -EINVAL;
1967}
1968
1969static int sd_config(struct gspca_dev *gspca_dev,
1970 const struct usb_device_id *id)
1971{
1972 struct sd *sd = (struct sd *) gspca_dev;
1973 struct cam *cam;
1974
1975 cam = &gspca_dev->cam;
1976
1977 sd->sensor = (id->driver_info >> 8) & 0xff;
1978 sd->i2c_addr = id->driver_info & 0xff;
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03001979 sd->flags = (id->driver_info >> 16) & 0xff;
Brian Johnson26e744b2009-07-19 05:52:58 -03001980
1981 switch (sd->sensor) {
Brian Johnsone99ac542010-03-16 13:58:28 -03001982 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03001983 case SENSOR_MT9M111:
Brian Johnson26e744b2009-07-19 05:52:58 -03001984 case SENSOR_OV9650:
Brian Johnsone8b7acc2009-09-02 13:14:41 -03001985 case SENSOR_SOI968:
Brian Johnson26e744b2009-07-19 05:52:58 -03001986 cam->cam_mode = sxga_mode;
1987 cam->nmodes = ARRAY_SIZE(sxga_mode);
1988 break;
1989 default:
1990 cam->cam_mode = vga_mode;
1991 cam->nmodes = ARRAY_SIZE(vga_mode);
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03001992 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03001993 }
1994
1995 sd->old_step = 0;
1996 sd->older_step = 0;
1997 sd->exposure_step = 16;
1998
1999 sd->brightness = BRIGHTNESS_DEFAULT;
2000 sd->contrast = CONTRAST_DEFAULT;
2001 sd->saturation = SATURATION_DEFAULT;
2002 sd->hue = HUE_DEFAULT;
2003 sd->gamma = GAMMA_DEFAULT;
2004 sd->red = RED_DEFAULT;
2005 sd->blue = BLUE_DEFAULT;
2006
2007 sd->hflip = HFLIP_DEFAULT;
2008 sd->vflip = VFLIP_DEFAULT;
2009 sd->exposure = EXPOSURE_DEFAULT;
2010 sd->gain = GAIN_DEFAULT;
2011 sd->auto_exposure = AUTO_EXPOSURE_DEFAULT;
2012
2013 sd->quality = 95;
2014
Brian Johnson26e744b2009-07-19 05:52:58 -03002015 return 0;
2016}
2017
2018static int sd_init(struct gspca_dev *gspca_dev)
2019{
2020 struct sd *sd = (struct sd *) gspca_dev;
2021 int i;
2022 u8 value;
2023 u8 i2c_init[9] =
2024 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
2025
2026 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
2027 value = bridge_init[i][1];
2028 if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
2029 err("Device initialization failed");
2030 return -ENODEV;
2031 }
2032 }
2033
Brian Johnson0c045eb2010-03-16 13:58:27 -03002034 if (sd->flags & LED_REVERSE)
2035 reg_w1(gspca_dev, 0x1006, 0x00);
2036 else
2037 reg_w1(gspca_dev, 0x1006, 0x20);
2038
Brian Johnson26e744b2009-07-19 05:52:58 -03002039 if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
2040 err("Device initialization failed");
2041 return -ENODEV;
2042 }
2043
2044 switch (sd->sensor) {
2045 case SENSOR_OV9650:
2046 if (ov9650_init_sensor(gspca_dev) < 0)
2047 return -ENODEV;
2048 info("OV9650 sensor detected");
2049 break;
2050 case SENSOR_OV9655:
2051 if (ov9655_init_sensor(gspca_dev) < 0)
2052 return -ENODEV;
2053 info("OV9655 sensor detected");
2054 break;
2055 case SENSOR_SOI968:
2056 if (soi968_init_sensor(gspca_dev) < 0)
2057 return -ENODEV;
2058 info("SOI968 sensor detected");
2059 break;
2060 case SENSOR_OV7660:
2061 if (ov7660_init_sensor(gspca_dev) < 0)
2062 return -ENODEV;
2063 info("OV7660 sensor detected");
2064 break;
2065 case SENSOR_OV7670:
2066 if (ov7670_init_sensor(gspca_dev) < 0)
2067 return -ENODEV;
2068 info("OV7670 sensor detected");
2069 break;
2070 case SENSOR_MT9VPRB:
2071 if (mt9v_init_sensor(gspca_dev) < 0)
2072 return -ENODEV;
2073 break;
2074 case SENSOR_MT9M111:
2075 if (mt9m111_init_sensor(gspca_dev) < 0)
2076 return -ENODEV;
2077 info("MT9M111 sensor detected");
2078 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002079 case SENSOR_MT9M112:
2080 if (mt9m112_init_sensor(gspca_dev) < 0)
2081 return -ENODEV;
2082 info("MT9M112 sensor detected");
2083 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002084 case SENSOR_MT9M001:
2085 if (mt9m001_init_sensor(gspca_dev) < 0)
2086 return -ENODEV;
2087 info("MT9M001 sensor detected");
2088 break;
2089 case SENSOR_HV7131R:
2090 if (hv7131r_init_sensor(gspca_dev) < 0)
2091 return -ENODEV;
2092 info("HV7131R sensor detected");
2093 break;
2094 default:
2095 info("Unsupported Sensor");
2096 return -ENODEV;
2097 }
2098
2099 return 0;
2100}
2101
2102static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
2103{
2104 struct sd *sd = (struct sd *) gspca_dev;
2105 u8 value;
2106 switch (sd->sensor) {
Brian Johnsone8b7acc2009-09-02 13:14:41 -03002107 case SENSOR_SOI968:
2108 if (mode & MODE_SXGA) {
2109 i2c_w1(gspca_dev, 0x17, 0x1d);
2110 i2c_w1(gspca_dev, 0x18, 0xbd);
2111 i2c_w1(gspca_dev, 0x19, 0x01);
2112 i2c_w1(gspca_dev, 0x1a, 0x81);
2113 i2c_w1(gspca_dev, 0x12, 0x00);
2114 sd->hstart = 140;
2115 sd->vstart = 19;
2116 } else {
2117 i2c_w1(gspca_dev, 0x17, 0x13);
2118 i2c_w1(gspca_dev, 0x18, 0x63);
2119 i2c_w1(gspca_dev, 0x19, 0x01);
2120 i2c_w1(gspca_dev, 0x1a, 0x79);
2121 i2c_w1(gspca_dev, 0x12, 0x40);
2122 sd->hstart = 60;
2123 sd->vstart = 11;
2124 }
2125 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002126 case SENSOR_OV9650:
2127 if (mode & MODE_SXGA) {
2128 i2c_w1(gspca_dev, 0x17, 0x1b);
2129 i2c_w1(gspca_dev, 0x18, 0xbc);
2130 i2c_w1(gspca_dev, 0x19, 0x01);
2131 i2c_w1(gspca_dev, 0x1a, 0x82);
2132 i2c_r1(gspca_dev, 0x12, &value);
2133 i2c_w1(gspca_dev, 0x12, value & 0x07);
2134 } else {
2135 i2c_w1(gspca_dev, 0x17, 0x24);
2136 i2c_w1(gspca_dev, 0x18, 0xc5);
2137 i2c_w1(gspca_dev, 0x19, 0x00);
2138 i2c_w1(gspca_dev, 0x1a, 0x3c);
2139 i2c_r1(gspca_dev, 0x12, &value);
2140 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
2141 }
2142 break;
Brian Johnsone99ac542010-03-16 13:58:28 -03002143 case SENSOR_MT9M112:
Brian Johnson4d708a52009-09-03 19:10:15 -03002144 case SENSOR_MT9M111:
2145 if (mode & MODE_SXGA) {
2146 i2c_w2(gspca_dev, 0xf0, 0x0002);
2147 i2c_w2(gspca_dev, 0xc8, 0x970b);
2148 i2c_w2(gspca_dev, 0xf0, 0x0000);
2149 } else {
2150 i2c_w2(gspca_dev, 0xf0, 0x0002);
2151 i2c_w2(gspca_dev, 0xc8, 0x8000);
2152 i2c_w2(gspca_dev, 0xf0, 0x0000);
2153 }
2154 break;
Brian Johnson26e744b2009-07-19 05:52:58 -03002155 }
2156}
2157
2158#define HW_WIN(mode, hstart, vstart) \
Jean-Francois Moine83955552009-12-12 06:58:01 -03002159((const u8 []){hstart, 0, vstart, 0, \
Brian Johnson26e744b2009-07-19 05:52:58 -03002160(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2161(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2162
2163#define CLR_WIN(width, height) \
2164((const u8 [])\
2165{0, width >> 2, 0, height >> 1,\
2166((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2167
2168static int sd_start(struct gspca_dev *gspca_dev)
2169{
2170 struct sd *sd = (struct sd *) gspca_dev;
2171 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2172 int width = gspca_dev->width;
2173 int height = gspca_dev->height;
2174 u8 fmt, scale = 0;
2175
2176 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
2177 if (sd->jpeg_hdr == NULL)
2178 return -ENOMEM;
2179
2180 jpeg_define(sd->jpeg_hdr, height, width,
2181 0x21);
2182 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2183
2184 if (mode & MODE_RAW)
2185 fmt = 0x2d;
2186 else if (mode & MODE_JPEG)
2187 fmt = 0x2c;
2188 else
2189 fmt = 0x2f;
2190
2191 switch (mode & 0x0f) {
2192 case 3:
2193 scale = 0xc0;
2194 info("Set 1280x1024");
2195 break;
2196 case 2:
2197 scale = 0x80;
2198 info("Set 640x480");
2199 break;
2200 case 1:
2201 scale = 0x90;
2202 info("Set 320x240");
2203 break;
2204 case 0:
2205 scale = 0xa0;
2206 info("Set 160x120");
2207 break;
2208 }
2209
2210 configure_sensor_output(gspca_dev, mode);
2211 reg_w(gspca_dev, 0x1100, sd->jpeg_hdr + JPEG_QT0_OFFSET, 64);
2212 reg_w(gspca_dev, 0x1140, sd->jpeg_hdr + JPEG_QT1_OFFSET, 64);
2213 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2214 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2215 reg_w1(gspca_dev, 0x1189, scale);
2216 reg_w1(gspca_dev, 0x10e0, fmt);
2217
2218 set_cmatrix(gspca_dev);
2219 set_gamma(gspca_dev);
2220 set_redblue(gspca_dev);
2221 set_gain(gspca_dev);
2222 set_exposure(gspca_dev);
2223 set_hvflip(gspca_dev);
2224
Brian Johnson0c045eb2010-03-16 13:58:27 -03002225 reg_w1(gspca_dev, 0x1007, 0x20);
2226
Brian Johnson26e744b2009-07-19 05:52:58 -03002227 reg_r(gspca_dev, 0x1061, 1);
2228 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
2229 return 0;
2230}
2231
2232static void sd_stopN(struct gspca_dev *gspca_dev)
2233{
Brian Johnson0c045eb2010-03-16 13:58:27 -03002234 reg_w1(gspca_dev, 0x1007, 0x00);
2235
Brian Johnson26e744b2009-07-19 05:52:58 -03002236 reg_r(gspca_dev, 0x1061, 1);
2237 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2238}
2239
2240static void sd_stop0(struct gspca_dev *gspca_dev)
2241{
2242 struct sd *sd = (struct sd *) gspca_dev;
2243 kfree(sd->jpeg_hdr);
2244}
2245
Brian Johnsone1430472009-09-02 12:39:41 -03002246static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
Brian Johnson26e744b2009-07-19 05:52:58 -03002247{
2248 struct sd *sd = (struct sd *) gspca_dev;
Brian Johnsone1430472009-09-02 12:39:41 -03002249 s16 new_exp;
Brian Johnson26e744b2009-07-19 05:52:58 -03002250
2251 /*
2252 * some hardcoded values are present
2253 * like those for maximal/minimal exposure
2254 * and exposure steps
2255 */
2256 if (avg_lum < MIN_AVG_LUM) {
2257 if (sd->exposure > 0x1770)
2258 return;
2259
2260 new_exp = sd->exposure + sd->exposure_step;
2261 if (new_exp > 0x1770)
2262 new_exp = 0x1770;
2263 if (new_exp < 0x10)
2264 new_exp = 0x10;
2265 sd->exposure = new_exp;
2266 set_exposure(gspca_dev);
2267
2268 sd->older_step = sd->old_step;
2269 sd->old_step = 1;
2270
2271 if (sd->old_step ^ sd->older_step)
2272 sd->exposure_step /= 2;
2273 else
2274 sd->exposure_step += 2;
2275 }
2276 if (avg_lum > MAX_AVG_LUM) {
2277 if (sd->exposure < 0x10)
2278 return;
2279 new_exp = sd->exposure - sd->exposure_step;
2280 if (new_exp > 0x1700)
2281 new_exp = 0x1770;
2282 if (new_exp < 0x10)
2283 new_exp = 0x10;
2284 sd->exposure = new_exp;
2285 set_exposure(gspca_dev);
2286 sd->older_step = sd->old_step;
2287 sd->old_step = 0;
2288
2289 if (sd->old_step ^ sd->older_step)
2290 sd->exposure_step /= 2;
2291 else
2292 sd->exposure_step += 2;
2293 }
2294}
2295
Brian Johnsone1430472009-09-02 12:39:41 -03002296static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2297{
2298 struct sd *sd = (struct sd *) gspca_dev;
2299
2300 if (avg_lum < MIN_AVG_LUM) {
2301 if (sd->gain + 1 <= 28) {
2302 sd->gain++;
2303 set_gain(gspca_dev);
2304 }
2305 }
2306 if (avg_lum > MAX_AVG_LUM) {
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002307 if (sd->gain > 0) {
Brian Johnsone1430472009-09-02 12:39:41 -03002308 sd->gain--;
2309 set_gain(gspca_dev);
2310 }
2311 }
2312}
2313
2314static void sd_dqcallback(struct gspca_dev *gspca_dev)
2315{
2316 struct sd *sd = (struct sd *) gspca_dev;
2317 int avg_lum;
2318
2319 if (!sd->auto_exposure)
2320 return;
2321
2322 avg_lum = atomic_read(&sd->avg_lum);
2323 if (sd->sensor == SENSOR_SOI968)
2324 do_autogain(gspca_dev, avg_lum);
2325 else
2326 do_autoexposure(gspca_dev, avg_lum);
2327}
2328
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002329#ifdef CONFIG_INPUT
2330static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2331 u8 *data, /* interrupt packet */
2332 int len) /* interrupt packet length */
2333{
2334 struct sd *sd = (struct sd *) gspca_dev;
2335 int ret = -EINVAL;
2336 if (sd->flags & HAS_BUTTON && len == 1) {
2337 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2338 input_sync(gspca_dev->input_dev);
2339 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2340 input_sync(gspca_dev->input_dev);
2341 ret = 0;
2342 }
2343 return ret;
2344}
2345#endif
2346
Brian Johnson26e744b2009-07-19 05:52:58 -03002347static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Brian Johnson26e744b2009-07-19 05:52:58 -03002348 u8 *data, /* isoc packet */
2349 int len) /* iso packet length */
2350{
2351 struct sd *sd = (struct sd *) gspca_dev;
2352 int avg_lum;
Jean-Francois Moinede2d1542009-12-19 07:03:43 -03002353 static u8 frame_header[] =
Brian Johnson26e744b2009-07-19 05:52:58 -03002354 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
2355 if (len == 64 && memcmp(data, frame_header, 6) == 0) {
2356 avg_lum = ((data[35] >> 2) & 3) |
2357 (data[20] << 2) |
2358 (data[19] << 10);
2359 avg_lum += ((data[35] >> 4) & 3) |
2360 (data[22] << 2) |
2361 (data[21] << 10);
2362 avg_lum += ((data[35] >> 6) & 3) |
2363 (data[24] << 2) |
2364 (data[23] << 10);
2365 avg_lum += (data[36] & 3) |
2366 (data[26] << 2) |
2367 (data[25] << 10);
2368 avg_lum += ((data[36] >> 2) & 3) |
2369 (data[28] << 2) |
2370 (data[27] << 10);
2371 avg_lum += ((data[36] >> 4) & 3) |
2372 (data[30] << 2) |
2373 (data[29] << 10);
2374 avg_lum += ((data[36] >> 6) & 3) |
2375 (data[32] << 2) |
2376 (data[31] << 10);
2377 avg_lum += ((data[44] >> 4) & 3) |
2378 (data[34] << 2) |
2379 (data[33] << 10);
2380 avg_lum >>= 9;
2381 atomic_set(&sd->avg_lum, avg_lum);
2382 gspca_frame_add(gspca_dev, LAST_PACKET,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002383 data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002384 return;
2385 }
2386 if (gspca_dev->last_packet_type == LAST_PACKET) {
2387 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2388 & MODE_JPEG) {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002389 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002390 sd->jpeg_hdr, JPEG_HDR_SZ);
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002391 gspca_frame_add(gspca_dev, INTER_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002392 data, len);
2393 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002394 gspca_frame_add(gspca_dev, FIRST_PACKET,
Brian Johnson26e744b2009-07-19 05:52:58 -03002395 data, len);
2396 }
2397 } else {
Jean-Francois Moine76dd2722009-11-13 09:21:03 -03002398 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Brian Johnson26e744b2009-07-19 05:52:58 -03002399 }
2400}
2401
2402/* sub-driver description */
2403static const struct sd_desc sd_desc = {
2404 .name = MODULE_NAME,
2405 .ctrls = sd_ctrls,
2406 .nctrls = ARRAY_SIZE(sd_ctrls),
2407 .config = sd_config,
2408 .init = sd_init,
2409 .start = sd_start,
2410 .stopN = sd_stopN,
2411 .stop0 = sd_stop0,
2412 .pkt_scan = sd_pkt_scan,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002413#ifdef CONFIG_INPUT
2414 .int_pkt_scan = sd_int_pkt_scan,
2415#endif
Brian Johnsone1430472009-09-02 12:39:41 -03002416 .dq_callback = sd_dqcallback,
Brian Johnson26e744b2009-07-19 05:52:58 -03002417#ifdef CONFIG_VIDEO_ADV_DEBUG
2418 .set_register = sd_dbg_s_register,
2419 .get_register = sd_dbg_g_register,
2420#endif
2421 .get_chip_ident = sd_chip_ident,
2422};
2423
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002424#define SN9C20X(sensor, i2c_addr, flags) \
Brian Johnson0c045eb2010-03-16 13:58:27 -03002425 .driver_info = ((flags & 0xff) << 16) \
Brian Johnson26e744b2009-07-19 05:52:58 -03002426 | (SENSOR_ ## sensor << 8) \
2427 | (i2c_addr)
2428
2429static const __devinitdata struct usb_device_id device_table[] = {
2430 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2431 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2432 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002433 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson0c045eb2010-03-16 13:58:27 -03002434 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30,
2435 (HAS_BUTTON | LED_REVERSE))},
Brian Johnson7ddaac72010-03-16 13:58:27 -03002436 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, FLIP_DETECT)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002437 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2438 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2439 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2440 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
2441 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, 0)},
2442 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2443 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2444 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2445 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002446 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, HAS_BUTTON)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002447 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002448 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2449 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2450 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2451 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
2452 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002453 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, HAS_BUTTON)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002454 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2455 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2456 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2457 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
Brian Johnsone99ac542010-03-16 13:58:28 -03002458 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2459 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002460 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2461 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2462 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2463 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002464 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, HAS_BUTTON)},
Brian Johnson26e744b2009-07-19 05:52:58 -03002465 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2466 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2467 {}
2468};
2469MODULE_DEVICE_TABLE(usb, device_table);
2470
2471/* -- device connect -- */
2472static int sd_probe(struct usb_interface *intf,
2473 const struct usb_device_id *id)
2474{
2475 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2476 THIS_MODULE);
2477}
2478
Brian Johnson26e744b2009-07-19 05:52:58 -03002479static struct usb_driver sd_driver = {
2480 .name = MODULE_NAME,
2481 .id_table = device_table,
2482 .probe = sd_probe,
Mauro Carvalho Chehaba39db272010-05-18 00:49:44 -03002483 .disconnect = gspca_disconnect,
Brian Johnson26e744b2009-07-19 05:52:58 -03002484#ifdef CONFIG_PM
2485 .suspend = gspca_suspend,
2486 .resume = gspca_resume,
2487 .reset_resume = gspca_resume,
2488#endif
2489};
2490
2491/* -- module insert / remove -- */
2492static int __init sd_mod_init(void)
2493{
2494 int ret;
2495 ret = usb_register(&sd_driver);
2496 if (ret < 0)
2497 return ret;
2498 info("registered");
2499 return 0;
2500}
2501static void __exit sd_mod_exit(void)
2502{
2503 usb_deregister(&sd_driver);
2504 info("deregistered");
2505}
2506
2507module_init(sd_mod_init);
2508module_exit(sd_mod_exit);