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