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;
47 char tosof; /* number of bytes before next start of frame */
49 #define AG_CNT_START 13
52 #define SENSOR_PAC7302 0
53 #define SENSOR_PAC7311 1
56 /* V4L2 controls supported by the driver */
57 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
58 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
59 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
60 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
61 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
62 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
63 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
64 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
65 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
67 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
70 static struct ctrl sd_ctrls[] = {
73 .id = V4L2_CID_BRIGHTNESS,
74 .type = V4L2_CTRL_TYPE_INTEGER,
77 #define BRIGHTNESS_MAX 0x20
78 .maximum = BRIGHTNESS_MAX,
80 #define BRIGHTNESS_DEF 0x10
81 .default_value = BRIGHTNESS_DEF,
83 .set = sd_setbrightness,
84 .get = sd_getbrightness,
88 .id = V4L2_CID_CONTRAST,
89 .type = V4L2_CTRL_TYPE_INTEGER,
92 #define CONTRAST_MAX 255
93 .maximum = CONTRAST_MAX,
95 #define CONTRAST_DEF 60
96 .default_value = CONTRAST_DEF,
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Saturation",
107 #define COLOR_MAX 255
108 .maximum = COLOR_MAX,
110 #define COLOR_DEF 127
111 .default_value = COLOR_DEF,
118 .id = V4L2_CID_AUTOGAIN,
119 .type = V4L2_CTRL_TYPE_BOOLEAN,
124 #define AUTOGAIN_DEF 1
125 .default_value = AUTOGAIN_DEF,
127 .set = sd_setautogain,
128 .get = sd_getautogain,
130 /* next controls work with pac7302 only */
133 .id = V4L2_CID_HFLIP,
134 .type = V4L2_CTRL_TYPE_BOOLEAN,
140 .default_value = HFLIP_DEF,
147 .id = V4L2_CID_VFLIP,
148 .type = V4L2_CTRL_TYPE_BOOLEAN,
154 .default_value = VFLIP_DEF,
161 static struct v4l2_pix_format vga_mode[] = {
162 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
164 .sizeimage = 160 * 120 * 3 / 8 + 590,
165 .colorspace = V4L2_COLORSPACE_JPEG,
167 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
169 .sizeimage = 320 * 240 * 3 / 8 + 590,
170 .colorspace = V4L2_COLORSPACE_JPEG,
172 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
174 .sizeimage = 640 * 480 * 3 / 8 + 590,
175 .colorspace = V4L2_COLORSPACE_JPEG,
180 static const __u8 probe_7302[] = {
182 0xff, 0x01, /* page 1 */
183 0x78, 0x00, /* deactivate */
185 0x78, 0x40, /* led off */
187 static const __u8 start_7302[] = {
188 /* index, len, [value]* */
189 0xff, 1, 0x00, /* page 0 */
190 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
191 0x00, 0x00, 0x00, 0x00,
192 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
193 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
194 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
198 0x3a, 3, 0x14, 0xff, 0x5a,
199 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
202 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
204 0x6e, 3, 0x08, 0x06, 0x00,
205 0x72, 3, 0x00, 0xff, 0x00,
206 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
207 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
208 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
209 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
214 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
216 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
219 0xff, 1, 0x01, /* page 1 */
220 0x12, 3, 0x02, 0x00, 0x01,
222 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
224 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
226 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
227 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
228 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
231 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
232 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
234 0xff, 1, 0x02, /* page 2 */
236 0xff, 1, 0x03, /* page 3 */
237 0x00, 255, /* load the page 3 */
239 0xff, 1, 0x02, /* page 2 */
241 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
243 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
244 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
246 0xff, 1, 0x03, /* page 1 */
248 0, 0 /* end of sequence */
251 /* page 3 - the value 0xaa says skip the index - see reg_w_page() */
252 static const __u8 page3_7302[] = {
253 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
254 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
255 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
257 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
258 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
259 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
260 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
262 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
263 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
264 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
266 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
267 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
268 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
269 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
276 static const __u8 probe_7311[] = {
277 0x78, 0x40, /* Bit_0=start stream, Bit_7=LED */
278 0x78, 0x40, /* Bit_0=start stream, Bit_7=LED */
279 0x78, 0x44, /* Bit_0=start stream, Bit_7=LED */
289 static const __u8 start_7311[] = {
290 /* index, len, [value]* */
291 0xff, 1, 0x01, /* page 1 */
292 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
293 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
294 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
295 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
299 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
300 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
301 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
302 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
304 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
305 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
306 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
308 0x96, 3, 0x01, 0x08, 0x04,
309 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
310 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
311 0x3f, 0x00, 0x0a, 0x01, 0x00,
312 0xff, 1, 0x04, /* page 4 */
313 0x00, 254, /* load the page 4 */
315 0, 0 /* end of sequence */
318 /* page 4 - the value 0xaa says skip the index - see reg_w_page() */
319 static const __u8 page4_7311[] = {
320 0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
321 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62,
322 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa,
324 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x01,
325 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
326 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
329 static void reg_w_buf(struct gspca_dev *gspca_dev,
331 const char *buffer, int len)
333 memcpy(gspca_dev->usb_buf, buffer, len);
334 usb_control_msg(gspca_dev->dev,
335 usb_sndctrlpipe(gspca_dev->dev, 0),
337 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
339 index, gspca_dev->usb_buf, len,
343 static __u8 reg_r(struct gspca_dev *gspca_dev,
346 usb_control_msg(gspca_dev->dev,
347 usb_rcvctrlpipe(gspca_dev->dev, 0),
349 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
351 index, gspca_dev->usb_buf, 1,
353 return gspca_dev->usb_buf[0];
356 static void reg_w(struct gspca_dev *gspca_dev,
360 gspca_dev->usb_buf[0] = value;
361 usb_control_msg(gspca_dev->dev,
362 usb_sndctrlpipe(gspca_dev->dev, 0),
364 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
365 value, index, gspca_dev->usb_buf, 1,
369 static void reg_w_seq(struct gspca_dev *gspca_dev,
370 const __u8 *seq, int len)
373 reg_w(gspca_dev, seq[0], seq[1]);
378 /* load the beginning of a page */
379 static void reg_w_page(struct gspca_dev *gspca_dev,
380 const __u8 *page, int len)
384 for (index = 0; index < len; index++) {
385 if (page[index] == 0xaa) /* skip this index */
387 gspca_dev->usb_buf[0] = page[index];
388 usb_control_msg(gspca_dev->dev,
389 usb_sndctrlpipe(gspca_dev->dev, 0),
391 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
392 0, index, gspca_dev->usb_buf, 1,
397 /* output a variable sequence */
398 static void reg_w_var(struct gspca_dev *gspca_dev,
410 reg_w_page(gspca_dev, page4_7311, sizeof page4_7311);
413 reg_w_page(gspca_dev, page3_7302, sizeof page3_7302);
417 PDEBUG(D_ERR|D_STREAM,
418 "Incorrect variable sequence");
423 reg_w_buf(gspca_dev, index, seq, len);
427 reg_w_buf(gspca_dev, index, seq, 8);
437 /* this function is called at probe time */
438 static int sd_config(struct gspca_dev *gspca_dev,
439 const struct usb_device_id *id)
441 struct sd *sd = (struct sd *) gspca_dev;
444 cam = &gspca_dev->cam;
447 sd->sensor = id->driver_info;
448 if (sd->sensor == SENSOR_PAC7302) {
449 PDEBUG(D_CONF, "Find Sensor PAC7302");
450 reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302);
452 cam->cam_mode = &vga_mode[2]; /* only 640x480 */
455 PDEBUG(D_CONF, "Find Sensor PAC7311");
456 reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302);
458 cam->cam_mode = vga_mode;
459 cam->nmodes = ARRAY_SIZE(vga_mode);
462 sd->brightness = BRIGHTNESS_DEF;
463 sd->contrast = CONTRAST_DEF;
464 sd->colors = COLOR_DEF;
465 sd->autogain = AUTOGAIN_DEF;
466 sd->hflip = HFLIP_DEF;
467 sd->vflip = VFLIP_DEF;
474 static void setbrightcont(struct gspca_dev *gspca_dev)
476 struct sd *sd = (struct sd *) gspca_dev;
478 static const __u8 max[10] =
479 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
481 static const __u8 delta[10] =
482 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
485 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
486 for (i = 0; i < 10; i++) {
488 v += (sd->brightness - BRIGHTNESS_MAX)
489 * 150 / BRIGHTNESS_MAX; /* 200 ? */
490 v -= delta[i] * sd->contrast / CONTRAST_MAX;
495 reg_w(gspca_dev, 0xa2 + i, v);
497 reg_w(gspca_dev, 0xdc, 0x01);
500 static void setbrightness(struct gspca_dev *gspca_dev)
502 struct sd *sd = (struct sd *) gspca_dev;
505 if (sd->sensor == SENSOR_PAC7302) {
506 setbrightcont(gspca_dev);
510 brightness = BRIGHTNESS_MAX - sd->brightness;
511 reg_w(gspca_dev, 0xff, 0x04);
512 reg_w(gspca_dev, 0x0e, 0x00);
513 reg_w(gspca_dev, 0x0f, brightness);
514 /* load registers to sensor (Bit 0, auto clear) */
515 reg_w(gspca_dev, 0x11, 0x01);
516 PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
519 static void setcontrast(struct gspca_dev *gspca_dev)
521 struct sd *sd = (struct sd *) gspca_dev;
523 if (sd->sensor == SENSOR_PAC7302) {
524 setbrightcont(gspca_dev);
527 reg_w(gspca_dev, 0xff, 0x01);
528 reg_w(gspca_dev, 0x10, sd->contrast);
529 /* load registers to sensor (Bit 0, auto clear) */
530 reg_w(gspca_dev, 0x11, 0x01);
533 static void setcolors(struct gspca_dev *gspca_dev)
535 struct sd *sd = (struct sd *) gspca_dev;
537 if (sd->sensor == SENSOR_PAC7302) {
539 static const int a[9] =
540 {217, -212, 0, -101, 170, -67, -38, -315, 355};
541 static const int b[9] =
542 {19, 106, 0, 19, 106, 1, 19, 106, 1};
544 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
545 reg_w(gspca_dev, 0x11, 0x01);
546 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
547 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
548 for (i = 0; i < 9; i++) {
549 v = a[i] * sd->colors / COLOR_MAX + b[i];
550 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
551 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
553 reg_w(gspca_dev, 0xdc, 0x01);
556 reg_w(gspca_dev, 0xff, 0x01);
557 reg_w(gspca_dev, 0x80, sd->colors);
558 /* load registers to sensor (Bit 0, auto clear) */
559 reg_w(gspca_dev, 0x11, 0x01);
560 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
563 static void setautogain(struct gspca_dev *gspca_dev)
565 struct sd *sd = (struct sd *) gspca_dev;
569 sd->ag_cnt = AG_CNT_START;
575 /* this function is used by pac7302 only */
576 static void sethvflip(struct gspca_dev *gspca_dev)
578 struct sd *sd = (struct sd *) gspca_dev;
581 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
582 data = (sd->hflip ? 0x00 : 0x08)
583 | (sd->vflip ? 0x04 : 0x00);
584 reg_w(gspca_dev, 0x21, data);
585 reg_w(gspca_dev, 0x11, 0x01);
588 /* this function is called at open time */
589 static int sd_open(struct gspca_dev *gspca_dev)
591 reg_w(gspca_dev, 0x78, 0x44); /* Turn on LED */
595 static void sd_start(struct gspca_dev *gspca_dev)
597 struct sd *sd = (struct sd *) gspca_dev;
601 if (sd->sensor == SENSOR_PAC7302)
602 reg_w_var(gspca_dev, start_7302);
604 reg_w_var(gspca_dev, start_7311);
606 setcontrast(gspca_dev);
607 setbrightness(gspca_dev);
608 setcolors(gspca_dev);
609 setautogain(gspca_dev);
611 /* set correct resolution */
612 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
613 case 2: /* 160x120 pac7311 */
614 reg_w(gspca_dev, 0xff, 0x04);
615 reg_w(gspca_dev, 0x02, 0x03);
616 reg_w(gspca_dev, 0xff, 0x01);
617 reg_w(gspca_dev, 0x08, 0x09);
618 reg_w(gspca_dev, 0x17, 0x20);
619 reg_w(gspca_dev, 0x1b, 0x00);
620 reg_w(gspca_dev, 0x87, 0x10);
622 case 1: /* 320x240 pac7311 */
623 reg_w(gspca_dev, 0xff, 0x04);
624 reg_w(gspca_dev, 0x02, 0x07);
625 reg_w(gspca_dev, 0xff, 0x01);
626 reg_w(gspca_dev, 0x08, 0x09);
627 reg_w(gspca_dev, 0x17, 0x30);
628 reg_w(gspca_dev, 0x87, 0x11);
630 case 0: /* 640x480 */
631 if (sd->sensor == SENSOR_PAC7302)
633 reg_w(gspca_dev, 0xff, 0x04);
634 reg_w(gspca_dev, 0x02, 0x07);
635 reg_w(gspca_dev, 0xff, 0x01);
636 reg_w(gspca_dev, 0x08, 0x08);
637 reg_w(gspca_dev, 0x17, 0x00);
638 reg_w(gspca_dev, 0x87, 0x12);
643 reg_w(gspca_dev, 0xff, 0x01);
644 if (sd->sensor == SENSOR_PAC7302) {
645 sethvflip(gspca_dev);
646 reg_w(gspca_dev, 0x78, 0x01);
647 reg_w(gspca_dev, 0xff, 0x01);
648 reg_w(gspca_dev, 0x78, 0x01);
650 reg_w(gspca_dev, 0x78, 0x44);
651 reg_w(gspca_dev, 0x78, 0x45);
655 static void sd_stopN(struct gspca_dev *gspca_dev)
657 struct sd *sd = (struct sd *) gspca_dev;
659 if (sd->sensor == SENSOR_PAC7302) {
660 reg_w(gspca_dev, 0x78, 0x00);
661 reg_w(gspca_dev, 0x78, 0x00);
664 reg_w(gspca_dev, 0xff, 0x04);
665 reg_w(gspca_dev, 0x27, 0x80);
666 reg_w(gspca_dev, 0x28, 0xca);
667 reg_w(gspca_dev, 0x29, 0x53);
668 reg_w(gspca_dev, 0x2a, 0x0e);
669 reg_w(gspca_dev, 0xff, 0x01);
670 reg_w(gspca_dev, 0x3e, 0x20);
671 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
672 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
673 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
676 static void sd_stop0(struct gspca_dev *gspca_dev)
678 struct sd *sd = (struct sd *) gspca_dev;
680 if (sd->sensor == SENSOR_PAC7302) {
681 reg_w(gspca_dev, 0xff, 0x01);
682 reg_w(gspca_dev, 0x78, 0x40);
686 /* this function is called at close time */
687 static void sd_close(struct gspca_dev *gspca_dev)
691 static void do_autogain(struct gspca_dev *gspca_dev)
693 struct sd *sd = (struct sd *) gspca_dev;
700 if (!atomic_read(&sd->do_gain))
702 atomic_set(&sd->do_gain, 0);
704 luma = atomic_read(&sd->avg_lum);
705 Gbright = reg_r(gspca_dev, 0x02);
706 PDEBUG(D_FRAM, "luma mean %d", luma);
707 if (luma < luma_mean - luma_delta ||
708 luma > luma_mean + luma_delta) {
709 Gbright += (luma_mean - luma) >> spring;
712 else if (Gbright < 4)
714 PDEBUG(D_FRAM, "gbright %d", Gbright);
715 if (sd->sensor == SENSOR_PAC7302) {
716 reg_w(gspca_dev, 0xff, 0x03);
717 reg_w(gspca_dev, 0x10, Gbright);
718 /* load registers to sensor (Bit 0, auto clear) */
719 reg_w(gspca_dev, 0x11, 0x01);
721 reg_w(gspca_dev, 0xff, 0x04);
722 reg_w(gspca_dev, 0x0f, Gbright);
723 /* load registers to sensor (Bit 0, auto clear) */
724 reg_w(gspca_dev, 0x11, 0x01);
729 /* this function is run at interrupt level */
730 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
731 struct gspca_frame *frame, /* target */
732 __u8 *data, /* isoc packet */
733 int len) /* iso packet length */
735 struct sd *sd = (struct sd *) gspca_dev;
738 #define INTER_FRAME 0x53 /* eof + inter frame + sof */
739 #define LUM_OFFSET 0x1e /* reverse offset / start of frame */
742 * inside a frame, there may be:
743 * escaped ff ('ff 00')
744 * sequences'ff ff ff xx' to remove
745 * end of frame ('ff d9')
746 * at the end of frame, there are:
749 * one byte luminosity
751 * ff ff 00 ff 96 62 44 start of frame
754 if (sd->tosof != 0) { /* if outside a frame */
756 /* get the luminosity and go to the start of frame */
759 if (sd->tosof > LUM_OFFSET)
760 sd->lum_sum += data[-LUM_OFFSET];
762 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
765 for (i = 0; i < len; i++) {
768 switch (data[i + 1]) {
769 case 0xd9: /* 'ff d9' end of frame */
770 frame = gspca_frame_add(gspca_dev,
773 data += i + INTER_FRAME;
774 len -= i + INTER_FRAME;
776 if (len > -LUM_OFFSET)
777 sd->lum_sum += data[-LUM_OFFSET];
782 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
786 gspca_frame_add(gspca_dev, INTER_PACKET,
790 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
792 struct sd *sd = (struct sd *) gspca_dev;
794 sd->brightness = val;
795 if (gspca_dev->streaming)
796 setbrightness(gspca_dev);
800 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
802 struct sd *sd = (struct sd *) gspca_dev;
804 *val = sd->brightness;
808 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
810 struct sd *sd = (struct sd *) gspca_dev;
813 if (gspca_dev->streaming)
814 setcontrast(gspca_dev);
818 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
820 struct sd *sd = (struct sd *) gspca_dev;
826 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
828 struct sd *sd = (struct sd *) gspca_dev;
831 if (gspca_dev->streaming)
832 setcolors(gspca_dev);
836 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
838 struct sd *sd = (struct sd *) gspca_dev;
844 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
846 struct sd *sd = (struct sd *) gspca_dev;
849 if (gspca_dev->streaming)
850 setautogain(gspca_dev);
854 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
856 struct sd *sd = (struct sd *) gspca_dev;
862 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
864 struct sd *sd = (struct sd *) gspca_dev;
867 if (gspca_dev->streaming)
868 sethvflip(gspca_dev);
872 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
874 struct sd *sd = (struct sd *) gspca_dev;
880 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
882 struct sd *sd = (struct sd *) gspca_dev;
885 if (gspca_dev->streaming)
886 sethvflip(gspca_dev);
890 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
892 struct sd *sd = (struct sd *) gspca_dev;
898 /* sub-driver description */
899 static struct sd_desc sd_desc = {
902 .nctrls = ARRAY_SIZE(sd_ctrls),
909 .pkt_scan = sd_pkt_scan,
910 .dq_callback = do_autogain,
913 /* -- module initialisation -- */
914 static __devinitdata struct usb_device_id device_table[] = {
915 {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311},
916 {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311},
917 {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311},
918 {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311},
919 {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311},
920 {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311},
921 {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
924 MODULE_DEVICE_TABLE(usb, device_table);
926 /* -- device connect -- */
927 static int sd_probe(struct usb_interface *intf,
928 const struct usb_device_id *id)
930 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
934 static struct usb_driver sd_driver = {
936 .id_table = device_table,
938 .disconnect = gspca_disconnect,
941 /* -- module insert / remove -- */
942 static int __init sd_mod_init(void)
944 if (usb_register(&sd_driver) < 0)
946 PDEBUG(D_PROBE, "registered");
949 static void __exit sd_mod_exit(void)
951 usb_deregister(&sd_driver);
952 PDEBUG(D_PROBE, "deregistered");
955 module_init(sd_mod_init);
956 module_exit(sd_mod_exit);