57232ba96b4ae06460bfe953a4be8185e51d17a2
[linux-2.6.git] / drivers / media / video / gspca / sonixj.c
1 /*
2  *              Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3  *              Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4  *
5  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6  *
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
10  * any later version.
11  *
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.
16  *
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
20  */
21
22 #define MODULE_NAME "sonixj"
23
24 #include "gspca.h"
25 #include "jpeg.h"
26
27 #define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0)
28
29 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30 MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
31 MODULE_LICENSE("GPL");
32
33 /* specific webcam descriptor */
34 struct sd {
35         struct gspca_dev gspca_dev;     /* !! must be the first item */
36
37         atomic_t avg_lum;
38         unsigned int exposure;
39
40         __u16 brightness;
41         __u8 contrast;
42         __u8 colors;
43         __u8 autogain;
44         __u8 blue;
45         __u8 red;
46         __u8 vflip;                     /* ov7630 only */
47         __u8 infrared;                  /* mi0360 only */
48
49         __s8 ag_cnt;
50 #define AG_CNT_START 13
51
52         __u8 qindex;
53         __u8 bridge;
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         __u8 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         __u8 i2c_base;
68 };
69
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);
87
88 static struct ctrl sd_ctrls[] = {
89         {
90             {
91                 .id      = V4L2_CID_BRIGHTNESS,
92                 .type    = V4L2_CTRL_TYPE_INTEGER,
93                 .name    = "Brightness",
94                 .minimum = 0,
95 #define BRIGHTNESS_MAX 0xffff
96                 .maximum = BRIGHTNESS_MAX,
97                 .step    = 1,
98 #define BRIGHTNESS_DEF 0x8000
99                 .default_value = BRIGHTNESS_DEF,
100             },
101             .set = sd_setbrightness,
102             .get = sd_getbrightness,
103         },
104         {
105             {
106                 .id      = V4L2_CID_CONTRAST,
107                 .type    = V4L2_CTRL_TYPE_INTEGER,
108                 .name    = "Contrast",
109                 .minimum = 0,
110 #define CONTRAST_MAX 127
111                 .maximum = CONTRAST_MAX,
112                 .step    = 1,
113 #define CONTRAST_DEF 63
114                 .default_value = CONTRAST_DEF,
115             },
116             .set = sd_setcontrast,
117             .get = sd_getcontrast,
118         },
119         {
120             {
121                 .id      = V4L2_CID_SATURATION,
122                 .type    = V4L2_CTRL_TYPE_INTEGER,
123                 .name    = "Color",
124                 .minimum = 0,
125                 .maximum = 40,
126                 .step    = 1,
127 #define COLOR_DEF 32
128                 .default_value = COLOR_DEF,
129             },
130             .set = sd_setcolors,
131             .get = sd_getcolors,
132         },
133         {
134             {
135                 .id      = V4L2_CID_BLUE_BALANCE,
136                 .type    = V4L2_CTRL_TYPE_INTEGER,
137                 .name    = "Blue Balance",
138                 .minimum = 24,
139                 .maximum = 40,
140                 .step    = 1,
141 #define BLUE_BALANCE_DEF 32
142                 .default_value = BLUE_BALANCE_DEF,
143             },
144             .set = sd_setblue_balance,
145             .get = sd_getblue_balance,
146         },
147         {
148             {
149                 .id      = V4L2_CID_RED_BALANCE,
150                 .type    = V4L2_CTRL_TYPE_INTEGER,
151                 .name    = "Red Balance",
152                 .minimum = 24,
153                 .maximum = 40,
154                 .step    = 1,
155 #define RED_BALANCE_DEF 32
156                 .default_value = RED_BALANCE_DEF,
157             },
158             .set = sd_setred_balance,
159             .get = sd_getred_balance,
160         },
161 #define AUTOGAIN_IDX 5
162         {
163             {
164                 .id      = V4L2_CID_AUTOGAIN,
165                 .type    = V4L2_CTRL_TYPE_BOOLEAN,
166                 .name    = "Auto Gain",
167                 .minimum = 0,
168                 .maximum = 1,
169                 .step    = 1,
170 #define AUTOGAIN_DEF 1
171                 .default_value = AUTOGAIN_DEF,
172             },
173             .set = sd_setautogain,
174             .get = sd_getautogain,
175         },
176 /* ov7630 only */
177 #define VFLIP_IDX 6
178         {
179             {
180                 .id      = V4L2_CID_VFLIP,
181                 .type    = V4L2_CTRL_TYPE_BOOLEAN,
182                 .name    = "Vflip",
183                 .minimum = 0,
184                 .maximum = 1,
185                 .step    = 1,
186 #define VFLIP_DEF 1
187                 .default_value = VFLIP_DEF,
188             },
189             .set = sd_setvflip,
190             .get = sd_getvflip,
191         },
192 /* mi0360 only */
193 #define INFRARED_IDX 7
194         {
195             {
196                 .id      = V4L2_CID_INFRARED,
197                 .type    = V4L2_CTRL_TYPE_BOOLEAN,
198                 .name    = "Infrared",
199                 .minimum = 0,
200                 .maximum = 1,
201                 .step    = 1,
202 #define INFRARED_DEF 0
203                 .default_value = INFRARED_DEF,
204             },
205             .set = sd_setinfrared,
206             .get = sd_getinfrared,
207         },
208 };
209
210 /* table of the disabled controls */
211 static __u32 ctrl_dis[] = {
212         (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
213                                                 /* SENSOR_HV7131R 0 */
214         (1 << VFLIP_IDX),
215                                                 /* SENSOR_MI0360 1 */
216         (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
217                                                 /* SENSOR_MO4000 2 */
218         (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
219                                                 /* SENSOR_OM6802 3 */
220         (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX),
221                                                 /* SENSOR_OV7630 4 */
222         (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
223                                                 /* SENSOR_OV7648 5 */
224         (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
225                                                 /* SENSOR_OV7660 6 */
226 };
227
228 static struct v4l2_pix_format vga_mode[] = {
229         {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
230                 .bytesperline = 160,
231                 .sizeimage = 160 * 120 * 4 / 8 + 590,
232                 .colorspace = V4L2_COLORSPACE_JPEG,
233                 .priv = 2},
234         {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
235                 .bytesperline = 320,
236                 .sizeimage = 320 * 240 * 3 / 8 + 590,
237                 .colorspace = V4L2_COLORSPACE_JPEG,
238                 .priv = 1},
239         {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
240                 .bytesperline = 640,
241                 .sizeimage = 640 * 480 * 3 / 8 + 590,
242                 .colorspace = V4L2_COLORSPACE_JPEG,
243                 .priv = 0},
244 };
245
246 /*Data from sn9c102p+hv71331r */
247 static const __u8 sn_hv7131[] = {
248 /*      reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
249         0x00,   0x03,   0x64,   0x00,   0x1a,   0x20,   0x20,   0x20,
250 /*      reg8    reg9    rega    regb    regc    regd    rege    regf */
251         0xa1,   0x11,   0x02,   0x09,   0x00,   0x00,   0x00,   0x10,
252 /*      reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
253         0x03,   0x00,   0x00,   0x01,   0x03,   0x28,   0x1e,   0x41,
254 /*      reg18   reg19   reg1a   reg1b   reg1c   reg1d   reg1e   reg1f */
255         0x0a,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00
256 };
257
258 static const __u8 sn_mi0360[] = {
259 /*      reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
260         0x00,   0x61,   0x44,   0x00,   0x1a,   0x20,   0x20,   0x20,
261 /*      reg8    reg9    rega    regb    regc    regd    rege    regf */
262         0xb1,   0x5d,   0x07,   0x00,   0x00,   0x00,   0x00,   0x10,
263 /*      reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
264         0x03,   0x00,   0x00,   0x02,   0x0a,   0x28,   0x1e,   0x61,
265 /*      reg18   reg19   reg1a   reg1b   reg1c   reg1d   reg1e   reg1f */
266         0x06,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00
267 };
268
269 static const __u8 sn_mo4000[] = {
270 /*      reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
271         0x12,   0x23,   0x60,   0x00,   0x1a,   0x00,   0x20,   0x18,
272 /*      reg8    reg9    rega    regb    regc    regd    rege    regf */
273         0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
274 /*      reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
275         0x03,    0x00,  0x0b,   0x0f,   0x14,   0x28,   0x1e,   0x40,
276 /*      reg18   reg19   reg1a   reg1b   reg1c   reg1d   reg1e   reg1f */
277         0x08,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00
278 };
279
280 static const __u8 sn_om6802[] = {
281 /*      reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
282         0x00,   0x23,   0x72,   0x00,   0x1a,   0x34,   0x27,   0x20,
283 /*      reg8    reg9    rega    regb    regc    regd    rege    regf */
284         0x80,   0x34,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
285 /*      reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
286         0x03,   0x00,   0x51,   0x01,   0x00,   0x28,   0x1e,   0x40,
287 /*      reg18   reg19   reg1a   reg1b   reg1c   reg1d   reg1e   reg1f */
288         0x05,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
289         0x08,   0x22,   0x44,   0x63,   0x7d,   0x92,   0xa3,   0xaf,
290         0xbc,   0xc4,   0xcd,   0xd5,   0xdc,   0xe1,   0xe8,   0xef,
291         0xf7
292 };
293
294 static const __u8 sn_ov7630[] = {
295 /*      reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
296         0x00,   0x21,   0x40,   0x00,   0x1a,   0x20,   0x1f,   0x20,
297 /*      reg8    reg9    rega    regb    regc    regd    rege    regf */
298         0xa1,   0x21,   0x76,   0x21,   0x00,   0x00,   0x00,   0x10,
299 /*      reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
300         0x03,   0x00,   0x04,   0x01,   0x0a,   0x28,   0x1e,   0xc2,
301 /*      reg18   reg19   reg1a   reg1b   reg1c   reg1d   reg1e   reg1f */
302         0x0b,   0x00,   0x00,   0x00,   0x00,   0x00
303 };
304
305 static const __u8 sn_ov7648[] = {
306 /*      reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
307         0x00,   0x63,   0x40,   0x00,   0x1a,   0x20,   0x20,   0x20,
308 /*      reg8    reg9    rega    regb    regc    regd    rege    regf */
309         0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x10,
310 /*      reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
311         0x03,   0x00,   0x00,   0x01,   0x00,   0x28,   0x1e,   0x00,
312 /*      reg18   reg19   reg1a   reg1b   reg1c   reg1d   reg1e   reg1f */
313         0x0b,   0x00,   0x00,   0x00,   0x00,   0x00
314 };
315
316 static const __u8 sn_ov7660[]   = {
317 /*      reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
318         0x00,   0x61,   0x40,   0x00,   0x1a,   0x20,   0x20,   0x20,
319 /*      reg8    reg9    rega    regb    regc    regd    rege    regf */
320         0x81,   0x21,   0x07,   0x00,   0x00,   0x00,   0x00,   0x10,
321 /*      reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
322         0x03,   0x00,   0x01,   0x01,   0x08,   0x28,   0x1e,   0x20,
323 /*      reg18   reg19   reg1a   reg1b   reg1c   reg1d   reg1e   reg1f */
324         0x07,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
325 };
326
327 /* sequence specific to the sensors - !! index = SENSOR_xxx */
328 static const __u8 *sn_tb[] = {
329         sn_hv7131,
330         sn_mi0360,
331         sn_mo4000,
332         sn_om6802,
333         sn_ov7630,
334         sn_ov7648,
335         sn_ov7660
336 };
337
338 static const __u8 gamma_def[] = {
339         0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
340         0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
341 };
342
343 /* color matrix and offsets */
344 static const __u8 reg84[] = {
345         0x14, 0x00, 0x27, 0x00, 0x07, 0x00,     /* YR YG YB gains */
346         0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00,     /* UR UG UB */
347         0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f,     /* VR VG VB */
348         0x00, 0x00, 0x00                        /* YUV offsets */
349 };
350 static const __u8 hv7131r_sensor_init[][8] = {
351         {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
352         {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
353         {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
354         {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
355         {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
356         {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
357         {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
358
359         {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
360         {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
361         {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
362         {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
363         {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
364         {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
365         {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
366         {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
367
368         {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
369         {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
370         {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
371         {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
372         {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
373
374         {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
375         {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
376         {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
377         {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
378         {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
379         {}
380 };
381 static const __u8 mi0360_sensor_init[][8] = {
382         {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
383         {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
384         {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
385         {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
386         {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
387         {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
388         {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
389         {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
390         {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
391         {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
392         {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
393         {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
394         {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
395         {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
396         {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
397         {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
398         {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
399         {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
400         {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
401         {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
402         {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
403         {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
404         {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
405         {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
406         {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
407         {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
408         {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
409         {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
410         {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
411         {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
412         {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
413         {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
414         {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
415
416         {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
417         {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
418         {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
419         {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
420         {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
421
422         {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
423         {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
424         {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
425         {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
426
427         {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
428         {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
429 /*      {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
430 /*      {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
431         {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
432         {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
433         {}
434 };
435 static const __u8 mo4000_sensor_init[][8] = {
436         {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
437         {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
438         {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
439         {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
440         {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
441         {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
442         {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
443         {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
444         {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
445         {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
446         {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
447         {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
448         {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
449         {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
450         {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
451         {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
452         {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
453         {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
454         {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
455         {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
456         {}
457 };
458 static __u8 om6802_sensor_init[][8] = {
459         {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
460         {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
461         {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
462         {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
463 /*      {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
464         {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
465                                         /* white balance & auto-exposure */
466 /*      {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
467                                                          * set color mode */
468 /*      {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
469                                                  * max AGC value in AE */
470 /*      {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
471                                                          * preset AGC */
472 /*      {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
473                                                  * preset brightness */
474 /*      {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
475                                                          * preset contrast */
476 /*      {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
477                                                          * preset gamma */
478         {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
479                                         /* luminance mode (0x4f = AE) */
480         {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
481                                                         /* preset shutter */
482 /*      {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
483                                                          * auto frame rate */
484 /*      {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
485
486 /*      {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
487 /*      {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
488 /*      {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
489 /*      {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
490         {}
491 };
492 static const __u8 ov7630_sensor_init[][8] = {
493         {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
494         {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
495 /* win: delay 20ms */
496         {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
497         {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
498 /* win: delay 20ms */
499         {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
500 /* win: i2c_r from 00 to 80 */
501         {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
502         {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
503         {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
504         {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
505         {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
506         {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
507         {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
508         {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
509         {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
510         {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
511         {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
512         {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
513         {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
514         {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
515         {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
516         {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
517         {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
518         {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
519         {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
520         {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
521         {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
522         {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
523         {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
524         {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
525         {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
526         {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
527 /* */
528         {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
529         {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
530 /*fixme: + 0x12, 0x04*/
531 /*      {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},  * COMN
532                                                          * set by setvflip */
533         {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
534         {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
535         {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
536 /* */
537         {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
538         {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
539         {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
540 /* */
541         {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
542 /*      {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
543         {}
544 };
545
546 static const __u8 ov7648_sensor_init[][8] = {
547         {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
548         {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},       /* reset */
549         {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
550         {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
551         {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
552         {0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
553         {0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
554         {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
555         {0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
556         {0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
557         {0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
558         {0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
559         {0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
560         {0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
561         {0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
562         {0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
563         {0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
564         {0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
565         {0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
566         {0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
567         {0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
568
569         {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
570 /*      {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
571 /*      {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
572         {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10},
573 /*...*/
574 /*      {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
575 /*      {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, jfm done */
576         {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
577         {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
578 /*      {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
579 /*      {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},  * GAIN - def */
580 /*      {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10},  * B R - def: 80 */
581 /*...*/
582         {0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
583 /*      {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
584 /*      {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
585 /*      {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
586 /*      {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
587 /*      {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10},  * B R - def: 80 */
588
589         {}
590 };
591
592 static const __u8 ov7660_sensor_init[][8] = {
593         {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
594 /*              (delay 20ms) */
595         {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
596                                                 /* Outformat = rawRGB */
597         {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
598         {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
599                                                 /* GAIN BLUE RED VREF */
600         {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
601                                                 /* COM 1 BAVE GEAVE AECHH */
602         {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
603         {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
604         {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
605                                                 /* AECH CLKRC COM7 COM8 */
606         {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
607         {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
608                                                 /* HSTART HSTOP VSTRT VSTOP */
609         {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
610         {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
611         {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
612                                         /* BOS GBOS GROS ROS (BGGR offset) */
613 /*      {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
614         {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
615                                                 /* AEW AEB VPT BBIAS */
616         {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
617                                                 /* GbBIAS RSVD EXHCH EXHCL */
618         {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
619                                                 /* RBIAS ADVFL ASDVFH YAVE */
620         {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
621                                                 /* HSYST HSYEN HREF */
622         {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
623         {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
624                                                 /* ADC ACOM OFON TSLB */
625         {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
626                                                 /* COM11 COM12 COM13 COM14 */
627         {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
628                                                 /* EDGE COM15 COM16 COM17 */
629         {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
630         {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
631         {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
632         {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
633         {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
634         {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
635         {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
636         {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
637         {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
638         {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
639                                                 /* LCC1 LCC2 LCC3 LCC4 */
640         {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
641         {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
642         {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
643                                         /* band gap reference [0:3] DBLV */
644         {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
645         {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
646         {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
647         {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
648         {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
649         {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
650         {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
651         {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
652         {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
653         {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
654 /****** (some exchanges in the win trace) ******/
655         {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
656                                                 /* bits[3..0]reserved */
657         {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
658         {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
659                                                 /* VREF vertical frame ctrl */
660         {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
661         {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
662         {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
663         {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
664         {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
665 /*      {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
666 /****** (some exchanges in the win trace) ******/
667         {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
668         {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
669         {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
670         {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
671 /*      {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},  * RED */
672 /****** (some exchanges in the win trace) ******/
673 /******!! startsensor KO if changed !!****/
674         {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
675         {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
676         {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
677         {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
678         {}
679 };
680
681 static const __u8 qtable4[] = {
682         0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
683         0x06, 0x08, 0x0A, 0x11,
684         0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
685         0x19, 0x19, 0x17, 0x15,
686         0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
687         0x21, 0x2E, 0x21, 0x23,
688         0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
689         0x25, 0x29, 0x2C, 0x29,
690         0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
691         0x17, 0x1B, 0x29, 0x29,
692         0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
693         0x29, 0x29, 0x29, 0x29,
694         0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
695         0x29, 0x29, 0x29, 0x29,
696         0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
697         0x29, 0x29, 0x29, 0x29
698 };
699
700 /* read <len> bytes to gspca_dev->usb_buf */
701 static void reg_r(struct gspca_dev *gspca_dev,
702                   __u16 value, int len)
703 {
704 #ifdef GSPCA_DEBUG
705         if (len > USB_BUF_SZ) {
706                 err("reg_r: buffer overflow");
707                 return;
708         }
709 #endif
710         usb_control_msg(gspca_dev->dev,
711                         usb_rcvctrlpipe(gspca_dev->dev, 0),
712                         0,
713                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
714                         value, 0,
715                         gspca_dev->usb_buf, len,
716                         500);
717         PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
718 }
719
720 static void reg_w1(struct gspca_dev *gspca_dev,
721                    __u16 value,
722                    __u8 data)
723 {
724         PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
725         gspca_dev->usb_buf[0] = data;
726         usb_control_msg(gspca_dev->dev,
727                         usb_sndctrlpipe(gspca_dev->dev, 0),
728                         0x08,
729                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
730                         value,
731                         0,
732                         gspca_dev->usb_buf, 1,
733                         500);
734 }
735 static void reg_w(struct gspca_dev *gspca_dev,
736                           __u16 value,
737                           const __u8 *buffer,
738                           int len)
739 {
740         PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
741                 value, buffer[0], buffer[1]);
742 #ifdef GSPCA_DEBUG
743         if (len > USB_BUF_SZ) {
744                 err("reg_w: buffer overflow");
745                 return;
746         }
747 #endif
748         memcpy(gspca_dev->usb_buf, buffer, len);
749         usb_control_msg(gspca_dev->dev,
750                         usb_sndctrlpipe(gspca_dev->dev, 0),
751                         0x08,
752                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
753                         value, 0,
754                         gspca_dev->usb_buf, len,
755                         500);
756 }
757
758 /* I2C write 1 byte */
759 static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
760 {
761         struct sd *sd = (struct sd *) gspca_dev;
762
763         PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
764         gspca_dev->usb_buf[0] = 0x81 | (2 << 4);        /* = a1 */
765         gspca_dev->usb_buf[1] = sd->i2c_base;
766         gspca_dev->usb_buf[2] = reg;
767         gspca_dev->usb_buf[3] = val;
768         gspca_dev->usb_buf[4] = 0;
769         gspca_dev->usb_buf[5] = 0;
770         gspca_dev->usb_buf[6] = 0;
771         gspca_dev->usb_buf[7] = 0x10;
772         usb_control_msg(gspca_dev->dev,
773                         usb_sndctrlpipe(gspca_dev->dev, 0),
774                         0x08,
775                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
776                         0x08,                   /* value = i2c */
777                         0,
778                         gspca_dev->usb_buf, 8,
779                         500);
780 }
781
782 /* I2C write 8 bytes */
783 static void i2c_w8(struct gspca_dev *gspca_dev,
784                    const __u8 *buffer)
785 {
786         memcpy(gspca_dev->usb_buf, buffer, 8);
787         usb_control_msg(gspca_dev->dev,
788                         usb_sndctrlpipe(gspca_dev->dev, 0),
789                         0x08,
790                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
791                         0x08, 0,                /* value, index */
792                         gspca_dev->usb_buf, 8,
793                         500);
794         msleep(2);
795 }
796
797 /* read 5 bytes in gspca_dev->usb_buf */
798 static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
799 {
800         struct sd *sd = (struct sd *) gspca_dev;
801         __u8 mode[8];
802
803         mode[0] = 0x81 | 0x10;
804         mode[1] = sd->i2c_base;
805         mode[2] = reg;
806         mode[3] = 0;
807         mode[4] = 0;
808         mode[5] = 0;
809         mode[6] = 0;
810         mode[7] = 0x10;
811         i2c_w8(gspca_dev, mode);
812         msleep(2);
813         mode[0] = 0x81 | (5 << 4) | 0x02;
814         mode[2] = 0;
815         i2c_w8(gspca_dev, mode);
816         msleep(2);
817         reg_r(gspca_dev, 0x0a, 5);
818 }
819
820 static int probesensor(struct gspca_dev *gspca_dev)
821 {
822         i2c_w1(gspca_dev, 0x02, 0);                     /* sensor wakeup */
823         msleep(10);
824         reg_w1(gspca_dev, 0x02, 0x66);                  /* Gpio on */
825         msleep(10);
826         i2c_r5(gspca_dev, 0);                           /* read sensor id */
827         if (gspca_dev->usb_buf[0] == 0x02
828             && gspca_dev->usb_buf[1] == 0x09
829             && gspca_dev->usb_buf[2] == 0x01
830             && gspca_dev->usb_buf[3] == 0x00
831             && gspca_dev->usb_buf[4] == 0x00) {
832                 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
833                 return 0;
834         }
835         PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
836                 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
837                 gspca_dev->usb_buf[2]);
838         PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
839         return -ENODEV;
840 }
841
842 static int configure_gpio(struct gspca_dev *gspca_dev,
843                           const __u8 *sn9c1xx)
844 {
845         struct sd *sd = (struct sd *) gspca_dev;
846         const __u8 *reg9a;
847         static const __u8 reg9a_def[] =
848                 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
849         static const __u8 reg9a_sn9c325[] =
850                 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
851         static const __u8 regd4[] = {0x60, 0x00, 0x00};
852
853         reg_w1(gspca_dev, 0xf1, 0x00);
854         reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
855
856         /* configure gpio */
857         reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
858         reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
859         reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);      /* jfm len was 3 */
860         switch (sd->bridge) {
861         case BRIDGE_SN9C325:
862                 reg9a = reg9a_sn9c325;
863                 break;
864         default:
865                 reg9a = reg9a_def;
866                 break;
867         }
868         reg_w(gspca_dev, 0x9a, reg9a, 6);
869
870         reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
871
872         reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
873
874         switch (sd->sensor) {
875         case SENSOR_OM6802:
876                 reg_w1(gspca_dev, 0x02, 0x71);
877                 reg_w1(gspca_dev, 0x01, 0x42);
878                 reg_w1(gspca_dev, 0x17, 0x64);
879                 reg_w1(gspca_dev, 0x01, 0x42);
880                 break;
881 /*jfm: from win trace */
882         case SENSOR_OV7630:
883                 reg_w1(gspca_dev, 0x01, 0x61);
884                 reg_w1(gspca_dev, 0x17, 0xe2);
885                 reg_w1(gspca_dev, 0x01, 0x60);
886                 reg_w1(gspca_dev, 0x01, 0x40);
887                 break;
888         case SENSOR_OV7648:
889                 reg_w1(gspca_dev, 0x01, 0x63);
890                 reg_w1(gspca_dev, 0x17, 0x20);
891                 reg_w1(gspca_dev, 0x01, 0x42);
892                 break;
893 /*jfm: from win trace */
894         case SENSOR_OV7660:
895                 if (sd->bridge == BRIDGE_SN9C120) {
896                         reg_w1(gspca_dev, 0x01, 0x61);
897                         reg_w1(gspca_dev, 0x17, 0x20);
898                         reg_w1(gspca_dev, 0x01, 0x60);
899                         reg_w1(gspca_dev, 0x01, 0x40);
900                         break;
901                 }
902                 /* fall thru */
903         default:
904                 reg_w1(gspca_dev, 0x01, 0x43);
905                 reg_w1(gspca_dev, 0x17, 0x61);
906                 reg_w1(gspca_dev, 0x01, 0x42);
907                 if (sd->sensor == SENSOR_HV7131R) {
908                         if (probesensor(gspca_dev) < 0)
909                                 return -ENODEV;
910                 }
911                 break;
912         }
913         return 0;
914 }
915
916 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
917 {
918         int i = 0;
919         static const __u8 SetSensorClk[] =      /* 0x08 Mclk */
920                 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
921
922         while (hv7131r_sensor_init[i][0]) {
923                 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
924                 i++;
925         }
926         i2c_w8(gspca_dev, SetSensorClk);
927 }
928
929 static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
930 {
931         int i = 0;
932
933         while (mi0360_sensor_init[i][0]) {
934                 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
935                 i++;
936         }
937 }
938
939 static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
940 {
941         int i = 0;
942
943         while (mo4000_sensor_init[i][0]) {
944                 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
945                 i++;
946         }
947 }
948
949 static void om6802_InitSensor(struct gspca_dev *gspca_dev)
950 {
951         int i = 0;
952
953         while (om6802_sensor_init[i][0]) {
954                 i2c_w8(gspca_dev, om6802_sensor_init[i]);
955                 i++;
956         }
957 }
958
959 static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
960 {
961         int i = 0;
962
963         i2c_w8(gspca_dev, ov7630_sensor_init[i]);       /* 76 01 */
964         i++;
965         i2c_w8(gspca_dev, ov7630_sensor_init[i]);       /* 12 c8 (RGB+SRST) */
966         i++;
967         msleep(20);
968         i2c_w8(gspca_dev, ov7630_sensor_init[i]);       /* 12 48 */
969         i++;
970         i2c_w8(gspca_dev, ov7630_sensor_init[i]);       /* 12 c8 */
971         i++;
972         msleep(20);
973         i2c_w8(gspca_dev, ov7630_sensor_init[i]);       /* 12 48 */
974         i++;
975 /*jfm:win i2c_r from 00 to 80*/
976
977         while (ov7630_sensor_init[i][0]) {
978                 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
979                 i++;
980         }
981 }
982
983 static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
984 {
985         int i = 0;
986
987         i2c_w8(gspca_dev, ov7648_sensor_init[i]);
988         i++;
989 /* win: dble reset */
990         i2c_w8(gspca_dev, ov7648_sensor_init[i]);       /* reset */
991         i++;
992         msleep(20);
993 /* win: i2c reg read 00..7f */
994         while (ov7648_sensor_init[i][0]) {
995                 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
996                 i++;
997         }
998 }
999
1000 static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
1001 {
1002         int i = 0;
1003
1004         i2c_w8(gspca_dev, ov7660_sensor_init[i]);       /* reset SCCB */
1005         i++;
1006         msleep(20);
1007         while (ov7660_sensor_init[i][0]) {
1008                 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
1009                 i++;
1010         }
1011 }
1012
1013 /* this function is called at probe time */
1014 static int sd_config(struct gspca_dev *gspca_dev,
1015                         const struct usb_device_id *id)
1016 {
1017         struct sd *sd = (struct sd *) gspca_dev;
1018         struct cam *cam;
1019
1020         cam = &gspca_dev->cam;
1021         cam->epaddr = 0x01;
1022         cam->cam_mode = vga_mode;
1023         cam->nmodes = ARRAY_SIZE(vga_mode);
1024
1025         sd->bridge = id->driver_info >> 16;
1026         sd->sensor = id->driver_info >> 8;
1027         sd->i2c_base = id->driver_info;
1028
1029         sd->qindex = 4;                 /* set the quantization table */
1030         sd->brightness = BRIGHTNESS_DEF;
1031         sd->contrast = CONTRAST_DEF;
1032         sd->colors = COLOR_DEF;
1033         sd->blue = BLUE_BALANCE_DEF;
1034         sd->red = RED_BALANCE_DEF;
1035         sd->autogain = AUTOGAIN_DEF;
1036         sd->ag_cnt = -1;
1037         sd->vflip = VFLIP_DEF;
1038         sd->infrared = INFRARED_DEF;
1039
1040         gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
1041         return 0;
1042 }
1043
1044 /* this function is called at probe and resume time */
1045 static int sd_init(struct gspca_dev *gspca_dev)
1046 {
1047         struct sd *sd = (struct sd *) gspca_dev;
1048         __u8 regGpio[] = { 0x29, 0x74 };
1049         __u8 regF1;
1050
1051         /* setup a selector by bridge */
1052         reg_w1(gspca_dev, 0xf1, 0x01);
1053         reg_r(gspca_dev, 0x00, 1);
1054         reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
1055         reg_r(gspca_dev, 0x00, 1);              /* get sonix chip id */
1056         regF1 = gspca_dev->usb_buf[0];
1057         PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
1058         switch (sd->bridge) {
1059         case BRIDGE_SN9C102P:
1060                 if (regF1 != 0x11)
1061                         return -ENODEV;
1062                 reg_w1(gspca_dev, 0x02, regGpio[1]);
1063                 break;
1064         case BRIDGE_SN9C105:
1065                 if (regF1 != 0x11)
1066                         return -ENODEV;
1067                 reg_w(gspca_dev, 0x01, regGpio, 2);
1068                 break;
1069         case BRIDGE_SN9C120:
1070                 if (regF1 != 0x12)
1071                         return -ENODEV;
1072                 regGpio[1] = 0x70;
1073                 reg_w(gspca_dev, 0x01, regGpio, 2);
1074                 break;
1075         default:
1076 /*      case BRIDGE_SN9C110: */
1077 /*      case BRIDGE_SN9C325: */
1078                 if (regF1 != 0x12)
1079                         return -ENODEV;
1080                 reg_w1(gspca_dev, 0x02, 0x62);
1081                 break;
1082         }
1083
1084         reg_w1(gspca_dev, 0xf1, 0x01);
1085
1086         return 0;
1087 }
1088
1089 static unsigned int setexposure(struct gspca_dev *gspca_dev,
1090                                 unsigned int expo)
1091 {
1092         struct sd *sd = (struct sd *) gspca_dev;
1093         static const __u8 doit[] =              /* update sensor */
1094                 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1095         static const __u8 sensorgo[] =          /* sensor on */
1096                 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1097         static const __u8 gainMo[] =
1098                 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1099
1100         switch (sd->sensor) {
1101         case SENSOR_HV7131R: {
1102                 __u8 Expodoit[] =
1103                         { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1104
1105                 Expodoit[3] = expo >> 16;
1106                 Expodoit[4] = expo >> 8;
1107                 Expodoit[5] = expo;
1108                 i2c_w8(gspca_dev, Expodoit);
1109                 break;
1110             }
1111         case SENSOR_MI0360: {
1112                 __u8 expoMi[] =  /* exposure 0x0635 -> 4 fp/s 0x10 */
1113                         { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1114
1115                 if (expo > 0x0635)
1116                         expo = 0x0635;
1117                 else if (expo < 0x0001)
1118                         expo = 0x0001;
1119                 expoMi[3] = expo >> 8;
1120                 expoMi[4] = expo;
1121                 i2c_w8(gspca_dev, expoMi);
1122                 i2c_w8(gspca_dev, doit);
1123                 i2c_w8(gspca_dev, sensorgo);
1124                 break;
1125             }
1126         case SENSOR_MO4000: {
1127                 __u8 expoMof[] =
1128                         { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1129                 __u8 expoMo10[] =
1130                         { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1131
1132                 if (expo > 0x1fff)
1133                         expo = 0x1fff;
1134                 else if (expo < 0x0001)
1135                         expo = 0x0001;
1136                 expoMof[3] = (expo & 0x03fc) >> 2;
1137                 i2c_w8(gspca_dev, expoMof);
1138                 expoMo10[3] = ((expo & 0x1c00) >> 10)
1139                                 | ((expo & 0x0003) << 4);
1140                 i2c_w8(gspca_dev, expoMo10);
1141                 i2c_w8(gspca_dev, gainMo);
1142                 PDEBUG(D_CONF, "set exposure %d",
1143                         ((expoMo10[3] & 0x07) << 10)
1144                         | (expoMof[3] << 2)
1145                         | ((expoMo10[3] & 0x30) >> 4));
1146                 break;
1147             }
1148         case SENSOR_OM6802: {
1149                 __u8 gainOm[] =
1150                         { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1151
1152                 if (expo > 0x03ff)
1153                         expo = 0x03ff;
1154                  if (expo < 0x0001)
1155                         expo = 0x0001;
1156                 gainOm[3] = expo >> 2;
1157                 i2c_w8(gspca_dev, gainOm);
1158                 reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
1159                 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
1160                 break;
1161             }
1162         }
1163         return expo;
1164 }
1165
1166 static void setbrightness(struct gspca_dev *gspca_dev)
1167 {
1168         struct sd *sd = (struct sd *) gspca_dev;
1169         unsigned int expo;
1170         __u8 k2;
1171
1172         k2 = ((int) sd->brightness - 0x8000) >> 10;
1173         switch (sd->sensor) {
1174         case SENSOR_HV7131R:
1175                 expo = sd->brightness << 4;
1176                 if (expo > 0x002dc6c0)
1177                         expo = 0x002dc6c0;
1178                 else if (expo < 0x02a0)
1179                         expo = 0x02a0;
1180                 sd->exposure = setexposure(gspca_dev, expo);
1181                 break;
1182         case SENSOR_MI0360:
1183         case SENSOR_MO4000:
1184                 expo = sd->brightness >> 4;
1185                 sd->exposure = setexposure(gspca_dev, expo);
1186                 break;
1187         case SENSOR_OM6802:
1188                 expo = sd->brightness >> 6;
1189                 sd->exposure = setexposure(gspca_dev, expo);
1190                 k2 = sd->brightness >> 11;
1191                 break;
1192         }
1193
1194         reg_w1(gspca_dev, 0x96, k2);            /* color matrix Y offset */
1195 }
1196
1197 static void setcontrast(struct gspca_dev *gspca_dev)
1198 {
1199         struct sd *sd = (struct sd *) gspca_dev;
1200         __u8 k2;
1201         __u8 contrast[6];
1202
1203         k2 = sd->contrast * 0x30 / (CONTRAST_MAX + 1) + 0x10;   /* 10..40 */
1204         contrast[0] = (k2 + 1) / 2;             /* red */
1205         contrast[1] = 0;
1206         contrast[2] = k2;                       /* green */
1207         contrast[3] = 0;
1208         contrast[4] = (k2 + 1) / 5;             /* blue */
1209         contrast[5] = 0;
1210         reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
1211 }
1212
1213 static void setcolors(struct gspca_dev *gspca_dev)
1214 {
1215         struct sd *sd = (struct sd *) gspca_dev;
1216         int i, v;
1217         __u8 reg8a[12];                 /* U & V gains */
1218         static __s16 uv[6] = {          /* same as reg84 in signed decimal */
1219                 -24, -38, 64,           /* UR UG UB */
1220                  62, -51, -9            /* VR VG VB */
1221         };
1222         for (i = 0; i < 6; i++) {
1223                 v = uv[i] * sd->colors / COLOR_DEF;
1224                 reg8a[i * 2] = v;
1225                 reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
1226         }
1227         reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
1228 }
1229
1230 static void setredblue(struct gspca_dev *gspca_dev)
1231 {
1232         struct sd *sd = (struct sd *) gspca_dev;
1233
1234         reg_w1(gspca_dev, 0x05, sd->red);
1235 /*      reg_w1(gspca_dev, 0x07, 32); */
1236         reg_w1(gspca_dev, 0x06, sd->blue);
1237 }
1238
1239 static void setautogain(struct gspca_dev *gspca_dev)
1240 {
1241         struct sd *sd = (struct sd *) gspca_dev;
1242
1243         if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1244                 return;
1245         if (sd->autogain)
1246                 sd->ag_cnt = AG_CNT_START;
1247         else
1248                 sd->ag_cnt = -1;
1249 }
1250
1251 static void setvflip(struct sd *sd)
1252 {
1253         i2c_w1(&sd->gspca_dev, 0x75,                    /* COMN */
1254                 sd->vflip ? 0x82 : 0x02);
1255 }
1256
1257 static void setinfrared(struct sd *sd)
1258 {
1259 /*fixme: different sequence for StarCam Clip and StarCam 370i */
1260 /* Clip */
1261         i2c_w1(&sd->gspca_dev, 0x02,                    /* gpio */
1262                 sd->infrared ? 0x66 : 0x64);
1263 }
1264
1265 /* -- start the camera -- */
1266 static int sd_start(struct gspca_dev *gspca_dev)
1267 {
1268         struct sd *sd = (struct sd *) gspca_dev;
1269         int i;
1270         __u8 reg1, reg17, reg18;
1271         const __u8 *sn9c1xx;
1272         int mode;
1273         static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1274         static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1275         static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };    /* MI0360 */
1276         static const __u8 CE_ov76xx[] =
1277                                 { 0x32, 0xdd, 0x32, 0xdd };
1278
1279         sn9c1xx = sn_tb[(int) sd->sensor];
1280         configure_gpio(gspca_dev, sn9c1xx);
1281
1282         reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1283         reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1284         reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1285         reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1286         reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1287         reg_w1(gspca_dev, 0xd2, 0x6a);          /* DC29 */
1288         reg_w1(gspca_dev, 0xd3, 0x50);
1289         reg_w1(gspca_dev, 0xc6, 0x00);
1290         reg_w1(gspca_dev, 0xc7, 0x00);
1291         reg_w1(gspca_dev, 0xc8, 0x50);
1292         reg_w1(gspca_dev, 0xc9, 0x3c);
1293         reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1294         switch (sd->sensor) {
1295         case SENSOR_OV7630:
1296                 reg17 = 0xe2;
1297                 break;
1298         case SENSOR_OV7648:
1299                 reg17 = 0x20;
1300                 break;
1301 /*jfm: from win trace */
1302         case SENSOR_OV7660:
1303                 if (sd->bridge == BRIDGE_SN9C120) {
1304                         reg17 = 0xa0;
1305                         break;
1306                 }
1307                 /* fall thru */
1308         default:
1309                 reg17 = 0x60;
1310                 break;
1311         }
1312         reg_w1(gspca_dev, 0x17, reg17);
1313 /* set reg1 was here */
1314         reg_w1(gspca_dev, 0x05, sn9c1xx[5]);    /* red */
1315         reg_w1(gspca_dev, 0x07, sn9c1xx[7]);    /* green */
1316         reg_w1(gspca_dev, 0x06, sn9c1xx[6]);    /* blue */
1317         reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
1318         reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
1319         for (i = 0; i < 8; i++)
1320                 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1321         switch (sd->sensor) {
1322         case SENSOR_OV7648:
1323                 reg_w1(gspca_dev, 0x9a, 0x0a);
1324                 reg_w1(gspca_dev, 0x99, 0x60);
1325                 break;
1326         case SENSOR_OV7660:
1327                 if (sd->bridge == BRIDGE_SN9C120) {
1328                         reg_w1(gspca_dev, 0x9a, 0x05);
1329                         break;
1330                 }
1331                 /* fall thru */
1332         default:
1333                 reg_w1(gspca_dev, 0x9a, 0x08);
1334                 reg_w1(gspca_dev, 0x99, 0x59);
1335                 break;
1336         }
1337
1338         mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1339         if (mode)
1340                 reg1 = 0x46;    /* 320x240: clk 48Mhz, video trf enable */
1341         else
1342                 reg1 = 0x06;    /* 640x480: clk 24Mhz, video trf enable */
1343         reg17 = 0x61;           /* 0x:20: enable sensor clock */
1344         switch (sd->sensor) {
1345         case SENSOR_HV7131R:
1346                 hv7131R_InitSensor(gspca_dev);
1347                 break;
1348         case SENSOR_MI0360:
1349                 mi0360_InitSensor(gspca_dev);
1350                 break;
1351         case SENSOR_MO4000:
1352                 mo4000_InitSensor(gspca_dev);
1353                 if (mode) {
1354 /*                      reg1 = 0x46;     * 320 clk 48Mhz 60fp/s */
1355                         reg1 = 0x06;    /* clk 24Mz */
1356                 } else {
1357                         reg17 = 0x22;   /* 640 MCKSIZE */
1358 /*                      reg1 = 0x06;     * 640 clk 24Mz (done) */
1359                 }
1360                 break;
1361         case SENSOR_OM6802:
1362                 om6802_InitSensor(gspca_dev);
1363                 reg17 = 0x64;           /* 640 MCKSIZE */
1364                 break;
1365         case SENSOR_OV7630:
1366                 ov7630_InitSensor(gspca_dev);
1367                 setvflip(sd);
1368                 reg17 = 0xe2;
1369                 reg1 = 0x44;
1370                 break;
1371         case SENSOR_OV7648:
1372                 ov7648_InitSensor(gspca_dev);
1373                 reg17 = 0x21;
1374 /*              reg1 = 0x42;             * 42 - 46? */
1375                 break;
1376         default:
1377 /*      case SENSOR_OV7660: */
1378                 ov7660_InitSensor(gspca_dev);
1379                 if (sd->bridge == BRIDGE_SN9C120) {
1380                         if (mode) {             /* 320x240 - 160x120 */
1381                                 reg17 = 0xa2;
1382                                 reg1 = 0x44;    /* 48 Mhz, video trf eneble */
1383                         }
1384                 } else {
1385                         reg17 = 0x22;
1386                         reg1 = 0x06;    /* 24 Mhz, video trf eneble
1387                                          * inverse power down */
1388                 }
1389                 break;
1390         }
1391         reg_w(gspca_dev, 0xc0, C0, 6);
1392         reg_w(gspca_dev, 0xca, CA, 4);
1393         switch (sd->sensor) {
1394         case SENSOR_OV7630:
1395         case SENSOR_OV7648:
1396         case SENSOR_OV7660:
1397                 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
1398                 break;
1399         default:
1400                 reg_w(gspca_dev, 0xce, CE, 4);
1401                                         /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1402                 break;
1403         }
1404
1405         /* here change size mode 0 -> VGA; 1 -> CIF */
1406         reg18 = sn9c1xx[0x18] | (mode << 4);
1407         reg_w1(gspca_dev, 0x18, reg18 | 0x40);
1408
1409         reg_w(gspca_dev, 0x100, qtable4, 0x40);
1410         reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1411
1412         reg_w1(gspca_dev, 0x18, reg18);
1413
1414         reg_w1(gspca_dev, 0x17, reg17);
1415         reg_w1(gspca_dev, 0x01, reg1);
1416         switch (sd->sensor) {
1417         case SENSOR_MI0360:
1418                 setinfrared(sd);
1419                 break;
1420         case SENSOR_OV7630:
1421                 setvflip(sd);
1422                 break;
1423         }
1424         setbrightness(gspca_dev);
1425         setcontrast(gspca_dev);
1426         setautogain(gspca_dev);
1427         return 0;
1428 }
1429
1430 static void sd_stopN(struct gspca_dev *gspca_dev)
1431 {
1432         struct sd *sd = (struct sd *) gspca_dev;
1433         static const __u8 stophv7131[] =
1434                 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1435         static const __u8 stopmi0360[] =
1436                 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1437         static const __u8 stopov7648[] =
1438                 { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
1439         __u8 data;
1440         const __u8 *sn9c1xx;
1441
1442         data = 0x0b;
1443         switch (sd->sensor) {
1444         case SENSOR_HV7131R:
1445                 i2c_w8(gspca_dev, stophv7131);
1446                 data = 0x2b;
1447                 break;
1448         case SENSOR_MI0360:
1449                 i2c_w8(gspca_dev, stopmi0360);
1450                 data = 0x29;
1451                 break;
1452         case SENSOR_OV7648:
1453                 i2c_w8(gspca_dev, stopov7648);
1454                 /* fall thru */
1455         case SENSOR_OV7630:
1456                 data = 0x29;
1457                 break;
1458         default:
1459 /*      case SENSOR_MO4000: */
1460 /*      case SENSOR_OV7660: */
1461                 break;
1462         }
1463         sn9c1xx = sn_tb[(int) sd->sensor];
1464         reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1465         reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1466         reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1467         reg_w1(gspca_dev, 0x01, data);
1468         reg_w1(gspca_dev, 0xf1, 0x00);
1469 }
1470
1471 static void do_autogain(struct gspca_dev *gspca_dev)
1472 {
1473         struct sd *sd = (struct sd *) gspca_dev;
1474         int delta;
1475         int expotimes;
1476         __u8 luma_mean = 130;
1477         __u8 luma_delta = 20;
1478
1479         /* Thanks S., without your advice, autobright should not work :) */
1480         if (sd->ag_cnt < 0)
1481                 return;
1482         if (--sd->ag_cnt >= 0)
1483                 return;
1484         sd->ag_cnt = AG_CNT_START;
1485
1486         delta = atomic_read(&sd->avg_lum);
1487         PDEBUG(D_FRAM, "mean lum %d", delta);
1488         if (delta < luma_mean - luma_delta ||
1489             delta > luma_mean + luma_delta) {
1490                 switch (sd->sensor) {
1491                 case SENSOR_HV7131R:
1492                         expotimes = sd->exposure >> 8;
1493                         expotimes += (luma_mean - delta) >> 4;
1494                         if (expotimes < 0)
1495                                 expotimes = 0;
1496                         sd->exposure = setexposure(gspca_dev,
1497                                         (unsigned int) (expotimes << 8));
1498                         break;
1499                 default:
1500 /*              case SENSOR_MO4000: */
1501 /*              case SENSOR_MI0360: */
1502 /*              case SENSOR_OM6802: */
1503                         expotimes = sd->exposure;
1504                         expotimes += (luma_mean - delta) >> 6;
1505                         if (expotimes < 0)
1506                                 expotimes = 0;
1507                         sd->exposure = setexposure(gspca_dev,
1508                                                    (unsigned int) expotimes);
1509                         setredblue(gspca_dev);
1510                         break;
1511                 }
1512         }
1513 }
1514
1515 /* scan the URB packets */
1516 /* This function is run at interrupt level. */
1517 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1518                         struct gspca_frame *frame,      /* target */
1519                         __u8 *data,                     /* isoc packet */
1520                         int len)                        /* iso packet length */
1521 {
1522         struct sd *sd = (struct sd *) gspca_dev;
1523         int sof, avg_lum;
1524
1525         sof = len - 64;
1526         if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1527
1528                 /* end of frame */
1529                 gspca_frame_add(gspca_dev, LAST_PACKET,
1530                                 frame, data, sof + 2);
1531                 if (sd->ag_cnt < 0)
1532                         return;
1533 /* w1 w2 w3 */
1534 /* w4 w5 w6 */
1535 /* w7 w8 */
1536 /* w4 */
1537                 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1538 /* w6 */
1539                 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1540 /* w2 */
1541                 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1542 /* w8 */
1543                 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1544 /* w5 */
1545                 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1546                 avg_lum >>= 4;
1547                 atomic_set(&sd->avg_lum, avg_lum);
1548                 return;
1549         }
1550         if (gspca_dev->last_packet_type == LAST_PACKET) {
1551
1552                 /* put the JPEG 422 header */
1553                 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1554         }
1555         gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1556 }
1557
1558 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1559 {
1560         struct sd *sd = (struct sd *) gspca_dev;
1561
1562         sd->brightness = val;
1563         if (gspca_dev->streaming)
1564                 setbrightness(gspca_dev);
1565         return 0;
1566 }
1567
1568 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1569 {
1570         struct sd *sd = (struct sd *) gspca_dev;
1571
1572         *val = sd->brightness;
1573         return 0;
1574 }
1575
1576 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1577 {
1578         struct sd *sd = (struct sd *) gspca_dev;
1579
1580         sd->contrast = val;
1581         if (gspca_dev->streaming)
1582                 setcontrast(gspca_dev);
1583         return 0;
1584 }
1585
1586 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1587 {
1588         struct sd *sd = (struct sd *) gspca_dev;
1589
1590         *val = sd->contrast;
1591         return 0;
1592 }
1593
1594 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1595 {
1596         struct sd *sd = (struct sd *) gspca_dev;
1597
1598         sd->colors = val;
1599         if (gspca_dev->streaming)
1600                 setcolors(gspca_dev);
1601         return 0;
1602 }
1603
1604 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1605 {
1606         struct sd *sd = (struct sd *) gspca_dev;
1607
1608         *val = sd->colors;
1609         return 0;
1610 }
1611
1612 static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1613 {
1614         struct sd *sd = (struct sd *) gspca_dev;
1615
1616         sd->blue = val;
1617         if (gspca_dev->streaming)
1618                 setredblue(gspca_dev);
1619         return 0;
1620 }
1621
1622 static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1623 {
1624         struct sd *sd = (struct sd *) gspca_dev;
1625
1626         *val = sd->blue;
1627         return 0;
1628 }
1629
1630 static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1631 {
1632         struct sd *sd = (struct sd *) gspca_dev;
1633
1634         sd->red = val;
1635         if (gspca_dev->streaming)
1636                 setredblue(gspca_dev);
1637         return 0;
1638 }
1639
1640 static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1641 {
1642         struct sd *sd = (struct sd *) gspca_dev;
1643
1644         *val = sd->red;
1645         return 0;
1646 }
1647
1648 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1649 {
1650         struct sd *sd = (struct sd *) gspca_dev;
1651
1652         sd->autogain = val;
1653         if (gspca_dev->streaming)
1654                 setautogain(gspca_dev);
1655         return 0;
1656 }
1657
1658 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1659 {
1660         struct sd *sd = (struct sd *) gspca_dev;
1661
1662         *val = sd->autogain;
1663         return 0;
1664 }
1665
1666 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1667 {
1668         struct sd *sd = (struct sd *) gspca_dev;
1669
1670         sd->vflip = val;
1671         if (gspca_dev->streaming)
1672                 setvflip(sd);
1673         return 0;
1674 }
1675
1676 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1677 {
1678         struct sd *sd = (struct sd *) gspca_dev;
1679
1680         *val = sd->vflip;
1681         return 0;
1682 }
1683
1684 static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val)
1685 {
1686         struct sd *sd = (struct sd *) gspca_dev;
1687
1688         sd->infrared = val;
1689         if (gspca_dev->streaming)
1690                 setinfrared(sd);
1691         return 0;
1692 }
1693
1694 static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val)
1695 {
1696         struct sd *sd = (struct sd *) gspca_dev;
1697
1698         *val = sd->infrared;
1699         return 0;
1700 }
1701
1702 /* sub-driver description */
1703 static const struct sd_desc sd_desc = {
1704         .name = MODULE_NAME,
1705         .ctrls = sd_ctrls,
1706         .nctrls = ARRAY_SIZE(sd_ctrls),
1707         .config = sd_config,
1708         .init = sd_init,
1709         .start = sd_start,
1710         .stopN = sd_stopN,
1711         .pkt_scan = sd_pkt_scan,
1712         .dq_callback = do_autogain,
1713 };
1714
1715 /* -- module initialisation -- */
1716 #define BSI(bridge, sensor, i2c_addr) \
1717         .driver_info = (BRIDGE_ ## bridge << 16) \
1718                         | (SENSOR_ ## sensor << 8) \
1719                         | (i2c_addr)
1720 static const __devinitdata struct usb_device_id device_table[] = {
1721 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1722         {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
1723         {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)},
1724 #endif
1725         {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1726         {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
1727 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1728         {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
1729 #endif
1730         {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
1731         {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
1732         {USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)},
1733         {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1734 /* bw600.inf:
1735         {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1736 /*      {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1737 /*      {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1738         {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1739 /*      {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1740         {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1741 /*      {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1742 /*      {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1743         {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1744 /*      {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1745 /*      {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1746         {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1747         {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
1748 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1749         {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
1750 #endif
1751 /*      {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1752 /*      {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1753 /*      {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
1754         {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1755 /*bw600.inf:*/
1756         {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c110?*/
1757         {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
1758         {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
1759 /*      {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
1760 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1761         {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
1762 #endif
1763         {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
1764         {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)},
1765 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1766         {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1767         {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1768 /*      {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
1769 #endif
1770         {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
1771         {}
1772 };
1773 MODULE_DEVICE_TABLE(usb, device_table);
1774
1775 /* -- device connect -- */
1776 static int sd_probe(struct usb_interface *intf,
1777                     const struct usb_device_id *id)
1778 {
1779         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1780                                 THIS_MODULE);
1781 }
1782
1783 static struct usb_driver sd_driver = {
1784         .name = MODULE_NAME,
1785         .id_table = device_table,
1786         .probe = sd_probe,
1787         .disconnect = gspca_disconnect,
1788 #ifdef CONFIG_PM
1789         .suspend = gspca_suspend,
1790         .resume = gspca_resume,
1791 #endif
1792 };
1793
1794 /* -- module insert / remove -- */
1795 static int __init sd_mod_init(void)
1796 {
1797         if (usb_register(&sd_driver) < 0)
1798                 return -1;
1799         info("registered");
1800         return 0;
1801 }
1802 static void __exit sd_mod_exit(void)
1803 {
1804         usb_deregister(&sd_driver);
1805         info("deregistered");
1806 }
1807
1808 module_init(sd_mod_init);
1809 module_exit(sd_mod_exit);