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