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;
44 __u8 vflip; /* ov7630 only */
45 __u8 infrared; /* mi0360 only */
48 #define AG_CNT_START 13
52 #define BRIDGE_SN9C102P 0
53 #define BRIDGE_SN9C105 1
54 #define BRIDGE_SN9C110 2
55 #define BRIDGE_SN9C120 3
56 #define BRIDGE_SN9C325 4
57 char sensor; /* Type of image sensor chip */
58 #define SENSOR_HV7131R 0
59 #define SENSOR_MI0360 1
60 #define SENSOR_MO4000 2
61 #define SENSOR_OM6802 3
62 #define SENSOR_OV7630 4
63 #define SENSOR_OV7648 5
64 #define SENSOR_OV7660 6
65 unsigned char i2c_base;
68 /* V4L2 controls supported by the driver */
69 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
70 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
71 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
72 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
73 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
74 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
75 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
76 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
77 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
78 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
79 static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val);
80 static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val);
82 static struct ctrl sd_ctrls[] = {
85 .id = V4L2_CID_BRIGHTNESS,
86 .type = V4L2_CTRL_TYPE_INTEGER,
89 #define BRIGHTNESS_MAX 0xffff
90 .maximum = BRIGHTNESS_MAX,
92 #define BRIGHTNESS_DEF 0x7fff
93 .default_value = BRIGHTNESS_DEF,
95 .set = sd_setbrightness,
96 .get = sd_getbrightness,
100 .id = V4L2_CID_CONTRAST,
101 .type = V4L2_CTRL_TYPE_INTEGER,
104 #define CONTRAST_MAX 127
105 .maximum = CONTRAST_MAX,
107 #define CONTRAST_DEF 63
108 .default_value = CONTRAST_DEF,
110 .set = sd_setcontrast,
111 .get = sd_getcontrast,
115 .id = V4L2_CID_SATURATION,
116 .type = V4L2_CTRL_TYPE_INTEGER,
122 .default_value = COLOR_DEF,
127 #define AUTOGAIN_IDX 3
130 .id = V4L2_CID_AUTOGAIN,
131 .type = V4L2_CTRL_TYPE_BOOLEAN,
136 #define AUTOGAIN_DEF 1
137 .default_value = AUTOGAIN_DEF,
139 .set = sd_setautogain,
140 .get = sd_getautogain,
146 .id = V4L2_CID_VFLIP,
147 .type = V4L2_CTRL_TYPE_BOOLEAN,
153 .default_value = VFLIP_DEF,
159 #define INFRARED_IDX 5
162 .id = V4L2_CID_INFRARED,
163 .type = V4L2_CTRL_TYPE_BOOLEAN,
168 #define INFRARED_DEF 0
169 .default_value = INFRARED_DEF,
171 .set = sd_setinfrared,
172 .get = sd_getinfrared,
176 static struct v4l2_pix_format vga_mode[] = {
177 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
179 .sizeimage = 160 * 120 * 4 / 8 + 590,
180 .colorspace = V4L2_COLORSPACE_JPEG,
182 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
184 .sizeimage = 320 * 240 * 3 / 8 + 590,
185 .colorspace = V4L2_COLORSPACE_JPEG,
187 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
189 .sizeimage = 640 * 480 * 3 / 8 + 590,
190 .colorspace = V4L2_COLORSPACE_JPEG,
194 /*Data from sn9c102p+hv71331r */
195 static const __u8 sn_hv7131[] = {
196 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
197 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
198 /* reg8 reg9 rega regb regc regd rege regf */
199 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
200 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
201 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
202 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
203 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
206 static const __u8 sn_mi0360[] = {
207 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
208 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
209 /* reg8 reg9 rega regb regc regd rege regf */
210 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
211 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
212 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
213 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
214 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
217 static const __u8 sn_mo4000[] = {
218 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
219 0x12, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
220 /* reg8 reg9 rega regb regc regd rege regf */
221 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
223 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
224 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
225 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
228 static const __u8 sn_om6802[] = {
229 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
230 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
231 /* reg8 reg9 rega regb regc regd rege regf */
232 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
234 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
235 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
236 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf,
238 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef,
242 static const __u8 sn_ov7630[] = {
243 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
244 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20,
245 /* reg8 reg9 rega regb regc regd rege regf */
246 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10,
247 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
248 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
249 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
250 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
253 static const __u8 sn_ov7648[] = {
254 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
255 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
256 /* reg8 reg9 rega regb regc regd rege regf */
257 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
258 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
259 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00,
260 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
261 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00
264 static const __u8 sn_ov7660[] = {
265 /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
266 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
267 /* reg8 reg9 rega regb regc regd rege regf */
268 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
269 /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
270 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
271 /* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */
272 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
275 /* sequence specific to the sensors - !! index = SENSOR_xxx */
276 static const __u8 *sn_tb[] = {
286 static const __u8 gamma_def[] = {
287 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
288 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
291 /* color matrix and offsets */
292 static const __u8 reg84[] = {
293 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */
294 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */
295 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */
296 0x00, 0x00, 0x00 /* YUV offsets */
298 static const __u8 hv7131r_sensor_init[][8] = {
299 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
300 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
301 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
302 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
305 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
308 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
309 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
310 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
311 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
312 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
313 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
314 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
316 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
317 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
318 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
319 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
320 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
322 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
323 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
324 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
325 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
326 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
329 static const __u8 mi0360_sensor_init[][8] = {
330 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
331 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
332 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
333 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
334 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
335 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
336 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
337 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
338 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
339 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
340 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
341 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
342 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
343 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
344 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
345 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
346 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
347 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
348 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
349 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
350 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
351 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
352 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
353 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
354 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
355 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
356 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
357 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
358 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
359 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
360 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
361 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
362 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
364 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
365 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
366 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
367 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
368 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
370 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
371 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
372 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
373 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
375 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
376 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
377 /* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
378 /* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
379 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
380 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
383 static const __u8 mo4000_sensor_init[][8] = {
384 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
385 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
386 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
387 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
388 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
389 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
390 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
391 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
392 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
393 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
394 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
395 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
396 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
397 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
398 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
399 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
400 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
401 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
402 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
403 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
406 static __u8 om6802_sensor_init[][8] = {
407 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
408 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
409 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
410 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
411 /* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
412 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
413 /* white balance & auto-exposure */
414 /* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
416 /* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
417 * max AGC value in AE */
418 /* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
420 /* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
421 * preset brightness */
422 /* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
424 /* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
426 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
427 /* luminance mode (0x4f = AE) */
428 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
430 /* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
432 /* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
434 /* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
435 /* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
436 /* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
437 /* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
440 static const __u8 ov7630_sensor_init[][8] = {
441 {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
442 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
443 /* win: delay 20ms */
444 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
445 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
446 /* win: delay 20ms */
447 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
448 /* win: i2c_r from 00 to 80 */
449 {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
450 {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
451 {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
452 {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
453 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
454 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
455 {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
456 {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
457 {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
458 {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
459 {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
460 {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
461 {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
462 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
463 {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
464 {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
465 {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
466 {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
467 {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
468 {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
469 {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
470 {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
471 {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
472 {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
473 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
474 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
476 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
477 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
478 /*fixme: + 0x12, 0x04*/
479 /* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN
481 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
482 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
483 {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
485 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
486 {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
487 {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
489 {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
490 /* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
494 static const __u8 ov7648_sensor_init[][8] = {
495 {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
496 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
497 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
498 {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
499 {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
500 {0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
501 {0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
502 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
503 {0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
504 {0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
505 {0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
506 {0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
507 {0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
508 {0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
509 {0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
510 {0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
511 {0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
512 {0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
513 {0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
514 {0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
515 {0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
517 {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
518 /* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
519 /* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
520 {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10},
522 /* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
523 /* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, jfm done */
524 {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
525 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
526 /* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
527 /* {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, * GAIN - def */
528 /* {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10}, * B R - def: 80 */
530 {0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
531 /* {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
532 /* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
533 /* {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
534 /* {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
535 /* {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10}, * B R - def: 80 */
540 static const __u8 ov7660_sensor_init[][8] = {
541 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
543 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
544 /* Outformat = rawRGB */
545 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
546 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
547 /* GAIN BLUE RED VREF */
548 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
549 /* COM 1 BAVE GEAVE AECHH */
550 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
551 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
552 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
553 /* AECH CLKRC COM7 COM8 */
554 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
555 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
556 /* HSTART HSTOP VSTRT VSTOP */
557 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
558 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
559 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
560 /* BOS GBOS GROS ROS (BGGR offset) */
561 /* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
562 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
563 /* AEW AEB VPT BBIAS */
564 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
565 /* GbBIAS RSVD EXHCH EXHCL */
566 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
567 /* RBIAS ADVFL ASDVFH YAVE */
568 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
569 /* HSYST HSYEN HREF */
570 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
571 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
572 /* ADC ACOM OFON TSLB */
573 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
574 /* COM11 COM12 COM13 COM14 */
575 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
576 /* EDGE COM15 COM16 COM17 */
577 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
578 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
579 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
580 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
581 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
582 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
583 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
584 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
585 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
586 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
587 /* LCC1 LCC2 LCC3 LCC4 */
588 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
589 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
590 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
591 /* band gap reference [0:3] DBLV */
592 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
593 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
594 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
595 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
596 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
597 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
598 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
599 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
600 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
601 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
602 /****** (some exchanges in the win trace) ******/
603 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
604 /* bits[3..0]reserved */
605 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
606 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
607 /* VREF vertical frame ctrl */
608 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
609 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
610 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
611 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
612 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
613 /* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
614 /****** (some exchanges in the win trace) ******/
615 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
616 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
617 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
618 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
619 /* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
620 /****** (some exchanges in the win trace) ******/
621 /******!! startsensor KO if changed !!****/
622 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
623 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
624 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
625 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
629 static const __u8 qtable4[] = {
630 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
631 0x06, 0x08, 0x0A, 0x11,
632 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
633 0x19, 0x19, 0x17, 0x15,
634 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
635 0x21, 0x2E, 0x21, 0x23,
636 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
637 0x25, 0x29, 0x2C, 0x29,
638 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
639 0x17, 0x1B, 0x29, 0x29,
640 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
641 0x29, 0x29, 0x29, 0x29,
642 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
643 0x29, 0x29, 0x29, 0x29,
644 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
645 0x29, 0x29, 0x29, 0x29
648 /* read <len> bytes to gspca_dev->usb_buf */
649 static void reg_r(struct gspca_dev *gspca_dev,
650 __u16 value, int len)
653 if (len > USB_BUF_SZ) {
654 err("reg_r: buffer overflow");
658 usb_control_msg(gspca_dev->dev,
659 usb_rcvctrlpipe(gspca_dev->dev, 0),
661 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
663 gspca_dev->usb_buf, len,
665 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
668 static void reg_w1(struct gspca_dev *gspca_dev,
672 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
673 gspca_dev->usb_buf[0] = data;
674 usb_control_msg(gspca_dev->dev,
675 usb_sndctrlpipe(gspca_dev->dev, 0),
677 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
680 gspca_dev->usb_buf, 1,
683 static void reg_w(struct gspca_dev *gspca_dev,
688 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
689 value, buffer[0], buffer[1]);
691 if (len > USB_BUF_SZ) {
692 err("reg_w: buffer overflow");
696 memcpy(gspca_dev->usb_buf, buffer, len);
697 usb_control_msg(gspca_dev->dev,
698 usb_sndctrlpipe(gspca_dev->dev, 0),
700 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
702 gspca_dev->usb_buf, len,
706 /* I2C write 1 byte */
707 static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
709 struct sd *sd = (struct sd *) gspca_dev;
711 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
712 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
713 gspca_dev->usb_buf[1] = sd->i2c_base;
714 gspca_dev->usb_buf[2] = reg;
715 gspca_dev->usb_buf[3] = val;
716 gspca_dev->usb_buf[4] = 0;
717 gspca_dev->usb_buf[5] = 0;
718 gspca_dev->usb_buf[6] = 0;
719 gspca_dev->usb_buf[7] = 0x10;
720 usb_control_msg(gspca_dev->dev,
721 usb_sndctrlpipe(gspca_dev->dev, 0),
723 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
724 0x08, /* value = i2c */
726 gspca_dev->usb_buf, 8,
730 /* I2C write 8 bytes */
731 static void i2c_w8(struct gspca_dev *gspca_dev,
734 memcpy(gspca_dev->usb_buf, buffer, 8);
735 usb_control_msg(gspca_dev->dev,
736 usb_sndctrlpipe(gspca_dev->dev, 0),
738 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
739 0x08, 0, /* value, index */
740 gspca_dev->usb_buf, 8,
745 /* read 5 bytes in gspca_dev->usb_buf */
746 static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
748 struct sd *sd = (struct sd *) gspca_dev;
751 mode[0] = 0x81 | 0x10;
752 mode[1] = sd->i2c_base;
759 i2c_w8(gspca_dev, mode);
761 mode[0] = 0x81 | (5 << 4) | 0x02;
763 i2c_w8(gspca_dev, mode);
765 reg_r(gspca_dev, 0x0a, 5);
768 static int probesensor(struct gspca_dev *gspca_dev)
770 struct sd *sd = (struct sd *) gspca_dev;
772 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
774 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
776 i2c_r5(gspca_dev, 0); /* read sensor id */
777 if (gspca_dev->usb_buf[0] == 0x02
778 && gspca_dev->usb_buf[1] == 0x09
779 && gspca_dev->usb_buf[2] == 0x01
780 && gspca_dev->usb_buf[3] == 0x00
781 && gspca_dev->usb_buf[4] == 0x00) {
782 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
783 sd->sensor = SENSOR_HV7131R;
784 return SENSOR_HV7131R;
786 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
787 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
788 gspca_dev->usb_buf[2]);
789 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
793 static int configure_gpio(struct gspca_dev *gspca_dev,
796 struct sd *sd = (struct sd *) gspca_dev;
798 static const __u8 reg9a_def[] =
799 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
800 static const __u8 reg9a_sn9c325[] =
801 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
802 static const __u8 regd4[] = {0x60, 0x00, 0x00};
804 reg_w1(gspca_dev, 0xf1, 0x00);
805 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
808 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
809 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
810 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
811 switch (sd->bridge) {
813 reg9a = reg9a_sn9c325;
819 reg_w(gspca_dev, 0x9a, reg9a, 6);
821 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
823 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
825 switch (sd->sensor) {
827 reg_w1(gspca_dev, 0x02, 0x71);
828 reg_w1(gspca_dev, 0x01, 0x42);
829 reg_w1(gspca_dev, 0x17, 0x64);
830 reg_w1(gspca_dev, 0x01, 0x42);
832 /*jfm: from win trace */
834 reg_w1(gspca_dev, 0x01, 0x61);
835 reg_w1(gspca_dev, 0x17, 0xe2);
836 reg_w1(gspca_dev, 0x01, 0x60);
837 reg_w1(gspca_dev, 0x01, 0x40);
840 reg_w1(gspca_dev, 0x01, 0x63);
841 reg_w1(gspca_dev, 0x17, 0x20);
842 reg_w1(gspca_dev, 0x01, 0x42);
844 /*jfm: from win trace */
846 if (sd->bridge == BRIDGE_SN9C120) {
847 reg_w1(gspca_dev, 0x01, 0x61);
848 reg_w1(gspca_dev, 0x17, 0x20);
849 reg_w1(gspca_dev, 0x01, 0x60);
850 reg_w1(gspca_dev, 0x01, 0x40);
855 reg_w1(gspca_dev, 0x01, 0x43);
856 reg_w1(gspca_dev, 0x17, 0x61);
857 reg_w1(gspca_dev, 0x01, 0x42);
858 if (sd->sensor == SENSOR_HV7131R) {
859 if (probesensor(gspca_dev) < 0)
867 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
870 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
871 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
873 while (hv7131r_sensor_init[i][0]) {
874 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
877 i2c_w8(gspca_dev, SetSensorClk);
880 static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
884 while (mi0360_sensor_init[i][0]) {
885 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
890 static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
894 while (mo4000_sensor_init[i][0]) {
895 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
900 static void om6802_InitSensor(struct gspca_dev *gspca_dev)
904 while (om6802_sensor_init[i][0]) {
905 i2c_w8(gspca_dev, om6802_sensor_init[i]);
910 static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
914 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */
916 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */
919 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
921 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */
924 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
926 /*jfm:win i2c_r from 00 to 80*/
928 while (ov7630_sensor_init[i][0]) {
929 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
934 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
938 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
940 /* win: dble reset */
941 i2c_w8(gspca_dev, ov7648_sensor_init[i]); /* reset */
944 /* win: i2c reg read 00..7f */
945 while (ov7648_sensor_init[i][0]) {
946 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
951 static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
955 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
958 while (ov7660_sensor_init[i][0]) {
959 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
964 /* this function is called at probe time */
965 static int sd_config(struct gspca_dev *gspca_dev,
966 const struct usb_device_id *id)
968 struct sd *sd = (struct sd *) gspca_dev;
971 cam = &gspca_dev->cam;
973 cam->cam_mode = vga_mode;
974 cam->nmodes = ARRAY_SIZE(vga_mode);
976 sd->bridge = id->driver_info >> 16;
977 sd->sensor = id->driver_info >> 8;
978 sd->i2c_base = id->driver_info;
980 sd->qindex = 4; /* set the quantization table */
981 sd->brightness = BRIGHTNESS_DEF;
982 sd->contrast = CONTRAST_DEF;
983 sd->colors = COLOR_DEF;
984 sd->autogain = AUTOGAIN_DEF;
986 sd->vflip = VFLIP_DEF;
987 sd->infrared = INFRARED_DEF;
989 switch (sd->sensor) {
993 gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX);
996 if (sd->sensor != SENSOR_OV7630)
997 gspca_dev->ctrl_dis |= (1 << VFLIP_IDX);
998 if (sd->sensor != SENSOR_MI0360)
999 gspca_dev->ctrl_dis |= (1 << INFRARED_IDX);
1003 /* this function is called at probe and resume time */
1004 static int sd_init(struct gspca_dev *gspca_dev)
1006 struct sd *sd = (struct sd *) gspca_dev;
1007 /* const __u8 *sn9c1xx; */
1008 __u8 regGpio[] = { 0x29, 0x74 };
1011 /* setup a selector by bridge */
1012 reg_w1(gspca_dev, 0xf1, 0x01);
1013 reg_r(gspca_dev, 0x00, 1);
1014 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
1015 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
1016 regF1 = gspca_dev->usb_buf[0];
1017 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
1018 switch (sd->bridge) {
1019 case BRIDGE_SN9C102P:
1022 reg_w1(gspca_dev, 0x02, regGpio[1]);
1024 case BRIDGE_SN9C105:
1027 reg_w(gspca_dev, 0x01, regGpio, 2);
1029 case BRIDGE_SN9C120:
1033 reg_w(gspca_dev, 0x01, regGpio, 2);
1036 /* case BRIDGE_SN9C110: */
1037 /* case BRIDGE_SN9C325: */
1040 reg_w1(gspca_dev, 0x02, 0x62);
1044 reg_w1(gspca_dev, 0xf1, 0x01);
1049 static unsigned int setexposure(struct gspca_dev *gspca_dev,
1052 struct sd *sd = (struct sd *) gspca_dev;
1053 static const __u8 doit[] = /* update sensor */
1054 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1055 static const __u8 sensorgo[] = /* sensor on */
1056 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1057 static const __u8 gainMo[] =
1058 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1060 switch (sd->sensor) {
1061 case SENSOR_HV7131R: {
1063 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1065 Expodoit[3] = expo >> 16;
1066 Expodoit[4] = expo >> 8;
1068 i2c_w8(gspca_dev, Expodoit);
1071 case SENSOR_MI0360: {
1072 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1073 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1077 else if (expo < 0x0001)
1079 expoMi[3] = expo >> 8;
1081 i2c_w8(gspca_dev, expoMi);
1082 i2c_w8(gspca_dev, doit);
1083 i2c_w8(gspca_dev, sensorgo);
1086 case SENSOR_MO4000: {
1088 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1090 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1094 else if (expo < 0x0001)
1096 expoMof[3] = (expo & 0x03fc) >> 2;
1097 i2c_w8(gspca_dev, expoMof);
1098 expoMo10[3] = ((expo & 0x1c00) >> 10)
1099 | ((expo & 0x0003) << 4);
1100 i2c_w8(gspca_dev, expoMo10);
1101 i2c_w8(gspca_dev, gainMo);
1102 PDEBUG(D_CONF, "set exposure %d",
1103 ((expoMo10[3] & 0x07) << 10)
1105 | ((expoMo10[3] & 0x30) >> 4));
1108 case SENSOR_OM6802: {
1110 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1116 gainOm[3] = expo >> 2;
1117 i2c_w8(gspca_dev, gainOm);
1118 reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
1119 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
1126 /* this function is used for sensors o76xx only */
1127 static void setbrightcont(struct gspca_dev *gspca_dev)
1129 struct sd *sd = (struct sd *) gspca_dev;
1131 __u8 reg84_full[0x15];
1133 memcpy(reg84_full, reg84, sizeof reg84_full);
1134 val = sd->contrast * 0x30 / CONTRAST_MAX + 0x10; /* 10..40 */
1135 reg84_full[0] = (val + 1) / 2; /* red */
1136 reg84_full[2] = val; /* green */
1137 reg84_full[4] = (val + 1) / 5; /* blue */
1138 val = (sd->brightness - BRIGHTNESS_DEF) * 0x10
1140 reg84_full[0x12] = val & 0x1f; /* 5:0 signed value */
1141 reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full);
1144 /* sensor != ov76xx */
1145 static void setbrightness(struct gspca_dev *gspca_dev)
1147 struct sd *sd = (struct sd *) gspca_dev;
1151 k2 = sd->brightness >> 10;
1152 switch (sd->sensor) {
1153 case SENSOR_HV7131R:
1154 expo = sd->brightness << 4;
1155 if (expo > 0x002dc6c0)
1157 else if (expo < 0x02a0)
1159 sd->exposure = setexposure(gspca_dev, expo);
1163 expo = sd->brightness >> 4;
1164 sd->exposure = setexposure(gspca_dev, expo);
1167 expo = sd->brightness >> 6;
1168 sd->exposure = setexposure(gspca_dev, expo);
1169 k2 = sd->brightness >> 11;
1173 reg_w1(gspca_dev, 0x96, k2);
1176 /* sensor != ov76xx */
1177 static void setcontrast(struct gspca_dev *gspca_dev)
1179 struct sd *sd = (struct sd *) gspca_dev;
1181 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1185 contrast[0] = (k2 + 1) >> 1;
1186 contrast[4] = (k2 + 1) / 5;
1187 reg_w(gspca_dev, 0x84, contrast, 6);
1190 static void setcolors(struct gspca_dev *gspca_dev)
1192 struct sd *sd = (struct sd *) gspca_dev;
1195 if (sd->colors >= 32) {
1196 red = 32 + (sd->colors - 32) / 2;
1197 blue = 64 - sd->colors;
1200 blue = 32 + (32 - sd->colors) / 2;
1202 reg_w1(gspca_dev, 0x05, red);
1203 /* reg_w1(gspca_dev, 0x07, 32); */
1204 reg_w1(gspca_dev, 0x06, blue);
1207 static void setautogain(struct gspca_dev *gspca_dev)
1209 struct sd *sd = (struct sd *) gspca_dev;
1211 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1214 sd->ag_cnt = AG_CNT_START;
1219 static void setvflip(struct sd *sd)
1221 i2c_w1(&sd->gspca_dev, 0x75, /* COMN */
1222 sd->vflip ? 0x82 : 0x02);
1225 static void setinfrared(struct sd *sd)
1227 /*fixme: different sequence for StarCam Clip and StarCam 370i */
1229 i2c_w1(&sd->gspca_dev, 0x02, /* gpio */
1230 sd->infrared ? 0x66 : 0x64);
1233 /* -- start the camera -- */
1234 static int sd_start(struct gspca_dev *gspca_dev)
1236 struct sd *sd = (struct sd *) gspca_dev;
1238 __u8 reg1, reg17, reg18;
1239 const __u8 *sn9c1xx;
1241 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1242 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1243 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1244 static const __u8 CE_ov76xx[] =
1245 { 0x32, 0xdd, 0x32, 0xdd };
1247 sn9c1xx = sn_tb[(int) sd->sensor];
1248 configure_gpio(gspca_dev, sn9c1xx);
1250 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1251 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1252 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1253 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1254 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1255 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1256 reg_w1(gspca_dev, 0xd3, 0x50);
1257 reg_w1(gspca_dev, 0xc6, 0x00);
1258 reg_w1(gspca_dev, 0xc7, 0x00);
1259 reg_w1(gspca_dev, 0xc8, 0x50);
1260 reg_w1(gspca_dev, 0xc9, 0x3c);
1261 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1262 switch (sd->sensor) {
1269 /*jfm: from win trace */
1271 if (sd->bridge == BRIDGE_SN9C120) {
1280 reg_w1(gspca_dev, 0x17, reg17);
1281 /* set reg1 was here */
1282 reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
1283 reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
1284 reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
1285 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
1286 reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
1287 for (i = 0; i < 8; i++)
1288 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1289 switch (sd->sensor) {
1291 reg_w1(gspca_dev, 0x9a, 0x0a);
1292 reg_w1(gspca_dev, 0x99, 0x60);
1295 if (sd->bridge == BRIDGE_SN9C120) {
1296 reg_w1(gspca_dev, 0x9a, 0x05);
1301 reg_w1(gspca_dev, 0x9a, 0x08);
1302 reg_w1(gspca_dev, 0x99, 0x59);
1306 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1308 reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */
1310 reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */
1311 reg17 = 0x61; /* 0x:20: enable sensor clock */
1312 switch (sd->sensor) {
1313 case SENSOR_HV7131R:
1314 hv7131R_InitSensor(gspca_dev);
1317 mi0360_InitSensor(gspca_dev);
1320 mo4000_InitSensor(gspca_dev);
1322 /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1323 reg1 = 0x06; /* clk 24Mz */
1325 reg17 = 0x22; /* 640 MCKSIZE */
1326 /* reg1 = 0x06; * 640 clk 24Mz (done) */
1330 om6802_InitSensor(gspca_dev);
1331 reg17 = 0x64; /* 640 MCKSIZE */
1334 ov7630_InitSensor(gspca_dev);
1340 ov7648_InitSensor(gspca_dev);
1342 /* reg1 = 0x42; * 42 - 46? */
1349 /* case SENSOR_OV7660: */
1350 ov7660_InitSensor(gspca_dev);
1352 /* reg17 = 0x21; * 320 */
1354 /* reg1 = 0x46; (done) */
1356 if (sd->bridge == BRIDGE_SN9C120) {
1358 reg1 = 0x44; /* 48 Mhz, video trf eneble */
1361 reg1 = 0x06; /* 24 Mhz, video trf eneble
1362 * inverse power down */
1367 reg_w(gspca_dev, 0xc0, C0, 6);
1368 reg_w(gspca_dev, 0xca, CA, 4);
1369 switch (sd->sensor) {
1373 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
1376 reg_w(gspca_dev, 0xce, CE, 4);
1377 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1381 /* here change size mode 0 -> VGA; 1 -> CIF */
1382 reg18 = sn9c1xx[0x18] | (mode << 4);
1383 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
1385 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1386 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1388 reg_w1(gspca_dev, 0x18, reg18);
1390 reg_w1(gspca_dev, 0x17, reg17);
1391 reg_w1(gspca_dev, 0x01, reg1);
1392 switch (sd->sensor) {
1396 case SENSOR_HV7131R:
1399 setbrightness(gspca_dev);
1400 setcontrast(gspca_dev);
1405 default: /* OV76xx */
1406 setbrightcont(gspca_dev);
1409 setautogain(gspca_dev);
1413 static void sd_stopN(struct gspca_dev *gspca_dev)
1415 struct sd *sd = (struct sd *) gspca_dev;
1416 static const __u8 stophv7131[] =
1417 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1418 static const __u8 stopmi0360[] =
1419 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1420 static const __u8 stopov7648[] =
1421 { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
1423 const __u8 *sn9c1xx;
1426 switch (sd->sensor) {
1427 case SENSOR_HV7131R:
1428 i2c_w8(gspca_dev, stophv7131);
1432 i2c_w8(gspca_dev, stopmi0360);
1436 i2c_w8(gspca_dev, stopov7648);
1442 /* case SENSOR_MO4000: */
1443 /* case SENSOR_OV7660: */
1446 sn9c1xx = sn_tb[(int) sd->sensor];
1447 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1448 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1449 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1450 reg_w1(gspca_dev, 0x01, data);
1451 reg_w1(gspca_dev, 0xf1, 0x00);
1454 static void do_autogain(struct gspca_dev *gspca_dev)
1456 struct sd *sd = (struct sd *) gspca_dev;
1459 __u8 luma_mean = 130;
1460 __u8 luma_delta = 20;
1462 /* Thanks S., without your advice, autobright should not work :) */
1465 if (--sd->ag_cnt >= 0)
1467 sd->ag_cnt = AG_CNT_START;
1469 delta = atomic_read(&sd->avg_lum);
1470 PDEBUG(D_FRAM, "mean lum %d", delta);
1471 if (delta < luma_mean - luma_delta ||
1472 delta > luma_mean + luma_delta) {
1473 switch (sd->sensor) {
1474 case SENSOR_HV7131R:
1475 expotimes = sd->exposure >> 8;
1476 expotimes += (luma_mean - delta) >> 4;
1479 sd->exposure = setexposure(gspca_dev,
1480 (unsigned int) (expotimes << 8));
1483 /* case SENSOR_MO4000: */
1484 /* case SENSOR_MI0360: */
1485 /* case SENSOR_OM6802: */
1486 expotimes = sd->exposure;
1487 expotimes += (luma_mean - delta) >> 6;
1490 sd->exposure = setexposure(gspca_dev,
1491 (unsigned int) expotimes);
1492 setcolors(gspca_dev);
1498 /* scan the URB packets */
1499 /* This function is run at interrupt level. */
1500 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1501 struct gspca_frame *frame, /* target */
1502 __u8 *data, /* isoc packet */
1503 int len) /* iso packet length */
1505 struct sd *sd = (struct sd *) gspca_dev;
1509 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1512 gspca_frame_add(gspca_dev, LAST_PACKET,
1513 frame, data, sof + 2);
1520 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1522 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1524 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1526 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1528 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1530 atomic_set(&sd->avg_lum, avg_lum);
1533 if (gspca_dev->last_packet_type == LAST_PACKET) {
1535 /* put the JPEG 422 header */
1536 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1538 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1541 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1543 struct sd *sd = (struct sd *) gspca_dev;
1545 sd->brightness = val;
1546 if (gspca_dev->streaming) {
1547 switch (sd->sensor) {
1548 case SENSOR_HV7131R:
1552 setbrightness(gspca_dev);
1554 default: /* OV76xx */
1555 setbrightcont(gspca_dev);
1562 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1564 struct sd *sd = (struct sd *) gspca_dev;
1566 *val = sd->brightness;
1570 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1572 struct sd *sd = (struct sd *) gspca_dev;
1575 if (gspca_dev->streaming) {
1576 switch (sd->sensor) {
1577 case SENSOR_HV7131R:
1581 setcontrast(gspca_dev);
1583 default: /* OV76xx */
1584 setbrightcont(gspca_dev);
1591 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1593 struct sd *sd = (struct sd *) gspca_dev;
1595 *val = sd->contrast;
1599 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1601 struct sd *sd = (struct sd *) gspca_dev;
1604 if (gspca_dev->streaming)
1605 setcolors(gspca_dev);
1609 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1611 struct sd *sd = (struct sd *) gspca_dev;
1617 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1619 struct sd *sd = (struct sd *) gspca_dev;
1622 if (gspca_dev->streaming)
1623 setautogain(gspca_dev);
1627 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1629 struct sd *sd = (struct sd *) gspca_dev;
1631 *val = sd->autogain;
1635 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1637 struct sd *sd = (struct sd *) gspca_dev;
1640 if (gspca_dev->streaming)
1645 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1647 struct sd *sd = (struct sd *) gspca_dev;
1653 static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val)
1655 struct sd *sd = (struct sd *) gspca_dev;
1658 if (gspca_dev->streaming)
1663 static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val)
1665 struct sd *sd = (struct sd *) gspca_dev;
1667 *val = sd->infrared;
1671 /* sub-driver description */
1672 static const struct sd_desc sd_desc = {
1673 .name = MODULE_NAME,
1675 .nctrls = ARRAY_SIZE(sd_ctrls),
1676 .config = sd_config,
1680 .pkt_scan = sd_pkt_scan,
1681 .dq_callback = do_autogain,
1684 /* -- module initialisation -- */
1685 #define BSI(bridge, sensor, i2c_addr) \
1686 .driver_info = (BRIDGE_ ## bridge << 16) \
1687 | (SENSOR_ ## sensor << 8) \
1689 static const __devinitdata struct usb_device_id device_table[] = {
1690 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1691 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1692 {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)},
1693 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1694 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1695 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1697 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
1698 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1699 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1701 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1702 /* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1703 /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1704 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1705 /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1706 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1707 /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1708 /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1709 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1710 /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1711 /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1712 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1713 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1714 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1715 {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
1717 /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1718 /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1719 /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1720 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1722 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c110?*/
1723 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1724 {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
1725 /* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
1726 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1727 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1729 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1730 {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)},
1731 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1732 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1733 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1734 /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
1736 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
1739 MODULE_DEVICE_TABLE(usb, device_table);
1741 /* -- device connect -- */
1742 static int sd_probe(struct usb_interface *intf,
1743 const struct usb_device_id *id)
1745 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1749 static struct usb_driver sd_driver = {
1750 .name = MODULE_NAME,
1751 .id_table = device_table,
1753 .disconnect = gspca_disconnect,
1755 .suspend = gspca_suspend,
1756 .resume = gspca_resume,
1760 /* -- module insert / remove -- */
1761 static int __init sd_mod_init(void)
1763 if (usb_register(&sd_driver) < 0)
1768 static void __exit sd_mod_exit(void)
1770 usb_deregister(&sd_driver);
1771 info("deregistered");
1774 module_init(sd_mod_init);
1775 module_exit(sd_mod_exit);