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