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