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 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,
248 static const __u8 probe_7302[] = {
250 0xff, 0x01, /* page 1 */
251 0x78, 0x00, /* deactivate */
253 0x78, 0x40, /* led off */
255 static const __u8 start_7302[] = {
256 /* index, len, [value]* */
257 0xff, 1, 0x00, /* page 0 */
258 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
259 0x00, 0x00, 0x00, 0x00,
260 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
261 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
262 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
266 0x3a, 3, 0x14, 0xff, 0x5a,
267 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
270 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
272 0x6e, 3, 0x08, 0x06, 0x00,
273 0x72, 3, 0x00, 0xff, 0x00,
274 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
275 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
276 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
277 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
282 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
284 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
287 0xff, 1, 0x01, /* page 1 */
288 0x12, 3, 0x02, 0x00, 0x01,
290 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
292 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
294 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
295 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
296 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
299 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
300 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
302 0xff, 1, 0x02, /* page 2 */
304 0xff, 1, 0x03, /* page 3 */
305 0x00, 255, /* load the page 3 */
307 0xff, 1, 0x02, /* page 2 */
309 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
311 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
312 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
314 0xff, 1, 0x01, /* page 1 */
316 0, 0 /* end of sequence */
319 /* page 3 - the value 0xaa says skip the index - see reg_w_page() */
320 static const __u8 page3_7302[] = {
321 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
322 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
323 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
325 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
326 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
327 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
328 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
330 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
331 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
335 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
336 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
337 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
344 static const __u8 probe_7311[] = {
345 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
346 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
347 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
357 static const __u8 start_7311[] = {
358 /* index, len, [value]* */
359 0xff, 1, 0x01, /* page 1 */
360 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
361 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
362 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
363 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
367 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
368 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
369 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
370 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
372 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
373 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
374 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
376 0x96, 3, 0x01, 0x08, 0x04,
377 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
378 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
379 0x3f, 0x00, 0x0a, 0x01, 0x00,
380 0xff, 1, 0x04, /* page 4 */
381 0x00, 254, /* load the page 4 */
383 0, 0 /* end of sequence */
386 /* page 4 - the value 0xaa says skip the index - see reg_w_page() */
387 static const __u8 page4_7311[] = {
388 0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
389 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62,
390 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa,
392 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x68,
393 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
394 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
397 static void reg_w_buf(struct gspca_dev *gspca_dev,
399 const char *buffer, int len)
401 memcpy(gspca_dev->usb_buf, buffer, len);
402 usb_control_msg(gspca_dev->dev,
403 usb_sndctrlpipe(gspca_dev->dev, 0),
405 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
407 index, gspca_dev->usb_buf, len,
412 static void reg_w(struct gspca_dev *gspca_dev,
416 gspca_dev->usb_buf[0] = value;
417 usb_control_msg(gspca_dev->dev,
418 usb_sndctrlpipe(gspca_dev->dev, 0),
420 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
421 0, index, gspca_dev->usb_buf, 1,
425 static void reg_w_seq(struct gspca_dev *gspca_dev,
426 const __u8 *seq, int len)
429 reg_w(gspca_dev, seq[0], seq[1]);
434 /* load the beginning of a page */
435 static void reg_w_page(struct gspca_dev *gspca_dev,
436 const __u8 *page, int len)
440 for (index = 0; index < len; index++) {
441 if (page[index] == 0xaa) /* skip this index */
443 gspca_dev->usb_buf[0] = page[index];
444 usb_control_msg(gspca_dev->dev,
445 usb_sndctrlpipe(gspca_dev->dev, 0),
447 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
448 0, index, gspca_dev->usb_buf, 1,
453 /* output a variable sequence */
454 static void reg_w_var(struct gspca_dev *gspca_dev,
466 reg_w_page(gspca_dev, page4_7311, sizeof page4_7311);
469 reg_w_page(gspca_dev, page3_7302, sizeof page3_7302);
473 PDEBUG(D_ERR|D_STREAM,
474 "Incorrect variable sequence");
479 reg_w_buf(gspca_dev, index, seq, len);
483 reg_w_buf(gspca_dev, index, seq, 8);
493 /* this function is called at probe time */
494 static int sd_config(struct gspca_dev *gspca_dev,
495 const struct usb_device_id *id)
497 struct sd *sd = (struct sd *) gspca_dev;
500 cam = &gspca_dev->cam;
503 sd->sensor = id->driver_info;
504 if (sd->sensor == SENSOR_PAC7302) {
505 PDEBUG(D_CONF, "Find Sensor PAC7302");
506 reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302);
508 cam->cam_mode = &vga_mode[2]; /* only 640x480 */
511 PDEBUG(D_CONF, "Find Sensor PAC7311");
512 reg_w_seq(gspca_dev, probe_7311, sizeof probe_7311);
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 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
583 for (i = 0; i < 9; i++) {
584 v = a[i] * sd->colors / COLOR_MAX + b[i];
585 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
586 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
588 reg_w(gspca_dev, 0xdc, 0x01);
589 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
592 static void setgain(struct gspca_dev *gspca_dev)
594 struct sd *sd = (struct sd *) gspca_dev;
596 if (sd->sensor == SENSOR_PAC7302) {
597 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
598 reg_w(gspca_dev, 0x10, sd->gain >> 3);
600 int gain = GAIN_MAX - sd->gain;
605 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
606 reg_w(gspca_dev, 0x0e, 0x00);
607 reg_w(gspca_dev, 0x0f, gain);
609 /* load registers to sensor (Bit 0, auto clear) */
610 reg_w(gspca_dev, 0x11, 0x01);
613 static void setexposure(struct gspca_dev *gspca_dev)
615 struct sd *sd = (struct sd *) gspca_dev;
618 /* register 2 of frame 3/4 contains the clock divider configuring the
619 no fps according to the formula: 60 / reg. sd->exposure is the
620 desired exposure time in ms. */
621 reg = 120 * sd->exposure / 1000;
627 if (sd->sensor == SENSOR_PAC7302) {
628 /* On the pac7302 reg2 MUST be a multiple of 3, so round it to
629 the nearest multiple of 3, except when between 6 and 12? */
630 if (reg < 6 || reg > 12)
631 reg = ((reg + 1) / 3) * 3;
632 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
633 reg_w(gspca_dev, 0x02, reg);
635 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
636 reg_w(gspca_dev, 0x02, reg);
637 /* Page 1 register 8 must always be 0x08 except when not in
638 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
639 reg_w(gspca_dev, 0xff, 0x01);
640 if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
642 reg_w(gspca_dev, 0x08, 0x09);
644 reg_w(gspca_dev, 0x08, 0x08);
646 /* load registers to sensor (Bit 0, auto clear) */
647 reg_w(gspca_dev, 0x11, 0x01);
650 static void sethvflip(struct gspca_dev *gspca_dev)
652 struct sd *sd = (struct sd *) gspca_dev;
655 if (sd->sensor == SENSOR_PAC7302) {
656 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
657 data = (sd->hflip ? 0x08 : 0x00)
658 | (sd->vflip ? 0x04 : 0x00);
660 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
661 data = (sd->hflip ? 0x04 : 0x00)
662 | (sd->vflip ? 0x08 : 0x00);
664 reg_w(gspca_dev, 0x21, data);
665 /* load registers to sensor (Bit 0, auto clear) */
666 reg_w(gspca_dev, 0x11, 0x01);
669 /* this function is called at probe and resume time */
670 static int sd_init(struct gspca_dev *gspca_dev)
675 static void sd_start(struct gspca_dev *gspca_dev)
677 struct sd *sd = (struct sd *) gspca_dev;
681 if (sd->sensor == SENSOR_PAC7302) {
682 reg_w_var(gspca_dev, start_7302);
683 setbrightcont(gspca_dev);
684 setcolors(gspca_dev);
686 reg_w_var(gspca_dev, start_7311);
687 setcontrast(gspca_dev);
690 setexposure(gspca_dev);
691 sethvflip(gspca_dev);
693 /* set correct resolution */
694 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
695 case 2: /* 160x120 pac7311 */
696 reg_w(gspca_dev, 0xff, 0x01);
697 reg_w(gspca_dev, 0x17, 0x20);
698 reg_w(gspca_dev, 0x87, 0x10);
700 case 1: /* 320x240 pac7311 */
701 reg_w(gspca_dev, 0xff, 0x01);
702 reg_w(gspca_dev, 0x17, 0x30);
703 reg_w(gspca_dev, 0x87, 0x11);
705 case 0: /* 640x480 */
706 if (sd->sensor == SENSOR_PAC7302)
708 reg_w(gspca_dev, 0xff, 0x01);
709 reg_w(gspca_dev, 0x17, 0x00);
710 reg_w(gspca_dev, 0x87, 0x12);
715 sd->autogain_ignore_frames = 0;
716 atomic_set(&sd->avg_lum, -1);
719 reg_w(gspca_dev, 0xff, 0x01);
720 if (sd->sensor == SENSOR_PAC7302)
721 reg_w(gspca_dev, 0x78, 0x01);
723 reg_w(gspca_dev, 0x78, 0x05);
726 static void sd_stopN(struct gspca_dev *gspca_dev)
728 struct sd *sd = (struct sd *) gspca_dev;
730 if (sd->sensor == SENSOR_PAC7302) {
731 reg_w(gspca_dev, 0xff, 0x01);
732 reg_w(gspca_dev, 0x78, 0x00);
733 reg_w(gspca_dev, 0x78, 0x00);
736 reg_w(gspca_dev, 0xff, 0x04);
737 reg_w(gspca_dev, 0x27, 0x80);
738 reg_w(gspca_dev, 0x28, 0xca);
739 reg_w(gspca_dev, 0x29, 0x53);
740 reg_w(gspca_dev, 0x2a, 0x0e);
741 reg_w(gspca_dev, 0xff, 0x01);
742 reg_w(gspca_dev, 0x3e, 0x20);
743 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
744 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
745 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
748 static void sd_stop0(struct gspca_dev *gspca_dev)
750 struct sd *sd = (struct sd *) gspca_dev;
752 if (sd->sensor == SENSOR_PAC7302) {
753 reg_w(gspca_dev, 0xff, 0x01);
754 reg_w(gspca_dev, 0x78, 0x40);
758 /* Include pac common sof detection functions */
759 #include "pac_common.h"
761 static void do_autogain(struct gspca_dev *gspca_dev)
763 struct sd *sd = (struct sd *) gspca_dev;
764 int avg_lum = atomic_read(&sd->avg_lum);
765 int desired_lum, deadzone;
770 if (sd->sensor == SENSOR_PAC7302) {
771 desired_lum = 270 + sd->brightness * 4;
772 /* Hack hack, with the 7202 the first exposure step is
773 pretty large, so if we're about to make the first
774 exposure increase make the deadzone large to avoid
776 if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
777 sd->exposure > EXPOSURE_DEF &&
787 if (sd->autogain_ignore_frames > 0)
788 sd->autogain_ignore_frames--;
789 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
790 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
791 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
794 static const unsigned char pac7311_jpeg_header1[] = {
795 0xff, 0xd8, 0xff, 0xc0, 0x00, 0x11, 0x08
798 static const unsigned char pac7311_jpeg_header2[] = {
799 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda,
800 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
803 /* this function is run at interrupt level */
804 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
805 struct gspca_frame *frame, /* target */
806 __u8 *data, /* isoc packet */
807 int len) /* iso packet length */
809 struct sd *sd = (struct sd *) gspca_dev;
812 sof = pac_find_sof(gspca_dev, data, len);
814 unsigned char tmpbuf[4];
815 int n, lum_offset, footer_length;
817 if (sd->sensor == SENSOR_PAC7302) {
818 /* 6 bytes after the FF D9 EOF marker a number of lumination
819 bytes are send corresponding to different parts of the
820 image, the 14th and 15th byte after the EOF seem to
821 correspond to the center of the image */
822 lum_offset = 61 + sizeof pac_sof_marker;
825 lum_offset = 24 + sizeof pac_sof_marker;
829 /* Finish decoding current frame */
830 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
832 frame->data_end += n;
835 frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
837 if (gspca_dev->last_packet_type != DISCARD_PACKET &&
838 frame->data_end[-2] == 0xff &&
839 frame->data_end[-1] == 0xd9)
840 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
847 /* Get average lumination */
848 if (gspca_dev->last_packet_type == LAST_PACKET &&
850 atomic_set(&sd->avg_lum, data[-lum_offset] +
851 data[-lum_offset + 1]);
853 atomic_set(&sd->avg_lum, -1);
855 /* Start the new frame with the jpeg header */
856 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
857 pac7311_jpeg_header1, sizeof(pac7311_jpeg_header1));
858 if (sd->sensor == SENSOR_PAC7302) {
859 /* The PAC7302 has the image rotated 90 degrees */
860 tmpbuf[0] = gspca_dev->width >> 8;
861 tmpbuf[1] = gspca_dev->width & 0xff;
862 tmpbuf[2] = gspca_dev->height >> 8;
863 tmpbuf[3] = gspca_dev->height & 0xff;
865 tmpbuf[0] = gspca_dev->height >> 8;
866 tmpbuf[1] = gspca_dev->height & 0xff;
867 tmpbuf[2] = gspca_dev->width >> 8;
868 tmpbuf[3] = gspca_dev->width & 0xff;
870 gspca_frame_add(gspca_dev, INTER_PACKET, frame, tmpbuf, 4);
871 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
872 pac7311_jpeg_header2, sizeof(pac7311_jpeg_header2));
874 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
877 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
879 struct sd *sd = (struct sd *) gspca_dev;
881 sd->brightness = val;
882 if (gspca_dev->streaming)
883 setbrightcont(gspca_dev);
887 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
889 struct sd *sd = (struct sd *) gspca_dev;
891 *val = sd->brightness;
895 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
897 struct sd *sd = (struct sd *) gspca_dev;
900 if (gspca_dev->streaming) {
901 if (sd->sensor == SENSOR_PAC7302)
902 setbrightcont(gspca_dev);
904 setcontrast(gspca_dev);
909 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
911 struct sd *sd = (struct sd *) gspca_dev;
917 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
919 struct sd *sd = (struct sd *) gspca_dev;
922 if (gspca_dev->streaming)
923 setcolors(gspca_dev);
927 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
929 struct sd *sd = (struct sd *) gspca_dev;
935 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
937 struct sd *sd = (struct sd *) gspca_dev;
940 if (gspca_dev->streaming)
945 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
947 struct sd *sd = (struct sd *) gspca_dev;
953 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
955 struct sd *sd = (struct sd *) gspca_dev;
958 if (gspca_dev->streaming)
959 setexposure(gspca_dev);
963 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
965 struct sd *sd = (struct sd *) gspca_dev;
971 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
973 struct sd *sd = (struct sd *) gspca_dev;
976 /* when switching to autogain set defaults to make sure
977 we are on a valid point of the autogain gain /
978 exposure knee graph, and give this change time to
979 take effect before doing autogain. */
981 sd->exposure = EXPOSURE_DEF;
983 if (gspca_dev->streaming) {
984 sd->autogain_ignore_frames =
985 PAC_AUTOGAIN_IGNORE_FRAMES;
986 setexposure(gspca_dev);
994 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
996 struct sd *sd = (struct sd *) gspca_dev;
1002 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
1004 struct sd *sd = (struct sd *) gspca_dev;
1007 if (gspca_dev->streaming)
1008 sethvflip(gspca_dev);
1012 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
1014 struct sd *sd = (struct sd *) gspca_dev;
1020 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1022 struct sd *sd = (struct sd *) gspca_dev;
1025 if (gspca_dev->streaming)
1026 sethvflip(gspca_dev);
1030 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1032 struct sd *sd = (struct sd *) gspca_dev;
1038 /* sub-driver description */
1039 static struct sd_desc sd_desc = {
1040 .name = MODULE_NAME,
1042 .nctrls = ARRAY_SIZE(sd_ctrls),
1043 .config = sd_config,
1048 .pkt_scan = sd_pkt_scan,
1049 .dq_callback = do_autogain,
1052 /* -- module initialisation -- */
1053 static __devinitdata struct usb_device_id device_table[] = {
1054 {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311},
1055 {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311},
1056 {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311},
1057 {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311},
1058 {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311},
1059 {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311},
1060 {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
1061 {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},
1062 {USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302},
1065 MODULE_DEVICE_TABLE(usb, device_table);
1067 /* -- device connect -- */
1068 static int sd_probe(struct usb_interface *intf,
1069 const struct usb_device_id *id)
1071 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1075 static struct usb_driver sd_driver = {
1076 .name = MODULE_NAME,
1077 .id_table = device_table,
1079 .disconnect = gspca_disconnect,
1081 .suspend = gspca_suspend,
1082 .resume = gspca_resume,
1086 /* -- module insert / remove -- */
1087 static int __init sd_mod_init(void)
1089 if (usb_register(&sd_driver) < 0)
1091 PDEBUG(D_PROBE, "registered");
1094 static void __exit sd_mod_exit(void)
1096 usb_deregister(&sd_driver);
1097 PDEBUG(D_PROBE, "deregistered");
1100 module_init(sd_mod_init);
1101 module_exit(sd_mod_exit);