diff options
Diffstat (limited to 'linux/drivers/media/video/gspca/pac207.c')
-rw-r--r-- | linux/drivers/media/video/gspca/pac207.c | 87 |
1 files changed, 14 insertions, 73 deletions
diff --git a/linux/drivers/media/video/gspca/pac207.c b/linux/drivers/media/video/gspca/pac207.c index 4f197c1f4..fa7abc411 100644 --- a/linux/drivers/media/video/gspca/pac207.c +++ b/linux/drivers/media/video/gspca/pac207.c @@ -27,8 +27,8 @@ #include "gspca.h" -#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 5) -static const char version[] = "2.1.5"; +#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7) +static const char version[] = "2.1.7"; MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>"); MODULE_DESCRIPTION("Pixart PAC207"); @@ -187,18 +187,18 @@ static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 }; static const unsigned char pac207_sof_marker[5] = { 0xff, 0xff, 0x00, 0xff, 0x96 }; -int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index, +static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index, const u8 *buffer, u16 length) { struct usb_device *udev = gspca_dev->dev; int err; - u8 kbuf[8]; - memcpy(kbuf, buffer, length); + memcpy(gspca_dev->usb_buf, buffer, length); err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, index, kbuf, length, PAC207_CTRL_TIMEOUT); + 0x00, index, + gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT); if (err < 0) PDEBUG(D_ERR, "Failed to write registers to index 0x%04X, error %d)", @@ -227,12 +227,12 @@ int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value) int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index) { struct usb_device *udev = gspca_dev->dev; - u8 buff; int res; res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, index, &buff, 1, PAC207_CTRL_TIMEOUT); + 0x00, index, + gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT); if (res < 0) { PDEBUG(D_ERR, "Failed to read a register (index 0x%04X, error %d)", @@ -240,10 +240,9 @@ int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index) return res; } - return buff; + return gspca_dev->usb_buf[0]; } - /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -357,70 +356,20 @@ static void sd_close(struct gspca_dev *gspca_dev) { } -/* auto gain and exposure algorithm based on the knee algorithm described here: - * <http://ytse.tricolour.net/docs/LowLightOptimization.html> */ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int i, steps, desired_avg_lum; - int orig_gain = sd->gain; - int orig_exposure = sd->exposure; int avg_lum = atomic_read(&sd->avg_lum); - if (!sd->autogain || avg_lum == -1) + if (avg_lum == -1) return; - if (sd->autogain_ignore_frames > 0) { + if (sd->autogain_ignore_frames > 0) sd->autogain_ignore_frames--; - return; - } - - /* correct desired lumination for the configured brightness */ - desired_avg_lum = 100 + sd->brightness / 2; - - /* If we are of a multiple of deadzone, do multiple step to reach the - desired lumination fast (with the risc of a slight overshoot) */ - steps = abs(desired_avg_lum - avg_lum) / PAC207_AUTOGAIN_DEADZONE; - - for (i = 0; i < steps; i++) { - if (avg_lum > desired_avg_lum) { - if (sd->gain > PAC207_GAIN_KNEE) - sd->gain--; - else if (sd->exposure > PAC207_EXPOSURE_KNEE) - sd->exposure--; - else if (sd->gain > PAC207_GAIN_DEFAULT) - sd->gain--; - else if (sd->exposure > PAC207_EXPOSURE_MIN) - sd->exposure--; - else if (sd->gain > PAC207_GAIN_MIN) - sd->gain--; - else - break; - } else { - if (sd->gain < PAC207_GAIN_DEFAULT) - sd->gain++; - else if (sd->exposure < PAC207_EXPOSURE_KNEE) - sd->exposure++; - else if (sd->gain < PAC207_GAIN_KNEE) - sd->gain++; - else if (sd->exposure < PAC207_EXPOSURE_MAX) - sd->exposure++; - else if (sd->gain < PAC207_GAIN_MAX) - sd->gain++; - else - break; - } - } - - if (sd->exposure != orig_exposure || sd->gain != orig_gain) { - if (sd->exposure != orig_exposure) - pac207_write_reg(gspca_dev, 0x0002, sd->exposure); - if (sd->gain != orig_gain) - pac207_write_reg(gspca_dev, 0x000e, sd->gain); - pac207_write_reg(gspca_dev, 0x13, 0x01); /* load reg to sen */ - pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */ + else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, + 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE, + PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE)) sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES; - } } static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev, @@ -546,10 +495,6 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; - /* don't allow mucking with exposure when using autogain */ - if (sd->autogain) - return -EINVAL; - sd->exposure = val; if (gspca_dev->streaming) setexposure(gspca_dev); @@ -568,10 +513,6 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; - /* don't allow mucking with gain when using autogain */ - if (sd->autogain) - return -EINVAL; - sd->gain = val; if (gspca_dev->streaming) setgain(gspca_dev); |