2 * Pixart PAC207BCA library
4 * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
5 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
6 * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
8 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define MODULE_NAME "pac207"
30 MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
31 MODULE_DESCRIPTION("Pixart PAC207");
32 MODULE_LICENSE("GPL");
34 #define PAC207_CTRL_TIMEOUT 100 /* ms */
36 #define PAC207_BRIGHTNESS_MIN 0
37 #define PAC207_BRIGHTNESS_MAX 255
38 #define PAC207_BRIGHTNESS_DEFAULT 4 /* power on default: 4 */
40 /* An exposure value of 4 also works (3 does not) but then we need to lower
41 the compression balance setting when in 352x288 mode, otherwise the usb
42 bandwidth is not enough and packets get dropped resulting in corrupt
43 frames. The problem with this is that when the compression balance gets
44 lowered below 0x80, the pac207 starts using a different compression
45 algorithm for some lines, these lines get prefixed with a 0x2dd2 prefix
46 and currently we do not know how to decompress these lines, so for now
47 we use a minimum exposure value of 5 */
48 #define PAC207_EXPOSURE_MIN 5
49 #define PAC207_EXPOSURE_MAX 26
50 #define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 ?? */
51 #define PAC207_EXPOSURE_KNEE 11 /* 4 = 30 fps, 11 = 8, 15 = 6 */
53 #define PAC207_GAIN_MIN 0
54 #define PAC207_GAIN_MAX 31
55 #define PAC207_GAIN_DEFAULT 9 /* power on default: 9 */
56 #define PAC207_GAIN_KNEE 20
58 #define PAC207_AUTOGAIN_DEADZONE 30
59 /* We calculating the autogain at the end of the transfer of a frame, at this
60 moment a frame with the old settings is being transmitted, and a frame is
61 being captured with the old settings. So if we adjust the autogain we must
62 ignore atleast the 2 next frames for the new settings to come into effect
63 before doing any other adjustments */
64 #define PAC207_AUTOGAIN_IGNORE_FRAMES 3
66 /* specific webcam descriptor */
68 struct gspca_dev gspca_dev; /* !! must be the first item */
79 u8 autogain_ignore_frames;
84 /* V4L2 controls supported by the driver */
85 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
86 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
87 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
88 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
89 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
90 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
91 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
92 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
94 static struct ctrl sd_ctrls[] = {
95 #define SD_BRIGHTNESS 0
98 .id = V4L2_CID_BRIGHTNESS,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Brightness",
101 .minimum = PAC207_BRIGHTNESS_MIN,
102 .maximum = PAC207_BRIGHTNESS_MAX,
104 .default_value = PAC207_BRIGHTNESS_DEFAULT,
107 .set = sd_setbrightness,
108 .get = sd_getbrightness,
110 #define SD_EXPOSURE 1
113 .id = V4L2_CID_EXPOSURE,
114 .type = V4L2_CTRL_TYPE_INTEGER,
116 .minimum = PAC207_EXPOSURE_MIN,
117 .maximum = PAC207_EXPOSURE_MAX,
119 .default_value = PAC207_EXPOSURE_DEFAULT,
122 .set = sd_setexposure,
123 .get = sd_getexposure,
125 #define SD_AUTOGAIN 2
128 .id = V4L2_CID_AUTOGAIN,
129 .type = V4L2_CTRL_TYPE_BOOLEAN,
137 .set = sd_setautogain,
138 .get = sd_getautogain,
144 .type = V4L2_CTRL_TYPE_INTEGER,
146 .minimum = PAC207_GAIN_MIN,
147 .maximum = PAC207_GAIN_MAX,
149 .default_value = PAC207_GAIN_DEFAULT,
157 static struct v4l2_pix_format sif_mode[] = {
158 {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
160 .sizeimage = (176 + 2) * 144,
161 /* uncompressed, add 2 bytes / line for line header */
162 .colorspace = V4L2_COLORSPACE_SRGB,
164 {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
166 /* compressed, but only when needed (not compressed
167 when the framerate is low) */
168 .sizeimage = (352 + 2) * 288,
169 .colorspace = V4L2_COLORSPACE_SRGB,
173 static const __u8 pac207_sensor_init[][8] = {
174 {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0},
175 {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
176 {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
177 {0x00, 0x00, 0x32, 0x00, 0x96, 0x00, 0xa2, 0x02},
178 {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00},
181 /* 48 reg_72 Rate Control end BalSize_4a =0x36 */
182 static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 };
184 static const unsigned char pac207_sof_marker[5] =
185 { 0xff, 0xff, 0x00, 0xff, 0x96 };
187 static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
188 const u8 *buffer, u16 length)
190 struct usb_device *udev = gspca_dev->dev;
193 memcpy(gspca_dev->usb_buf, buffer, length);
195 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
196 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
198 gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
201 "Failed to write registers to index 0x%04X, error %d)",
208 static int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
210 struct usb_device *udev = gspca_dev->dev;
213 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
214 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
215 value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
217 PDEBUG(D_ERR, "Failed to write a register (index 0x%04X,"
218 " value 0x%02X, error %d)", index, value, err);
223 static int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
225 struct usb_device *udev = gspca_dev->dev;
228 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
229 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
231 gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
234 "Failed to read a register (index 0x%04X, error %d)",
239 return gspca_dev->usb_buf[0];
242 /* this function is called at probe time */
243 static int sd_config(struct gspca_dev *gspca_dev,
244 const struct usb_device_id *id)
246 struct sd *sd = (struct sd *) gspca_dev;
250 idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
251 idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
252 idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4);
253 idreg[1] = idreg[1] & 0x0f;
254 PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
257 if (idreg[0] != 0x27) {
258 PDEBUG(D_PROBE, "Error invalid sensor ID!");
262 pac207_write_reg(gspca_dev, 0x41, 0x00);
263 /* Bit_0=Image Format,
265 * Bit_2=Compression test mode enable */
266 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
267 pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
270 "Pixart PAC207BCA Image Processor and Control Chip detected"
271 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
273 cam = &gspca_dev->cam;
274 cam->dev_name = (char *) id->driver_info;
276 cam->cam_mode = sif_mode;
277 cam->nmodes = ARRAY_SIZE(sif_mode);
278 sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
279 sd->exposure = PAC207_EXPOSURE_DEFAULT;
280 sd->gain = PAC207_GAIN_DEFAULT;
285 /* this function is called at open time */
286 static int sd_open(struct gspca_dev *gspca_dev)
288 struct sd *sd = (struct sd *) gspca_dev;
294 /* -- start the camera -- */
295 static void sd_start(struct gspca_dev *gspca_dev)
297 struct sd *sd = (struct sd *) gspca_dev;
300 pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
301 pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
302 pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
303 pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
304 pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8);
305 pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8);
306 pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4);
308 /* Compression Balance */
309 if (gspca_dev->width == 176)
310 pac207_write_reg(gspca_dev, 0x4a, 0xff);
312 pac207_write_reg(gspca_dev, 0x4a, 0x88);
313 pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
314 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
316 /* PGA global gain (Bit 4-0) */
317 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
318 pac207_write_reg(gspca_dev, 0x02, sd->exposure); /* PXCK = 12MHz /n */
320 mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
321 if (gspca_dev->width == 176) { /* 176x144 */
323 PDEBUG(D_STREAM, "pac207_start mode 176x144");
324 } else { /* 352x288 */
325 PDEBUG(D_STREAM, "pac207_start mode 352x288");
327 pac207_write_reg(gspca_dev, 0x41, mode);
329 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
330 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
332 pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
335 sd->autogain_ignore_frames = 0;
336 atomic_set(&sd->avg_lum, -1);
339 static void sd_stopN(struct gspca_dev *gspca_dev)
341 pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
342 pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
343 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
346 static void sd_stop0(struct gspca_dev *gspca_dev)
350 /* this function is called at close time */
351 static void sd_close(struct gspca_dev *gspca_dev)
355 static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
357 struct sd *sd = (struct sd *) gspca_dev;
358 int avg_lum = atomic_read(&sd->avg_lum);
363 if (sd->autogain_ignore_frames > 0)
364 sd->autogain_ignore_frames--;
365 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
366 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE,
367 PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
368 sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
371 static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
372 unsigned char *m, int len)
374 struct sd *sd = (struct sd *) gspca_dev;
377 /* Search for the SOF marker (fixed part) in the header */
378 for (i = 0; i < len; i++) {
379 if (m[i] == pac207_sof_marker[sd->sof_read]) {
381 if (sd->sof_read == sizeof(pac207_sof_marker)) {
383 "SOF found, bytes to analyze: %u."
384 " Frame starts at byte #%u",
397 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
398 struct gspca_frame *frame,
402 struct sd *sd = (struct sd *) gspca_dev;
405 sof = pac207_find_sof(gspca_dev, data, len);
409 /* finish decoding current frame */
411 if (n > sizeof pac207_sof_marker)
412 n -= sizeof pac207_sof_marker;
415 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
418 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
422 if (sd->header_read < 11) {
425 /* get average lumination from frame header (byte 5) */
426 if (sd->header_read < 5) {
427 needed = 5 - sd->header_read;
429 atomic_set(&sd->avg_lum, data[needed - 1]);
431 /* skip the rest of the header */
432 needed = 11 - sd->header_read;
434 sd->header_read += len;
439 sd->header_read = 11;
442 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
445 static void setbrightness(struct gspca_dev *gspca_dev)
447 struct sd *sd = (struct sd *) gspca_dev;
449 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
450 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
451 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
454 static void setexposure(struct gspca_dev *gspca_dev)
456 struct sd *sd = (struct sd *) gspca_dev;
458 pac207_write_reg(gspca_dev, 0x02, sd->exposure);
459 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
460 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
463 static void setgain(struct gspca_dev *gspca_dev)
465 struct sd *sd = (struct sd *) gspca_dev;
467 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
468 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
469 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
472 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
474 struct sd *sd = (struct sd *) gspca_dev;
476 sd->brightness = val;
477 if (gspca_dev->streaming)
478 setbrightness(gspca_dev);
482 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
484 struct sd *sd = (struct sd *) gspca_dev;
486 *val = sd->brightness;
490 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
492 struct sd *sd = (struct sd *) gspca_dev;
495 if (gspca_dev->streaming)
496 setexposure(gspca_dev);
500 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
502 struct sd *sd = (struct sd *) gspca_dev;
508 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
510 struct sd *sd = (struct sd *) gspca_dev;
513 if (gspca_dev->streaming)
518 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
520 struct sd *sd = (struct sd *) gspca_dev;
526 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
528 struct sd *sd = (struct sd *) gspca_dev;
531 /* when switching to autogain set defaults to make sure
532 we are on a valid point of the autogain gain /
533 exposure knee graph, and give this change time to
534 take effect before doing autogain. */
536 sd->exposure = PAC207_EXPOSURE_DEFAULT;
537 sd->gain = PAC207_GAIN_DEFAULT;
538 if (gspca_dev->streaming) {
539 sd->autogain_ignore_frames =
540 PAC207_AUTOGAIN_IGNORE_FRAMES;
541 setexposure(gspca_dev);
549 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
551 struct sd *sd = (struct sd *) gspca_dev;
557 /* sub-driver description */
558 static const struct sd_desc sd_desc = {
561 .nctrls = ARRAY_SIZE(sd_ctrls),
568 .dq_callback = pac207_do_auto_gain,
569 .pkt_scan = sd_pkt_scan,
572 /* -- module initialisation -- */
573 static const __devinitdata struct usb_device_id device_table[] = {
574 {USB_DEVICE(0x041e, 0x4028)},
575 {USB_DEVICE(0x093a, 0x2460)},
576 {USB_DEVICE(0x093a, 0x2463)},
577 {USB_DEVICE(0x093a, 0x2464)},
578 {USB_DEVICE(0x093a, 0x2468)},
579 {USB_DEVICE(0x093a, 0x2470)},
580 {USB_DEVICE(0x093a, 0x2471)},
581 {USB_DEVICE(0x093a, 0x2472)},
582 {USB_DEVICE(0x2001, 0xf115)},
585 MODULE_DEVICE_TABLE(usb, device_table);
587 /* -- device connect -- */
588 static int sd_probe(struct usb_interface *intf,
589 const struct usb_device_id *id)
591 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
595 static struct usb_driver sd_driver = {
597 .id_table = device_table,
599 .disconnect = gspca_disconnect,
602 /* -- module insert / remove -- */
603 static int __init sd_mod_init(void)
605 if (usb_register(&sd_driver) < 0)
607 PDEBUG(D_PROBE, "registered");
610 static void __exit sd_mod_exit(void)
612 usb_deregister(&sd_driver);
613 PDEBUG(D_PROBE, "deregistered");
616 module_init(sd_mod_init);
617 module_exit(sd_mod_exit);