• 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 "acamera_fw.h"
21 #include "acamera_math.h"
22 #include "system_timer.h"
23 #include "acamera_command_api.h"
24 #include "cmos_fsm.h"
25 
26 #include "acamera_logger.h"
27 
28 #define is_short_exposure_frame( base ) ( ACAMERA_FSM2CTX_PTR( p_fsm )->frame & 1 )
29 
30 #ifdef LOG_MODULE
31 #undef LOG_MODULE
32 #define LOG_MODULE LOG_MODULE_CMOS
33 #endif
34 
35 #define EXPOSURE_PARTITION_INTEGRATION_TIME_INDEX 0
36 #define EXPOSURE_PARTITION_GAIN_INDEX 1
37 
cmos_get_partition_lut(cmos_fsm_ptr_t p_fsm,cmos_partition_lut_index_t lut_idx)38 uint16_t *cmos_get_partition_lut( cmos_fsm_ptr_t p_fsm, cmos_partition_lut_index_t lut_idx )
39 {
40     uint32_t i = 0;
41     uint16_t *p_luts = _GET_USHORT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_EXPOSURE_PARTITION_LUTS );
42     uint32_t lut_len = _GET_COLS( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_EXPOSURE_PARTITION_LUTS );
43     uint32_t lut_count = _GET_ROWS( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_EXPOSURE_PARTITION_LUTS );
44 
45     if ( lut_idx >= PARTITION_LUT_INDEX_MAX ) {
46         LOG( LOG_CRIT, "Error: invalid partition lut index: %d, max: %d.", lut_idx, PARTITION_LUT_INDEX_MAX - 1 );
47         return NULL;
48     }
49 
50     // each lut has SYSTEM_EXPOSURE_PARTITION_VALUE_COUNT items
51     if ( lut_len != SYSTEM_EXPOSURE_PARTITION_VALUE_COUNT ) {
52         LOG( LOG_CRIT, "Error: corrupted calibration luts, lut_len: %d, expected: %d.", lut_len, SYSTEM_EXPOSURE_PARTITION_VALUE_COUNT );
53         return NULL;
54     }
55 
56     if ( lut_idx >= lut_count ) {
57         LOG( LOG_CRIT, "Error: corrupted calibration luts, max_index: %d, expected: %d.", lut_count - 1, lut_idx );
58         return NULL;
59     }
60 
61     p_luts += lut_len * lut_idx;
62 
63     for ( i = 0; i < lut_len; i += 2 ) {
64         LOG( LOG_DEBUG, "%d - %d", p_luts[i], p_luts[i + 1] );
65     }
66 
67     return p_luts;
68 }
69 
cmos_update_exposure_partitioning_lut(cmos_fsm_ptr_t p_fsm)70 void cmos_update_exposure_partitioning_lut( cmos_fsm_ptr_t p_fsm )
71 {
72     int i;
73     int32_t param[2] = {0, 0}; // in log2
74 
75 
76     uint16_t *exposure_partitions = cmos_get_partition_lut( p_fsm, PARTITION_LUT_BALANED_INDEX );
77 #ifdef AE_SPLIT_PRESET_ID
78     if ( p_fsm->strategy == AE_SPLIT_INTEGRATION_PRIORITY ) {
79         exposure_partitions = cmos_get_partition_lut( p_fsm, PARTITION_LUT_INTEGRATION_PRIORITY_INDEX );
80     }
81 #endif
82 
83     fsm_param_sensor_info_t sensor_info;
84     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
85 
86     int32_t max_gain = sensor_info.again_log2_max + sensor_info.dgain_log2_max + p_fsm->maximum_isp_digital_gain;
87     for ( i = 0; i < SYSTEM_EXPOSURE_PARTITION_VALUE_COUNT; ++i ) {
88         // exposure_partitions has {integration_time, gain } pairs,
89         // so if i is even number, such as 0, 2, means int_time, odd num means gain.
90         int i_param = i & 1;
91         int32_t addon = 0;
92         uint16_t v = exposure_partitions[i];
93 
94         switch ( i_param ) {
95         case EXPOSURE_PARTITION_INTEGRATION_TIME_INDEX:
96             if ( !v ) {
97                 addon = acamera_log2_fixed_to_fixed( sensor_info.integration_time_limit, 0, LOG2_GAIN_SHIFT );
98             } else {
99                 int32_t lines = cmos_convert_integration_time_ms2lines( p_fsm, v );
100                 if ( lines < sensor_info.integration_time_min ) {
101                     lines = sensor_info.integration_time_min;
102                 }
103                 addon = acamera_log2_fixed_to_fixed( lines, 0, LOG2_GAIN_SHIFT );
104             }
105             break;
106         case EXPOSURE_PARTITION_GAIN_INDEX:
107             if ( !v ) {
108                 addon = max_gain;
109             } else {
110                 addon = acamera_log2_fixed_to_fixed( v, 0, LOG2_GAIN_SHIFT );
111             }
112             break;
113         }
114         addon -= param[i_param];
115         if ( addon < 0 ) {
116             addon = 0;
117         }
118         p_fsm->exp_lut[i] = addon;
119         param[i_param] += addon;
120     }
121 }
122 
_process_fps_cnt(fps_counter_t * fps_cnt)123 void _process_fps_cnt( fps_counter_t *fps_cnt )
124 {
125     uint32_t cur_tick = system_timer_timestamp();
126     uint32_t frame_ticks = cur_tick - fps_cnt->last_tick;
127     fps_cnt->avg_frame_ticks += frame_ticks - ( fps_cnt->avg_frame_ticks >> 4 );
128     fps_cnt->last_tick = cur_tick;
129 }
130 
_init_fps_cnt(fps_counter_t * fps_cnt)131 void _init_fps_cnt( fps_counter_t *fps_cnt )
132 {
133     fps_cnt->last_tick = 0;
134     fps_cnt->avg_frame_ticks = ( system_timer_frequency() / 15 ) << 4; // initially it's something like 15 FPS // division by zero is checked
135     system_timer_init();
136     fps_cnt->last_tick = system_timer_timestamp();
137 }
138 
cmos_get_fps(cmos_fsm_ptr_t p_fsm)139 uint16_t cmos_get_fps( cmos_fsm_ptr_t p_fsm )
140 {
141     uint64_t tps = system_timer_frequency();
142     uint16_t fps;
143     if ( p_fsm->fps_cnt.avg_frame_ticks ) {
144         uint64_t _tps = ( tps << ( 8 + 4 ) );
145         fps = (uint16_t)div64_u64( _tps, p_fsm->fps_cnt.avg_frame_ticks ); // division by zero is checked
146     } else {
147         LOG( LOG_CRIT, "AVOIDED DIVISION BY ZERO" );
148         fps = 15 << 8;
149     }
150     return fps;
151 }
152 
cmos_init(cmos_fsm_ptr_t p_fsm)153 void cmos_init( cmos_fsm_ptr_t p_fsm )
154 {
155 #ifdef AE_SPLIT_PRESET_ID
156     p_fsm->strategy = AE_SPLIT_BALANCED;
157 #endif
158 
159     p_fsm->mask.repeat_irq_mask = ACAMERA_IRQ_MASK( ACAMERA_IRQ_FRAME_START ) | ACAMERA_IRQ_MASK( ACAMERA_IRQ_FRAME_END );
160     cmos_request_interrupt( p_fsm, p_fsm->mask.repeat_irq_mask );
161 
162 #ifdef FLASH_XENON
163     p_fsm->flash_state = flash_get_init_state();
164     p_fsm->flash_skip_charge = 1;
165 #endif
166     _init_fps_cnt( &p_fsm->fps_cnt );
167 
168 
169 #if FILTER_LONG_INT_TIME || FILTER_SHORT_INT_TIME
170     uint16_t i;
171 #endif
172 #if FILTER_LONG_INT_TIME
173     for ( i = 0; i < FILTER_LONG_INT_TIME; i++ ) {
174         p_fsm->long_it_hist.v[i] = 1;
175     }
176     p_fsm->long_it_hist.sum = FILTER_LONG_INT_TIME;
177     p_fsm->long_it_hist.p = &( p_fsm->long_it_hist.v[0] );
178 #endif
179 
180 #if FILTER_SHORT_INT_TIME
181     for ( i = 0; i < FILTER_SHORT_INT_TIME; i++ ) {
182         p_fsm->short_it_hist.v[i] = 1;
183     }
184     p_fsm->short_it_hist.sum = FILTER_SHORT_INT_TIME;
185     p_fsm->short_it_hist.p = &( p_fsm->short_it_hist.v[0] );
186 #endif
187 
188     system_spinlock_init( &p_fsm->exp_lock );
189 }
190 
cmos_alloc_integration_time(cmos_fsm_ptr_t p_fsm,int32_t int_time)191 void cmos_alloc_integration_time( cmos_fsm_ptr_t p_fsm, int32_t int_time )
192 {
193     // We should set as maximum as possible analogue gain less than or equals target_gain
194     unsigned int new_integration_time_short;
195     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
196 
197     fsm_param_sensor_info_t sensor_info;
198     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
199 
200     uint32_t min_integration_time_short = sensor_info.integration_time_min;
201     uint32_t max_integration_time_short = sensor_info.integration_time_limit;
202     if ( param->global_manual_max_integration_time && max_integration_time_short > param->global_max_integration_time ) {
203         max_integration_time_short = param->global_max_integration_time;
204     }
205     if ( param->global_manual_integration_time ) {
206         new_integration_time_short = param->global_integration_time;
207     } else {
208         new_integration_time_short = acamera_math_exp2( int_time, LOG2_GAIN_SHIFT, 0 );
209     }
210     if ( new_integration_time_short < min_integration_time_short ) {
211         new_integration_time_short = min_integration_time_short;
212     } else if ( new_integration_time_short > max_integration_time_short ) {
213         new_integration_time_short = max_integration_time_short;
214     }
215 
216 #if FILTER_SHORT_INT_TIME
217     //rotate the FIFO
218     if ( ++p_fsm->short_it_hist.p > &( p_fsm->short_it_hist.v[FILTER_SHORT_INT_TIME - 1] ) )
219         p_fsm->short_it_hist.p = &( p_fsm->short_it_hist.v[0] );
220     p_fsm->short_it_hist.sum -= *p_fsm->short_it_hist.p;
221     *p_fsm->short_it_hist.p = new_integration_time_short;
222     p_fsm->short_it_hist.sum += *p_fsm->short_it_hist.p;
223 
224     new_integration_time_short = p_fsm->short_it_hist.sum / FILTER_SHORT_INT_TIME; // division by zero is checked
225 #endif
226 
227     p_fsm->prev_integration_time_short = p_fsm->integration_time_short;
228     p_fsm->integration_time_short = new_integration_time_short;
229 }
230 
cmos_alloc_sensor_analog_gain(cmos_fsm_ptr_t p_fsm,int32_t gain)231 int32_t cmos_alloc_sensor_analog_gain( cmos_fsm_ptr_t p_fsm, int32_t gain )
232 {
233     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
234 
235     if ( gain < 0 ) {
236         return 0;
237     }
238 
239     fsm_param_sensor_info_t sensor_info;
240     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
241 
242     int32_t max_gain = param->global_max_sensor_analog_gain << ( LOG2_GAIN_SHIFT - 5 );
243     if ( gain > max_gain ) {
244         gain = max_gain;
245     }
246 
247     acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_SENSOR_ALLOC_ANALOG_GAIN, &gain, sizeof( gain ) );
248 
249     // gain will be changed inside function, so we can return gain as the real gain.
250     return gain;
251 }
252 
cmos_alloc_sensor_digital_gain(cmos_fsm_ptr_t p_fsm,int32_t gain)253 int32_t cmos_alloc_sensor_digital_gain( cmos_fsm_ptr_t p_fsm, int32_t gain )
254 {
255     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
256     if ( gain < 0 ) {
257         return 0;
258     }
259 
260     fsm_param_sensor_info_t sensor_info;
261     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
262 
263     int32_t max_gain = MIN( sensor_info.dgain_log2_max, (int32_t)param->global_max_sensor_digital_gain << ( LOG2_GAIN_SHIFT - 5 ) );
264     if ( gain > max_gain ) {
265         gain = max_gain;
266     }
267 
268     acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_SENSOR_ALLOC_DIGITAL_GAIN, &gain, sizeof( gain ) );
269 
270     if ( gain < 0 ) {
271         gain = 0; // special mode like native HDR
272     }
273     return gain;
274 }
275 
cmos_alloc_isp_digital_gain(cmos_fsm_ptr_t p_fsm,int32_t gain)276 int32_t cmos_alloc_isp_digital_gain( cmos_fsm_ptr_t p_fsm, int32_t gain )
277 {
278     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
279     if ( gain < 0 ) {
280         return 0;
281     }
282     if ( gain > p_fsm->maximum_isp_digital_gain ) {
283         gain = p_fsm->maximum_isp_digital_gain;
284     }
285     int32_t max_gain = param->global_max_isp_digital_gain << ( LOG2_GAIN_SHIFT - 5 );
286     if ( gain > max_gain ) {
287         gain = max_gain;
288     }
289     return gain;
290 }
291 
cmos_get_manual_again_log2(cmos_fsm_ptr_t p_fsm)292 int32_t cmos_get_manual_again_log2( cmos_fsm_ptr_t p_fsm )
293 {
294     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
295     if ( param->global_manual_sensor_analog_gain ) {
296         int32_t gain = param->global_sensor_analog_gain << ( LOG2_GAIN_SHIFT - 5 );
297         return cmos_alloc_sensor_analog_gain( p_fsm, gain );
298     }
299     return -1; // negative means it is not manual
300 }
301 
cmos_get_manual_dgain_log2(cmos_fsm_ptr_t p_fsm)302 int32_t cmos_get_manual_dgain_log2( cmos_fsm_ptr_t p_fsm )
303 {
304     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
305     if ( param->global_manual_sensor_digital_gain ) {
306         int32_t gain = ( param->global_sensor_digital_gain << ( LOG2_GAIN_SHIFT - 5 ) );
307         return cmos_alloc_sensor_digital_gain( p_fsm, gain );
308     }
309     return -1; // negative means it is not manual
310 }
311 
cmos_get_manual_isp_dgain_log2(cmos_fsm_ptr_t p_fsm)312 int32_t cmos_get_manual_isp_dgain_log2( cmos_fsm_ptr_t p_fsm )
313 {
314     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
315     if ( param->global_manual_isp_digital_gain ) {
316         int32_t gain = ( param->global_isp_digital_gain << ( LOG2_GAIN_SHIFT - 5 ) );
317         return cmos_alloc_isp_digital_gain( p_fsm, gain );
318     }
319     return -1; // negative means it is not manual
320 }
321 
cmos_convert_integration_time_ms2lines(cmos_fsm_ptr_t p_fsm,int time_ms)322 int cmos_convert_integration_time_ms2lines( cmos_fsm_ptr_t p_fsm, int time_ms )
323 {
324     fsm_param_sensor_info_t sensor_info;
325     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
326 
327     int res = sensor_info.lines_per_second * time_ms / 1000; // division by zero is checked
328     return res;
329 }
330 
cmos_get_frame_exposure_set(cmos_fsm_ptr_t p_fsm,int i_frame)331 exposure_set_t *cmos_get_frame_exposure_set( cmos_fsm_ptr_t p_fsm, int i_frame )
332 {
333     int pos = p_fsm->exposure_hist_pos + i_frame;
334     if ( pos < 0 ) {
335         pos += ( sizeof( p_fsm->exposure_hist ) / sizeof( p_fsm->exposure_hist[0] ) );          // division by zero is checked
336     } else if ( pos >= ( sizeof( p_fsm->exposure_hist ) / sizeof( p_fsm->exposure_hist[0] ) ) ) // division by zero is checked
337     {
338         pos -= ( sizeof( p_fsm->exposure_hist ) / sizeof( p_fsm->exposure_hist[0] ) ); // division by zero is checked
339     }
340     return p_fsm->exposure_hist + pos;
341 }
342 
cmos_store_frame_exposure_set(cmos_fsm_ptr_t p_fsm,exposure_set_t * p_set)343 static void cmos_store_frame_exposure_set( cmos_fsm_ptr_t p_fsm, exposure_set_t *p_set )
344 {
345     fsm_param_sensor_info_t sensor_info;
346     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
347 
348     p_set->data.integration_time = p_fsm->integration_time_short;
349 
350     p_set->data.isp_dgain_log2 = p_fsm->isp_dgain_log2;
351     int32_t prev_again;
352 
353     if ( sensor_info.sensor_exp_number == 4 ) {
354 
355         p_set->data.integration_time_long = p_fsm->integration_time_long;
356         p_set->data.integration_time_medium = p_fsm->integration_time_medium;
357         p_set->data.integration_time_medium2 = p_fsm->integration_time_medium2;
358 
359         p_set->data.exposure_ratio_short = 64 * (uint32_t)p_fsm->integration_time_medium / p_fsm->integration_time_short;
360         p_set->data.exposure_ratio_medium = 64 * (uint32_t)p_fsm->integration_time_medium2 / p_fsm->integration_time_medium;
361 
362         switch ( sensor_info.isp_exposure_channel_delay ) {
363         case 1:
364             prev_again = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->info.again_log2;
365             p_set->data.exposure_ratio_medium2 = 64 * (uint32_t)p_fsm->integration_time_long / p_fsm->integration_time_medium2 * acamera_math_exp2( prev_again - p_fsm->again_val_log2, LOG2_GAIN_SHIFT, 8 ) >> 8;
366             break;
367         default:
368             p_set->data.exposure_ratio_medium2 = 64 * (uint32_t)p_fsm->integration_time_long / p_fsm->integration_time_medium2;
369             break;
370         }
371 
372     } else if ( sensor_info.sensor_exp_number == 3 ) {
373         p_set->data.integration_time_medium = p_fsm->integration_time_medium;
374         p_set->data.exposure_ratio_short = 64 * (uint32_t)p_fsm->integration_time_medium / p_fsm->integration_time_short;
375         p_set->data.integration_time_long = p_fsm->integration_time_long;
376 
377         switch ( sensor_info.isp_exposure_channel_delay ) {
378         case 1:
379             prev_again = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->info.again_log2;
380             p_set->data.exposure_ratio_medium = 64 * (uint32_t)p_fsm->integration_time_long / p_fsm->integration_time_medium * acamera_math_exp2( prev_again - p_fsm->again_val_log2, LOG2_GAIN_SHIFT, 8 ) >> 8;
381             break;
382         default:
383             p_set->data.exposure_ratio_medium = 64 * (uint32_t)p_fsm->integration_time_long / p_fsm->integration_time_medium;
384             break;
385         }
386 
387     } else if ( sensor_info.sensor_exp_number == 2 ) {
388         p_set->data.integration_time_long = p_fsm->integration_time_long;
389 
390         switch ( sensor_info.isp_exposure_channel_delay ) {
391         case 1:
392             prev_again = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->info.again_log2;
393             p_set->data.exposure_ratio = 64 * (uint32_t)p_fsm->integration_time_long / p_fsm->integration_time_short * acamera_math_exp2( prev_again - p_fsm->again_val_log2, LOG2_GAIN_SHIFT, 8 ) >> 8;
394             break;
395         default:
396             p_set->data.exposure_ratio = 64 * (uint32_t)p_fsm->integration_time_long / p_fsm->integration_time_short;
397             break;
398         }
399     } else {
400         p_set->data.integration_time_long = p_fsm->integration_time_long;
401         p_set->data.exposure_ratio = 64 * (uint32_t)p_fsm->integration_time_long / p_fsm->integration_time_short;
402     }
403 
404 
405     p_set->info.again_log2 = p_fsm->again_val_log2;
406     p_set->info.dgain_log2 = p_fsm->dgain_val_log2;
407     p_set->info.isp_dgain_log2 = p_fsm->isp_dgain_log2;
408     // update exposure for this frame
409     p_set->info.exposure_log2 = p_set->info.again_log2 + p_set->info.dgain_log2 + p_set->info.isp_dgain_log2;
410     p_set->info.exposure_log2 += acamera_log2_fixed_to_fixed( p_set->data.integration_time, 0, LOG2_GAIN_SHIFT );
411 
412     p_set->data.frame_id_tracking = p_fsm->frame_id_tracking;
413 }
414 
cmos_update_exposure_history(cmos_fsm_ptr_t p_fsm)415 void cmos_update_exposure_history( cmos_fsm_ptr_t p_fsm )
416 {
417     unsigned long irq_flags;
418     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
419     //uint32_t gain;
420     if ( p_fsm->exposure_hist_pos < 0 ) {
421         int pos;
422         fsm_param_sensor_info_t sensor_info;
423         acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
424 
425         p_fsm->exposure_hist_pos = 0;
426         // reset state
427         for ( pos = 0; pos <= sensor_info.integration_time_apply_delay; ++pos ) {
428             cmos_store_frame_exposure_set( p_fsm, cmos_get_frame_exposure_set( p_fsm, pos ) );
429         }
430     }
431 
432     irq_flags = system_spinlock_lock( p_fsm->exp_lock );
433     cmos_store_frame_exposure_set( p_fsm, &( p_fsm->exp_next_set ) );
434     system_spinlock_unlock( p_fsm->exp_lock, irq_flags );
435 
436     // display gains in control tool
437     if ( !param->global_manual_integration_time ) {
438 #if EXPOSURE_DRIVES_LONG_INTEGRATION_TIME
439         uint32_t wdr_mode = 0;
440 
441         acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_WDR_MODE, NULL, 0, &wdr_mode, sizeof( wdr_mode ) );
442 
443         param->global_integration_time = ( ( ( wdr_mode == WDR_MODE_LINEAR ) ? p_fsm->integration_time_short : p_fsm->integration_time_long ) );
444 #else
445         param->global_integration_time = ( p_fsm->integration_time_short );
446 #endif
447     }
448     if ( !param->global_manual_sensor_analog_gain ) {
449         param->global_sensor_analog_gain = ( p_fsm->again_val_log2 >> ( LOG2_GAIN_SHIFT - 5 ) );
450     }
451     if ( !param->global_manual_sensor_digital_gain ) {
452         param->global_sensor_digital_gain = ( p_fsm->dgain_val_log2 >> ( LOG2_GAIN_SHIFT - 5 ) );
453     }
454     if ( !param->global_manual_isp_digital_gain ) {
455         param->global_isp_digital_gain = ( p_fsm->isp_dgain_log2 >> ( LOG2_GAIN_SHIFT - 5 ) );
456     }
457 }
458 
cmos_mointor_frame_start(cmos_fsm_ptr_t p_fsm)459 static void cmos_mointor_frame_start( cmos_fsm_ptr_t p_fsm )
460 {
461     uint32_t cur_frame_id = acamera_fsm_util_get_cur_frame_id( &p_fsm->cmn );
462 
463     /* CMOS FrameStart should be called for every frame */
464     if ( ( p_fsm->prev_fs_frame_id != 0 ) &&
465          ( p_fsm->prev_fs_frame_id + 1 != cur_frame_id ) ) {
466 
467         fsm_param_mon_err_head_t mon_err;
468         mon_err.err_type = MON_TYPE_ERR_CMOS_FS_DELAY;
469         acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_MON_ERROR_REPORT, &mon_err, sizeof( mon_err ) );
470         LOG( LOG_ERR, "cmos_mon_fe: cur: %u, pre: %u.", cur_frame_id, p_fsm->prev_fs_frame_id );
471     }
472 
473     p_fsm->prev_fs_frame_id = cur_frame_id;
474 }
475 
476 
cmos_mointor_frame_end(cmos_fsm_ptr_t p_fsm)477 static void cmos_mointor_frame_end( cmos_fsm_ptr_t p_fsm )
478 {
479 
480     uint32_t irq_mask = acamera_isp_isp_global_interrupt_status_vector_read( p_fsm->cmn.isp_base );
481     if ( irq_mask & 0x1 ) {
482         fsm_param_mon_err_head_t mon_err;
483         mon_err.err_type = MON_TYPE_ERR_CMOS_UPDATE_NOT_IN_VB;
484         acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_MON_ERROR_REPORT, &mon_err, sizeof( mon_err ) );
485     }
486 }
487 
cmos_move_exposure_history(cmos_fsm_ptr_t p_fsm)488 static void cmos_move_exposure_history( cmos_fsm_ptr_t p_fsm )
489 {
490     unsigned long irq_flags;
491 
492     int pos = p_fsm->exposure_hist_pos + 1;
493     if ( pos >= ( sizeof( p_fsm->exposure_hist ) / sizeof( p_fsm->exposure_hist[0] ) ) ) // division by zero is checked
494     {
495         pos = 0;
496     }
497     p_fsm->exposure_hist_pos = pos;
498     fsm_param_sensor_info_t sensor_info;
499     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
500 
501     irq_flags = system_spinlock_lock( p_fsm->exp_lock );
502     *cmos_get_frame_exposure_set( p_fsm, sensor_info.integration_time_apply_delay ) = p_fsm->exp_next_set;
503     system_spinlock_unlock( p_fsm->exp_lock, irq_flags );
504 }
505 
cmos_fsm_process_interrupt(cmos_fsm_const_ptr_t p_fsm,uint8_t irq_event)506 void cmos_fsm_process_interrupt( cmos_fsm_const_ptr_t p_fsm, uint8_t irq_event )
507 {
508     if ( acamera_fsm_util_is_irq_event_ignored( (fsm_irq_mask_t *)( &p_fsm->mask ), irq_event ) )
509         return;
510 
511     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
512     status_info_param_t *p_status_info = (status_info_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_STATUS_INFO );
513 
514     uint32_t wdr_mode = 0;
515 
516     fsm_param_sensor_info_t sensor_info;
517     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
518     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_WDR_MODE, NULL, 0, &wdr_mode, sizeof( wdr_mode ) );
519 
520     switch ( irq_event ) {
521     case ACAMERA_IRQ_FRAME_START:
522         cmos_move_exposure_history( (cmos_fsm_ptr_t)p_fsm );
523         {
524             exposure_data_set_t exp_set = {0};
525             if ( ( wdr_mode == WDR_MODE_FS_LIN ) || ( ( wdr_mode == WDR_MODE_NATIVE ) && ( sensor_info.sensor_exp_number == 3 ) ) ) {
526                 if ( sensor_info.sensor_exp_number == 1 ) {
527                     exp_set.integration_time = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.actual_integration_time;
528                     exp_set.exposure_ratio = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio;
529                     if ( is_short_exposure_frame( p_fsm->cmn.isp_base ) == 0 ) {
530                         ACAMERA_FSM2CTX_PTR( p_fsm )
531                             ->stab.global_long_integration_time = exp_set.integration_time;
532                     } else {
533                         ACAMERA_FSM2CTX_PTR( p_fsm )
534                             ->stab.global_short_integration_time = ( exp_set.integration_time );
535                     }
536                     exp_set.actual_integration_time = exp_set.integration_time;
537 
538                 } else if ( sensor_info.sensor_exp_number == 2 ) {
539                     exp_set.integration_time = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time;
540                     exp_set.integration_time_long = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time_long;
541                     exp_set.exposure_ratio = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio;
542                     ACAMERA_FSM2CTX_PTR( p_fsm )
543                         ->stab.global_long_integration_time = ( exp_set.integration_time_long );
544                     ACAMERA_FSM2CTX_PTR( p_fsm )
545                         ->stab.global_short_integration_time = ( exp_set.integration_time );
546 
547                 } else if ( sensor_info.sensor_exp_number == 3 ) {
548                     exp_set.integration_time = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time;
549                     exp_set.integration_time_medium = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time_medium;
550                     exp_set.integration_time_long = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time_long;
551                     exp_set.exposure_ratio_short = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio_short;
552                     exp_set.exposure_ratio_medium = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio_medium;
553                     //LOG( LOG_ERR, " short %d medium %d long %d Rs %d Rm %d", exp_set.integration_time, exp_set.integration_time_medium, exp_set.integration_time_long, exp_set.exposure_ratio_short, exp_set.exposure_ratio_medium );
554 
555                     ACAMERA_FSM2CTX_PTR( p_fsm )
556                         ->stab.global_long_integration_time = ( exp_set.integration_time_long );
557                     ACAMERA_FSM2CTX_PTR( p_fsm )
558                         ->stab.global_short_integration_time = ( exp_set.integration_time );
559 
560                 } else /* sensor_exp_number == 4 */ {
561                     exp_set.integration_time = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time;
562                     exp_set.integration_time_medium = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time_medium;
563                     exp_set.integration_time_medium2 = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time_medium2;
564                     exp_set.integration_time_long = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time_long;
565                     exp_set.exposure_ratio_short = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio_short;
566                     exp_set.exposure_ratio_medium = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio_medium;
567                     exp_set.exposure_ratio_medium2 = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio_medium2;
568                     //LOG( LOG_ERR, " short %d medium %d long %d Rs %d Rm %d", exp_set.integration_time, exp_set.integration_time_medium, exp_set.integration_time_long, exp_set.exposure_ratio_short, exp_set.exposure_ratio_medium );
569 
570                     ACAMERA_FSM2CTX_PTR( p_fsm )
571                         ->stab.global_long_integration_time = ( exp_set.integration_time_long );
572                     ACAMERA_FSM2CTX_PTR( p_fsm )
573                         ->stab.global_short_integration_time = ( exp_set.integration_time );
574                 }
575             } else {
576                 exp_set.integration_time = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time;
577                 ACAMERA_FSM2CTX_PTR( p_fsm )
578                     ->stab.global_short_integration_time = ( exp_set.integration_time );
579 
580                 if ( sensor_info.sensor_exp_number == 1 ) {
581                     exp_set.actual_integration_time = exp_set.integration_time;
582                     exp_set.exposure_ratio = 64;
583 
584                 } else if ( sensor_info.sensor_exp_number == 2 ) {
585                     exp_set.integration_time = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time;
586                     exp_set.integration_time_long = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time_long;
587                     exp_set.exposure_ratio = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio;
588 
589                 } else if ( sensor_info.sensor_exp_number == 3 ) {
590                     exp_set.integration_time = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time;
591                     exp_set.integration_time_medium = exp_set.integration_time;
592                     exp_set.integration_time_long = exp_set.integration_time;
593                     exp_set.exposure_ratio_short = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio_short;
594                     exp_set.exposure_ratio_medium = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio_medium;
595 
596                 } else /* sensor_exp_number == 4 */ {
597                     exp_set.integration_time = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, sensor_info.integration_time_apply_delay )->data.integration_time;
598                     exp_set.integration_time_medium = exp_set.integration_time;
599                     exp_set.integration_time_medium2 = exp_set.integration_time;
600                     exp_set.integration_time_long = exp_set.integration_time;
601                     exp_set.exposure_ratio_short = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio_short;
602                     exp_set.exposure_ratio_medium = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio_medium;
603                     exp_set.exposure_ratio_medium2 = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.exposure_ratio_medium2;
604                 }
605             }
606             exp_set.isp_dgain_log2 = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.isp_dgain_log2;
607 
608             // tracking integration time and isp_dgain separately?
609             exp_set.frame_id_tracking = cmos_get_frame_exposure_set( (cmos_fsm_ptr_t)p_fsm, 2 )->data.frame_id_tracking;
610 
611             ( (cmos_fsm_ptr_t)p_fsm )->exp_write_set = exp_set;
612 
613             if ( ( ACAMERA_FSM2CTX_PTR( p_fsm )->stab.global_freeze_firmware != 1 ) ) {
614                 acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_SENSOR_UPDATE, NULL, 0 );
615 
616                 // frame_id should not be 0, at the beginning, it's initialized to 0 and we should skip it.
617                 if ( ( p_fsm->prev_ae_frame_id_tracking != exp_set.frame_id_tracking ) && ( exp_set.frame_id_tracking != 0 ) ) {
618                     fsm_param_mon_alg_flow_t ae_flow;
619 
620                     ( (cmos_fsm_ptr_t)p_fsm )->prev_ae_frame_id_tracking = exp_set.frame_id_tracking;
621 
622                     ae_flow.frame_id_tracking = exp_set.frame_id_tracking;
623                     ae_flow.frame_id_current = acamera_fsm_util_get_cur_frame_id( &( (cmos_fsm_ptr_t)p_fsm )->cmn );
624                     ae_flow.flow_state = MON_ALG_FLOW_STATE_APPLIED;
625                     acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_MON_AE_FLOW, &ae_flow, sizeof( ae_flow ) );
626                 }
627             }
628 
629             // check antiflicker frequency value
630             int flicker_freq = (int)param->global_anti_flicker_frequency * 256;
631             if ( param->global_antiflicker_enable == 0 ) {
632                 flicker_freq = 0;
633             }
634             if ( flicker_freq != p_fsm->flicker_freq ) {
635                 ( (cmos_fsm_ptr_t)p_fsm )->flicker_freq = flicker_freq;
636                 fsm_raise_event( p_fsm, event_id_antiflicker_changed );
637             }
638         }
639 
640         p_status_info->sys_info.exposure_log2 = p_fsm->exposure_log2;
641         p_status_info->sys_info.total_gain_log2 = p_fsm->again_val_log2 + p_fsm->dgain_val_log2 + p_fsm->isp_dgain_log2;
642 
643         cmos_mointor_frame_start( (cmos_fsm_ptr_t)p_fsm );
644 
645         break;
646     case ACAMERA_IRQ_FRAME_END: {
647 
648         if ( ( wdr_mode == WDR_MODE_FS_LIN ) && ( ACAMERA_FSM2CTX_PTR( p_fsm )->stab.global_manual_frame_stitch == 0 ) ) {
649 
650             if ( sensor_info.sensor_exp_number == 4 ) {
651                 acamera_isp_frame_stitch_svs_exposure_ratio_write( p_fsm->cmn.isp_base, p_fsm->exp_write_set.exposure_ratio_short );
652                 acamera_isp_frame_stitch_ms_exposure_ratio_write( p_fsm->cmn.isp_base, p_fsm->exp_write_set.exposure_ratio_medium );
653                 acamera_isp_frame_stitch_lm_exposure_ratio_write( p_fsm->cmn.isp_base, p_fsm->exp_write_set.exposure_ratio_medium2 );
654 
655                 int32_t R12 = p_fsm->exp_write_set.exposure_ratio_medium2;                        //long/medium ratio
656                 int32_t R13 = ( R12 * (int32_t)p_fsm->exp_write_set.exposure_ratio_medium ) >> 6; //long/short ratio
657                 int32_t R14 = ( R13 * (int32_t)p_fsm->exp_write_set.exposure_ratio_short ) >> 6;  //long/very_short ratio
658 
659                 if ( R12 < 0 ) {
660                     R12 = 1;
661                 }
662                 if ( R13 < 0 ) {
663                     R13 = 1;
664                 }
665                 if ( R14 < 0 ) {
666                     R14 = 1;
667                 }
668 
669                 const int32_t SF2 = ( 262144 / R12 + 262144 / R13 + 262144 / R14 ) * 2048 / ( 4096 + 262144 / R12 + 262144 / R13 + 262144 / R14 );
670                 const int32_t SF3 = ( 262144 / R13 + 262144 / R14 ) * 2048 / ( 262144 / R12 + 262144 / R13 + 262144 / R14 );
671                 const int32_t SF4 = ( 262144 / R14 ) * 2048 / ( 262144 / R13 + 262144 / R14 );
672 
673                 acamera_isp_frame_stitch_mcoff_l_scaler_write( p_fsm->cmn.isp_base, (uint16_t)SF2 );
674                 acamera_isp_frame_stitch_mcoff_lm_scaler_write( p_fsm->cmn.isp_base, (uint16_t)SF3 );
675                 acamera_isp_frame_stitch_mcoff_lms_scaler_write( p_fsm->cmn.isp_base, (uint16_t)SF4 );
676 
677             } else if ( sensor_info.sensor_exp_number == 3 ) {
678 
679                 acamera_isp_frame_stitch_ms_exposure_ratio_write( p_fsm->cmn.isp_base, p_fsm->exp_write_set.exposure_ratio_short );
680                 acamera_isp_frame_stitch_lm_exposure_ratio_write( p_fsm->cmn.isp_base, p_fsm->exp_write_set.exposure_ratio_medium );
681                 // mc off
682                 // if(Exp == 2)
683                 //     param.SF2 = 1/(1 + R12);
684                 //     param.SF3 = 0;
685                 //     param.SF4 = 0;
686                 // elseif(Exp == 3)
687                 //     param.SF2 = (1/R12 + 1/R13) / (1 + 1/R12 + 1/R13);
688                 //     param.SF3 = (1/R13)/(1/R12 + 1/R13);
689                 //     param.SF4 = 0;
690                 // elseif(Exp == 4)
691                 //     param.SF2 = (1/R12 + 1/R13 + 1/R14)/(1 + 1/R12 + 1/R13 + 1/R14);
692                 //     param.SF3 = (1/R13 + 1/R14)/(1/R12 + 1/R13 + 1/R14);
693                 //     param.SF4 = (1/R14)/(1/R13 + 1/R14);
694 
695                 int32_t SF2, SF3, SF4; //U0.11 registers
696                 int32_t R12, R13;
697                 R12 = p_fsm->exp_write_set.exposure_ratio_medium;                                                                                    //long/medium ratio
698                 R13 = ( ( int32_t )( p_fsm->exp_write_set.exposure_ratio_medium ) * ( int32_t )( p_fsm->exp_write_set.exposure_ratio_short ) ) >> 6; //long/short ratio
699                 // printf("r12 %d r13 %d\n",(int)R12,(int)R13 );
700                 // SF2 = round(((round(262144/R12) + round(262144/R13))*2048) / round((2^12 + round(262144/R12) + round(262144/R13))))
701 
702                 SF2 = ( ( 262144 / R12 + 262144 / R13 ) * 2048 ) / ( 4096 + 262144 / R12 + 262144 / R13 ); //U0.11
703                 SF3 = ( ( 262144 / R13 ) * 2048 ) / ( 262144 / R12 + 262144 / R13 );                       //U0.11
704                 SF4 = 0;
705                 acamera_isp_frame_stitch_mcoff_l_scaler_write( p_fsm->cmn.isp_base, (uint16_t)SF2 );
706                 acamera_isp_frame_stitch_mcoff_lm_scaler_write( p_fsm->cmn.isp_base, (uint16_t)SF3 );
707                 acamera_isp_frame_stitch_mcoff_lms_scaler_write( p_fsm->cmn.isp_base, (uint16_t)SF4 );
708 
709             } else if ( sensor_info.sensor_exp_number == 2 ) {
710                 int32_t SF2, R12; //U0.11 registers
711                 R12 = p_fsm->exp_write_set.exposure_ratio;
712                 SF2 = 262144 / ( 2048 + R12 );
713                 acamera_isp_frame_stitch_lm_exposure_ratio_write( p_fsm->cmn.isp_base, p_fsm->exp_write_set.exposure_ratio );
714 
715                 acamera_isp_frame_stitch_mcoff_l_scaler_write( p_fsm->cmn.isp_base, (uint16_t)SF2 );
716                 acamera_isp_frame_stitch_mcoff_lm_scaler_write( p_fsm->cmn.isp_base, (uint16_t)0 );
717                 acamera_isp_frame_stitch_mcoff_lms_scaler_write( p_fsm->cmn.isp_base, (uint16_t)0 );
718             } else {
719                 acamera_isp_frame_stitch_lm_exposure_ratio_write( p_fsm->cmn.isp_base, p_fsm->exp_write_set.exposure_ratio );
720             }
721         }
722 
723 #if defined( ISP_HAS_AWB_MESH_NBP_FSM ) || defined( ISP_HAS_AWB_MANUAL_FSM )
724         uint32_t i;
725         int32_t isp_dgain_log2 = p_fsm->exp_write_set.isp_dgain_log2;
726 
727         fsm_param_awb_info_t wb_info;
728         acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_AWB_INFO, NULL, 0, &wb_info, sizeof( wb_info ) );
729 
730         uint32_t gain;
731 
732         gain = acamera_math_exp2( isp_dgain_log2, LOG2_GAIN_SHIFT, 8 );
733         acamera_isp_digital_gain_gain_write( p_fsm->cmn.isp_base, gain );
734 
735         for ( i = 0; i < 4; ++i ) {
736             gain = acamera_math_exp2( wb_info.wb_log2[i], LOG2_GAIN_SHIFT, 8 );
737             ( (cmos_fsm_ptr_t)p_fsm )->wb[i] = gain > 0xFFF ? 0xFFF : (uint16_t)gain;
738         }
739 
740         // Expansion of values to the full range
741         uint32_t bl[4] = {acamera_isp_sensor_offset_pre_shading_offset_00_read( p_fsm->cmn.isp_base ),
742                           acamera_isp_sensor_offset_pre_shading_offset_01_read( p_fsm->cmn.isp_base ),
743                           acamera_isp_sensor_offset_pre_shading_offset_10_read( p_fsm->cmn.isp_base ),
744                           acamera_isp_sensor_offset_pre_shading_offset_11_read( p_fsm->cmn.isp_base )};
745         for ( i = 0; i < 4; ++i ) {
746             uint32_t mult = ( 256 * ( ( (uint32_t)1 << ACAMERA_ISP_SENSOR_OFFSET_PRE_SHADING_OFFSET_00_DATASIZE ) - 1 ) ) / ( ( ( (uint32_t)1 << ACAMERA_ISP_SENSOR_OFFSET_PRE_SHADING_OFFSET_00_DATASIZE ) - 1 ) - bl[i] );
747             ( (cmos_fsm_ptr_t)p_fsm )->wb[i] = ( ( ( uint32_t )( (cmos_fsm_ptr_t)p_fsm )->wb[i] ) * mult ) / 256;
748         }
749 
750         acamera_isp_white_balance_gain_00_write( p_fsm->cmn.isp_base, ( (cmos_fsm_ptr_t)p_fsm )->wb[0] );
751         acamera_isp_white_balance_gain_01_write( p_fsm->cmn.isp_base, ( (cmos_fsm_ptr_t)p_fsm )->wb[1] );
752         acamera_isp_white_balance_gain_10_write( p_fsm->cmn.isp_base, ( (cmos_fsm_ptr_t)p_fsm )->wb[2] );
753         acamera_isp_white_balance_gain_11_write( p_fsm->cmn.isp_base, ( (cmos_fsm_ptr_t)p_fsm )->wb[3] );
754 
755         if ( ACAMERA_FSM2CTX_PTR( p_fsm )->stab.global_manual_frame_stitch == 0 ) {
756 
757             acamera_isp_frame_stitch_gain_r_write( p_fsm->cmn.isp_base, ( (cmos_fsm_ptr_t)p_fsm )->wb[0] );
758             acamera_isp_frame_stitch_gain_b_write( p_fsm->cmn.isp_base, ( (cmos_fsm_ptr_t)p_fsm )->wb[3] );
759 
760             if ( acamera_isp_frame_stitch_mcoff_mode_enable_read( p_fsm->cmn.isp_base ) == 1 ) {
761                 acamera_isp_frame_stitch_gain_r_write( p_fsm->cmn.isp_base, 65536 / ( ( (cmos_fsm_ptr_t)p_fsm )->wb[0] ) );
762                 acamera_isp_frame_stitch_gain_b_write( p_fsm->cmn.isp_base, 65536 / ( ( (cmos_fsm_ptr_t)p_fsm )->wb[3] ) );
763             }
764         }
765 
766         uint32_t cur_frame_id = acamera_fsm_util_get_cur_frame_id( &( (cmos_fsm_ptr_t)p_fsm )->cmn );
767 
768         // "sensor_info.integration_time_apply_delay + 1" because the current frame_id is not so accurate.
769         if ( p_fsm->exp_write_set.frame_id_tracking && ( p_fsm->exp_write_set.frame_id_tracking != p_fsm->prev_dgain_frame_id ) &&
770              ( cur_frame_id - p_fsm->exp_write_set.frame_id_tracking > sensor_info.integration_time_apply_delay + 1 ) ) {
771             fsm_param_mon_err_head_t mon_err;
772             mon_err.err_type = MON_TYPE_ERR_CMOS_UPDATE_DGAIN_WRONG_TIMING;
773             mon_err.err_param = cur_frame_id - p_fsm->exp_write_set.frame_id_tracking - sensor_info.integration_time_apply_delay;
774             acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_MON_ERROR_REPORT, &mon_err, sizeof( mon_err ) );
775             ( (cmos_fsm_ptr_t)p_fsm )->prev_dgain_frame_id = p_fsm->exp_write_set.frame_id_tracking;
776         }
777 
778         // frame_id should not be 0, at the beginning, it's initialized to 0 and we should skip it.
779         if ( ( p_fsm->prev_awb_frame_id_tracking != wb_info.result_gain_frame_id ) && ( wb_info.result_gain_frame_id != 0 ) ) {
780             fsm_param_mon_alg_flow_t awb_flow;
781 
782             ( (cmos_fsm_ptr_t)p_fsm )->prev_awb_frame_id_tracking = wb_info.result_gain_frame_id;
783 
784             awb_flow.frame_id_tracking = wb_info.result_gain_frame_id;
785             awb_flow.frame_id_current = cur_frame_id;
786             awb_flow.flow_state = MON_ALG_FLOW_STATE_APPLIED;
787             acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_MON_AWB_FLOW, &awb_flow, sizeof( awb_flow ) );
788         }
789 
790 #endif //ISP_HAS_AWB_MESH_NBP_FSM
791 
792         _process_fps_cnt( (fps_counter_t *)&p_fsm->fps_cnt );
793     }
794 
795         cmos_mointor_frame_end( (cmos_fsm_ptr_t)p_fsm );
796 
797         break;
798     }
799 }
800 
cmos_inttime_update(cmos_fsm_ptr_t p_fsm)801 void cmos_inttime_update( cmos_fsm_ptr_t p_fsm )
802 {
803     int32_t int_time = 0;
804     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
805     if ( param->global_manual_integration_time == 0 ) {
806         int i;
807         int32_t exposure = 0, exp_target = p_fsm->exposure_log2;
808         if ( p_fsm->manual_gain_mode == 1 ) {
809             int_time = exp_target - acamera_log2_fixed_to_fixed( p_fsm->manual_gain, 8, LOG2_GAIN_SHIFT );
810         } else {
811             int32_t gain;
812             gain = cmos_get_manual_again_log2( p_fsm );
813             if ( gain >= 0 ) {
814                 exp_target -= gain;
815             }
816             gain = cmos_get_manual_dgain_log2( p_fsm );
817             if ( gain >= 0 ) {
818                 exp_target -= gain;
819             }
820             gain = cmos_get_manual_isp_dgain_log2( p_fsm );
821             if ( gain >= 0 ) {
822                 exp_target -= gain;
823             }
824             if ( exp_target < 0 ) {
825                 exp_target = 0;
826             }
827 
828             for ( i = 0; i < SYSTEM_EXPOSURE_PARTITION_VALUE_COUNT; ++i ) {
829                 int i_param = i & 1;
830                 int32_t addon = p_fsm->exp_lut[i];
831 
832                 if ( i_param == EXPOSURE_PARTITION_INTEGRATION_TIME_INDEX ) {
833                     if ( exposure + addon > exp_target ) {
834                         addon = exp_target - exposure;
835                     }
836                     int_time += addon;
837                 }
838                 exposure += addon;
839                 if ( exposure >= exp_target ) {
840                     break;
841                 }
842             }
843             if ( p_fsm->flicker_freq && !p_fsm->manual_gain_mode && param->global_antiflicker_enable ) {
844                 fsm_param_sensor_info_t sensor_info;
845                 acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
846 
847                 uint32_t line_per_half_period = ( sensor_info.lines_per_second << 8 ) / ( p_fsm->flicker_freq * 2 ); // division by zero is checked
848                 if ( line_per_half_period != 0 ) {
849                     int32_t half_period_log2 = acamera_log2_fixed_to_fixed( line_per_half_period, 0, LOG2_GAIN_SHIFT );
850                     if ( int_time < half_period_log2 ) {
851                         int_time = MIN( exp_target, half_period_log2 );
852                     }
853                 }
854             }
855         }
856     }
857     cmos_alloc_integration_time( p_fsm, int_time );
858 }
859 
cmos_analog_gain_update(cmos_fsm_ptr_t p_fsm)860 void cmos_analog_gain_update( cmos_fsm_ptr_t p_fsm )
861 {
862     int32_t target_gain = p_fsm->target_gain_log2;
863     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
864 
865     uint32_t wdr_mode = 0;
866     if ( param->global_analog_gain_last_priority == 1 ) {
867         acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_WDR_MODE, NULL, 0, &wdr_mode, sizeof( wdr_mode ) );
868 
869         if ( wdr_mode == WDR_MODE_NATIVE || wdr_mode == WDR_MODE_FS_LIN || wdr_mode == WDR_MODE_LINEAR ) {
870             // automatic sensor digital gain goes before analog gain
871             if ( cmos_get_manual_dgain_log2( p_fsm ) < 0 ) // negative means it is not manual
872             {
873                 p_fsm->dgain_val_log2 = cmos_alloc_sensor_digital_gain( p_fsm, target_gain );
874                 target_gain -= p_fsm->dgain_val_log2;
875             }
876             // analog gain has reserve before achieving maximum
877             if ( cmos_get_manual_isp_dgain_log2( p_fsm ) < 0 ) // negative means it is not manual
878             {
879                 int32_t max_again = (int32_t)param->global_max_sensor_analog_gain << ( LOG2_GAIN_SHIFT - 5 );
880                 int32_t max_isp_gain = ( (int32_t)param->global_max_isp_digital_gain << ( LOG2_GAIN_SHIFT - 5 ) ) - ( 1 << LOG2_GAIN_SHIFT );
881                 int32_t reserved_again = max_again - ( ( (int32_t)param->global_analog_gain_reserve ) << LOG2_GAIN_SHIFT );
882                 if ( target_gain > reserved_again + max_isp_gain ) {
883                     target_gain -= max_isp_gain;
884                 } else if ( target_gain > reserved_again ) {
885                     target_gain = reserved_again;
886                 }
887             }
888         }
889     }
890     const int32_t again_accuracy = ANALOG_GAIN_ACCURACY;
891     int32_t gain = cmos_get_manual_again_log2( p_fsm );
892     if ( gain < 0 ) // negative means it is not manual
893     {
894         // We should set as maximum as possible analogue gain less than or equals target_gain
895         gain = target_gain - again_accuracy;
896         if ( gain < 0 ) {
897             gain = 0;
898         }
899     }
900     if (param->global_manual_sensor_analog_gain == 0) {
901         int32_t again = cmos_alloc_sensor_analog_gain( p_fsm, gain );
902         if ( !param->global_manual_sensor_analog_gain &&
903              ( again != p_fsm->again_val_log2 ) ) {
904              if ( ( gain > p_fsm->again_val_log2 - again_accuracy ) &&
905                  ( gain < p_fsm->again_val_log2 + again_accuracy ) ) {
906                  again = cmos_alloc_sensor_analog_gain( p_fsm, p_fsm->again_val_log2 );
907              }
908         }
909         p_fsm->again_val_log2 = again;
910     } else {
911         p_fsm->again_val_log2 = gain;
912     }
913 }
914 
cmos_digital_gain_update(cmos_fsm_ptr_t p_fsm)915 void cmos_digital_gain_update( cmos_fsm_ptr_t p_fsm )
916 {
917 
918     int32_t gain = cmos_get_manual_dgain_log2( p_fsm );
919     if ( gain < 0 ) // negative means it is not manual
920     {
921         // we should set the rest gain to make target_gain equals analogue_gain x digital_gain
922         gain = cmos_alloc_sensor_digital_gain( p_fsm, p_fsm->target_gain_log2 - p_fsm->again_val_log2 );
923     }
924     p_fsm->dgain_val_log2 = gain;
925     gain = cmos_get_manual_isp_dgain_log2( p_fsm );
926     if ( gain < 0 ) // negative means it is not manual
927     {
928         gain = cmos_alloc_isp_digital_gain( p_fsm, p_fsm->target_gain_log2 - p_fsm->again_val_log2 - p_fsm->dgain_val_log2 );
929     }
930     p_fsm->isp_dgain_log2 = gain;
931 }
932 
get_quantised_integration_time(cmos_fsm_ptr_t p_fsm,uint32_t int_time)933 uint32_t get_quantised_integration_time( cmos_fsm_ptr_t p_fsm, uint32_t int_time )
934 {
935     if ( !p_fsm->flicker_freq || p_fsm->manual_gain_mode ) {
936         return int_time;
937     }
938 
939     fsm_param_sensor_info_t sensor_info;
940     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
941 
942     uint32_t line_per_half_period = ( sensor_info.lines_per_second << 8 ) / ( p_fsm->flicker_freq * 2 ); // division by zero is checked
943     if ( line_per_half_period != 0 && ( int_time >= line_per_half_period && int_time <= ( line_per_half_period << 2 ) ) ) {
944         uint32_t N = int_time / line_per_half_period; // division by zero is checked
945         if ( N < 1 ) {
946             N = 1;
947         }
948         return N * line_per_half_period;
949     } else {
950         return int_time;
951     }
952 }
953 
get_quantised_long_integration_time(cmos_fsm_ptr_t p_fsm,uint32_t int_time,uint32_t max_int_time)954 uint32_t get_quantised_long_integration_time( cmos_fsm_ptr_t p_fsm, uint32_t int_time, uint32_t max_int_time )
955 {
956     fsm_param_sensor_info_t sensor_info;
957     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
958 
959     if ( int_time < sensor_info.integration_time_min ) {
960         int_time = sensor_info.integration_time_min;
961     } else if ( int_time > max_int_time ) {
962         int_time = max_int_time;
963     }
964     return get_quantised_integration_time( p_fsm, int_time );
965 }
966 
cmos_antiflicker_update(cmos_fsm_ptr_t p_fsm)967 void cmos_antiflicker_update( cmos_fsm_ptr_t p_fsm )
968 {
969     uint32_t integration_time_short = get_quantised_integration_time( p_fsm, p_fsm->integration_time_short );
970 
971     if ( integration_time_short <= p_fsm->integration_time_short ) {
972         p_fsm->integration_time_short = integration_time_short;
973     } else {
974 // Very bright scene
975 #if OVEREXPOSE_TO_KEEP_ANTIFLICKER
976         uint32_t wdr_mode = 0;
977         acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_WDR_MODE, NULL, 0, &wdr_mode, sizeof( wdr_mode ) );
978         //Only do overexpose to keep antiflicker in linear mode
979         if ( wdr_mode == WDR_MODE_LINEAR ) {
980             cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
981             // if set manual integration time, do not adjust.
982             if ( param->global_manual_integration_time ) {
983                 return;
984             }
985             if ( param->global_antiflicker_enable && p_fsm->integration_time_short < integration_time_short ) {
986                 p_fsm->integration_time_short = integration_time_short; // division by zero is checked
987             }
988         }
989 #endif
990     }
991 }
992 
cmos_long_exposure_update(cmos_fsm_ptr_t p_fsm)993 void cmos_long_exposure_update( cmos_fsm_ptr_t p_fsm )
994 {
995     fsm_param_sensor_int_time_t time;
996 
997     fsm_param_sensor_info_t sensor_info;
998     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
999 
1000     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
1001     uint32_t exposure_ratio, integration_time_long, integration_time_long_quant;
1002     uint32_t wdr_mode = 0;
1003 
1004     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_WDR_MODE, NULL, 0, &wdr_mode, sizeof( wdr_mode ) );
1005 
1006     if ( ( wdr_mode == WDR_MODE_FS_LIN ) || ( ( wdr_mode == WDR_MODE_NATIVE ) && ( sensor_info.sensor_exp_number == 3 ) ) ) {
1007         uint32_t integration_time_long_max = sensor_info.integration_time_long_max;
1008         if ( !integration_time_long_max ) {
1009             uint32_t integration_time_long_max = sensor_info.integration_time_limit;
1010 
1011             if ( param->global_manual_max_integration_time && integration_time_long_max > param->global_max_integration_time ) {
1012                 integration_time_long_max = param->global_max_integration_time;
1013             }
1014         }
1015         exposure_ratio = p_fsm->exposure_ratio_in;
1016         if ( exposure_ratio < 64 ) {
1017             exposure_ratio = 64;
1018         }
1019 #if EXPOSURE_DRIVES_LONG_INTEGRATION_TIME
1020         uint32_t min_integration_time_short = sensor_info.integration_time_min;
1021         // Inverse long and short exposure
1022         integration_time_long = p_fsm->integration_time_short;
1023         p_fsm->integration_time_short = ( (uint32_t)integration_time_long << 6 ) / exposure_ratio; // division by zero is checked
1024         if ( p_fsm->integration_time_short < min_integration_time_short ) {
1025             p_fsm->integration_time_short = min_integration_time_short;
1026         }
1027         uint32_t integration_time_max = sensor_info.integration_time_max;
1028         if ( p_fsm->integration_time_short > integration_time_max ) {
1029             p_fsm->integration_time_short = integration_time_max;
1030         }
1031 #else
1032         integration_time_long = (uint32_t)p_fsm->integration_time_short * exposure_ratio >> 6;
1033         if ( integration_time_long > 0xFFFF )
1034             integration_time_long = 0xFFFF;
1035 #endif
1036 
1037         integration_time_long_quant = get_quantised_long_integration_time( p_fsm, integration_time_long, integration_time_long_max );
1038 #if EXPOSURE_DRIVES_LONG_INTEGRATION_TIME
1039         if ( integration_time_long < integration_time_long_quant ) {
1040             integration_time_long_quant = integration_time_long;
1041         }
1042 #endif
1043         if ( integration_time_long_quant > integration_time_long_max ) {
1044             integration_time_long_quant = integration_time_long_max;
1045         }
1046 
1047 #if FILTER_LONG_INT_TIME
1048         //rotate the FIFO
1049         if ( ++p_fsm->long_it_hist.p > &( p_fsm->long_it_hist.v[FILTER_LONG_INT_TIME - 1] ) )
1050             p_fsm->long_it_hist.p = &( p_fsm->long_it_hist.v[0] );
1051         p_fsm->long_it_hist.sum -= *p_fsm->long_it_hist.p;
1052         *p_fsm->long_it_hist.p = integration_time_long_quant;
1053         p_fsm->long_it_hist.sum += *p_fsm->long_it_hist.p;
1054 
1055         integration_time_long_quant = p_fsm->long_it_hist.sum / FILTER_LONG_INT_TIME; // division by zero is checked
1056 #endif
1057 
1058         p_fsm->integration_time_long = integration_time_long_quant;
1059         if ( sensor_info.sensor_exp_number == 4 ) {
1060 
1061             const uint32_t exposure_ratio_thresholded = exposure_ratio > 256 ? exposure_ratio / 2 : exposure_ratio;
1062             const uint32_t ratio_cube_root = acamera_math_exp2( acamera_log2_fixed_to_fixed( exposure_ratio_thresholded, 6, 16 ) / 3, 16, 6 );
1063             //LOG(LOG_CRIT, "ratio_cube_root: %d -> %d", exposure_ratio_thresholded, ratio_cube_root);
1064 
1065             uint32_t integration_time_medium1 = p_fsm->integration_time_short * ratio_cube_root >> 6;
1066             uint32_t integration_time_medium2 = integration_time_medium1 * ratio_cube_root >> 6;
1067 
1068             if ( integration_time_medium2 > integration_time_long_max ) {
1069                 integration_time_medium2 = integration_time_long_max;
1070             }
1071             if ( integration_time_medium2 > p_fsm->integration_time_long ) {
1072                 integration_time_medium2 = p_fsm->integration_time_long;
1073             }
1074             if ( integration_time_medium1 > integration_time_medium2 ) {
1075                 integration_time_medium1 = integration_time_medium2;
1076             }
1077 
1078             time.int_time = p_fsm->integration_time_short;
1079             time.int_time_M = integration_time_medium1;
1080             time.int_time_M2 = integration_time_medium2;
1081             time.int_time_L = p_fsm->integration_time_long;
1082 
1083             acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_SENSOR_ALLOC_INTEGRATION_TIME, &time, sizeof( time ) );
1084 
1085             // time is updated in above function, save it.
1086             p_fsm->integration_time_short = time.int_time;
1087             p_fsm->integration_time_medium = time.int_time_M;
1088             p_fsm->integration_time_medium2 = time.int_time_M2;
1089             p_fsm->integration_time_long = time.int_time_L;
1090 
1091         } else if ( sensor_info.sensor_exp_number == 3 ) {
1092             uint32_t integration_time_medium;
1093             if ( exposure_ratio > 256 ) {
1094                 //half ML ratio by two
1095                 integration_time_medium = (uint32_t)p_fsm->integration_time_short * ( acamera_sqrt32( exposure_ratio ) << 1 ) >> 3;
1096             } else {
1097                 integration_time_medium = (uint32_t)p_fsm->integration_time_short * acamera_sqrt32( exposure_ratio ) >> 3;
1098             }
1099             //integration_time_medium = (uint32_t)p_fsm->integration_time_short * acamera_sqrt32( exposure_ratio ) >> 3;
1100 
1101             //LOG( LOG_ERR, "integration_time_medium %d exposure_ratio %d  sqrt32( exposure_ratio ) %d", integration_time_medium, exposure_ratio/64, acamera_sqrt32( exposure_ratio )<<3 );
1102             if ( integration_time_medium > integration_time_long_max ) {
1103                 integration_time_medium = integration_time_long_max;
1104             }
1105             if ( integration_time_medium > p_fsm->integration_time_long ) {
1106                 integration_time_medium = p_fsm->integration_time_long;
1107             }
1108             p_fsm->integration_time_medium = (uint16_t)integration_time_medium;
1109 
1110             time.int_time = p_fsm->integration_time_short;
1111             time.int_time_M = p_fsm->integration_time_medium;
1112             time.int_time_L = p_fsm->integration_time_long;
1113             //LOG( LOG_ERR, " short %d medium %d long %d", p_fsm->integration_time_short, p_fsm->integration_time_medium, p_fsm->integration_time_long );
1114 
1115             acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_SENSOR_ALLOC_INTEGRATION_TIME, &time, sizeof( time ) );
1116 
1117             // time is updated in above function, save it.
1118             p_fsm->integration_time_short = time.int_time;
1119             p_fsm->integration_time_medium = time.int_time_M;
1120             p_fsm->integration_time_long = time.int_time_L;
1121 
1122         } else if ( sensor_info.sensor_exp_number == 2 ) {
1123             time.int_time = p_fsm->integration_time_short;
1124             time.int_time_L = p_fsm->integration_time_long;
1125 
1126             acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_SENSOR_ALLOC_INTEGRATION_TIME, &time, sizeof( time ) );
1127 
1128             // time is updated in above function, save it.
1129             p_fsm->integration_time_short = time.int_time;
1130             p_fsm->integration_time_long = time.int_time_L;
1131 
1132         } else {
1133             time.int_time = is_short_exposure_frame( p_fsm->cmn.isp_base ) ? p_fsm->integration_time_short : p_fsm->integration_time_long;
1134 
1135             acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_SENSOR_ALLOC_INTEGRATION_TIME, &time, sizeof( time ) );
1136 
1137             // time is updated in above function, save it.
1138             if ( is_short_exposure_frame( p_fsm->cmn.isp_base ) )
1139                 p_fsm->integration_time_short = time.int_time;
1140             else
1141                 p_fsm->integration_time_long = time.int_time;
1142         }
1143 
1144         p_fsm->exposure_ratio = ( uint16_t )( 64 * (uint32_t)p_fsm->integration_time_long / p_fsm->integration_time_short );
1145     } else {
1146         p_fsm->exposure_ratio = 64;
1147 
1148         if ( sensor_info.sensor_exp_number == 4 ) {
1149 
1150             time.int_time = p_fsm->integration_time_short;
1151             time.int_time_M = p_fsm->integration_time_short;
1152             time.int_time_M2 = p_fsm->integration_time_short;
1153             time.int_time_L = p_fsm->integration_time_short;
1154 
1155             acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_SENSOR_ALLOC_INTEGRATION_TIME, &time, sizeof( time ) );
1156 
1157             // NOTE: the value of 'p_fsm->integration_time_short' depends on the order
1158             // that sensor function modify the pointer values, I checked the some functions,
1159             // and found that the 3rd parameter will be modified at last, so we use the 3rd
1160             // parameter to save back into the 'p_fsm->integration_time_short' variable.
1161             p_fsm->integration_time_short = time.int_time_L;
1162 
1163         } else if ( sensor_info.sensor_exp_number == 3 ) {
1164             time.int_time = p_fsm->integration_time_short;
1165             time.int_time_M = p_fsm->integration_time_short;
1166             time.int_time_L = p_fsm->integration_time_short;
1167 
1168             acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_SENSOR_ALLOC_INTEGRATION_TIME, &time, sizeof( time ) );
1169 
1170             // time is updated in above function, save it.
1171             p_fsm->integration_time_short = time.int_time_L;
1172 
1173         } else if ( sensor_info.sensor_exp_number == 2 ) {
1174             time.int_time = p_fsm->integration_time_short;
1175             time.int_time_L = p_fsm->integration_time_short;
1176 
1177             acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_SENSOR_ALLOC_INTEGRATION_TIME, &time, sizeof( time ) );
1178 
1179             // time is updated in above function, save it.
1180             p_fsm->integration_time_short = time.int_time_L;
1181         } else {
1182             time.int_time = p_fsm->integration_time_short;
1183 
1184             acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_SENSOR_ALLOC_INTEGRATION_TIME, &time, sizeof( time ) );
1185 
1186             // time is updated in above function, save it.
1187             p_fsm->integration_time_short = time.int_time;
1188         }
1189     }
1190 }
1191 
cmos_calc_target_gain(cmos_fsm_ptr_t p_fsm)1192 void cmos_calc_target_gain( cmos_fsm_ptr_t p_fsm )
1193 {
1194     int32_t target_gain_log2 = 0;
1195     if ( p_fsm->manual_gain_mode == 1 ) {
1196         target_gain_log2 = acamera_log2_fixed_to_fixed( p_fsm->manual_gain, 8, LOG2_GAIN_SHIFT );
1197     } else {
1198 #if EXPOSURE_DRIVES_LONG_INTEGRATION_TIME
1199         uint32_t wdr_mode = 0;
1200 
1201         acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_WDR_MODE, NULL, 0, &wdr_mode, sizeof( wdr_mode ) );
1202 
1203         target_gain_log2 = p_fsm->exposure_log2 - acamera_log2_fixed_to_fixed( ( ( wdr_mode == WDR_MODE_LINEAR ) ? p_fsm->integration_time_short : p_fsm->integration_time_long ), 0, LOG2_GAIN_SHIFT );
1204 #else
1205         target_gain_log2 = p_fsm->exposure_log2 - acamera_log2_fixed_to_fixed( p_fsm->integration_time_short, 0, LOG2_GAIN_SHIFT );
1206 #endif
1207     }
1208 
1209     if ( target_gain_log2 < 0 ) {
1210         target_gain_log2 = 0;
1211     }
1212     p_fsm->target_gain_step_log2 = target_gain_log2 - p_fsm->target_gain_log2;
1213     if ( p_fsm->target_gain_step_log2 < 0 ) {
1214         p_fsm->target_gain_step_log2 = -p_fsm->target_gain_step_log2;
1215     }
1216     p_fsm->target_gain_log2 = target_gain_log2;
1217 }
1218 
cmos_set_exposure_target(cmos_fsm_ptr_t p_fsm,int32_t exposure_log2,uint32_t exposure_ratio)1219 void cmos_set_exposure_target( cmos_fsm_ptr_t p_fsm, int32_t exposure_log2, uint32_t exposure_ratio )
1220 {
1221 #if defined( ISP_HAS_DEFECT_PIXEL_FSM )
1222 
1223     fsm_param_defect_pixel_info_t dp_info;
1224 
1225     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_DEFECT_PIXEL_INFO, NULL, 0, &dp_info, sizeof( dp_info ) );
1226 
1227     if ( !dp_info.hp_started )
1228 #endif
1229     {
1230 
1231         uint32_t wdr_mode = 0;
1232 
1233         fsm_param_sensor_info_t sensor_info;
1234         acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
1235         acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_WDR_MODE, NULL, 0, &wdr_mode, sizeof( wdr_mode ) );
1236 
1237         // for HDR mode with one exposure we can set new exposure only every second frame
1238         if ( !( ( ( wdr_mode == WDR_MODE_FS_LIN ) ) && ( sensor_info.sensor_exp_number == 1 ) && !is_short_exposure_frame( p_fsm->cmn.isp_base ) ) ) {
1239             cmos_control_param_t *param_cmos = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
1240             p_fsm->exposure_log2 = exposure_log2;
1241             p_fsm->exposure_ratio_in = exposure_ratio;
1242             if ( p_fsm->exposure_ratio_in > (uint32_t)param_cmos->global_max_exposure_ratio * 64 ) {
1243 
1244                 p_fsm->exposure_ratio_in = param_cmos->global_max_exposure_ratio * 64;
1245             }
1246 
1247             LOG( LOG_DEBUG, "Set exposure %d and exposure ratio %d", (unsigned int)exposure_log2, (unsigned int)exposure_ratio );
1248         }
1249     }
1250 #ifdef ISP_HAS_SENSOR_FSM
1251 #if USER_MODULE
1252     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_MAX_EXPOSURE_LOG2, NULL, 0, &p_fsm->max_exposure_log2, sizeof( p_fsm->max_exposure_log2 ) );
1253 #else
1254     cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
1255 
1256     fsm_param_sensor_info_t sensor_info;
1257     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_SENSOR_INFO, NULL, 0, &sensor_info, sizeof( sensor_info ) );
1258 
1259     param->global_max_sensor_analog_gain = MIN( param->global_max_sensor_analog_gain, sensor_info.again_log2_max >> ( LOG2_GAIN_SHIFT - 5 ) );
1260     param->global_max_sensor_digital_gain = MIN( param->global_max_sensor_digital_gain, sensor_info.dgain_log2_max >> ( LOG2_GAIN_SHIFT - 5 ) );
1261     param->global_max_integration_time = MIN( param->global_max_integration_time, sensor_info.integration_time_limit );
1262 
1263 
1264     int32_t max_again_log2 = MIN( sensor_info.again_log2_max, (int32_t)param->global_max_sensor_analog_gain << ( LOG2_GAIN_SHIFT - 5 ) );
1265     int32_t max_dgain_log2 = MIN( sensor_info.dgain_log2_max, (int32_t)param->global_max_sensor_digital_gain << ( LOG2_GAIN_SHIFT - 5 ) );
1266     int32_t max_isp_gain_log2 = MIN( p_fsm->maximum_isp_digital_gain, (int32_t)param->global_max_isp_digital_gain << ( LOG2_GAIN_SHIFT - 5 ) );
1267     int32_t max_integration_time_log2 = acamera_log2_fixed_to_fixed( sensor_info.integration_time_limit, 0, LOG2_GAIN_SHIFT );
1268     p_fsm->max_exposure_log2 = max_again_log2 + max_dgain_log2 + max_isp_gain_log2 + max_integration_time_log2;
1269 #endif // #if USER_MODULE
1270 #endif
1271 }
1272 
cmos_deinit(cmos_fsm_ptr_t p_fsm)1273 void cmos_deinit( cmos_fsm_ptr_t p_fsm )
1274 {
1275     system_spinlock_destroy( p_fsm->exp_lock );
1276 }
1277