V4L/DVB (8156): Many bug fixes, zc3xx added.
[firewire-audio.git] / drivers / media / video / gspca / pac207.c
blob482ef4a6afc0ff014f669407c774726f7091a6e4
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 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 2, 15)
31 static const char version[] = "0.2.15";
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 #define PAC207_EXPOSURE_MIN 4
44 #define PAC207_EXPOSURE_MAX 26
45 #define PAC207_EXPOSURE_DEFAULT 4 /* power on default: 3 ?? */
46 #define PAC207_EXPOSURE_KNEE 11 /* 4 = 30 fps, 11 = 8, 15 = 6 */
48 #define PAC207_GAIN_MIN 0
49 #define PAC207_GAIN_MAX 31
50 #define PAC207_GAIN_DEFAULT 9 /* power on default: 9 */
51 #define PAC207_GAIN_KNEE 20
53 #define PAC207_AUTOGAIN_DEADZONE 30
54 /* We calculating the autogain at the end of the transfer of a frame, at this
55 moment a frame with the old settings is being transmitted, and a frame is
56 being captured with the old settings. So if we adjust the autogain we must
57 ignore atleast the 2 next frames for the new settings to come into effect
58 before doing any other adjustments */
59 #define PAC207_AUTOGAIN_IGNORE_FRAMES 3
61 enum pac207_line_state {
62 LINE_HEADER1,
63 LINE_HEADER2,
64 LINE_UNCOMPRESSED,
65 LINE_COMPRESSED,
68 struct pac207_decoder_state {
69 /* generic state */
70 u16 line_read;
71 u16 line_marker;
72 u8 line_state;
73 u8 header_read;
74 /* compression state */
75 u16 processed_bytes;
76 u8 remaining_bits;
77 s8 no_remaining_bits;
78 u8 get_abs;
79 u8 discard_byte;
80 u8 line_decode_buf[352];
83 /* specific webcam descriptor */
84 struct sd {
85 struct gspca_dev gspca_dev; /* !! must be the first item */
87 struct pac207_decoder_state decoder_state;
89 u8 mode;
91 u8 brightness;
92 u8 exposure;
93 u8 autogain;
94 u8 gain;
96 u8 sof_read;
97 u8 autogain_ignore_frames;
99 atomic_t avg_lum;
102 /* V4L2 controls supported by the driver */
103 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
104 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
105 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
106 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
107 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
108 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
109 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
110 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
112 static struct ctrl sd_ctrls[] = {
113 #define SD_BRIGHTNESS 0
116 .id = V4L2_CID_BRIGHTNESS,
117 .type = V4L2_CTRL_TYPE_INTEGER,
118 .name = "Brightness",
119 .minimum = PAC207_BRIGHTNESS_MIN,
120 .maximum = PAC207_BRIGHTNESS_MAX,
121 .step = 1,
122 .default_value = PAC207_BRIGHTNESS_DEFAULT,
123 .flags = 0,
125 .set = sd_setbrightness,
126 .get = sd_getbrightness,
128 #define SD_EXPOSURE 1
131 .id = V4L2_CID_EXPOSURE,
132 .type = V4L2_CTRL_TYPE_INTEGER,
133 .name = "exposure",
134 .minimum = PAC207_EXPOSURE_MIN,
135 .maximum = PAC207_EXPOSURE_MAX,
136 .step = 1,
137 .default_value = PAC207_EXPOSURE_DEFAULT,
138 .flags = 0,
140 .set = sd_setexposure,
141 .get = sd_getexposure,
143 #define SD_AUTOGAIN 2
146 .id = V4L2_CID_AUTOGAIN,
147 .type = V4L2_CTRL_TYPE_BOOLEAN,
148 .name = "Auto Gain",
149 .minimum = 0,
150 .maximum = 1,
151 .step = 1,
152 .default_value = 1,
153 .flags = 0,
155 .set = sd_setautogain,
156 .get = sd_getautogain,
158 #define SD_GAIN 3
161 .id = V4L2_CID_GAIN,
162 .type = V4L2_CTRL_TYPE_INTEGER,
163 .name = "gain",
164 .minimum = PAC207_GAIN_MIN,
165 .maximum = PAC207_GAIN_MAX,
166 .step = 1,
167 .default_value = PAC207_GAIN_DEFAULT,
168 .flags = 0,
170 .set = sd_setgain,
171 .get = sd_getgain,
175 static struct cam_mode sif_mode[] = {
176 {V4L2_PIX_FMT_SBGGR8, 176, 144, 1},
177 {V4L2_PIX_FMT_SBGGR8, 352, 288, 0},
180 static const __u8 pac207_sensor_init[][8] = {
181 {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0},
182 {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
183 {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
184 {0x00, 0x00, 0x32, 0x00, 0x96, 0x00, 0xa2, 0x02},
185 {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00},
188 /* 48 reg_72 Rate Control end BalSize_4a =0x36 */
189 static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 };
191 static const unsigned char pac207_sof_marker[5] =
192 { 0xff, 0xff, 0x00, 0xff, 0x96 };
194 int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
195 const u8 *buffer, u16 length)
197 struct usb_device *udev = gspca_dev->dev;
198 int err;
199 u8 kbuf[8];
201 memcpy(kbuf, buffer, length);
203 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
204 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
205 0x00, index, kbuf, length, PAC207_CTRL_TIMEOUT);
206 if (err < 0)
207 PDEBUG(D_ERR,
208 "Failed to write registers to index 0x%04X, error %d)",
209 index, err);
211 return err;
215 int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
217 struct usb_device *udev = gspca_dev->dev;
218 int err;
220 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
221 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
222 value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
223 if (err)
224 PDEBUG(D_ERR, "Failed to write a register (index 0x%04X,"
225 " value 0x%02X, error %d)", index, value, err);
227 return err;
231 int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
233 struct usb_device *udev = gspca_dev->dev;
234 u8 buff;
235 int res;
237 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
238 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
239 0x00, index, &buff, 1, PAC207_CTRL_TIMEOUT);
240 if (res < 0) {
241 PDEBUG(D_ERR,
242 "Failed to read a register (index 0x%04X, error %d)",
243 index, res);
244 return res;
247 return buff;
251 /* this function is called at probe time */
252 static int sd_config(struct gspca_dev *gspca_dev,
253 const struct usb_device_id *id)
255 struct sd *sd = (struct sd *) gspca_dev;
256 struct cam *cam;
257 u8 idreg[2];
259 idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
260 idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
261 idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4);
262 idreg[1] = idreg[1] & 0x0f;
263 PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
264 idreg[0], idreg[1]);
266 if (idreg[0] != 0x27) {
267 PDEBUG(D_PROBE, "Error invalid sensor ID!");
268 return -ENODEV;
271 pac207_write_reg(gspca_dev, 0x41, 0x00);
272 /* Bit_0=Image Format,
273 * Bit_1=LED,
274 * Bit_2=Compression test mode enable */
275 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
276 pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
278 PDEBUG(D_PROBE,
279 "Pixart PAC207BCA Image Processor and Control Chip detected"
280 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
282 cam = &gspca_dev->cam;
283 cam->dev_name = (char *) id->driver_info;
284 cam->epaddr = 0x05;
285 cam->cam_mode = sif_mode;
286 cam->nmodes = ARRAY_SIZE(sif_mode);
287 sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
288 sd->exposure = PAC207_EXPOSURE_DEFAULT;
289 sd->gain = PAC207_GAIN_DEFAULT;
291 return 0;
294 /* this function is called at open time */
295 static int sd_open(struct gspca_dev *gspca_dev)
297 struct sd *sd = (struct sd *) gspca_dev;
299 sd->autogain = 1;
301 return 0;
304 /* -- start the camera -- */
305 static void sd_start(struct gspca_dev *gspca_dev)
307 struct sd *sd = (struct sd *) gspca_dev;
308 __u8 mode;
310 pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
311 pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
312 pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
313 pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
314 pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8);
315 pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8);
316 pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4);
318 /* Compression Balance */
319 if (gspca_dev->width == 176)
320 pac207_write_reg(gspca_dev, 0x4a, 0xff);
321 else
322 pac207_write_reg(gspca_dev, 0x4a, 0x88);
323 pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
324 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
326 /* PGA global gain (Bit 4-0) */
327 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
328 pac207_write_reg(gspca_dev, 0x02, sd->exposure); /* PXCK = 12MHz /n */
330 mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
331 if (gspca_dev->width == 176) { /* 176x144 */
332 mode |= 0x01;
333 PDEBUG(D_STREAM, "pac207_start mode 176x144");
334 } else { /* 352x288 */
335 PDEBUG(D_STREAM, "pac207_start mode 352x288");
337 pac207_write_reg(gspca_dev, 0x41, mode);
339 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
340 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
341 udelay(1000); /* taken from gspca */
342 pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
344 sd->sof_read = 0;
345 sd->autogain_ignore_frames = 0;
346 atomic_set(&sd->avg_lum, -1);
349 static void sd_stopN(struct gspca_dev *gspca_dev)
351 pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
352 pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
353 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
356 static void sd_stop0(struct gspca_dev *gspca_dev)
360 /* this function is called at close time */
361 static void sd_close(struct gspca_dev *gspca_dev)
365 /* -- convert pixart frames to Bayer -- */
366 /* Sonix decompressor struct B.S.(2004) */
367 static struct {
368 u8 is_abs;
369 u8 len;
370 s8 val;
371 } table[256];
373 void init_pixart_decoder(void)
375 int i, is_abs, val, len;
377 for (i = 0; i < 256; i++) {
378 is_abs = 0;
379 val = 0;
380 len = 0;
381 if ((i & 0xC0) == 0) {
382 /* code 00 */
383 val = 0;
384 len = 2;
385 } else if ((i & 0xC0) == 0x40) {
386 /* code 01 */
387 val = -5;
388 len = 2;
389 } else if ((i & 0xC0) == 0x80) {
390 /* code 10 */
391 val = 5;
392 len = 2;
393 } else if ((i & 0xF0) == 0xC0) {
394 /* code 1100 */
395 val = -10;
396 len = 4;
397 } else if ((i & 0xF0) == 0xD0) {
398 /* code 1101 */
399 val = 10;
400 len = 4;
401 } else if ((i & 0xF8) == 0xE0) {
402 /* code 11100 */
403 val = -15;
404 len = 5;
405 } else if ((i & 0xF8) == 0xE8) {
406 /* code 11101 */
407 val = 15;
408 len = 5;
409 } else if ((i & 0xFC) == 0xF0) {
410 /* code 111100 */
411 val = -20;
412 len = 6;
413 } else if ((i & 0xFC) == 0xF4) {
414 /* code 111101 */
415 val = 20;
416 len = 6;
417 } else if ((i & 0xF8) == 0xF8) {
418 /* code 11111xxxxxx */
419 is_abs = 1;
420 val = 0;
421 len = 5;
423 table[i].is_abs = is_abs;
424 table[i].val = val;
425 table[i].len = len;
429 /* auto gain and exposure algorithm based on the knee algorithm described here:
430 * <http://ytse.tricolour.net/docs/LowLightOptimization.html> */
431 static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
433 struct sd *sd = (struct sd *) gspca_dev;
434 int i, steps, desired_avg_lum;
435 int orig_gain = sd->gain;
436 int orig_exposure = sd->exposure;
437 int avg_lum = atomic_read(&sd->avg_lum);
439 if (!sd->autogain || avg_lum == -1)
440 return;
442 if (sd->autogain_ignore_frames > 0) {
443 sd->autogain_ignore_frames--;
444 return;
447 /* correct desired lumination for the configured brightness */
448 desired_avg_lum = 100 + sd->brightness / 2;
450 /* If we are of a multiple of deadzone, do multiple step to reach the
451 desired lumination fast (with the risc of a slight overshoot) */
452 steps = abs(desired_avg_lum - avg_lum) / PAC207_AUTOGAIN_DEADZONE;
454 for (i = 0; i < steps; i++) {
455 if (avg_lum > desired_avg_lum) {
456 if (sd->gain > PAC207_GAIN_KNEE) {
457 sd->gain--;
458 } else if (sd->exposure > PAC207_EXPOSURE_KNEE) {
459 sd->exposure--;
460 } else if (sd->gain > PAC207_GAIN_DEFAULT) {
461 sd->gain--;
462 } else if (sd->exposure > PAC207_EXPOSURE_MIN) {
463 sd->exposure--;
464 } else if (sd->gain > PAC207_GAIN_MIN) {
465 sd->gain--;
466 } else
467 break;
468 } else {
469 if (sd->gain < PAC207_GAIN_DEFAULT) {
470 sd->gain++;
471 } else if (sd->exposure < PAC207_EXPOSURE_KNEE) {
472 sd->exposure++;
473 } else if (sd->gain < PAC207_GAIN_KNEE) {
474 sd->gain++;
475 } else if (sd->exposure < PAC207_EXPOSURE_MAX) {
476 sd->exposure++;
477 } else if (sd->gain < PAC207_GAIN_MAX) {
478 sd->gain++;
479 } else
480 break;
484 if (sd->exposure != orig_exposure || sd->gain != orig_gain) {
485 if (sd->exposure != orig_exposure)
486 pac207_write_reg(gspca_dev, 0x0002, sd->exposure);
487 if (sd->gain != orig_gain)
488 pac207_write_reg(gspca_dev, 0x000e, sd->gain);
489 pac207_write_reg(gspca_dev, 0x13, 0x01); /* load reg to sen */
490 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
491 sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
495 static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
496 unsigned char *m, int len)
498 struct sd *sd = (struct sd *) gspca_dev;
499 int i;
501 /* Search for the SOF marker (fixed part) in the header */
502 for (i = 0; i < len; i++) {
503 if (m[i] == pac207_sof_marker[sd->sof_read]) {
504 sd->sof_read++;
505 if (sd->sof_read == sizeof(pac207_sof_marker)) {
506 PDEBUG(D_STREAM,
507 "SOF found, bytes to analyze: %u."
508 " Frame starts at byte #%u",
509 len, i + 1);
510 sd->sof_read = 0;
511 return m + i + 1;
513 } else {
514 sd->sof_read = 0;
518 return NULL;
521 static int pac207_decompress_row(struct gspca_dev *gspca_dev,
522 struct gspca_frame *f, unsigned char *cdata, int len)
524 struct sd *sd = (struct sd *) gspca_dev;
525 struct pac207_decoder_state *decoder_state = &sd->decoder_state;
526 unsigned char *outp = decoder_state->line_decode_buf +
527 decoder_state->line_read;
528 int val, bitlen, bitpos = -decoder_state->no_remaining_bits;
529 u8 code;
531 /* first two pixels are stored as raw 8-bit */
532 while (decoder_state->line_read < 2) {
533 *outp++ = *cdata++;
534 decoder_state->line_read++;
535 len--;
536 if (len == 0)
537 return 0;
540 while (decoder_state->line_read < gspca_dev->width) {
541 if (bitpos < 0) {
542 code = decoder_state->remaining_bits << (8 + bitpos) |
543 cdata[0] >> -bitpos;
544 } else {
545 u8 *addr = cdata + bitpos / 8;
546 code = addr[0] << (bitpos & 7) |
547 addr[1] >> (8 - (bitpos & 7));
550 bitlen = decoder_state->get_abs ?
551 6 : table[code].len;
553 /* Stop decompressing if we're out of input data */
554 if ((bitpos + bitlen) > (len * 8))
555 break;
557 if (decoder_state->get_abs) {
558 *outp++ = code & 0xFC;
559 decoder_state->line_read++;
560 decoder_state->get_abs = 0;
561 } else {
562 if (table[code].is_abs) {
563 decoder_state->get_abs = 1;
564 } else {
565 /* relative to left pixel */
566 val = outp[-2] +
567 table[code].val;
568 if (val > 0xff)
569 val = 0xff;
570 else if (val < 0)
571 val = 0;
572 *outp++ = val;
573 decoder_state->line_read++;
576 bitpos += bitlen;
579 if (decoder_state->line_read == gspca_dev->width) {
580 int compressed_line_len;
582 gspca_frame_add(gspca_dev, INTER_PACKET, f,
583 decoder_state->line_decode_buf,
584 gspca_dev->width);
586 /* completely decompressed line, round pos to nearest word */
587 compressed_line_len = ((decoder_state->processed_bytes * 8 +
588 bitpos + 15) / 16) * 2;
590 len -= compressed_line_len - decoder_state->processed_bytes;
591 if (len < 0) {
592 decoder_state->discard_byte = 1;
593 len = 0;
595 } else {
596 decoder_state->processed_bytes += len;
597 decoder_state->remaining_bits = cdata[bitpos/8];
598 decoder_state->no_remaining_bits = (8 - bitpos) & 7;
599 len = 0;
602 return len;
605 static void pac207_decode_line_init(struct gspca_dev *gspca_dev)
607 struct sd *sd = (struct sd *) gspca_dev;
608 struct pac207_decoder_state *decoder_state = &sd->decoder_state;
610 decoder_state->line_read = 0;
611 decoder_state->line_state = LINE_HEADER1;
612 decoder_state->processed_bytes = 0;
613 decoder_state->no_remaining_bits = 0;
614 decoder_state->get_abs = 0;
617 static void pac207_decode_frame_init(struct gspca_dev *gspca_dev)
619 struct sd *sd = (struct sd *) gspca_dev;
620 struct pac207_decoder_state *decoder_state = &sd->decoder_state;
622 decoder_state->header_read = 0;
623 decoder_state->discard_byte = 0;
625 pac207_decode_line_init(gspca_dev);
628 static int pac207_decode_frame_data(struct gspca_dev *gspca_dev,
629 struct gspca_frame *f, unsigned char *data, int len)
631 struct sd *sd = (struct sd *) gspca_dev;
632 struct pac207_decoder_state *decoder_state = &sd->decoder_state;
633 int needed = 0;
635 /* first 11 bytes after sof marker: frame header */
636 if (decoder_state->header_read < 11) {
637 /* get average lumination from frame header (byte 5) */
638 if (decoder_state->header_read < 5) {
639 needed = 5 - decoder_state->header_read;
640 if (len >= needed)
641 atomic_set(&sd->avg_lum, data[needed-1]);
643 /* skip the rest of the header */
644 needed = 11 - decoder_state->header_read;
645 if (len <= needed) {
646 decoder_state->header_read += len;
647 return 0;
649 data += needed;
650 len -= needed;
651 decoder_state->header_read = 11;
654 while (len) {
655 if (decoder_state->discard_byte) {
656 data++;
657 len--;
658 decoder_state->discard_byte = 0;
659 continue;
662 switch (decoder_state->line_state) {
663 case LINE_HEADER1:
664 decoder_state->line_marker = data[0] << 8;
665 decoder_state->line_state = LINE_HEADER2;
666 needed = 1;
667 break;
668 case LINE_HEADER2:
669 decoder_state->line_marker |= data[0];
670 switch (decoder_state->line_marker) {
671 case 0x0FF0:
672 decoder_state->line_state = LINE_UNCOMPRESSED;
673 break;
674 case 0x1EE1:
675 decoder_state->line_state = LINE_COMPRESSED;
676 break;
677 default:
678 PDEBUG(D_STREAM,
679 "Error unknown line-header %04X",
680 (int) decoder_state->line_marker);
681 gspca_dev->last_packet_type = DISCARD_PACKET;
682 return 0;
684 needed = 1;
685 break;
686 case LINE_UNCOMPRESSED:
687 needed = gspca_dev->width - decoder_state->line_read;
688 if (needed > len)
689 needed = len;
690 gspca_frame_add(gspca_dev, INTER_PACKET, f, data,
691 needed);
692 decoder_state->line_read += needed;
693 break;
694 case LINE_COMPRESSED:
695 needed = len -
696 pac207_decompress_row(gspca_dev, f, data, len);
697 break;
700 data += needed;
701 len -= needed;
703 if (decoder_state->line_read == gspca_dev->width) {
704 if ((f->data_end - f->data) ==
705 (gspca_dev->width * gspca_dev->height)) {
706 /* eureka we've got a frame */
707 return 1;
709 pac207_decode_line_init(gspca_dev);
713 return 0;
716 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
717 struct gspca_frame *frame,
718 unsigned char *data,
719 int len)
721 unsigned char *sof;
722 int n;
724 sof = pac207_find_sof(gspca_dev, data, len);
726 if (sof) {
727 /* finish decoding current frame */
728 if (gspca_dev->last_packet_type == INTER_PACKET) {
729 n = sof - data;
730 if (n > sizeof(pac207_sof_marker))
731 n -= sizeof(pac207_sof_marker);
732 else
733 n = 0;
734 n = pac207_decode_frame_data(gspca_dev, frame,
735 data, n);
736 if (n)
737 frame = gspca_frame_add(gspca_dev,
738 LAST_PACKET,
739 frame,
740 NULL,
742 else
743 PDEBUG(D_STREAM, "Incomplete frame");
745 pac207_decode_frame_init(gspca_dev);
746 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL,
748 len -= sof - data;
749 data = sof;
752 if (gspca_dev->last_packet_type == DISCARD_PACKET)
753 return;
755 n = pac207_decode_frame_data(gspca_dev, frame, data, len);
756 if (n)
757 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
758 frame, NULL, 0);
761 static void setbrightness(struct gspca_dev *gspca_dev)
763 struct sd *sd = (struct sd *) gspca_dev;
765 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
766 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
767 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
770 static void setexposure(struct gspca_dev *gspca_dev)
772 struct sd *sd = (struct sd *) gspca_dev;
774 pac207_write_reg(gspca_dev, 0x02, sd->exposure);
775 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
776 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
779 static void setgain(struct gspca_dev *gspca_dev)
781 struct sd *sd = (struct sd *) gspca_dev;
783 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
784 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
785 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
788 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
790 struct sd *sd = (struct sd *) gspca_dev;
792 sd->brightness = val;
793 if (gspca_dev->streaming)
794 setbrightness(gspca_dev);
795 return 0;
798 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
800 struct sd *sd = (struct sd *) gspca_dev;
802 *val = sd->brightness;
803 return 0;
806 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
808 struct sd *sd = (struct sd *) gspca_dev;
810 /* don't allow mucking with exposure when using autogain */
811 if (sd->autogain)
812 return -EINVAL;
814 sd->exposure = val;
815 if (gspca_dev->streaming)
816 setexposure(gspca_dev);
817 return 0;
820 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
822 struct sd *sd = (struct sd *) gspca_dev;
824 *val = sd->exposure;
825 return 0;
828 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
830 struct sd *sd = (struct sd *) gspca_dev;
832 /* don't allow mucking with gain when using autogain */
833 if (sd->autogain)
834 return -EINVAL;
836 sd->gain = val;
837 if (gspca_dev->streaming)
838 setgain(gspca_dev);
839 return 0;
842 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
844 struct sd *sd = (struct sd *) gspca_dev;
846 *val = sd->gain;
847 return 0;
850 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
852 struct sd *sd = (struct sd *) gspca_dev;
854 sd->autogain = val;
855 /* when switching to autogain set defaults to make sure
856 we are on a valid point of the autogain gain /
857 exposure knee graph, and give this change time to
858 take effect before doing autogain. */
859 if (sd->autogain) {
860 sd->exposure = PAC207_EXPOSURE_DEFAULT;
861 sd->gain = PAC207_GAIN_DEFAULT;
862 if (gspca_dev->streaming) {
863 sd->autogain_ignore_frames =
864 PAC207_AUTOGAIN_IGNORE_FRAMES;
865 setexposure(gspca_dev);
866 setgain(gspca_dev);
870 return 0;
873 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
875 struct sd *sd = (struct sd *) gspca_dev;
877 *val = sd->autogain;
878 return 0;
881 /* sub-driver description */
882 static struct sd_desc sd_desc = {
883 .name = MODULE_NAME,
884 .ctrls = sd_ctrls,
885 .nctrls = ARRAY_SIZE(sd_ctrls),
886 .config = sd_config,
887 .open = sd_open,
888 .start = sd_start,
889 .stopN = sd_stopN,
890 .stop0 = sd_stop0,
891 .close = sd_close,
892 .dq_callback = pac207_do_auto_gain,
893 .pkt_scan = sd_pkt_scan,
896 /* -- module initialisation -- */
897 #define DVNM(name) .driver_info = (kernel_ulong_t) name
898 static __devinitdata struct usb_device_id device_table[] = {
899 {USB_DEVICE(0x041e, 0x4028), DVNM("Creative Webcam Vista Plus")},
900 {USB_DEVICE(0x093a, 0x2460), DVNM("Q-Tec Webcam 100")},
901 {USB_DEVICE(0x093a, 0x2463), DVNM("Philips spc200nc pac207")},
902 {USB_DEVICE(0x093a, 0x2464), DVNM("Labtec Webcam 1200")},
903 {USB_DEVICE(0x093a, 0x2468), DVNM("PAC207")},
904 {USB_DEVICE(0x093a, 0x2470), DVNM("Genius GF112")},
905 {USB_DEVICE(0x093a, 0x2471), DVNM("Genius VideoCam GE111")},
906 {USB_DEVICE(0x093a, 0x2472), DVNM("Genius VideoCam GE110")},
907 {USB_DEVICE(0x2001, 0xf115), DVNM("D-Link DSB-C120")},
910 MODULE_DEVICE_TABLE(usb, device_table);
912 /* -- device connect -- */
913 static int sd_probe(struct usb_interface *intf,
914 const struct usb_device_id *id)
916 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
917 THIS_MODULE);
920 static struct usb_driver sd_driver = {
921 .name = MODULE_NAME,
922 .id_table = device_table,
923 .probe = sd_probe,
924 .disconnect = gspca_disconnect,
927 /* -- module insert / remove -- */
928 static int __init sd_mod_init(void)
930 init_pixart_decoder();
931 if (usb_register(&sd_driver) < 0)
932 return -1;
933 PDEBUG(D_PROBE, "v%s registered", version);
934 return 0;
936 static void __exit sd_mod_exit(void)
938 usb_deregister(&sd_driver);
939 PDEBUG(D_PROBE, "deregistered");
942 module_init(sd_mod_init);
943 module_exit(sd_mod_exit);