• 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 "cmos_fsm.h"
22 
23 #ifdef LOG_MODULE
24 #undef LOG_MODULE
25 #define LOG_MODULE LOG_MODULE_CMOS
26 #endif
27 
cmos_fsm_clear(cmos_fsm_t * p_fsm)28 void cmos_fsm_clear( cmos_fsm_t *p_fsm )
29 {
30     p_fsm->manual_gain_mode = 0;
31     p_fsm->manual_gain = 1;
32     p_fsm->exposure = 256;
33     p_fsm->exposure_log2 = 2 << LOG2_GAIN_SHIFT;
34     p_fsm->max_exposure_log2 = 2 << LOG2_GAIN_SHIFT;
35     p_fsm->exposure_hist_pos = -1;
36     p_fsm->flicker_freq = 50 * 256;
37     p_fsm->exposure_ratio_in = 64;
38     p_fsm->integration_time_short = 0;
39     p_fsm->integration_time_medium = 0;
40     p_fsm->integration_time_long = 0;
41     p_fsm->exposure_ratio = 64;
42     p_fsm->log2_gain_avg = 0;
43     p_fsm->isp_dgain_log2 = 0;
44     p_fsm->target_gain_log2 = 0;
45     p_fsm->strategy = 0;
46 
47     p_fsm->maximum_isp_digital_gain = ( ( ACAMERA_ISP_DIGITAL_GAIN_GAIN_DATASIZE - 8 ) << LOG2_GAIN_SHIFT ) + acamera_log2_fixed_to_fixed( ( 1 << ACAMERA_ISP_DIGITAL_GAIN_GAIN_DATASIZE ) - 1, ACAMERA_ISP_DIGITAL_GAIN_GAIN_DATASIZE, LOG2_GAIN_SHIFT );
48 
49 
50     p_fsm->frame_id_tracking = 0;
51     p_fsm->prev_ae_frame_id_tracking = 0;
52     p_fsm->prev_awb_frame_id_tracking = 0;
53 
54     p_fsm->prev_fs_frame_id = 0;
55     p_fsm->prev_dgain_frame_id = 0;
56 }
57 
cmos_request_interrupt(cmos_fsm_ptr_t p_fsm,system_fw_interrupt_mask_t mask)58 void cmos_request_interrupt( cmos_fsm_ptr_t p_fsm, system_fw_interrupt_mask_t mask )
59 {
60     acamera_isp_interrupts_disable( ACAMERA_FSM2MGR_PTR( p_fsm ) );
61     p_fsm->mask.irq_mask |= mask;
62     acamera_isp_interrupts_enable( ACAMERA_FSM2MGR_PTR( p_fsm ) );
63 }
64 
cmos_fsm_init(void * fsm,fsm_init_param_t * init_param)65 void cmos_fsm_init( void *fsm, fsm_init_param_t *init_param )
66 {
67     cmos_fsm_t *p_fsm = (cmos_fsm_t *)fsm;
68     p_fsm->cmn.p_fsm_mgr = init_param->p_fsm_mgr;
69     p_fsm->cmn.isp_base = init_param->isp_base;
70     p_fsm->p_fsm_mgr = init_param->p_fsm_mgr;
71 
72     cmos_fsm_clear( p_fsm );
73 
74     cmos_init( p_fsm );
75 }
76 
cmos_fsm_set_param(void * fsm,uint32_t param_id,void * input,uint32_t input_size)77 int cmos_fsm_set_param( void *fsm, uint32_t param_id, void *input, uint32_t input_size )
78 {
79     int rc = 0;
80     cmos_fsm_t *p_fsm = (cmos_fsm_t *)fsm;
81 
82     switch ( param_id ) {
83     case FSM_PARAM_SET_EXPOSURE_TARGET: {
84         fsm_param_exposure_target_t *p_exp_target = NULL;
85 
86         if ( ( !input || input_size != sizeof( fsm_param_exposure_target_t ) ) ) {
87             LOG( LOG_ERR, "Inavlid param, param_id: %d.", param_id );
88             rc = -1;
89             break;
90         }
91 
92         p_exp_target = (fsm_param_exposure_target_t *)input;
93 
94         cmos_set_exposure_target( p_fsm, p_exp_target->exposure_log2, p_exp_target->exposure_ratio );
95 
96         /* check whether the application is succeed
97          * just need to check exposure, the exp_ratio maybe adjusted by max_exp_ratio.
98          */
99         if ( p_fsm->exposure_log2 != p_exp_target->exposure_log2 ) {
100             LOG( LOG_INFO, "new AE failed, expected: exp_log2: %d, cmos_values: exp_log2: %d.",
101                  (int)p_exp_target->exposure_log2,
102                  (int)p_fsm->exposure_log2 );
103 
104             rc = -2;
105         } else {
106             LOG( LOG_DEBUG, "new frame_id_tracking: %d.", p_exp_target->frame_id_tracking );
107             p_fsm->frame_id_tracking = p_exp_target->frame_id_tracking;
108         }
109 
110         break;
111     }
112 
113     case FSM_PARAM_SET_AE_MODE: {
114         if ( !input || input_size != sizeof( fsm_param_ae_mode_t ) ) {
115             LOG( LOG_ERR, "Invalid param, param_id: %d.", param_id );
116             rc = -1;
117             break;
118         }
119 
120         fsm_param_ae_mode_t *p_ae_mode = (fsm_param_ae_mode_t *)input;
121 
122         if ( p_ae_mode->flag & AE_MODE_BIT_MANUAL_INT_TIME ) {
123             cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
124             param->global_manual_integration_time = p_ae_mode->manual_integration_time;
125         }
126 
127         if ( p_ae_mode->flag & AE_MODE_BIT_MANUAL_GAIN_MODE ) {
128             p_fsm->manual_gain_mode = p_ae_mode->manual_gain_mode;
129         }
130 
131         break;
132     }
133 
134     case FSM_PARAM_SET_MANUAL_GAIN:
135         if ( !input || input_size != sizeof( uint32_t ) ) {
136             LOG( LOG_ERR, "Invalid param, param_id: %d.", param_id );
137             rc = -1;
138             break;
139         }
140 
141         p_fsm->manual_gain = *(uint32_t *)input;
142 
143         break;
144 
145     case FSM_PARAM_SET_CMOS_ADJUST_EXP: {
146         int i;
147         int32_t corr = 0;
148 
149         if ( !input || input_size != sizeof( int32_t ) ) {
150             LOG( LOG_ERR, "Invalid param, param_id: %d.", param_id );
151             rc = -1;
152             break;
153         }
154 
155         corr = *(int32_t *)input;
156 
157         // adjust exposure
158         for ( i = 0; i < array_size_s( p_fsm->exposure_hist ); i++ ) {
159             exposure_info_set_t *info = &cmos_get_frame_exposure_set( p_fsm, i )->info;
160             info->exposure_log2 += corr;
161             if ( info->exposure_log2 < 0 )
162                 info->exposure_log2 = 0;
163         }
164         break;
165     }
166 
167     case FSM_PARAM_SET_CMOS_SPLIT_STRATEGY: {
168         uint32_t strategy;
169 
170         if ( !input || input_size != sizeof( uint32_t ) ) {
171             LOG( LOG_ERR, "Invalid param, param_id: %d.", param_id );
172             rc = -1;
173             break;
174         }
175 
176         strategy = *(uint32_t *)input;
177 
178         switch ( strategy ) {
179         case AE_SPLIT_BALANCED:
180             p_fsm->strategy = AE_SPLIT_BALANCED;
181             cmos_update_exposure_partitioning_lut( p_fsm );
182             break;
183 
184         case AE_SPLIT_INTEGRATION_PRIORITY:
185             p_fsm->strategy = AE_SPLIT_INTEGRATION_PRIORITY;
186             cmos_update_exposure_partitioning_lut( p_fsm );
187             break;
188         default:
189             rc = -2;
190             LOG( LOG_WARNING, "Not supported strategy preset: %d.", strategy );
191             return NOT_SUPPORTED;
192         }
193         break;
194     }
195 
196     default:
197         rc = -1;
198         LOG( LOG_WARNING, "Not supported cmd id: %d.", param_id );
199         break;
200     }
201 
202     return rc;
203 }
204 
cmos_fsm_get_param(void * fsm,uint32_t param_id,void * input,uint32_t input_size,void * output,uint32_t output_size)205 int cmos_fsm_get_param( void *fsm, uint32_t param_id, void *input, uint32_t input_size, void *output, uint32_t output_size )
206 {
207     int rc = 0;
208     cmos_fsm_t *p_fsm = (cmos_fsm_t *)fsm;
209 
210     switch ( param_id ) {
211     case FSM_PARAM_GET_CMOS_EXPOSURE_LOG2: {
212 
213         if ( ( !input || input_size != sizeof( int32_t ) ) ||
214              ( !output || output_size != sizeof( int32_t ) ) ) {
215             LOG( LOG_ERR, "Inavlid param, param_id: %d.", param_id );
216             rc = -1;
217             break;
218         }
219 
220         if ( CMOS_CURRENT_EXPOSURE_LOG2 == *(int32_t *)input ) {
221             *(int32_t *)output = p_fsm->exposure_log2;
222         } else if ( CMOS_MAX_EXPOSURE_LOG2 == *(int32_t *)input ) {
223             *(int32_t *)output = p_fsm->max_exposure_log2;
224         } else {
225             LOG( LOG_ERR, "Param_id: %d, unsupported param: %d.", param_id, *(int32_t *)input );
226             rc = -1;
227         }
228 
229         break;
230     }
231 
232     case FSM_PARAM_GET_CMOS_EXPOSURE_RATIO:
233         if ( ( !output || output_size != sizeof( uint32_t ) ) ) {
234             LOG( LOG_ERR, "Inavlid param, param_id: %d.", param_id );
235             rc = -1;
236             break;
237         }
238 
239         *(uint32_t *)output = p_fsm->exposure_ratio;
240 
241         break;
242 
243     case FSM_PARAM_GET_FRAME_EXPOSURE_SET: {
244 
245         if ( ( !input || input_size != sizeof( int32_t ) ) ||
246              ( !output || output_size != sizeof( exposure_set_t ) ) ) {
247             LOG( LOG_ERR, "Inavlid param, param_id: %d.", param_id );
248             rc = -1;
249             break;
250         }
251 
252         exposure_set_t *p_set_get = NULL;
253         exposure_set_t *p_set_out = (exposure_set_t *)output;
254 
255         p_set_get = cmos_get_frame_exposure_set( p_fsm, *( (int *)input ) );
256 
257         *p_set_out = *p_set_get;
258 
259         break;
260     }
261 
262     case FSM_PARAM_GET_CMOS_TOTAL_GAIN:
263         if ( ( !output || output_size != sizeof( int32_t ) ) ) {
264             LOG( LOG_ERR, "Inavlid param, param_id: %d.", param_id );
265             rc = -1;
266             break;
267         }
268 
269 #if USER_MODULE
270         rc = acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_TOTAL_GAIN_LOG2, NULL, 0, output, output_size );
271 #else
272         *( (int32_t *)output ) = p_fsm->again_val_log2 +
273                                  p_fsm->dgain_val_log2 +
274                                  p_fsm->isp_dgain_log2;
275 #endif
276         break;
277 
278     case FSM_PARAM_GET_FPS:
279         if ( ( !output || output_size != sizeof( uint32_t ) ) ) {
280             LOG( LOG_ERR, "Inavlid param, param_id: %d.", param_id );
281             rc = -1;
282             break;
283         }
284 
285         *( (uint32_t *)output ) = cmos_get_fps( p_fsm );
286 
287         break;
288 
289     case FSM_PARAM_GET_AE_MODE: {
290         if ( ( !output || output_size != sizeof( fsm_param_ae_mode_t ) ) ) {
291             LOG( LOG_ERR, "Inavlid param, param_id: %d.", param_id );
292             rc = -1;
293             break;
294         }
295 
296         fsm_param_ae_mode_t *p_ae_mode = (fsm_param_ae_mode_t *)output;
297 
298         if ( p_ae_mode->flag & AE_MODE_BIT_MANUAL_INT_TIME ) {
299             cmos_control_param_t *param = (cmos_control_param_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CMOS_CONTROL );
300             p_ae_mode->manual_integration_time = param->global_manual_integration_time;
301         }
302 
303         if ( p_ae_mode->flag & AE_MODE_BIT_MANUAL_GAIN_MODE ) {
304             p_ae_mode->manual_gain_mode = p_fsm->manual_gain_mode;
305         }
306 
307         break;
308     }
309 
310     case FSM_PARAM_GET_GAIN: {
311         if ( !input || input_size != sizeof( fsm_param_gain_calc_param_t ) ||
312              !output || output_size != sizeof( uint32_t ) ) {
313             LOG( LOG_ERR, "Inavlid param, param_id: %d.", param_id );
314             rc = -1;
315             break;
316         }
317 
318         fsm_param_gain_calc_param_t *p_param = (fsm_param_gain_calc_param_t *)input;
319 
320         *( (uint32_t *)output ) = acamera_math_exp2( p_fsm->again_val_log2 + p_fsm->dgain_val_log2 + p_fsm->isp_dgain_log2, p_param->shift_in, p_param->shift_out );
321 
322         break;
323     }
324 
325     case FSM_PARAM_GET_CMOS_EXP_WRITE_SET:
326         if ( ( !output || output_size != sizeof( exposure_data_set_t ) ) ) {
327             LOG( LOG_ERR, "Inavlid param, param_id: %d.", param_id );
328             rc = -1;
329             break;
330         }
331 
332         *(exposure_data_set_t *)output = p_fsm->exp_write_set;
333 
334         break;
335 
336     case FSM_PARAM_GET_CMOS_SPLIT_STRATEGY:
337         if ( ( !output || output_size != sizeof( uint32_t ) ) ) {
338             LOG( LOG_ERR, "Inavlid param, param_id: %d.", param_id );
339             rc = -1;
340             break;
341         }
342 
343         *( (uint32_t *)output ) = p_fsm->strategy;
344 
345         break;
346 
347     default:
348         rc = -1;
349         break;
350     }
351 
352     return rc;
353 }
354 
355 
cmos_fsm_process_event(cmos_fsm_t * p_fsm,event_id_t event_id)356 uint8_t cmos_fsm_process_event( cmos_fsm_t *p_fsm, event_id_t event_id )
357 {
358     uint8_t b_event_processed = 0;
359     switch ( event_id ) {
360     default:
361         break;
362     case event_id_sensor_ready:
363         cmos_update_exposure_partitioning_lut( p_fsm );
364 
365         // Update gains
366         cmos_inttime_update( p_fsm );
367         cmos_antiflicker_update( p_fsm );
368         cmos_long_exposure_update( p_fsm );
369 
370         // Update gains
371         cmos_calc_target_gain( p_fsm );
372         cmos_analog_gain_update( p_fsm );
373         cmos_digital_gain_update( p_fsm );
374         fsm_raise_event( p_fsm, event_id_update_iridix );
375 
376         cmos_update_exposure_history( p_fsm );
377 
378         b_event_processed = 1;
379         break;
380 
381     case event_id_antiflicker_changed:
382 
383         cmos_antiflicker_update( p_fsm );
384         cmos_long_exposure_update( p_fsm );
385 
386         // Update gains
387         cmos_calc_target_gain( p_fsm );
388         cmos_analog_gain_update( p_fsm );
389         cmos_digital_gain_update( p_fsm );
390         fsm_raise_event( p_fsm, event_id_update_iridix );
391 
392         cmos_update_exposure_history( p_fsm );
393 
394         b_event_processed = 1;
395         break;
396 
397     case event_id_cmos_refresh:
398         cmos_request_interrupt( p_fsm, ACAMERA_IRQ_MASK( ACAMERA_IRQ_FRAME_START ) );
399         b_event_processed = 1;
400         break;
401 
402     case event_id_sensor_not_ready:
403         b_event_processed = 1;
404         break;
405 
406     case event_id_exposure_changed:
407 
408         // Update gains
409         cmos_inttime_update( p_fsm );
410         cmos_antiflicker_update( p_fsm );
411         cmos_long_exposure_update( p_fsm );
412 
413         // Update gains
414         cmos_calc_target_gain( p_fsm );
415         cmos_analog_gain_update( p_fsm );
416         cmos_digital_gain_update( p_fsm );
417         fsm_raise_event( p_fsm, event_id_update_iridix );
418 
419         cmos_update_exposure_history( p_fsm );
420 
421         b_event_processed = 1;
422         break;
423     }
424 
425     return b_event_processed;
426 }
427