aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/gspca.c
diff options
context:
space:
mode:
authorHans de Goede <j.w.r.degoede@hhs.nl>2008-07-10 09:40:53 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-20 06:25:59 -0400
commitdcef3237b652e1c02093feac0f443485a144f035 (patch)
tree81df2d056ef1c4179868512076d9339dbd98680a /drivers/media/video/gspca/gspca.c
parentd0d0e39bc5912793405d3f84ffc982fa400e6cc0 (diff)
V4L/DVB (8348): gspca: Add auto gain/exposure to sonixb and tas5110 / ov6650 sensors.
sonixb: Do auto gain for tas5110 / ov6650 sensors. pac207: Move the auto_gain function to gspca. gspca: New function gspca_auto_gain_n_exposure(). Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl> Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/gspca/gspca.c')
-rw-r--r--drivers/media/video/gspca/gspca.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 09f190c689d5..2ffb00ab0811 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -1790,6 +1790,94 @@ void gspca_disconnect(struct usb_interface *intf)
1790} 1790}
1791EXPORT_SYMBOL(gspca_disconnect); 1791EXPORT_SYMBOL(gspca_disconnect);
1792 1792
1793/* -- cam driver utility functions -- */
1794
1795/* auto gain and exposure algorithm based on the knee algorithm described here:
1796 http://ytse.tricolour.net/docs/LowLightOptimization.html
1797
1798 Returns 0 if no changes were made, 1 if the gain and or exposure settings
1799 where changed. */
1800int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
1801 int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee)
1802{
1803 int i, steps, gain, orig_gain, exposure, orig_exposure, autogain;
1804 const struct ctrl *gain_ctrl = NULL;
1805 const struct ctrl *exposure_ctrl = NULL;
1806 const struct ctrl *autogain_ctrl = NULL;
1807 int retval = 0;
1808
1809 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
1810 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN)
1811 gain_ctrl = &gspca_dev->sd_desc->ctrls[i];
1812 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE)
1813 exposure_ctrl = &gspca_dev->sd_desc->ctrls[i];
1814 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_AUTOGAIN)
1815 autogain_ctrl = &gspca_dev->sd_desc->ctrls[i];
1816 }
1817 if (!gain_ctrl || !exposure_ctrl || !autogain_ctrl) {
1818 PDEBUG(D_ERR, "Error: gspca_auto_gain_n_exposure called "
1819 "on cam without (auto)gain/exposure");
1820 return 0;
1821 }
1822
1823 if (gain_ctrl->get(gspca_dev, &gain) ||
1824 exposure_ctrl->get(gspca_dev, &exposure) ||
1825 autogain_ctrl->get(gspca_dev, &autogain) || !autogain)
1826 return 0;
1827
1828 orig_gain = gain;
1829 orig_exposure = exposure;
1830
1831 /* If we are of a multiple of deadzone, do multiple steps to reach the
1832 desired lumination fast (with the risc of a slight overshoot) */
1833 steps = abs(desired_avg_lum - avg_lum) / deadzone;
1834
1835 PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d\n",
1836 avg_lum, desired_avg_lum, steps);
1837
1838 for (i = 0; i < steps; i++) {
1839 if (avg_lum > desired_avg_lum) {
1840 if (gain > gain_knee)
1841 gain--;
1842 else if (exposure > exposure_knee)
1843 exposure--;
1844 else if (gain > gain_ctrl->qctrl.default_value)
1845 gain--;
1846 else if (exposure > exposure_ctrl->qctrl.minimum)
1847 exposure--;
1848 else if (gain > gain_ctrl->qctrl.minimum)
1849 gain--;
1850 else
1851 break;
1852 } else {
1853 if (gain < gain_ctrl->qctrl.default_value)
1854 gain++;
1855 else if (exposure < exposure_knee)
1856 exposure++;
1857 else if (gain < gain_knee)
1858 gain++;
1859 else if (exposure < exposure_ctrl->qctrl.maximum)
1860 exposure++;
1861 else if (gain < gain_ctrl->qctrl.maximum)
1862 gain++;
1863 else
1864 break;
1865 }
1866 }
1867
1868 if (gain != orig_gain) {
1869 gain_ctrl->set(gspca_dev, gain);
1870 retval = 1;
1871 }
1872 if (exposure != orig_exposure) {
1873 exposure_ctrl->set(gspca_dev, exposure);
1874 retval = 1;
1875 }
1876
1877 return retval;
1878}
1879EXPORT_SYMBOL(gspca_auto_gain_n_exposure);
1880
1793/* -- module insert / remove -- */ 1881/* -- module insert / remove -- */
1794static int __init gspca_init(void) 1882static int __init gspca_init(void)
1795{ 1883{