• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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