2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define MODULE_NAME "sonixj"
25 #define QUANT_VAL 4 /* quantization table */
28 #define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0)
30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31 MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
32 MODULE_LICENSE("GPL");
34 /* specific webcam descriptor */
36 struct gspca_dev gspca_dev; /* !! must be the first item */
48 u8 vflip; /* ov7630 only */
49 u8 infrared; /* mi0360 only */
52 #define AG_CNT_START 13
55 #define BRIDGE_SN9C102P 0
56 #define BRIDGE_SN9C105 1
57 #define BRIDGE_SN9C110 2
58 #define BRIDGE_SN9C120 3
59 #define BRIDGE_SN9C325 4
60 u8 sensor; /* Type of image sensor chip */
61 #define SENSOR_HV7131R 0
62 #define SENSOR_MI0360 1
63 #define SENSOR_MO4000 2
64 #define SENSOR_OM6802 3
65 #define SENSOR_OV7630 4
66 #define SENSOR_OV7648 5
67 #define SENSOR_OV7660 6
71 /* V4L2 controls supported by the driver */
72 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
73 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
74 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
75 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
76 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
77 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
78 static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val);
79 static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
80 static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
81 static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
82 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
83 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
84 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val);
91 static struct ctrl sd_ctrls[] = {
94 .id = V4L2_CID_BRIGHTNESS,
95 .type = V4L2_CTRL_TYPE_INTEGER,
98 #define BRIGHTNESS_MAX 0xffff
99 .maximum = BRIGHTNESS_MAX,
101 #define BRIGHTNESS_DEF 0x8000
102 .default_value = BRIGHTNESS_DEF,
104 .set = sd_setbrightness,
105 .get = sd_getbrightness,
109 .id = V4L2_CID_CONTRAST,
110 .type = V4L2_CTRL_TYPE_INTEGER,
113 #define CONTRAST_MAX 127
114 .maximum = CONTRAST_MAX,
116 #define CONTRAST_DEF 63
117 .default_value = CONTRAST_DEF,
119 .set = sd_setcontrast,
120 .get = sd_getcontrast,
124 .id = V4L2_CID_SATURATION,
125 .type = V4L2_CTRL_TYPE_INTEGER,
131 .default_value = COLOR_DEF,
138 .id = V4L2_CID_BLUE_BALANCE,
139 .type = V4L2_CTRL_TYPE_INTEGER,
140 .name = "Blue Balance",
144 #define BLUE_BALANCE_DEF 32
145 .default_value = BLUE_BALANCE_DEF,
147 .set = sd_setblue_balance,
148 .get = sd_getblue_balance,
152 .id = V4L2_CID_RED_BALANCE,
153 .type = V4L2_CTRL_TYPE_INTEGER,
154 .name = "Red Balance",
158 #define RED_BALANCE_DEF 32
159 .default_value = RED_BALANCE_DEF,
161 .set = sd_setred_balance,
162 .get = sd_getred_balance,
166 .id = V4L2_CID_GAMMA,
167 .type = V4L2_CTRL_TYPE_INTEGER,
173 .default_value = GAMMA_DEF,
178 #define AUTOGAIN_IDX 5
181 .id = V4L2_CID_AUTOGAIN,
182 .type = V4L2_CTRL_TYPE_BOOLEAN,
187 #define AUTOGAIN_DEF 1
188 .default_value = AUTOGAIN_DEF,
190 .set = sd_setautogain,
191 .get = sd_getautogain,
197 .id = V4L2_CID_VFLIP,
198 .type = V4L2_CTRL_TYPE_BOOLEAN,
204 .default_value = VFLIP_DEF,
210 #define INFRARED_IDX 7
213 .id = V4L2_CID_INFRARED,
214 .type = V4L2_CTRL_TYPE_BOOLEAN,
219 #define INFRARED_DEF 0
220 .default_value = INFRARED_DEF,
222 .set = sd_setinfrared,
223 .get = sd_getinfrared,
227 /* table of the disabled controls */
228 static __u32 ctrl_dis[] = {
229 (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
230 /* SENSOR_HV7131R 0 */
232 /* SENSOR_MI0360 1 */
233 (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
234 /* SENSOR_MO4000 2 */
235 (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
236 /* SENSOR_OM6802 3 */
237 (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX),
238 /* SENSOR_OV7630 4 */
239 (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
240 /* SENSOR_OV7648 5 */
241 (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
242 /* SENSOR_OV7660 6 */
245 static const struct v4l2_pix_format vga_mode[] = {
246 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
248 .sizeimage = 160 * 120 * 4 / 8 + 590,
249 .colorspace = V4L2_COLORSPACE_JPEG,
251 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
253 .sizeimage = 320 * 240 * 3 / 8 + 590,
254 .colorspace = V4L2_COLORSPACE_JPEG,
256 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
258 .sizeimage = 640 * 480 * 3 / 8 + 590,
259 .colorspace = V4L2_COLORSPACE_JPEG,
263 /*Data from sn9c102p+hv7131r */
264 static const u8 sn_hv7131[0x1c] = {
265 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
266 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
267 /* reg8 reg9 rega regb regc regd rege regf */
268 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
269 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
270 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
271 /* reg18 reg19 reg1a reg1b */
272 0x0a, 0x00, 0x00, 0x00
275 static const u8 sn_mi0360[0x1c] = {
276 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
277 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
278 /* reg8 reg9 rega regb regc regd rege regf */
279 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
280 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
281 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
282 /* reg18 reg19 reg1a reg1b */
283 0x06, 0x00, 0x00, 0x00
286 static const u8 sn_mo4000[0x1c] = {
287 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
288 0x00, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
289 /* reg8 reg9 rega regb regc regd rege regf */
290 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
292 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
293 /* reg18 reg19 reg1a reg1b */
294 0x08, 0x00, 0x00, 0x00
297 static const u8 sn_om6802[0x1c] = {
298 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
299 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
300 /* reg8 reg9 rega regb regc regd rege regf */
301 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
303 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
304 /* reg18 reg19 reg1a reg1b */
305 0x05, 0x00, 0x00, 0x00
308 static const u8 sn_ov7630[0x1c] = {
309 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
310 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20,
311 /* reg8 reg9 rega regb regc regd rege regf */
312 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10,
313 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
314 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
315 /* reg18 reg19 reg1a reg1b */
316 0x0b, 0x00, 0x00, 0x00
319 static const u8 sn_ov7648[0x1c] = {
320 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
321 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
322 /* reg8 reg9 rega regb regc regd rege regf */
323 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
324 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
325 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00,
326 /* reg18 reg19 reg1a reg1b */
327 0x0b, 0x00, 0x00, 0x00
330 static const u8 sn_ov7660[0x1c] = {
331 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
332 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
333 /* reg8 reg9 rega regb regc regd rege regf */
334 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
335 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
336 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
337 /* reg18 reg19 reg1a reg1b */
338 0x07, 0x00, 0x00, 0x00
341 /* sequence specific to the sensors - !! index = SENSOR_xxx */
342 static const u8 *sn_tb[] = {
352 static const u8 gamma_def[17] = {
353 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
354 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
358 /* color matrix and offsets */
359 static const u8 reg84[] = {
360 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */
361 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */
362 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */
363 0x00, 0x00, 0x00 /* YUV offsets */
365 static const u8 hv7131r_sensor_init[][8] = {
366 {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
367 {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
368 {0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10},
369 /* {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */
370 {0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
371 {0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10},
372 /* {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */
374 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
375 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
376 {0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10},
377 {0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
378 {0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10},
379 {0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10},
380 {0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
381 {0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
383 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
384 {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
385 {0xa1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
386 {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
387 {0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
389 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
390 {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
391 {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
392 {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
393 {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
396 static const u8 mi0360_sensor_init[][8] = {
397 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
398 {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
399 {0xb1, 0x5d, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
400 {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
401 {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
402 {0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
403 {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
404 {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
405 {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
406 {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
407 {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
408 {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
409 {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
410 {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
411 {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
412 {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
413 {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
414 {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
415 {0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
416 {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
417 {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
418 {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
419 {0xd1, 0x5d, 0x2f, 0xf7, 0xB0, 0x00, 0x04, 0x10},
420 {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
421 {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
422 {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
423 {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
424 {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
425 {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
426 {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
427 {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
428 {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
429 {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
431 {0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
432 {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
433 {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
434 {0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10},
435 {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10},
437 {0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
438 {0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
439 {0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10},
440 {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
442 {0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10},
443 {0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */
444 /* {0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
445 /* {0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
446 {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
447 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
450 static const u8 mo4000_sensor_init[][8] = {
451 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
452 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
453 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
454 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
455 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
456 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
457 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
458 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
459 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
460 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
461 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
462 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
463 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
464 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
465 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
466 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
467 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
468 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
469 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
470 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
473 static const u8 om6802_sensor_init[][8] = {
474 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
475 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
476 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
477 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
478 /* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
479 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
480 /* white balance & auto-exposure */
481 /* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
483 /* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
484 * max AGC value in AE */
485 /* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
487 /* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
488 * preset brightness */
489 /* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
491 /* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
493 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
494 /* luminance mode (0x4f = AE) */
495 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
497 /* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
499 /* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
501 /* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
502 /* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
503 /* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
504 /* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
507 static const u8 ov7630_sensor_init[][8] = {
508 {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
509 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
510 /* win: delay 20ms */
511 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
512 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
513 /* win: delay 20ms */
514 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
515 /* win: i2c_r from 00 to 80 */
516 {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
517 {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
518 {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
519 {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
520 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
521 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
522 {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
523 {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
524 {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
525 {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
526 {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
527 {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
528 {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
529 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
530 {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
531 {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
532 {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
533 {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
534 {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
535 {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
536 {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
537 {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
538 {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
539 {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
540 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
541 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
543 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
544 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
545 /*fixme: + 0x12, 0x04*/
546 /* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN
548 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
549 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
550 {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
552 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
553 {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
554 {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
556 {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
557 /* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
561 static const u8 ov7648_sensor_init[][8] = {
562 {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
563 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
564 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
565 {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
566 {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
567 {0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
568 {0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
569 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
570 {0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
571 {0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
572 {0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
573 {0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
574 {0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
575 {0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
576 {0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
577 {0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
578 {0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
579 {0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
580 {0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
581 {0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
582 {0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
584 {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
585 /* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
586 /* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
587 {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10},
589 /* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
590 /* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, jfm done */
591 {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
592 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
593 /* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
594 /* {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, * GAIN - def */
595 /* {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10}, * B R - def: 80 */
597 {0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
598 /* {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
599 /* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
600 /* {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
601 /* {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
602 /* {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10}, * B R - def: 80 */
607 static const u8 ov7660_sensor_init[][8] = {
608 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
610 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
611 /* Outformat = rawRGB */
612 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
613 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
614 /* GAIN BLUE RED VREF */
615 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
616 /* COM 1 BAVE GEAVE AECHH */
617 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
618 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
619 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
620 /* AECH CLKRC COM7 COM8 */
621 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
622 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
623 /* HSTART HSTOP VSTRT VSTOP */
624 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
625 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
626 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
627 /* BOS GBOS GROS ROS (BGGR offset) */
628 /* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
629 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
630 /* AEW AEB VPT BBIAS */
631 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
632 /* GbBIAS RSVD EXHCH EXHCL */
633 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
634 /* RBIAS ADVFL ASDVFH YAVE */
635 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
636 /* HSYST HSYEN HREF */
637 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
638 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
639 /* ADC ACOM OFON TSLB */
640 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
641 /* COM11 COM12 COM13 COM14 */
642 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
643 /* EDGE COM15 COM16 COM17 */
644 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
645 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
646 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
647 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
648 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
649 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
650 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
651 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
652 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
653 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
654 /* LCC1 LCC2 LCC3 LCC4 */
655 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
656 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
657 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
658 /* band gap reference [0:3] DBLV */
659 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
660 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
661 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
662 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
663 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
664 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
665 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
666 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
667 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
668 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
669 /****** (some exchanges in the win trace) ******/
670 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
671 /* bits[3..0]reserved */
672 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
673 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
674 /* VREF vertical frame ctrl */
675 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
676 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
677 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
678 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
679 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
680 /* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
681 /****** (some exchanges in the win trace) ******/
682 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
683 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
684 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
685 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
686 /* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
687 /****** (some exchanges in the win trace) ******/
688 /******!! startsensor KO if changed !!****/
689 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
690 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
691 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
692 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
696 static const u8 qtable4[] = {
697 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06,
698 0x06, 0x06, 0x08, 0x06, 0x06, 0x08, 0x0a, 0x11,
699 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x15, 0x0f, 0x0f,
700 0x0c, 0x11, 0x19, 0x15, 0x19, 0x19, 0x17, 0x15,
701 0x17, 0x17, 0x1b, 0x1d, 0x25, 0x21, 0x1b, 0x1d,
702 0x23, 0x1d, 0x17, 0x17, 0x21, 0x2e, 0x21, 0x23,
703 0x27, 0x29, 0x2c, 0x2c, 0x2c, 0x19, 0x1f, 0x30,
704 0x32, 0x2e, 0x29, 0x32, 0x25, 0x29, 0x2c, 0x29,
705 0x06, 0x08, 0x08, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
706 0x0a, 0x13, 0x29, 0x1b, 0x17, 0x1b, 0x29, 0x29,
707 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
708 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
709 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
710 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
711 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
712 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29
715 /* read <len> bytes to gspca_dev->usb_buf */
716 static void reg_r(struct gspca_dev *gspca_dev,
720 if (len > USB_BUF_SZ) {
721 err("reg_r: buffer overflow");
725 usb_control_msg(gspca_dev->dev,
726 usb_rcvctrlpipe(gspca_dev->dev, 0),
728 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
730 gspca_dev->usb_buf, len,
732 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
735 static void reg_w1(struct gspca_dev *gspca_dev,
739 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
740 gspca_dev->usb_buf[0] = data;
741 usb_control_msg(gspca_dev->dev,
742 usb_sndctrlpipe(gspca_dev->dev, 0),
744 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
747 gspca_dev->usb_buf, 1,
750 static void reg_w(struct gspca_dev *gspca_dev,
755 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
756 value, buffer[0], buffer[1]);
758 if (len > USB_BUF_SZ) {
759 err("reg_w: buffer overflow");
763 memcpy(gspca_dev->usb_buf, buffer, len);
764 usb_control_msg(gspca_dev->dev,
765 usb_sndctrlpipe(gspca_dev->dev, 0),
767 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
769 gspca_dev->usb_buf, len,
773 /* I2C write 1 byte */
774 static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
776 struct sd *sd = (struct sd *) gspca_dev;
778 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
779 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
780 gspca_dev->usb_buf[1] = sd->i2c_base;
781 gspca_dev->usb_buf[2] = reg;
782 gspca_dev->usb_buf[3] = val;
783 gspca_dev->usb_buf[4] = 0;
784 gspca_dev->usb_buf[5] = 0;
785 gspca_dev->usb_buf[6] = 0;
786 gspca_dev->usb_buf[7] = 0x10;
787 usb_control_msg(gspca_dev->dev,
788 usb_sndctrlpipe(gspca_dev->dev, 0),
790 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
791 0x08, /* value = i2c */
793 gspca_dev->usb_buf, 8,
797 /* I2C write 8 bytes */
798 static void i2c_w8(struct gspca_dev *gspca_dev,
801 memcpy(gspca_dev->usb_buf, buffer, 8);
802 usb_control_msg(gspca_dev->dev,
803 usb_sndctrlpipe(gspca_dev->dev, 0),
805 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
806 0x08, 0, /* value, index */
807 gspca_dev->usb_buf, 8,
812 /* read 5 bytes in gspca_dev->usb_buf */
813 static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg)
815 struct sd *sd = (struct sd *) gspca_dev;
818 mode[0] = 0x81 | 0x10;
819 mode[1] = sd->i2c_base;
826 i2c_w8(gspca_dev, mode);
828 mode[0] = 0x81 | (5 << 4) | 0x02;
830 i2c_w8(gspca_dev, mode);
832 reg_r(gspca_dev, 0x0a, 5);
835 static int probesensor(struct gspca_dev *gspca_dev)
837 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
839 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
841 i2c_r5(gspca_dev, 0); /* read sensor id */
842 if (gspca_dev->usb_buf[0] == 0x02
843 && gspca_dev->usb_buf[1] == 0x09
844 && gspca_dev->usb_buf[2] == 0x01
845 && gspca_dev->usb_buf[3] == 0x00
846 && gspca_dev->usb_buf[4] == 0x00) {
847 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
850 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
851 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
852 gspca_dev->usb_buf[2]);
853 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
857 static int configure_gpio(struct gspca_dev *gspca_dev,
860 struct sd *sd = (struct sd *) gspca_dev;
862 static const u8 reg9a_def[] =
863 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
864 static const u8 reg9a_sn9c325[] =
865 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
866 static const u8 regd4[] = {0x60, 0x00, 0x00};
868 reg_w1(gspca_dev, 0xf1, 0x00);
869 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
872 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
873 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
874 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
875 switch (sd->bridge) {
877 reg9a = reg9a_sn9c325;
883 reg_w(gspca_dev, 0x9a, reg9a, 6);
885 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
887 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
889 switch (sd->sensor) {
891 reg_w1(gspca_dev, 0x02, 0x71);
892 reg_w1(gspca_dev, 0x01, 0x42);
893 reg_w1(gspca_dev, 0x17, 0x64);
894 reg_w1(gspca_dev, 0x01, 0x42);
896 /*jfm: from win trace */
898 reg_w1(gspca_dev, 0x01, 0x61);
899 reg_w1(gspca_dev, 0x17, 0xe2);
900 reg_w1(gspca_dev, 0x01, 0x60);
901 reg_w1(gspca_dev, 0x01, 0x40);
904 reg_w1(gspca_dev, 0x01, 0x63);
905 reg_w1(gspca_dev, 0x17, 0x20);
906 reg_w1(gspca_dev, 0x01, 0x42);
908 /*jfm: from win trace */
910 if (sd->bridge == BRIDGE_SN9C120) {
911 reg_w1(gspca_dev, 0x01, 0x61);
912 reg_w1(gspca_dev, 0x17, 0x20);
913 reg_w1(gspca_dev, 0x01, 0x60);
914 reg_w1(gspca_dev, 0x01, 0x40);
919 reg_w1(gspca_dev, 0x01, 0x43);
920 reg_w1(gspca_dev, 0x17, 0x61);
921 reg_w1(gspca_dev, 0x01, 0x42);
922 if (sd->sensor == SENSOR_HV7131R) {
923 if (probesensor(gspca_dev) < 0)
931 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
934 static const u8 SetSensorClk[] = /* 0x08 Mclk */
935 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
937 while (hv7131r_sensor_init[i][0]) {
938 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
941 i2c_w8(gspca_dev, SetSensorClk);
944 static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
948 while (mi0360_sensor_init[i][0]) {
949 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
954 static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
958 while (mo4000_sensor_init[i][0]) {
959 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
964 static void om6802_InitSensor(struct gspca_dev *gspca_dev)
968 while (om6802_sensor_init[i][0]) {
969 i2c_w8(gspca_dev, om6802_sensor_init[i]);
974 static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
978 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */
980 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */
983 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
985 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */
988 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
990 /*jfm:win i2c_r from 00 to 80*/
992 while (ov7630_sensor_init[i][0]) {
993 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
998 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
1002 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
1004 /* win: dble reset */
1005 i2c_w8(gspca_dev, ov7648_sensor_init[i]); /* reset */
1008 /* win: i2c reg read 00..7f */
1009 while (ov7648_sensor_init[i][0]) {
1010 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
1015 static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
1019 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
1022 while (ov7660_sensor_init[i][0]) {
1023 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
1028 /* this function is called at probe time */
1029 static int sd_config(struct gspca_dev *gspca_dev,
1030 const struct usb_device_id *id)
1032 struct sd *sd = (struct sd *) gspca_dev;
1035 cam = &gspca_dev->cam;
1036 cam->cam_mode = vga_mode;
1037 cam->nmodes = ARRAY_SIZE(vga_mode);
1039 sd->bridge = id->driver_info >> 16;
1040 sd->sensor = id->driver_info >> 8;
1041 sd->i2c_base = id->driver_info;
1043 sd->brightness = BRIGHTNESS_DEF;
1044 sd->contrast = CONTRAST_DEF;
1045 sd->colors = COLOR_DEF;
1046 sd->blue = BLUE_BALANCE_DEF;
1047 sd->red = RED_BALANCE_DEF;
1048 sd->gamma = GAMMA_DEF;
1049 sd->autogain = AUTOGAIN_DEF;
1051 sd->vflip = VFLIP_DEF;
1052 sd->infrared = INFRARED_DEF;
1054 gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
1058 /* this function is called at probe and resume time */
1059 static int sd_init(struct gspca_dev *gspca_dev)
1061 struct sd *sd = (struct sd *) gspca_dev;
1062 u8 regGpio[] = { 0x29, 0x74 };
1065 /* setup a selector by bridge */
1066 reg_w1(gspca_dev, 0xf1, 0x01);
1067 reg_r(gspca_dev, 0x00, 1);
1068 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
1069 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
1070 regF1 = gspca_dev->usb_buf[0];
1071 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
1072 switch (sd->bridge) {
1073 case BRIDGE_SN9C102P:
1076 reg_w1(gspca_dev, 0x02, regGpio[1]);
1078 case BRIDGE_SN9C105:
1081 reg_w(gspca_dev, 0x01, regGpio, 2);
1083 case BRIDGE_SN9C120:
1087 reg_w(gspca_dev, 0x01, regGpio, 2);
1090 /* case BRIDGE_SN9C110: */
1091 /* case BRIDGE_SN9C325: */
1094 reg_w1(gspca_dev, 0x02, 0x62);
1098 reg_w1(gspca_dev, 0xf1, 0x01);
1103 static u32 setexposure(struct gspca_dev *gspca_dev,
1106 struct sd *sd = (struct sd *) gspca_dev;
1108 switch (sd->sensor) {
1109 case SENSOR_HV7131R: {
1111 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1113 Expodoit[3] = expo >> 16;
1114 Expodoit[4] = expo >> 8;
1116 i2c_w8(gspca_dev, Expodoit);
1119 case SENSOR_MI0360: {
1120 u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1121 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1122 static const u8 doit[] = /* update sensor */
1123 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1124 static const u8 sensorgo[] = /* sensor on */
1125 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1129 else if (expo < 0x0001)
1131 expoMi[3] = expo >> 8;
1133 i2c_w8(gspca_dev, expoMi);
1134 i2c_w8(gspca_dev, doit);
1135 i2c_w8(gspca_dev, sensorgo);
1138 case SENSOR_MO4000: {
1140 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1142 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1143 static const u8 gainMo[] =
1144 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1148 else if (expo < 0x0001)
1150 expoMof[3] = (expo & 0x03fc) >> 2;
1151 i2c_w8(gspca_dev, expoMof);
1152 expoMo10[3] = ((expo & 0x1c00) >> 10)
1153 | ((expo & 0x0003) << 4);
1154 i2c_w8(gspca_dev, expoMo10);
1155 i2c_w8(gspca_dev, gainMo);
1156 PDEBUG(D_CONF, "set exposure %d",
1157 ((expoMo10[3] & 0x07) << 10)
1159 | ((expoMo10[3] & 0x30) >> 4));
1162 case SENSOR_OM6802: {
1164 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1170 gainOm[3] = expo >> 2;
1171 i2c_w8(gspca_dev, gainOm);
1172 reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
1173 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
1180 static void setbrightness(struct gspca_dev *gspca_dev)
1182 struct sd *sd = (struct sd *) gspca_dev;
1186 k2 = ((int) sd->brightness - 0x8000) >> 10;
1187 switch (sd->sensor) {
1188 case SENSOR_HV7131R:
1189 expo = sd->brightness << 4;
1190 if (expo > 0x002dc6c0)
1192 else if (expo < 0x02a0)
1194 sd->exposure = setexposure(gspca_dev, expo);
1198 expo = sd->brightness >> 4;
1199 sd->exposure = setexposure(gspca_dev, expo);
1202 expo = sd->brightness >> 6;
1203 sd->exposure = setexposure(gspca_dev, expo);
1204 k2 = sd->brightness >> 11;
1208 reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */
1211 static void setcontrast(struct gspca_dev *gspca_dev)
1213 struct sd *sd = (struct sd *) gspca_dev;
1217 k2 = sd->contrast * 0x30 / (CONTRAST_MAX + 1) + 0x10; /* 10..40 */
1218 contrast[0] = (k2 + 1) / 2; /* red */
1220 contrast[2] = k2; /* green */
1222 contrast[4] = (k2 + 1) / 5; /* blue */
1224 reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
1227 static void setcolors(struct gspca_dev *gspca_dev)
1229 struct sd *sd = (struct sd *) gspca_dev;
1231 u8 reg8a[12]; /* U & V gains */
1232 static s16 uv[6] = { /* same as reg84 in signed decimal */
1233 -24, -38, 64, /* UR UG UB */
1234 62, -51, -9 /* VR VG VB */
1236 for (i = 0; i < 6; i++) {
1237 v = uv[i] * sd->colors / COLOR_DEF;
1239 reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
1241 reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
1244 static void setredblue(struct gspca_dev *gspca_dev)
1246 struct sd *sd = (struct sd *) gspca_dev;
1248 reg_w1(gspca_dev, 0x05, sd->red);
1249 /* reg_w1(gspca_dev, 0x07, 32); */
1250 reg_w1(gspca_dev, 0x06, sd->blue);
1253 static void setgamma(struct gspca_dev *gspca_dev)
1255 struct sd *sd = (struct sd *) gspca_dev;
1258 static const u8 delta[17] = {
1259 0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a,
1260 0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00
1263 for (i = 0; i < sizeof gamma; i++)
1264 gamma[i] = gamma_def[i]
1265 + delta[i] * (sd->gamma - GAMMA_DEF) / 32;
1266 reg_w(gspca_dev, 0x20, gamma, sizeof gamma);
1269 static void setautogain(struct gspca_dev *gspca_dev)
1271 struct sd *sd = (struct sd *) gspca_dev;
1273 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1276 sd->ag_cnt = AG_CNT_START;
1281 static void setvflip(struct sd *sd)
1283 i2c_w1(&sd->gspca_dev, 0x75, /* COMN */
1284 sd->vflip ? 0x82 : 0x02);
1287 static void setinfrared(struct sd *sd)
1289 /*fixme: different sequence for StarCam Clip and StarCam 370i */
1291 i2c_w1(&sd->gspca_dev, 0x02, /* gpio */
1292 sd->infrared ? 0x66 : 0x64);
1295 /* -- start the camera -- */
1296 static int sd_start(struct gspca_dev *gspca_dev)
1298 struct sd *sd = (struct sd *) gspca_dev;
1300 u8 reg1, reg17, reg18;
1303 static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1304 static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1305 static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1306 static const u8 CE_ov76xx[] =
1307 { 0x32, 0xdd, 0x32, 0xdd };
1309 sn9c1xx = sn_tb[(int) sd->sensor];
1310 configure_gpio(gspca_dev, sn9c1xx);
1312 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1313 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1314 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1315 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1316 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1317 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1318 reg_w1(gspca_dev, 0xd3, 0x50);
1319 reg_w1(gspca_dev, 0xc6, 0x00);
1320 reg_w1(gspca_dev, 0xc7, 0x00);
1321 reg_w1(gspca_dev, 0xc8, 0x50);
1322 reg_w1(gspca_dev, 0xc9, 0x3c);
1323 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1324 switch (sd->sensor) {
1331 /*jfm: from win trace */
1333 if (sd->bridge == BRIDGE_SN9C120) {
1342 reg_w1(gspca_dev, 0x17, reg17);
1343 /* set reg1 was here */
1344 reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */
1345 reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */
1346 reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */
1347 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
1348 setgamma(gspca_dev);
1349 for (i = 0; i < 8; i++)
1350 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1351 switch (sd->sensor) {
1353 reg_w1(gspca_dev, 0x9a, 0x0a);
1354 reg_w1(gspca_dev, 0x99, 0x60);
1357 if (sd->bridge == BRIDGE_SN9C120) {
1358 reg_w1(gspca_dev, 0x9a, 0x05);
1363 reg_w1(gspca_dev, 0x9a, 0x08);
1364 reg_w1(gspca_dev, 0x99, 0x59);
1368 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1370 reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */
1372 reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */
1373 reg17 = 0x61; /* 0x:20: enable sensor clock */
1374 switch (sd->sensor) {
1375 case SENSOR_HV7131R:
1376 hv7131R_InitSensor(gspca_dev);
1379 mi0360_InitSensor(gspca_dev);
1382 mo4000_InitSensor(gspca_dev);
1384 /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1385 reg1 = 0x06; /* clk 24Mz */
1387 reg17 = 0x22; /* 640 MCKSIZE */
1388 /* reg1 = 0x06; * 640 clk 24Mz (done) */
1392 om6802_InitSensor(gspca_dev);
1393 reg17 = 0x64; /* 640 MCKSIZE */
1396 ov7630_InitSensor(gspca_dev);
1402 ov7648_InitSensor(gspca_dev);
1404 /* reg1 = 0x42; * 42 - 46? */
1407 /* case SENSOR_OV7660: */
1408 ov7660_InitSensor(gspca_dev);
1409 if (sd->bridge == BRIDGE_SN9C120) {
1410 if (mode) { /* 320x240 - 160x120 */
1412 reg1 = 0x44; /* 48 Mhz, video trf eneble */
1416 reg1 = 0x06; /* 24 Mhz, video trf eneble
1417 * inverse power down */
1421 reg_w(gspca_dev, 0xc0, C0, 6);
1422 reg_w(gspca_dev, 0xca, CA, 4);
1423 switch (sd->sensor) {
1427 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
1430 reg_w(gspca_dev, 0xce, CE, 4);
1431 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1435 /* here change size mode 0 -> VGA; 1 -> CIF */
1436 reg18 = sn9c1xx[0x18] | (mode << 4);
1437 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
1439 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1440 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1442 reg_w1(gspca_dev, 0x18, reg18);
1444 reg_w1(gspca_dev, 0x17, reg17);
1445 reg_w1(gspca_dev, 0x01, reg1);
1446 switch (sd->sensor) {
1454 setbrightness(gspca_dev);
1455 setcontrast(gspca_dev);
1456 setautogain(gspca_dev);
1460 static void sd_stopN(struct gspca_dev *gspca_dev)
1462 struct sd *sd = (struct sd *) gspca_dev;
1463 static const u8 stophv7131[] =
1464 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1465 static const u8 stopmi0360[] =
1466 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1467 static const u8 stopov7648[] =
1468 { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
1473 switch (sd->sensor) {
1474 case SENSOR_HV7131R:
1475 i2c_w8(gspca_dev, stophv7131);
1479 i2c_w8(gspca_dev, stopmi0360);
1483 i2c_w8(gspca_dev, stopov7648);
1489 /* case SENSOR_MO4000: */
1490 /* case SENSOR_OV7660: */
1493 sn9c1xx = sn_tb[(int) sd->sensor];
1494 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1495 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1496 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1497 reg_w1(gspca_dev, 0x01, data);
1498 reg_w1(gspca_dev, 0xf1, 0x00);
1501 static void do_autogain(struct gspca_dev *gspca_dev)
1503 struct sd *sd = (struct sd *) gspca_dev;
1509 /* Thanks S., without your advice, autobright should not work :) */
1512 if (--sd->ag_cnt >= 0)
1514 sd->ag_cnt = AG_CNT_START;
1516 delta = atomic_read(&sd->avg_lum);
1517 PDEBUG(D_FRAM, "mean lum %d", delta);
1518 if (delta < luma_mean - luma_delta ||
1519 delta > luma_mean + luma_delta) {
1520 switch (sd->sensor) {
1521 case SENSOR_HV7131R:
1522 expotimes = sd->exposure >> 8;
1523 expotimes += (luma_mean - delta) >> 4;
1526 sd->exposure = setexposure(gspca_dev,
1527 (unsigned int) (expotimes << 8));
1530 /* case SENSOR_MO4000: */
1531 /* case SENSOR_MI0360: */
1532 /* case SENSOR_OM6802: */
1533 expotimes = sd->exposure;
1534 expotimes += (luma_mean - delta) >> 6;
1537 sd->exposure = setexposure(gspca_dev,
1538 (unsigned int) expotimes);
1539 setredblue(gspca_dev);
1545 /* scan the URB packets */
1546 /* This function is run at interrupt level. */
1547 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1548 struct gspca_frame *frame, /* target */
1549 u8 *data, /* isoc packet */
1550 int len) /* iso packet length */
1552 struct sd *sd = (struct sd *) gspca_dev;
1556 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1559 gspca_frame_add(gspca_dev, LAST_PACKET,
1560 frame, data, sof + 2);
1567 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1569 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1571 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1573 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1575 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1577 atomic_set(&sd->avg_lum, avg_lum);
1580 if (gspca_dev->last_packet_type == LAST_PACKET) {
1582 /* put the JPEG 422 header */
1583 jpeg_put_header(gspca_dev, frame, 0x21);
1585 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1588 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1590 struct sd *sd = (struct sd *) gspca_dev;
1592 sd->brightness = val;
1593 if (gspca_dev->streaming)
1594 setbrightness(gspca_dev);
1598 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1600 struct sd *sd = (struct sd *) gspca_dev;
1602 *val = sd->brightness;
1606 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1608 struct sd *sd = (struct sd *) gspca_dev;
1611 if (gspca_dev->streaming)
1612 setcontrast(gspca_dev);
1616 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1618 struct sd *sd = (struct sd *) gspca_dev;
1620 *val = sd->contrast;
1624 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1626 struct sd *sd = (struct sd *) gspca_dev;
1629 if (gspca_dev->streaming)
1630 setcolors(gspca_dev);
1634 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1636 struct sd *sd = (struct sd *) gspca_dev;
1642 static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1644 struct sd *sd = (struct sd *) gspca_dev;
1647 if (gspca_dev->streaming)
1648 setredblue(gspca_dev);
1652 static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1654 struct sd *sd = (struct sd *) gspca_dev;
1660 static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1662 struct sd *sd = (struct sd *) gspca_dev;
1665 if (gspca_dev->streaming)
1666 setredblue(gspca_dev);
1670 static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1672 struct sd *sd = (struct sd *) gspca_dev;
1678 static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1680 struct sd *sd = (struct sd *) gspca_dev;
1683 if (gspca_dev->streaming)
1684 setgamma(gspca_dev);
1688 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1690 struct sd *sd = (struct sd *) gspca_dev;
1696 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1698 struct sd *sd = (struct sd *) gspca_dev;
1701 if (gspca_dev->streaming)
1702 setautogain(gspca_dev);
1706 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1708 struct sd *sd = (struct sd *) gspca_dev;
1710 *val = sd->autogain;
1714 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1716 struct sd *sd = (struct sd *) gspca_dev;
1719 if (gspca_dev->streaming)
1724 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1726 struct sd *sd = (struct sd *) gspca_dev;
1732 static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val)
1734 struct sd *sd = (struct sd *) gspca_dev;
1737 if (gspca_dev->streaming)
1742 static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val)
1744 struct sd *sd = (struct sd *) gspca_dev;
1746 *val = sd->infrared;
1750 /* sub-driver description */
1751 static const struct sd_desc sd_desc = {
1752 .name = MODULE_NAME,
1754 .nctrls = ARRAY_SIZE(sd_ctrls),
1755 .config = sd_config,
1759 .pkt_scan = sd_pkt_scan,
1760 .dq_callback = do_autogain,
1763 /* -- module initialisation -- */
1764 #define BSI(bridge, sensor, i2c_addr) \
1765 .driver_info = (BRIDGE_ ## bridge << 16) \
1766 | (SENSOR_ ## sensor << 8) \
1768 static const __devinitdata struct usb_device_id device_table[] = {
1769 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1770 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1771 {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)},
1773 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1774 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1775 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1776 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1778 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
1779 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1780 {USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)},
1781 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1783 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1784 /* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1785 /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1786 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1787 /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1788 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1789 /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1790 /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1791 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1792 /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1793 /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1794 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1795 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1796 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1797 {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
1799 /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1800 /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1801 /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1802 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1804 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c110?*/
1805 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1806 {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
1807 /* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
1808 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1809 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1811 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1812 {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)},
1813 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1814 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1815 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1816 /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
1818 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
1821 MODULE_DEVICE_TABLE(usb, device_table);
1823 /* -- device connect -- */
1824 static int sd_probe(struct usb_interface *intf,
1825 const struct usb_device_id *id)
1827 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1831 static struct usb_driver sd_driver = {
1832 .name = MODULE_NAME,
1833 .id_table = device_table,
1835 .disconnect = gspca_disconnect,
1837 .suspend = gspca_suspend,
1838 .resume = gspca_resume,
1842 /* -- module insert / remove -- */
1843 static int __init sd_mod_init(void)
1846 ret = usb_register(&sd_driver);
1852 static void __exit sd_mod_exit(void)
1854 usb_deregister(&sd_driver);
1855 info("deregistered");
1858 module_init(sd_mod_init);
1859 module_exit(sd_mod_exit);