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