|
@@ -2435,95 +2435,6 @@ int gspca_resume(struct usb_interface *intf)
|
|
|
}
|
|
|
EXPORT_SYMBOL(gspca_resume);
|
|
|
#endif
|
|
|
-/* -- 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->ctrl_dis & (1 << i))
|
|
|
- continue;
|
|
|
- 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;
|
|
|
-
|
|
|
- PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
|
|
|
- avg_lum, desired_avg_lum, steps);
|
|
|
-
|
|
|
- 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)
|