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(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
{
68 struct pac207_decoder_state
{
74 /* compression state */
80 u8 line_decode_buf
[352];
83 /* specific webcam descriptor */
85 struct gspca_dev gspca_dev
; /* !! must be the first item */
87 struct pac207_decoder_state decoder_state
;
97 u8 autogain_ignore_frames
;
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
,
122 .default_value
= PAC207_BRIGHTNESS_DEFAULT
,
125 .set
= sd_setbrightness
,
126 .get
= sd_getbrightness
,
128 #define SD_EXPOSURE 1
131 .id
= V4L2_CID_EXPOSURE
,
132 .type
= V4L2_CTRL_TYPE_INTEGER
,
134 .minimum
= PAC207_EXPOSURE_MIN
,
135 .maximum
= PAC207_EXPOSURE_MAX
,
137 .default_value
= PAC207_EXPOSURE_DEFAULT
,
140 .set
= sd_setexposure
,
141 .get
= sd_getexposure
,
143 #define SD_AUTOGAIN 2
146 .id
= V4L2_CID_AUTOGAIN
,
147 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
155 .set
= sd_setautogain
,
156 .get
= sd_getautogain
,
162 .type
= V4L2_CTRL_TYPE_INTEGER
,
164 .minimum
= PAC207_GAIN_MIN
,
165 .maximum
= PAC207_GAIN_MAX
,
167 .default_value
= PAC207_GAIN_DEFAULT
,
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
;
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
);
208 "Failed to write registers to index 0x%04X, error %d)",
215 int pac207_write_reg(struct gspca_dev
*gspca_dev
, u16 index
, u16 value
)
217 struct usb_device
*udev
= gspca_dev
->dev
;
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
);
224 PDEBUG(D_ERR
, "Failed to write a register (index 0x%04X,"
225 " value 0x%02X, error %d)", index
, value
, err
);
231 int pac207_read_reg(struct gspca_dev
*gspca_dev
, u16 index
)
233 struct usb_device
*udev
= gspca_dev
->dev
;
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
);
242 "Failed to read a register (index 0x%04X, error %d)",
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
;
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",
266 if (idreg
[0] != 0x27) {
267 PDEBUG(D_PROBE
, "Error invalid sensor ID!");
271 pac207_write_reg(gspca_dev
, 0x41, 0x00);
272 /* Bit_0=Image Format,
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 */
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
;
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
;
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
;
304 /* -- start the camera -- */
305 static void sd_start(struct gspca_dev
*gspca_dev
)
307 struct sd
*sd
= (struct sd
*) gspca_dev
;
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);
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 */
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 */
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) */
373 void init_pixart_decoder(void)
375 int i
, is_abs
, val
, len
;
377 for (i
= 0; i
< 256; i
++) {
381 if ((i
& 0xC0) == 0) {
385 } else if ((i
& 0xC0) == 0x40) {
389 } else if ((i
& 0xC0) == 0x80) {
393 } else if ((i
& 0xF0) == 0xC0) {
397 } else if ((i
& 0xF0) == 0xD0) {
401 } else if ((i
& 0xF8) == 0xE0) {
405 } else if ((i
& 0xF8) == 0xE8) {
409 } else if ((i
& 0xFC) == 0xF0) {
413 } else if ((i
& 0xFC) == 0xF4) {
417 } else if ((i
& 0xF8) == 0xF8) {
418 /* code 11111xxxxxx */
423 table
[i
].is_abs
= is_abs
;
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)
442 if (sd
->autogain_ignore_frames
> 0) {
443 sd
->autogain_ignore_frames
--;
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
) {
458 } else if (sd
->exposure
> PAC207_EXPOSURE_KNEE
) {
460 } else if (sd
->gain
> PAC207_GAIN_DEFAULT
) {
462 } else if (sd
->exposure
> PAC207_EXPOSURE_MIN
) {
464 } else if (sd
->gain
> PAC207_GAIN_MIN
) {
469 if (sd
->gain
< PAC207_GAIN_DEFAULT
) {
471 } else if (sd
->exposure
< PAC207_EXPOSURE_KNEE
) {
473 } else if (sd
->gain
< PAC207_GAIN_KNEE
) {
475 } else if (sd
->exposure
< PAC207_EXPOSURE_MAX
) {
477 } else if (sd
->gain
< PAC207_GAIN_MAX
) {
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
;
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
]) {
505 if (sd
->sof_read
== sizeof(pac207_sof_marker
)) {
507 "SOF found, bytes to analyze: %u."
508 " Frame starts at byte #%u",
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
;
531 /* first two pixels are stored as raw 8-bit */
532 while (decoder_state
->line_read
< 2) {
534 decoder_state
->line_read
++;
540 while (decoder_state
->line_read
< gspca_dev
->width
) {
542 code
= decoder_state
->remaining_bits
<< (8 + bitpos
) |
545 u8
*addr
= cdata
+ bitpos
/ 8;
546 code
= addr
[0] << (bitpos
& 7) |
547 addr
[1] >> (8 - (bitpos
& 7));
550 bitlen
= decoder_state
->get_abs
?
553 /* Stop decompressing if we're out of input data */
554 if ((bitpos
+ bitlen
) > (len
* 8))
557 if (decoder_state
->get_abs
) {
558 *outp
++ = code
& 0xFC;
559 decoder_state
->line_read
++;
560 decoder_state
->get_abs
= 0;
562 if (table
[code
].is_abs
) {
563 decoder_state
->get_abs
= 1;
565 /* relative to left pixel */
573 decoder_state
->line_read
++;
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
,
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
;
592 decoder_state
->discard_byte
= 1;
596 decoder_state
->processed_bytes
+= len
;
597 decoder_state
->remaining_bits
= cdata
[bitpos
/8];
598 decoder_state
->no_remaining_bits
= (8 - bitpos
) & 7;
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
;
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
;
641 atomic_set(&sd
->avg_lum
, data
[needed
-1]);
643 /* skip the rest of the header */
644 needed
= 11 - decoder_state
->header_read
;
646 decoder_state
->header_read
+= len
;
651 decoder_state
->header_read
= 11;
655 if (decoder_state
->discard_byte
) {
658 decoder_state
->discard_byte
= 0;
662 switch (decoder_state
->line_state
) {
664 decoder_state
->line_marker
= data
[0] << 8;
665 decoder_state
->line_state
= LINE_HEADER2
;
669 decoder_state
->line_marker
|= data
[0];
670 switch (decoder_state
->line_marker
) {
672 decoder_state
->line_state
= LINE_UNCOMPRESSED
;
675 decoder_state
->line_state
= LINE_COMPRESSED
;
679 "Error unknown line-header %04X",
680 (int) decoder_state
->line_marker
);
681 gspca_dev
->last_packet_type
= DISCARD_PACKET
;
686 case LINE_UNCOMPRESSED
:
687 needed
= gspca_dev
->width
- decoder_state
->line_read
;
690 gspca_frame_add(gspca_dev
, INTER_PACKET
, f
, data
,
692 decoder_state
->line_read
+= needed
;
694 case LINE_COMPRESSED
:
696 pac207_decompress_row(gspca_dev
, f
, data
, len
);
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 */
709 pac207_decode_line_init(gspca_dev
);
716 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
717 struct gspca_frame
*frame
,
724 sof
= pac207_find_sof(gspca_dev
, data
, len
);
727 /* finish decoding current frame */
728 if (gspca_dev
->last_packet_type
== INTER_PACKET
) {
730 if (n
> sizeof(pac207_sof_marker
))
731 n
-= sizeof(pac207_sof_marker
);
734 n
= pac207_decode_frame_data(gspca_dev
, frame
,
737 frame
= gspca_frame_add(gspca_dev
,
743 PDEBUG(D_STREAM
, "Incomplete frame");
745 pac207_decode_frame_init(gspca_dev
);
746 gspca_frame_add(gspca_dev
, FIRST_PACKET
, frame
, NULL
,
752 if (gspca_dev
->last_packet_type
== DISCARD_PACKET
)
755 n
= pac207_decode_frame_data(gspca_dev
, frame
, data
, len
);
757 frame
= gspca_frame_add(gspca_dev
, LAST_PACKET
,
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
);
798 static int sd_getbrightness(struct gspca_dev
*gspca_dev
, __s32
*val
)
800 struct sd
*sd
= (struct sd
*) gspca_dev
;
802 *val
= sd
->brightness
;
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 */
815 if (gspca_dev
->streaming
)
816 setexposure(gspca_dev
);
820 static int sd_getexposure(struct gspca_dev
*gspca_dev
, __s32
*val
)
822 struct sd
*sd
= (struct sd
*) gspca_dev
;
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 */
837 if (gspca_dev
->streaming
)
842 static int sd_getgain(struct gspca_dev
*gspca_dev
, __s32
*val
)
844 struct sd
*sd
= (struct sd
*) gspca_dev
;
850 static int sd_setautogain(struct gspca_dev
*gspca_dev
, __s32 val
)
852 struct sd
*sd
= (struct sd
*) gspca_dev
;
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. */
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
);
873 static int sd_getautogain(struct gspca_dev
*gspca_dev
, __s32
*val
)
875 struct sd
*sd
= (struct sd
*) gspca_dev
;
881 /* sub-driver description */
882 static struct sd_desc sd_desc
= {
885 .nctrls
= ARRAY_SIZE(sd_ctrls
),
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
),
920 static struct usb_driver sd_driver
= {
922 .id_table
= device_table
,
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)
933 PDEBUG(D_PROBE
, "v%s registered", version
);
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
);