]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/media/video/gspca/pac207.c
V4L/DVB (8201): gspca: v4l2_pix_format in each subdriver.
[linux-2.6-omap-h63xx.git] / drivers / media / video / gspca / pac207.c
1 /*
2  * Pixart PAC207BCA library
3  *
4  * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
5  * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
6  * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
7  *
8  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  */
25
26 #define MODULE_NAME "pac207"
27
28 #include "gspca.h"
29
30 #define DRIVER_VERSION_NUMBER   KERNEL_VERSION(2, 1, 5)
31 static const char version[] = "2.1.5";
32
33 MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
34 MODULE_DESCRIPTION("Pixart PAC207");
35 MODULE_LICENSE("GPL");
36
37 #define PAC207_CTRL_TIMEOUT             100  /* ms */
38
39 #define PAC207_BRIGHTNESS_MIN           0
40 #define PAC207_BRIGHTNESS_MAX           255
41 #define PAC207_BRIGHTNESS_DEFAULT       4 /* power on default: 4 */
42
43 /* An exposure value of 4 also works (3 does not) but then we need to lower
44    the compression balance setting when in 352x288 mode, otherwise the usb
45    bandwidth is not enough and packets get dropped resulting in corrupt
46    frames. The problem with this is that when the compression balance gets
47    lowered below 0x80, the pac207 starts using a different compression
48    algorithm for some lines, these lines get prefixed with a 0x2dd2 prefix
49    and currently we do not know how to decompress these lines, so for now
50    we use a minimum exposure value of 5 */
51 #define PAC207_EXPOSURE_MIN             5
52 #define PAC207_EXPOSURE_MAX             26
53 #define PAC207_EXPOSURE_DEFAULT         5 /* power on default: 3 ?? */
54 #define PAC207_EXPOSURE_KNEE            11 /* 4 = 30 fps, 11 = 8, 15 = 6 */
55
56 #define PAC207_GAIN_MIN                 0
57 #define PAC207_GAIN_MAX                 31
58 #define PAC207_GAIN_DEFAULT             9 /* power on default: 9 */
59 #define PAC207_GAIN_KNEE                20
60
61 #define PAC207_AUTOGAIN_DEADZONE        30
62 /* We calculating the autogain at the end of the transfer of a frame, at this
63    moment a frame with the old settings is being transmitted, and a frame is
64    being captured with the old settings. So if we adjust the autogain we must
65    ignore atleast the 2 next frames for the new settings to come into effect
66    before doing any other adjustments */
67 #define PAC207_AUTOGAIN_IGNORE_FRAMES   3
68
69 /* specific webcam descriptor */
70 struct sd {
71         struct gspca_dev gspca_dev;             /* !! must be the first item */
72
73         u8 mode;
74
75         u8 brightness;
76         u8 exposure;
77         u8 autogain;
78         u8 gain;
79
80         u8 sof_read;
81         u8 header_read;
82         u8 autogain_ignore_frames;
83
84         atomic_t avg_lum;
85 };
86
87 /* V4L2 controls supported by the driver */
88 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
90 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
91 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
92 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
93 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
94 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
95 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
96
97 static struct ctrl sd_ctrls[] = {
98 #define SD_BRIGHTNESS 0
99         {
100             {
101                 .id      = V4L2_CID_BRIGHTNESS,
102                 .type    = V4L2_CTRL_TYPE_INTEGER,
103                 .name    = "Brightness",
104                 .minimum = PAC207_BRIGHTNESS_MIN,
105                 .maximum = PAC207_BRIGHTNESS_MAX,
106                 .step = 1,
107                 .default_value = PAC207_BRIGHTNESS_DEFAULT,
108                 .flags = 0,
109             },
110             .set = sd_setbrightness,
111             .get = sd_getbrightness,
112         },
113 #define SD_EXPOSURE 1
114         {
115             {
116                 .id = V4L2_CID_EXPOSURE,
117                 .type = V4L2_CTRL_TYPE_INTEGER,
118                 .name = "exposure",
119                 .minimum = PAC207_EXPOSURE_MIN,
120                 .maximum = PAC207_EXPOSURE_MAX,
121                 .step = 1,
122                 .default_value = PAC207_EXPOSURE_DEFAULT,
123                 .flags = 0,
124             },
125             .set = sd_setexposure,
126             .get = sd_getexposure,
127         },
128 #define SD_AUTOGAIN 2
129         {
130             {
131                 .id       = V4L2_CID_AUTOGAIN,
132                 .type   = V4L2_CTRL_TYPE_BOOLEAN,
133                 .name   = "Auto Gain",
134                 .minimum = 0,
135                 .maximum = 1,
136                 .step   = 1,
137                 .default_value = 1,
138                 .flags = 0,
139             },
140             .set = sd_setautogain,
141             .get = sd_getautogain,
142         },
143 #define SD_GAIN 3
144         {
145             {
146                 .id = V4L2_CID_GAIN,
147                 .type = V4L2_CTRL_TYPE_INTEGER,
148                 .name = "gain",
149                 .minimum = PAC207_GAIN_MIN,
150                 .maximum = PAC207_GAIN_MAX,
151                 .step = 1,
152                 .default_value = PAC207_GAIN_DEFAULT,
153                 .flags = 0,
154             },
155             .set = sd_setgain,
156             .get = sd_getgain,
157         },
158 };
159
160 static struct v4l2_pix_format sif_mode[] = {
161         {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
162                 .bytesperline = 176,
163                 .sizeimage = (176 + 2) * 144,
164                         /* uncompressed, add 2 bytes / line for line header */
165                 .colorspace = V4L2_COLORSPACE_SRGB,
166                 .priv = 1},
167         {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
168                 .bytesperline = 352,
169                 .sizeimage = 352 * 288 / 2,     /* compressed */
170                 .colorspace = V4L2_COLORSPACE_SRGB,
171                 .priv = 0},
172 };
173
174 static const __u8 pac207_sensor_init[][8] = {
175         {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0},
176         {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
177         {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
178         {0x00, 0x00, 0x32, 0x00, 0x96, 0x00, 0xa2, 0x02},
179         {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00},
180 };
181
182                         /* 48 reg_72 Rate Control end BalSize_4a =0x36 */
183 static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 };
184
185 static const unsigned char pac207_sof_marker[5] =
186                 { 0xff, 0xff, 0x00, 0xff, 0x96 };
187
188 int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
189         const u8 *buffer, u16 length)
190 {
191         struct usb_device *udev = gspca_dev->dev;
192         int err;
193         u8 kbuf[8];
194
195         memcpy(kbuf, buffer, length);
196
197         err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
198                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
199                         0x00, index, kbuf, length, PAC207_CTRL_TIMEOUT);
200         if (err < 0)
201                 PDEBUG(D_ERR,
202                         "Failed to write registers to index 0x%04X, error %d)",
203                         index, err);
204
205         return err;
206 }
207
208
209 int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
210 {
211         struct usb_device *udev = gspca_dev->dev;
212         int err;
213
214         err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
215                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
216                         value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
217         if (err)
218                 PDEBUG(D_ERR, "Failed to write a register (index 0x%04X,"
219                         " value 0x%02X, error %d)", index, value, err);
220
221         return err;
222 }
223
224
225 int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
226 {
227         struct usb_device *udev = gspca_dev->dev;
228         u8 buff;
229         int res;
230
231         res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
232                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
233                         0x00, index, &buff, 1, PAC207_CTRL_TIMEOUT);
234         if (res < 0) {
235                 PDEBUG(D_ERR,
236                         "Failed to read a register (index 0x%04X, error %d)",
237                         index, res);
238                 return res;
239         }
240
241         return buff;
242 }
243
244
245 /* this function is called at probe time */
246 static int sd_config(struct gspca_dev *gspca_dev,
247                         const struct usb_device_id *id)
248 {
249         struct sd *sd = (struct sd *) gspca_dev;
250         struct cam *cam;
251         u8 idreg[2];
252
253         idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
254         idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
255         idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4);
256         idreg[1] = idreg[1] & 0x0f;
257         PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
258                 idreg[0], idreg[1]);
259
260         if (idreg[0] != 0x27) {
261                 PDEBUG(D_PROBE, "Error invalid sensor ID!");
262                 return -ENODEV;
263         }
264
265         pac207_write_reg(gspca_dev, 0x41, 0x00);
266                                 /* Bit_0=Image Format,
267                                  * Bit_1=LED,
268                                  * Bit_2=Compression test mode enable */
269         pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
270         pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
271
272         PDEBUG(D_PROBE,
273                 "Pixart PAC207BCA Image Processor and Control Chip detected"
274                 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
275
276         cam = &gspca_dev->cam;
277         cam->dev_name = (char *) id->driver_info;
278         cam->epaddr = 0x05;
279         cam->cam_mode = sif_mode;
280         cam->nmodes = ARRAY_SIZE(sif_mode);
281         sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
282         sd->exposure = PAC207_EXPOSURE_DEFAULT;
283         sd->gain = PAC207_GAIN_DEFAULT;
284
285         return 0;
286 }
287
288 /* this function is called at open time */
289 static int sd_open(struct gspca_dev *gspca_dev)
290 {
291         struct sd *sd = (struct sd *) gspca_dev;
292
293         sd->autogain = 1;
294         return 0;
295 }
296
297 /* -- start the camera -- */
298 static void sd_start(struct gspca_dev *gspca_dev)
299 {
300         struct sd *sd = (struct sd *) gspca_dev;
301         __u8 mode;
302
303         pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
304         pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
305         pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
306         pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
307         pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8);
308         pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8);
309         pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4);
310
311         /* Compression Balance */
312         if (gspca_dev->width == 176)
313                 pac207_write_reg(gspca_dev, 0x4a, 0xff);
314         else
315                 pac207_write_reg(gspca_dev, 0x4a, 0x88);
316         pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
317         pac207_write_reg(gspca_dev, 0x08, sd->brightness);
318
319         /* PGA global gain (Bit 4-0) */
320         pac207_write_reg(gspca_dev, 0x0e, sd->gain);
321         pac207_write_reg(gspca_dev, 0x02, sd->exposure); /* PXCK = 12MHz /n */
322
323         mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
324         if (gspca_dev->width == 176) {  /* 176x144 */
325                 mode |= 0x01;
326                 PDEBUG(D_STREAM, "pac207_start mode 176x144");
327         } else {                                /* 352x288 */
328                 PDEBUG(D_STREAM, "pac207_start mode 352x288");
329         }
330         pac207_write_reg(gspca_dev, 0x41, mode);
331
332         pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
333         pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
334         msleep(10);
335         pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
336
337         sd->sof_read = 0;
338         sd->autogain_ignore_frames = 0;
339         atomic_set(&sd->avg_lum, -1);
340 }
341
342 static void sd_stopN(struct gspca_dev *gspca_dev)
343 {
344         pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
345         pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
346         pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
347 }
348
349 static void sd_stop0(struct gspca_dev *gspca_dev)
350 {
351 }
352
353 /* this function is called at close time */
354 static void sd_close(struct gspca_dev *gspca_dev)
355 {
356 }
357
358 /* auto gain and exposure algorithm based on the knee algorithm described here:
359  * <http://ytse.tricolour.net/docs/LowLightOptimization.html> */
360 static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
361 {
362         struct sd *sd = (struct sd *) gspca_dev;
363         int i, steps, desired_avg_lum;
364         int orig_gain = sd->gain;
365         int orig_exposure = sd->exposure;
366         int avg_lum = atomic_read(&sd->avg_lum);
367
368         if (!sd->autogain || avg_lum == -1)
369                 return;
370
371         if (sd->autogain_ignore_frames > 0) {
372                 sd->autogain_ignore_frames--;
373                 return;
374         }
375
376         /* correct desired lumination for the configured brightness */
377         desired_avg_lum = 100 + sd->brightness / 2;
378
379         /* If we are of a multiple of deadzone, do multiple step to reach the
380            desired lumination fast (with the risc of a slight overshoot) */
381         steps = abs(desired_avg_lum - avg_lum) / PAC207_AUTOGAIN_DEADZONE;
382
383         for (i = 0; i < steps; i++) {
384                 if (avg_lum > desired_avg_lum) {
385                         if (sd->gain > PAC207_GAIN_KNEE)
386                                 sd->gain--;
387                         else if (sd->exposure > PAC207_EXPOSURE_KNEE)
388                                 sd->exposure--;
389                         else if (sd->gain > PAC207_GAIN_DEFAULT)
390                                 sd->gain--;
391                         else if (sd->exposure > PAC207_EXPOSURE_MIN)
392                                 sd->exposure--;
393                         else if (sd->gain > PAC207_GAIN_MIN)
394                                 sd->gain--;
395                         else
396                                 break;
397                 } else {
398                         if (sd->gain < PAC207_GAIN_DEFAULT)
399                                 sd->gain++;
400                         else if (sd->exposure < PAC207_EXPOSURE_KNEE)
401                                 sd->exposure++;
402                         else if (sd->gain < PAC207_GAIN_KNEE)
403                                 sd->gain++;
404                         else if (sd->exposure < PAC207_EXPOSURE_MAX)
405                                 sd->exposure++;
406                         else if (sd->gain < PAC207_GAIN_MAX)
407                                 sd->gain++;
408                         else
409                                 break;
410                 }
411         }
412
413         if (sd->exposure != orig_exposure || sd->gain != orig_gain) {
414                 if (sd->exposure != orig_exposure)
415                         pac207_write_reg(gspca_dev, 0x0002, sd->exposure);
416                 if (sd->gain != orig_gain)
417                         pac207_write_reg(gspca_dev, 0x000e, sd->gain);
418                 pac207_write_reg(gspca_dev, 0x13, 0x01); /* load reg to sen */
419                 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
420                 sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
421         }
422 }
423
424 static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
425                                         unsigned char *m, int len)
426 {
427         struct sd *sd = (struct sd *) gspca_dev;
428         int i;
429
430         /* Search for the SOF marker (fixed part) in the header */
431         for (i = 0; i < len; i++) {
432                 if (m[i] == pac207_sof_marker[sd->sof_read]) {
433                         sd->sof_read++;
434                         if (sd->sof_read == sizeof(pac207_sof_marker)) {
435                                 PDEBUG(D_STREAM,
436                                         "SOF found, bytes to analyze: %u."
437                                         " Frame starts at byte #%u",
438                                         len, i + 1);
439                                 sd->sof_read = 0;
440                                 return m + i + 1;
441                         }
442                 } else {
443                         sd->sof_read = 0;
444                 }
445         }
446
447         return NULL;
448 }
449
450 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
451                         struct gspca_frame *frame,
452                         __u8 *data,
453                         int len)
454 {
455         struct sd *sd = (struct sd *) gspca_dev;
456         unsigned char *sof;
457
458         sof = pac207_find_sof(gspca_dev, data, len);
459         if (sof) {
460                 int n;
461
462                 /* finish decoding current frame */
463                 n = sof - data;
464                 if (n > sizeof pac207_sof_marker)
465                         n -= sizeof pac207_sof_marker;
466                 else
467                         n = 0;
468                 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
469                                         data, n);
470                 sd->header_read = 0;
471                 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
472                 len -= sof - data;
473                 data = sof;
474         }
475         if (sd->header_read < 11) {
476                 int needed;
477
478                 /* get average lumination from frame header (byte 5) */
479                 if (sd->header_read < 5) {
480                         needed = 5 - sd->header_read;
481                         if (len >= needed)
482                                 atomic_set(&sd->avg_lum, data[needed - 1]);
483                 }
484                 /* skip the rest of the header */
485                 needed = 11 - sd->header_read;
486                 if (len <= needed) {
487                         sd->header_read += len;
488                         return;
489                 }
490                 data += needed;
491                 len -= needed;
492                 sd->header_read = 11;
493         }
494
495         gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
496 }
497
498 static void setbrightness(struct gspca_dev *gspca_dev)
499 {
500         struct sd *sd = (struct sd *) gspca_dev;
501
502         pac207_write_reg(gspca_dev, 0x08, sd->brightness);
503         pac207_write_reg(gspca_dev, 0x13, 0x01);        /* Bit 0, auto clear */
504         pac207_write_reg(gspca_dev, 0x1c, 0x01);        /* not documented */
505 }
506
507 static void setexposure(struct gspca_dev *gspca_dev)
508 {
509         struct sd *sd = (struct sd *) gspca_dev;
510
511         pac207_write_reg(gspca_dev, 0x02, sd->exposure);
512         pac207_write_reg(gspca_dev, 0x13, 0x01);        /* Bit 0, auto clear */
513         pac207_write_reg(gspca_dev, 0x1c, 0x01);        /* not documented */
514 }
515
516 static void setgain(struct gspca_dev *gspca_dev)
517 {
518         struct sd *sd = (struct sd *) gspca_dev;
519
520         pac207_write_reg(gspca_dev, 0x0e, sd->gain);
521         pac207_write_reg(gspca_dev, 0x13, 0x01);        /* Bit 0, auto clear */
522         pac207_write_reg(gspca_dev, 0x1c, 0x01);        /* not documented */
523 }
524
525 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
526 {
527         struct sd *sd = (struct sd *) gspca_dev;
528
529         sd->brightness = val;
530         if (gspca_dev->streaming)
531                 setbrightness(gspca_dev);
532         return 0;
533 }
534
535 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
536 {
537         struct sd *sd = (struct sd *) gspca_dev;
538
539         *val = sd->brightness;
540         return 0;
541 }
542
543 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
544 {
545         struct sd *sd = (struct sd *) gspca_dev;
546
547         /* don't allow mucking with exposure when using autogain */
548         if (sd->autogain)
549                 return -EINVAL;
550
551         sd->exposure = val;
552         if (gspca_dev->streaming)
553                 setexposure(gspca_dev);
554         return 0;
555 }
556
557 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
558 {
559         struct sd *sd = (struct sd *) gspca_dev;
560
561         *val = sd->exposure;
562         return 0;
563 }
564
565 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
566 {
567         struct sd *sd = (struct sd *) gspca_dev;
568
569         /* don't allow mucking with gain when using autogain */
570         if (sd->autogain)
571                 return -EINVAL;
572
573         sd->gain = val;
574         if (gspca_dev->streaming)
575                 setgain(gspca_dev);
576         return 0;
577 }
578
579 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
580 {
581         struct sd *sd = (struct sd *) gspca_dev;
582
583         *val = sd->gain;
584         return 0;
585 }
586
587 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
588 {
589         struct sd *sd = (struct sd *) gspca_dev;
590
591         sd->autogain = val;
592         /* when switching to autogain set defaults to make sure
593            we are on a valid point of the autogain gain /
594            exposure knee graph, and give this change time to
595            take effect before doing autogain. */
596         if (sd->autogain) {
597                 sd->exposure = PAC207_EXPOSURE_DEFAULT;
598                 sd->gain = PAC207_GAIN_DEFAULT;
599                 if (gspca_dev->streaming) {
600                         sd->autogain_ignore_frames =
601                                 PAC207_AUTOGAIN_IGNORE_FRAMES;
602                         setexposure(gspca_dev);
603                         setgain(gspca_dev);
604                 }
605         }
606
607         return 0;
608 }
609
610 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
611 {
612         struct sd *sd = (struct sd *) gspca_dev;
613
614         *val = sd->autogain;
615         return 0;
616 }
617
618 /* sub-driver description */
619 static const struct sd_desc sd_desc = {
620         .name = MODULE_NAME,
621         .ctrls = sd_ctrls,
622         .nctrls = ARRAY_SIZE(sd_ctrls),
623         .config = sd_config,
624         .open = sd_open,
625         .start = sd_start,
626         .stopN = sd_stopN,
627         .stop0 = sd_stop0,
628         .close = sd_close,
629         .dq_callback = pac207_do_auto_gain,
630         .pkt_scan = sd_pkt_scan,
631 };
632
633 /* -- module initialisation -- */
634 #define DVNM(name) .driver_info = (kernel_ulong_t) name
635 static const __devinitdata struct usb_device_id device_table[] = {
636         {USB_DEVICE(0x041e, 0x4028), DVNM("Creative Webcam Vista Plus")},
637         {USB_DEVICE(0x093a, 0x2460), DVNM("Q-Tec Webcam 100")},
638         {USB_DEVICE(0x093a, 0x2463), DVNM("Philips spc200nc pac207")},
639         {USB_DEVICE(0x093a, 0x2464), DVNM("Labtec Webcam 1200")},
640         {USB_DEVICE(0x093a, 0x2468), DVNM("PAC207")},
641         {USB_DEVICE(0x093a, 0x2470), DVNM("Genius GF112")},
642         {USB_DEVICE(0x093a, 0x2471), DVNM("Genius VideoCam GE111")},
643         {USB_DEVICE(0x093a, 0x2472), DVNM("Genius VideoCam GE110")},
644         {USB_DEVICE(0x2001, 0xf115), DVNM("D-Link DSB-C120")},
645         {}
646 };
647 MODULE_DEVICE_TABLE(usb, device_table);
648
649 /* -- device connect -- */
650 static int sd_probe(struct usb_interface *intf,
651                         const struct usb_device_id *id)
652 {
653         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
654                                 THIS_MODULE);
655 }
656
657 static struct usb_driver sd_driver = {
658         .name = MODULE_NAME,
659         .id_table = device_table,
660         .probe = sd_probe,
661         .disconnect = gspca_disconnect,
662 };
663
664 /* -- module insert / remove -- */
665 static int __init sd_mod_init(void)
666 {
667         if (usb_register(&sd_driver) < 0)
668                 return -1;
669         PDEBUG(D_PROBE, "v%s registered", version);
670         return 0;
671 }
672 static void __exit sd_mod_exit(void)
673 {
674         usb_deregister(&sd_driver);
675         PDEBUG(D_PROBE, "deregistered");
676 }
677
678 module_init(sd_mod_init);
679 module_exit(sd_mod_exit);