V4L/DVB (8440): gspca: Makes some needlessly global functions static.
[linux-2.6/kvm.git] / drivers / media / video / gspca / pac207.c
blobf790746370d7344c38d6c81e51f760819b6467db
1 /*
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"
28 #include "gspca.h"
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 */
67 struct sd {
68 struct gspca_dev gspca_dev; /* !! must be the first item */
70 u8 mode;
72 u8 brightness;
73 u8 exposure;
74 u8 autogain;
75 u8 gain;
77 u8 sof_read;
78 u8 header_read;
79 u8 autogain_ignore_frames;
81 atomic_t avg_lum;
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,
103 .step = 1,
104 .default_value = PAC207_BRIGHTNESS_DEFAULT,
105 .flags = 0,
107 .set = sd_setbrightness,
108 .get = sd_getbrightness,
110 #define SD_EXPOSURE 1
113 .id = V4L2_CID_EXPOSURE,
114 .type = V4L2_CTRL_TYPE_INTEGER,
115 .name = "exposure",
116 .minimum = PAC207_EXPOSURE_MIN,
117 .maximum = PAC207_EXPOSURE_MAX,
118 .step = 1,
119 .default_value = PAC207_EXPOSURE_DEFAULT,
120 .flags = 0,
122 .set = sd_setexposure,
123 .get = sd_getexposure,
125 #define SD_AUTOGAIN 2
128 .id = V4L2_CID_AUTOGAIN,
129 .type = V4L2_CTRL_TYPE_BOOLEAN,
130 .name = "Auto Gain",
131 .minimum = 0,
132 .maximum = 1,
133 .step = 1,
134 .default_value = 1,
135 .flags = 0,
137 .set = sd_setautogain,
138 .get = sd_getautogain,
140 #define SD_GAIN 3
143 .id = V4L2_CID_GAIN,
144 .type = V4L2_CTRL_TYPE_INTEGER,
145 .name = "gain",
146 .minimum = PAC207_GAIN_MIN,
147 .maximum = PAC207_GAIN_MAX,
148 .step = 1,
149 .default_value = PAC207_GAIN_DEFAULT,
150 .flags = 0,
152 .set = sd_setgain,
153 .get = sd_getgain,
157 static struct v4l2_pix_format sif_mode[] = {
158 {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
159 .bytesperline = 176,
160 .sizeimage = (176 + 2) * 144,
161 /* uncompressed, add 2 bytes / line for line header */
162 .colorspace = V4L2_COLORSPACE_SRGB,
163 .priv = 1},
164 {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
165 .bytesperline = 352,
166 /* compressed, but only when needed (not compressed
167 when the framerate is low) */
168 .sizeimage = (352 + 2) * 288,
169 .colorspace = V4L2_COLORSPACE_SRGB,
170 .priv = 0},
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;
191 int err;
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,
197 0x00, index,
198 gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
199 if (err < 0)
200 PDEBUG(D_ERR,
201 "Failed to write registers to index 0x%04X, error %d)",
202 index, err);
204 return err;
208 static int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
210 struct usb_device *udev = gspca_dev->dev;
211 int err;
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);
216 if (err)
217 PDEBUG(D_ERR, "Failed to write a register (index 0x%04X,"
218 " value 0x%02X, error %d)", index, value, err);
220 return err;
223 static int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
225 struct usb_device *udev = gspca_dev->dev;
226 int res;
228 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
229 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
230 0x00, index,
231 gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
232 if (res < 0) {
233 PDEBUG(D_ERR,
234 "Failed to read a register (index 0x%04X, error %d)",
235 index, res);
236 return res;
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;
247 struct cam *cam;
248 u8 idreg[2];
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",
255 idreg[0], idreg[1]);
257 if (idreg[0] != 0x27) {
258 PDEBUG(D_PROBE, "Error invalid sensor ID!");
259 return -ENODEV;
262 pac207_write_reg(gspca_dev, 0x41, 0x00);
263 /* Bit_0=Image Format,
264 * Bit_1=LED,
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 */
269 PDEBUG(D_PROBE,
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;
275 cam->epaddr = 0x05;
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;
282 return 0;
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;
290 sd->autogain = 1;
291 return 0;
294 /* -- start the camera -- */
295 static void sd_start(struct gspca_dev *gspca_dev)
297 struct sd *sd = (struct sd *) gspca_dev;
298 __u8 mode;
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);
311 else
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 */
322 mode |= 0x01;
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 */
331 msleep(10);
332 pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
334 sd->sof_read = 0;
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);
360 if (avg_lum == -1)
361 return;
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;
375 int i;
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]) {
380 sd->sof_read++;
381 if (sd->sof_read == sizeof(pac207_sof_marker)) {
382 PDEBUG(D_STREAM,
383 "SOF found, bytes to analyze: %u."
384 " Frame starts at byte #%u",
385 len, i + 1);
386 sd->sof_read = 0;
387 return m + i + 1;
389 } else {
390 sd->sof_read = 0;
394 return NULL;
397 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
398 struct gspca_frame *frame,
399 __u8 *data,
400 int len)
402 struct sd *sd = (struct sd *) gspca_dev;
403 unsigned char *sof;
405 sof = pac207_find_sof(gspca_dev, data, len);
406 if (sof) {
407 int n;
409 /* finish decoding current frame */
410 n = sof - data;
411 if (n > sizeof pac207_sof_marker)
412 n -= sizeof pac207_sof_marker;
413 else
414 n = 0;
415 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
416 data, n);
417 sd->header_read = 0;
418 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
419 len -= sof - data;
420 data = sof;
422 if (sd->header_read < 11) {
423 int needed;
425 /* get average lumination from frame header (byte 5) */
426 if (sd->header_read < 5) {
427 needed = 5 - sd->header_read;
428 if (len >= needed)
429 atomic_set(&sd->avg_lum, data[needed - 1]);
431 /* skip the rest of the header */
432 needed = 11 - sd->header_read;
433 if (len <= needed) {
434 sd->header_read += len;
435 return;
437 data += needed;
438 len -= needed;
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);
479 return 0;
482 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
484 struct sd *sd = (struct sd *) gspca_dev;
486 *val = sd->brightness;
487 return 0;
490 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
492 struct sd *sd = (struct sd *) gspca_dev;
494 sd->exposure = val;
495 if (gspca_dev->streaming)
496 setexposure(gspca_dev);
497 return 0;
500 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
502 struct sd *sd = (struct sd *) gspca_dev;
504 *val = sd->exposure;
505 return 0;
508 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
510 struct sd *sd = (struct sd *) gspca_dev;
512 sd->gain = val;
513 if (gspca_dev->streaming)
514 setgain(gspca_dev);
515 return 0;
518 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
520 struct sd *sd = (struct sd *) gspca_dev;
522 *val = sd->gain;
523 return 0;
526 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
528 struct sd *sd = (struct sd *) gspca_dev;
530 sd->autogain = val;
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. */
535 if (sd->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);
542 setgain(gspca_dev);
546 return 0;
549 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
551 struct sd *sd = (struct sd *) gspca_dev;
553 *val = sd->autogain;
554 return 0;
557 /* sub-driver description */
558 static const struct sd_desc sd_desc = {
559 .name = MODULE_NAME,
560 .ctrls = sd_ctrls,
561 .nctrls = ARRAY_SIZE(sd_ctrls),
562 .config = sd_config,
563 .open = sd_open,
564 .start = sd_start,
565 .stopN = sd_stopN,
566 .stop0 = sd_stop0,
567 .close = sd_close,
568 .dq_callback = pac207_do_auto_gain,
569 .pkt_scan = sd_pkt_scan,
572 /* -- module initialisation -- */
573 #define DVNM(name) .driver_info = (kernel_ulong_t) name
574 static const __devinitdata struct usb_device_id device_table[] = {
575 {USB_DEVICE(0x041e, 0x4028), DVNM("Creative Webcam Vista Plus")},
576 {USB_DEVICE(0x093a, 0x2460), DVNM("Q-Tec Webcam 100")},
577 {USB_DEVICE(0x093a, 0x2463), DVNM("Philips spc200nc pac207")},
578 {USB_DEVICE(0x093a, 0x2464), DVNM("Labtec Webcam 1200")},
579 {USB_DEVICE(0x093a, 0x2468), DVNM("PAC207")},
580 {USB_DEVICE(0x093a, 0x2470), DVNM("Genius GF112")},
581 {USB_DEVICE(0x093a, 0x2471), DVNM("Genius VideoCam GE111")},
582 {USB_DEVICE(0x093a, 0x2472), DVNM("Genius VideoCam GE110")},
583 {USB_DEVICE(0x2001, 0xf115), DVNM("D-Link DSB-C120")},
586 MODULE_DEVICE_TABLE(usb, device_table);
588 /* -- device connect -- */
589 static int sd_probe(struct usb_interface *intf,
590 const struct usb_device_id *id)
592 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
593 THIS_MODULE);
596 static struct usb_driver sd_driver = {
597 .name = MODULE_NAME,
598 .id_table = device_table,
599 .probe = sd_probe,
600 .disconnect = gspca_disconnect,
603 /* -- module insert / remove -- */
604 static int __init sd_mod_init(void)
606 if (usb_register(&sd_driver) < 0)
607 return -1;
608 PDEBUG(D_PROBE, "registered");
609 return 0;
611 static void __exit sd_mod_exit(void)
613 usb_deregister(&sd_driver);
614 PDEBUG(D_PROBE, "deregistered");
617 module_init(sd_mod_init);
618 module_exit(sd_mod_exit);