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 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
22 #include <linux/ktime.h>
23 #include <linux/time64.h>
24 #include <linux/timekeeping.h>
25 #endif
26 #include <linux/module.h>
27 #include "acamera_fw.h"
28 #include "acamera_math.h"
29 #include "acamera_math.h"
30 #include "acamera_isp_config.h"
31 #include "system_timer.h"
32
33 #include "acamera_logger.h"
34 #include "sensor_fsm.h"
35
36 #include "acamera.h"
37
38 #if USER_MODULE
39 #include "sbuf.h"
40 #endif
41
42 typedef struct {
43 uint16_t active_width;
44 uint16_t active_height;
45 uint16_t total_width;
46 uint16_t total_height;
47 uint16_t offset_x;
48 uint16_t offset_y;
49 uint16_t h_front_porch;
50 uint16_t v_front_porch;
51 uint16_t h_sync_width;
52 uint16_t v_sync_width;
53 } dvi_sync_param_t;
54
55
56 #ifdef LOG_MODULE
57 #undef LOG_MODULE
58 #define LOG_MODULE LOG_MODULE_SENSOR
59 #endif
60
61 unsigned int temper3_4k = 0;
62 module_param(temper3_4k, uint, 0664);
63 MODULE_PARM_DESC(temper3_4k, "\n temper3 4k enable\n");
64
sensor_init_output(sensor_fsm_ptr_t p_fsm,int mode)65 void sensor_init_output( sensor_fsm_ptr_t p_fsm, int mode )
66 {
67 const sensor_param_t *param = p_fsm->ctrl.get_parameters( p_fsm->sensor_ctx );
68 if ( ( mode != 720 ) && ( mode != 1080 ) ) {
69 if ( param->active.height >= 1080 ) {
70 mode = 1080;
71 } else {
72 mode = 720;
73 }
74 }
75
76 // decrease output mode to 720p if active_height < mode
77 if ( mode > param->active.height )
78 mode = 720;
79
80 p_fsm->isp_output_mode = mode;
81 }
82
83 ///////////////////////////////////////////////////////////////////////////////
84
sensor_boot_init(sensor_fsm_ptr_t p_fsm)85 uint32_t sensor_boot_init( sensor_fsm_ptr_t p_fsm )
86 {
87 ACAMERA_FSM2CTX_PTR( p_fsm )
88 ->settings.sensor_init( &p_fsm->sensor_ctx, &p_fsm->ctrl );
89
90
91 #if USER_MODULE
92 uint32_t idx = 0;
93 sensor_param_t *param = (sensor_param_t *)p_fsm->ctrl.get_parameters( p_fsm->sensor_ctx );
94 struct sensor_info ksensor_info;
95 acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_KSENSOR_INFO, NULL, 0, &ksensor_info, sizeof( ksensor_info ) );
96
97 param->modes_num = ksensor_info.modes_num;
98 if ( param->modes_num > ISP_MAX_SENSOR_MODES ) {
99 param->modes_num = ISP_MAX_SENSOR_MODES;
100 }
101
102 for ( idx = 0; idx < param->modes_num; idx++ ) {
103 param->modes_table[idx] = ksensor_info.modes[idx];
104 }
105 #endif
106
107 return 0;
108 }
109
sensor_hw_init(sensor_fsm_ptr_t p_fsm)110 void sensor_hw_init( sensor_fsm_ptr_t p_fsm )
111 {
112 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0))
113 struct timeval txs,txe;
114 do_gettimeofday(&txs);
115 #endif
116
117 #if FW_DO_INITIALIZATION
118 if(p_fsm->p_fsm_mgr->isp_seamless == 0)
119 acamera_isp_input_port_mode_request_write( p_fsm->cmn.isp_base, ACAMERA_ISP_INPUT_PORT_MODE_REQUEST_SAFE_STOP ); // urgent stop
120 #endif //FW_DO_INITIALIZATION
121
122 // 1): set sensor to preset_mode as required.
123 if(p_fsm->p_fsm_mgr->isp_seamless)
124 {
125 if(acamera_isp_input_port_mode_status_read( 0 ) != ACAMERA_ISP_INPUT_PORT_MODE_REQUEST_SAFE_START)
126 p_fsm->ctrl.set_mode( p_fsm->sensor_ctx, p_fsm->preset_mode );
127 }
128 else
129 p_fsm->ctrl.set_mode( p_fsm->sensor_ctx, p_fsm->preset_mode );
130 p_fsm->ctrl.disable_sensor_isp( p_fsm->sensor_ctx );
131
132 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 19, 0))
133 do_gettimeofday(&txe);
134 LOG( LOG_INFO, "sensor_hw_init:%d", (txe.tv_sec*1000000+txe.tv_usec) - (txs.tv_sec*1000000+txs.tv_usec));
135 #endif
136
137 // 2): set to wdr_mode through general router (wdr_mode changed in sensor param in 1st step).
138 const sensor_param_t *param = p_fsm->ctrl.get_parameters( p_fsm->sensor_ctx );
139
140 fsm_param_set_wdr_param_t set_wdr_param;
141 set_wdr_param.wdr_mode = param->modes_table[param->mode].wdr_mode;
142 set_wdr_param.exp_number = param->modes_table[param->mode].exposures;
143 if(p_fsm->p_fsm_mgr->isp_seamless)
144 {
145 if(acamera_isp_input_port_mode_status_read( 0 ) == ACAMERA_ISP_INPUT_PORT_MODE_REQUEST_SAFE_START)
146 {
147 if((param->modes_table[p_fsm->preset_mode].exposures == 2 && set_wdr_param.exp_number == 1) ||
148 (param->modes_table[p_fsm->preset_mode].exposures == 1 && set_wdr_param.exp_number == 2) ||
149 (param->modes_table[p_fsm->preset_mode].exposures == 1 && set_wdr_param.exp_number == 3))
150 {
151 LOG(LOG_CRIT, "preset not match user mode, execute switch and close seamless");
152 p_fsm->ctrl.set_mode( p_fsm->sensor_ctx, p_fsm->preset_mode );
153 p_fsm->p_fsm_mgr->isp_seamless = 0;
154 }
155 if(param->modes_table[p_fsm->preset_mode].exposures != set_wdr_param.exp_number)
156 {
157 set_wdr_param.wdr_mode = param->modes_table[p_fsm->preset_mode].wdr_mode;
158 set_wdr_param.exp_number = param->modes_table[p_fsm->preset_mode].exposures;
159 }
160 }
161 }
162 acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_WDR_MODE, &set_wdr_param, sizeof( set_wdr_param ) );
163 // 3): Init or update the calibration data.
164 acamera_init_calibrations( ACAMERA_FSM2CTX_PTR( p_fsm ), ((sensor_param_t *)(p_fsm->sensor_ctx))->s_name.name );
165
166 // 4). update new settings to ISP if necessary
167 //acamera_update_cur_settings_to_isp(0xff);
168 }
169
sensor_configure_buffers(sensor_fsm_ptr_t p_fsm)170 void sensor_configure_buffers( sensor_fsm_ptr_t p_fsm )
171 {
172 #if ISP_HAS_TEMPER
173 acamera_isp_temper_enable_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, 0 );
174 aframe_t *temper_frames = ACAMERA_FSM2CTX_PTR( p_fsm )->settings.temper_frames;
175 uint32_t temper_frames_num = ACAMERA_FSM2CTX_PTR( p_fsm )->settings.temper_frames_number;
176 uint32_t temper_frame_size = acamera_isp_top_active_width_read( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base ) * acamera_isp_top_active_height_read( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base ) * 4;
177 if ( temper_frames != NULL && temper_frames_num != 0 && ( ( temper_frames_num > 1 ) ? ( temper_frames[0].size + temper_frames[1].size >= temper_frame_size * 2 ) : ( temper_frames[0].size >= temper_frame_size ) ) ) {
178 if ( temper_frames_num == 1 ) {
179 acamera_isp_temper_dma_lsb_bank_base_reader_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, temper_frames[0].address );
180 acamera_isp_temper_dma_lsb_bank_base_writer_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, temper_frames[0].address );
181 acamera_isp_temper_temper2_mode_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, 1 ); //temper 2
182 } else {
183 // temper3 has lsb and msb parts
184 acamera_isp_temper_dma_lsb_bank_base_reader_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, temper_frames[0].address );
185 acamera_isp_temper_dma_lsb_bank_base_writer_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, temper_frames[0].address );
186 acamera_isp_temper_dma_msb_bank_base_reader_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, temper_frames[1].address );
187 acamera_isp_temper_dma_msb_bank_base_writer_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, temper_frames[1].address );
188 acamera_isp_temper_temper2_mode_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, 0 ); //temper 3
189 }
190 acamera_isp_temper_dma_line_offset_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, temper_frames[0].line_offset);
191 acamera_isp_temper_enable_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, 1 );
192 acamera_isp_temper_dma_frame_write_on_lsb_dma_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, 1 );
193 acamera_isp_temper_dma_frame_read_on_lsb_dma_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, 1 );
194
195 } else {
196 acamera_isp_temper_enable_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, 0 );
197 acamera_isp_temper_dma_frame_write_on_lsb_dma_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, 0 );
198 acamera_isp_temper_dma_frame_read_on_lsb_dma_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, 0 );
199 LOG( LOG_ERR, "No output buffers for temper block provided in settings. Temper is disabled" );
200 }
201
202 if ( temper3_4k == 0 )
203 {
204 const sensor_param_t *param = p_fsm->ctrl.get_parameters( p_fsm->sensor_ctx );
205 if ( param->modes_table[p_fsm->preset_mode].resolution.width > 1920 && param->modes_table[p_fsm->preset_mode].resolution.height > 1080 )
206 {
207 LOG(LOG_CRIT, "Resolution: %dx%d > 1080P, close temper3",param->modes_table[p_fsm->preset_mode].resolution.width ,param->modes_table[p_fsm->preset_mode].resolution.height);
208 acamera_isp_temper_temper2_mode_write( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, 1 );
209 }
210 }
211 #endif
212 }
213
sensor_check_mirror_bayer(sensor_fsm_ptr_t p_fsm)214 static void sensor_check_mirror_bayer(sensor_fsm_ptr_t p_fsm)
215 {
216 uint8_t mirror_bypass = acamera_isp_top_bypass_mirror_read(p_fsm->cmn.isp_base);
217
218 if (mirror_bypass == 1)
219 return;
220
221 uint8_t bayer = acamera_isp_top_rggb_start_post_mirror_read(p_fsm->cmn.isp_base);
222 if (bayer == BAYER_RGGB)
223 acamera_isp_top_rggb_start_post_mirror_write( p_fsm->cmn.isp_base, BAYER_GRBG );
224 else if (bayer == BAYER_GRBG)
225 acamera_isp_top_rggb_start_post_mirror_write( p_fsm->cmn.isp_base, BAYER_RGGB );
226 else if (bayer == BAYER_GBRG)
227 acamera_isp_top_rggb_start_post_mirror_write( p_fsm->cmn.isp_base, BAYER_BGGR );
228 else if (bayer == BAYER_BGGR)
229 acamera_isp_top_rggb_start_post_mirror_write( p_fsm->cmn.isp_base, BAYER_GBRG );
230 }
231
sensor_update_bayer_bits(sensor_fsm_ptr_t p_fsm)232 static void sensor_update_bayer_bits(sensor_fsm_ptr_t p_fsm)
233 {
234 const sensor_param_t *param = p_fsm->ctrl.get_parameters( p_fsm->sensor_ctx );
235 uint8_t isp_bayer = param->bayer;
236 uint8_t bits = param->modes_table[p_fsm->preset_mode].bits;
237 uint8_t isp_bit_width = 1;
238
239 switch (bits) {
240 case 8:
241 isp_bit_width = 0;
242 break;
243 case 10:
244 isp_bit_width = 1;
245 break;
246 case 12:
247 isp_bit_width = 2;
248 break;
249 case 14:
250 isp_bit_width = 3;
251 break;
252 case 16:
253 isp_bit_width = 4;
254 break;
255 case 20:
256 isp_bit_width = 5;
257 break;
258 default:
259 LOG(LOG_ERR, "Error input bits\n");
260 break;
261 }
262
263 acamera_isp_top_rggb_start_pre_mirror_write(p_fsm->cmn.isp_base, isp_bayer);
264 acamera_isp_top_rggb_start_post_mirror_write(p_fsm->cmn.isp_base, isp_bayer);
265 acamera_isp_input_formatter_input_bitwidth_select_write(p_fsm->cmn.isp_base, isp_bit_width);
266
267 sensor_check_mirror_bayer(p_fsm);
268 }
269
270
sensor_sw_init(sensor_fsm_ptr_t p_fsm)271 void sensor_sw_init( sensor_fsm_ptr_t p_fsm )
272 {
273 const sensor_param_t *param = p_fsm->ctrl.get_parameters( p_fsm->sensor_ctx );
274
275 #if FW_DO_INITIALIZATION
276 if(p_fsm->p_fsm_mgr->isp_seamless == 0){
277 /* sensor resolution */
278 acamera_isp_top_active_width_write( p_fsm->cmn.isp_base, param->active.width );
279 acamera_isp_top_active_height_write( p_fsm->cmn.isp_base, param->active.height );
280
281 acamera_isp_metering_af_active_width_write(p_fsm->cmn.isp_base, param->active.width);
282 acamera_isp_metering_af_active_height_write(p_fsm->cmn.isp_base, param->active.height);
283
284 acamera_isp_lumvar_active_width_write(p_fsm->cmn.isp_base, param->active.width);
285 acamera_isp_lumvar_active_height_write(p_fsm->cmn.isp_base, param->active.height);
286
287 acamera_isp_input_port_hc_size0_write( p_fsm->cmn.isp_base, param->active.width );
288 acamera_isp_input_port_hc_size1_write( p_fsm->cmn.isp_base, param->active.width );
289 acamera_isp_input_port_vc_size_write( p_fsm->cmn.isp_base, param->active.height );
290
291 sensor_init_output( p_fsm, p_fsm->isp_output_mode );
292 }
293 #endif //FW_DO_INITIALIZATION
294
295 //acamera_isp_input_port_mode_request_write( p_fsm->cmn.isp_base, ACAMERA_ISP_INPUT_PORT_MODE_REQUEST_SAFE_START );
296
297 sensor_update_black( p_fsm );
298
299 sensor_update_bayer_bits(p_fsm);
300
301 if(p_fsm->p_fsm_mgr->isp_seamless)
302 {
303 if(acamera_isp_input_port_mode_status_read( 0 ) != ACAMERA_ISP_INPUT_PORT_MODE_REQUEST_SAFE_START)
304 {
305 acamera_reset_ping_pong_port();
306 acamera_update_cur_settings_to_isp(ISP_CONFIG_PING);
307 }
308 }
309 else
310 {
311 acamera_reset_ping_pong_port();
312 acamera_update_cur_settings_to_isp(ISP_CONFIG_PING);
313 }
314 LOG( LOG_NOTICE, "Sensor initialization is complete, ID 0x%04X resolution %dx%d", p_fsm->ctrl.get_id( p_fsm->sensor_ctx ), param->active.width, param->active.height );
315 }
316
sqrt_ext_param_update(sensor_fsm_ptr_t p_fsm)317 static void sqrt_ext_param_update(sensor_fsm_ptr_t p_fsm)
318 {
319 int32_t rtn = 0;
320 int32_t t_gain = 0;
321 struct sqrt_ext_param_t p_result;
322 fsm_ext_param_ctrl_t p_ctrl;
323
324 acamera_fsm_mgr_get_param(p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_CMOS_TOTAL_GAIN, NULL, 0, &t_gain, sizeof(t_gain));
325
326 p_ctrl.ctx = (void *)(ACAMERA_FSM2CTX_PTR(p_fsm));
327 p_ctrl.id = CALIBRATION_SQRT_EXT_CONTROL;
328 p_ctrl.total_gain = t_gain;
329 p_ctrl.result = (void *)&p_result;
330
331 rtn = acamera_extern_param_calculate(&p_ctrl);
332 if (rtn != 0) {
333 LOG(LOG_CRIT, "Failed to calculate sqrt ext");
334 return;
335 }
336
337 acamera_isp_sqrt_black_level_in_write(p_fsm->cmn.isp_base, p_result.black_level_in);
338 acamera_isp_sqrt_black_level_out_write(p_fsm->cmn.isp_base, p_result.black_level_out);
339 }
340
square_be_ext_param_update(sensor_fsm_ptr_t p_fsm)341 static void square_be_ext_param_update(sensor_fsm_ptr_t p_fsm)
342 {
343 int32_t rtn = 0;
344 int32_t t_gain = 0;
345 struct square_be_ext_param_t p_result;
346 fsm_ext_param_ctrl_t p_ctrl;
347
348 acamera_fsm_mgr_get_param(p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_CMOS_TOTAL_GAIN, NULL, 0, &t_gain, sizeof(t_gain));
349
350 p_ctrl.ctx = (void *)(ACAMERA_FSM2CTX_PTR(p_fsm));
351 p_ctrl.id = CALIBRATION_SQUARE_BE_EXT_CONTROL;
352 p_ctrl.total_gain = t_gain;
353 p_ctrl.result = (void *)&p_result;
354
355 rtn = acamera_extern_param_calculate(&p_ctrl);
356 if (rtn != 0) {
357 LOG(LOG_CRIT, "Failed to square be ext");
358 return;
359 }
360
361 acamera_isp_square_be_black_level_in_write(p_fsm->cmn.isp_base, p_result.black_level_in);
362 acamera_isp_square_be_black_level_out_write(p_fsm->cmn.isp_base, p_result.black_level_out);
363 }
364
sensor_update_black(sensor_fsm_ptr_t p_fsm)365 void sensor_update_black( sensor_fsm_ptr_t p_fsm )
366 {
367 int32_t stub = 0;
368 exposure_set_t exp;
369
370 acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_FRAME_EXPOSURE_SET, &stub, sizeof( stub ), &exp, sizeof( exp ) );
371
372 uint16_t again_log2 = ( uint16_t )( exp.info.again_log2 >> ( LOG2_GAIN_SHIFT - 5 ) ); // makes again in format log2(gain)*32
373 uint32_t wdr_mode = 0;
374
375 acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_WDR_MODE, NULL, 0, &wdr_mode, sizeof( wdr_mode ) );
376 uint32_t idx_r = CALIBRATION_BLACK_LEVEL_R;
377 uint32_t idx_b = CALIBRATION_BLACK_LEVEL_B;
378 uint32_t idx_gr = CALIBRATION_BLACK_LEVEL_GR;
379 uint32_t idx_gb = CALIBRATION_BLACK_LEVEL_GB;
380 uint32_t r = acamera_calc_modulation_u16( again_log2, _GET_MOD_ENTRY16_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_r ), _GET_ROWS( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_r ) );
381 uint32_t b = acamera_calc_modulation_u16( again_log2, _GET_MOD_ENTRY16_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_b ), _GET_ROWS( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_b ) );
382 uint32_t gr = acamera_calc_modulation_u16( again_log2, _GET_MOD_ENTRY16_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_gr ), _GET_ROWS( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_gr ) );
383 uint32_t gb = acamera_calc_modulation_u16( again_log2, _GET_MOD_ENTRY16_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_gb ), _GET_ROWS( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_gb ) );
384
385 p_fsm->black_level = r;
386
387 if ( wdr_mode == WDR_MODE_FS_LIN ) {
388 if ( ACAMERA_FSM2CTX_PTR( p_fsm )->stab.global_manual_frame_stitch == 0 ) {
389 acamera_isp_frame_stitch_black_level_long_write( p_fsm->cmn.isp_base, p_fsm->black_level );
390 acamera_isp_frame_stitch_black_level_medium_write( p_fsm->cmn.isp_base, p_fsm->black_level );
391 acamera_isp_frame_stitch_black_level_short_write( p_fsm->cmn.isp_base, p_fsm->black_level );
392 acamera_isp_frame_stitch_black_level_very_short_write( p_fsm->cmn.isp_base, p_fsm->black_level );
393 acamera_isp_frame_stitch_black_level_out_write( p_fsm->cmn.isp_base, p_fsm->black_level << BLACK_LEVEL_SHIFT_DG );
394 }
395
396 if ( ACAMERA_FSM2CTX_PTR( p_fsm )->stab.global_manual_black_level == 0 ) {
397 acamera_isp_sensor_offset_pre_shading_offset_00_write( p_fsm->cmn.isp_base, (uint32_t)_GET_MOD_ENTRY16_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_r )->y << BLACK_LEVEL_SHIFT_WB );
398 acamera_isp_sensor_offset_pre_shading_offset_01_write( p_fsm->cmn.isp_base, (uint32_t)_GET_MOD_ENTRY16_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_gr )->y << BLACK_LEVEL_SHIFT_WB );
399 acamera_isp_sensor_offset_pre_shading_offset_10_write( p_fsm->cmn.isp_base, (uint32_t)_GET_MOD_ENTRY16_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_gb )->y << BLACK_LEVEL_SHIFT_WB );
400 acamera_isp_sensor_offset_pre_shading_offset_11_write( p_fsm->cmn.isp_base, (uint32_t)_GET_MOD_ENTRY16_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_b )->y << BLACK_LEVEL_SHIFT_WB );
401
402 sqrt_ext_param_update(p_fsm);
403 square_be_ext_param_update(p_fsm);
404 }
405
406 acamera_isp_digital_gain_offset_write( p_fsm->cmn.isp_base, (uint32_t)_GET_MOD_ENTRY16_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), idx_gr )->y << BLACK_LEVEL_SHIFT_DG );
407 } else {
408 if ( ACAMERA_FSM2CTX_PTR( p_fsm )->stab.global_manual_black_level == 0 ) {
409 acamera_isp_sensor_offset_pre_shading_offset_00_write( p_fsm->cmn.isp_base, r << BLACK_LEVEL_SHIFT_WB );
410 acamera_isp_sensor_offset_pre_shading_offset_01_write( p_fsm->cmn.isp_base, gr << BLACK_LEVEL_SHIFT_WB );
411 acamera_isp_sensor_offset_pre_shading_offset_10_write( p_fsm->cmn.isp_base, gb << BLACK_LEVEL_SHIFT_WB );
412 acamera_isp_sensor_offset_pre_shading_offset_11_write( p_fsm->cmn.isp_base, b << BLACK_LEVEL_SHIFT_WB );
413
414 sqrt_ext_param_update(p_fsm);
415 square_be_ext_param_update(p_fsm);
416 }
417
418 acamera_isp_digital_gain_offset_write( p_fsm->cmn.isp_base, (uint32_t)p_fsm->black_level << BLACK_LEVEL_SHIFT_DG );
419 }
420 }
421
sensor_get_lines_second(sensor_fsm_ptr_t p_fsm)422 uint32_t sensor_get_lines_second( sensor_fsm_ptr_t p_fsm )
423 {
424 const sensor_param_t *param = p_fsm->ctrl.get_parameters( p_fsm->sensor_ctx );
425 return param->lines_per_second;
426 }
427
sensor_deinit(sensor_fsm_ptr_t p_fsm)428 void sensor_deinit( sensor_fsm_ptr_t p_fsm )
429 {
430 ACAMERA_FSM2CTX_PTR( p_fsm )
431 ->settings.sensor_deinit( p_fsm->sensor_ctx );
432 }
433