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;
275 cam->cam_mode = sif_mode;
276 cam->nmodes = ARRAY_SIZE(sif_mode);
277 sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
278 sd->exposure = PAC207_EXPOSURE_DEFAULT;
279 sd->gain = PAC207_GAIN_DEFAULT;
284 /* this function is called at open time */
285 static int sd_open(struct gspca_dev *gspca_dev)
287 struct sd *sd = (struct sd *) gspca_dev;
293 /* -- start the camera -- */
294 static void sd_start(struct gspca_dev *gspca_dev)
296 struct sd *sd = (struct sd *) gspca_dev;
299 pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
300 pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
301 pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
302 pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
303 pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8);
304 pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8);
305 pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4);
307 /* Compression Balance */
308 if (gspca_dev->width == 176)
309 pac207_write_reg(gspca_dev, 0x4a, 0xff);
311 pac207_write_reg(gspca_dev, 0x4a, 0x88);
312 pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
313 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
315 /* PGA global gain (Bit 4-0) */
316 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
317 pac207_write_reg(gspca_dev, 0x02, sd->exposure); /* PXCK = 12MHz /n */
319 mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
320 if (gspca_dev->width == 176) { /* 176x144 */
322 PDEBUG(D_STREAM, "pac207_start mode 176x144");
323 } else { /* 352x288 */
324 PDEBUG(D_STREAM, "pac207_start mode 352x288");
326 pac207_write_reg(gspca_dev, 0x41, mode);
328 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
329 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
331 pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
334 sd->autogain_ignore_frames = 0;
335 atomic_set(&sd->avg_lum, -1);
338 static void sd_stopN(struct gspca_dev *gspca_dev)
340 pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
341 pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
342 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
345 static void sd_stop0(struct gspca_dev *gspca_dev)
349 /* this function is called at close time */
350 static void sd_close(struct gspca_dev *gspca_dev)
354 static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
356 struct sd *sd = (struct sd *) gspca_dev;
357 int avg_lum = atomic_read(&sd->avg_lum);
362 if (sd->autogain_ignore_frames > 0)
363 sd->autogain_ignore_frames--;
364 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
365 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE,
366 PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
367 sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
370 static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
371 unsigned char *m, int len)
373 struct sd *sd = (struct sd *) gspca_dev;
376 /* Search for the SOF marker (fixed part) in the header */
377 for (i = 0; i < len; i++) {
378 if (m[i] == pac207_sof_marker[sd->sof_read]) {
380 if (sd->sof_read == sizeof(pac207_sof_marker)) {
382 "SOF found, bytes to analyze: %u."
383 " Frame starts at byte #%u",
396 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
397 struct gspca_frame *frame,
401 struct sd *sd = (struct sd *) gspca_dev;
404 sof = pac207_find_sof(gspca_dev, data, len);
408 /* finish decoding current frame */
410 if (n > sizeof pac207_sof_marker)
411 n -= sizeof pac207_sof_marker;
414 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
417 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
421 if (sd->header_read < 11) {
424 /* get average lumination from frame header (byte 5) */
425 if (sd->header_read < 5) {
426 needed = 5 - sd->header_read;
428 atomic_set(&sd->avg_lum, data[needed - 1]);
430 /* skip the rest of the header */
431 needed = 11 - sd->header_read;
433 sd->header_read += len;
438 sd->header_read = 11;
441 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
444 static void setbrightness(struct gspca_dev *gspca_dev)
446 struct sd *sd = (struct sd *) gspca_dev;
448 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
449 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
450 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
453 static void setexposure(struct gspca_dev *gspca_dev)
455 struct sd *sd = (struct sd *) gspca_dev;
457 pac207_write_reg(gspca_dev, 0x02, sd->exposure);
458 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
459 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
462 static void setgain(struct gspca_dev *gspca_dev)
464 struct sd *sd = (struct sd *) gspca_dev;
466 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
467 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
468 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
471 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
473 struct sd *sd = (struct sd *) gspca_dev;
475 sd->brightness = val;
476 if (gspca_dev->streaming)
477 setbrightness(gspca_dev);
481 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
483 struct sd *sd = (struct sd *) gspca_dev;
485 *val = sd->brightness;
489 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
491 struct sd *sd = (struct sd *) gspca_dev;
494 if (gspca_dev->streaming)
495 setexposure(gspca_dev);
499 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
501 struct sd *sd = (struct sd *) gspca_dev;
507 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
509 struct sd *sd = (struct sd *) gspca_dev;
512 if (gspca_dev->streaming)
517 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
519 struct sd *sd = (struct sd *) gspca_dev;
525 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
527 struct sd *sd = (struct sd *) gspca_dev;
530 /* when switching to autogain set defaults to make sure
531 we are on a valid point of the autogain gain /
532 exposure knee graph, and give this change time to
533 take effect before doing autogain. */
535 sd->exposure = PAC207_EXPOSURE_DEFAULT;
536 sd->gain = PAC207_GAIN_DEFAULT;
537 if (gspca_dev->streaming) {
538 sd->autogain_ignore_frames =
539 PAC207_AUTOGAIN_IGNORE_FRAMES;
540 setexposure(gspca_dev);
548 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
550 struct sd *sd = (struct sd *) gspca_dev;
556 /* sub-driver description */
557 static const struct sd_desc sd_desc = {
560 .nctrls = ARRAY_SIZE(sd_ctrls),
567 .dq_callback = pac207_do_auto_gain,
568 .pkt_scan = sd_pkt_scan,
571 /* -- module initialisation -- */
572 static const __devinitdata struct usb_device_id device_table[] = {
573 {USB_DEVICE(0x041e, 0x4028)},
574 {USB_DEVICE(0x093a, 0x2460)},
575 {USB_DEVICE(0x093a, 0x2463)},
576 {USB_DEVICE(0x093a, 0x2464)},
577 {USB_DEVICE(0x093a, 0x2468)},
578 {USB_DEVICE(0x093a, 0x2470)},
579 {USB_DEVICE(0x093a, 0x2471)},
580 {USB_DEVICE(0x093a, 0x2472)},
581 {USB_DEVICE(0x2001, 0xf115)},
584 MODULE_DEVICE_TABLE(usb, device_table);
586 /* -- device connect -- */
587 static int sd_probe(struct usb_interface *intf,
588 const struct usb_device_id *id)
590 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
594 static struct usb_driver sd_driver = {
596 .id_table = device_table,
598 .disconnect = gspca_disconnect,
600 .suspend = gspca_suspend,
601 .resume = gspca_resume,
605 /* -- module insert / remove -- */
606 static int __init sd_mod_init(void)
608 if (usb_register(&sd_driver) < 0)
610 PDEBUG(D_PROBE, "registered");
613 static void __exit sd_mod_exit(void)
615 usb_deregister(&sd_driver);
616 PDEBUG(D_PROBE, "deregistered");
619 module_init(sd_mod_init);
620 module_exit(sd_mod_exit);