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 /* Some documentation about various registers as determined by trial and error.
23 When the register addresses differ between the 7202 and the 7311 the 2
24 different addresses are written as 7302addr/7311addr, when one of the 2
25 addresses is a - sign that register description is not valid for the
31 -/0x08 Unknown compressor related, must always be 8 except when not
32 in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
33 -/0x1b Auto white balance related, bit 0 is AWB enable (inverted)
34 bits 345 seem to toggle per color gains on/off (inverted)
35 0x78 Global control, bit 6 controls the LED (inverted)
36 -/0x80 JPEG compression ratio ? Best not touched
41 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
42 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
43 -/0x0f Master gain 1-245, low value = high gain
44 0x10/- Master gain 0-31
45 -/0x10 Another gain 0-15, limited influence (1-2x gain I guess)
46 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
47 -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
48 completely disable the analog amplification block. Set to 0x68
49 for max gain, 0x14 for minimal gain.
52 #define MODULE_NAME "pac7311"
56 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
57 MODULE_DESCRIPTION("Pixart PAC7311");
58 MODULE_LICENSE("GPL");
60 /* specific webcam descriptor */
62 struct gspca_dev gspca_dev; /* !! must be the first item */
64 unsigned char brightness;
65 unsigned char contrast;
68 unsigned char exposure;
69 unsigned char autogain;
74 #define SENSOR_PAC7302 0
75 #define SENSOR_PAC7311 1
78 u8 autogain_ignore_frames;
83 /* V4L2 controls supported by the driver */
84 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
90 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
91 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
92 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
93 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
94 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
95 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
96 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
97 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
98 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
99 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
101 static struct ctrl sd_ctrls[] = {
102 /* This control is pac7302 only */
103 #define BRIGHTNESS_IDX 0
106 .id = V4L2_CID_BRIGHTNESS,
107 .type = V4L2_CTRL_TYPE_INTEGER,
108 .name = "Brightness",
110 #define BRIGHTNESS_MAX 0x20
111 .maximum = BRIGHTNESS_MAX,
113 #define BRIGHTNESS_DEF 0x10
114 .default_value = BRIGHTNESS_DEF,
116 .set = sd_setbrightness,
117 .get = sd_getbrightness,
119 /* This control is for both the 7302 and the 7311 */
122 .id = V4L2_CID_CONTRAST,
123 .type = V4L2_CTRL_TYPE_INTEGER,
126 #define CONTRAST_MAX 255
127 .maximum = CONTRAST_MAX,
129 #define CONTRAST_DEF 127
130 .default_value = CONTRAST_DEF,
132 .set = sd_setcontrast,
133 .get = sd_getcontrast,
135 /* This control is pac7302 only */
136 #define SATURATION_IDX 2
139 .id = V4L2_CID_SATURATION,
140 .type = V4L2_CTRL_TYPE_INTEGER,
141 .name = "Saturation",
143 #define COLOR_MAX 255
144 .maximum = COLOR_MAX,
146 #define COLOR_DEF 127
147 .default_value = COLOR_DEF,
152 /* All controls below are for both the 7302 and the 7311 */
156 .type = V4L2_CTRL_TYPE_INTEGER,
163 #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
164 .default_value = GAIN_DEF,
171 .id = V4L2_CID_EXPOSURE,
172 .type = V4L2_CTRL_TYPE_INTEGER,
175 #define EXPOSURE_MAX 255
176 .maximum = EXPOSURE_MAX,
178 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
179 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
180 .default_value = EXPOSURE_DEF,
182 .set = sd_setexposure,
183 .get = sd_getexposure,
187 .id = V4L2_CID_AUTOGAIN,
188 .type = V4L2_CTRL_TYPE_BOOLEAN,
193 #define AUTOGAIN_DEF 1
194 .default_value = AUTOGAIN_DEF,
196 .set = sd_setautogain,
197 .get = sd_getautogain,
201 .id = V4L2_CID_HFLIP,
202 .type = V4L2_CTRL_TYPE_BOOLEAN,
208 .default_value = HFLIP_DEF,
215 .id = V4L2_CID_VFLIP,
216 .type = V4L2_CTRL_TYPE_BOOLEAN,
222 .default_value = VFLIP_DEF,
229 static const struct v4l2_pix_format vga_mode[] = {
230 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
232 .sizeimage = 160 * 120 * 3 / 8 + 590,
233 .colorspace = V4L2_COLORSPACE_JPEG,
235 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
237 .sizeimage = 320 * 240 * 3 / 8 + 590,
238 .colorspace = V4L2_COLORSPACE_JPEG,
240 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
242 .sizeimage = 640 * 480 * 3 / 8 + 590,
243 .colorspace = V4L2_COLORSPACE_JPEG,
247 #define LOAD_PAGE3 255
248 #define LOAD_PAGE4 254
249 #define END_OF_SEQUENCE 0
252 static const __u8 init_7302[] = {
254 0xff, 0x01, /* page 1 */
255 0x78, 0x00, /* deactivate */
257 0x78, 0x40, /* led off */
259 static const __u8 start_7302[] = {
260 /* index, len, [value]* */
261 0xff, 1, 0x00, /* page 0 */
262 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
263 0x00, 0x00, 0x00, 0x00,
264 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
265 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
266 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
270 0x3a, 3, 0x14, 0xff, 0x5a,
271 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
274 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
276 0x6e, 3, 0x08, 0x06, 0x00,
277 0x72, 3, 0x00, 0xff, 0x00,
278 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
279 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
280 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
281 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
286 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
288 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
291 0xff, 1, 0x01, /* page 1 */
292 0x12, 3, 0x02, 0x00, 0x01,
294 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
296 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
298 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
299 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
300 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
303 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
304 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
306 0xff, 1, 0x02, /* page 2 */
308 0xff, 1, 0x03, /* page 3 */
309 0, LOAD_PAGE3, /* load the page 3 */
311 0xff, 1, 0x02, /* page 2 */
313 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
315 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
316 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
318 0xff, 1, 0x01, /* page 1 */
320 0, END_OF_SEQUENCE /* end of sequence */
324 /* page 3 - the value SKIP says skip the index - see reg_w_page() */
325 static const __u8 page3_7302[] = {
326 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
327 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
328 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
330 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
331 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
332 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
333 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
335 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
336 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
340 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
341 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
342 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
349 static const __u8 init_7311[] = {
350 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
351 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
352 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
362 static const __u8 start_7311[] = {
363 /* index, len, [value]* */
364 0xff, 1, 0x01, /* page 1 */
365 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
366 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
367 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
368 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
372 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
373 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
374 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
375 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
377 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
378 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
379 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
381 0x96, 3, 0x01, 0x08, 0x04,
382 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
383 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
384 0x3f, 0x00, 0x0a, 0x01, 0x00,
385 0xff, 1, 0x04, /* page 4 */
386 0, LOAD_PAGE4, /* load the page 4 */
388 0, END_OF_SEQUENCE /* end of sequence */
391 /* page 4 - the value SKIP says skip the index - see reg_w_page() */
392 static const __u8 page4_7311[] = {
393 SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
394 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
395 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
396 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
397 SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
398 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
399 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
402 static void reg_w_buf(struct gspca_dev *gspca_dev,
404 const char *buffer, int len)
406 memcpy(gspca_dev->usb_buf, buffer, len);
407 usb_control_msg(gspca_dev->dev,
408 usb_sndctrlpipe(gspca_dev->dev, 0),
410 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
412 index, gspca_dev->usb_buf, len,
417 static void reg_w(struct gspca_dev *gspca_dev,
421 gspca_dev->usb_buf[0] = value;
422 usb_control_msg(gspca_dev->dev,
423 usb_sndctrlpipe(gspca_dev->dev, 0),
425 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
426 0, index, gspca_dev->usb_buf, 1,
430 static void reg_w_seq(struct gspca_dev *gspca_dev,
431 const __u8 *seq, int len)
434 reg_w(gspca_dev, seq[0], seq[1]);
439 /* load the beginning of a page */
440 static void reg_w_page(struct gspca_dev *gspca_dev,
441 const __u8 *page, int len)
445 for (index = 0; index < len; index++) {
446 if (page[index] == SKIP) /* skip this index */
448 gspca_dev->usb_buf[0] = page[index];
449 usb_control_msg(gspca_dev->dev,
450 usb_sndctrlpipe(gspca_dev->dev, 0),
452 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
453 0, index, gspca_dev->usb_buf, 1,
458 /* output a variable sequence */
459 static void reg_w_var(struct gspca_dev *gspca_dev,
468 case END_OF_SEQUENCE:
471 reg_w_page(gspca_dev, page4_7311, sizeof page4_7311);
474 reg_w_page(gspca_dev, page3_7302, sizeof page3_7302);
477 if (len > USB_BUF_SZ) {
478 PDEBUG(D_ERR|D_STREAM,
479 "Incorrect variable sequence");
484 reg_w_buf(gspca_dev, index, seq, len);
488 reg_w_buf(gspca_dev, index, seq, 8);
498 /* this function is called at probe time */
499 static int sd_config(struct gspca_dev *gspca_dev,
500 const struct usb_device_id *id)
502 struct sd *sd = (struct sd *) gspca_dev;
505 cam = &gspca_dev->cam;
507 sd->sensor = id->driver_info;
508 if (sd->sensor == SENSOR_PAC7302) {
509 PDEBUG(D_CONF, "Find Sensor PAC7302");
510 cam->cam_mode = &vga_mode[2]; /* only 640x480 */
513 PDEBUG(D_CONF, "Find Sensor PAC7311");
514 cam->cam_mode = vga_mode;
515 cam->nmodes = ARRAY_SIZE(vga_mode);
516 gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX)
517 | (1 << SATURATION_IDX);
520 sd->brightness = BRIGHTNESS_DEF;
521 sd->contrast = CONTRAST_DEF;
522 sd->colors = COLOR_DEF;
524 sd->exposure = EXPOSURE_DEF;
525 sd->autogain = AUTOGAIN_DEF;
526 sd->hflip = HFLIP_DEF;
527 sd->vflip = VFLIP_DEF;
531 /* This function is used by pac7302 only */
532 static void setbrightcont(struct gspca_dev *gspca_dev)
534 struct sd *sd = (struct sd *) gspca_dev;
536 static const __u8 max[10] =
537 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
539 static const __u8 delta[10] =
540 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
543 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
544 for (i = 0; i < 10; i++) {
546 v += (sd->brightness - BRIGHTNESS_MAX)
547 * 150 / BRIGHTNESS_MAX; /* 200 ? */
548 v -= delta[i] * sd->contrast / CONTRAST_MAX;
553 reg_w(gspca_dev, 0xa2 + i, v);
555 reg_w(gspca_dev, 0xdc, 0x01);
558 /* This function is used by pac7311 only */
559 static void setcontrast(struct gspca_dev *gspca_dev)
561 struct sd *sd = (struct sd *) gspca_dev;
563 reg_w(gspca_dev, 0xff, 0x04);
564 reg_w(gspca_dev, 0x10, sd->contrast >> 4);
565 /* load registers to sensor (Bit 0, auto clear) */
566 reg_w(gspca_dev, 0x11, 0x01);
569 /* This function is used by pac7302 only */
570 static void setcolors(struct gspca_dev *gspca_dev)
572 struct sd *sd = (struct sd *) gspca_dev;
574 static const int a[9] =
575 {217, -212, 0, -101, 170, -67, -38, -315, 355};
576 static const int b[9] =
577 {19, 106, 0, 19, 106, 1, 19, 106, 1};
579 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
580 reg_w(gspca_dev, 0x11, 0x01);
581 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
582 for (i = 0; i < 9; i++) {
583 v = a[i] * sd->colors / COLOR_MAX + b[i];
584 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
585 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
587 reg_w(gspca_dev, 0xdc, 0x01);
588 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
591 static void setgain(struct gspca_dev *gspca_dev)
593 struct sd *sd = (struct sd *) gspca_dev;
595 if (sd->sensor == SENSOR_PAC7302) {
596 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
597 reg_w(gspca_dev, 0x10, sd->gain >> 3);
599 int gain = GAIN_MAX - sd->gain;
604 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
605 reg_w(gspca_dev, 0x0e, 0x00);
606 reg_w(gspca_dev, 0x0f, gain);
608 /* load registers to sensor (Bit 0, auto clear) */
609 reg_w(gspca_dev, 0x11, 0x01);
612 static void setexposure(struct gspca_dev *gspca_dev)
614 struct sd *sd = (struct sd *) gspca_dev;
617 /* register 2 of frame 3/4 contains the clock divider configuring the
618 no fps according to the formula: 60 / reg. sd->exposure is the
619 desired exposure time in ms. */
620 reg = 120 * sd->exposure / 1000;
626 if (sd->sensor == SENSOR_PAC7302) {
627 /* On the pac7302 reg2 MUST be a multiple of 3, so round it to
628 the nearest multiple of 3, except when between 6 and 12? */
629 if (reg < 6 || reg > 12)
630 reg = ((reg + 1) / 3) * 3;
631 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
632 reg_w(gspca_dev, 0x02, reg);
634 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
635 reg_w(gspca_dev, 0x02, reg);
636 /* Page 1 register 8 must always be 0x08 except when not in
637 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
638 reg_w(gspca_dev, 0xff, 0x01);
639 if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
641 reg_w(gspca_dev, 0x08, 0x09);
643 reg_w(gspca_dev, 0x08, 0x08);
645 /* load registers to sensor (Bit 0, auto clear) */
646 reg_w(gspca_dev, 0x11, 0x01);
649 static void sethvflip(struct gspca_dev *gspca_dev)
651 struct sd *sd = (struct sd *) gspca_dev;
654 if (sd->sensor == SENSOR_PAC7302) {
655 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
656 data = (sd->hflip ? 0x08 : 0x00)
657 | (sd->vflip ? 0x04 : 0x00);
659 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
660 data = (sd->hflip ? 0x04 : 0x00)
661 | (sd->vflip ? 0x08 : 0x00);
663 reg_w(gspca_dev, 0x21, data);
664 /* load registers to sensor (Bit 0, auto clear) */
665 reg_w(gspca_dev, 0x11, 0x01);
668 /* this function is called at probe and resume time */
669 static int sd_init(struct gspca_dev *gspca_dev)
671 struct sd *sd = (struct sd *) gspca_dev;
673 if (sd->sensor == SENSOR_PAC7302)
674 reg_w_seq(gspca_dev, init_7302, sizeof init_7302);
676 reg_w_seq(gspca_dev, init_7311, sizeof init_7311);
681 static int sd_start(struct gspca_dev *gspca_dev)
683 struct sd *sd = (struct sd *) gspca_dev;
687 if (sd->sensor == SENSOR_PAC7302) {
688 reg_w_var(gspca_dev, start_7302);
689 setbrightcont(gspca_dev);
690 setcolors(gspca_dev);
692 reg_w_var(gspca_dev, start_7311);
693 setcontrast(gspca_dev);
696 setexposure(gspca_dev);
697 sethvflip(gspca_dev);
699 /* set correct resolution */
700 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
701 case 2: /* 160x120 pac7311 */
702 reg_w(gspca_dev, 0xff, 0x01);
703 reg_w(gspca_dev, 0x17, 0x20);
704 reg_w(gspca_dev, 0x87, 0x10);
706 case 1: /* 320x240 pac7311 */
707 reg_w(gspca_dev, 0xff, 0x01);
708 reg_w(gspca_dev, 0x17, 0x30);
709 reg_w(gspca_dev, 0x87, 0x11);
711 case 0: /* 640x480 */
712 if (sd->sensor == SENSOR_PAC7302)
714 reg_w(gspca_dev, 0xff, 0x01);
715 reg_w(gspca_dev, 0x17, 0x00);
716 reg_w(gspca_dev, 0x87, 0x12);
721 sd->autogain_ignore_frames = 0;
722 atomic_set(&sd->avg_lum, -1);
725 reg_w(gspca_dev, 0xff, 0x01);
726 if (sd->sensor == SENSOR_PAC7302)
727 reg_w(gspca_dev, 0x78, 0x01);
729 reg_w(gspca_dev, 0x78, 0x05);
733 static void sd_stopN(struct gspca_dev *gspca_dev)
735 struct sd *sd = (struct sd *) gspca_dev;
737 if (sd->sensor == SENSOR_PAC7302) {
738 reg_w(gspca_dev, 0xff, 0x01);
739 reg_w(gspca_dev, 0x78, 0x00);
740 reg_w(gspca_dev, 0x78, 0x00);
743 reg_w(gspca_dev, 0xff, 0x04);
744 reg_w(gspca_dev, 0x27, 0x80);
745 reg_w(gspca_dev, 0x28, 0xca);
746 reg_w(gspca_dev, 0x29, 0x53);
747 reg_w(gspca_dev, 0x2a, 0x0e);
748 reg_w(gspca_dev, 0xff, 0x01);
749 reg_w(gspca_dev, 0x3e, 0x20);
750 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
751 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
752 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
755 /* called on streamoff with alt 0 and on disconnect */
756 static void sd_stop0(struct gspca_dev *gspca_dev)
758 struct sd *sd = (struct sd *) gspca_dev;
760 if (!gspca_dev->present)
762 if (sd->sensor == SENSOR_PAC7302) {
763 reg_w(gspca_dev, 0xff, 0x01);
764 reg_w(gspca_dev, 0x78, 0x40);
768 /* Include pac common sof detection functions */
769 #include "pac_common.h"
771 static void do_autogain(struct gspca_dev *gspca_dev)
773 struct sd *sd = (struct sd *) gspca_dev;
774 int avg_lum = atomic_read(&sd->avg_lum);
775 int desired_lum, deadzone;
780 if (sd->sensor == SENSOR_PAC7302) {
781 desired_lum = 270 + sd->brightness * 4;
782 /* Hack hack, with the 7202 the first exposure step is
783 pretty large, so if we're about to make the first
784 exposure increase make the deadzone large to avoid
786 if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
787 sd->exposure > EXPOSURE_DEF &&
797 if (sd->autogain_ignore_frames > 0)
798 sd->autogain_ignore_frames--;
799 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
800 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
801 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
804 /* JPEG header, part 1 */
805 static const unsigned char pac_jpeg_header1[] = {
806 0xff, 0xd8, /* SOI: Start of Image */
808 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
809 0x00, 0x11, /* length = 17 bytes (including this length field) */
810 0x08 /* Precision: 8 */
811 /* 2 bytes is placed here: number of image lines */
812 /* 2 bytes is placed here: samples per line */
815 /* JPEG header, continued */
816 static const unsigned char pac_jpeg_header2[] = {
817 0x03, /* Number of image components: 3 */
818 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
819 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
820 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
822 0xff, 0xda, /* SOS: Start Of Scan */
823 0x00, 0x0c, /* length = 12 bytes (including this length field) */
824 0x03, /* number of components: 3 */
825 0x01, 0x00, /* selector 1, table 0x00 */
826 0x02, 0x11, /* selector 2, table 0x11 */
827 0x03, 0x11, /* selector 3, table 0x11 */
828 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
829 0x00 /* Successive approximation: 0 */
832 static void pac_start_frame(struct gspca_dev *gspca_dev,
833 struct gspca_frame *frame,
834 __u16 lines, __u16 samples_per_line)
836 unsigned char tmpbuf[4];
838 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
839 pac_jpeg_header1, sizeof(pac_jpeg_header1));
841 tmpbuf[0] = lines >> 8;
842 tmpbuf[1] = lines & 0xff;
843 tmpbuf[2] = samples_per_line >> 8;
844 tmpbuf[3] = samples_per_line & 0xff;
846 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
847 tmpbuf, sizeof(tmpbuf));
848 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
849 pac_jpeg_header2, sizeof(pac_jpeg_header2));
852 /* this function is run at interrupt level */
853 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
854 struct gspca_frame *frame, /* target */
855 __u8 *data, /* isoc packet */
856 int len) /* iso packet length */
858 struct sd *sd = (struct sd *) gspca_dev;
861 sof = pac_find_sof(&sd->sof_read, data, len);
863 int n, lum_offset, footer_length;
865 if (sd->sensor == SENSOR_PAC7302) {
866 /* 6 bytes after the FF D9 EOF marker a number of lumination
867 bytes are send corresponding to different parts of the
868 image, the 14th and 15th byte after the EOF seem to
869 correspond to the center of the image */
870 lum_offset = 61 + sizeof pac_sof_marker;
873 lum_offset = 24 + sizeof pac_sof_marker;
877 /* Finish decoding current frame */
878 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
880 frame->data_end += n;
883 frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
885 if (gspca_dev->last_packet_type != DISCARD_PACKET &&
886 frame->data_end[-2] == 0xff &&
887 frame->data_end[-1] == 0xd9)
888 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
895 /* Get average lumination */
896 if (gspca_dev->last_packet_type == LAST_PACKET &&
898 atomic_set(&sd->avg_lum, data[-lum_offset] +
899 data[-lum_offset + 1]);
901 atomic_set(&sd->avg_lum, -1);
903 /* Start the new frame with the jpeg header */
904 if (sd->sensor == SENSOR_PAC7302) {
905 /* The PAC7302 has the image rotated 90 degrees */
906 pac_start_frame(gspca_dev, frame,
907 gspca_dev->width, gspca_dev->height);
909 pac_start_frame(gspca_dev, frame,
910 gspca_dev->height, gspca_dev->width);
913 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
916 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
918 struct sd *sd = (struct sd *) gspca_dev;
920 sd->brightness = val;
921 if (gspca_dev->streaming)
922 setbrightcont(gspca_dev);
926 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
928 struct sd *sd = (struct sd *) gspca_dev;
930 *val = sd->brightness;
934 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
936 struct sd *sd = (struct sd *) gspca_dev;
939 if (gspca_dev->streaming) {
940 if (sd->sensor == SENSOR_PAC7302)
941 setbrightcont(gspca_dev);
943 setcontrast(gspca_dev);
948 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
950 struct sd *sd = (struct sd *) gspca_dev;
956 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
958 struct sd *sd = (struct sd *) gspca_dev;
961 if (gspca_dev->streaming)
962 setcolors(gspca_dev);
966 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
968 struct sd *sd = (struct sd *) gspca_dev;
974 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
976 struct sd *sd = (struct sd *) gspca_dev;
979 if (gspca_dev->streaming)
984 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
986 struct sd *sd = (struct sd *) gspca_dev;
992 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
994 struct sd *sd = (struct sd *) gspca_dev;
997 if (gspca_dev->streaming)
998 setexposure(gspca_dev);
1002 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1004 struct sd *sd = (struct sd *) gspca_dev;
1006 *val = sd->exposure;
1010 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1012 struct sd *sd = (struct sd *) gspca_dev;
1015 /* when switching to autogain set defaults to make sure
1016 we are on a valid point of the autogain gain /
1017 exposure knee graph, and give this change time to
1018 take effect before doing autogain. */
1020 sd->exposure = EXPOSURE_DEF;
1021 sd->gain = GAIN_DEF;
1022 if (gspca_dev->streaming) {
1023 sd->autogain_ignore_frames =
1024 PAC_AUTOGAIN_IGNORE_FRAMES;
1025 setexposure(gspca_dev);
1033 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1035 struct sd *sd = (struct sd *) gspca_dev;
1037 *val = sd->autogain;
1041 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
1043 struct sd *sd = (struct sd *) gspca_dev;
1046 if (gspca_dev->streaming)
1047 sethvflip(gspca_dev);
1051 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
1053 struct sd *sd = (struct sd *) gspca_dev;
1059 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1061 struct sd *sd = (struct sd *) gspca_dev;
1064 if (gspca_dev->streaming)
1065 sethvflip(gspca_dev);
1069 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1071 struct sd *sd = (struct sd *) gspca_dev;
1077 /* sub-driver description */
1078 static struct sd_desc sd_desc = {
1079 .name = MODULE_NAME,
1081 .nctrls = ARRAY_SIZE(sd_ctrls),
1082 .config = sd_config,
1087 .pkt_scan = sd_pkt_scan,
1088 .dq_callback = do_autogain,
1091 /* -- module initialisation -- */
1092 static __devinitdata struct usb_device_id device_table[] = {
1093 {USB_DEVICE(0x06f8, 0x3009), .driver_info = SENSOR_PAC7302},
1094 {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311},
1095 {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311},
1096 {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311},
1097 {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311},
1098 {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311},
1099 {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311},
1100 {USB_DEVICE(0x093a, 0x2620), .driver_info = SENSOR_PAC7302},
1101 {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
1102 {USB_DEVICE(0x093a, 0x2622), .driver_info = SENSOR_PAC7302},
1103 {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},
1104 {USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302},
1105 {USB_DEVICE(0x093a, 0x2628), .driver_info = SENSOR_PAC7302},
1106 {USB_DEVICE(0x093a, 0x2629), .driver_info = SENSOR_PAC7302},
1107 {USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302},
1108 {USB_DEVICE(0x093a, 0x262c), .driver_info = SENSOR_PAC7302},
1111 MODULE_DEVICE_TABLE(usb, device_table);
1113 /* -- device connect -- */
1114 static int sd_probe(struct usb_interface *intf,
1115 const struct usb_device_id *id)
1117 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1121 static struct usb_driver sd_driver = {
1122 .name = MODULE_NAME,
1123 .id_table = device_table,
1125 .disconnect = gspca_disconnect,
1127 .suspend = gspca_suspend,
1128 .resume = gspca_resume,
1132 /* -- module insert / remove -- */
1133 static int __init sd_mod_init(void)
1136 ret = usb_register(&sd_driver);
1139 PDEBUG(D_PROBE, "registered");
1142 static void __exit sd_mod_exit(void)
1144 usb_deregister(&sd_driver);
1145 PDEBUG(D_PROBE, "deregistered");
1148 module_init(sd_mod_init);
1149 module_exit(sd_mod_exit);