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"
27 #define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0)
29 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30 MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
31 MODULE_LICENSE("GPL");
33 /* specific webcam descriptor */
35 struct gspca_dev gspca_dev; /* !! must be the first item */
38 unsigned int exposure;
40 unsigned short brightness;
41 unsigned char contrast;
43 unsigned char autogain;
46 __u8 vflip; /* ov7630 only */
47 __u8 infrared; /* mi0360 only */
50 #define AG_CNT_START 13
54 #define BRIDGE_SN9C102P 0
55 #define BRIDGE_SN9C105 1
56 #define BRIDGE_SN9C110 2
57 #define BRIDGE_SN9C120 3
58 #define BRIDGE_SN9C325 4
59 char sensor; /* Type of image sensor chip */
60 #define SENSOR_HV7131R 0
61 #define SENSOR_MI0360 1
62 #define SENSOR_MO4000 2
63 #define SENSOR_OM6802 3
64 #define SENSOR_OV7630 4
65 #define SENSOR_OV7648 5
66 #define SENSOR_OV7660 6
67 unsigned char i2c_base;
70 /* V4L2 controls supported by the driver */
71 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
72 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
73 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
74 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
75 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
76 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
77 static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val);
78 static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
79 static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
80 static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
81 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
82 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
83 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
84 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
85 static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val);
86 static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val);
88 static struct ctrl sd_ctrls[] = {
91 .id = V4L2_CID_BRIGHTNESS,
92 .type = V4L2_CTRL_TYPE_INTEGER,
95 #define BRIGHTNESS_MAX 0xffff
96 .maximum = BRIGHTNESS_MAX,
98 #define BRIGHTNESS_DEF 0x8000
99 .default_value = BRIGHTNESS_DEF,
101 .set = sd_setbrightness,
102 .get = sd_getbrightness,
106 .id = V4L2_CID_CONTRAST,
107 .type = V4L2_CTRL_TYPE_INTEGER,
110 #define CONTRAST_MAX 127
111 .maximum = CONTRAST_MAX,
113 #define CONTRAST_DEF 63
114 .default_value = CONTRAST_DEF,
116 .set = sd_setcontrast,
117 .get = sd_getcontrast,
121 .id = V4L2_CID_SATURATION,
122 .type = V4L2_CTRL_TYPE_INTEGER,
128 .default_value = COLOR_DEF,
135 .id = V4L2_CID_BLUE_BALANCE,
136 .type = V4L2_CTRL_TYPE_INTEGER,
137 .name = "Blue Balance",
141 #define BLUE_BALANCE_DEF 32
142 .default_value = BLUE_BALANCE_DEF,
144 .set = sd_setblue_balance,
145 .get = sd_getblue_balance,
149 .id = V4L2_CID_RED_BALANCE,
150 .type = V4L2_CTRL_TYPE_INTEGER,
151 .name = "Red Balance",
155 #define RED_BALANCE_DEF 32
156 .default_value = RED_BALANCE_DEF,
158 .set = sd_setred_balance,
159 .get = sd_getred_balance,
161 #define AUTOGAIN_IDX 5
164 .id = V4L2_CID_AUTOGAIN,
165 .type = V4L2_CTRL_TYPE_BOOLEAN,
170 #define AUTOGAIN_DEF 1
171 .default_value = AUTOGAIN_DEF,
173 .set = sd_setautogain,
174 .get = sd_getautogain,
180 .id = V4L2_CID_VFLIP,
181 .type = V4L2_CTRL_TYPE_BOOLEAN,
187 .default_value = VFLIP_DEF,
193 #define INFRARED_IDX 7
196 .id = V4L2_CID_INFRARED,
197 .type = V4L2_CTRL_TYPE_BOOLEAN,
202 #define INFRARED_DEF 0
203 .default_value = INFRARED_DEF,
205 .set = sd_setinfrared,
206 .get = sd_getinfrared,
210 static struct v4l2_pix_format vga_mode[] = {
211 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
213 .sizeimage = 160 * 120 * 4 / 8 + 590,
214 .colorspace = V4L2_COLORSPACE_JPEG,
216 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
218 .sizeimage = 320 * 240 * 3 / 8 + 590,
219 .colorspace = V4L2_COLORSPACE_JPEG,
221 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
223 .sizeimage = 640 * 480 * 3 / 8 + 590,
224 .colorspace = V4L2_COLORSPACE_JPEG,
228 /*Data from sn9c102p+hv71331r */
229 static const __u8 sn_hv7131[] = {
230 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
231 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
232 /* reg8 reg9 rega regb regc regd rege regf */
233 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
234 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
235 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
236 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
237 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
240 static const __u8 sn_mi0360[] = {
241 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
242 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
243 /* reg8 reg9 rega regb regc regd rege regf */
244 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
245 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
246 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
247 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
248 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
251 static const __u8 sn_mo4000[] = {
252 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
253 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
254 /* reg8 reg9 rega regb regc regd rege regf */
255 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
257 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
258 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
259 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
262 static const __u8 sn_om6802[] = {
263 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
264 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
265 /* reg8 reg9 rega regb regc regd rege regf */
266 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
268 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
269 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
270 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf,
272 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef,
276 static const __u8 sn_ov7630[] = {
277 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
278 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20,
279 /* reg8 reg9 rega regb regc regd rege regf */
280 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10,
281 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
282 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
283 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
284 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
287 static const __u8 sn_ov7648[] = {
288 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
289 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
290 /* reg8 reg9 rega regb regc regd rege regf */
291 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
292 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
293 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00,
294 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
295 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
298 static const __u8 sn_ov7660[] = {
299 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
300 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
301 /* reg8 reg9 rega regb regc regd rege regf */
302 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
303 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
304 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
305 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
306 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
309 /* sequence specific to the sensors - !! index = SENSOR_xxx */
310 static const __u8 *sn_tb[] = {
320 static const __u8 gamma_def[] = {
321 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
322 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
325 /* color matrix and offsets */
326 static const __u8 reg84[] = {
327 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */
328 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */
329 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */
330 0x00, 0x00, 0x00 /* YUV offsets */
332 static const __u8 hv7131r_sensor_init[][8] = {
333 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
334 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
335 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
336 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
337 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
338 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
339 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
341 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
342 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
343 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
344 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
345 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
346 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
347 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
348 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
350 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
351 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
352 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
353 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
354 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
356 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
357 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
358 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
359 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
360 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
363 static const __u8 mi0360_sensor_init[][8] = {
364 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
365 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
366 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
367 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
368 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
369 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
370 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
371 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
372 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
373 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
374 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
375 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
376 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
377 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
378 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
379 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
380 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
381 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
382 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
383 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
384 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
385 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
386 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
387 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
388 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
389 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
390 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
391 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
392 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
393 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
394 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
395 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
396 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
398 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
399 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
400 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
401 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
402 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
404 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
405 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
406 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
407 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
409 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
410 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
411 /* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
412 /* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
413 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
414 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
417 static const __u8 mo4000_sensor_init[][8] = {
418 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
419 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
420 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
421 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
422 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
423 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
424 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
425 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
426 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
427 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
428 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
429 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
430 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
431 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
432 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
433 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
434 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
435 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
436 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
437 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
440 static __u8 om6802_sensor_init[][8] = {
441 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
442 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
443 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
444 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
445 /* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
446 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
447 /* white balance & auto-exposure */
448 /* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
450 /* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
451 * max AGC value in AE */
452 /* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
454 /* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
455 * preset brightness */
456 /* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
458 /* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
460 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
461 /* luminance mode (0x4f = AE) */
462 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
464 /* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
466 /* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
468 /* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
469 /* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
470 /* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
471 /* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
474 static const __u8 ov7630_sensor_init[][8] = {
475 {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
476 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
477 /* win: delay 20ms */
478 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
479 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
480 /* win: delay 20ms */
481 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
482 /* win: i2c_r from 00 to 80 */
483 {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
484 {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
485 {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
486 {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
487 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
488 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
489 {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
490 {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
491 {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
492 {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
493 {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
494 {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
495 {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
496 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
497 {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
498 {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
499 {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
500 {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
501 {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
502 {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
503 {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
504 {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
505 {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
506 {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
507 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
508 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
510 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
511 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
512 /*fixme: + 0x12, 0x04*/
513 /* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN
515 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
516 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
517 {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
519 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
520 {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
521 {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
523 {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
524 /* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
528 static const __u8 ov7648_sensor_init[][8] = {
529 {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
530 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
531 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
532 {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
533 {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
534 {0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
535 {0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
536 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
537 {0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
538 {0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
539 {0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
540 {0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
541 {0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
542 {0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
543 {0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
544 {0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
545 {0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
546 {0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
547 {0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
548 {0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
549 {0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
551 {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
552 /* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
553 /* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
554 {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10},
556 /* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
557 /* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, jfm done */
558 {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
559 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
560 /* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
561 /* {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, * GAIN - def */
562 /* {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10}, * B R - def: 80 */
564 {0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
565 /* {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
566 /* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
567 /* {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
568 /* {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
569 /* {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10}, * B R - def: 80 */
574 static const __u8 ov7660_sensor_init[][8] = {
575 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
577 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
578 /* Outformat = rawRGB */
579 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
580 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
581 /* GAIN BLUE RED VREF */
582 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
583 /* COM 1 BAVE GEAVE AECHH */
584 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
585 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
586 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
587 /* AECH CLKRC COM7 COM8 */
588 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
589 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
590 /* HSTART HSTOP VSTRT VSTOP */
591 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
592 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
593 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
594 /* BOS GBOS GROS ROS (BGGR offset) */
595 /* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
596 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
597 /* AEW AEB VPT BBIAS */
598 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
599 /* GbBIAS RSVD EXHCH EXHCL */
600 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
601 /* RBIAS ADVFL ASDVFH YAVE */
602 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
603 /* HSYST HSYEN HREF */
604 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
605 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
606 /* ADC ACOM OFON TSLB */
607 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
608 /* COM11 COM12 COM13 COM14 */
609 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
610 /* EDGE COM15 COM16 COM17 */
611 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
612 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
613 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
614 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
615 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
616 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
617 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
618 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
619 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
620 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
621 /* LCC1 LCC2 LCC3 LCC4 */
622 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
623 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
624 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
625 /* band gap reference [0:3] DBLV */
626 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
627 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
628 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
629 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
630 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
631 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
632 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
633 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
634 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
635 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
636 /****** (some exchanges in the win trace) ******/
637 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
638 /* bits[3..0]reserved */
639 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
640 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
641 /* VREF vertical frame ctrl */
642 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
643 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
644 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
645 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
646 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
647 /* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
648 /****** (some exchanges in the win trace) ******/
649 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
650 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
651 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
652 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
653 /* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
654 /****** (some exchanges in the win trace) ******/
655 /******!! startsensor KO if changed !!****/
656 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
657 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
658 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
659 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
663 static const __u8 qtable4[] = {
664 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
665 0x06, 0x08, 0x0A, 0x11,
666 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
667 0x19, 0x19, 0x17, 0x15,
668 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
669 0x21, 0x2E, 0x21, 0x23,
670 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
671 0x25, 0x29, 0x2C, 0x29,
672 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
673 0x17, 0x1B, 0x29, 0x29,
674 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
675 0x29, 0x29, 0x29, 0x29,
676 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
677 0x29, 0x29, 0x29, 0x29,
678 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
679 0x29, 0x29, 0x29, 0x29
682 /* read <len> bytes to gspca_dev->usb_buf */
683 static void reg_r(struct gspca_dev *gspca_dev,
684 __u16 value, int len)
687 if (len > USB_BUF_SZ) {
688 err("reg_r: buffer overflow");
692 usb_control_msg(gspca_dev->dev,
693 usb_rcvctrlpipe(gspca_dev->dev, 0),
695 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
697 gspca_dev->usb_buf, len,
699 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
702 static void reg_w1(struct gspca_dev *gspca_dev,
706 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
707 gspca_dev->usb_buf[0] = data;
708 usb_control_msg(gspca_dev->dev,
709 usb_sndctrlpipe(gspca_dev->dev, 0),
711 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
714 gspca_dev->usb_buf, 1,
717 static void reg_w(struct gspca_dev *gspca_dev,
722 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
723 value, buffer[0], buffer[1]);
725 if (len > USB_BUF_SZ) {
726 err("reg_w: buffer overflow");
730 memcpy(gspca_dev->usb_buf, buffer, len);
731 usb_control_msg(gspca_dev->dev,
732 usb_sndctrlpipe(gspca_dev->dev, 0),
734 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
736 gspca_dev->usb_buf, len,
740 /* I2C write 1 byte */
741 static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
743 struct sd *sd = (struct sd *) gspca_dev;
745 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
746 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
747 gspca_dev->usb_buf[1] = sd->i2c_base;
748 gspca_dev->usb_buf[2] = reg;
749 gspca_dev->usb_buf[3] = val;
750 gspca_dev->usb_buf[4] = 0;
751 gspca_dev->usb_buf[5] = 0;
752 gspca_dev->usb_buf[6] = 0;
753 gspca_dev->usb_buf[7] = 0x10;
754 usb_control_msg(gspca_dev->dev,
755 usb_sndctrlpipe(gspca_dev->dev, 0),
757 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
758 0x08, /* value = i2c */
760 gspca_dev->usb_buf, 8,
764 /* I2C write 8 bytes */
765 static void i2c_w8(struct gspca_dev *gspca_dev,
768 memcpy(gspca_dev->usb_buf, buffer, 8);
769 usb_control_msg(gspca_dev->dev,
770 usb_sndctrlpipe(gspca_dev->dev, 0),
772 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
773 0x08, 0, /* value, index */
774 gspca_dev->usb_buf, 8,
779 /* read 5 bytes in gspca_dev->usb_buf */
780 static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
782 struct sd *sd = (struct sd *) gspca_dev;
785 mode[0] = 0x81 | 0x10;
786 mode[1] = sd->i2c_base;
793 i2c_w8(gspca_dev, mode);
795 mode[0] = 0x81 | (5 << 4) | 0x02;
797 i2c_w8(gspca_dev, mode);
799 reg_r(gspca_dev, 0x0a, 5);
802 static int probesensor(struct gspca_dev *gspca_dev)
804 struct sd *sd = (struct sd *) gspca_dev;
806 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
808 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
810 i2c_r5(gspca_dev, 0); /* read sensor id */
811 if (gspca_dev->usb_buf[0] == 0x02
812 && gspca_dev->usb_buf[1] == 0x09
813 && gspca_dev->usb_buf[2] == 0x01
814 && gspca_dev->usb_buf[3] == 0x00
815 && gspca_dev->usb_buf[4] == 0x00) {
816 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
817 sd->sensor = SENSOR_HV7131R;
818 return SENSOR_HV7131R;
820 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
821 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
822 gspca_dev->usb_buf[2]);
823 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
827 static int configure_gpio(struct gspca_dev *gspca_dev,
830 struct sd *sd = (struct sd *) gspca_dev;
832 static const __u8 reg9a_def[] =
833 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
834 static const __u8 reg9a_sn9c325[] =
835 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
836 static const __u8 regd4[] = {0x60, 0x00, 0x00};
838 reg_w1(gspca_dev, 0xf1, 0x00);
839 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
842 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
843 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
844 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
845 switch (sd->bridge) {
847 reg9a = reg9a_sn9c325;
853 reg_w(gspca_dev, 0x9a, reg9a, 6);
855 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
857 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
859 switch (sd->sensor) {
861 reg_w1(gspca_dev, 0x02, 0x71);
862 reg_w1(gspca_dev, 0x01, 0x42);
863 reg_w1(gspca_dev, 0x17, 0x64);
864 reg_w1(gspca_dev, 0x01, 0x42);
866 /*jfm: from win trace */
868 reg_w1(gspca_dev, 0x01, 0x61);
869 reg_w1(gspca_dev, 0x17, 0xe2);
870 reg_w1(gspca_dev, 0x01, 0x60);
871 reg_w1(gspca_dev, 0x01, 0x40);
874 reg_w1(gspca_dev, 0x01, 0x63);
875 reg_w1(gspca_dev, 0x17, 0x20);
876 reg_w1(gspca_dev, 0x01, 0x42);
878 /*jfm: from win trace */
880 if (sd->bridge == BRIDGE_SN9C120) {
881 reg_w1(gspca_dev, 0x01, 0x61);
882 reg_w1(gspca_dev, 0x17, 0x20);
883 reg_w1(gspca_dev, 0x01, 0x60);
884 reg_w1(gspca_dev, 0x01, 0x40);
889 reg_w1(gspca_dev, 0x01, 0x43);
890 reg_w1(gspca_dev, 0x17, 0x61);
891 reg_w1(gspca_dev, 0x01, 0x42);
892 if (sd->sensor == SENSOR_HV7131R) {
893 if (probesensor(gspca_dev) < 0)
901 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
904 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
905 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
907 while (hv7131r_sensor_init[i][0]) {
908 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
911 i2c_w8(gspca_dev, SetSensorClk);
914 static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
918 while (mi0360_sensor_init[i][0]) {
919 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
924 static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
928 while (mo4000_sensor_init[i][0]) {
929 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
934 static void om6802_InitSensor(struct gspca_dev *gspca_dev)
938 while (om6802_sensor_init[i][0]) {
939 i2c_w8(gspca_dev, om6802_sensor_init[i]);
944 static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
948 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */
950 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */
953 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
955 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */
958 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
960 /*jfm:win i2c_r from 00 to 80*/
962 while (ov7630_sensor_init[i][0]) {
963 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
968 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
972 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
974 /* win: dble reset */
975 i2c_w8(gspca_dev, ov7648_sensor_init[i]); /* reset */
978 /* win: i2c reg read 00..7f */
979 while (ov7648_sensor_init[i][0]) {
980 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
985 static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
989 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
992 while (ov7660_sensor_init[i][0]) {
993 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
998 /* this function is called at probe time */
999 static int sd_config(struct gspca_dev *gspca_dev,
1000 const struct usb_device_id *id)
1002 struct sd *sd = (struct sd *) gspca_dev;
1005 cam = &gspca_dev->cam;
1007 cam->cam_mode = vga_mode;
1008 cam->nmodes = ARRAY_SIZE(vga_mode);
1010 sd->bridge = id->driver_info >> 16;
1011 sd->sensor = id->driver_info >> 8;
1012 sd->i2c_base = id->driver_info;
1014 sd->qindex = 4; /* set the quantization table */
1015 sd->brightness = BRIGHTNESS_DEF;
1016 sd->contrast = CONTRAST_DEF;
1017 sd->colors = COLOR_DEF;
1018 sd->blue = BLUE_BALANCE_DEF;
1019 sd->red = RED_BALANCE_DEF;
1020 sd->autogain = AUTOGAIN_DEF;
1022 sd->vflip = VFLIP_DEF;
1023 sd->infrared = INFRARED_DEF;
1025 switch (sd->sensor) {
1029 gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX);
1032 if (sd->sensor != SENSOR_OV7630)
1033 gspca_dev->ctrl_dis |= (1 << VFLIP_IDX);
1034 if (sd->sensor != SENSOR_MI0360)
1035 gspca_dev->ctrl_dis |= (1 << INFRARED_IDX);
1039 /* this function is called at probe and resume time */
1040 static int sd_init(struct gspca_dev *gspca_dev)
1042 struct sd *sd = (struct sd *) gspca_dev;
1043 /* const __u8 *sn9c1xx; */
1044 __u8 regGpio[] = { 0x29, 0x74 };
1047 /* setup a selector by bridge */
1048 reg_w1(gspca_dev, 0xf1, 0x01);
1049 reg_r(gspca_dev, 0x00, 1);
1050 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
1051 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
1052 regF1 = gspca_dev->usb_buf[0];
1053 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
1054 switch (sd->bridge) {
1055 case BRIDGE_SN9C102P:
1058 reg_w1(gspca_dev, 0x02, regGpio[1]);
1060 case BRIDGE_SN9C105:
1063 reg_w(gspca_dev, 0x01, regGpio, 2);
1065 case BRIDGE_SN9C120:
1069 reg_w(gspca_dev, 0x01, regGpio, 2);
1072 /* case BRIDGE_SN9C110: */
1073 /* case BRIDGE_SN9C325: */
1076 reg_w1(gspca_dev, 0x02, 0x62);
1080 reg_w1(gspca_dev, 0xf1, 0x01);
1085 static unsigned int setexposure(struct gspca_dev *gspca_dev,
1088 struct sd *sd = (struct sd *) gspca_dev;
1089 static const __u8 doit[] = /* update sensor */
1090 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1091 static const __u8 sensorgo[] = /* sensor on */
1092 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1093 static const __u8 gainMo[] =
1094 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1096 switch (sd->sensor) {
1097 case SENSOR_HV7131R: {
1099 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1101 Expodoit[3] = expo >> 16;
1102 Expodoit[4] = expo >> 8;
1104 i2c_w8(gspca_dev, Expodoit);
1107 case SENSOR_MI0360: {
1108 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1109 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1113 else if (expo < 0x0001)
1115 expoMi[3] = expo >> 8;
1117 i2c_w8(gspca_dev, expoMi);
1118 i2c_w8(gspca_dev, doit);
1119 i2c_w8(gspca_dev, sensorgo);
1122 case SENSOR_MO4000: {
1124 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1126 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1130 else if (expo < 0x0001)
1132 expoMof[3] = (expo & 0x03fc) >> 2;
1133 i2c_w8(gspca_dev, expoMof);
1134 expoMo10[3] = ((expo & 0x1c00) >> 10)
1135 | ((expo & 0x0003) << 4);
1136 i2c_w8(gspca_dev, expoMo10);
1137 i2c_w8(gspca_dev, gainMo);
1138 PDEBUG(D_CONF, "set exposure %d",
1139 ((expoMo10[3] & 0x07) << 10)
1141 | ((expoMo10[3] & 0x30) >> 4));
1144 case SENSOR_OM6802: {
1146 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1152 gainOm[3] = expo >> 2;
1153 i2c_w8(gspca_dev, gainOm);
1154 reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
1155 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
1162 static void setbrightness(struct gspca_dev *gspca_dev)
1164 struct sd *sd = (struct sd *) gspca_dev;
1168 k2 = ((int) sd->brightness - 0x8000) >> 10;
1169 switch (sd->sensor) {
1170 case SENSOR_HV7131R:
1171 expo = sd->brightness << 4;
1172 if (expo > 0x002dc6c0)
1174 else if (expo < 0x02a0)
1176 sd->exposure = setexposure(gspca_dev, expo);
1180 expo = sd->brightness >> 4;
1181 sd->exposure = setexposure(gspca_dev, expo);
1184 expo = sd->brightness >> 6;
1185 sd->exposure = setexposure(gspca_dev, expo);
1186 k2 = sd->brightness >> 11;
1190 reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */
1193 static void setcontrast(struct gspca_dev *gspca_dev)
1195 struct sd *sd = (struct sd *) gspca_dev;
1197 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1199 k2 = sd->contrast * 0x30 / (CONTRAST_MAX + 1) + 0x10; /* 10..40 */
1200 contrast[0] = (k2 + 1) / 2; /* red */
1201 contrast[2] = k2; /* green */
1202 contrast[4] = (k2 + 1) / 5; /* blue */
1203 reg_w(gspca_dev, 0x84, contrast, 6);
1206 static void setcolors(struct gspca_dev *gspca_dev)
1208 struct sd *sd = (struct sd *) gspca_dev;
1210 __u8 reg8a[12]; /* U & V gains */
1211 static __s16 uv[6] = { /* same as reg84 in signed decimal */
1212 -24, -38, 64, /* UR UG UB */
1213 62, -51, -9 /* VR VG VB */
1215 for (i = 0; i < 6; i++) {
1216 v = uv[i] * sd->colors / COLOR_DEF;
1218 reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
1220 reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
1223 static void setredblue(struct gspca_dev *gspca_dev)
1225 struct sd *sd = (struct sd *) gspca_dev;
1227 reg_w1(gspca_dev, 0x05, sd->red);
1228 /* reg_w1(gspca_dev, 0x07, 32); */
1229 reg_w1(gspca_dev, 0x06, sd->blue);
1232 static void setautogain(struct gspca_dev *gspca_dev)
1234 struct sd *sd = (struct sd *) gspca_dev;
1236 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1239 sd->ag_cnt = AG_CNT_START;
1244 static void setvflip(struct sd *sd)
1246 i2c_w1(&sd->gspca_dev, 0x75, /* COMN */
1247 sd->vflip ? 0x82 : 0x02);
1250 static void setinfrared(struct sd *sd)
1252 /*fixme: different sequence for StarCam Clip and StarCam 370i */
1254 i2c_w1(&sd->gspca_dev, 0x02, /* gpio */
1255 sd->infrared ? 0x66 : 0x64);
1258 /* -- start the camera -- */
1259 static int sd_start(struct gspca_dev *gspca_dev)
1261 struct sd *sd = (struct sd *) gspca_dev;
1263 __u8 reg1, reg17, reg18;
1264 const __u8 *sn9c1xx;
1266 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1267 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1268 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1269 static const __u8 CE_ov76xx[] =
1270 { 0x32, 0xdd, 0x32, 0xdd };
1272 sn9c1xx = sn_tb[(int) sd->sensor];
1273 configure_gpio(gspca_dev, sn9c1xx);
1275 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1276 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1277 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1278 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1279 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1280 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1281 reg_w1(gspca_dev, 0xd3, 0x50);
1282 reg_w1(gspca_dev, 0xc6, 0x00);
1283 reg_w1(gspca_dev, 0xc7, 0x00);
1284 reg_w1(gspca_dev, 0xc8, 0x50);
1285 reg_w1(gspca_dev, 0xc9, 0x3c);
1286 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1287 switch (sd->sensor) {
1294 /*jfm: from win trace */
1296 if (sd->bridge == BRIDGE_SN9C120) {
1305 reg_w1(gspca_dev, 0x17, reg17);
1306 /* set reg1 was here */
1307 reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */
1308 reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */
1309 reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */
1310 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
1311 reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
1312 for (i = 0; i < 8; i++)
1313 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1314 switch (sd->sensor) {
1316 reg_w1(gspca_dev, 0x9a, 0x0a);
1317 reg_w1(gspca_dev, 0x99, 0x60);
1320 if (sd->bridge == BRIDGE_SN9C120) {
1321 reg_w1(gspca_dev, 0x9a, 0x05);
1326 reg_w1(gspca_dev, 0x9a, 0x08);
1327 reg_w1(gspca_dev, 0x99, 0x59);
1331 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1333 reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */
1335 reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */
1336 reg17 = 0x61; /* 0x:20: enable sensor clock */
1337 switch (sd->sensor) {
1338 case SENSOR_HV7131R:
1339 hv7131R_InitSensor(gspca_dev);
1342 mi0360_InitSensor(gspca_dev);
1345 mo4000_InitSensor(gspca_dev);
1347 /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1348 reg1 = 0x06; /* clk 24Mz */
1350 reg17 = 0x22; /* 640 MCKSIZE */
1351 /* reg1 = 0x06; * 640 clk 24Mz (done) */
1355 om6802_InitSensor(gspca_dev);
1356 reg17 = 0x64; /* 640 MCKSIZE */
1359 ov7630_InitSensor(gspca_dev);
1365 ov7648_InitSensor(gspca_dev);
1367 /* reg1 = 0x42; * 42 - 46? */
1374 /* case SENSOR_OV7660: */
1375 ov7660_InitSensor(gspca_dev);
1376 if (sd->bridge == BRIDGE_SN9C120) {
1377 if (mode) { /* 320x240 - 160x120 */
1379 reg1 = 0x44; /* 48 Mhz, video trf eneble */
1383 reg1 = 0x06; /* 24 Mhz, video trf eneble
1384 * inverse power down */
1388 reg_w(gspca_dev, 0xc0, C0, 6);
1389 reg_w(gspca_dev, 0xca, CA, 4);
1390 switch (sd->sensor) {
1394 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
1397 reg_w(gspca_dev, 0xce, CE, 4);
1398 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1402 /* here change size mode 0 -> VGA; 1 -> CIF */
1403 reg18 = sn9c1xx[0x18] | (mode << 4);
1404 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
1406 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1407 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1409 reg_w1(gspca_dev, 0x18, reg18);
1411 reg_w1(gspca_dev, 0x17, reg17);
1412 reg_w1(gspca_dev, 0x01, reg1);
1413 switch (sd->sensor) {
1421 setbrightness(gspca_dev);
1422 setcontrast(gspca_dev);
1423 setautogain(gspca_dev);
1427 static void sd_stopN(struct gspca_dev *gspca_dev)
1429 struct sd *sd = (struct sd *) gspca_dev;
1430 static const __u8 stophv7131[] =
1431 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1432 static const __u8 stopmi0360[] =
1433 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1434 static const __u8 stopov7648[] =
1435 { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
1437 const __u8 *sn9c1xx;
1440 switch (sd->sensor) {
1441 case SENSOR_HV7131R:
1442 i2c_w8(gspca_dev, stophv7131);
1446 i2c_w8(gspca_dev, stopmi0360);
1450 i2c_w8(gspca_dev, stopov7648);
1456 /* case SENSOR_MO4000: */
1457 /* case SENSOR_OV7660: */
1460 sn9c1xx = sn_tb[(int) sd->sensor];
1461 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1462 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1463 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1464 reg_w1(gspca_dev, 0x01, data);
1465 reg_w1(gspca_dev, 0xf1, 0x00);
1468 static void do_autogain(struct gspca_dev *gspca_dev)
1470 struct sd *sd = (struct sd *) gspca_dev;
1473 __u8 luma_mean = 130;
1474 __u8 luma_delta = 20;
1476 /* Thanks S., without your advice, autobright should not work :) */
1479 if (--sd->ag_cnt >= 0)
1481 sd->ag_cnt = AG_CNT_START;
1483 delta = atomic_read(&sd->avg_lum);
1484 PDEBUG(D_FRAM, "mean lum %d", delta);
1485 if (delta < luma_mean - luma_delta ||
1486 delta > luma_mean + luma_delta) {
1487 switch (sd->sensor) {
1488 case SENSOR_HV7131R:
1489 expotimes = sd->exposure >> 8;
1490 expotimes += (luma_mean - delta) >> 4;
1493 sd->exposure = setexposure(gspca_dev,
1494 (unsigned int) (expotimes << 8));
1497 /* case SENSOR_MO4000: */
1498 /* case SENSOR_MI0360: */
1499 /* case SENSOR_OM6802: */
1500 expotimes = sd->exposure;
1501 expotimes += (luma_mean - delta) >> 6;
1504 sd->exposure = setexposure(gspca_dev,
1505 (unsigned int) expotimes);
1506 setredblue(gspca_dev);
1512 /* scan the URB packets */
1513 /* This function is run at interrupt level. */
1514 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1515 struct gspca_frame *frame, /* target */
1516 __u8 *data, /* isoc packet */
1517 int len) /* iso packet length */
1519 struct sd *sd = (struct sd *) gspca_dev;
1523 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1526 gspca_frame_add(gspca_dev, LAST_PACKET,
1527 frame, data, sof + 2);
1534 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1536 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1538 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1540 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1542 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1544 atomic_set(&sd->avg_lum, avg_lum);
1547 if (gspca_dev->last_packet_type == LAST_PACKET) {
1549 /* put the JPEG 422 header */
1550 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1552 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1555 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1557 struct sd *sd = (struct sd *) gspca_dev;
1559 sd->brightness = val;
1560 if (gspca_dev->streaming)
1561 setbrightness(gspca_dev);
1565 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1567 struct sd *sd = (struct sd *) gspca_dev;
1569 *val = sd->brightness;
1573 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1575 struct sd *sd = (struct sd *) gspca_dev;
1578 if (gspca_dev->streaming)
1579 setcontrast(gspca_dev);
1583 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1585 struct sd *sd = (struct sd *) gspca_dev;
1587 *val = sd->contrast;
1591 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1593 struct sd *sd = (struct sd *) gspca_dev;
1596 if (gspca_dev->streaming)
1597 setcolors(gspca_dev);
1601 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1603 struct sd *sd = (struct sd *) gspca_dev;
1609 static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1611 struct sd *sd = (struct sd *) gspca_dev;
1614 if (gspca_dev->streaming)
1615 setredblue(gspca_dev);
1619 static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1621 struct sd *sd = (struct sd *) gspca_dev;
1627 static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1629 struct sd *sd = (struct sd *) gspca_dev;
1632 if (gspca_dev->streaming)
1633 setredblue(gspca_dev);
1637 static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1639 struct sd *sd = (struct sd *) gspca_dev;
1645 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1647 struct sd *sd = (struct sd *) gspca_dev;
1650 if (gspca_dev->streaming)
1651 setautogain(gspca_dev);
1655 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1657 struct sd *sd = (struct sd *) gspca_dev;
1659 *val = sd->autogain;
1663 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1665 struct sd *sd = (struct sd *) gspca_dev;
1668 if (gspca_dev->streaming)
1673 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1675 struct sd *sd = (struct sd *) gspca_dev;
1681 static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val)
1683 struct sd *sd = (struct sd *) gspca_dev;
1686 if (gspca_dev->streaming)
1691 static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val)
1693 struct sd *sd = (struct sd *) gspca_dev;
1695 *val = sd->infrared;
1699 /* sub-driver description */
1700 static const struct sd_desc sd_desc = {
1701 .name = MODULE_NAME,
1703 .nctrls = ARRAY_SIZE(sd_ctrls),
1704 .config = sd_config,
1708 .pkt_scan = sd_pkt_scan,
1709 .dq_callback = do_autogain,
1712 /* -- module initialisation -- */
1713 #define BSI(bridge, sensor, i2c_addr) \
1714 .driver_info = (BRIDGE_ ## bridge << 16) \
1715 | (SENSOR_ ## sensor << 8) \
1717 static const __devinitdata struct usb_device_id device_table[] = {
1718 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1719 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1720 {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)},
1722 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1723 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1724 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1725 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1727 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
1728 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1729 {USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)},
1730 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1732 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1733 /* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1734 /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1735 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1736 /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1737 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1738 /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1739 /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1740 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1741 /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1742 /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1743 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1744 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1745 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1746 {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
1748 /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1749 /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1750 /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1751 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1753 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c110?*/
1754 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1755 {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
1756 /* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
1757 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1758 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1760 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1761 {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)},
1762 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1763 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1764 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1765 /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
1767 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
1770 MODULE_DEVICE_TABLE(usb, device_table);
1772 /* -- device connect -- */
1773 static int sd_probe(struct usb_interface *intf,
1774 const struct usb_device_id *id)
1776 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1780 static struct usb_driver sd_driver = {
1781 .name = MODULE_NAME,
1782 .id_table = device_table,
1784 .disconnect = gspca_disconnect,
1786 .suspend = gspca_suspend,
1787 .resume = gspca_resume,
1791 /* -- module insert / remove -- */
1792 static int __init sd_mod_init(void)
1794 if (usb_register(&sd_driver) < 0)
1799 static void __exit sd_mod_exit(void)
1801 usb_deregister(&sd_driver);
1802 info("deregistered");
1805 module_init(sd_mod_init);
1806 module_exit(sd_mod_exit);