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