blob: 57d48f51e3a0a7adc47a6cca45bc7f6037777a9a [file] [log] [blame]
Hans de Goedee2997a72008-04-23 08:09:12 -03001/*
2 * Pixart PAC207BCA library
3 *
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
7 *
8 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
9 *
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.
14 *
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.
19 *
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
23 *
24 */
25
26#define MODULE_NAME "pac207"
27
28#include "gspca.h"
29
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -030030#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 1)
31static const char version[] = "0.1.1";
Hans de Goedee2997a72008-04-23 08:09:12 -030032
33MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
34MODULE_DESCRIPTION("Pixart PAC207");
35MODULE_LICENSE("GPL");
36
37#define PAC207_CTRL_TIMEOUT 100 /* ms */
38
39#define PAC207_BRIGHTNESS_MIN 0
40#define PAC207_BRIGHTNESS_MAX 255
41#define PAC207_BRIGHTNESS_DEFAULT 4 /* power on default: 4 */
42
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 */
47
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
52
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
60
61enum pac207_line_state {
62 LINE_HEADER1,
63 LINE_HEADER2,
64 LINE_UNCOMPRESSED,
65 LINE_COMPRESSED,
66};
67
68struct 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];
81};
82
83/* specific webcam descriptor */
84struct sd {
85 struct gspca_dev gspca_dev; /* !! must be the first item */
86
87 struct pac207_decoder_state decoder_state;
88
89 u8 mode;
90
91 u8 brightness;
92 u8 exposure;
93 u8 autogain;
94 u8 gain;
95
96 u8 sof_read;
97 u8 autogain_ignore_frames;
98
99 atomic_t avg_lum;
100};
101
102/* V4L2 controls supported by the driver */
103static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
104static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
105static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
106static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
107static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
108static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
109static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
110static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
111
112static struct ctrl sd_ctrls[] = {
113#define SD_BRIGHTNESS 0
114 {
115 {
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,
124 },
125 .set = sd_setbrightness,
126 .get = sd_getbrightness,
127 },
128#define SD_EXPOSURE 1
129 {
130 {
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,
139 },
140 .set = sd_setexposure,
141 .get = sd_getexposure,
142 },
143#define SD_AUTOGAIN 2
144 {
145 {
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,
154 },
155 .set = sd_setautogain,
156 .get = sd_getautogain,
157 },
158#define SD_GAIN 3
159 {
160 {
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,
169 },
170 .set = sd_setgain,
171 .get = sd_getgain,
172 },
173};
174
175static struct cam_mode sif_mode[] = {
176 {V4L2_PIX_FMT_SBGGR8, 176, 144, 1},
177 {V4L2_PIX_FMT_SBGGR8, 352, 288, 0},
178};
179
180static 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},
186};
187
188 /* 48 reg_72 Rate Control end BalSize_4a =0x36 */
189static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 };
190
191static const char pac207_sof_marker[5] = { 0xff, 0xff, 0x00, 0xff, 0x96 };
192
193int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
194 const u8 *buffer, u16 length)
195{
196 struct usb_device *udev = gspca_dev->dev;
197 int err;
198 u8 kbuf[8];
199
200 memcpy(kbuf, buffer, length);
201
202 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
203 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
204 0x00, index, kbuf, length, PAC207_CTRL_TIMEOUT);
205 if (err < 0)
206 PDEBUG(D_ERR,
207 "Failed to write registers to index 0x%04X, error %d)",
208 index, err);
209
210 return err;
211}
212
213
214int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
215{
216 struct usb_device *udev = gspca_dev->dev;
217 int err;
218
219 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
220 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
221 value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
222 if (err)
223 PDEBUG(D_ERR, "Failed to write a register (index 0x%04X,"
224 " value 0x%02X, error %d)", index, value, err);
225
226 return err;
227}
228
229
230int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
231{
232 struct usb_device *udev = gspca_dev->dev;
233 u8 buff;
234 int res;
235
236 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
237 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
238 0x00, index, &buff, 1, PAC207_CTRL_TIMEOUT);
239 if (res < 0) {
240 PDEBUG(D_ERR,
241 "Failed to read a register (index 0x%04X, error %d)",
242 index, res);
243 return res;
244 }
245
246 return buff;
247}
248
249
250/* this function is called at probe time */
251static int sd_config(struct gspca_dev *gspca_dev,
252 const struct usb_device_id *id)
253{
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300254 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goedee2997a72008-04-23 08:09:12 -0300255 struct cam *cam;
256 u8 idreg[2];
257
258 idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
259 idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
260 idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4);
261 idreg[1] = idreg[1] & 0x0f;
262 PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
263 idreg[0], idreg[1]);
264
265 if (idreg[0] != 0x27) {
266 PDEBUG(D_PROBE, "Error invalid sensor ID!");
267 return -ENODEV;
268 }
269
270 pac207_write_reg(gspca_dev, 0x41, 0x00);
271 /* Bit_0=Image Format,
272 * Bit_1=LED,
273 * Bit_2=Compression test mode enable */
274 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
275 pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
276
277 PDEBUG(D_PROBE,
278 "Pixart PAC207BCA Image Processor and Control Chip detected"
279 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
280
281 cam = &gspca_dev->cam;
282 cam->dev_name = (char *) id->driver_info;
283 cam->epaddr = 0x05;
284 cam->cam_mode = sif_mode;
285 cam->nmodes = ARRAY_SIZE(sif_mode);
Jean-Francois Moine4aa0d032008-05-04 06:46:21 -0300286 sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
287 sd->exposure = PAC207_EXPOSURE_DEFAULT;
288 sd->gain = PAC207_GAIN_DEFAULT;
Hans de Goedee2997a72008-04-23 08:09:12 -0300289
290 return 0;
291}
292
293/* this function is called at open time */
294static int sd_open(struct gspca_dev *gspca_dev)
295{
296 struct sd *sd = (struct sd *) gspca_dev;
297
Hans de Goedee2997a72008-04-23 08:09:12 -0300298 sd->autogain = 1;
299
300 return 0;
301}
302
303/* -- start the camera -- */
304static void sd_start(struct gspca_dev *gspca_dev)
305{
306 struct sd *sd = (struct sd *) gspca_dev;
307 __u8 mode;
308
309 pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
310 pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
311 pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
312 pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
313 pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8);
314 pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8);
315 pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4);
316
317 /* Compression Balance */
318 if (gspca_dev->width == 176)
319 pac207_write_reg(gspca_dev, 0x4a, 0xff);
320 else
321 pac207_write_reg(gspca_dev, 0x4a, 0x88);
322 pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
323 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
324
325 /* PGA global gain (Bit 4-0) */
326 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
327 pac207_write_reg(gspca_dev, 0x02, sd->exposure); /* PXCK = 12MHz /n */
328
329 mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
330 if (gspca_dev->width == 176) { /* 176x144 */
331 mode |= 0x01;
332 PDEBUG(D_STREAM, "pac207_start mode 176x144");
333 } else/* 352x288 */
334 PDEBUG(D_STREAM, "pac207_start mode 352x288");
335 pac207_write_reg(gspca_dev, 0x41, mode);
336
337 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
338 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
339 udelay(1000); /* taken from gspca */
340 pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
341
342 sd->sof_read = 0;
343 sd->autogain_ignore_frames = 0;
344 atomic_set(&sd->avg_lum, -1);
345}
346
347static void sd_stopN(struct gspca_dev *gspca_dev)
348{
349 pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
350 pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
351 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
352}
353
354static void sd_stop0(struct gspca_dev *gspca_dev)
355{
356}
357
358/* this function is called at close time */
359static void sd_close(struct gspca_dev *gspca_dev)
360{
361}
362
363/* -- convert pixart frames to Bayer -- */
364/* Sonix decompressor struct B.S.(2004) */
365static struct {
366 u8 is_abs;
367 u8 len;
368 s8 val;
369} table[256];
370
371void init_pixart_decoder(void)
372{
373 int i, is_abs, val, len;
374
375 for (i = 0; i < 256; i++) {
376 is_abs = 0;
377 val = 0;
378 len = 0;
379 if ((i & 0xC0) == 0) {
380 /* code 00 */
381 val = 0;
382 len = 2;
383 } else if ((i & 0xC0) == 0x40) {
384 /* code 01 */
385 val = -5;
386 len = 2;
387 } else if ((i & 0xC0) == 0x80) {
388 /* code 10 */
389 val = 5;
390 len = 2;
391 } else if ((i & 0xF0) == 0xC0) {
392 /* code 1100 */
393 val = -10;
394 len = 4;
395 } else if ((i & 0xF0) == 0xD0) {
396 /* code 1101 */
397 val = 10;
398 len = 4;
399 } else if ((i & 0xF8) == 0xE0) {
400 /* code 11100 */
401 val = -15;
402 len = 5;
403 } else if ((i & 0xF8) == 0xE8) {
404 /* code 11101 */
405 val = 15;
406 len = 5;
407 } else if ((i & 0xFC) == 0xF0) {
408 /* code 111100 */
409 val = -20;
410 len = 6;
411 } else if ((i & 0xFC) == 0xF4) {
412 /* code 111101 */
413 val = 20;
414 len = 6;
415 } else if ((i & 0xF8) == 0xF8) {
416 /* code 11111xxxxxx */
417 is_abs = 1;
418 val = 0;
419 len = 5;
420 }
421 table[i].is_abs = is_abs;
422 table[i].val = val;
423 table[i].len = len;
424 }
425}
426
427/* auto gain and exposure algorithm based on the knee algorithm described here:
428 http://ytse.tricolour.net/docs/LowLightOptimization.html */
429static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
430{
431 struct sd *sd = (struct sd *) gspca_dev;
432 int i, steps, desired_avg_lum;
433 int orig_gain = sd->gain;
434 int orig_exposure = sd->exposure;
435 int avg_lum = atomic_read(&sd->avg_lum);
436
437 if (!sd->autogain || avg_lum == -1)
438 return;
439
440 if (sd->autogain_ignore_frames > 0) {
441 sd->autogain_ignore_frames--;
442 return;
443 }
444
445 /* correct desired lumination for the configured brightness */
446 desired_avg_lum = 100 + sd->brightness / 2;
447
448 /* If we are of a multiple of deadzone, do multiple step to reach the
449 desired lumination fast (with the risc of a slight overshoot) */
450 steps = abs(desired_avg_lum - avg_lum) / PAC207_AUTOGAIN_DEADZONE;
451
452 for (i = 0; i < steps; i++) {
453 if (avg_lum > desired_avg_lum) {
454 if (sd->gain > PAC207_GAIN_KNEE) {
455 sd->gain--;
456 } else if (sd->exposure > PAC207_EXPOSURE_KNEE) {
457 sd->exposure--;
458 } else if (sd->gain > PAC207_GAIN_DEFAULT) {
459 sd->gain--;
460 } else if (sd->exposure > PAC207_EXPOSURE_MIN) {
461 sd->exposure--;
462 } else if (sd->gain > PAC207_GAIN_MIN) {
463 sd->gain--;
464 } else
465 break;
466 } else {
467 if (sd->gain < PAC207_GAIN_DEFAULT) {
468 sd->gain++;
469 } else if (sd->exposure < PAC207_EXPOSURE_KNEE) {
470 sd->exposure++;
471 } else if (sd->gain < PAC207_GAIN_KNEE) {
472 sd->gain++;
473 } else if (sd->exposure < PAC207_EXPOSURE_MAX) {
474 sd->exposure++;
475 } else if (sd->gain < PAC207_GAIN_MAX) {
476 sd->gain++;
477 } else
478 break;
479 }
480 }
481
482 if (sd->exposure != orig_exposure || sd->gain != orig_gain) {
483 if (sd->exposure != orig_exposure)
484 pac207_write_reg(gspca_dev, 0x0002, sd->exposure);
485 if (sd->gain != orig_gain)
486 pac207_write_reg(gspca_dev, 0x000e, sd->gain);
487 pac207_write_reg(gspca_dev, 0x13, 0x01); /* load reg to sen */
488 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
489 sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
490 }
491}
492
493static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
494 unsigned char *m, int len)
495{
496 struct sd *sd = (struct sd *) gspca_dev;
497 int i;
498
499 /* Search for the SOF marker (fixed part) in the header */
500 for (i = 0; i < len; i++) {
501 if (m[i] == pac207_sof_marker[sd->sof_read]) {
502 sd->sof_read++;
503 if (sd->sof_read == sizeof(pac207_sof_marker)) {
504 PDEBUG(D_STREAM,
505 "SOF found, bytes to analyze: %u."
506 " Frame starts at byte #%u",
507 len, i + 1);
508 sd->sof_read = 0;
509 return m + i + 1;
510 }
511 } else
512 sd->sof_read = 0;
513 }
514
515 return NULL;
516}
517
518static int pac207_decompress_row(struct gspca_dev *gspca_dev,
519 struct gspca_frame *f, unsigned char *cdata, int len)
520{
521 struct sd *sd = (struct sd *) gspca_dev;
522 struct pac207_decoder_state *decoder_state = &sd->decoder_state;
523 unsigned char *outp = decoder_state->line_decode_buf +
524 decoder_state->line_read;
525 int val, bitlen, bitpos = -decoder_state->no_remaining_bits;
526 u8 code;
527
528 /* first two pixels are stored as raw 8-bit */
529 while (decoder_state->line_read < 2) {
530 *outp++ = *cdata++;
531 decoder_state->line_read++;
532 len--;
533 if (len == 0)
534 return 0;
535 }
536
537 while (decoder_state->line_read < gspca_dev->width) {
538 if (bitpos < 0) {
539 code = decoder_state->remaining_bits << (8 + bitpos) |
540 cdata[0] >> -bitpos;
541 } else {
542 u8 *addr = cdata + bitpos / 8;
543 code = addr[0] << (bitpos & 7) |
544 addr[1] >> (8 - (bitpos & 7));
545 }
546
547 bitlen = decoder_state->get_abs ?
548 6 : table[code].len;
549
550 /* Stop decompressing if we're out of input data */
551 if ((bitpos + bitlen) > (len * 8))
552 break;
553
554 if (decoder_state->get_abs) {
555 *outp++ = code & 0xFC;
556 decoder_state->line_read++;
557 decoder_state->get_abs = 0;
558 } else {
559 if (table[code].is_abs)
560 decoder_state->get_abs = 1;
561 else {
562 /* relative to left pixel */
563 val = outp[-2] +
564 table[code].val;
565 if (val > 0xff)
566 val = 0xff;
567 else if (val < 0)
568 val = 0;
569 *outp++ = val;
570 decoder_state->line_read++;
571 }
572 }
573 bitpos += bitlen;
574 }
575
576 if (decoder_state->line_read == gspca_dev->width) {
577 int compressed_line_len;
578
579 gspca_frame_add(gspca_dev, INTER_PACKET, f,
580 decoder_state->line_decode_buf,
581 gspca_dev->width);
582
583 /* completely decompressed line, round pos to nearest word */
584 compressed_line_len = ((decoder_state->processed_bytes * 8 +
585 bitpos + 15) / 16) * 2;
586
587 len -= compressed_line_len - decoder_state->processed_bytes;
588 if (len < 0) {
589 decoder_state->discard_byte = 1;
590 len = 0;
591 }
592 } else {
593 decoder_state->processed_bytes += len;
594 decoder_state->remaining_bits = cdata[bitpos/8];
595 decoder_state->no_remaining_bits = (8 - bitpos) & 7;
596 len = 0;
597 }
598
599 return len;
600}
601
602static void pac207_decode_line_init(struct gspca_dev *gspca_dev)
603{
604 struct sd *sd = (struct sd *) gspca_dev;
605 struct pac207_decoder_state *decoder_state = &sd->decoder_state;
606
607 decoder_state->line_read = 0;
608 decoder_state->line_state = LINE_HEADER1;
609 decoder_state->processed_bytes = 0;
610 decoder_state->no_remaining_bits = 0;
611 decoder_state->get_abs = 0;
612}
613
614static void pac207_decode_frame_init(struct gspca_dev *gspca_dev)
615{
616 struct sd *sd = (struct sd *) gspca_dev;
617 struct pac207_decoder_state *decoder_state = &sd->decoder_state;
618
619 decoder_state->header_read = 0;
620 decoder_state->discard_byte = 0;
621
622 pac207_decode_line_init(gspca_dev);
623}
624
625static int pac207_decode_frame_data(struct gspca_dev *gspca_dev,
626 struct gspca_frame *f, unsigned char *data, int len)
627{
628 struct sd *sd = (struct sd *) gspca_dev;
629 struct pac207_decoder_state *decoder_state = &sd->decoder_state;
630 int needed = 0;
631
632 /* first 11 bytes after sof marker: frame header */
633 if (decoder_state->header_read < 11) {
634 /* get average lumination from frame header (byte 5) */
635 if (decoder_state->header_read < 5) {
636 needed = 5 - decoder_state->header_read;
637 if (len >= needed)
638 atomic_set(&sd->avg_lum, data[needed-1]);
639 }
640 /* skip the rest of the header */
641 needed = 11 - decoder_state->header_read;
642 if (len <= needed) {
643 decoder_state->header_read += len;
644 return 0;
645 }
646 data += needed;
647 len -= needed;
648 decoder_state->header_read = 11;
649 }
650
651 while (len) {
652 if (decoder_state->discard_byte) {
653 data++;
654 len--;
655 decoder_state->discard_byte = 0;
656 continue;
657 }
658
659 switch (decoder_state->line_state) {
660 case LINE_HEADER1:
661 decoder_state->line_marker = data[0] << 8;
662 decoder_state->line_state = LINE_HEADER2;
663 needed = 1;
664 break;
665 case LINE_HEADER2:
666 decoder_state->line_marker |= data[0];
667 switch (decoder_state->line_marker) {
668 case 0x0FF0:
669 decoder_state->line_state = LINE_UNCOMPRESSED;
670 break;
671 case 0x1EE1:
672 decoder_state->line_state = LINE_COMPRESSED;
673 break;
674 default:
675 PDEBUG(D_STREAM,
676 "Error unknown line-header %04X",
677 (int) decoder_state->line_marker);
678 gspca_dev->last_packet_type = DISCARD_PACKET;
679 return 0;
680 }
681 needed = 1;
682 break;
683 case LINE_UNCOMPRESSED:
684 needed = gspca_dev->width - decoder_state->line_read;
685 if (needed > len)
686 needed = len;
687 gspca_frame_add(gspca_dev, INTER_PACKET, f, data,
688 needed);
689 decoder_state->line_read += needed;
690 break;
691 case LINE_COMPRESSED:
692 needed = len -
693 pac207_decompress_row(gspca_dev, f, data, len);
694 break;
695 }
696
697 data += needed;
698 len -= needed;
699
700 if (decoder_state->line_read == gspca_dev->width) {
701 if ((f->data_end - f->data) ==
702 (gspca_dev->width * gspca_dev->height)) {
703 /* eureka we've got a frame */
704 return 1;
705 }
706 pac207_decode_line_init(gspca_dev);
707 }
708 }
709
710 return 0;
711}
712
713static void sd_pkt_scan(struct gspca_dev *gspca_dev,
714 struct gspca_frame *frame,
715 unsigned char *data,
716 int len)
717{
718 unsigned char *sof;
719 int n;
720
721 sof = pac207_find_sof(gspca_dev, data, len);
722
723 if (sof) {
724 /* finish decoding current frame */
725 if (gspca_dev->last_packet_type == INTER_PACKET) {
726 n = sof - data;
727 if (n > sizeof(pac207_sof_marker))
728 n -= sizeof(pac207_sof_marker);
729 else
730 n = 0;
731 n = pac207_decode_frame_data(gspca_dev, frame,
732 data, n);
733 if (n)
734 frame = gspca_frame_add(gspca_dev,
735 LAST_PACKET,
736 frame,
737 NULL,
738 0);
739 else
740 PDEBUG(D_STREAM, "Incomplete frame");
741 }
742 pac207_decode_frame_init(gspca_dev);
743 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL,
744 0);
745 len -= sof - data;
746 data = sof;
747 }
748
749 if (gspca_dev->last_packet_type == DISCARD_PACKET)
750 return;
751
752 n = pac207_decode_frame_data(gspca_dev, frame, data, len);
753 if (n)
754 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
755 frame, NULL, 0);
756}
757
758static void setbrightness(struct gspca_dev *gspca_dev)
759{
760 struct sd *sd = (struct sd *) gspca_dev;
761
762 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
763 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
764 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
765}
766
767static void setexposure(struct gspca_dev *gspca_dev)
768{
769 struct sd *sd = (struct sd *) gspca_dev;
770
771 pac207_write_reg(gspca_dev, 0x02, sd->exposure);
772 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
773 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
774}
775
776static void setgain(struct gspca_dev *gspca_dev)
777{
778 struct sd *sd = (struct sd *) gspca_dev;
779
780 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
781 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
782 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
783}
784
785static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
786{
787 struct sd *sd = (struct sd *) gspca_dev;
788
789 sd->brightness = val;
790 if (gspca_dev->streaming)
791 setbrightness(gspca_dev);
792 return 0;
793}
794
795static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
796{
797 struct sd *sd = (struct sd *) gspca_dev;
798
799 *val = sd->brightness;
800 return 0;
801}
802
803static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
804{
805 struct sd *sd = (struct sd *) gspca_dev;
806
807 /* don't allow mucking with exposure when using autogain */
808 if (sd->autogain)
809 return -EINVAL;
810
811 sd->exposure = val;
812 if (gspca_dev->streaming)
813 setexposure(gspca_dev);
814 return 0;
815}
816
817static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
818{
819 struct sd *sd = (struct sd *) gspca_dev;
820
821 *val = sd->exposure;
822 return 0;
823}
824
825static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
826{
827 struct sd *sd = (struct sd *) gspca_dev;
828
829 /* don't allow mucking with gain when using autogain */
830 if (sd->autogain)
831 return -EINVAL;
832
833 sd->gain = val;
834 if (gspca_dev->streaming)
835 setgain(gspca_dev);
836 return 0;
837}
838
839static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
840{
841 struct sd *sd = (struct sd *) gspca_dev;
842
843 *val = sd->gain;
844 return 0;
845}
846
847static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
848{
849 struct sd *sd = (struct sd *) gspca_dev;
850
851 sd->autogain = val;
852 /* when switching to autogain set defaults to make sure
853 we are on a valid point of the autogain gain /
854 exposure knee graph, and give this change time to
855 take effect before doing autogain. */
856 if (sd->autogain) {
857 sd->exposure = PAC207_EXPOSURE_DEFAULT;
858 sd->gain = PAC207_GAIN_DEFAULT;
859 if (gspca_dev->streaming) {
860 sd->autogain_ignore_frames =
861 PAC207_AUTOGAIN_IGNORE_FRAMES;
862 setexposure(gspca_dev);
863 setgain(gspca_dev);
864 }
865 }
866
867 return 0;
868}
869
870static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
871{
872 struct sd *sd = (struct sd *) gspca_dev;
873
874 *val = sd->autogain;
875 return 0;
876}
877
878/* sub-driver description */
879static struct sd_desc sd_desc = {
880 .name = MODULE_NAME,
881 .ctrls = sd_ctrls,
882 .nctrls = ARRAY_SIZE(sd_ctrls),
883 .config = sd_config,
884 .open = sd_open,
885 .start = sd_start,
886 .stopN = sd_stopN,
887 .stop0 = sd_stop0,
888 .close = sd_close,
889 .dq_callback = pac207_do_auto_gain,
890 .pkt_scan = sd_pkt_scan,
891};
892
893/* -- module initialisation -- */
894#define DVNM(name) .driver_info = (kernel_ulong_t) name
895static __devinitdata struct usb_device_id device_table[] = {
896 {USB_DEVICE(0x041e, 0x4028), DVNM("Creative Webcam Vista Plus")},
897 {USB_DEVICE(0x093a, 0x2460), DVNM("PAC207 Qtec Webcam 100")},
898 {USB_DEVICE(0x093a, 0x2463), DVNM("Philips spc200nc pac207")},
899 {USB_DEVICE(0x093a, 0x2464), DVNM("Labtec Webcam 1200")},
900 {USB_DEVICE(0x093a, 0x2468), DVNM("PAC207")},
901 {USB_DEVICE(0x093a, 0x2470), DVNM("Genius GF112")},
902 {USB_DEVICE(0x093a, 0x2471), DVNM("PAC207 Genius VideoCam ge111")},
903 {USB_DEVICE(0x093a, 0x2472), DVNM("PAC207 Genius VideoCam ge110")},
904 {USB_DEVICE(0x2001, 0xf115), DVNM("D-Link DSB-C120")},
905 {}
906};
907MODULE_DEVICE_TABLE(usb, device_table);
908
909/* -- device connect -- */
910static int sd_probe(struct usb_interface *intf,
911 const struct usb_device_id *id)
912{
913 PDEBUG(D_PROBE, "camera probe");
914 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd));
915}
916
917static struct usb_driver sd_driver = {
918 .name = MODULE_NAME,
919 .id_table = device_table,
920 .probe = sd_probe,
921 .disconnect = gspca_disconnect,
922};
923
924/* -- module insert / remove -- */
925static int __init sd_mod_init(void)
926{
927 init_pixart_decoder();
928 if (usb_register(&sd_driver) < 0)
929 return -1;
930 PDEBUG(D_PROBE, "v%s registered", version);
931 return 0;
932}
933static void __exit sd_mod_exit(void)
934{
935 usb_deregister(&sd_driver);
936 PDEBUG(D_PROBE, "deregistered");
937}
938
939module_init(sd_mod_init);
940module_exit(sd_mod_exit);