* PATCH: gspca-general-autogain_n_exposure-knee-algp.patch
@ 2008-07-09 13:29 Hans de Goede
0 siblings, 0 replies; only message in thread
From: Hans de Goede @ 2008-07-09 13:29 UTC (permalink / raw)
To: video4linux-list
[-- Attachment #1: Type: text/plain, Size: 427 bytes --]
Hi,
Make the knee auto gain and exposure algorithm, described here:
http://ytse.tricolour.net/docs/LowLightOptimization.html
And currently used in the pac207 generic (iow not pac207 specific) and move it
to gspca.c . This is a preperation patch for adding exposure setting and auto
gain and exposure to the sn9c10x driver (for selective sensors for now).
Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl>
Regards,
Hans
[-- Attachment #2: gspca-general-autogain_n_exposure-knee-algp.patch --]
[-- Type: text/plain, Size: 6978 bytes --]
Make the knee auto gain and exposure algorithm, described here:
http://ytse.tricolour.net/docs/LowLightOptimization.html
And currently used in the pac207 generic (iow not pac207 specific) and move it
to gspca.c . This is a preperation patch for adding exposure setting and auto
gain and exposure to the sn9c10x driver (for selective sensors for now).
Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl>
diff -r 5065159a99d4 linux/drivers/media/video/gspca/gspca.c
--- a/linux/drivers/media/video/gspca/gspca.c Sun Jul 06 09:27:19 2008 +0200
+++ b/linux/drivers/media/video/gspca/gspca.c Mon Jul 07 09:15:54 2008 +0200
@@ -1894,6 +1894,91 @@
}
EXPORT_SYMBOL(gspca_disconnect);
+/* -- cam driver utility functions -- */
+
+/* auto gain and exposure algorithm based on the knee algorithm described here:
+ http://ytse.tricolour.net/docs/LowLightOptimization.html
+
+ Returns 0 if no changes were made, 1 if the gain and or exposure settings
+ where changed. */
+int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
+ int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee)
+{
+ int i, steps, gain, orig_gain, exposure, orig_exposure, autogain;
+ const struct ctrl *gain_ctrl = NULL;
+ const struct ctrl *exposure_ctrl = NULL;
+ const struct ctrl *autogain_ctrl = NULL;
+ int retval = 0;
+
+ for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
+ if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN)
+ gain_ctrl = &gspca_dev->sd_desc->ctrls[i];
+ if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE)
+ exposure_ctrl = &gspca_dev->sd_desc->ctrls[i];
+ if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_AUTOGAIN)
+ autogain_ctrl = &gspca_dev->sd_desc->ctrls[i];
+ }
+ if (!gain_ctrl || !exposure_ctrl || !autogain_ctrl) {
+ PDEBUG(D_ERR, "Error: gspca_auto_gain_n_exposure called "
+ "on cam without (auto)gain/exposure");
+ return 0;
+ }
+
+ if (gain_ctrl->get(gspca_dev, &gain) ||
+ exposure_ctrl->get(gspca_dev, &exposure) ||
+ autogain_ctrl->get(gspca_dev, &autogain) || !autogain)
+ return 0;
+
+ orig_gain = gain;
+ orig_exposure = exposure;
+
+ /* If we are of a multiple of deadzone, do multiple steps to reach the
+ desired lumination fast (with the risc of a slight overshoot) */
+ steps = abs(desired_avg_lum - avg_lum) / deadzone;
+
+ for (i = 0; i < steps; i++) {
+ if (avg_lum > desired_avg_lum) {
+ if (gain > gain_knee)
+ gain--;
+ else if (exposure > exposure_knee)
+ exposure--;
+ else if (gain > gain_ctrl->qctrl.default_value)
+ gain--;
+ else if (exposure > exposure_ctrl->qctrl.minimum)
+ exposure--;
+ else if (gain > gain_ctrl->qctrl.minimum)
+ gain--;
+ else
+ break;
+ } else {
+ if (gain < gain_ctrl->qctrl.default_value)
+ gain++;
+ else if (exposure < exposure_knee)
+ exposure++;
+ else if (gain < gain_knee)
+ gain++;
+ else if (exposure < exposure_ctrl->qctrl.maximum)
+ exposure++;
+ else if (gain < gain_ctrl->qctrl.maximum)
+ gain++;
+ else
+ break;
+ }
+ }
+
+ if (gain != orig_gain) {
+ gain_ctrl->set(gspca_dev, gain);
+ retval = 1;
+ }
+ if (exposure != orig_exposure) {
+ exposure_ctrl->set(gspca_dev, exposure);
+ retval = 1;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(gspca_auto_gain_n_exposure);
+
/* -- module insert / remove -- */
static int __init gspca_init(void)
{
diff -r 5065159a99d4 linux/drivers/media/video/gspca/gspca.h
--- a/linux/drivers/media/video/gspca/gspca.h Sun Jul 06 09:27:19 2008 +0200
+++ b/linux/drivers/media/video/gspca/gspca.h Mon Jul 07 09:15:54 2008 +0200
@@ -172,4 +172,6 @@
struct gspca_frame *frame,
const __u8 *data,
int len);
+int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
+ int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee);
#endif /* GSPCAV2_H */
diff -r 5065159a99d4 linux/drivers/media/video/gspca/pac207.c
--- a/linux/drivers/media/video/gspca/pac207.c Sun Jul 06 09:27:19 2008 +0200
+++ b/linux/drivers/media/video/gspca/pac207.c Mon Jul 07 09:15:54 2008 +0200
@@ -357,70 +357,20 @@
{
}
-/* 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 +496,6 @@
{
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);
@@ -567,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)
[-- Attachment #3: Type: text/plain, Size: 164 bytes --]
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2008-07-09 13:30 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-09 13:29 PATCH: gspca-general-autogain_n_exposure-knee-algp.patch Hans de Goede
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox