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 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 5)
31 static const char version[] = "2.1.5";
33 MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
34 MODULE_DESCRIPTION("Pixart PAC207");
35 MODULE_LICENSE("GPL");
37 #define PAC207_CTRL_TIMEOUT 100 /* ms */
39 #define PAC207_BRIGHTNESS_MIN 0
40 #define PAC207_BRIGHTNESS_MAX 255
41 #define PAC207_BRIGHTNESS_DEFAULT 4 /* power on default: 4 */
43 /* An exposure value of 4 also works (3 does not) but then we need to lower
44 the compression balance setting when in 352x288 mode, otherwise the usb
45 bandwidth is not enough and packets get dropped resulting in corrupt
46 frames. The problem with this is that when the compression balance gets
47 lowered below 0x80, the pac207 starts using a different compression
48 algorithm for some lines, these lines get prefixed with a 0x2dd2 prefix
49 and currently we do not know how to decompress these lines, so for now
50 we use a minimum exposure value of 5 */
51 #define PAC207_EXPOSURE_MIN 5
52 #define PAC207_EXPOSURE_MAX 26
53 #define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 ?? */
54 #define PAC207_EXPOSURE_KNEE 11 /* 4 = 30 fps, 11 = 8, 15 = 6 */
56 #define PAC207_GAIN_MIN 0
57 #define PAC207_GAIN_MAX 31
58 #define PAC207_GAIN_DEFAULT 9 /* power on default: 9 */
59 #define PAC207_GAIN_KNEE 20
61 #define PAC207_AUTOGAIN_DEADZONE 30
62 /* We calculating the autogain at the end of the transfer of a frame, at this
63 moment a frame with the old settings is being transmitted, and a frame is
64 being captured with the old settings. So if we adjust the autogain we must
65 ignore atleast the 2 next frames for the new settings to come into effect
66 before doing any other adjustments */
67 #define PAC207_AUTOGAIN_IGNORE_FRAMES 3
69 /* specific webcam descriptor */
71 struct gspca_dev gspca_dev; /* !! must be the first item */
82 u8 autogain_ignore_frames;
87 /* V4L2 controls supported by the driver */
88 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
90 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
91 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
92 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
93 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
94 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
95 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
97 static struct ctrl sd_ctrls[] = {
98 #define SD_BRIGHTNESS 0
101 .id = V4L2_CID_BRIGHTNESS,
102 .type = V4L2_CTRL_TYPE_INTEGER,
103 .name = "Brightness",
104 .minimum = PAC207_BRIGHTNESS_MIN,
105 .maximum = PAC207_BRIGHTNESS_MAX,
107 .default_value = PAC207_BRIGHTNESS_DEFAULT,
110 .set = sd_setbrightness,
111 .get = sd_getbrightness,
113 #define SD_EXPOSURE 1
116 .id = V4L2_CID_EXPOSURE,
117 .type = V4L2_CTRL_TYPE_INTEGER,
119 .minimum = PAC207_EXPOSURE_MIN,
120 .maximum = PAC207_EXPOSURE_MAX,
122 .default_value = PAC207_EXPOSURE_DEFAULT,
125 .set = sd_setexposure,
126 .get = sd_getexposure,
128 #define SD_AUTOGAIN 2
131 .id = V4L2_CID_AUTOGAIN,
132 .type = V4L2_CTRL_TYPE_BOOLEAN,
140 .set = sd_setautogain,
141 .get = sd_getautogain,
147 .type = V4L2_CTRL_TYPE_INTEGER,
149 .minimum = PAC207_GAIN_MIN,
150 .maximum = PAC207_GAIN_MAX,
152 .default_value = PAC207_GAIN_DEFAULT,
160 static struct v4l2_pix_format sif_mode[] = {
161 {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
163 .sizeimage = (176 + 2) * 144,
164 /* uncompressed, add 2 bytes / line for line header */
165 .colorspace = V4L2_COLORSPACE_SRGB,
167 {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
169 .sizeimage = 352 * 288 / 2, /* compressed */
170 .colorspace = V4L2_COLORSPACE_SRGB,
174 static const __u8 pac207_sensor_init[][8] = {
175 {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0},
176 {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
177 {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
178 {0x00, 0x00, 0x32, 0x00, 0x96, 0x00, 0xa2, 0x02},
179 {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00},
182 /* 48 reg_72 Rate Control end BalSize_4a =0x36 */
183 static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 };
185 static const unsigned char pac207_sof_marker[5] =
186 { 0xff, 0xff, 0x00, 0xff, 0x96 };
188 int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
189 const u8 *buffer, u16 length)
191 struct usb_device *udev = gspca_dev->dev;
195 memcpy(kbuf, buffer, length);
197 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
198 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
199 0x00, index, kbuf, length, PAC207_CTRL_TIMEOUT);
202 "Failed to write registers to index 0x%04X, error %d)",
209 int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
211 struct usb_device *udev = gspca_dev->dev;
214 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
215 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
216 value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
218 PDEBUG(D_ERR, "Failed to write a register (index 0x%04X,"
219 " value 0x%02X, error %d)", index, value, err);
225 int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
227 struct usb_device *udev = gspca_dev->dev;
231 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
232 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
233 0x00, index, &buff, 1, PAC207_CTRL_TIMEOUT);
236 "Failed to read a register (index 0x%04X, error %d)",
245 /* this function is called at probe time */
246 static int sd_config(struct gspca_dev *gspca_dev,
247 const struct usb_device_id *id)
249 struct sd *sd = (struct sd *) gspca_dev;
253 idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
254 idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
255 idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4);
256 idreg[1] = idreg[1] & 0x0f;
257 PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
260 if (idreg[0] != 0x27) {
261 PDEBUG(D_PROBE, "Error invalid sensor ID!");
265 pac207_write_reg(gspca_dev, 0x41, 0x00);
266 /* Bit_0=Image Format,
268 * Bit_2=Compression test mode enable */
269 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
270 pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
273 "Pixart PAC207BCA Image Processor and Control Chip detected"
274 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
276 cam = &gspca_dev->cam;
277 cam->dev_name = (char *) id->driver_info;
279 cam->cam_mode = sif_mode;
280 cam->nmodes = ARRAY_SIZE(sif_mode);
281 sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
282 sd->exposure = PAC207_EXPOSURE_DEFAULT;
283 sd->gain = PAC207_GAIN_DEFAULT;
288 /* this function is called at open time */
289 static int sd_open(struct gspca_dev *gspca_dev)
291 struct sd *sd = (struct sd *) gspca_dev;
297 /* -- start the camera -- */
298 static void sd_start(struct gspca_dev *gspca_dev)
300 struct sd *sd = (struct sd *) gspca_dev;
303 pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
304 pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
305 pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
306 pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
307 pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8);
308 pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8);
309 pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4);
311 /* Compression Balance */
312 if (gspca_dev->width == 176)
313 pac207_write_reg(gspca_dev, 0x4a, 0xff);
315 pac207_write_reg(gspca_dev, 0x4a, 0x88);
316 pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
317 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
319 /* PGA global gain (Bit 4-0) */
320 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
321 pac207_write_reg(gspca_dev, 0x02, sd->exposure); /* PXCK = 12MHz /n */
323 mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
324 if (gspca_dev->width == 176) { /* 176x144 */
326 PDEBUG(D_STREAM, "pac207_start mode 176x144");
327 } else { /* 352x288 */
328 PDEBUG(D_STREAM, "pac207_start mode 352x288");
330 pac207_write_reg(gspca_dev, 0x41, mode);
332 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
333 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
335 pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
338 sd->autogain_ignore_frames = 0;
339 atomic_set(&sd->avg_lum, -1);
342 static void sd_stopN(struct gspca_dev *gspca_dev)
344 pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
345 pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
346 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
349 static void sd_stop0(struct gspca_dev *gspca_dev)
353 /* this function is called at close time */
354 static void sd_close(struct gspca_dev *gspca_dev)
358 /* auto gain and exposure algorithm based on the knee algorithm described here:
359 * <http://ytse.tricolour.net/docs/LowLightOptimization.html> */
360 static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
362 struct sd *sd = (struct sd *) gspca_dev;
363 int i, steps, desired_avg_lum;
364 int orig_gain = sd->gain;
365 int orig_exposure = sd->exposure;
366 int avg_lum = atomic_read(&sd->avg_lum);
368 if (!sd->autogain || avg_lum == -1)
371 if (sd->autogain_ignore_frames > 0) {
372 sd->autogain_ignore_frames--;
376 /* correct desired lumination for the configured brightness */
377 desired_avg_lum = 100 + sd->brightness / 2;
379 /* If we are of a multiple of deadzone, do multiple step to reach the
380 desired lumination fast (with the risc of a slight overshoot) */
381 steps = abs(desired_avg_lum - avg_lum) / PAC207_AUTOGAIN_DEADZONE;
383 for (i = 0; i < steps; i++) {
384 if (avg_lum > desired_avg_lum) {
385 if (sd->gain > PAC207_GAIN_KNEE)
387 else if (sd->exposure > PAC207_EXPOSURE_KNEE)
389 else if (sd->gain > PAC207_GAIN_DEFAULT)
391 else if (sd->exposure > PAC207_EXPOSURE_MIN)
393 else if (sd->gain > PAC207_GAIN_MIN)
398 if (sd->gain < PAC207_GAIN_DEFAULT)
400 else if (sd->exposure < PAC207_EXPOSURE_KNEE)
402 else if (sd->gain < PAC207_GAIN_KNEE)
404 else if (sd->exposure < PAC207_EXPOSURE_MAX)
406 else if (sd->gain < PAC207_GAIN_MAX)
413 if (sd->exposure != orig_exposure || sd->gain != orig_gain) {
414 if (sd->exposure != orig_exposure)
415 pac207_write_reg(gspca_dev, 0x0002, sd->exposure);
416 if (sd->gain != orig_gain)
417 pac207_write_reg(gspca_dev, 0x000e, sd->gain);
418 pac207_write_reg(gspca_dev, 0x13, 0x01); /* load reg to sen */
419 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
420 sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
424 static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
425 unsigned char *m, int len)
427 struct sd *sd = (struct sd *) gspca_dev;
430 /* Search for the SOF marker (fixed part) in the header */
431 for (i = 0; i < len; i++) {
432 if (m[i] == pac207_sof_marker[sd->sof_read]) {
434 if (sd->sof_read == sizeof(pac207_sof_marker)) {
436 "SOF found, bytes to analyze: %u."
437 " Frame starts at byte #%u",
450 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
451 struct gspca_frame *frame,
455 struct sd *sd = (struct sd *) gspca_dev;
458 sof = pac207_find_sof(gspca_dev, data, len);
462 /* finish decoding current frame */
464 if (n > sizeof pac207_sof_marker)
465 n -= sizeof pac207_sof_marker;
468 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
471 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
475 if (sd->header_read < 11) {
478 /* get average lumination from frame header (byte 5) */
479 if (sd->header_read < 5) {
480 needed = 5 - sd->header_read;
482 atomic_set(&sd->avg_lum, data[needed - 1]);
484 /* skip the rest of the header */
485 needed = 11 - sd->header_read;
487 sd->header_read += len;
492 sd->header_read = 11;
495 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
498 static void setbrightness(struct gspca_dev *gspca_dev)
500 struct sd *sd = (struct sd *) gspca_dev;
502 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
503 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
504 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
507 static void setexposure(struct gspca_dev *gspca_dev)
509 struct sd *sd = (struct sd *) gspca_dev;
511 pac207_write_reg(gspca_dev, 0x02, sd->exposure);
512 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
513 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
516 static void setgain(struct gspca_dev *gspca_dev)
518 struct sd *sd = (struct sd *) gspca_dev;
520 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
521 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
522 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
525 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
527 struct sd *sd = (struct sd *) gspca_dev;
529 sd->brightness = val;
530 if (gspca_dev->streaming)
531 setbrightness(gspca_dev);
535 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
537 struct sd *sd = (struct sd *) gspca_dev;
539 *val = sd->brightness;
543 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
545 struct sd *sd = (struct sd *) gspca_dev;
547 /* don't allow mucking with exposure when using autogain */
552 if (gspca_dev->streaming)
553 setexposure(gspca_dev);
557 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
559 struct sd *sd = (struct sd *) gspca_dev;
565 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
567 struct sd *sd = (struct sd *) gspca_dev;
569 /* don't allow mucking with gain when using autogain */
574 if (gspca_dev->streaming)
579 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
581 struct sd *sd = (struct sd *) gspca_dev;
587 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
589 struct sd *sd = (struct sd *) gspca_dev;
592 /* when switching to autogain set defaults to make sure
593 we are on a valid point of the autogain gain /
594 exposure knee graph, and give this change time to
595 take effect before doing autogain. */
597 sd->exposure = PAC207_EXPOSURE_DEFAULT;
598 sd->gain = PAC207_GAIN_DEFAULT;
599 if (gspca_dev->streaming) {
600 sd->autogain_ignore_frames =
601 PAC207_AUTOGAIN_IGNORE_FRAMES;
602 setexposure(gspca_dev);
610 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
612 struct sd *sd = (struct sd *) gspca_dev;
618 /* sub-driver description */
619 static const struct sd_desc sd_desc = {
622 .nctrls = ARRAY_SIZE(sd_ctrls),
629 .dq_callback = pac207_do_auto_gain,
630 .pkt_scan = sd_pkt_scan,
633 /* -- module initialisation -- */
634 #define DVNM(name) .driver_info = (kernel_ulong_t) name
635 static const __devinitdata struct usb_device_id device_table[] = {
636 {USB_DEVICE(0x041e, 0x4028), DVNM("Creative Webcam Vista Plus")},
637 {USB_DEVICE(0x093a, 0x2460), DVNM("Q-Tec Webcam 100")},
638 {USB_DEVICE(0x093a, 0x2463), DVNM("Philips spc200nc pac207")},
639 {USB_DEVICE(0x093a, 0x2464), DVNM("Labtec Webcam 1200")},
640 {USB_DEVICE(0x093a, 0x2468), DVNM("PAC207")},
641 {USB_DEVICE(0x093a, 0x2470), DVNM("Genius GF112")},
642 {USB_DEVICE(0x093a, 0x2471), DVNM("Genius VideoCam GE111")},
643 {USB_DEVICE(0x093a, 0x2472), DVNM("Genius VideoCam GE110")},
644 {USB_DEVICE(0x2001, 0xf115), DVNM("D-Link DSB-C120")},
647 MODULE_DEVICE_TABLE(usb, device_table);
649 /* -- device connect -- */
650 static int sd_probe(struct usb_interface *intf,
651 const struct usb_device_id *id)
653 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
657 static struct usb_driver sd_driver = {
659 .id_table = device_table,
661 .disconnect = gspca_disconnect,
664 /* -- module insert / remove -- */
665 static int __init sd_mod_init(void)
667 if (usb_register(&sd_driver) < 0)
669 PDEBUG(D_PROBE, "v%s registered", version);
672 static void __exit sd_mod_exit(void)
674 usb_deregister(&sd_driver);
675 PDEBUG(D_PROBE, "deregistered");
678 module_init(sd_mod_init);
679 module_exit(sd_mod_exit);