aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/pac207.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/pac207.c')
-rw-r--r--drivers/media/video/gspca/pac207.c68
1 files changed, 5 insertions, 63 deletions
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
index 4f197c1f4a76..5d68d3f42262 100644
--- a/drivers/media/video/gspca/pac207.c
+++ b/drivers/media/video/gspca/pac207.c
@@ -357,70 +357,20 @@ static void sd_close(struct gspca_dev *gspca_dev)
357{ 357{
358} 358}
359 359
360/* auto gain and exposure algorithm based on the knee algorithm described here:
361 * <http://ytse.tricolour.net/docs/LowLightOptimization.html> */
362static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) 360static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
363{ 361{
364 struct sd *sd = (struct sd *) gspca_dev; 362 struct sd *sd = (struct sd *) gspca_dev;
365 int i, steps, desired_avg_lum;
366 int orig_gain = sd->gain;
367 int orig_exposure = sd->exposure;
368 int avg_lum = atomic_read(&sd->avg_lum); 363 int avg_lum = atomic_read(&sd->avg_lum);
369 364
370 if (!sd->autogain || avg_lum == -1) 365 if (avg_lum == -1)
371 return; 366 return;
372 367
373 if (sd->autogain_ignore_frames > 0) { 368 if (sd->autogain_ignore_frames > 0)
374 sd->autogain_ignore_frames--; 369 sd->autogain_ignore_frames--;
375 return; 370 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
376 } 371 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE,
377 372 PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
378 /* correct desired lumination for the configured brightness */
379 desired_avg_lum = 100 + sd->brightness / 2;
380
381 /* If we are of a multiple of deadzone, do multiple step to reach the
382 desired lumination fast (with the risc of a slight overshoot) */
383 steps = abs(desired_avg_lum - avg_lum) / PAC207_AUTOGAIN_DEADZONE;
384
385 for (i = 0; i < steps; i++) {
386 if (avg_lum > desired_avg_lum) {
387 if (sd->gain > PAC207_GAIN_KNEE)
388 sd->gain--;
389 else if (sd->exposure > PAC207_EXPOSURE_KNEE)
390 sd->exposure--;
391 else if (sd->gain > PAC207_GAIN_DEFAULT)
392 sd->gain--;
393 else if (sd->exposure > PAC207_EXPOSURE_MIN)
394 sd->exposure--;
395 else if (sd->gain > PAC207_GAIN_MIN)
396 sd->gain--;
397 else
398 break;
399 } else {
400 if (sd->gain < PAC207_GAIN_DEFAULT)
401 sd->gain++;
402 else if (sd->exposure < PAC207_EXPOSURE_KNEE)
403 sd->exposure++;
404 else if (sd->gain < PAC207_GAIN_KNEE)
405 sd->gain++;
406 else if (sd->exposure < PAC207_EXPOSURE_MAX)
407 sd->exposure++;
408 else if (sd->gain < PAC207_GAIN_MAX)
409 sd->gain++;
410 else
411 break;
412 }
413 }
414
415 if (sd->exposure != orig_exposure || sd->gain != orig_gain) {
416 if (sd->exposure != orig_exposure)
417 pac207_write_reg(gspca_dev, 0x0002, sd->exposure);
418 if (sd->gain != orig_gain)
419 pac207_write_reg(gspca_dev, 0x000e, sd->gain);
420 pac207_write_reg(gspca_dev, 0x13, 0x01); /* load reg to sen */
421 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
422 sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES; 373 sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
423 }
424} 374}
425 375
426static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev, 376static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
@@ -546,10 +496,6 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
546{ 496{
547 struct sd *sd = (struct sd *) gspca_dev; 497 struct sd *sd = (struct sd *) gspca_dev;
548 498
549 /* don't allow mucking with exposure when using autogain */
550 if (sd->autogain)
551 return -EINVAL;
552
553 sd->exposure = val; 499 sd->exposure = val;
554 if (gspca_dev->streaming) 500 if (gspca_dev->streaming)
555 setexposure(gspca_dev); 501 setexposure(gspca_dev);
@@ -568,10 +514,6 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
568{ 514{
569 struct sd *sd = (struct sd *) gspca_dev; 515 struct sd *sd = (struct sd *) gspca_dev;
570 516
571 /* don't allow mucking with gain when using autogain */
572 if (sd->autogain)
573 return -EINVAL;
574
575 sd->gain = val; 517 sd->gain = val;
576 if (gspca_dev->streaming) 518 if (gspca_dev->streaming)
577 setgain(gspca_dev); 519 setgain(gspca_dev);