1 /*
2 *
3 * SPDX-License-Identifier: GPL-2.0
4 *
5 * Copyright (C) 2011-2018 ARM or its affiliates
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19
20 #include <linux/version.h>
21 #include <media/v4l2-device.h>
22 #include <media/v4l2-ctrls.h>
23
24 #include "acamera_logger.h"
25
26 #include "isp-v4l2-common.h"
27 #include "isp-v4l2-ctrl.h"
28 #include "fw-interface.h"
29
isp_v4l2_ctrl_check_valid(struct v4l2_ctrl * ctrl)30 static int isp_v4l2_ctrl_check_valid( struct v4l2_ctrl *ctrl )
31 {
32 if ( ctrl->is_int == 1 ) {
33 if ( ctrl->val < ctrl->minimum || ctrl->val > ctrl->maximum )
34 return -EINVAL;
35 }
36
37 return 0;
38 }
39
isp_v4l2_ctrl_s_ctrl_standard(struct v4l2_ctrl * ctrl)40 static int isp_v4l2_ctrl_s_ctrl_standard( struct v4l2_ctrl *ctrl )
41 {
42 int ret = 0;
43 struct v4l2_ctrl_handler *hdl = ctrl->handler;
44
45 isp_v4l2_ctrl_t *isp_ctrl = std_hdl_to_isp_ctrl( hdl );
46 int ctx_id = isp_ctrl->ctx_id;
47
48 LOG( LOG_DEBUG, "Control - id:0x%x, val:%d, is_int:%d, min:%d, max:%d.\n",
49 ctrl->id, ctrl->val, ctrl->is_int, ctrl->minimum, ctrl->maximum );
50
51 if ( isp_v4l2_ctrl_check_valid( ctrl ) < 0 ) {
52 return -EINVAL;
53 }
54
55 switch ( ctrl->id ) {
56 case V4L2_CID_BRIGHTNESS:
57 ret = fw_intf_set_brightness( ctx_id, ctrl->val );
58 break;
59 case V4L2_CID_CONTRAST:
60 ret = fw_intf_set_contrast( ctx_id, ctrl->val );
61 break;
62 case V4L2_CID_SATURATION:
63 ret = fw_intf_set_saturation( ctx_id, ctrl->val );
64 break;
65 case V4L2_CID_HUE:
66 ret = fw_intf_set_hue( ctx_id, ctrl->val );
67 break;
68 case V4L2_CID_SHARPNESS:
69 ret = fw_intf_set_sharpness( ctx_id, ctrl->val );
70 break;
71 case V4L2_CID_COLORFX:
72 ret = fw_intf_set_color_fx( ctx_id, ctrl->val );
73 break;
74 case V4L2_CID_HFLIP:
75 ret = fw_intf_set_hflip( ctx_id, ctrl->val );
76 break;
77 case V4L2_CID_VFLIP:
78 ret = fw_intf_set_vflip( ctx_id, ctrl->val );
79 break;
80 case V4L2_CID_AUTOGAIN:
81 ret = fw_intf_set_autogain( ctx_id, ctrl->val );
82 break;
83 case V4L2_CID_GAIN:
84 ret = fw_intf_set_gain( ctx_id, ctrl->val );
85 break;
86 case V4L2_CID_EXPOSURE_AUTO:
87 ret = fw_intf_set_exposure_auto( ctx_id, ctrl->val );
88 break;
89 case V4L2_CID_EXPOSURE_ABSOLUTE:
90 ret = fw_intf_set_exposure( ctx_id, ctrl->val );
91 break;
92 case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
93 ret = fw_intf_set_variable_frame_rate( ctx_id, ctrl->val );
94 break;
95 case V4L2_CID_AUTO_WHITE_BALANCE:
96 ret = fw_intf_set_white_balance_auto( ctx_id, ctrl->val );
97 break;
98 case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
99 ret = fw_intf_set_white_balance( ctx_id, ctrl->val );
100 break;
101 case V4L2_CID_FOCUS_AUTO:
102 ret = fw_intf_set_focus_auto( ctx_id, ctrl->val );
103 break;
104 case V4L2_CID_FOCUS_ABSOLUTE:
105 ret = fw_intf_set_focus( ctx_id, ctrl->val );
106 break;
107 }
108
109 return ret;
110 }
111
isp_v4l2_ctrl_g_ctrl_standard(struct v4l2_ctrl * ctrl)112 static int isp_v4l2_ctrl_g_ctrl_standard( struct v4l2_ctrl *ctrl )
113 {
114 int ret = 0;
115 struct v4l2_ctrl_handler *hdl = ctrl->handler;
116
117 isp_v4l2_ctrl_t *isp_ctrl = std_hdl_to_isp_ctrl( hdl );
118 int ctx_id = isp_ctrl->ctx_id;
119
120 LOG( LOG_DEBUG, "Control - id:0x%x.\n", ctrl->id);
121
122 switch ( ctrl->id ) {
123 case V4L2_CID_EXPOSURE_AUTO:
124 ctrl->val = fw_intf_get_exposure_auto( ctx_id );
125 break;
126 case V4L2_CID_EXPOSURE_ABSOLUTE:
127 ctrl->val = fw_intf_get_exposure( ctx_id );
128 break;
129 case V4L2_CID_AUTO_WHITE_BALANCE:
130 ctrl->val = fw_intf_get_white_balance_auto( ctx_id );
131 break;
132 }
133
134 return ret;
135 }
136
isp_v4l2_ctrl_s_ctrl_custom(struct v4l2_ctrl * ctrl)137 static int isp_v4l2_ctrl_s_ctrl_custom( struct v4l2_ctrl *ctrl )
138 {
139 int ret = 0;
140 struct v4l2_ctrl_handler *hdl = ctrl->handler;
141
142 isp_v4l2_ctrl_t *isp_ctrl = cst_hdl_to_isp_ctrl( hdl );
143 int ctx_id = isp_ctrl->ctx_id;
144
145 LOG( LOG_DEBUG, "Control - id:0x%x, val:%d, is_int:%d, min:%d, max:%d.\n",
146 ctrl->id, ctrl->val, ctrl->is_int, ctrl->minimum, ctrl->maximum);
147
148 if ( isp_v4l2_ctrl_check_valid( ctrl ) < 0 ) {
149 LOG( LOG_ERR, "Invalid param: id:0x%x, val:0x%x, is_int:%d, min:0x%x, max:0x%x.\n",
150 ctrl->id, ctrl->val, ctrl->is_int, ctrl->minimum, ctrl->maximum );
151
152 return -EINVAL;
153 }
154
155 switch ( ctrl->id ) {
156 case ISP_V4L2_CID_TEST_PATTERN:
157 LOG( LOG_INFO, "new test_pattern: %d.\n", ctrl->val );
158 ret = fw_intf_set_test_pattern( ctx_id, ctrl->val );
159 break;
160 case ISP_V4L2_CID_TEST_PATTERN_TYPE:
161 LOG( LOG_INFO, "new test_pattern_type: %d.\n", ctrl->val );
162 ret = fw_intf_set_test_pattern_type( ctx_id, ctrl->val );
163 break;
164 case ISP_V4L2_CID_AF_REFOCUS:
165 LOG( LOG_INFO, "new focus: %d.\n", ctrl->val );
166 ret = fw_intf_set_af_refocus( ctx_id, ctrl->val );
167 break;
168 case ISP_V4L2_CID_SENSOR_PRESET:
169 LOG( LOG_INFO, "new sensor preset: %d.\n", ctrl->val );
170 ret = fw_intf_isp_set_sensor_preset( ctx_id, ctrl->val );
171 break;
172 case ISP_V4L2_CID_AF_ROI:
173 // map [0,127] to [0, 254] due to limitaton of V4L2_CTRL_TYPE_INTEGER.
174 LOG( LOG_INFO, "new af roi: 0x%x.\n", ctrl->val * 2 );
175 ret = fw_intf_set_af_roi( ctx_id, ctrl->val * 2 );
176 break;
177 case ISP_V4L2_CID_OUTPUT_FR_ON_OFF:
178 LOG( LOG_INFO, "output FR on/off: 0x%x.\n", ctrl->val );
179 ret = fw_intf_set_output_fr_on_off( ctx_id, ctrl->val );
180 break;
181 case ISP_V4L2_CID_OUTPUT_DS1_ON_OFF:
182 LOG( LOG_INFO, "output DS1 on/off: 0x%x.\n", ctrl->val );
183 ret = fw_intf_set_output_ds1_on_off( ctx_id, ctrl->val );
184 break;
185 case ISP_V4L2_CID_CUSTOM_SENSOR_WDR_MODE:
186 LOG( LOG_INFO, "set custom wdr mode: 0x%x.\n", ctrl->val );
187 ret = fw_intf_set_custom_sensor_wdr_mode(ctx_id, ctrl->val);
188 break;
189 case ISP_V4L2_CID_CUSTOM_SENSOR_EXPOSURE:
190 LOG( LOG_INFO, "set custom exposure: 0x%x.\n", ctrl->val );
191 ret = fw_intf_set_custom_sensor_exposure(ctx_id, ctrl->val);
192 break;
193 case ISP_V4L2_CID_CUSTOM_SET_FR_FPS:
194 LOG( LOG_INFO, "set fr fps: 0x%x.\n", ctrl->val );
195 ret = fw_intf_set_custom_fr_fps(ctx_id, ctrl->val);
196 *(ctrl->p_new.p_s32) = 0;
197 break;
198 case ISP_V4L2_CID_CUSTOM_SET_SENSOR_TESTPATTERN:
199 LOG( LOG_INFO, "set sensor test pattern: 0x%x.\n", ctrl->val );
200 ret = fw_intf_set_custom_sensor_testpattern(ctx_id, ctrl->val);
201 break;
202 case ISP_V4L2_CID_CUSTOM_SENSOR_IR_CUT:
203 LOG( LOG_INFO, "set_customer_sensor_ir_cut = %d\n", ctrl->val );
204 ret = fw_intf_set_customer_sensor_ir_cut(ctx_id, ctrl->val);
205 break;
206 case ISP_V4L2_CID_CUSTOM_SET_AE_ZONE_WEIGHT:
207 LOG( LOG_INFO, "set ae zone weight: 0x%llx.\n", *(ctrl->p_new.p_s64));
208 ret = fw_intf_set_customer_ae_zone_weight(ctx_id, *(ctrl->p_new.p_s64));
209 *(ctrl->p_new.p_s64) = 0;
210 break;
211 case ISP_V4L2_CID_CUSTOM_SET_AWB_ZONE_WEIGHT:
212 LOG( LOG_INFO, "set awb zone weight: 0x%llx.\n", *(ctrl->p_new.p_s64));
213 ret = fw_intf_set_customer_awb_zone_weight(ctx_id, *(ctrl->p_new.p_s64));
214 *(ctrl->p_new.p_s64) = 0;
215 break;
216 case ISP_V4L2_CID_CUSTOM_SET_MANUAL_EXPOSURE:
217 LOG( LOG_INFO, "set_customer_manual_exposure = %d\n", ctrl->val );
218 ret = fw_intf_set_customer_manual_exposure(ctx_id, ctrl->val);
219 ctrl->val = -1;
220 break;
221 case ISP_V4L2_CID_CUSTOM_SET_SENSOR_INTEGRATION_TIME:
222 LOG( LOG_INFO, "set_customer_integration_time = %d\n", ctrl->val );
223 ret = fw_intf_set_customer_sensor_integration_time(ctx_id, ctrl->val);
224 ctrl->val = -1;
225 break;
226 case ISP_V4L2_CID_CUSTOM_SET_SENSOR_ANALOG_GAIN:
227 LOG( LOG_INFO, "set_customer_sensor_analog_gain = %d\n", ctrl->val );
228 ret = fw_intf_set_customer_sensor_analog_gain(ctx_id, ctrl->val);
229 ctrl->val = -1;
230 break;
231 case ISP_V4L2_CID_CUSTOM_SET_ISP_DIGITAL_GAIN:
232 LOG( LOG_INFO, "set_customer_isp_digital_gain = %d\n", ctrl->val );
233 ret = fw_intf_set_customer_isp_digital_gain(ctx_id, ctrl->val);
234 ctrl->val = -1;
235 break;
236 case ISP_V4L2_CID_CUSTOM_SET_STOP_SENSOR_UPDATE:
237 LOG( LOG_INFO, "set_customer_stop_sensor_update = %d\n", ctrl->val );
238 ret = fw_intf_set_customer_stop_sensor_update(ctx_id, ctrl->val);
239 ctrl->val = -1;
240 break;
241 case ISP_V4L2_CID_CUSTOM_SET_DS1_FPS:
242 LOG( LOG_INFO, "set ds1 fps: 0x%x.\n", ctrl->val );
243 ret = fw_intf_set_custom_ds1_fps(ctx_id, ctrl->val);
244 *(ctrl->p_new.p_s32) = 0;
245 break;
246 case ISP_V4L2_CID_AE_COMPENSATION:
247 LOG( LOG_INFO, "new ae compensation: %d.\n", ctrl->val );
248 ret = fw_intf_set_ae_compensation( ctx_id, ctrl->val );
249 break;
250 case ISP_V4L2_CID_CUSTOM_SET_SENSOR_DIGITAL_GAIN:
251 LOG( LOG_INFO, "set_customer_sensor_digital_gain = %d\n", ctrl->val );
252 ret = fw_intf_set_customer_sensor_digital_gain(ctx_id, ctrl->val);
253 ctrl->val = -1;
254 break;
255 case ISP_V4L2_CID_CUSTOM_SET_AWB_RED_GAIN:
256 LOG( LOG_INFO, "set_customer_awb_red_gain = %d\n", ctrl->val );
257 ret = fw_intf_set_customer_awb_red_gain(ctx_id, ctrl->val);
258 break;
259 case ISP_V4L2_CID_CUSTOM_SET_AWB_BLUE_GAIN:
260 LOG( LOG_INFO, "set_customer_awb_blue_gain = %d\n", ctrl->val );
261 ret = fw_intf_set_customer_awb_blue_gain(ctx_id, ctrl->val);
262 break;
263 case ISP_V4L2_CID_CUSTOM_SET_MAX_INTEGRATION_TIME:
264 LOG( LOG_INFO, "set_customer_max_integration_time = %d\n", ctrl->val );
265 ret = fw_intf_set_customer_max_integration_time(ctx_id, ctrl->val);
266 break;
267 case ISP_V4L2_CID_CUSTOM_SENSOR_FPS:
268 LOG( LOG_INFO, "set custom fps: %d.\n", ctrl->val );
269 ret = fw_intf_set_custom_sensor_fps(ctx_id, ctrl->val);
270 break;
271 case ISP_V4L2_CID_CUSTOM_SNR_MANUAL:
272 LOG( LOG_INFO, "set snr manual: %d.\n", ctrl->val );
273 ret = fw_intf_set_custom_snr_manual(ctx_id, ctrl->val);
274 break;
275 case ISP_V4L2_CID_CUSTOM_SNR_STRENGTH:
276 LOG( LOG_INFO, "set snr strength: %d.\n", ctrl->val );
277 ret = fw_intf_set_custom_snr_strength(ctx_id, ctrl->val);
278 break;
279 case ISP_V4L2_CID_CUSTOM_TNR_MANUAL:
280 LOG( LOG_INFO, "set tnr manual: %d.\n", ctrl->val );
281 ret = fw_intf_set_custom_tnr_manual(ctx_id, ctrl->val);
282 break;
283 case ISP_V4L2_CID_CUSTOM_TNR_OFFSET:
284 LOG( LOG_INFO, "set tnr offset: %d.\n", ctrl->val );
285 ret = fw_intf_set_custom_tnr_offset(ctx_id, ctrl->val);
286 break;
287 case ISP_V4L2_CID_CUSTOM_TEMPER_MODE:
288 LOG( LOG_INFO, "set temper mode: %d.\n", ctrl->val );
289 ret = fw_intf_set_customer_temper_mode(ctx_id, ctrl->val);
290 break;
291 case ISP_V4L2_CID_CUSTOM_WDR_SWITCH:
292 LOG( LOG_INFO, "set wdr mode: %d.\n", ctrl->val );
293 ret = fw_intf_set_customer_sensor_mode(ctx_id, ctrl->val);
294 break;
295 case ISP_V4L2_CID_CUSTOM_ANTIFLICKER:
296 LOG( LOG_INFO, "set anti flicker: %d.\n", ctrl->val );
297 ret = fw_intf_set_customer_antiflicker(ctx_id, ctrl->val);
298 break;
299 case ISP_V4L2_CID_CUSTOM_DEFOG_SWITCH:
300 LOG( LOG_INFO, "set defog mode: %d.\n", ctrl->val );
301 ret = fw_intf_set_customer_defog_mode(ctx_id, ctrl->val);
302 break;
303 case ISP_V4L2_CID_CUSTOM_DEFOG_STRENGTH:
304 LOG( LOG_INFO, "set defog strength: %d.\n", ctrl->val );
305 ret = fw_intf_set_customer_defog_ratio(ctx_id, ctrl->val);
306 break;
307 }
308
309 return ret;
310 }
311
isp_v4l2_ctrl_g_ctrl_custom(struct v4l2_ctrl * ctrl)312 static int isp_v4l2_ctrl_g_ctrl_custom( struct v4l2_ctrl *ctrl )
313 {
314 int ret = 0;
315 struct v4l2_ctrl_handler *hdl = ctrl->handler;
316
317 isp_v4l2_ctrl_t *isp_ctrl = cst_hdl_to_isp_ctrl( hdl );
318 int ctx_id = isp_ctrl->ctx_id;
319
320 LOG( LOG_DEBUG, "Control - id:0x%x, val:%d, is_int:%d, min:%d, max:%d.\n",
321 ctrl->id, ctrl->val, ctrl->is_int, ctrl->minimum, ctrl->maximum);
322
323 switch ( ctrl->id ) {
324 case ISP_V4L2_CID_AE_COMPENSATION:
325 LOG( LOG_INFO, "get ae compensation: %d.\n" );
326 ctrl->val = fw_intf_get_ae_compensation(ctx_id);
327 break;
328 case ISP_V4L2_CID_CUSTOM_SNR_MANUAL:
329 LOG( LOG_INFO, "get snr manual: %d.\n" );
330 ctrl->val = fw_intf_get_custom_snr_manual(ctx_id);
331 break;
332 case ISP_V4L2_CID_CUSTOM_SNR_STRENGTH:
333 LOG( LOG_INFO, "get snr strength: %d.\n" );
334 ctrl->val = fw_intf_get_custom_snr_strength(ctx_id);
335 break;
336 case ISP_V4L2_CID_CUSTOM_TNR_MANUAL:
337 LOG( LOG_INFO, "get tnr manual: %d.\n" );
338 ctrl->val = fw_intf_get_custom_tnr_manual(ctx_id);
339 break;
340 case ISP_V4L2_CID_CUSTOM_TNR_OFFSET:
341 LOG( LOG_INFO, "get tnr offset: %d.\n" );
342 ctrl->val = fw_intf_get_custom_tnr_offset(ctx_id);
343 break;
344 case ISP_V4L2_CID_CUSTOM_TEMPER_MODE:
345 LOG( LOG_INFO, "get temper mode: %d.\n" );
346 ctrl->val = fw_intf_get_custom_temper_mode(ctx_id);
347 break;
348 case ISP_V4L2_CID_CUSTOM_WDR_SWITCH:
349 LOG( LOG_INFO, "get wdr mode: %d.\n" );
350 ctrl->val = fw_intf_get_customer_sensor_mode(ctx_id);
351 break;
352 case ISP_V4L2_CID_CUSTOM_ANTIFLICKER:
353 LOG( LOG_INFO, "get anti flicker: %d.\n" );
354 ctrl->val = fw_intf_get_customer_antiflicker(ctx_id);
355 break;
356 default:
357 ret = 1;
358 break;
359 }
360
361 return ret;
362 }
363
364 static const struct v4l2_ctrl_ops isp_v4l2_ctrl_ops_custom = {
365 .s_ctrl = isp_v4l2_ctrl_s_ctrl_custom,
366 .g_volatile_ctrl = isp_v4l2_ctrl_g_ctrl_custom,
367 };
368
369 static const struct v4l2_ctrl_config isp_v4l2_ctrl_test_pattern = {
370 .ops = &isp_v4l2_ctrl_ops_custom,
371 .id = ISP_V4L2_CID_TEST_PATTERN,
372 .name = "ISP Test Pattern",
373 .type = V4L2_CTRL_TYPE_INTEGER,
374 .min = 0,
375 .max = 1,
376 .step = 1,
377 .def = 0,
378 };
379
380 static const struct v4l2_ctrl_config isp_v4l2_ctrl_test_pattern_type = {
381 .ops = &isp_v4l2_ctrl_ops_custom,
382 .id = ISP_V4L2_CID_TEST_PATTERN_TYPE,
383 .name = "ISP Test Pattern Type",
384 .type = V4L2_CTRL_TYPE_INTEGER,
385 .min = 0,
386 .max = 3,
387 .step = 1,
388 .def = 3,
389 };
390
391 static const struct v4l2_ctrl_config isp_v4l2_ctrl_af_refocus = {
392 .ops = &isp_v4l2_ctrl_ops_custom,
393 .id = ISP_V4L2_CID_AF_REFOCUS,
394 .name = "ISP AF Refocus",
395 .type = V4L2_CTRL_TYPE_BUTTON,
396 .min = 0,
397 .max = 0,
398 .step = 0,
399 .def = 0,
400 };
401
402 static const struct v4l2_ctrl_config isp_v4l2_ctrl_sensor_preset = {
403 .ops = &isp_v4l2_ctrl_ops_custom,
404 .id = ISP_V4L2_CID_SENSOR_PRESET,
405 .name = "ISP Sensor Preset",
406 .type = V4L2_CTRL_TYPE_INTEGER,
407 .min = 0,
408 .max = 5,
409 .step = 1,
410 .def = 0,
411 };
412
413
414 static const struct v4l2_ctrl_config isp_v4l2_ctrl_af_roi = {
415 .ops = &isp_v4l2_ctrl_ops_custom,
416 .id = ISP_V4L2_CID_AF_ROI,
417 .name = "ISP AF ROI",
418 .type = V4L2_CTRL_TYPE_INTEGER,
419 .min = 0,
420 .max = 0x7F7F7F7F,
421 .step = 1,
422 .def = 0x20206060,
423 };
424
425
426 static const struct v4l2_ctrl_config isp_v4l2_ctrl_output_fr_on_off = {
427 .ops = &isp_v4l2_ctrl_ops_custom,
428 .id = ISP_V4L2_CID_OUTPUT_FR_ON_OFF,
429 .name = "ISP FR ON/OFF",
430 .type = V4L2_CTRL_TYPE_INTEGER,
431 .min = 0,
432 .max = 0x7FFFFFFF,
433 .step = 1,
434 .def = 0,
435 };
436
437
438 static const struct v4l2_ctrl_config isp_v4l2_ctrl_output_ds1_on_off = {
439 .ops = &isp_v4l2_ctrl_ops_custom,
440 .id = ISP_V4L2_CID_OUTPUT_DS1_ON_OFF,
441 .name = "ISP DS1 ON/OFF",
442 .type = V4L2_CTRL_TYPE_INTEGER,
443 .min = 0,
444 .max = 0x7FFFFFFF,
445 .step = 1,
446 .def = 0,
447 };
448
449
450 static const struct v4l2_ctrl_config isp_v4l2_ctrl_sensor_wdr_mode = {
451 .ops = &isp_v4l2_ctrl_ops_custom,
452 .id = ISP_V4L2_CID_CUSTOM_SENSOR_WDR_MODE,
453 .name = "ISP Sensor wdr mode",
454 .type = V4L2_CTRL_TYPE_INTEGER,
455 .min = 0,
456 .max = 3,
457 .step = 1,
458 .def = 0,
459 };
460
461 static const struct v4l2_ctrl_config isp_v4l2_ctrl_sensor_exposure = {
462 .ops = &isp_v4l2_ctrl_ops_custom,
463 .id = ISP_V4L2_CID_CUSTOM_SENSOR_EXPOSURE,
464 .name = "ISP Sensor exposure",
465 .type = V4L2_CTRL_TYPE_INTEGER,
466 .min = 1,
467 .max = 4,
468 .step = 1,
469 .def = 1,
470 };
471
472 static const struct v4l2_ctrl_config isp_v4l2_ctrl_fr_fps = {
473 .ops = &isp_v4l2_ctrl_ops_custom,
474 .id = ISP_V4L2_CID_CUSTOM_SET_FR_FPS,
475 .name = "ISP fr fps",
476 .type = V4L2_CTRL_TYPE_INTEGER,
477 .min = 0,
478 .max = 120,
479 .step = 1,
480 .def = 0,
481 };
482
483 static const struct v4l2_ctrl_config isp_v4l2_ctrl_ds1_fps = {
484 .ops = &isp_v4l2_ctrl_ops_custom,
485 .id = ISP_V4L2_CID_CUSTOM_SET_DS1_FPS,
486 .name = "ISP ds1 fps",
487 .type = V4L2_CTRL_TYPE_INTEGER,
488 .min = 0,
489 .max = 120,
490 .step = 1,
491 .def = 0,
492 };
493
494 static const struct v4l2_ctrl_config isp_v4l2_ctrl_sensor_testpattern = {
495 .ops = &isp_v4l2_ctrl_ops_custom,
496 .id = ISP_V4L2_CID_CUSTOM_SET_SENSOR_TESTPATTERN,
497 .name = "ISP Sensor test pattern",
498 .type = V4L2_CTRL_TYPE_INTEGER,
499 .min = 0,
500 .max = 10,
501 .step = 1,
502 .def = 0,
503 };
504
505 static const struct v4l2_ctrl_config isp_v4l2_ctrl_sensor_ir_cut = {
506 .ops = &isp_v4l2_ctrl_ops_custom,
507 .id = ISP_V4L2_CID_CUSTOM_SENSOR_IR_CUT,
508 .name = "sensor ir cut set",
509 .type = V4L2_CTRL_TYPE_INTEGER,
510 .min = -1,
511 .max = 2,
512 .step = 1,
513 .def = -1,
514 };
515
516 static const struct v4l2_ctrl_config isp_v4l2_ctrl_ae_zone_weight = {
517 .ops = &isp_v4l2_ctrl_ops_custom,
518 .id = ISP_V4L2_CID_CUSTOM_SET_AE_ZONE_WEIGHT,
519 .name = "set isp ae zone weight",
520 .type = V4L2_CTRL_TYPE_INTEGER64,
521 .min = 0x8000000000000000,
522 .max = 0x7fffffffffffffff,
523 .step = 8,
524 .def = 0,
525 };
526
527 static const struct v4l2_ctrl_config isp_v4l2_ctrl_awb_zone_weight = {
528 .ops = &isp_v4l2_ctrl_ops_custom,
529 .id = ISP_V4L2_CID_CUSTOM_SET_AWB_ZONE_WEIGHT,
530 .name = "set isp awb zone weight",
531 .type = V4L2_CTRL_TYPE_INTEGER64,
532 .min = 0x8000000000000000,
533 .max = 0x7fffffffffffffff,
534 .step = 8,
535 .def = 0,
536 };
537
538 static const struct v4l2_ctrl_config isp_v4l2_ctrl_manual_exposure = {
539 .ops = &isp_v4l2_ctrl_ops_custom,
540 .id = ISP_V4L2_CID_CUSTOM_SET_MANUAL_EXPOSURE,
541 .name = "manual_exposure set",
542 .type = V4L2_CTRL_TYPE_INTEGER,
543 .min = -1,
544 .max = 2,
545 .step = 1,
546 .def = -1,
547 };
548
549 static const struct v4l2_ctrl_config isp_v4l2_ctrl_sensor_integration_time = {
550 .ops = &isp_v4l2_ctrl_ops_custom,
551 .id = ISP_V4L2_CID_CUSTOM_SET_SENSOR_INTEGRATION_TIME,
552 .name = "sensor_integration_timet set",
553 .type = V4L2_CTRL_TYPE_INTEGER,
554 .min = -1,
555 .max = 4000,
556 .step = 1,
557 .def = -1,
558 };
559
560 static const struct v4l2_ctrl_config isp_v4l2_ctrl_sensor_analog_gain = {
561 .ops = &isp_v4l2_ctrl_ops_custom,
562 .id = ISP_V4L2_CID_CUSTOM_SET_SENSOR_ANALOG_GAIN,
563 .name = "sensor_analog_gain set",
564 .type = V4L2_CTRL_TYPE_INTEGER,
565 .min = -1,
566 .max = 256,
567 .step = 1,
568 .def = -1,
569 };
570
571 static const struct v4l2_ctrl_config isp_v4l2_ctrl_isp_digital_gain = {
572 .ops = &isp_v4l2_ctrl_ops_custom,
573 .id = ISP_V4L2_CID_CUSTOM_SET_ISP_DIGITAL_GAIN,
574 .name = "isp_digital_gain set",
575 .type = V4L2_CTRL_TYPE_INTEGER,
576 .min = -1,
577 .max = 256,
578 .step = 1,
579 .def = -1,
580 };
581
582 static const struct v4l2_ctrl_config isp_v4l2_ctrl_stop_sensor_update = {
583 .ops = &isp_v4l2_ctrl_ops_custom,
584 .id = ISP_V4L2_CID_CUSTOM_SET_STOP_SENSOR_UPDATE,
585 .name = "stop_sensor_update set",
586 .type = V4L2_CTRL_TYPE_INTEGER,
587 .min = -1,
588 .max = 2,
589 .step = 1,
590 .def = -1,
591 };
592
593 static const struct v4l2_ctrl_config isp_v4l2_ctrl_ae_compensation = {
594 .ops = &isp_v4l2_ctrl_ops_custom,
595 .id = ISP_V4L2_CID_AE_COMPENSATION,
596 .name = "ISP AE Compensation",
597 .type = V4L2_CTRL_TYPE_INTEGER,
598 .min = 0,
599 .max = 255,
600 .step = 1,
601 .def = 0,
602 };
603
604 static const struct v4l2_ctrl_config isp_v4l2_ctrl_sensor_digital_gain = {
605 .ops = &isp_v4l2_ctrl_ops_custom,
606 .id = ISP_V4L2_CID_CUSTOM_SET_SENSOR_DIGITAL_GAIN,
607 .name = "sensor_digital_gain set",
608 .type = V4L2_CTRL_TYPE_INTEGER,
609 .min = -1,
610 .max = 256,
611 .step = 1,
612 .def = -1,
613 };
614
615 static const struct v4l2_ctrl_config isp_v4l2_ctrl_awb_red_gain = {
616 .ops = &isp_v4l2_ctrl_ops_custom,
617 .id = ISP_V4L2_CID_CUSTOM_SET_AWB_RED_GAIN,
618 .name = "awb_red_gain set",
619 .type = V4L2_CTRL_TYPE_INTEGER,
620 .min = -1,
621 .max = 65535,
622 .step = 1,
623 .def = -1,
624 };
625
626 static const struct v4l2_ctrl_config isp_v4l2_ctrl_awb_blue_gain = {
627 .ops = &isp_v4l2_ctrl_ops_custom,
628 .id = ISP_V4L2_CID_CUSTOM_SET_AWB_BLUE_GAIN,
629 .name = "awb_blue_gain set",
630 .type = V4L2_CTRL_TYPE_INTEGER,
631 .min = -1,
632 .max = 65535,
633 .step = 1,
634 .def = -1,
635 };
636
637 static const struct v4l2_ctrl_config isp_v4l2_ctrl_max_integration_time = {
638 .ops = &isp_v4l2_ctrl_ops_custom,
639 .id = ISP_V4L2_CID_CUSTOM_SET_MAX_INTEGRATION_TIME,
640 .name = "max_int_time set",
641 .type = V4L2_CTRL_TYPE_INTEGER,
642 .min = -1,
643 .max = 5564,
644 .step = 1,
645 .def = -1,
646 };
647
648 static const struct v4l2_ctrl_config isp_v4l2_ctrl_sensor_fps = {
649 .ops = &isp_v4l2_ctrl_ops_custom,
650 .id = ISP_V4L2_CID_CUSTOM_SENSOR_FPS,
651 .name = "ISP Sensor fps",
652 .type = V4L2_CTRL_TYPE_INTEGER,
653 .min = 0,
654 .max = 120,
655 .step = 1,
656 .def = 0,
657 };
658
659 static const struct v4l2_ctrl_config isp_v4l2_ctrl_snr_manual = {
660 .ops = &isp_v4l2_ctrl_ops_custom,
661 .id = ISP_V4L2_CID_CUSTOM_SNR_MANUAL,
662 .name = "ISP SNR manual",
663 .type = V4L2_CTRL_TYPE_INTEGER,
664 .min = 0,
665 .max = 1,
666 .step = 1,
667 .def = 0,
668 };
669
670 static const struct v4l2_ctrl_config isp_v4l2_ctrl_snr_strength = {
671 .ops = &isp_v4l2_ctrl_ops_custom,
672 .id = ISP_V4L2_CID_CUSTOM_SNR_STRENGTH,
673 .name = "ISP SNR strength",
674 .type = V4L2_CTRL_TYPE_INTEGER,
675 .min = 0,
676 .max = 255,
677 .step = 1,
678 .def = 128,
679 };
680
681 static const struct v4l2_ctrl_config isp_v4l2_ctrl_tnr_manual = {
682 .ops = &isp_v4l2_ctrl_ops_custom,
683 .id = ISP_V4L2_CID_CUSTOM_TNR_MANUAL,
684 .name = "ISP TNR manual",
685 .type = V4L2_CTRL_TYPE_INTEGER,
686 .min = 0,
687 .max = 1,
688 .step = 1,
689 .def = 0,
690 };
691
692 static const struct v4l2_ctrl_config isp_v4l2_ctrl_tnr_offset = {
693 .ops = &isp_v4l2_ctrl_ops_custom,
694 .id = ISP_V4L2_CID_CUSTOM_TNR_OFFSET,
695 .name = "ISP TNR offset",
696 .type = V4L2_CTRL_TYPE_INTEGER,
697 .min = 0,
698 .max = 255,
699 .step = 1,
700 .def = 128,
701 };
702
703 static const struct v4l2_ctrl_config isp_v4l2_ctrl_temper_mode = {
704 .ops = &isp_v4l2_ctrl_ops_custom,
705 .id = ISP_V4L2_CID_CUSTOM_TEMPER_MODE,
706 .name = "ISP Temper mode",
707 .type = V4L2_CTRL_TYPE_INTEGER,
708 .min = 1,
709 .max = 2,
710 .step = 1,
711 .def = 1,
712 };
713
714 static const struct v4l2_ctrl_config isp_v4l2_ctrl_wdr_mode = {
715 .ops = &isp_v4l2_ctrl_ops_custom,
716 .id = ISP_V4L2_CID_CUSTOM_WDR_SWITCH,
717 .name = "ISP WDR mode",
718 .type = V4L2_CTRL_TYPE_INTEGER,
719 .min = 0,
720 .max = 2,
721 .step = 1,
722 .def = 0,
723 };
724
725 static const struct v4l2_ctrl_config isp_v4l2_ctrl_antiflicker = {
726 .ops = &isp_v4l2_ctrl_ops_custom,
727 .id = ISP_V4L2_CID_CUSTOM_ANTIFLICKER,
728 .name = "ISP Anti Flicker mode",
729 .type = V4L2_CTRL_TYPE_INTEGER,
730 .min = 0,
731 .max = 60,
732 .step = 5,
733 .def = 0,
734 };
735
736 static const struct v4l2_ctrl_config isp_v4l2_ctrl_defog_mode = {
737 .ops = &isp_v4l2_ctrl_ops_custom,
738 .id = ISP_V4L2_CID_CUSTOM_DEFOG_SWITCH,
739 .name = "Defog alg mode",
740 .type = V4L2_CTRL_TYPE_INTEGER,
741 .min = 0,
742 .max = 2,
743 .step = 1,
744 .def = 0,
745 };
746
747 static const struct v4l2_ctrl_config isp_v4l2_ctrl_defog_ratio = {
748 .ops = &isp_v4l2_ctrl_ops_custom,
749 .id = ISP_V4L2_CID_CUSTOM_DEFOG_STRENGTH,
750 .name = "Defog alg ratio delta",
751 .type = V4L2_CTRL_TYPE_INTEGER,
752 .min = 0,
753 .max = 4096,
754 .step = 1,
755 .def = 0,
756 };
757
758 static const struct v4l2_ctrl_ops isp_v4l2_ctrl_ops = {
759 .s_ctrl = isp_v4l2_ctrl_s_ctrl_standard,
760 .g_volatile_ctrl = isp_v4l2_ctrl_g_ctrl_standard,
761 };
762
763 static const struct v4l2_ctrl_config isp_v4l2_ctrl_class = {
764 .ops = &isp_v4l2_ctrl_ops_custom,
765 .flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY,
766 .id = ISP_V4L2_CID_ISP_V4L2_CLASS,
767 .name = "ARM ISP Controls",
768 .type = V4L2_CTRL_TYPE_CTRL_CLASS,
769 };
770
771 #define ADD_CTRL_STD( id, min, max, step, def ) \
772 { \
773 if ( fw_intf_validate_control( id ) ) { \
774 v4l2_ctrl_new_std( hdl_std_ctrl, &isp_v4l2_ctrl_ops, \
775 id, min, max, step, def ); \
776 } \
777 }
778
779 #define ADD_CTRL_STD_MENU( id, max, skipmask, def ) \
780 { \
781 if ( fw_intf_validate_control( id ) ) { \
782 v4l2_ctrl_new_std_menu( hdl_std_ctrl, &isp_v4l2_ctrl_ops, \
783 id, max, skipmask, def ); \
784 } \
785 }
786
787 #define ADD_CTRL_CST( id, cfg, priv ) \
788 { \
789 if ( fw_intf_validate_control( id ) ) { \
790 v4l2_ctrl_new_custom( hdl_cst_ctrl, cfg, priv ); \
791 } \
792 }
793
isp_v4l2_ctrl_init(uint32_t ctx_id,isp_v4l2_ctrl_t * ctrl)794 int isp_v4l2_ctrl_init( uint32_t ctx_id, isp_v4l2_ctrl_t *ctrl )
795 {
796 struct v4l2_ctrl_handler *hdl_std_ctrl = &ctrl->ctrl_hdl_std_ctrl;
797 struct v4l2_ctrl_handler *hdl_cst_ctrl = &ctrl->ctrl_hdl_cst_ctrl;
798
799 /* Init and add standard controls */
800 v4l2_ctrl_handler_init( hdl_std_ctrl, 10 );
801 v4l2_ctrl_new_custom( hdl_std_ctrl, &isp_v4l2_ctrl_class, NULL );
802
803 /* general */
804 ADD_CTRL_STD( V4L2_CID_BRIGHTNESS, 0, 255, 1, 128 );
805 ADD_CTRL_STD( V4L2_CID_CONTRAST, 0, 255, 1, 128 );
806 ADD_CTRL_STD( V4L2_CID_SATURATION, 0, 255, 1, 128 );
807 ADD_CTRL_STD( V4L2_CID_HUE, 0, 360, 1, 180 );
808 ADD_CTRL_STD( V4L2_CID_SHARPNESS, 0, 255, 1, 128 );
809 ADD_CTRL_STD_MENU( V4L2_CID_COLORFX, 4, 0x1F0, 0 );
810 /* orientation */
811 ADD_CTRL_STD( V4L2_CID_HFLIP, 0, 1, 1, 0 );
812 ADD_CTRL_STD( V4L2_CID_VFLIP, 0, 1, 1, 0 );
813 /* exposure */
814 ADD_CTRL_STD( V4L2_CID_AUTOGAIN, 0, 1, 1, 1 );
815 ADD_CTRL_STD( V4L2_CID_GAIN, 100, 3200, 1, 100 );
816 ADD_CTRL_STD_MENU( V4L2_CID_EXPOSURE_AUTO,
817 1, 0x0, 0 );
818 ADD_CTRL_STD( V4L2_CID_EXPOSURE_ABSOLUTE,
819 1, 1000, 1, 33 );
820 ADD_CTRL_STD( V4L2_CID_EXPOSURE_AUTO_PRIORITY,
821 0, 1, 1, 0 );
822 /* white balance */
823 ADD_CTRL_STD( V4L2_CID_AUTO_WHITE_BALANCE,
824 0, 1, 1, 1 );
825 ADD_CTRL_STD( V4L2_CID_WHITE_BALANCE_TEMPERATURE,
826 2000, 8000, 1000, 5000 );
827 /* focus */
828 ADD_CTRL_STD( V4L2_CID_FOCUS_AUTO, 0, 1, 1, 1 );
829 ADD_CTRL_STD( V4L2_CID_FOCUS_ABSOLUTE,
830 0, 255, 1, 0 );
831
832 /* Init and add custom controls */
833 v4l2_ctrl_handler_init( hdl_cst_ctrl, 2 );
834 v4l2_ctrl_new_custom( hdl_cst_ctrl, &isp_v4l2_ctrl_class, NULL );
835
836 ADD_CTRL_CST( ISP_V4L2_CID_TEST_PATTERN,
837 &isp_v4l2_ctrl_test_pattern, NULL );
838 ADD_CTRL_CST( ISP_V4L2_CID_TEST_PATTERN_TYPE,
839 &isp_v4l2_ctrl_test_pattern_type, NULL );
840 ADD_CTRL_CST( ISP_V4L2_CID_AF_REFOCUS,
841 &isp_v4l2_ctrl_af_refocus, NULL );
842 ADD_CTRL_CST( ISP_V4L2_CID_SENSOR_PRESET,
843 &isp_v4l2_ctrl_sensor_preset, NULL );
844 ADD_CTRL_CST( ISP_V4L2_CID_AF_ROI,
845 &isp_v4l2_ctrl_af_roi, NULL );
846 ADD_CTRL_CST( ISP_V4L2_CID_OUTPUT_FR_ON_OFF,
847 &isp_v4l2_ctrl_output_fr_on_off, NULL );
848 ADD_CTRL_CST( ISP_V4L2_CID_OUTPUT_DS1_ON_OFF,
849 &isp_v4l2_ctrl_output_ds1_on_off, NULL );
850 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SENSOR_WDR_MODE,
851 &isp_v4l2_ctrl_sensor_wdr_mode, NULL );
852 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SENSOR_EXPOSURE,
853 &isp_v4l2_ctrl_sensor_exposure, NULL );
854 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_FR_FPS,
855 &isp_v4l2_ctrl_fr_fps, NULL);
856 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_SENSOR_TESTPATTERN,
857 &isp_v4l2_ctrl_sensor_testpattern, NULL);
858 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SENSOR_IR_CUT,
859 &isp_v4l2_ctrl_sensor_ir_cut, NULL);
860 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_AE_ZONE_WEIGHT,
861 &isp_v4l2_ctrl_ae_zone_weight, NULL);
862 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_AWB_ZONE_WEIGHT,
863 &isp_v4l2_ctrl_awb_zone_weight, NULL);
864 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_MANUAL_EXPOSURE,
865 &isp_v4l2_ctrl_manual_exposure, NULL);
866 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_SENSOR_INTEGRATION_TIME,
867 &isp_v4l2_ctrl_sensor_integration_time, NULL);
868 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_SENSOR_ANALOG_GAIN,
869 &isp_v4l2_ctrl_sensor_analog_gain, NULL);
870 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_ISP_DIGITAL_GAIN,
871 &isp_v4l2_ctrl_isp_digital_gain, NULL);
872 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_STOP_SENSOR_UPDATE,
873 &isp_v4l2_ctrl_stop_sensor_update, NULL);
874 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_DS1_FPS,
875 &isp_v4l2_ctrl_ds1_fps, NULL);
876 ADD_CTRL_CST( ISP_V4L2_CID_AE_COMPENSATION,
877 &isp_v4l2_ctrl_ae_compensation, NULL);
878 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_SENSOR_DIGITAL_GAIN,
879 &isp_v4l2_ctrl_sensor_digital_gain, NULL);
880 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_AWB_RED_GAIN,
881 &isp_v4l2_ctrl_awb_red_gain, NULL);
882 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_AWB_BLUE_GAIN,
883 &isp_v4l2_ctrl_awb_blue_gain, NULL);
884 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SET_MAX_INTEGRATION_TIME,
885 &isp_v4l2_ctrl_max_integration_time, NULL);
886 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SENSOR_FPS,
887 &isp_v4l2_ctrl_sensor_fps, NULL);
888 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SNR_MANUAL,
889 &isp_v4l2_ctrl_snr_manual, NULL);
890 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_SNR_STRENGTH,
891 &isp_v4l2_ctrl_snr_strength, NULL);
892 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_TNR_MANUAL,
893 &isp_v4l2_ctrl_tnr_manual, NULL);
894 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_TNR_OFFSET,
895 &isp_v4l2_ctrl_tnr_offset, NULL);
896 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_TEMPER_MODE,
897 &isp_v4l2_ctrl_temper_mode, NULL);
898 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_WDR_SWITCH,
899 &isp_v4l2_ctrl_wdr_mode, NULL);
900 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_ANTIFLICKER,
901 &isp_v4l2_ctrl_antiflicker, NULL);
902 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_DEFOG_SWITCH,
903 &isp_v4l2_ctrl_defog_mode, NULL);
904 ADD_CTRL_CST( ISP_V4L2_CID_CUSTOM_DEFOG_STRENGTH,
905 &isp_v4l2_ctrl_defog_ratio, NULL);
906 /* Add control handler to v4l2 device */
907 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0))
908 v4l2_ctrl_add_handler( hdl_std_ctrl, hdl_cst_ctrl, NULL );
909 #else
910 v4l2_ctrl_add_handler( hdl_std_ctrl, hdl_cst_ctrl, NULL, false );
911 #endif
912 ctrl->video_dev->ctrl_handler = hdl_std_ctrl;
913
914 v4l2_ctrl_handler_setup( hdl_std_ctrl );
915
916 return 0;
917 }
918
isp_v4l2_ctrl_deinit(isp_v4l2_ctrl_t * ctrl)919 void isp_v4l2_ctrl_deinit( isp_v4l2_ctrl_t *ctrl )
920 {
921 v4l2_ctrl_handler_free( &ctrl->ctrl_hdl_std_ctrl );
922 v4l2_ctrl_handler_free( &ctrl->ctrl_hdl_cst_ctrl );
923 }
924