History

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]

Eugen Hristev committed 6 years ago

Commit 4e528891 parent bfaaa204 files · +281 −28Browse files

Unified · Split

4 files
  1. drivers/media/platform/atmel/atmel-isc-base.c +195 −27
  2. drivers/media/platform/atmel/atmel-isc.h +22 −1
  3. include/linux/atmel-isc-media.h +58 −0
  4. include/uapi/linux/v4l2-controls.h +6 −0
drivers/media/platform/atmel/atmel-isc-base.c+195−27
@@ -22,6 +22,7 @@ · 21 unmodified lines
2222 #include <linux/pm_runtime.h>
2323 #include <linux/regmap.h>
2424 #include <linux/videodev2.h>
25+#include <linux/atmel-isc-media.h>
2526
2627 #include <media/v4l2-ctrls.h>
2728 #include <media/v4l2-device.h>
@@ -224,10 +225,35 @@ const u32 isc_gamma_table[GAMMA_MAX + 1][GAMMA_ENTRIES] = { · 196 unmodified lines
224225 (((mbus_code) == MEDIA_BUS_FMT_Y10_1X10) | \
225226 (((mbus_code) == MEDIA_BUS_FMT_Y8_1X8)))
226227
228+#define ISC_CTRL_ISC_TO_V4L2(x) ((x) == ISC_WB_O_ZERO_VAL ? 0 : (x))
229+#define ISC_CTRL_V4L2_TO_ISC(x) ((x) ? (x) : ISC_WB_O_ZERO_VAL)
230+
231+static inline void isc_update_v4l2_ctrls(struct isc_device *isc)
232+{
233+ struct isc_ctrls *ctrls = &isc->ctrls;
234+
235+ /* In here we set the v4l2 controls w.r.t. our pipeline config */
236+ v4l2_ctrl_s_ctrl(isc->r_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_R]);
237+ v4l2_ctrl_s_ctrl(isc->b_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_B]);
238+ v4l2_ctrl_s_ctrl(isc->gr_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_GR]);
239+ v4l2_ctrl_s_ctrl(isc->gb_gain_ctrl, ctrls->gain[ISC_HIS_CFG_MODE_GB]);
240+
241+ v4l2_ctrl_s_ctrl(isc->r_off_ctrl,
242+ ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_R]));
243+ v4l2_ctrl_s_ctrl(isc->b_off_ctrl,
244+ ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_B]));
245+ v4l2_ctrl_s_ctrl(isc->gr_off_ctrl,
246+ ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_GR]));
247+ v4l2_ctrl_s_ctrl(isc->gb_off_ctrl,
248+ ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_GB]));
249+}
250+
227251 static inline void isc_update_awb_ctrls(struct isc_device *isc)
228252 {
229253 struct isc_ctrls *ctrls = &isc->ctrls;
230254
255+ /* In here we set our actual hw pipeline config */
256+
231257 regmap_write(isc->regmap, ISC_WB_O_RGR,
232258 (ISC_WB_O_ZERO_VAL - (ctrls->offset[ISC_HIS_CFG_MODE_R])) |
233259 ((ISC_WB_O_ZERO_VAL - ctrls->offset[ISC_HIS_CFG_MODE_GR]) << 16));
@@ -662,11 +688,9 @@ static void isc_set_pipeline(struct isc_device *isc, u32 pipeline) · 428 unmodified lines
662688
663689 bay_cfg = isc->config.sd_format->cfa_baycfg;
664690
665− if (ctrls->awb == ISC_WB_NONE)
666− isc_reset_awb_ctrls(isc);
667−
668691 regmap_write(regmap, ISC_WB_CFG, bay_cfg);
669692 isc_update_awb_ctrls(isc);
693+ isc_update_v4l2_ctrls(isc);
670694
671695 regmap_write(regmap, ISC_CFA_CFG, bay_cfg | ISC_CFA_CFG_EITPOL);
672696
@@ -1396,6 +1420,7 @@ static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f) · 723 unmodified lines
13961420 isc->try_config.sd_format != isc->config.sd_format) {
13971421 isc->ctrls.hist_stat = HIST_INIT;
13981422 isc_reset_awb_ctrls(isc);
1423+ isc_update_v4l2_ctrls(isc);
13991424 }
14001425 /* make the try configuration active */
14011426 isc->config = isc->try_config;
@@ -1814,10 +1839,6 @@ static void isc_awb_work(struct work_struct *w) · 412 unmodified lines
18141839 ctrls->hist_id = hist_id;
18151840 baysel = isc->config.sd_format->cfa_baycfg << ISC_HIS_CFG_BAYSEL_SHIFT;
18161841
1817− /* if no more auto white balance, reset controls. */
1818− if (ctrls->awb == ISC_WB_NONE)
1819− isc_reset_awb_ctrls(isc);
1820−
18211842 pm_runtime_get_sync(isc->dev);
18221843
18231844 /*
@@ -1842,6 +1863,8 @@ static void isc_awb_work(struct work_struct *w) · 18 unmodified lines
18421863 if (ctrls->awb == ISC_WB_ONETIME) {
18431864 v4l2_info(&isc->v4l2_dev,
18441865 "Completed one time white-balance adjustment.\n");
1866+ /* update the v4l2 controls values */
1867+ isc_update_v4l2_ctrls(isc);
18451868 ctrls->awb = ISC_WB_NONE;
18461869 }
18471870 }
@@ -1873,6 +1896,27 @@ static int isc_s_ctrl(struct v4l2_ctrl *ctrl) · 25 unmodified lines
18731896 case V4L2_CID_GAMMA:
18741897 ctrls->gamma_index = ctrl->val;
18751898 break;
1899+ default:
1900+ return -EINVAL;
1901+ }
1902+
1903+ return 0;
1904+}
1905+
1906+static const struct v4l2_ctrl_ops isc_ctrl_ops = {
1907+ .s_ctrl = isc_s_ctrl,
1908+};
1909+
1910+static int isc_s_awb_ctrl(struct v4l2_ctrl *ctrl)
1911+{
1912+ struct isc_device *isc = container_of(ctrl->handler,
1913+ struct isc_device, ctrls.handler);
1914+ struct isc_ctrls *ctrls = &isc->ctrls;
1915+
1916+ if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
1917+ return 0;
1918+
1919+ switch (ctrl->id) {
18761920 case V4L2_CID_AUTO_WHITE_BALANCE:
18771921 if (ctrl->val == 1)
18781922 ctrls->awb = ISC_WB_AUTO;
@@ -1883,36 +1927,142 @@ static int isc_s_ctrl(struct v4l2_ctrl *ctrl) · 4 unmodified lines
18831927 if (!isc->config.sd_format)
18841928 break;
18851929
1886− if (ctrls->hist_stat != HIST_ENABLED)
1887− isc_reset_awb_ctrls(isc);
1930+ /* configure the controls with new values from v4l2 */
1931+ if (ctrl->cluster[ISC_CTRL_R_GAIN]->is_new)
1932+ ctrls->gain[ISC_HIS_CFG_MODE_R] = isc->r_gain_ctrl->val;
1933+ if (ctrl->cluster[ISC_CTRL_B_GAIN]->is_new)
1934+ ctrls->gain[ISC_HIS_CFG_MODE_B] = isc->b_gain_ctrl->val;
1935+ if (ctrl->cluster[ISC_CTRL_GR_GAIN]->is_new)
1936+ ctrls->gain[ISC_HIS_CFG_MODE_GR] = isc->gr_gain_ctrl->val;
1937+ if (ctrl->cluster[ISC_CTRL_GB_GAIN]->is_new)
1938+ ctrls->gain[ISC_HIS_CFG_MODE_GB] = isc->gb_gain_ctrl->val;
1939+
1940+ if (ctrl->cluster[ISC_CTRL_R_OFF]->is_new)
1941+ ctrls->offset[ISC_HIS_CFG_MODE_R] =
1942+ ISC_CTRL_V4L2_TO_ISC(isc->r_off_ctrl->val);
1943+ if (ctrl->cluster[ISC_CTRL_B_OFF]->is_new)
1944+ ctrls->offset[ISC_HIS_CFG_MODE_B] =
1945+ ISC_CTRL_V4L2_TO_ISC(isc->b_off_ctrl->val);
1946+ if (ctrl->cluster[ISC_CTRL_GR_OFF]->is_new)
1947+ ctrls->offset[ISC_HIS_CFG_MODE_GR] =
1948+ ISC_CTRL_V4L2_TO_ISC(isc->gr_off_ctrl->val);
1949+ if (ctrl->cluster[ISC_CTRL_GB_OFF]->is_new)
1950+ ctrls->offset[ISC_HIS_CFG_MODE_GB] =
1951+ ISC_CTRL_V4L2_TO_ISC(isc->gb_off_ctrl->val);
18881952
1889− if (isc->ctrls.awb == ISC_WB_AUTO &&
1953+ isc_update_awb_ctrls(isc);
1954+
1955+ if (vb2_is_streaming(&isc->vb2_vidq)) {
1956+ /*
1957+ * If we are streaming, we can update profile to
1958+ * have the new settings in place.
1959+ */
1960+ isc_update_profile(isc);
1961+ } else {
1962+ /*
1963+ * The auto cluster will activate automatically this
1964+ * control. This has to be deactivated when not
1965+ * streaming.
1966+ */
1967+ v4l2_ctrl_activate(isc->do_wb_ctrl, false);
1968+ }
1969+
1970+ /* if we have autowhitebalance on, start histogram procedure */
1971+ if (ctrls->awb == ISC_WB_AUTO &&
18901972 vb2_is_streaming(&isc->vb2_vidq) &&
18911973 ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code))
18921974 isc_set_histogram(isc, true);
18931975
1894− break;
1895− case V4L2_CID_DO_WHITE_BALANCE:
1896− /* if AWB is enabled, do nothing */
1897− if (ctrls->awb == ISC_WB_AUTO)
1898− return 0;
1976+ /*
1977+ * for one time whitebalance adjustment, check the button,
1978+ * if it's pressed, perform the one time operation.
1979+ */
1980+ if (ctrls->awb == ISC_WB_NONE &&
1981+ ctrl->cluster[ISC_CTRL_DO_WB]->is_new &&
1982+ !(ctrl->cluster[ISC_CTRL_DO_WB]->flags &
1983+ V4L2_CTRL_FLAG_INACTIVE)) {
1984+ ctrls->awb = ISC_WB_ONETIME;
1985+ isc_set_histogram(isc, true);
1986+ v4l2_dbg(1, debug, &isc->v4l2_dev,
1987+ "One time white-balance started.\n");
1988+ }
1989+ return 0;
1990+ }
1991+ return 0;
1992+}
18991993
1900− ctrls->awb = ISC_WB_ONETIME;
1901− isc_set_histogram(isc, true);
1902− v4l2_dbg(1, debug, &isc->v4l2_dev,
1903− "One time white-balance started.\n");
1994+static int isc_g_volatile_awb_ctrl(struct v4l2_ctrl *ctrl)
1995+{
1996+ struct isc_device *isc = container_of(ctrl->handler,
1997+ struct isc_device, ctrls.handler);
1998+ struct isc_ctrls *ctrls = &isc->ctrls;
1999+
2000+ switch (ctrl->id) {
2001+ /* being a cluster, this id will be called for every control */
2002+ case V4L2_CID_AUTO_WHITE_BALANCE:
2003+ ctrl->cluster[ISC_CTRL_R_GAIN]->val =
2004+ ctrls->gain[ISC_HIS_CFG_MODE_R];
2005+ ctrl->cluster[ISC_CTRL_B_GAIN]->val =
2006+ ctrls->gain[ISC_HIS_CFG_MODE_B];
2007+ ctrl->cluster[ISC_CTRL_GR_GAIN]->val =
2008+ ctrls->gain[ISC_HIS_CFG_MODE_GR];
2009+ ctrl->cluster[ISC_CTRL_GB_GAIN]->val =
2010+ ctrls->gain[ISC_HIS_CFG_MODE_GB];
2011+
2012+ ctrl->cluster[ISC_CTRL_R_OFF]->val =
2013+ ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_R]);
2014+ ctrl->cluster[ISC_CTRL_B_OFF]->val =
2015+ ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_B]);
2016+ ctrl->cluster[ISC_CTRL_GR_OFF]->val =
2017+ ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_GR]);
2018+ ctrl->cluster[ISC_CTRL_GB_OFF]->val =
2019+ ISC_CTRL_ISC_TO_V4L2(ctrls->offset[ISC_HIS_CFG_MODE_GB]);
19042020 break;
1905− default:
1906− return -EINVAL;
19072021 }
1908−
19092022 return 0;
19102023 }
19112024
1912−static const struct v4l2_ctrl_ops isc_ctrl_ops = {
1913− .s_ctrl = isc_s_ctrl,
2025+static const struct v4l2_ctrl_ops isc_awb_ops = {
2026+ .s_ctrl = isc_s_awb_ctrl,
2027+ .g_volatile_ctrl = isc_g_volatile_awb_ctrl,
19142028 };
19152029
2030+#define ISC_CTRL_OFF(_name, _id, _name_str) \
2031+ static const struct v4l2_ctrl_config _name = { \
2032+ .ops = &isc_awb_ops, \
2033+ .id = _id, \
2034+ .name = _name_str, \
2035+ .type = V4L2_CTRL_TYPE_INTEGER, \
2036+ .flags = V4L2_CTRL_FLAG_SLIDER, \
2037+ .min = -4095, \
2038+ .max = 4095, \
2039+ .step = 1, \
2040+ .def = 0, \
2041+ }
2042+
2043+ISC_CTRL_OFF(isc_r_off_ctrl, ISC_CID_R_OFFSET, "Red Component Offset");
2044+ISC_CTRL_OFF(isc_b_off_ctrl, ISC_CID_B_OFFSET, "Blue Component Offset");
2045+ISC_CTRL_OFF(isc_gr_off_ctrl, ISC_CID_GR_OFFSET, "Green Red Component Offset");
2046+ISC_CTRL_OFF(isc_gb_off_ctrl, ISC_CID_GB_OFFSET, "Green Blue Component Offset");
2047+
2048+#define ISC_CTRL_GAIN(_name, _id, _name_str) \
2049+ static const struct v4l2_ctrl_config _name = { \
2050+ .ops = &isc_awb_ops, \
2051+ .id = _id, \
2052+ .name = _name_str, \
2053+ .type = V4L2_CTRL_TYPE_INTEGER, \
2054+ .flags = V4L2_CTRL_FLAG_SLIDER, \
2055+ .min = 0, \
2056+ .max = 8191, \
2057+ .step = 1, \
2058+ .def = 512, \
2059+ }
2060+
2061+ISC_CTRL_GAIN(isc_r_gain_ctrl, ISC_CID_R_GAIN, "Red Component Gain");
2062+ISC_CTRL_GAIN(isc_b_gain_ctrl, ISC_CID_B_GAIN, "Blue Component Gain");
2063+ISC_CTRL_GAIN(isc_gr_gain_ctrl, ISC_CID_GR_GAIN, "Green Red Component Gain");
2064+ISC_CTRL_GAIN(isc_gb_gain_ctrl, ISC_CID_GB_GAIN, "Green Blue Component Gain");
2065+
19162066 static int isc_ctrl_init(struct isc_device *isc)
19172067 {
19182068 const struct v4l2_ctrl_ops *ops = &isc_ctrl_ops;
@@ -1923,7 +2073,7 @@ static int isc_ctrl_init(struct isc_device *isc) · 4 unmodified lines
19232073 ctrls->hist_stat = HIST_INIT;
19242074 isc_reset_awb_ctrls(isc);
19252075
1926− ret = v4l2_ctrl_handler_init(hdl, 5);
2076+ ret = v4l2_ctrl_handler_init(hdl, 13);
19272077 if (ret < 0)
19282078 return ret;
19292079
@@ -1933,10 +2083,13 @@ static int isc_ctrl_init(struct isc_device *isc) · 3 unmodified lines
19332083 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -1024, 1023, 1, 0);
19342084 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -2048, 2047, 1, 256);
19352085 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAMMA, 0, GAMMA_MAX, 1, 2);
1936− v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
2086+ isc->awb_ctrl = v4l2_ctrl_new_std(hdl, &isc_awb_ops,
2087+ V4L2_CID_AUTO_WHITE_BALANCE,
2088+ 0, 1, 1, 1);
19372089
19382090 /* do_white_balance is a button, so min,max,step,default are ignored */
1939− isc->do_wb_ctrl = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_DO_WHITE_BALANCE,
2091+ isc->do_wb_ctrl = v4l2_ctrl_new_std(hdl, &isc_awb_ops,
2092+ V4L2_CID_DO_WHITE_BALANCE,
19402093 0, 0, 0, 0);
19412094
19422095 if (!isc->do_wb_ctrl) {
@@ -1947,6 +2100,21 @@ static int isc_ctrl_init(struct isc_device *isc) · 4 unmodified lines
19472100
19482101 v4l2_ctrl_activate(isc->do_wb_ctrl, false);
19492102
2103+ isc->r_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_r_gain_ctrl, NULL);
2104+ isc->b_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_b_gain_ctrl, NULL);
2105+ isc->gr_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gr_gain_ctrl, NULL);
2106+ isc->gb_gain_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gb_gain_ctrl, NULL);
2107+ isc->r_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_r_off_ctrl, NULL);
2108+ isc->b_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_b_off_ctrl, NULL);
2109+ isc->gr_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gr_off_ctrl, NULL);
2110+ isc->gb_off_ctrl = v4l2_ctrl_new_custom(hdl, &isc_gb_off_ctrl, NULL);
2111+
2112+ /*
2113+ * The cluster is in auto mode with autowhitebalance enabled
2114+ * and manual mode otherwise.
2115+ */
2116+ v4l2_ctrl_auto_cluster(10, &isc->awb_ctrl, 0, true);
2117+
19502118 v4l2_ctrl_handler_setup(hdl);
19512119
19522120 return 0;
drivers/media/platform/atmel/atmel-isc.h+22−1
@@ -213,7 +213,6 @@ struct isc_device { · 212 unmodified lines
213213 struct fmt_config try_config;
214214
215215 struct isc_ctrls ctrls;
216− struct v4l2_ctrl *do_wb_ctrl;
217216 struct work_struct awb_work;
218217
219218 struct mutex lock; /* serialize access to file operations */
@@ -223,6 +222,28 @@ struct isc_device { · 3 unmodified lines
223222
224223 struct isc_subdev_entity *current_subdev;
225224 struct list_head subdev_entities;
225+
226+ struct {
227+#define ISC_CTRL_DO_WB 1
228+#define ISC_CTRL_R_GAIN 2
229+#define ISC_CTRL_B_GAIN 3
230+#define ISC_CTRL_GR_GAIN 4
231+#define ISC_CTRL_GB_GAIN 5
232+#define ISC_CTRL_R_OFF 6
233+#define ISC_CTRL_B_OFF 7
234+#define ISC_CTRL_GR_OFF 8
235+#define ISC_CTRL_GB_OFF 9
236+ struct v4l2_ctrl *awb_ctrl;
237+ struct v4l2_ctrl *do_wb_ctrl;
238+ struct v4l2_ctrl *r_gain_ctrl;
239+ struct v4l2_ctrl *b_gain_ctrl;
240+ struct v4l2_ctrl *gr_gain_ctrl;
241+ struct v4l2_ctrl *gb_gain_ctrl;
242+ struct v4l2_ctrl *r_off_ctrl;
243+ struct v4l2_ctrl *b_off_ctrl;
244+ struct v4l2_ctrl *gr_off_ctrl;
245+ struct v4l2_ctrl *gb_off_ctrl;
246+ };
226247 };
227248
228249 #define GAMMA_MAX 2
include/linux/atmel-isc-media.h+58−0
@@ -0,0 +1,58 @@
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
include/uapi/linux/v4l2-controls.h+6−0
@@ -192,6 +192,12 @@ enum v4l2_colorfx { · 191 unmodified lines
192192 * We reserve 16 controls for this driver. */
193193 #define V4L2_CID_USER_IMX_BASE (V4L2_CID_USER_BASE + 0x10b0)
194194
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+
195201 /* MPEG-class control IDs */
196202 /* The MPEG controls are applicable to all codec controls
197203 * and the 'MPEG' part of the define is historical */