V4L/DVB (8198): gspca: Frame decoding errors when PAC207 in full daylight.
[linux-2.6.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, 4)
31 static const char version[] = "2.1.4";
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 cam_mode sif_mode[] = {
161         {V4L2_PIX_FMT_PAC207, 176, 144, 1},
162         {V4L2_PIX_FMT_PAC207, 352, 288, 0},
163 };
164
165 static const __u8 pac207_sensor_init[][8] = {
166         {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0},
167         {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
168         {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
169         {0x00, 0x00, 0x32, 0x00, 0x96, 0x00, 0xa2, 0x02},
170         {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00},
171 };
172
173                         /* 48 reg_72 Rate Control end BalSize_4a =0x36 */
174 static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 };
175
176 static const unsigned char pac207_sof_marker[5] =
177                 { 0xff, 0xff, 0x00, 0xff, 0x96 };
178
179 int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
180         const u8 *buffer, u16 length)
181 {
182         struct usb_device *udev = gspca_dev->dev;
183         int err;
184         u8 kbuf[8];
185
186         memcpy(kbuf, buffer, length);
187
188         err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
189                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
190                         0x00, index, kbuf, length, PAC207_CTRL_TIMEOUT);
191         if (err < 0)
192                 PDEBUG(D_ERR,
193                         "Failed to write registers to index 0x%04X, error %d)",
194                         index, err);
195
196         return err;
197 }
198
199
200 int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
201 {
202         struct usb_device *udev = gspca_dev->dev;
203         int err;
204
205         err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
206                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
207                         value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
208         if (err)
209                 PDEBUG(D_ERR, "Failed to write a register (index 0x%04X,"
210                         " value 0x%02X, error %d)", index, value, err);
211
212         return err;
213 }
214
215
216 int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
217 {
218         struct usb_device *udev = gspca_dev->dev;
219         u8 buff;
220         int res;
221
222         res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
223                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
224                         0x00, index, &buff, 1, PAC207_CTRL_TIMEOUT);
225         if (res < 0) {
226                 PDEBUG(D_ERR,
227                         "Failed to read a register (index 0x%04X, error %d)",
228                         index, res);
229                 return res;
230         }
231
232         return buff;
233 }
234
235
236 /* this function is called at probe time */
237 static int sd_config(struct gspca_dev *gspca_dev,
238                         const struct usb_device_id *id)
239 {
240         struct sd *sd = (struct sd *) gspca_dev;
241         struct cam *cam;
242         u8 idreg[2];
243
244         idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
245         idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
246         idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4);
247         idreg[1] = idreg[1] & 0x0f;
248         PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
249                 idreg[0], idreg[1]);
250
251         if (idreg[0] != 0x27) {
252                 PDEBUG(D_PROBE, "Error invalid sensor ID!");
253                 return -ENODEV;
254         }
255
256         pac207_write_reg(gspca_dev, 0x41, 0x00);
257                                 /* Bit_0=Image Format,
258                                  * Bit_1=LED,
259                                  * Bit_2=Compression test mode enable */
260         pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
261         pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
262
263         PDEBUG(D_PROBE,
264                 "Pixart PAC207BCA Image Processor and Control Chip detected"
265                 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
266
267         cam = &gspca_dev->cam;
268         cam->dev_name = (char *) id->driver_info;
269         cam->epaddr = 0x05;
270         cam->cam_mode = sif_mode;
271         cam->nmodes = ARRAY_SIZE(sif_mode);
272         sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
273         sd->exposure = PAC207_EXPOSURE_DEFAULT;
274         sd->gain = PAC207_GAIN_DEFAULT;
275
276         return 0;
277 }
278
279 /* this function is called at open time */
280 static int sd_open(struct gspca_dev *gspca_dev)
281 {
282         struct sd *sd = (struct sd *) gspca_dev;
283
284         sd->autogain = 1;
285         return 0;
286 }
287
288 /* -- start the camera -- */
289 static void sd_start(struct gspca_dev *gspca_dev)
290 {
291         struct sd *sd = (struct sd *) gspca_dev;
292         __u8 mode;
293
294         pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
295         pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
296         pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
297         pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
298         pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8);
299         pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8);
300         pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4);
301
302         /* Compression Balance */
303         if (gspca_dev->width == 176)
304                 pac207_write_reg(gspca_dev, 0x4a, 0xff);
305         else
306                 pac207_write_reg(gspca_dev, 0x4a, 0x88);
307         pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
308         pac207_write_reg(gspca_dev, 0x08, sd->brightness);
309
310         /* PGA global gain (Bit 4-0) */
311         pac207_write_reg(gspca_dev, 0x0e, sd->gain);
312         pac207_write_reg(gspca_dev, 0x02, sd->exposure); /* PXCK = 12MHz /n */
313
314         mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
315         if (gspca_dev->width == 176) {  /* 176x144 */
316                 mode |= 0x01;
317                 PDEBUG(D_STREAM, "pac207_start mode 176x144");
318         } else {                                /* 352x288 */
319                 PDEBUG(D_STREAM, "pac207_start mode 352x288");
320         }
321         pac207_write_reg(gspca_dev, 0x41, mode);
322
323         pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
324         pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
325         msleep(10);
326         pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
327
328         sd->sof_read = 0;
329         sd->autogain_ignore_frames = 0;
330         atomic_set(&sd->avg_lum, -1);
331 }
332
333 static void sd_stopN(struct gspca_dev *gspca_dev)
334 {
335         pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
336         pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
337         pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
338 }
339
340 static void sd_stop0(struct gspca_dev *gspca_dev)
341 {
342 }
343
344 /* this function is called at close time */
345 static void sd_close(struct gspca_dev *gspca_dev)
346 {
347 }
348
349 static int sd_get_buff_size_op(struct gspca_dev *gspca_dev, int mode)
350 {
351         switch (gspca_dev->cam.cam_mode[mode].width) {
352         case 176: /* 176x144 */
353                 /* uncompressed, add 2 bytes / line for line header */
354                 return (176 + 2) * 144;
355         case 352: /* 352x288 */
356                 /* compressed */
357                 return 352 * 288 / 2;
358         }
359         return -EIO; /* should never happen */
360 }
361
362 /* auto gain and exposure algorithm based on the knee algorithm described here:
363  * <http://ytse.tricolour.net/docs/LowLightOptimization.html> */
364 static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
365 {
366         struct sd *sd = (struct sd *) gspca_dev;
367         int i, steps, desired_avg_lum;
368         int orig_gain = sd->gain;
369         int orig_exposure = sd->exposure;
370         int avg_lum = atomic_read(&sd->avg_lum);
371
372         if (!sd->autogain || avg_lum == -1)
373                 return;
374
375         if (sd->autogain_ignore_frames > 0) {
376                 sd->autogain_ignore_frames--;
377                 return;
378         }
379
380         /* correct desired lumination for the configured brightness */
381         desired_avg_lum = 100 + sd->brightness / 2;
382
383         /* If we are of a multiple of deadzone, do multiple step to reach the
384            desired lumination fast (with the risc of a slight overshoot) */
385         steps = abs(desired_avg_lum - avg_lum) / PAC207_AUTOGAIN_DEADZONE;
386
387         for (i = 0; i < steps; i++) {
388                 if (avg_lum > desired_avg_lum) {
389                         if (sd->gain > PAC207_GAIN_KNEE)
390                                 sd->gain--;
391                         else if (sd->exposure > PAC207_EXPOSURE_KNEE)
392                                 sd->exposure--;
393                         else if (sd->gain > PAC207_GAIN_DEFAULT)
394                                 sd->gain--;
395                         else if (sd->exposure > PAC207_EXPOSURE_MIN)
396                                 sd->exposure--;
397                         else if (sd->gain > PAC207_GAIN_MIN)
398                                 sd->gain--;
399                         else
400                                 break;
401                 } else {
402                         if (sd->gain < PAC207_GAIN_DEFAULT)
403                                 sd->gain++;
404                         else if (sd->exposure < PAC207_EXPOSURE_KNEE)
405                                 sd->exposure++;
406                         else if (sd->gain < PAC207_GAIN_KNEE)
407                                 sd->gain++;
408                         else if (sd->exposure < PAC207_EXPOSURE_MAX)
409                                 sd->exposure++;
410                         else if (sd->gain < PAC207_GAIN_MAX)
411                                 sd->gain++;
412                         else
413                                 break;
414                 }
415         }
416
417         if (sd->exposure != orig_exposure || sd->gain != orig_gain) {
418                 if (sd->exposure != orig_exposure)
419                         pac207_write_reg(gspca_dev, 0x0002, sd->exposure);
420                 if (sd->gain != orig_gain)
421                         pac207_write_reg(gspca_dev, 0x000e, sd->gain);
422                 pac207_write_reg(gspca_dev, 0x13, 0x01); /* load reg to sen */
423                 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
424                 sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
425         }
426 }
427
428 static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
429                                         unsigned char *m, int len)
430 {
431         struct sd *sd = (struct sd *) gspca_dev;
432         int i;
433
434         /* Search for the SOF marker (fixed part) in the header */
435         for (i = 0; i < len; i++) {
436                 if (m[i] == pac207_sof_marker[sd->sof_read]) {
437                         sd->sof_read++;
438                         if (sd->sof_read == sizeof(pac207_sof_marker)) {
439                                 PDEBUG(D_STREAM,
440                                         "SOF found, bytes to analyze: %u."
441                                         " Frame starts at byte #%u",
442                                         len, i + 1);
443                                 sd->sof_read = 0;
444                                 return m + i + 1;
445                         }
446                 } else {
447                         sd->sof_read = 0;
448                 }
449         }
450
451         return NULL;
452 }
453
454 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
455                         struct gspca_frame *frame,
456                         __u8 *data,
457                         int len)
458 {
459         struct sd *sd = (struct sd *) gspca_dev;
460         unsigned char *sof;
461
462         sof = pac207_find_sof(gspca_dev, data, len);
463         if (sof) {
464                 int n;
465
466                 /* finish decoding current frame */
467                 n = sof - data;
468                 if (n > sizeof pac207_sof_marker)
469                         n -= sizeof pac207_sof_marker;
470                 else
471                         n = 0;
472                 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
473                                         data, n);
474                 sd->header_read = 0;
475                 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
476                 len -= sof - data;
477                 data = sof;
478         }
479         if (sd->header_read < 11) {
480                 int needed;
481
482                 /* get average lumination from frame header (byte 5) */
483                 if (sd->header_read < 5) {
484                         needed = 5 - sd->header_read;
485                         if (len >= needed)
486                                 atomic_set(&sd->avg_lum, data[needed - 1]);
487                 }
488                 /* skip the rest of the header */
489                 needed = 11 - sd->header_read;
490                 if (len <= needed) {
491                         sd->header_read += len;
492                         return;
493                 }
494                 data += needed;
495                 len -= needed;
496                 sd->header_read = 11;
497         }
498
499         gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
500 }
501
502 static void setbrightness(struct gspca_dev *gspca_dev)
503 {
504         struct sd *sd = (struct sd *) gspca_dev;
505
506         pac207_write_reg(gspca_dev, 0x08, sd->brightness);
507         pac207_write_reg(gspca_dev, 0x13, 0x01);        /* Bit 0, auto clear */
508         pac207_write_reg(gspca_dev, 0x1c, 0x01);        /* not documented */
509 }
510
511 static void setexposure(struct gspca_dev *gspca_dev)
512 {
513         struct sd *sd = (struct sd *) gspca_dev;
514
515         pac207_write_reg(gspca_dev, 0x02, sd->exposure);
516         pac207_write_reg(gspca_dev, 0x13, 0x01);        /* Bit 0, auto clear */
517         pac207_write_reg(gspca_dev, 0x1c, 0x01);        /* not documented */
518 }
519
520 static void setgain(struct gspca_dev *gspca_dev)
521 {
522         struct sd *sd = (struct sd *) gspca_dev;
523
524         pac207_write_reg(gspca_dev, 0x0e, sd->gain);
525         pac207_write_reg(gspca_dev, 0x13, 0x01);        /* Bit 0, auto clear */
526         pac207_write_reg(gspca_dev, 0x1c, 0x01);        /* not documented */
527 }
528
529 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
530 {
531         struct sd *sd = (struct sd *) gspca_dev;
532
533         sd->brightness = val;
534         if (gspca_dev->streaming)
535                 setbrightness(gspca_dev);
536         return 0;
537 }
538
539 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
540 {
541         struct sd *sd = (struct sd *) gspca_dev;
542
543         *val = sd->brightness;
544         return 0;
545 }
546
547 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
548 {
549         struct sd *sd = (struct sd *) gspca_dev;
550
551         /* don't allow mucking with exposure when using autogain */
552         if (sd->autogain)
553                 return -EINVAL;
554
555         sd->exposure = val;
556         if (gspca_dev->streaming)
557                 setexposure(gspca_dev);
558         return 0;
559 }
560
561 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
562 {
563         struct sd *sd = (struct sd *) gspca_dev;
564
565         *val = sd->exposure;
566         return 0;
567 }
568
569 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
570 {
571         struct sd *sd = (struct sd *) gspca_dev;
572
573         /* don't allow mucking with gain when using autogain */
574         if (sd->autogain)
575                 return -EINVAL;
576
577         sd->gain = val;
578         if (gspca_dev->streaming)
579                 setgain(gspca_dev);
580         return 0;
581 }
582
583 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
584 {
585         struct sd *sd = (struct sd *) gspca_dev;
586
587         *val = sd->gain;
588         return 0;
589 }
590
591 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
592 {
593         struct sd *sd = (struct sd *) gspca_dev;
594
595         sd->autogain = val;
596         /* when switching to autogain set defaults to make sure
597            we are on a valid point of the autogain gain /
598            exposure knee graph, and give this change time to
599            take effect before doing autogain. */
600         if (sd->autogain) {
601                 sd->exposure = PAC207_EXPOSURE_DEFAULT;
602                 sd->gain = PAC207_GAIN_DEFAULT;
603                 if (gspca_dev->streaming) {
604                         sd->autogain_ignore_frames =
605                                 PAC207_AUTOGAIN_IGNORE_FRAMES;
606                         setexposure(gspca_dev);
607                         setgain(gspca_dev);
608                 }
609         }
610
611         return 0;
612 }
613
614 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
615 {
616         struct sd *sd = (struct sd *) gspca_dev;
617
618         *val = sd->autogain;
619         return 0;
620 }
621
622 /* sub-driver description */
623 static const struct sd_desc sd_desc = {
624         .name = MODULE_NAME,
625         .ctrls = sd_ctrls,
626         .nctrls = ARRAY_SIZE(sd_ctrls),
627         .config = sd_config,
628         .open = sd_open,
629         .start = sd_start,
630         .stopN = sd_stopN,
631         .stop0 = sd_stop0,
632         .close = sd_close,
633         .dq_callback = pac207_do_auto_gain,
634         .pkt_scan = sd_pkt_scan,
635         .get_buff_size = sd_get_buff_size_op,
636 };
637
638 /* -- module initialisation -- */
639 #define DVNM(name) .driver_info = (kernel_ulong_t) name
640 static const __devinitdata struct usb_device_id device_table[] = {
641         {USB_DEVICE(0x041e, 0x4028), DVNM("Creative Webcam Vista Plus")},
642         {USB_DEVICE(0x093a, 0x2460), DVNM("Q-Tec Webcam 100")},
643         {USB_DEVICE(0x093a, 0x2463), DVNM("Philips spc200nc pac207")},
644         {USB_DEVICE(0x093a, 0x2464), DVNM("Labtec Webcam 1200")},
645         {USB_DEVICE(0x093a, 0x2468), DVNM("PAC207")},
646         {USB_DEVICE(0x093a, 0x2470), DVNM("Genius GF112")},
647         {USB_DEVICE(0x093a, 0x2471), DVNM("Genius VideoCam GE111")},
648         {USB_DEVICE(0x093a, 0x2472), DVNM("Genius VideoCam GE110")},
649         {USB_DEVICE(0x2001, 0xf115), DVNM("D-Link DSB-C120")},
650         {}
651 };
652 MODULE_DEVICE_TABLE(usb, device_table);
653
654 /* -- device connect -- */
655 static int sd_probe(struct usb_interface *intf,
656                         const struct usb_device_id *id)
657 {
658         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
659                                 THIS_MODULE);
660 }
661
662 static struct usb_driver sd_driver = {
663         .name = MODULE_NAME,
664         .id_table = device_table,
665         .probe = sd_probe,
666         .disconnect = gspca_disconnect,
667 };
668
669 /* -- module insert / remove -- */
670 static int __init sd_mod_init(void)
671 {
672         if (usb_register(&sd_driver) < 0)
673                 return -1;
674         PDEBUG(D_PROBE, "v%s registered", version);
675         return 0;
676 }
677 static void __exit sd_mod_exit(void)
678 {
679         usb_deregister(&sd_driver);
680         PDEBUG(D_PROBE, "deregistered");
681 }
682
683 module_init(sd_mod_init);
684 module_exit(sd_mod_exit);