2 * Pixart PAC7311 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define MODULE_NAME "pac7311"
27 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
28 MODULE_DESCRIPTION("Pixart PAC7311");
29 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
33 struct gspca_dev gspca_dev; /* !! must be the first item */
39 unsigned char brightness;
40 unsigned char contrast;
42 unsigned char autogain;
44 char tosof; /* number of bytes before next start of frame */
46 #define AG_CNT_START 13
49 #define SENSOR_PAC7302 0
50 #define SENSOR_PAC7311 1
53 /* V4L2 controls supported by the driver */
54 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
55 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
56 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
57 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
58 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
59 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
60 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
61 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
63 static struct ctrl sd_ctrls[] = {
66 .id = V4L2_CID_BRIGHTNESS,
67 .type = V4L2_CTRL_TYPE_INTEGER,
70 #define BRIGHTNESS_MAX 0x20
71 .maximum = BRIGHTNESS_MAX,
73 #define BRIGHTNESS_DEF 0x10
74 .default_value = BRIGHTNESS_DEF,
76 .set = sd_setbrightness,
77 .get = sd_getbrightness,
81 .id = V4L2_CID_CONTRAST,
82 .type = V4L2_CTRL_TYPE_INTEGER,
87 #define CONTRAST_DEF 127
88 .default_value = CONTRAST_DEF,
90 .set = sd_setcontrast,
91 .get = sd_getcontrast,
95 .id = V4L2_CID_SATURATION,
96 .type = V4L2_CTRL_TYPE_INTEGER,
101 #define COLOR_DEF 127
102 .default_value = COLOR_DEF,
109 .id = V4L2_CID_AUTOGAIN,
110 .type = V4L2_CTRL_TYPE_BOOLEAN,
115 #define AUTOGAIN_DEF 1
116 .default_value = AUTOGAIN_DEF,
118 .set = sd_setautogain,
119 .get = sd_getautogain,
123 static struct v4l2_pix_format vga_mode[] = {
124 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
126 .sizeimage = 160 * 120 * 3 / 8 + 590,
127 .colorspace = V4L2_COLORSPACE_JPEG,
129 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
131 .sizeimage = 320 * 240 * 3 / 8 + 590,
132 .colorspace = V4L2_COLORSPACE_JPEG,
134 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
136 .sizeimage = 640 * 480 * 3 / 8 + 590,
137 .colorspace = V4L2_COLORSPACE_JPEG,
142 static const __u8 probe_7302[] = {
144 0xff, 0x01, /* page 1 */
145 0x78, 0x00, /* deactivate */
147 0x78, 0x40, /* led off */
149 static const __u8 start_7302[] = {
150 /* index, len, [value]* */
151 0xff, 1, 0x00, /* page 0 */
152 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
153 0x00, 0x00, 0x00, 0x00,
154 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
155 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
156 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
160 0x3a, 3, 0x14, 0xff, 0x5a,
161 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
164 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
166 0x6e, 3, 0x08, 0x06, 0x00,
167 0x72, 3, 0x00, 0xff, 0x00,
168 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
169 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
170 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
171 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
176 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
178 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
181 0xff, 1, 0x01, /* page 1 */
182 0x12, 3, 0x02, 0x00, 0x01,
184 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
186 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
188 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
189 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
190 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
193 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
194 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
196 0xff, 1, 0x02, /* page 2 */
198 0xff, 1, 0x03, /* page 3 */
199 0x00, 255, /* load the page 3 */
201 0xff, 1, 0x02, /* page 2 */
203 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
205 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
206 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
208 0xff, 1, 0x03, /* page 1 */
210 0, 0 /* end of sequence */
213 /* page 3 - the value 0xaa says skip the index - see reg_w_page() */
214 static const __u8 page3_7302[] = {
215 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
216 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
217 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
219 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
220 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
221 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
222 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
224 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
225 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
229 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
230 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
231 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
238 static const __u8 probe_7311[] = {
239 0x78, 0x40, /* Bit_0=start stream, Bit_7=LED */
240 0x78, 0x40, /* Bit_0=start stream, Bit_7=LED */
241 0x78, 0x44, /* Bit_0=start stream, Bit_7=LED */
251 static const __u8 start_7311[] = {
252 /* index, len, [value]* */
253 0xff, 1, 0x01, /* page 1 */
254 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
255 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
256 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
257 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
261 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
262 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
263 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
264 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
266 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
267 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
268 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
270 0x96, 3, 0x01, 0x08, 0x04,
271 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
272 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
273 0x3f, 0x00, 0x0a, 0x01, 0x00,
274 0xff, 1, 0x04, /* page 4 */
275 0x00, 254, /* load the page 4 */
277 0, 0 /* end of sequence */
280 /* page 4 - the value 0xaa says skip the index - see reg_w_page() */
281 static const __u8 page4_7311[] = {
282 0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
283 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62,
284 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa,
286 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x01,
287 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
288 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
291 static void reg_w_buf(struct gspca_dev *gspca_dev,
293 const char *buffer, int len)
295 memcpy(gspca_dev->usb_buf, buffer, len);
296 usb_control_msg(gspca_dev->dev,
297 usb_sndctrlpipe(gspca_dev->dev, 0),
299 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
301 index, gspca_dev->usb_buf, len,
305 static __u8 reg_r(struct gspca_dev *gspca_dev,
308 usb_control_msg(gspca_dev->dev,
309 usb_rcvctrlpipe(gspca_dev->dev, 0),
311 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
313 index, gspca_dev->usb_buf, 1,
315 return gspca_dev->usb_buf[0];
318 static void reg_w(struct gspca_dev *gspca_dev,
322 gspca_dev->usb_buf[0] = value;
323 usb_control_msg(gspca_dev->dev,
324 usb_sndctrlpipe(gspca_dev->dev, 0),
326 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
327 value, index, gspca_dev->usb_buf, 1,
331 static void reg_w_seq(struct gspca_dev *gspca_dev,
332 const __u8 *seq, int len)
335 reg_w(gspca_dev, seq[0], seq[1]);
340 /* load the beginning of a page */
341 static void reg_w_page(struct gspca_dev *gspca_dev,
342 const __u8 *page, int len)
346 for (index = 0; index < len; index++) {
347 if (page[index] == 0xaa) /* skip this index */
349 gspca_dev->usb_buf[0] = page[index];
350 usb_control_msg(gspca_dev->dev,
351 usb_sndctrlpipe(gspca_dev->dev, 0),
353 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
354 0, index, gspca_dev->usb_buf, 1,
359 /* output a variable sequence */
360 static void reg_w_var(struct gspca_dev *gspca_dev,
372 reg_w_page(gspca_dev, page4_7311, sizeof page4_7311);
375 reg_w_page(gspca_dev, page3_7302, sizeof page3_7302);
379 PDEBUG(D_ERR|D_STREAM,
380 "Incorrect variable sequence");
385 reg_w_buf(gspca_dev, index, seq, len);
389 reg_w_buf(gspca_dev, index, seq, 8);
399 /* this function is called at probe time */
400 static int sd_config(struct gspca_dev *gspca_dev,
401 const struct usb_device_id *id)
403 struct sd *sd = (struct sd *) gspca_dev;
406 cam = &gspca_dev->cam;
409 sd->sensor = id->driver_info;
410 if (sd->sensor == SENSOR_PAC7302) {
411 PDEBUG(D_CONF, "Find Sensor PAC7302");
412 reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302);
414 cam->cam_mode = &vga_mode[2]; /* only 640x480 */
417 PDEBUG(D_CONF, "Find Sensor PAC7311");
418 reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302);
420 cam->cam_mode = vga_mode;
421 cam->nmodes = ARRAY_SIZE(vga_mode);
424 sd->brightness = BRIGHTNESS_DEF;
425 sd->contrast = CONTRAST_DEF;
426 sd->colors = COLOR_DEF;
427 sd->autogain = AUTOGAIN_DEF;
432 static void setbrightness(struct gspca_dev *gspca_dev)
434 struct sd *sd = (struct sd *) gspca_dev;
437 if (sd->sensor == SENSOR_PAC7302)
440 brightness = BRIGHTNESS_MAX - sd->brightness;
441 reg_w(gspca_dev, 0xff, 0x04);
442 reg_w(gspca_dev, 0x0f, brightness);
443 /* load registers to sensor (Bit 0, auto clear) */
444 reg_w(gspca_dev, 0x11, 0x01);
445 PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
448 static void setcontrast(struct gspca_dev *gspca_dev)
450 struct sd *sd = (struct sd *) gspca_dev;
452 if (sd->sensor == SENSOR_PAC7302)
454 reg_w(gspca_dev, 0xff, 0x01);
455 reg_w(gspca_dev, 0x80, sd->contrast);
456 /* load registers to sensor (Bit 0, auto clear) */
457 reg_w(gspca_dev, 0x11, 0x01);
458 PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
461 static void setcolors(struct gspca_dev *gspca_dev)
463 struct sd *sd = (struct sd *) gspca_dev;
465 if (sd->sensor == SENSOR_PAC7302)
467 reg_w(gspca_dev, 0xff, 0x01);
468 reg_w(gspca_dev, 0x10, sd->colors);
469 /* load registers to sensor (Bit 0, auto clear) */
470 reg_w(gspca_dev, 0x11, 0x01);
471 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
474 static void setautogain(struct gspca_dev *gspca_dev)
476 struct sd *sd = (struct sd *) gspca_dev;
480 sd->ag_cnt = AG_CNT_START;
486 /* this function is called at open time */
487 static int sd_open(struct gspca_dev *gspca_dev)
489 reg_w(gspca_dev, 0x78, 0x00); /* Turn on LED */
493 static void sd_start(struct gspca_dev *gspca_dev)
495 struct sd *sd = (struct sd *) gspca_dev;
499 if (sd->sensor == SENSOR_PAC7302)
500 reg_w_var(gspca_dev, start_7302);
502 reg_w_var(gspca_dev, start_7311);
504 setcontrast(gspca_dev);
505 setbrightness(gspca_dev);
506 setcolors(gspca_dev);
507 setautogain(gspca_dev);
509 /* set correct resolution */
510 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
511 case 2: /* 160x120 pac7311 */
512 reg_w(gspca_dev, 0xff, 0x04);
513 reg_w(gspca_dev, 0x02, 0x03);
514 reg_w(gspca_dev, 0xff, 0x01);
515 reg_w(gspca_dev, 0x08, 0x09);
516 reg_w(gspca_dev, 0x17, 0x20);
517 reg_w(gspca_dev, 0x1b, 0x00);
518 /* reg_w(gspca_dev, 0x80, 0x69); */
519 reg_w(gspca_dev, 0x87, 0x10);
521 case 1: /* 320x240 pac7311 */
522 reg_w(gspca_dev, 0xff, 0x04);
523 reg_w(gspca_dev, 0x02, 0x03);
524 reg_w(gspca_dev, 0xff, 0x01);
525 reg_w(gspca_dev, 0x08, 0x09);
526 reg_w(gspca_dev, 0x17, 0x30);
527 /* reg_w(gspca_dev, 0x80, 0x3f); */
528 reg_w(gspca_dev, 0x87, 0x11);
530 case 0: /* 640x480 */
531 if (sd->sensor == SENSOR_PAC7302)
533 reg_w(gspca_dev, 0xff, 0x04);
534 reg_w(gspca_dev, 0x02, 0x03);
535 reg_w(gspca_dev, 0xff, 0x01);
536 reg_w(gspca_dev, 0x08, 0x08);
537 reg_w(gspca_dev, 0x17, 0x00);
538 /* reg_w(gspca_dev, 0x80, 0x1c); */
539 reg_w(gspca_dev, 0x87, 0x12);
544 reg_w(gspca_dev, 0xff, 0x01);
545 if (sd->sensor == SENSOR_PAC7302) {
546 reg_w(gspca_dev, 0x78, 0x01);
547 reg_w(gspca_dev, 0xff, 0x01);
548 reg_w(gspca_dev, 0x78, 0x01);
550 reg_w(gspca_dev, 0x78, 0x04);
551 reg_w(gspca_dev, 0x78, 0x05);
555 static void sd_stopN(struct gspca_dev *gspca_dev)
557 struct sd *sd = (struct sd *) gspca_dev;
559 if (sd->sensor == SENSOR_PAC7302) {
560 reg_w(gspca_dev, 0x78, 0x00);
561 reg_w(gspca_dev, 0x78, 0x00);
564 reg_w(gspca_dev, 0xff, 0x04);
565 reg_w(gspca_dev, 0x27, 0x80);
566 reg_w(gspca_dev, 0x28, 0xca);
567 reg_w(gspca_dev, 0x29, 0x53);
568 reg_w(gspca_dev, 0x2a, 0x0e);
569 reg_w(gspca_dev, 0xff, 0x01);
570 reg_w(gspca_dev, 0x3e, 0x20);
571 reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
572 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
573 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
576 static void sd_stop0(struct gspca_dev *gspca_dev)
578 struct sd *sd = (struct sd *) gspca_dev;
580 if (sd->sensor == SENSOR_PAC7302) {
581 reg_w(gspca_dev, 0xff, 0x01);
582 reg_w(gspca_dev, 0x78, 0x40);
586 /* this function is called at close time */
587 static void sd_close(struct gspca_dev *gspca_dev)
591 static void do_autogain(struct gspca_dev *gspca_dev)
593 struct sd *sd = (struct sd *) gspca_dev;
600 if (!atomic_read(&sd->do_gain))
602 atomic_set(&sd->do_gain, 0);
604 luma = atomic_read(&sd->avg_lum);
605 Gbright = reg_r(gspca_dev, 0x02);
606 PDEBUG(D_FRAM, "luma mean %d", luma);
607 if (luma < luma_mean - luma_delta ||
608 luma > luma_mean + luma_delta) {
609 Gbright += (luma_mean - luma) >> spring;
612 else if (Gbright < 4)
614 PDEBUG(D_FRAM, "gbright %d", Gbright);
615 if (sd->sensor == SENSOR_PAC7302) {
616 reg_w(gspca_dev, 0xff, 0x03);
617 reg_w(gspca_dev, 0x10, Gbright);
618 /* load registers to sensor (Bit 0, auto clear) */
619 reg_w(gspca_dev, 0x11, 0x01);
621 reg_w(gspca_dev, 0xff, 0x04);
622 reg_w(gspca_dev, 0x0f, Gbright);
623 /* load registers to sensor (Bit 0, auto clear) */
624 reg_w(gspca_dev, 0x11, 0x01);
629 /* this function is run at interrupt level */
630 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
631 struct gspca_frame *frame, /* target */
632 __u8 *data, /* isoc packet */
633 int len) /* iso packet length */
635 struct sd *sd = (struct sd *) gspca_dev;
638 #define INTER_FRAME 0x53 /* eof + inter frame + sof */
639 #define LUM_OFFSET 0x1e /* reverse offset / start of frame */
642 * inside a frame, there may be:
643 * escaped ff ('ff 00')
644 * sequences'ff ff ff xx' to remove
645 * end of frame ('ff d9')
646 * at the end of frame, there are:
649 * one byte luminosity
651 * ff ff 00 ff 96 62 44 start of frame
654 if (sd->tosof != 0) { /* if outside a frame */
656 /* get the luminosity and go to the start of frame */
659 if (sd->tosof > LUM_OFFSET)
660 sd->lum_sum += data[-LUM_OFFSET];
662 jpeg_put_header(gspca_dev, frame, 1, 0x21);
665 for (i = 0; i < len; i++) {
668 switch (data[i + 1]) {
669 case 0xd9: /* 'ff d9' end of frame */
670 frame = gspca_frame_add(gspca_dev,
673 data += i + INTER_FRAME;
674 len -= i + INTER_FRAME;
676 if (len > -LUM_OFFSET)
677 sd->lum_sum += data[-LUM_OFFSET];
682 jpeg_put_header(gspca_dev, frame, 1, 0x21);
686 gspca_frame_add(gspca_dev, INTER_PACKET,
690 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
692 struct sd *sd = (struct sd *) gspca_dev;
694 sd->brightness = val;
695 if (gspca_dev->streaming)
696 setbrightness(gspca_dev);
700 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
702 struct sd *sd = (struct sd *) gspca_dev;
704 *val = sd->brightness;
708 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
710 struct sd *sd = (struct sd *) gspca_dev;
713 if (gspca_dev->streaming)
714 setcontrast(gspca_dev);
718 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
720 struct sd *sd = (struct sd *) gspca_dev;
726 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
728 struct sd *sd = (struct sd *) gspca_dev;
731 if (gspca_dev->streaming)
732 setcolors(gspca_dev);
736 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
738 struct sd *sd = (struct sd *) gspca_dev;
744 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
746 struct sd *sd = (struct sd *) gspca_dev;
749 if (gspca_dev->streaming)
750 setautogain(gspca_dev);
754 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
756 struct sd *sd = (struct sd *) gspca_dev;
762 /* sub-driver description */
763 static struct sd_desc sd_desc = {
766 .nctrls = ARRAY_SIZE(sd_ctrls),
773 .pkt_scan = sd_pkt_scan,
774 .dq_callback = do_autogain,
777 /* -- module initialisation -- */
778 static __devinitdata struct usb_device_id device_table[] = {
779 {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311},
780 {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311},
781 {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311},
782 {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311},
783 {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311},
784 {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311},
785 {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
788 MODULE_DEVICE_TABLE(usb, device_table);
790 /* -- device connect -- */
791 static int sd_probe(struct usb_interface *intf,
792 const struct usb_device_id *id)
794 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
798 static struct usb_driver sd_driver = {
800 .id_table = device_table,
802 .disconnect = gspca_disconnect,
805 /* -- module insert / remove -- */
806 static int __init sd_mod_init(void)
808 if (usb_register(&sd_driver) < 0)
810 PDEBUG(D_PROBE, "registered");
813 static void __exit sd_mod_exit(void)
815 usb_deregister(&sd_driver);
816 PDEBUG(D_PROBE, "deregistered");
819 module_init(sd_mod_init);
820 module_exit(sd_mod_exit);