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, ...
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
49 #define MODULE_NAME "pac7311"
53 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
54 MODULE_DESCRIPTION("Pixart PAC7311");
55 MODULE_LICENSE("GPL");
57 /* specific webcam descriptor */
59 struct gspca_dev gspca_dev; /* !! must be the first item */
61 unsigned char brightness;
62 unsigned char contrast;
64 unsigned char autogain;
69 #define SENSOR_PAC7302 0
70 #define SENSOR_PAC7311 1
74 u8 autogain_ignore_frames;
79 /* V4L2 controls supported by the driver */
80 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
81 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
82 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
83 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
84 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
90 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
91 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
93 static struct ctrl sd_ctrls[] = {
96 .id = V4L2_CID_BRIGHTNESS,
97 .type = V4L2_CTRL_TYPE_INTEGER,
100 #define BRIGHTNESS_MAX 0x20
101 .maximum = BRIGHTNESS_MAX,
103 #define BRIGHTNESS_DEF 0x10
104 .default_value = BRIGHTNESS_DEF,
106 .set = sd_setbrightness,
107 .get = sd_getbrightness,
111 .id = V4L2_CID_CONTRAST,
112 .type = V4L2_CTRL_TYPE_INTEGER,
115 #define CONTRAST_MAX 255
116 .maximum = CONTRAST_MAX,
118 #define CONTRAST_DEF 127
119 .default_value = CONTRAST_DEF,
121 .set = sd_setcontrast,
122 .get = sd_getcontrast,
126 .id = V4L2_CID_SATURATION,
127 .type = V4L2_CTRL_TYPE_INTEGER,
128 .name = "Saturation",
130 #define COLOR_MAX 255
131 .maximum = COLOR_MAX,
133 #define COLOR_DEF 127
134 .default_value = COLOR_DEF,
141 .id = V4L2_CID_AUTOGAIN,
142 .type = V4L2_CTRL_TYPE_BOOLEAN,
147 #define AUTOGAIN_DEF 1
148 .default_value = AUTOGAIN_DEF,
150 .set = sd_setautogain,
151 .get = sd_getautogain,
153 /* next controls work with pac7302 only */
156 .id = V4L2_CID_HFLIP,
157 .type = V4L2_CTRL_TYPE_BOOLEAN,
163 .default_value = HFLIP_DEF,
170 .id = V4L2_CID_VFLIP,
171 .type = V4L2_CTRL_TYPE_BOOLEAN,
177 .default_value = VFLIP_DEF,
184 static struct v4l2_pix_format vga_mode[] = {
185 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
187 .sizeimage = 160 * 120 * 3 / 8 + 590,
188 .colorspace = V4L2_COLORSPACE_JPEG,
190 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
192 .sizeimage = 320 * 240 * 3 / 8 + 590,
193 .colorspace = V4L2_COLORSPACE_JPEG,
195 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
197 .sizeimage = 640 * 480 * 3 / 8 + 590,
198 .colorspace = V4L2_COLORSPACE_JPEG,
203 static const __u8 probe_7302[] = {
205 0xff, 0x01, /* page 1 */
206 0x78, 0x00, /* deactivate */
208 0x78, 0x40, /* led off */
210 static const __u8 start_7302[] = {
211 /* index, len, [value]* */
212 0xff, 1, 0x00, /* page 0 */
213 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
214 0x00, 0x00, 0x00, 0x00,
215 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
216 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
217 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
221 0x3a, 3, 0x14, 0xff, 0x5a,
222 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
225 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
227 0x6e, 3, 0x08, 0x06, 0x00,
228 0x72, 3, 0x00, 0xff, 0x00,
229 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
230 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
231 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
232 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
237 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
239 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
242 0xff, 1, 0x01, /* page 1 */
243 0x12, 3, 0x02, 0x00, 0x01,
245 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
247 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
249 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
250 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
251 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
254 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
255 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
257 0xff, 1, 0x02, /* page 2 */
259 0xff, 1, 0x03, /* page 3 */
260 0x00, 255, /* load the page 3 */
262 0xff, 1, 0x02, /* page 2 */
264 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
266 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
267 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
269 0xff, 1, 0x01, /* page 1 */
271 0, 0 /* end of sequence */
274 /* page 3 - the value 0xaa says skip the index - see reg_w_page() */
275 static const __u8 page3_7302[] = {
276 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
277 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
278 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
279 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
280 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
281 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
282 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
283 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
286 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
289 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
290 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
291 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
292 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
299 static const __u8 probe_7311[] = {
300 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
301 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
302 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
312 static const __u8 start_7311[] = {
313 /* index, len, [value]* */
314 0xff, 1, 0x01, /* page 1 */
315 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
316 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
317 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
318 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
322 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
323 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
324 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
325 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
327 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
328 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
329 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
331 0x96, 3, 0x01, 0x08, 0x04,
332 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
333 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
334 0x3f, 0x00, 0x0a, 0x01, 0x00,
335 0xff, 1, 0x04, /* page 4 */
336 0x00, 254, /* load the page 4 */
338 0, 0 /* end of sequence */
341 /* page 4 - the value 0xaa says skip the index - see reg_w_page() */
342 static const __u8 page4_7311[] = {
343 0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
344 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62,
345 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
346 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa,
347 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x01,
348 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
349 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
352 static void reg_w_buf(struct gspca_dev *gspca_dev,
354 const char *buffer, int len)
356 memcpy(gspca_dev->usb_buf, buffer, len);
357 usb_control_msg(gspca_dev->dev,
358 usb_sndctrlpipe(gspca_dev->dev, 0),
360 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
362 index, gspca_dev->usb_buf, len,
367 static void reg_w(struct gspca_dev *gspca_dev,
371 gspca_dev->usb_buf[0] = value;
372 usb_control_msg(gspca_dev->dev,
373 usb_sndctrlpipe(gspca_dev->dev, 0),
375 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
376 value, index, gspca_dev->usb_buf, 1,
380 static void reg_w_seq(struct gspca_dev *gspca_dev,
381 const __u8 *seq, int len)
384 reg_w(gspca_dev, seq[0], seq[1]);
389 /* load the beginning of a page */
390 static void reg_w_page(struct gspca_dev *gspca_dev,
391 const __u8 *page, int len)
395 for (index = 0; index < len; index++) {
396 if (page[index] == 0xaa) /* skip this index */
398 gspca_dev->usb_buf[0] = page[index];
399 usb_control_msg(gspca_dev->dev,
400 usb_sndctrlpipe(gspca_dev->dev, 0),
402 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
403 0, index, gspca_dev->usb_buf, 1,
408 /* output a variable sequence */
409 static void reg_w_var(struct gspca_dev *gspca_dev,
421 reg_w_page(gspca_dev, page4_7311, sizeof page4_7311);
424 reg_w_page(gspca_dev, page3_7302, sizeof page3_7302);
428 PDEBUG(D_ERR|D_STREAM,
429 "Incorrect variable sequence");
434 reg_w_buf(gspca_dev, index, seq, len);
438 reg_w_buf(gspca_dev, index, seq, 8);
448 /* this function is called at probe time */
449 static int sd_config(struct gspca_dev *gspca_dev,
450 const struct usb_device_id *id)
452 struct sd *sd = (struct sd *) gspca_dev;
455 cam = &gspca_dev->cam;
458 sd->sensor = id->driver_info;
459 if (sd->sensor == SENSOR_PAC7302) {
460 PDEBUG(D_CONF, "Find Sensor PAC7302");
461 reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302);
463 cam->cam_mode = &vga_mode[2]; /* only 640x480 */
466 PDEBUG(D_CONF, "Find Sensor PAC7311");
467 reg_w_seq(gspca_dev, probe_7311, sizeof probe_7311);
469 cam->cam_mode = vga_mode;
470 cam->nmodes = ARRAY_SIZE(vga_mode);
473 sd->brightness = BRIGHTNESS_DEF;
474 sd->contrast = CONTRAST_DEF;
475 sd->colors = COLOR_DEF;
476 sd->autogain = AUTOGAIN_DEF;
477 sd->hflip = HFLIP_DEF;
478 sd->vflip = VFLIP_DEF;
483 static void setbrightcont(struct gspca_dev *gspca_dev)
485 struct sd *sd = (struct sd *) gspca_dev;
487 static const __u8 max[10] =
488 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
490 static const __u8 delta[10] =
491 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
494 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
495 for (i = 0; i < 10; i++) {
497 v += (sd->brightness - BRIGHTNESS_MAX)
498 * 150 / BRIGHTNESS_MAX; /* 200 ? */
499 v -= delta[i] * sd->contrast / CONTRAST_MAX;
504 reg_w(gspca_dev, 0xa2 + i, v);
506 reg_w(gspca_dev, 0xdc, 0x01);
509 /* This function is used by pac7302 only */
510 static void setbrightness(struct gspca_dev *gspca_dev)
512 struct sd *sd = (struct sd *) gspca_dev;
515 if (sd->sensor == SENSOR_PAC7302) {
516 setbrightcont(gspca_dev);
519 /* HDG: this is not brightness but gain, I'll add gain and exposure controls
523 brightness = BRIGHTNESS_MAX - sd->brightness;
524 reg_w(gspca_dev, 0xff, 0x04);
525 reg_w(gspca_dev, 0x0e, 0x00);
526 reg_w(gspca_dev, 0x0f, brightness);
527 /* load registers to sensor (Bit 0, auto clear) */
528 reg_w(gspca_dev, 0x11, 0x01);
529 PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
532 static void setcontrast(struct gspca_dev *gspca_dev)
534 struct sd *sd = (struct sd *) gspca_dev;
536 if (sd->sensor == SENSOR_PAC7302) {
537 setbrightcont(gspca_dev);
540 reg_w(gspca_dev, 0xff, 0x04);
541 reg_w(gspca_dev, 0x10, sd->contrast >> 4);
542 /* load registers to sensor (Bit 0, auto clear) */
543 reg_w(gspca_dev, 0x11, 0x01);
546 /* This function is used by pac7302 only */
547 static void setcolors(struct gspca_dev *gspca_dev)
549 struct sd *sd = (struct sd *) gspca_dev;
551 if (sd->sensor == SENSOR_PAC7302) {
553 static const int a[9] =
554 {217, -212, 0, -101, 170, -67, -38, -315, 355};
555 static const int b[9] =
556 {19, 106, 0, 19, 106, 1, 19, 106, 1};
558 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
559 reg_w(gspca_dev, 0x11, 0x01);
560 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
561 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
562 for (i = 0; i < 9; i++) {
563 v = a[i] * sd->colors / COLOR_MAX + b[i];
564 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
565 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
567 reg_w(gspca_dev, 0xdc, 0x01);
568 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
572 static void sethvflip(struct gspca_dev *gspca_dev)
574 struct sd *sd = (struct sd *) gspca_dev;
577 if (sd->sensor == SENSOR_PAC7302) {
578 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
579 data = (sd->hflip ? 0x00 : 0x08)
580 | (sd->vflip ? 0x04 : 0x00);
582 reg_w(gspca_dev, 0xff, 0x04); /* page 3 */
583 data = (sd->hflip ? 0x04 : 0x00)
584 | (sd->vflip ? 0x08 : 0x00);
586 reg_w(gspca_dev, 0x21, data);
587 reg_w(gspca_dev, 0x11, 0x01);
590 /* this function is called at open time */
591 static int sd_open(struct gspca_dev *gspca_dev)
596 static void sd_start(struct gspca_dev *gspca_dev)
598 struct sd *sd = (struct sd *) gspca_dev;
602 if (sd->sensor == SENSOR_PAC7302)
603 reg_w_var(gspca_dev, start_7302);
605 reg_w_var(gspca_dev, start_7311);
607 setcontrast(gspca_dev);
608 setbrightness(gspca_dev);
609 setcolors(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, 0x03);
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 sd->autogain_ignore_frames = 0;
656 atomic_set(&sd->avg_lum, -1);
659 static void sd_stopN(struct gspca_dev *gspca_dev)
661 struct sd *sd = (struct sd *) gspca_dev;
663 if (sd->sensor == SENSOR_PAC7302) {
664 reg_w(gspca_dev, 0xff, 0x01);
665 reg_w(gspca_dev, 0x78, 0x00);
666 reg_w(gspca_dev, 0x78, 0x00);
669 reg_w(gspca_dev, 0xff, 0x04);
670 reg_w(gspca_dev, 0x27, 0x80);
671 reg_w(gspca_dev, 0x28, 0xca);
672 reg_w(gspca_dev, 0x29, 0x53);
673 reg_w(gspca_dev, 0x2a, 0x0e);
674 reg_w(gspca_dev, 0xff, 0x01);
675 reg_w(gspca_dev, 0x3e, 0x20);
676 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
677 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
678 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
681 static void sd_stop0(struct gspca_dev *gspca_dev)
683 struct sd *sd = (struct sd *) gspca_dev;
685 if (sd->sensor == SENSOR_PAC7302) {
686 reg_w(gspca_dev, 0xff, 0x01);
687 reg_w(gspca_dev, 0x78, 0x40);
691 /* this function is called at close time */
692 static void sd_close(struct gspca_dev *gspca_dev)
696 static void do_autogain(struct gspca_dev *gspca_dev)
700 static const unsigned char pac7311_jpeg_header1[] = {
701 0xff, 0xd8, 0xff, 0xc0, 0x00, 0x11, 0x08
704 static const unsigned char pac7311_jpeg_header2[] = {
705 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda,
706 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
709 /* Include pac common sof detection functions */
710 #include "pac_common.h"
712 #define HEADER_LENGTH 2
714 /* this function is run at interrupt level */
715 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
716 struct gspca_frame *frame, /* target */
717 __u8 *data, /* isoc packet */
718 int len) /* iso packet length */
720 struct sd *sd = (struct sd *) gspca_dev;
723 sof = pac_find_sof(gspca_dev, data, len);
725 unsigned char tmpbuf[4];
726 int n, lum_offset, footer_length;
728 if (sd->sensor == SENSOR_PAC7302) {
729 lum_offset = 34 + sizeof pac_sof_marker;
732 lum_offset = 24 + sizeof pac_sof_marker;
736 /* Finish decoding current frame */
737 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
739 frame->data_end += n;
742 frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
744 if (gspca_dev->last_packet_type != DISCARD_PACKET &&
745 frame->data_end[-2] == 0xff &&
746 frame->data_end[-1] == 0xd9)
747 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
754 /* Get average lumination */
755 if (gspca_dev->last_packet_type == LAST_PACKET &&
757 if (sd->sensor == SENSOR_PAC7302)
758 atomic_set(&sd->avg_lum,
759 (data[-lum_offset] << 8) |
760 data[-lum_offset + 1]);
762 atomic_set(&sd->avg_lum,
764 data[-lum_offset + 1]);
766 atomic_set(&sd->avg_lum, -1);
769 /* Start the new frame with the jpeg header */
770 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
771 pac7311_jpeg_header1, sizeof(pac7311_jpeg_header1));
772 if (sd->sensor == SENSOR_PAC7302) {
773 /* The PAC7302 has the image rotated 90 degrees */
774 tmpbuf[0] = gspca_dev->width >> 8;
775 tmpbuf[1] = gspca_dev->width & 0xff;
776 tmpbuf[2] = gspca_dev->height >> 8;
777 tmpbuf[3] = gspca_dev->height & 0xff;
779 tmpbuf[0] = gspca_dev->height >> 8;
780 tmpbuf[1] = gspca_dev->height & 0xff;
781 tmpbuf[2] = gspca_dev->width >> 8;
782 tmpbuf[3] = gspca_dev->width & 0xff;
784 gspca_frame_add(gspca_dev, INTER_PACKET, frame, tmpbuf, 4);
785 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
786 pac7311_jpeg_header2, sizeof(pac7311_jpeg_header2));
791 if (sd->header_read < HEADER_LENGTH) {
792 /* skip the variable part of the sof header */
793 int needed = HEADER_LENGTH - sd->header_read;
795 sd->header_read += len;
800 sd->header_read = HEADER_LENGTH;
803 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
806 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
808 struct sd *sd = (struct sd *) gspca_dev;
810 sd->brightness = val;
811 if (gspca_dev->streaming)
812 setbrightness(gspca_dev);
816 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
818 struct sd *sd = (struct sd *) gspca_dev;
820 *val = sd->brightness;
824 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
826 struct sd *sd = (struct sd *) gspca_dev;
829 if (gspca_dev->streaming)
830 setcontrast(gspca_dev);
834 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
836 struct sd *sd = (struct sd *) gspca_dev;
842 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
844 struct sd *sd = (struct sd *) gspca_dev;
847 if (gspca_dev->streaming)
848 setcolors(gspca_dev);
852 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
854 struct sd *sd = (struct sd *) gspca_dev;
860 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
862 struct sd *sd = (struct sd *) gspca_dev;
869 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
871 struct sd *sd = (struct sd *) gspca_dev;
877 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
879 struct sd *sd = (struct sd *) gspca_dev;
882 if (gspca_dev->streaming)
883 sethvflip(gspca_dev);
887 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
889 struct sd *sd = (struct sd *) gspca_dev;
895 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
897 struct sd *sd = (struct sd *) gspca_dev;
900 if (gspca_dev->streaming)
901 sethvflip(gspca_dev);
905 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
907 struct sd *sd = (struct sd *) gspca_dev;
913 /* sub-driver description */
914 static struct sd_desc sd_desc = {
917 .nctrls = ARRAY_SIZE(sd_ctrls),
924 .pkt_scan = sd_pkt_scan,
925 .dq_callback = do_autogain,
928 /* -- module initialisation -- */
929 static __devinitdata struct usb_device_id device_table[] = {
930 {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311},
931 {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311},
932 {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311},
933 {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311},
934 {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311},
935 {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311},
936 {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
939 MODULE_DEVICE_TABLE(usb, device_table);
941 /* -- device connect -- */
942 static int sd_probe(struct usb_interface *intf,
943 const struct usb_device_id *id)
945 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
949 static struct usb_driver sd_driver = {
951 .id_table = device_table,
953 .disconnect = gspca_disconnect,
955 .suspend = gspca_suspend,
956 .resume = gspca_resume,
960 /* -- module insert / remove -- */
961 static int __init sd_mod_init(void)
963 if (usb_register(&sd_driver) < 0)
965 PDEBUG(D_PROBE, "registered");
968 static void __exit sd_mod_exit(void)
970 usb_deregister(&sd_driver);
971 PDEBUG(D_PROBE, "deregistered");
974 module_init(sd_mod_init);
975 module_exit(sd_mod_exit);