]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/media/video/gspca/sonixb.c
cfa62aef4700410bf8d1f137962c47756853db5a
[linux-2.6-omap-h63xx.git] / drivers / media / video / gspca / sonixb.c
1 /*
2  *              sonix sn9c102 (bayer) library
3  *              Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
4  * Add Pas106 Stefano Mozzi (C) 2004
5  *
6  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */
22
23 #define MODULE_NAME "sonixb"
24
25 #include "gspca.h"
26
27 #define DRIVER_VERSION_NUMBER   KERNEL_VERSION(2, 1, 7)
28 static const char version[] = "2.1.7";
29
30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31 MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
32 MODULE_LICENSE("GPL");
33
34 /* specific webcam descriptor */
35 struct sd {
36         struct gspca_dev gspca_dev;     /* !! must be the first item */
37
38         struct sd_desc sd_desc;         /* our nctrls differ dependend upon the
39                                            sensor, so we use a per cam copy */
40         atomic_t avg_lum;
41
42         unsigned short gain;
43         unsigned short exposure;
44         unsigned char brightness;
45         unsigned char autogain;
46         unsigned char autogain_ignore_frames;
47
48         unsigned char fr_h_sz;          /* size of frame header */
49         char sensor;                    /* Type of image sensor chip */
50         char sensor_has_gain;
51 #define SENSOR_HV7131R 0
52 #define SENSOR_OV6650 1
53 #define SENSOR_OV7630 2
54 #define SENSOR_OV7630_3 3
55 #define SENSOR_PAS106 4
56 #define SENSOR_PAS202 5
57 #define SENSOR_TAS5110 6
58 #define SENSOR_TAS5130CXX 7
59 };
60
61 #define COMP2 0x8f
62 #define COMP 0xc7               /* 0x87 //0x07 */
63 #define COMP1 0xc9              /* 0x89 //0x09 */
64
65 #define MCK_INIT 0x63
66 #define MCK_INIT1 0x20          /*fixme: Bayer - 0x50 for JPEG ??*/
67
68 #define SYS_CLK 0x04
69
70 /* We calculate the autogain at the end of the transfer of a frame, at this
71    moment a frame with the old settings is being transmitted, and a frame is
72    being captured with the old settings. So if we adjust the autogain we must
73    ignore atleast the 2 next frames for the new settings to come into effect
74    before doing any other adjustments */
75 #define AUTOGAIN_IGNORE_FRAMES 3
76 #define AUTOGAIN_DEADZONE 500
77 #define DESIRED_AVG_LUM 7000
78
79 /* V4L2 controls supported by the driver */
80 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
81 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
82 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
83 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
84 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
88
89 static struct ctrl sd_ctrls[] = {
90         {
91             {
92                 .id      = V4L2_CID_BRIGHTNESS,
93                 .type    = V4L2_CTRL_TYPE_INTEGER,
94                 .name    = "Brightness",
95                 .minimum = 0,
96                 .maximum = 255,
97                 .step    = 1,
98 #define BRIGHTNESS_DEF 127
99                 .default_value = BRIGHTNESS_DEF,
100             },
101             .set = sd_setbrightness,
102             .get = sd_getbrightness,
103         },
104         {
105             {
106                 .id      = V4L2_CID_GAIN,
107                 .type    = V4L2_CTRL_TYPE_INTEGER,
108                 .name    = "Gain",
109                 .minimum = 0,
110                 .maximum = 511,
111                 .step    = 1,
112 #define GAIN_DEF 255
113 #define GAIN_KNEE 400
114                 .default_value = GAIN_DEF,
115             },
116             .set = sd_setgain,
117             .get = sd_getgain,
118         },
119         {
120                 {
121                         .id = V4L2_CID_EXPOSURE,
122                         .type = V4L2_CTRL_TYPE_INTEGER,
123                         .name = "Exposure",
124 #define EXPOSURE_DEF 0
125 #define EXPOSURE_KNEE 353 /* 10 fps */
126                         .minimum = 0,
127                         .maximum = 511,
128                         .step = 1,
129                         .default_value = EXPOSURE_DEF,
130                         .flags = 0,
131                 },
132                 .set = sd_setexposure,
133                 .get = sd_getexposure,
134         },
135         {
136                 {
137                         .id = V4L2_CID_AUTOGAIN,
138                         .type = V4L2_CTRL_TYPE_BOOLEAN,
139                         .name = "Automatic Gain (and Exposure)",
140                         .minimum = 0,
141                         .maximum = 1,
142                         .step = 1,
143 #define AUTOGAIN_DEF 1
144                         .default_value = AUTOGAIN_DEF,
145                         .flags = 0,
146                 },
147                 .set = sd_setautogain,
148                 .get = sd_getautogain,
149         },
150 };
151
152 static struct v4l2_pix_format vga_mode[] = {
153         {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
154                 .bytesperline = 160,
155                 .sizeimage = 160 * 120,
156                 .colorspace = V4L2_COLORSPACE_SRGB,
157                 .priv = 2},
158         {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
159                 .bytesperline = 320,
160                 .sizeimage = 320 * 240,
161                 .colorspace = V4L2_COLORSPACE_SRGB,
162                 .priv = 1},
163         {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
164                 .bytesperline = 640,
165                 .sizeimage = 640 * 480,
166                 .colorspace = V4L2_COLORSPACE_SRGB,
167                 .priv = 0},
168 };
169 static struct v4l2_pix_format sif_mode[] = {
170         {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
171                 .bytesperline = 176,
172                 .sizeimage = 176 * 144,
173                 .colorspace = V4L2_COLORSPACE_SRGB,
174                 .priv = 1},
175         {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
176                 .bytesperline = 352,
177                 .sizeimage = 352 * 288,
178                 .colorspace = V4L2_COLORSPACE_SRGB,
179                 .priv = 0},
180 };
181
182 static const __u8 probe_ov7630[] = {0x08, 0x44};
183
184 static const __u8 initHv7131[] = {
185         0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
186         0x00, 0x00,
187         0x00, 0x00, 0x00, 0x03, 0x01, 0x00,     /* shift from 0x02 0x01 0x00 */
188         0x28, 0x1e, 0x60, 0x8a, 0x20,
189         0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
190 };
191 static const __u8 hv7131_sensor_init[][8] = {
192         {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
193         {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
194         {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
195         {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
196         {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
197 };
198 static const __u8 initOv6650[] = {
199         0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
200         0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201         0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
202         0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
203 };
204 static const __u8 ov6650_sensor_init[][8] =
205 {
206         /* Bright, contrast, etc are set througth SCBB interface.
207          * AVCAP on win2 do not send any data on this   controls. */
208         /* Anyway, some registers appears to alter bright and constrat */
209
210         /* Reset sensor */
211         {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
212         /* Set clock register 0x11 low nibble is clock divider */
213         {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
214         /* Next some unknown stuff */
215         {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
216 /*      {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
217                  * THIS SET GREEN SCREEN
218                  * (pixels could be innverted in decode kind of "brg",
219                  * but blue wont be there. Avoid this data ... */
220         {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
221         {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
222         {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
223         /* Disable autobright ? */
224         {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10},
225         /* Some more unknown stuff */
226         {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
227         {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
228         {0xa0, 0x60, 0x10, 0x57, 0x99, 0x04, 0x94, 0x16},
229         /* Framerate adjust register for artificial light 50 hz flicker
230            compensation, identical to ov6630 0x2b register, see 6630 datasheet.
231            0x4f -> (30 fps -> 25 fps), 0x00 -> no adjustment */
232         {0xa0, 0x60, 0x2b, 0x4f, 0x99, 0x04, 0x94, 0x15},
233 };
234
235 static const __u8 initOv7630[] = {
236         0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
237         0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
238         0x00, 0x02, 0x01, 0x0a,                         /* r11 .. r14 */
239         0x28, 0x1e,                     /* H & V sizes     r15 .. r16 */
240         0x68, COMP1, MCK_INIT1,                         /* r17 .. r19 */
241         0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c              /* r1a .. r1f */
242 };
243 static const __u8 initOv7630_3[] = {
244         0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
245         0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
246         0x00, 0x01, 0x01, 0x0a,                         /* r11 .. r14 */
247         0x16, 0x12,                     /* H & V sizes     r15 .. r16 */
248         0x68, 0x8f, MCK_INIT1,                          /* r17 .. r19 */
249         0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00,       /* r1a .. r20 */
250         0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
251         0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff  /* r29 .. r30 */
252 };
253 static const __u8 ov7630_sensor_init_com[][8] = {
254         {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
255         {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
256 /*      {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10},          jfm */
257         {0xd0, 0x21, 0x12, 0x78, 0x00, 0x80, 0x34, 0x10},       /* jfm */
258         {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
259         {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
260         {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
261         {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
262         {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
263         {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
264         {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
265 /*      {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},          jfm */
266         {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10},       /* jfm */
267         {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
268         {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
269         {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
270         {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
271         {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
272         {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
273 };
274 static const __u8 ov7630_sensor_init[][8] = {
275         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
276         {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10},       /* jfm */
277         {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
278         {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
279         {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15},       /* gain */
280 };
281 static const __u8 ov7630_sensor_init_3[][5][8] = {
282     {   {0xa0, 0x21, 0x10, 0x36, 0xbd, 0x06, 0xf6, 0x16},      /* exposure */
283         {0xa0, 0x21, 0x76, 0x03, 0xbd, 0x06, 0xf6, 0x16},
284         {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x16},
285         {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15},       /* gain */
286         {0xb0, 0x21, 0x2a, 0xa0, 0x1c, 0x06, 0xf6, 0x1d},
287     },
288     {   {0xa0, 0x21, 0x10, 0x83, 0xbd, 0x06, 0xf6, 0x16},      /* exposure */
289         {0xa0, 0x21, 0x76, 0x00, 0xbd, 0x06, 0xf6, 0x16},
290         {0xa0, 0x21, 0x11, 0x00, 0xbd, 0x06, 0xf6, 0x16},
291         {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15},       /* gain */
292 /*      {0xb0, 0x21, 0x2a, 0xc0, 0x3c, 0x06, 0xf6, 0x1d},
293                 * a0 1c,a0 1f,c0 3c frame rate ?line interval from ov6630 */
294 /*      {0xb0, 0x21, 0x2a, 0xa0, 0x1f, 0x06, 0xf6, 0x1d},        * from win */
295         {0xb0, 0x21, 0x2a, 0x80, 0x60, 0x06, 0xf6, 0x1d},
296     }
297 };
298
299 static const __u8 initPas106[] = {
300         0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
301         0x00, 0x00,
302         0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
303         0x16, 0x12, 0x28, COMP1, MCK_INIT1,
304         0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
305 };
306 /* compression 0x86 mckinit1 0x2b */
307 static const __u8 pas106_data[][2] = {
308         {0x02, 0x04},           /* Pixel Clock Divider 6 */
309         {0x03, 0x13},           /* Frame Time MSB */
310 /*      {0x03, 0x12},            * Frame Time MSB */
311         {0x04, 0x06},           /* Frame Time LSB */
312 /*      {0x04, 0x05},            * Frame Time LSB */
313         {0x05, 0x65},           /* Shutter Time Line Offset */
314 /*      {0x05, 0x6d},            * Shutter Time Line Offset */
315 /*      {0x06, 0xb1},            * Shutter Time Pixel Offset */
316         {0x06, 0xcd},           /* Shutter Time Pixel Offset */
317         {0x07, 0xc1},           /* Black Level Subtract Sign */
318 /*      {0x07, 0x00},            * Black Level Subtract Sign */
319         {0x08, 0x06},           /* Black Level Subtract Level */
320         {0x08, 0x06},           /* Black Level Subtract Level */
321 /*      {0x08, 0x01},            * Black Level Subtract Level */
322         {0x09, 0x05},           /* Color Gain B Pixel 5 a */
323         {0x0a, 0x04},           /* Color Gain G1 Pixel 1 5 */
324         {0x0b, 0x04},           /* Color Gain G2 Pixel 1 0 5 */
325         {0x0c, 0x05},           /* Color Gain R Pixel 3 1 */
326         {0x0d, 0x00},           /* Color GainH  Pixel */
327         {0x0e, 0x0e},           /* Global Gain */
328         {0x0f, 0x00},           /* Contrast */
329         {0x10, 0x06},           /* H&V synchro polarity */
330         {0x11, 0x06},           /* ?default */
331         {0x12, 0x06},           /* DAC scale */
332         {0x14, 0x02},           /* ?default */
333         {0x13, 0x01},           /* Validate Settings */
334 };
335 static const __u8 initPas202[] = {
336         0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
337         0x00, 0x00,
338         0x00, 0x00, 0x00, 0x07, 0x03, 0x0a,     /* 6 */
339         0x28, 0x1e, 0x28, 0x89, 0x30,
340         0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
341 };
342 static const __u8 pas202_sensor_init[][8] = {
343         {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
344         {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
345         {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
346         {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
347         {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
348         {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
349         {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
350         {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
351         {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
352         {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
353         {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
354         {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
355
356         {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
357         {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
358         {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
359         {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
360         {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
361         {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
362         {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
363         {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
364 };
365
366 static const __u8 initTas5110[] = {
367         0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
368         0x00, 0x00,
369         0x00, 0x01, 0x00, 0x46, 0x09, 0x0a,     /* shift from 0x45 0x09 0x0a */
370         0x16, 0x12, 0x60, 0x86, 0x2b,
371         0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
372 };
373 static const __u8 tas5110_sensor_init[][8] = {
374         {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
375         {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
376         {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
377 };
378
379 static const __u8 initTas5130[] = {
380         0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
381         0x00, 0x00,
382         0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
383         0x28, 0x1e, 0x60, COMP, MCK_INIT,
384         0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
385 };
386 static const __u8 tas5130_sensor_init[][8] = {
387 /*      {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
388                                         * shutter 0x47 short exposure? */
389         {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
390                                         /* shutter 0x01 long exposure */
391         {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
392 };
393
394 /* get one byte in gspca_dev->usb_buf */
395 static void reg_r(struct gspca_dev *gspca_dev,
396                   __u16 value)
397 {
398         usb_control_msg(gspca_dev->dev,
399                         usb_rcvctrlpipe(gspca_dev->dev, 0),
400                         0,                      /* request */
401                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
402                         value,
403                         0,                      /* index */
404                         gspca_dev->usb_buf, 1,
405                         500);
406 }
407
408 static void reg_w(struct gspca_dev *gspca_dev,
409                   __u16 value,
410                   const __u8 *buffer,
411                   int len)
412 {
413 #ifdef CONFIG_VIDEO_ADV_DEBUG
414         if (len > sizeof gspca_dev->usb_buf) {
415                 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
416                 return;
417         }
418 #endif
419         memcpy(gspca_dev->usb_buf, buffer, len);
420         usb_control_msg(gspca_dev->dev,
421                         usb_sndctrlpipe(gspca_dev->dev, 0),
422                         0x08,                   /* request */
423                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
424                         value,
425                         0,                      /* index */
426                         gspca_dev->usb_buf, len,
427                         500);
428 }
429
430 static void reg_w_big(struct gspca_dev *gspca_dev,
431                   __u16 value,
432                   const __u8 *buffer,
433                   int len)
434 {
435         __u8 *tmpbuf;
436
437         tmpbuf = kmalloc(len, GFP_KERNEL);
438         memcpy(tmpbuf, buffer, len);
439         usb_control_msg(gspca_dev->dev,
440                         usb_sndctrlpipe(gspca_dev->dev, 0),
441                         0x08,                   /* request */
442                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
443                         value,
444                         0,                      /* index */
445                         tmpbuf, len,
446                         500);
447         kfree(tmpbuf);
448 }
449
450 static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
451 {
452         int retry = 60;
453
454         /* is i2c ready */
455         reg_w(gspca_dev, 0x08, buffer, 8);
456         while (retry--) {
457                 msleep(10);
458                 reg_r(gspca_dev, 0x08);
459                 if (gspca_dev->usb_buf[0] == 4)
460                         return 0;
461         }
462         return -1;
463 }
464
465 static void i2c_w_vector(struct gspca_dev *gspca_dev,
466                         const __u8 buffer[][8], int len)
467 {
468         for (;;) {
469                 reg_w(gspca_dev, 0x08, *buffer, 8);
470                 len -= 8;
471                 if (len <= 0)
472                         break;
473                 buffer++;
474         }
475 }
476
477 static void setbrightness(struct gspca_dev *gspca_dev)
478 {
479         struct sd *sd = (struct sd *) gspca_dev;
480         __u8 value;
481
482         switch (sd->sensor) {
483         case SENSOR_OV6650: {
484                 __u8 i2cOV6650[] =
485                         {0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
486
487                 i2cOV6650[3] = sd->brightness;
488                 if (i2c_w(gspca_dev, i2cOV6650) < 0)
489                          goto err;
490                 break;
491             }
492         case  SENSOR_OV7630: {
493                 __u8 i2cOV[] =
494                         {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
495
496                 /* change reg 0x06 */
497                 i2cOV[3] = sd->brightness;
498                 if (i2c_w(gspca_dev, i2cOV) < 0)
499                         goto err;
500                 break;
501             }
502         case SENSOR_PAS106: {
503                 __u8 i2c1[] =
504                         {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
505
506                 i2c1[3] = sd->brightness >> 3;
507                 i2c1[2] = 0x0e;
508                 if (i2c_w(gspca_dev, i2c1) < 0)
509                         goto err;
510                 i2c1[3] = 0x01;
511                 i2c1[2] = 0x13;
512                 if (i2c_w(gspca_dev, i2c1) < 0)
513                         goto err;
514                 break;
515             }
516         case SENSOR_PAS202: {
517                 /* __u8 i2cpexpo1[] =
518                         {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
519                 __u8 i2cpexpo[] =
520                         {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
521                 __u8 i2cp202[] =
522                         {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
523                 static __u8 i2cpdoit[] =
524                         {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
525
526                 /* change reg 0x10 */
527                 i2cpexpo[4] = 0xff - sd->brightness;
528 /*              if(i2c_w(gspca_dev,i2cpexpo1) < 0)
529                         goto err; */
530 /*              if(i2c_w(gspca_dev,i2cpdoit) < 0)
531                         goto err; */
532                 if (i2c_w(gspca_dev, i2cpexpo) < 0)
533                         goto err;
534                 if (i2c_w(gspca_dev, i2cpdoit) < 0)
535                         goto err;
536                 i2cp202[3] = sd->brightness >> 3;
537                 if (i2c_w(gspca_dev, i2cp202) < 0)
538                         goto err;
539                 if (i2c_w(gspca_dev, i2cpdoit) < 0)
540                         goto err;
541                 break;
542             }
543         case SENSOR_TAS5130CXX: {
544                 __u8 i2c[] =
545                         {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
546
547                 value = 0xff - sd->brightness;
548                 i2c[4] = value;
549                 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
550                 if (i2c_w(gspca_dev, i2c) < 0)
551                         goto err;
552                 break;
553             }
554         case SENSOR_TAS5110:
555                 /* FIXME figure out howto control brightness on TAS5110 */
556                 break;
557         }
558         return;
559 err:
560         PDEBUG(D_ERR, "i2c error brightness");
561 }
562
563 static void setsensorgain(struct gspca_dev *gspca_dev)
564 {
565         struct sd *sd = (struct sd *) gspca_dev;
566         unsigned short gain;
567
568         gain = (sd->gain + 1) >> 1;
569         if (gain > 255)
570                 gain = 255;
571
572         switch (sd->sensor) {
573
574         case SENSOR_TAS5110: {
575                 __u8 i2c[] =
576                         {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
577
578                 i2c[4] = 255 - gain;
579                 if (i2c_w(gspca_dev, i2c) < 0)
580                         goto err;
581                 break;
582             }
583         case SENSOR_OV6650: {
584                 __u8 i2c[] = {0xa0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
585                 i2c[3] = gain;
586                 if (i2c_w(gspca_dev, i2c) < 0)
587                         goto err;
588                 break;
589             }
590         }
591         return;
592 err:
593         PDEBUG(D_ERR, "i2c error gain");
594 }
595
596 static void setgain(struct gspca_dev *gspca_dev)
597 {
598         struct sd *sd = (struct sd *) gspca_dev;
599         __u8 gain;
600         __u8 rgb_value;
601
602         gain = sd->gain >> 5;
603
604         /* red and blue gain */
605         rgb_value = gain << 4 | gain;
606         reg_w(gspca_dev, 0x10, &rgb_value, 1);
607         /* green gain */
608         rgb_value = gain;
609         reg_w(gspca_dev, 0x11, &rgb_value, 1);
610
611         if (sd->sensor_has_gain)
612                 setsensorgain(gspca_dev);
613 }
614
615 static void setexposure(struct gspca_dev *gspca_dev)
616 {
617         struct sd *sd = (struct sd *) gspca_dev;
618         /* translate 0 - 255 to a number of fps in a 30 - 1 scale */
619         int fps = 30 - sd->exposure * 29 / 511;
620
621         switch (sd->sensor) {
622         case SENSOR_TAS5110: {
623                 __u8 reg;
624
625                 /* register 19's high nibble contains the sn9c10x clock divider
626                    The high nibble configures the no fps according to the
627                    formula: 60 / high_nibble. With a maximum of 30 fps */
628                 reg = 60 / fps;
629                 if (reg > 15)
630                         reg = 15;
631                 reg = (reg << 4) | 0x0b;
632                 reg_w(gspca_dev, 0x19, &reg, 1);
633                 break;
634             }
635         case SENSOR_OV6650: {
636                 __u8 i2c[] = {0xa0, 0x60, 0x11, 0xc0, 0x00, 0x00, 0x00, 0x10};
637                 i2c[3] = 30 / fps - 1;
638                 if (i2c[3] > 15)
639                         i2c[3] = 15;
640                 i2c[3] |= 0xc0;
641                 if (i2c_w(gspca_dev, i2c) < 0)
642                         PDEBUG(D_ERR, "i2c error exposure");
643                 break;
644             }
645         }
646 }
647
648
649 static void do_autogain(struct gspca_dev *gspca_dev)
650 {
651         struct sd *sd = (struct sd *) gspca_dev;
652         int avg_lum = atomic_read(&sd->avg_lum);
653
654         if (avg_lum == -1)
655                 return;
656
657         if (sd->autogain_ignore_frames > 0)
658                 sd->autogain_ignore_frames--;
659         else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
660                         sd->brightness * DESIRED_AVG_LUM / 127,
661                         AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE))
662                 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
663 }
664
665 /* this function is called at probe time */
666 static int sd_config(struct gspca_dev *gspca_dev,
667                         const struct usb_device_id *id)
668 {
669         struct sd *sd = (struct sd *) gspca_dev;
670         struct cam *cam;
671         __u16 product;
672         int sif = 0;
673
674         /* nctrls depends upon the sensor, so we use a per cam copy */
675         memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
676         gspca_dev->sd_desc = &sd->sd_desc;
677
678         sd->fr_h_sz = 12;               /* default size of the frame header */
679         sd->sd_desc.nctrls = 2;         /* default nb of ctrls */
680
681         product = id->idProduct;
682 /*      switch (id->idVendor) { */
683 /*      case 0x0c45:                             * Sonix */
684                 switch (product) {
685                 case 0x6001:                    /* SN9C102 */
686                 case 0x6005:                    /* SN9C101 */
687                 case 0x6007:                    /* SN9C101 */
688                         sd->sensor = SENSOR_TAS5110;
689                         sd->sensor_has_gain = 1;
690                         sd->sd_desc.nctrls = 4;
691                         sd->sd_desc.dq_callback = do_autogain;
692                         sif = 1;
693                         break;
694                 case 0x6009:                    /* SN9C101 */
695                 case 0x600d:                    /* SN9C101 */
696                 case 0x6029:                    /* SN9C101 */
697                         sd->sensor = SENSOR_PAS106;
698                         sif = 1;
699                         break;
700                 case 0x6011:                    /* SN9C101 - SN9C101G */
701                         sd->sensor = SENSOR_OV6650;
702                         sd->sensor_has_gain = 1;
703                         sd->sd_desc.nctrls = 4;
704                         sd->sd_desc.dq_callback = do_autogain;
705                         sif = 1;
706                         break;
707                 case 0x6019:                    /* SN9C101 */
708                 case 0x602c:                    /* SN9C102 */
709                 case 0x602e:                    /* SN9C102 */
710                         sd->sensor = SENSOR_OV7630;
711                         break;
712                 case 0x60b0:                    /* SN9C103 */
713                         sd->sensor = SENSOR_OV7630_3;
714                         sd->fr_h_sz = 18;       /* size of frame header */
715                         break;
716                 case 0x6024:                    /* SN9C102 */
717                 case 0x6025:                    /* SN9C102 */
718                         sd->sensor = SENSOR_TAS5130CXX;
719                         break;
720                 case 0x6028:                    /* SN9C102 */
721                         sd->sensor = SENSOR_PAS202;
722                         break;
723                 case 0x602d:                    /* SN9C102 */
724                         sd->sensor = SENSOR_HV7131R;
725                         break;
726                 case 0x60af:                    /* SN9C103 */
727                         sd->sensor = SENSOR_PAS202;
728                         sd->fr_h_sz = 18;       /* size of frame header (?) */
729                         break;
730                 }
731 /*              break; */
732 /*      } */
733
734         cam = &gspca_dev->cam;
735         cam->dev_name = (char *) id->driver_info;
736         cam->epaddr = 0x01;
737         if (!sif) {
738                 cam->cam_mode = vga_mode;
739                 cam->nmodes = ARRAY_SIZE(vga_mode);
740                 if (sd->sensor == SENSOR_OV7630_3) {
741                         /* We only have 320x240 & 640x480 */
742                         cam->cam_mode++;
743                         cam->nmodes--;
744                 }
745         } else {
746                 cam->cam_mode = sif_mode;
747                 cam->nmodes = ARRAY_SIZE(sif_mode);
748         }
749         sd->brightness = BRIGHTNESS_DEF;
750         sd->gain = GAIN_DEF;
751         sd->exposure = EXPOSURE_DEF;
752         sd->autogain = AUTOGAIN_DEF;
753         if (sd->sensor == SENSOR_OV7630_3)      /* jfm: from win trace */
754                 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
755         return 0;
756 }
757
758 /* this function is called at open time */
759 static int sd_open(struct gspca_dev *gspca_dev)
760 {
761         reg_r(gspca_dev, 0x00);
762         if (gspca_dev->usb_buf[0] != 0x10)
763                 return -ENODEV;
764         return 0;
765 }
766
767 static void pas106_i2cinit(struct gspca_dev *gspca_dev)
768 {
769         int i;
770         const __u8 *data;
771         __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
772
773         i = ARRAY_SIZE(pas106_data);
774         data = pas106_data[0];
775         while (--i >= 0) {
776                 memcpy(&i2c1[2], data, 2);
777                                         /* copy 2 bytes from the template */
778                 if (i2c_w(gspca_dev, i2c1) < 0)
779                         PDEBUG(D_ERR, "i2c error pas106");
780                 data += 2;
781         }
782 }
783
784 /* -- start the camera -- */
785 static void sd_start(struct gspca_dev *gspca_dev)
786 {
787         struct sd *sd = (struct sd *) gspca_dev;
788         int mode, l;
789         const __u8 *sn9c10x;
790         __u8 reg01, reg17;
791         __u8 reg17_19[3];
792         static const __u8 reg15[2] = { 0x28, 0x1e };
793
794         mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
795         switch (sd->sensor) {
796         case SENSOR_HV7131R:
797                 sn9c10x = initHv7131;
798                 reg17_19[0] = 0x60;
799                 reg17_19[1] = (mode << 4) | 0x8a;
800                 reg17_19[2] = 0x20;
801                 break;
802         case SENSOR_OV6650:
803                 sn9c10x = initOv6650;
804                 reg17_19[0] = 0x68;
805                 reg17_19[1] = (mode << 4) | 0x8b;
806                 reg17_19[2] = 0x20;
807                 break;
808         case SENSOR_OV7630:
809                 sn9c10x = initOv7630;
810                 reg17_19[0] = 0x68;
811                 reg17_19[1] = (mode << 4) | COMP2;
812                 reg17_19[2] = MCK_INIT1;
813                 break;
814         case SENSOR_OV7630_3:
815                 sn9c10x = initOv7630_3;
816                 reg17_19[0] = 0x68;
817                 reg17_19[1] = (mode << 4) | COMP2;
818                 reg17_19[2] = MCK_INIT1;
819                 break;
820         case SENSOR_PAS106:
821                 sn9c10x = initPas106;
822                 reg17_19[0] = 0x24;             /* 0x28 */
823                 reg17_19[1] = (mode << 4) | COMP1;
824                 reg17_19[2] = MCK_INIT1;
825                 break;
826         case SENSOR_PAS202:
827                 sn9c10x = initPas202;
828                 reg17_19[0] = mode ? 0x24 : 0x20;
829                 reg17_19[1] = (mode << 4) | 0x89;
830                 reg17_19[2] = 0x20;
831                 break;
832         case SENSOR_TAS5110:
833                 sn9c10x = initTas5110;
834                 reg17_19[0] = 0x60;
835                 reg17_19[1] = (mode << 4) | 0x86;
836                 reg17_19[2] = 0x2b;             /* 0xf3; */
837                 break;
838         default:
839 /*      case SENSOR_TAS5130CXX: */
840                 sn9c10x = initTas5130;
841                 reg17_19[0] = 0x60;
842                 reg17_19[1] = (mode << 4) | COMP;
843                 reg17_19[2] = mode ? 0x23 : 0x43;
844                 break;
845         }
846         switch (sd->sensor) {
847         case SENSOR_OV7630:
848                 reg01 = 0x06;
849                 reg17 = 0x29;
850                 l = 0x10;
851                 break;
852         case SENSOR_OV7630_3:
853                 reg01 = 0x44;
854                 reg17 = 0x68;
855                 l = sizeof initOv7630_3;
856                 break;
857         default:
858                 reg01 = sn9c10x[0];
859                 reg17 = sn9c10x[0x17 - 1];
860                 l = 0x1f;
861                 break;
862         }
863
864         /* reg 0x01 bit 2 video transfert on */
865         reg_w(gspca_dev, 0x01, &reg01, 1);
866         /* reg 0x17 SensorClk enable inv Clk 0x60 */
867         reg_w(gspca_dev, 0x17, &reg17, 1);
868 /*fixme: for ov7630 102
869         reg_w(gspca_dev, 0x01, {0x06, sn9c10x[1]}, 2); */
870         /* Set the registers from the template */
871         reg_w_big(gspca_dev, 0x01, sn9c10x, l);
872         switch (sd->sensor) {
873         case SENSOR_HV7131R:
874                 i2c_w_vector(gspca_dev, hv7131_sensor_init,
875                                 sizeof hv7131_sensor_init);
876                 break;
877         case SENSOR_OV6650:
878                 i2c_w_vector(gspca_dev, ov6650_sensor_init,
879                                 sizeof ov6650_sensor_init);
880                 break;
881         case SENSOR_OV7630:
882                 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
883                                 sizeof ov7630_sensor_init_com);
884                 msleep(200);
885                 i2c_w_vector(gspca_dev, ov7630_sensor_init,
886                                 sizeof ov7630_sensor_init);
887                 break;
888         case SENSOR_OV7630_3:
889                 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
890                                 sizeof ov7630_sensor_init_com);
891                 msleep(200);
892                 i2c_w_vector(gspca_dev, ov7630_sensor_init_3[mode],
893                                 sizeof ov7630_sensor_init_3[mode]);
894                 break;
895         case SENSOR_PAS106:
896                 pas106_i2cinit(gspca_dev);
897                 break;
898         case SENSOR_PAS202:
899                 i2c_w_vector(gspca_dev, pas202_sensor_init,
900                                 sizeof pas202_sensor_init);
901                 break;
902         case SENSOR_TAS5110:
903                 i2c_w_vector(gspca_dev, tas5110_sensor_init,
904                                 sizeof tas5110_sensor_init);
905                 break;
906         default:
907 /*      case SENSOR_TAS5130CXX: */
908                 i2c_w_vector(gspca_dev, tas5130_sensor_init,
909                                 sizeof tas5130_sensor_init);
910                 break;
911         }
912         /* H_size V_size  0x28, 0x1e maybe 640x480 */
913         reg_w(gspca_dev, 0x15, reg15, 2);
914         /* compression register */
915         reg_w(gspca_dev, 0x18, &reg17_19[1], 1);
916         if (sd->sensor != SENSOR_OV7630_3) {
917                 /* H_start */
918                 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
919                 /* V_START */
920                 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
921         }
922         /* reset 0x17 SensorClk enable inv Clk 0x60 */
923                                 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
924         reg_w(gspca_dev, 0x17, &reg17_19[0], 1);
925         /*MCKSIZE ->3 */        /*fixme: not ov7630*/
926         if (sd->sensor != SENSOR_OV7630_3)
927                 reg_w(gspca_dev, 0x19, &reg17_19[2], 1);
928         /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
929         reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
930         /* Enable video transfert */
931         reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
932         /* Compression */
933         reg_w(gspca_dev, 0x18, &reg17_19[1], 2);
934         msleep(20);
935
936         setgain(gspca_dev);
937         setbrightness(gspca_dev);
938         setexposure(gspca_dev);
939
940         sd->autogain_ignore_frames = 0;
941         atomic_set(&sd->avg_lum, -1);
942 }
943
944 static void sd_stopN(struct gspca_dev *gspca_dev)
945 {
946         __u8 ByteSend;
947
948         ByteSend = 0x09;        /* 0X00 */
949         reg_w(gspca_dev, 0x01, &ByteSend, 1);
950 }
951
952 static void sd_stop0(struct gspca_dev *gspca_dev)
953 {
954 }
955
956 static void sd_close(struct gspca_dev *gspca_dev)
957 {
958 }
959
960 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
961                         struct gspca_frame *frame,      /* target */
962                         unsigned char *data,            /* isoc packet */
963                         int len)                        /* iso packet length */
964 {
965         int i;
966         struct sd *sd = (struct sd *) gspca_dev;
967
968         if (len > 6 && len < 24) {
969                 for (i = 0; i < len - 6; i++) {
970                         if (data[0 + i] == 0xff
971                             && data[1 + i] == 0xff
972                             && data[2 + i] == 0x00
973                             && data[3 + i] == 0xc4
974                             && data[4 + i] == 0xc4
975                             && data[5 + i] == 0x96) {   /* start of frame */
976                                 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
977                                                         frame, data, 0);
978                                 if (i < (len - 10)) {
979                                         atomic_set(&sd->avg_lum, data[i + 8] +
980                                                         (data[i + 9] << 8));
981                                 } else {
982                                         atomic_set(&sd->avg_lum, -1);
983 #ifdef CONFIG_VIDEO_ADV_DEBUG
984                                         PDEBUG(D_STREAM, "packet too short to "
985                                                 "get avg brightness");
986 #endif
987                                 }
988                                 data += i + sd->fr_h_sz;
989                                 len -= i + sd->fr_h_sz;
990                                 gspca_frame_add(gspca_dev, FIRST_PACKET,
991                                                 frame, data, len);
992                                 return;
993                         }
994                 }
995         }
996         gspca_frame_add(gspca_dev, INTER_PACKET,
997                         frame, data, len);
998 }
999
1000 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1001 {
1002         struct sd *sd = (struct sd *) gspca_dev;
1003
1004         sd->brightness = val;
1005         if (gspca_dev->streaming)
1006                 setbrightness(gspca_dev);
1007         return 0;
1008 }
1009
1010 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1011 {
1012         struct sd *sd = (struct sd *) gspca_dev;
1013
1014         *val = sd->brightness;
1015         return 0;
1016 }
1017
1018 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1019 {
1020         struct sd *sd = (struct sd *) gspca_dev;
1021
1022         sd->gain = val;
1023         if (gspca_dev->streaming)
1024                 setgain(gspca_dev);
1025         return 0;
1026 }
1027
1028 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1029 {
1030         struct sd *sd = (struct sd *) gspca_dev;
1031
1032         *val = sd->gain;
1033         return 0;
1034 }
1035
1036 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1037 {
1038         struct sd *sd = (struct sd *) gspca_dev;
1039
1040         sd->exposure = val;
1041         if (gspca_dev->streaming)
1042                 setexposure(gspca_dev);
1043         return 0;
1044 }
1045
1046 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1047 {
1048         struct sd *sd = (struct sd *) gspca_dev;
1049
1050         *val = sd->exposure;
1051         return 0;
1052 }
1053
1054 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1055 {
1056         struct sd *sd = (struct sd *) gspca_dev;
1057
1058         sd->autogain = val;
1059         /* when switching to autogain set defaults to make sure
1060            we are on a valid point of the autogain gain /
1061            exposure knee graph, and give this change time to
1062            take effect before doing autogain. */
1063         if (sd->autogain) {
1064                 sd->exposure = EXPOSURE_DEF;
1065                 sd->gain = GAIN_DEF;
1066                 if (gspca_dev->streaming) {
1067                         sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1068                         setexposure(gspca_dev);
1069                         setgain(gspca_dev);
1070                 }
1071         }
1072
1073         return 0;
1074 }
1075
1076 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1077 {
1078         struct sd *sd = (struct sd *) gspca_dev;
1079
1080         *val = sd->autogain;
1081         return 0;
1082 }
1083
1084 /* sub-driver description */
1085 static const struct sd_desc sd_desc = {
1086         .name = MODULE_NAME,
1087         .ctrls = sd_ctrls,
1088         .nctrls = ARRAY_SIZE(sd_ctrls),
1089         .config = sd_config,
1090         .open = sd_open,
1091         .start = sd_start,
1092         .stopN = sd_stopN,
1093         .stop0 = sd_stop0,
1094         .close = sd_close,
1095         .pkt_scan = sd_pkt_scan,
1096 };
1097
1098 /* -- module initialisation -- */
1099 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1100 static __devinitdata struct usb_device_id device_table[] = {
1101 #ifndef CONFIG_USB_SN9C102
1102         {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1103         {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1104         {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1105         {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1106         {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1107         {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1108         {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
1109         {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
1110         {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
1111         {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
1112         {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
1113         {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
1114         {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
1115         {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
1116         {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
1117         {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
1118 #endif
1119         {}
1120 };
1121 MODULE_DEVICE_TABLE(usb, device_table);
1122
1123 /* -- device connect -- */
1124 static int sd_probe(struct usb_interface *intf,
1125                         const struct usb_device_id *id)
1126 {
1127         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1128                                 THIS_MODULE);
1129 }
1130
1131 static struct usb_driver sd_driver = {
1132         .name = MODULE_NAME,
1133         .id_table = device_table,
1134         .probe = sd_probe,
1135         .disconnect = gspca_disconnect,
1136 };
1137
1138 /* -- module insert / remove -- */
1139 static int __init sd_mod_init(void)
1140 {
1141         if (usb_register(&sd_driver) < 0)
1142                 return -1;
1143         PDEBUG(D_PROBE, "v%s registered", version);
1144         return 0;
1145 }
1146 static void __exit sd_mod_exit(void)
1147 {
1148         usb_deregister(&sd_driver);
1149         PDEBUG(D_PROBE, "deregistered");
1150 }
1151
1152 module_init(sd_mod_init);
1153 module_exit(sd_mod_exit);