Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: atmel: atmel-isc-base: expose white balance as v4l2 controls

This exposes the white balance configuration of the ISC as v4l2 controls
into userspace.
There are 8 controls available:
4 gain controls, sliders, for each of the BAYER components: R, B, GR, GB.
These gains are multipliers for each component, in format unsigned 0:4:9
with a default value of 512 (1.0 multiplier).
4 offset controls, sliders, for each of the BAYER components: R, B, GR, GB.
These offsets are added/substracted from each component, in format signed
1:12:0 with a default value of 0 (+/- 0)

To expose this to userspace, added 8 custom controls, in an auto cluster.

To summarize the functionality:
The auto cluster switch is the auto white balance control, and it works
like this:
AWB == 1: autowhitebalance is on, the do_white_balance button is inactive,
the gains/offsets are inactive, but volatile and readable.
Thus, the results of the whitebalance algorithm are available to userspace
to read at any time.
AWB == 0: autowhitebalance is off, cluster is in manual mode, user can
configure the gain/offsets directly. More than that, if the
do_white_balance button is pressed, the driver will perform
one-time-adjustment, (preferably with color checker card) and the userspace
can read again the new values.

With this feature, the userspace can save the coefficients and reinstall
them for example after reboot or reprobing the driver.

[hverkuil: fix checkpatch warning]
[hverkuil: minor spacing adjustments in the functionality description]

Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

authored by

Eugen Hristev and committed by
Mauro Carvalho Chehab
4e52889f bfaaa20d

+293 -40
+207 -39
drivers/media/platform/atmel/atmel-isc-base.c
··· 22 22 #include <linux/pm_runtime.h> 23 23 #include <linux/regmap.h> 24 24 #include <linux/videodev2.h> 25 + #include <linux/atmel-isc-media.h> 25 26 26 27 #include <media/v4l2-ctrls.h> 27 28 #include <media/v4l2-device.h> ··· 225 224 (((mbus_code) == MEDIA_BUS_FMT_Y10_1X10) | \ 226 225 (((mbus_code) == MEDIA_BUS_FMT_Y8_1X8))) 227 226 227 + #define ISC_CTRL_ISC_TO_V4L2(x) ((x) == ISC_WB_O_ZERO_VAL ? 0 : (x)) 228 + #define ISC_CTRL_V4L2_TO_ISC(x) ((x) ? (x) : ISC_WB_O_ZERO_VAL) 229 + 230 + static inline void isc_update_v4l2_ctrls(struct isc_device *isc) 231 + { 232 + struct isc_ctrls *ctrls = &isc->ctrls; 233 + 234 + /* In here we set the v4l2 controls w.r.t. our pipeline config */ 235 + v4l2_ctrl_s_ctrl(isc->r_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_R]); 236 + v4l2_ctrl_s_ctrl(isc->b_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_B]); 237 + v4l2_ctrl_s_ctrl(isc->gr_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_GR]); 238 + v4l2_ctrl_s_ctrl(isc->gb_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_GB]); 239 + 240 + v4l2_ctrl_s_ctrl(isc->r_off_ctrl, 241 + ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_R])); 242 + v4l2_ctrl_s_ctrl(isc->b_off_ctrl, 243 + ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_B])); 244 + v4l2_ctrl_s_ctrl(isc->gr_off_ctrl, 245 + ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_GR])); 246 + v4l2_ctrl_s_ctrl(isc->gb_off_ctrl, 247 + ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_GB])); 248 + } 249 + 228 250 static inline void isc_update_awb_ctrls(struct isc_device *isc) 229 251 { 230 252 struct isc_ctrls *ctrls = &isc->ctrls; 253 + 254 + /* In here we set our actual hw pipeline config */ 231 255 232 256 regmap_write(isc->regmap, ISC_WB_O_RGR, 233 257 (ISC_WB_O_ZERO_VAL - (ctrls->offset[ISC_HIS_CFG_MODE_R])) | ··· 688 662 689 663 bay_cfg = isc->config.sd_format->cfa_baycfg; 690 664 691 - if (ctrls->awb == ISC_WB_NONE) 692 - isc_reset_awb_ctrls(isc); 693 - 694 665 regmap_write(regmap, ISC_WB_CFG, bay_cfg); 695 666 isc_update_awb_ctrls(isc); 667 + isc_update_v4l2_ctrls(isc); 696 668 697 669 regmap_write(regmap, ISC_CFA_CFG, bay_cfg | ISC_CFA_CFG_EITPOL); 698 670 ··· 1420 1396 isc->try_config.sd_format != isc->config.sd_format) { 1421 1397 isc->ctrls.hist_stat = HIST_INIT; 1422 1398 isc_reset_awb_ctrls(isc); 1399 + isc_update_v4l2_ctrls(isc); 1423 1400 } 1424 1401 /* make the try configuration active */ 1425 1402 isc->config = isc->try_config; ··· 1839 1814 ctrls->hist_id = hist_id; 1840 1815 baysel = isc->config.sd_format->cfa_baycfg << ISC_HIS_CFG_BAYSEL_SHIFT; 1841 1816 1842 - /* if no more auto white balance, reset controls. */ 1843 - if (ctrls->awb == ISC_WB_NONE) 1844 - isc_reset_awb_ctrls(isc); 1845 - 1846 1817 pm_runtime_get_sync(isc->dev); 1847 1818 1848 1819 /* ··· 1863 1842 if (ctrls->awb == ISC_WB_ONETIME) { 1864 1843 v4l2_info(&isc->v4l2_dev, 1865 1844 "Completed one time white-balance adjustment.\n"); 1845 + /* update the v4l2 controls values */ 1846 + isc_update_v4l2_ctrls(isc); 1866 1847 ctrls->awb = ISC_WB_NONE; 1867 1848 } 1868 1849 } ··· 1896 1873 case V4L2_CID_GAMMA: 1897 1874 ctrls->gamma_index = ctrl->val; 1898 1875 break; 1899 - case V4L2_CID_AUTO_WHITE_BALANCE: 1900 - if (ctrl->val == 1) 1901 - ctrls->awb = ISC_WB_AUTO; 1902 - else 1903 - ctrls->awb = ISC_WB_NONE; 1904 - 1905 - /* we did not configure ISC yet */ 1906 - if (!isc->config.sd_format) 1907 - break; 1908 - 1909 - if (ctrls->hist_stat != HIST_ENABLED) 1910 - isc_reset_awb_ctrls(isc); 1911 - 1912 - if (isc->ctrls.awb == ISC_WB_AUTO && 1913 - vb2_is_streaming(&isc->vb2_vidq) && 1914 - ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) 1915 - isc_set_histogram(isc, true); 1916 - 1917 - break; 1918 - case V4L2_CID_DO_WHITE_BALANCE: 1919 - /* if AWB is enabled, do nothing */ 1920 - if (ctrls->awb == ISC_WB_AUTO) 1921 - return 0; 1922 - 1923 - ctrls->awb = ISC_WB_ONETIME; 1924 - isc_set_histogram(isc, true); 1925 - v4l2_dbg(1, debug, &isc->v4l2_dev, 1926 - "One time white-balance started.\n"); 1927 - break; 1928 1876 default: 1929 1877 return -EINVAL; 1930 1878 } ··· 1907 1913 .s_ctrl = isc_s_ctrl, 1908 1914 }; 1909 1915 1916 + static int isc_s_awb_ctrl(struct v4l2_ctrl *ctrl) 1917 + { 1918 + struct isc_device *isc = container_of(ctrl->handler, 1919 + struct isc_device, ctrls.handler); 1920 + struct isc_ctrls *ctrls = &isc->ctrls; 1921 + 1922 + if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) 1923 + return 0; 1924 + 1925 + switch (ctrl->id) { 1926 + case V4L2_CID_AUTO_WHITE_BALANCE: 1927 + if (ctrl->val == 1) 1928 + ctrls->awb = ISC_WB_AUTO; 1929 + else 1930 + ctrls->awb = ISC_WB_NONE; 1931 + 1932 + /* we did not configure ISC yet */ 1933 + if (!isc->config.sd_format) 1934 + break; 1935 + 1936 + /* configure the controls with new values from v4l2 */ 1937 + if (ctrl->cluster[ISC_CTRL_R_GAIN]->is_new) 1938 + ctrls->gain[ISC_HIS_CFG_MODE_R] = isc->r_gain_ctrl->val; 1939 + if (ctrl->cluster[ISC_CTRL_B_GAIN]->is_new) 1940 + ctrls->gain[ISC_HIS_CFG_MODE_B] = isc->b_gain_ctrl->val; 1941 + if (ctrl->cluster[ISC_CTRL_GR_GAIN]->is_new) 1942 + ctrls->gain[ISC_HIS_CFG_MODE_GR] = isc->gr_gain_ctrl->val; 1943 + if (ctrl->cluster[ISC_CTRL_GB_GAIN]->is_new) 1944 + ctrls->gain[ISC_HIS_CFG_MODE_GB] = isc->gb_gain_ctrl->val; 1945 + 1946 + if (ctrl->cluster[ISC_CTRL_R_OFF]->is_new) 1947 + ctrls->offset[ISC_HIS_CFG_MODE_R] = 1948 + ISC_CTRL_V4L2_TO_ISC(isc->r_off_ctrl->val); 1949 + if (ctrl->cluster[ISC_CTRL_B_OFF]->is_new) 1950 + ctrls->offset[ISC_HIS_CFG_MODE_B] = 1951 + ISC_CTRL_V4L2_TO_ISC(isc->b_off_ctrl->val); 1952 + if (ctrl->cluster[ISC_CTRL_GR_OFF]->is_new) 1953 + ctrls->offset[ISC_HIS_CFG_MODE_GR] = 1954 + ISC_CTRL_V4L2_TO_ISC(isc->gr_off_ctrl->val); 1955 + if (ctrl->cluster[ISC_CTRL_GB_OFF]->is_new) 1956 + ctrls->offset[ISC_HIS_CFG_MODE_GB] = 1957 + ISC_CTRL_V4L2_TO_ISC(isc->gb_off_ctrl->val); 1958 + 1959 + isc_update_awb_ctrls(isc); 1960 + 1961 + if (vb2_is_streaming(&isc->vb2_vidq)) { 1962 + /* 1963 + * If we are streaming, we can update profile to 1964 + * have the new settings in place. 1965 + */ 1966 + isc_update_profile(isc); 1967 + } else { 1968 + /* 1969 + * The auto cluster will activate automatically this 1970 + * control. This has to be deactivated when not 1971 + * streaming. 1972 + */ 1973 + v4l2_ctrl_activate(isc->do_wb_ctrl, false); 1974 + } 1975 + 1976 + /* if we have autowhitebalance on, start histogram procedure */ 1977 + if (ctrls->awb == ISC_WB_AUTO && 1978 + vb2_is_streaming(&isc->vb2_vidq) && 1979 + ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) 1980 + isc_set_histogram(isc, true); 1981 + 1982 + /* 1983 + * for one time whitebalance adjustment, check the button, 1984 + * if it's pressed, perform the one time operation. 1985 + */ 1986 + if (ctrls->awb == ISC_WB_NONE && 1987 + ctrl->cluster[ISC_CTRL_DO_WB]->is_new && 1988 + !(ctrl->cluster[ISC_CTRL_DO_WB]->flags & 1989 + V4L2_CTRL_FLAG_INACTIVE)) { 1990 + ctrls->awb = ISC_WB_ONETIME; 1991 + isc_set_histogram(isc, true); 1992 + v4l2_dbg(1, debug, &isc->v4l2_dev, 1993 + "One time white-balance started.\n"); 1994 + } 1995 + return 0; 1996 + } 1997 + return 0; 1998 + } 1999 + 2000 + static int isc_g_volatile_awb_ctrl(struct v4l2_ctrl *ctrl) 2001 + { 2002 + struct isc_device *isc = container_of(ctrl->handler, 2003 + struct isc_device, ctrls.handler); 2004 + struct isc_ctrls *ctrls = &isc->ctrls; 2005 + 2006 + switch (ctrl->id) { 2007 + /* being a cluster, this id will be called for every control */ 2008 + case V4L2_CID_AUTO_WHITE_BALANCE: 2009 + ctrl->cluster[ISC_CTRL_R_GAIN]->val = 2010 + ctrls->gain[ISC_HIS_CFG_MODE_R]; 2011 + ctrl->cluster[ISC_CTRL_B_GAIN]->val = 2012 + ctrls->gain[ISC_HIS_CFG_MODE_B]; 2013 + ctrl->cluster[ISC_CTRL_GR_GAIN]->val = 2014 + ctrls->gain[ISC_HIS_CFG_MODE_GR]; 2015 + ctrl->cluster[ISC_CTRL_GB_GAIN]->val = 2016 + ctrls->gain[ISC_HIS_CFG_MODE_GB]; 2017 + 2018 + ctrl->cluster[ISC_CTRL_R_OFF]->val = 2019 + ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_R]); 2020 + ctrl->cluster[ISC_CTRL_B_OFF]->val = 2021 + ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_B]); 2022 + ctrl->cluster[ISC_CTRL_GR_OFF]->val = 2023 + ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_GR]); 2024 + ctrl->cluster[ISC_CTRL_GB_OFF]->val = 2025 + ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_GB]); 2026 + break; 2027 + } 2028 + return 0; 2029 + } 2030 + 2031 + static const struct v4l2_ctrl_ops isc_awb_ops = { 2032 + .s_ctrl = isc_s_awb_ctrl, 2033 + .g_volatile_ctrl = isc_g_volatile_awb_ctrl, 2034 + }; 2035 + 2036 + #define ISC_CTRL_OFF(_name, _id, _name_str) \ 2037 + static const struct v4l2_ctrl_config _name = { \ 2038 + .ops = &isc_awb_ops, \ 2039 + .id = _id, \ 2040 + .name = _name_str, \ 2041 + .type = V4L2_CTRL_TYPE_INTEGER, \ 2042 + .flags = V4L2_CTRL_FLAG_SLIDER, \ 2043 + .min = -4095, \ 2044 + .max = 4095, \ 2045 + .step = 1, \ 2046 + .def = 0, \ 2047 + } 2048 + 2049 + ISC_CTRL_OFF(isc_r_off_ctrl, ISC_CID_R_OFFSET, "Red Component Offset"); 2050 + ISC_CTRL_OFF(isc_b_off_ctrl, ISC_CID_B_OFFSET, "Blue Component Offset"); 2051 + ISC_CTRL_OFF(isc_gr_off_ctrl, ISC_CID_GR_OFFSET, "Green Red Component Offset"); 2052 + ISC_CTRL_OFF(isc_gb_off_ctrl, ISC_CID_GB_OFFSET, "Green Blue Component Offset"); 2053 + 2054 + #define ISC_CTRL_GAIN(_name, _id, _name_str) \ 2055 + static const struct v4l2_ctrl_config _name = { \ 2056 + .ops = &isc_awb_ops, \ 2057 + .id = _id, \ 2058 + .name = _name_str, \ 2059 + .type = V4L2_CTRL_TYPE_INTEGER, \ 2060 + .flags = V4L2_CTRL_FLAG_SLIDER, \ 2061 + .min = 0, \ 2062 + .max = 8191, \ 2063 + .step = 1, \ 2064 + .def = 512, \ 2065 + } 2066 + 2067 + ISC_CTRL_GAIN(isc_r_gain_ctrl, ISC_CID_R_GAIN, "Red Component Gain"); 2068 + ISC_CTRL_GAIN(isc_b_gain_ctrl, ISC_CID_B_GAIN, "Blue Component Gain"); 2069 + ISC_CTRL_GAIN(isc_gr_gain_ctrl, ISC_CID_GR_GAIN, "Green Red Component Gain"); 2070 + ISC_CTRL_GAIN(isc_gb_gain_ctrl, ISC_CID_GB_GAIN, "Green Blue Component Gain"); 2071 + 1910 2072 static int isc_ctrl_init(struct isc_device *isc) 1911 2073 { 1912 2074 const struct v4l2_ctrl_ops *ops = &isc_ctrl_ops; ··· 2073 1923 ctrls->hist_stat = HIST_INIT; 2074 1924 isc_reset_awb_ctrls(isc); 2075 1925 2076 - ret = v4l2_ctrl_handler_init(hdl, 5); 1926 + ret = v4l2_ctrl_handler_init(hdl, 13); 2077 1927 if (ret < 0) 2078 1928 return ret; 2079 1929 ··· 2083 1933 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -1024, 1023, 1, 0); 2084 1934 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -2048, 2047, 1, 256); 2085 1935 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAMMA, 0, GAMMA_MAX, 1, 2); 2086 - v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1); 1936 + isc->awb_ctrl = v4l2_ctrl_new_std(hdl, &isc_awb_ops, 1937 + V4L2_CID_AUTO_WHITE_BALANCE, 1938 + 0, 1, 1, 1); 2087 1939 2088 1940 /* do_white_balance is a button, so min,max,step,default are ignored */ 2089 - isc->do_wb_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_DO_WHITE_BALANCE, 1941 + isc->do_wb_ctrl = v4l2_ctrl_new_std(hdl, &isc_awb_ops, 1942 + V4L2_CID_DO_WHITE_BALANCE, 2090 1943 0, 0, 0, 0); 2091 1944 2092 1945 if (!isc->do_wb_ctrl) { ··· 2099 1946 } 2100 1947 2101 1948 v4l2_ctrl_activate(isc->do_wb_ctrl, false); 1949 + 1950 + isc->r_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_r_gain_ctrl, NULL); 1951 + isc->b_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_b_gain_ctrl, NULL); 1952 + isc->gr_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gr_gain_ctrl, NULL); 1953 + isc->gb_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gb_gain_ctrl, NULL); 1954 + isc->r_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_r_off_ctrl, NULL); 1955 + isc->b_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_b_off_ctrl, NULL); 1956 + isc->gr_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gr_off_ctrl, NULL); 1957 + isc->gb_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gb_off_ctrl, NULL); 1958 + 1959 + /* 1960 + * The cluster is in auto mode with autowhitebalance enabled 1961 + * and manual mode otherwise. 1962 + */ 1963 + v4l2_ctrl_auto_cluster(10, &isc->awb_ctrl, 0, true); 2102 1964 2103 1965 v4l2_ctrl_handler_setup(hdl); 2104 1966
+22 -1
drivers/media/platform/atmel/atmel-isc.h
··· 213 213 struct fmt_config try_config; 214 214 215 215 struct isc_ctrls ctrls; 216 - struct v4l2_ctrl *do_wb_ctrl; 217 216 struct work_struct awb_work; 218 217 219 218 struct mutex lock; /* serialize access to file operations */ ··· 222 223 223 224 struct isc_subdev_entity *current_subdev; 224 225 struct list_head subdev_entities; 226 + 227 + struct { 228 + #define ISC_CTRL_DO_WB 1 229 + #define ISC_CTRL_R_GAIN 2 230 + #define ISC_CTRL_B_GAIN 3 231 + #define ISC_CTRL_GR_GAIN 4 232 + #define ISC_CTRL_GB_GAIN 5 233 + #define ISC_CTRL_R_OFF 6 234 + #define ISC_CTRL_B_OFF 7 235 + #define ISC_CTRL_GR_OFF 8 236 + #define ISC_CTRL_GB_OFF 9 237 + struct v4l2_ctrl *awb_ctrl; 238 + struct v4l2_ctrl *do_wb_ctrl; 239 + struct v4l2_ctrl *r_gain_ctrl; 240 + struct v4l2_ctrl *b_gain_ctrl; 241 + struct v4l2_ctrl *gr_gain_ctrl; 242 + struct v4l2_ctrl *gb_gain_ctrl; 243 + struct v4l2_ctrl *r_off_ctrl; 244 + struct v4l2_ctrl *b_off_ctrl; 245 + struct v4l2_ctrl *gr_off_ctrl; 246 + struct v4l2_ctrl *gb_off_ctrl; 247 + }; 225 248 }; 226 249 227 250 #define GAMMA_MAX 2
+58
include/linux/atmel-isc-media.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2019 Microchip Technology Inc. and its subsidiaries 4 + * 5 + * Author: Eugen Hristev <eugen.hristev@microchip.com> 6 + */ 7 + 8 + #ifndef __LINUX_ATMEL_ISC_MEDIA_H__ 9 + #define __LINUX_ATMEL_ISC_MEDIA_H__ 10 + 11 + /* 12 + * There are 8 controls available: 13 + * 4 gain controls, sliders, for each of the BAYER components: R, B, GR, GB. 14 + * These gains are multipliers for each component, in format unsigned 0:4:9 with 15 + * a default value of 512 (1.0 multiplier). 16 + * 4 offset controls, sliders, for each of the BAYER components: R, B, GR, GB. 17 + * These offsets are added/substracted from each component, in format signed 18 + * 1:12:0 with a default value of 0 (+/- 0) 19 + * 20 + * To expose this to userspace, added 8 custom controls, in an auto cluster. 21 + * 22 + * To summarize the functionality: 23 + * The auto cluster switch is the auto white balance control, and it works 24 + * like this: 25 + * AWB == 1: autowhitebalance is on, the do_white_balance button is inactive, 26 + * the gains/offsets are inactive, but volatile and readable. 27 + * Thus, the results of the whitebalance algorithm are available to userspace to 28 + * read at any time. 29 + * AWB == 0: autowhitebalance is off, cluster is in manual mode, user can 30 + * configure the gain/offsets directly. 31 + * More than that, if the do_white_balance button is 32 + * pressed, the driver will perform one-time-adjustment, (preferably with color 33 + * checker card) and the userspace can read again the new values. 34 + * 35 + * With this feature, the userspace can save the coefficients and reinstall them 36 + * for example after reboot or reprobing the driver. 37 + */ 38 + 39 + enum atmel_isc_ctrl_id { 40 + /* Red component gain control */ 41 + ISC_CID_R_GAIN = (V4L2_CID_USER_ATMEL_ISC_BASE + 0), 42 + /* Blue component gain control */ 43 + ISC_CID_B_GAIN, 44 + /* Green Red component gain control */ 45 + ISC_CID_GR_GAIN, 46 + /* Green Blue gain control */ 47 + ISC_CID_GB_GAIN, 48 + /* Red component offset control */ 49 + ISC_CID_R_OFFSET, 50 + /* Blue component offset control */ 51 + ISC_CID_B_OFFSET, 52 + /* Green Red component offset control */ 53 + ISC_CID_GR_OFFSET, 54 + /* Green Blue component offset control */ 55 + ISC_CID_GB_OFFSET, 56 + }; 57 + 58 + #endif
+6
include/uapi/linux/v4l2-controls.h
··· 192 192 * We reserve 16 controls for this driver. */ 193 193 #define V4L2_CID_USER_IMX_BASE (V4L2_CID_USER_BASE + 0x10b0) 194 194 195 + /* 196 + * The base for the atmel isc driver controls. 197 + * We reserve 32 controls for this driver. 198 + */ 199 + #define V4L2_CID_USER_ATMEL_ISC_BASE (V4L2_CID_USER_BASE + 0x10c0) 200 + 195 201 /* MPEG-class control IDs */ 196 202 /* The MPEG controls are applicable to all codec controls 197 203 * and the 'MPEG' part of the define is historical */