diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-05-16 03:48:28 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-07-30 17:24:04 -0400 |
commit | a17dd1ebd5396e929c10c60237a1fab5adae57cf (patch) | |
tree | 109d4fca82a0b1b58a82545e2d7193ce8c6f6098 /drivers/media/video/gspca | |
parent | 3e0ed00903e1904112108135c18b1918386457aa (diff) |
[media] nw80x: convert to the control framework
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca')
-rw-r--r-- | drivers/media/video/gspca/nw80x.c | 203 |
1 files changed, 87 insertions, 116 deletions
diff --git a/drivers/media/video/gspca/nw80x.c b/drivers/media/video/gspca/nw80x.c index 42e021931e60..74a05bab9f60 100644 --- a/drivers/media/video/gspca/nw80x.c +++ b/drivers/media/video/gspca/nw80x.c | |||
@@ -32,22 +32,10 @@ MODULE_LICENSE("GPL"); | |||
32 | 32 | ||
33 | static int webcam; | 33 | static int webcam; |
34 | 34 | ||
35 | /* controls */ | ||
36 | enum e_ctrl { | ||
37 | GAIN, | ||
38 | EXPOSURE, | ||
39 | AUTOGAIN, | ||
40 | NCTRLS /* number of controls */ | ||
41 | }; | ||
42 | |||
43 | #define AUTOGAIN_DEF 1 | ||
44 | |||
45 | /* specific webcam descriptor */ | 35 | /* specific webcam descriptor */ |
46 | struct sd { | 36 | struct sd { |
47 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 37 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
48 | 38 | ||
49 | struct gspca_ctrl ctrls[NCTRLS]; | ||
50 | |||
51 | u32 ae_res; | 39 | u32 ae_res; |
52 | s8 ag_cnt; | 40 | s8 ag_cnt; |
53 | #define AG_CNT_START 13 | 41 | #define AG_CNT_START 13 |
@@ -1667,17 +1655,13 @@ static int swap_bits(int v) | |||
1667 | return r; | 1655 | return r; |
1668 | } | 1656 | } |
1669 | 1657 | ||
1670 | static void setgain(struct gspca_dev *gspca_dev) | 1658 | static void setgain(struct gspca_dev *gspca_dev, u8 val) |
1671 | { | 1659 | { |
1672 | struct sd *sd = (struct sd *) gspca_dev; | 1660 | struct sd *sd = (struct sd *) gspca_dev; |
1673 | u8 val, v[2]; | 1661 | u8 v[2]; |
1674 | 1662 | ||
1675 | val = sd->ctrls[GAIN].val; | ||
1676 | switch (sd->webcam) { | 1663 | switch (sd->webcam) { |
1677 | case P35u: | 1664 | case P35u: |
1678 | /* Note the control goes from 0-255 not 0-127, but anything | ||
1679 | above 127 just means amplifying noise */ | ||
1680 | val >>= 1; /* 0 - 255 -> 0 - 127 */ | ||
1681 | reg_w(gspca_dev, 0x1026, &val, 1); | 1665 | reg_w(gspca_dev, 0x1026, &val, 1); |
1682 | break; | 1666 | break; |
1683 | case Kr651us: | 1667 | case Kr651us: |
@@ -1690,13 +1674,11 @@ static void setgain(struct gspca_dev *gspca_dev) | |||
1690 | } | 1674 | } |
1691 | } | 1675 | } |
1692 | 1676 | ||
1693 | static void setexposure(struct gspca_dev *gspca_dev) | 1677 | static void setexposure(struct gspca_dev *gspca_dev, s32 val) |
1694 | { | 1678 | { |
1695 | struct sd *sd = (struct sd *) gspca_dev; | 1679 | struct sd *sd = (struct sd *) gspca_dev; |
1696 | s16 val; | ||
1697 | u8 v[2]; | 1680 | u8 v[2]; |
1698 | 1681 | ||
1699 | val = sd->ctrls[EXPOSURE].val; | ||
1700 | switch (sd->webcam) { | 1682 | switch (sd->webcam) { |
1701 | case P35u: | 1683 | case P35u: |
1702 | v[0] = ((9 - val) << 3) | 0x01; | 1684 | v[0] = ((9 - val) << 3) | 0x01; |
@@ -1713,14 +1695,12 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
1713 | } | 1695 | } |
1714 | } | 1696 | } |
1715 | 1697 | ||
1716 | static void setautogain(struct gspca_dev *gspca_dev) | 1698 | static void setautogain(struct gspca_dev *gspca_dev, s32 val) |
1717 | { | 1699 | { |
1718 | struct sd *sd = (struct sd *) gspca_dev; | 1700 | struct sd *sd = (struct sd *) gspca_dev; |
1719 | int w, h; | 1701 | int w, h; |
1720 | 1702 | ||
1721 | if (gspca_dev->ctrl_dis & (1 << AUTOGAIN)) | 1703 | if (!val) { |
1722 | return; | ||
1723 | if (!sd->ctrls[AUTOGAIN].val) { | ||
1724 | sd->ag_cnt = -1; | 1704 | sd->ag_cnt = -1; |
1725 | return; | 1705 | return; |
1726 | } | 1706 | } |
@@ -1763,7 +1743,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1763 | if ((unsigned) webcam >= NWEBCAMS) | 1743 | if ((unsigned) webcam >= NWEBCAMS) |
1764 | webcam = 0; | 1744 | webcam = 0; |
1765 | sd->webcam = webcam; | 1745 | sd->webcam = webcam; |
1766 | gspca_dev->cam.ctrls = sd->ctrls; | ||
1767 | gspca_dev->cam.needs_full_bandwidth = 1; | 1746 | gspca_dev->cam.needs_full_bandwidth = 1; |
1768 | sd->ag_cnt = -1; | 1747 | sd->ag_cnt = -1; |
1769 | 1748 | ||
@@ -1834,33 +1813,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1834 | break; | 1813 | break; |
1835 | } | 1814 | } |
1836 | } | 1815 | } |
1837 | switch (sd->webcam) { | ||
1838 | case P35u: | ||
1839 | /* sd->ctrls[EXPOSURE].max = 9; | ||
1840 | * sd->ctrls[EXPOSURE].def = 9; */ | ||
1841 | /* coarse expo auto gain function gain minimum, to avoid | ||
1842 | * a large settings jump the first auto adjustment */ | ||
1843 | sd->ctrls[GAIN].def = 255 / 5 * 2; | ||
1844 | break; | ||
1845 | case Cvideopro: | ||
1846 | case DvcV6: | ||
1847 | case Kritter: | ||
1848 | gspca_dev->ctrl_dis = (1 << GAIN) | (1 << AUTOGAIN); | ||
1849 | /* fall thru */ | ||
1850 | case Kr651us: | ||
1851 | sd->ctrls[EXPOSURE].max = 315; | ||
1852 | sd->ctrls[EXPOSURE].def = 150; | ||
1853 | break; | ||
1854 | default: | ||
1855 | gspca_dev->ctrl_dis = (1 << GAIN) | (1 << EXPOSURE) | ||
1856 | | (1 << AUTOGAIN); | ||
1857 | break; | ||
1858 | } | ||
1859 | 1816 | ||
1860 | #if AUTOGAIN_DEF | ||
1861 | if (!(gspca_dev->ctrl_dis & (1 << AUTOGAIN))) | ||
1862 | gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE); | ||
1863 | #endif | ||
1864 | return gspca_dev->usb_err; | 1817 | return gspca_dev->usb_err; |
1865 | } | 1818 | } |
1866 | 1819 | ||
@@ -1925,9 +1878,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1925 | break; | 1878 | break; |
1926 | } | 1879 | } |
1927 | 1880 | ||
1928 | setgain(gspca_dev); | 1881 | v4l2_ctrl_handler_setup(&gspca_dev->ctrl_handler); |
1929 | setexposure(gspca_dev); | ||
1930 | setautogain(gspca_dev); | ||
1931 | sd->exp_too_high_cnt = 0; | 1882 | sd->exp_too_high_cnt = 0; |
1932 | sd->exp_too_low_cnt = 0; | 1883 | sd->exp_too_low_cnt = 0; |
1933 | return gspca_dev->usb_err; | 1884 | return gspca_dev->usb_err; |
@@ -1987,24 +1938,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1987 | } | 1938 | } |
1988 | } | 1939 | } |
1989 | 1940 | ||
1990 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
1991 | { | ||
1992 | struct sd *sd = (struct sd *) gspca_dev; | ||
1993 | |||
1994 | sd->ctrls[AUTOGAIN].val = val; | ||
1995 | if (val) | ||
1996 | gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE); | ||
1997 | else | ||
1998 | gspca_dev->ctrl_inac = 0; | ||
1999 | if (gspca_dev->streaming) | ||
2000 | setautogain(gspca_dev); | ||
2001 | return gspca_dev->usb_err; | ||
2002 | } | ||
2003 | |||
2004 | #define WANT_REGULAR_AUTOGAIN | ||
2005 | #define WANT_COARSE_EXPO_AUTOGAIN | ||
2006 | #include "autogain_functions.h" | ||
2007 | |||
2008 | static void do_autogain(struct gspca_dev *gspca_dev) | 1941 | static void do_autogain(struct gspca_dev *gspca_dev) |
2009 | { | 1942 | { |
2010 | struct sd *sd = (struct sd *) gspca_dev; | 1943 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2024,62 +1957,100 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
2024 | 1957 | ||
2025 | switch (sd->webcam) { | 1958 | switch (sd->webcam) { |
2026 | case P35u: | 1959 | case P35u: |
2027 | coarse_grained_expo_autogain(gspca_dev, luma, 100, 5); | 1960 | gspca_coarse_grained_expo_autogain(gspca_dev, luma, 100, 5); |
2028 | break; | 1961 | break; |
2029 | default: | 1962 | default: |
2030 | auto_gain_n_exposure(gspca_dev, luma, 100, 5, 230, 0); | 1963 | gspca_expo_autogain(gspca_dev, luma, 100, 5, 230, 0); |
2031 | break; | 1964 | break; |
2032 | } | 1965 | } |
2033 | } | 1966 | } |
2034 | 1967 | ||
2035 | /* V4L2 controls supported by the driver */ | 1968 | |
2036 | static const struct ctrl sd_ctrls[NCTRLS] = { | 1969 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) |
2037 | [GAIN] = { | 1970 | { |
2038 | { | 1971 | struct gspca_dev *gspca_dev = |
2039 | .id = V4L2_CID_GAIN, | 1972 | container_of(ctrl->handler, struct gspca_dev, ctrl_handler); |
2040 | .type = V4L2_CTRL_TYPE_INTEGER, | 1973 | |
2041 | .name = "Gain", | 1974 | gspca_dev->usb_err = 0; |
2042 | .minimum = 0, | 1975 | |
2043 | .maximum = 253, | 1976 | if (!gspca_dev->streaming) |
2044 | .step = 1, | 1977 | return 0; |
2045 | .default_value = 128 | 1978 | |
2046 | }, | 1979 | switch (ctrl->id) { |
2047 | .set_control = setgain | 1980 | /* autogain/gain/exposure control cluster */ |
2048 | }, | 1981 | case V4L2_CID_AUTOGAIN: |
2049 | [EXPOSURE] = { | 1982 | if (ctrl->is_new) |
2050 | { | 1983 | setautogain(gspca_dev, ctrl->val); |
2051 | .id = V4L2_CID_EXPOSURE, | 1984 | if (!ctrl->val) { |
2052 | .type = V4L2_CTRL_TYPE_INTEGER, | 1985 | if (gspca_dev->gain->is_new) |
2053 | .name = "Exposure", | 1986 | setgain(gspca_dev, gspca_dev->gain->val); |
2054 | .minimum = 0, | 1987 | if (gspca_dev->exposure->is_new) |
2055 | .maximum = 9, | 1988 | setexposure(gspca_dev, |
2056 | .step = 1, | 1989 | gspca_dev->exposure->val); |
2057 | .default_value = 9 | 1990 | } |
2058 | }, | 1991 | break; |
2059 | .set_control = setexposure | 1992 | /* Some webcams only have exposure, so handle that separately from the |
2060 | }, | 1993 | autogain/gain/exposure cluster in the previous case. */ |
2061 | [AUTOGAIN] = { | 1994 | case V4L2_CID_EXPOSURE: |
2062 | { | 1995 | setexposure(gspca_dev, gspca_dev->exposure->val); |
2063 | .id = V4L2_CID_AUTOGAIN, | 1996 | break; |
2064 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 1997 | } |
2065 | .name = "Auto Gain", | 1998 | return gspca_dev->usb_err; |
2066 | .minimum = 0, | 1999 | } |
2067 | .maximum = 1, | 2000 | |
2068 | .step = 1, | 2001 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { |
2069 | .default_value = AUTOGAIN_DEF, | 2002 | .s_ctrl = sd_s_ctrl, |
2070 | .flags = V4L2_CTRL_FLAG_UPDATE | ||
2071 | }, | ||
2072 | .set = sd_setautogain | ||
2073 | }, | ||
2074 | }; | 2003 | }; |
2075 | 2004 | ||
2005 | static int sd_init_controls(struct gspca_dev *gspca_dev) | ||
2006 | { | ||
2007 | struct sd *sd = (struct sd *)gspca_dev; | ||
2008 | struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; | ||
2009 | |||
2010 | gspca_dev->vdev.ctrl_handler = hdl; | ||
2011 | v4l2_ctrl_handler_init(hdl, 3); | ||
2012 | switch (sd->webcam) { | ||
2013 | case P35u: | ||
2014 | gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
2015 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); | ||
2016 | /* For P35u choose coarse expo auto gain function gain minimum, | ||
2017 | * to avoid a large settings jump the first auto adjustment */ | ||
2018 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
2019 | V4L2_CID_GAIN, 0, 127, 1, 127 / 5 * 2); | ||
2020 | gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
2021 | V4L2_CID_EXPOSURE, 0, 9, 1, 9); | ||
2022 | break; | ||
2023 | case Kr651us: | ||
2024 | gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
2025 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); | ||
2026 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
2027 | V4L2_CID_GAIN, 0, 253, 1, 128); | ||
2028 | /* fall through */ | ||
2029 | case Cvideopro: | ||
2030 | case DvcV6: | ||
2031 | case Kritter: | ||
2032 | gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
2033 | V4L2_CID_EXPOSURE, 0, 315, 1, 150); | ||
2034 | break; | ||
2035 | default: | ||
2036 | break; | ||
2037 | } | ||
2038 | |||
2039 | if (hdl->error) { | ||
2040 | pr_err("Could not initialize controls\n"); | ||
2041 | return hdl->error; | ||
2042 | } | ||
2043 | if (gspca_dev->autogain) | ||
2044 | v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false); | ||
2045 | return 0; | ||
2046 | } | ||
2047 | |||
2076 | /* sub-driver description */ | 2048 | /* sub-driver description */ |
2077 | static const struct sd_desc sd_desc = { | 2049 | static const struct sd_desc sd_desc = { |
2078 | .name = MODULE_NAME, | 2050 | .name = MODULE_NAME, |
2079 | .ctrls = sd_ctrls, | ||
2080 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
2081 | .config = sd_config, | 2051 | .config = sd_config, |
2082 | .init = sd_init, | 2052 | .init = sd_init, |
2053 | .init_controls = sd_init_controls, | ||
2083 | .start = sd_start, | 2054 | .start = sd_start, |
2084 | .stopN = sd_stopN, | 2055 | .stopN = sd_stopN, |
2085 | .pkt_scan = sd_pkt_scan, | 2056 | .pkt_scan = sd_pkt_scan, |