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_firmware_api.h"
22 #include "acamera_firmware_config.h"
23 #include "acamera_calibrations.h"
24 #include "acamera.h"
25 #include "acamera_math.h"
26 #include "acamera_isp_config.h"
27 #include "acamera_isp_core_nomem_settings.h"
28 #include "system_stdlib.h"
29 #include "system_dma.h"
30 #include "acamera_metering_stats_mem_config.h"
31 #include "acamera_aexp_hist_stats_mem_config.h"
32 #include "acamera_decompander0_mem_config.h"
33 #include "acamera_ihist_stats_mem_config.h"
34 #include "system_am_md.h"
35
36
37 #if FW_HAS_CONTROL_CHANNEL
38 #include "acamera_ctrl_channel.h"
39 #endif
40
41 #if ISP_DMA_RAW_CAPTURE
42 #include "dma_raw_capture.h"
43 #endif
44
45 #if ACAMERA_ISP_PROFILING
46 #include "acamera_profiler.h"
47 #endif
48
49 #if ACAMERA_ISP_PROFILING
50 #ifndef CHECK_STACK_SIZE_DWORDS
51 #define CHECK_STACK_SIZE_DWORDS 1024
52 #endif
53 #define CHECK_STACK_SIZE_START 512
54 #endif
55
56 #include "acamera_logger.h"
57 #include "fsm_param.h"
58
59 static acamera_firmware_t g_firmware;
60
acamera_set_api_context(uint32_t ctx_num)61 int32_t acamera_set_api_context( uint32_t ctx_num )
62 {
63 int32_t result = 0;
64 if ( ctx_num < g_firmware.context_number ) {
65 g_firmware.api_context = ctx_num;
66 result = 0;
67 } else {
68 result = -1;
69 }
70 return result;
71 }
72
acamera_get_api_context(void)73 int32_t acamera_get_api_context( void )
74 {
75 int32_t result = g_firmware.api_context;
76 return result;
77 }
78
acamera_get_context_number(void)79 int32_t acamera_get_context_number( void )
80 {
81 int32_t result = g_firmware.context_number;
82 return result;
83 }
84
85
acamera_get_api_ctx_ptr(void)86 void *acamera_get_api_ctx_ptr( void )
87 {
88 return &( g_firmware.fw_ctx[acamera_get_api_context()] );
89 }
90
acamera_get_ctx_ptr(uint32_t ctx_id)91 void *acamera_get_ctx_ptr( uint32_t ctx_id )
92 {
93 if ( ctx_id >= FIRMWARE_CONTEXT_NUMBER ) {
94 LOG( LOG_CRIT, "Error: Invalid ctx_id: %d", ctx_id );
95 return NULL;
96 }
97
98 return &( g_firmware.fw_ctx[ctx_id] );
99 }
100
acamera_get_isp_sw_setting_base(void)101 uintptr_t acamera_get_isp_sw_setting_base( void )
102 {
103 acamera_context_t *p_ctx = (acamera_context_t *)(&g_firmware.fw_ctx[acamera_get_api_context()]);
104 if (p_ctx->settings.isp_base)
105 return p_ctx->settings.isp_base;
106 else
107 return 0;
108 }
109
acamera_notify_evt_data_avail(void)110 void acamera_notify_evt_data_avail( void )
111 {
112 system_semaphore_raise( g_firmware.sem_evt_avail );
113 }
114
115
validate_settings(acamera_settings * settings,uint32_t ctx_num)116 static int32_t validate_settings( acamera_settings *settings, uint32_t ctx_num )
117 {
118
119 int32_t result = 0;
120 int32_t idx = 0;
121
122 if ( settings != NULL ) {
123 // validate parameters for all input contexts
124 for ( idx = 0; idx < ctx_num; idx++ ) {
125 acamera_settings *ctx_set = &settings[idx];
126 if ( ctx_set->sensor_init == NULL ||
127 ctx_set->sensor_deinit == NULL ||
128 ctx_set->get_calibrations == NULL ) {
129 result = -1;
130 LOG( LOG_CRIT, "One of the mandatory input parameters in the init settings is null for the context %d", idx );
131 }
132 #if ISP_HAS_DS1 && defined( ISP_HAS_DMA_WRITER_FSM )
133 if ( ctx_set->ds1_frames && ctx_set->ds1_frames_number ) { //check if DS frames are initialized
134 if ( acamera_isp_isp_global_parameter_status_ds1_pipe_read( ctx_set->isp_base ) ) { //check if DS is chickened out
135 result = -1;
136 LOG( LOG_CRIT, "DS Frames are expected while DS block is not present in hardware for the context %d", idx );
137 }
138 }
139 #endif
140 }
141 } else {
142 result = -1;
143 }
144 return result;
145 }
146
147
148 #define ACAMERA_CONTEXT_SIZE ACAMERA_ISP1_BASE_ADDR + ACAMERA_ISP1_SIZE
149
dma_channel_addresses_setup(void * isp_chan,void * metering_chan,void * sw_context_map,uint32_t idx,uint32_t hw_isp_addr)150 static int32_t dma_channel_addresses_setup( void *isp_chan, void *metering_chan, void *sw_context_map, uint32_t idx, uint32_t hw_isp_addr )
151 {
152 int32_t result = 0;
153 //PING ISP
154 {
155 dma_addr_pair_t isp_dma_addr_pair[2] = {
156 {hw_isp_addr + ACAMERA_DECOMPANDER0_MEM_BASE_ADDR, ACAMERA_ISP1_BASE_ADDR - ACAMERA_DECOMPANDER0_MEM_BASE_ADDR},
157 {hw_isp_addr + ACAMERA_ISP1_BASE_ADDR, ACAMERA_ISP1_SIZE}};
158 if ( system_dma_sg_device_setup( isp_chan, ISP_CONFIG_PING, isp_dma_addr_pair, 2, idx ) ) {
159 LOG( LOG_CRIT, "ISP device channel address setup for PING ctx:%d failed", idx );
160 result = -1;
161 }
162 fwmem_addr_pair_t fwmem_add_pair[2] = {
163 {(void *)( (uintptr_t)sw_context_map + ACAMERA_DECOMPANDER0_MEM_BASE_ADDR ), ACAMERA_ISP1_BASE_ADDR - ACAMERA_DECOMPANDER0_MEM_BASE_ADDR},
164 {(void *)( (uintptr_t)sw_context_map + ACAMERA_ISP1_BASE_ADDR ), ACAMERA_ISP1_SIZE}};
165 if ( system_dma_sg_fwmem_setup( isp_chan, ISP_CONFIG_PING, fwmem_add_pair, 2, idx ) ) {
166 LOG( LOG_CRIT, "ISP memory channel address setup for PING ctx:%d failed", idx );
167 result = -1;
168 }
169 }
170 //PONG ISP
171 {
172 dma_addr_pair_t isp_dma_addr_pair[2] = {
173 {hw_isp_addr + ACAMERA_DECOMPANDER0_MEM_BASE_ADDR + ISP_CONFIG_PING_SIZE, ACAMERA_ISP1_BASE_ADDR - ACAMERA_DECOMPANDER0_MEM_BASE_ADDR},
174 {hw_isp_addr + ACAMERA_ISP1_BASE_ADDR + ISP_CONFIG_PING_SIZE, ACAMERA_ISP1_SIZE}};
175 if ( system_dma_sg_device_setup( isp_chan, ISP_CONFIG_PONG, isp_dma_addr_pair, 2, idx ) ) {
176 LOG( LOG_CRIT, "ISP device channel address setup for PONG ctx:%d failed", idx );
177 result = -1;
178 }
179
180 fwmem_addr_pair_t fwmem_add_pair[2] = {
181 {(void *)( (uintptr_t)sw_context_map + ACAMERA_DECOMPANDER0_MEM_BASE_ADDR ), ACAMERA_ISP1_BASE_ADDR - ACAMERA_DECOMPANDER0_MEM_BASE_ADDR},
182 {(void *)( (uintptr_t)sw_context_map + ACAMERA_ISP1_BASE_ADDR ), ACAMERA_ISP1_SIZE}};
183 if ( system_dma_sg_fwmem_setup( isp_chan, ISP_CONFIG_PONG, fwmem_add_pair, 2, idx ) ) {
184 LOG( LOG_CRIT, "ISP memory channel address setup for PONG ctx:%d failed", idx );
185 result = -1;
186 }
187 }
188 //PING METERING
189 {
190 dma_addr_pair_t isp_dma_addr_pair[2] = {
191 {hw_isp_addr + ACAMERA_AEXP_HIST_STATS_MEM_BASE_ADDR, ACAMERA_AEXP_HIST_STATS_MEM_SIZE + ACAMERA_IHIST_STATS_MEM_SIZE},
192 {hw_isp_addr + ACAMERA_METERING_STATS_MEM_BASE_ADDR, ACAMERA_METERING_STATS_MEM_SIZE}};
193 if ( system_dma_sg_device_setup( metering_chan, ISP_CONFIG_PING, isp_dma_addr_pair, 2, idx ) ) {
194 LOG( LOG_CRIT, "Metering device channel address setup for PING ctx:%d failed", idx );
195 result = -1;
196 }
197
198 fwmem_addr_pair_t fwmem_add_pair[2] = {
199 {(void *)( (uintptr_t)sw_context_map + ACAMERA_AEXP_HIST_STATS_MEM_BASE_ADDR ), ACAMERA_AEXP_HIST_STATS_MEM_SIZE + ACAMERA_IHIST_STATS_MEM_SIZE},
200 {(void *)( (uintptr_t)sw_context_map + ACAMERA_METERING_STATS_MEM_BASE_ADDR ), ACAMERA_METERING_STATS_MEM_SIZE}};
201 if ( system_dma_sg_fwmem_setup( metering_chan, ISP_CONFIG_PING, fwmem_add_pair, 2, idx ) ) {
202 LOG( LOG_CRIT, "Metering memory channel address setup for PING ctx:%d failed", idx );
203 result = -1;
204 }
205 }
206 //PONG METERING
207 {
208 dma_addr_pair_t isp_dma_addr_pair[2] = {
209 {hw_isp_addr + ACAMERA_AEXP_HIST_STATS_MEM_BASE_ADDR, ACAMERA_AEXP_HIST_STATS_MEM_SIZE + ACAMERA_IHIST_STATS_MEM_SIZE},
210 {hw_isp_addr + ACAMERA_METERING_STATS_MEM_BASE_ADDR + ISP_CONFIG_PING_SIZE, ACAMERA_METERING_STATS_MEM_SIZE}};
211 if ( system_dma_sg_device_setup( metering_chan, ISP_CONFIG_PONG, isp_dma_addr_pair, 2, idx ) ) {
212 LOG( LOG_CRIT, "Metering device channel address setup for PONG ctx:%d failed", idx );
213 result = -1;
214 }
215
216 fwmem_addr_pair_t fwmem_add_pair[2] = {
217 {(void *)( (uintptr_t)sw_context_map + ACAMERA_AEXP_HIST_STATS_MEM_BASE_ADDR ), ACAMERA_AEXP_HIST_STATS_MEM_SIZE + ACAMERA_IHIST_STATS_MEM_SIZE},
218 {(void *)( (uintptr_t)sw_context_map + ACAMERA_METERING_STATS_MEM_BASE_ADDR ), ACAMERA_METERING_STATS_MEM_SIZE}};
219 if ( system_dma_sg_fwmem_setup( metering_chan, ISP_CONFIG_PONG, fwmem_add_pair, 2, idx ) ) {
220 LOG( LOG_CRIT, "Metering memory channel address setup for PONG ctx:%d failed", idx );
221 result = -1;
222 }
223 }
224 return result;
225 }
226
227 #if USER_MODULE
228
acamera_init(acamera_settings * settings,uint32_t ctx_num)229 int32_t acamera_init( acamera_settings *settings, uint32_t ctx_num )
230 {
231 int32_t result = 0;
232 uint32_t idx = 0;
233
234 result = validate_settings( settings, ctx_num );
235
236 if ( result == 0 ) {
237
238 #if FW_HAS_CONTROL_CHANNEL
239 ctrl_channel_init();
240 #endif
241
242 g_firmware.api_context = 0;
243
244 system_semaphore_init( &g_firmware.sem_evt_avail );
245
246 if ( ctx_num <= FIRMWARE_CONTEXT_NUMBER ) {
247
248 g_firmware.context_number = ctx_num;
249
250 for ( idx = 0; idx < ctx_num; idx++ ) {
251 acamera_context_t *p_ctx = (acamera_context_ptr_t)&g_firmware.fw_ctx[idx];
252 LOG( LOG_INFO, "Initialize context %d, context size is %d bytes", idx, sizeof( struct _acamera_context_t ) );
253 system_memset( (void *)p_ctx, 0x0, sizeof( struct _acamera_context_t ) );
254 // each context has unique id
255 p_ctx->context_id = idx;
256
257 // init context
258 result = acamera_init_context( p_ctx, &settings[idx], &g_firmware );
259 if ( result != 0 ) {
260 LOG( LOG_CRIT, "Failed to initialized the context %d", (int)idx );
261 break;
262 }
263 }
264
265 if ( result == 0 ) {
266 g_firmware.initialized = 1;
267 } else {
268 g_firmware.initialized = 0;
269 }
270
271 } else {
272 result = -1;
273 LOG( LOG_CRIT, "Failed to initialized the firmware context. Not enough memory. " );
274 }
275
276 } else {
277 LOG( LOG_CRIT, "Input initializations settings are not correct" );
278 result = -1;
279 }
280
281 return result;
282 }
283
acamera_update_cur_settings_to_isp(int port)284 void acamera_update_cur_settings_to_isp( int port )
285 {
286 }
287
acamera_reset_ping_pong_port(void)288 void acamera_reset_ping_pong_port(void)
289 {
290 }
291
292 #else /* #if USER_MODULE */
293
acamera_init(acamera_settings * settings,uint32_t ctx_num)294 int32_t acamera_init( acamera_settings *settings, uint32_t ctx_num )
295 {
296 int32_t result = 0;
297 uint32_t p_id = 0;
298 uint32_t idx;
299
300 result = validate_settings( settings, ctx_num );
301
302 if ( result == 0 ) {
303 p_id = acamera_isp_id_product_read(0);
304 if (p_id != ACAMERA_ISP_ID_PRODUCT_DEFAULT) {
305 LOG(LOG_ERR, "Failed to read profuct id\n");
306 return 0;
307 }
308 LOG(LOG_INFO, "Success get product id: 0x%08x\n", p_id);
309 // disable irq and clear interrupts
310 acamera_isp_isp_global_interrupt_mask_vector_write( 0, ISP_IRQ_DISABLE_ALL_IRQ );
311
312
313 #if ACAMERA_ISP_PROFILING && ACAMERA_ISP_PROFILING_INIT
314 acamera_profiler_init();
315 acamera_profiler_start( 0 );
316 #endif
317
318 #if FW_HAS_CONTROL_CHANNEL
319 ctrl_channel_init();
320 #endif
321
322
323 if ( result == 0 ) {
324
325 g_firmware.api_context = 0;
326
327 system_semaphore_init( &g_firmware.sem_evt_avail );
328
329 if ( ctx_num <= FIRMWARE_CONTEXT_NUMBER ) {
330
331 g_firmware.context_number = ctx_num;
332
333 result = system_dma_init( &g_firmware.dma_chan_isp_config );
334 result |= system_dma_init( &g_firmware.dma_chan_isp_metering );
335 if ( result == 0 ) {
336 // allocate memory for dma transfers
337 for ( idx = 0; idx < ctx_num; idx++ ) {
338 acamera_context_t *p_ctx = (acamera_context_ptr_t)&g_firmware.fw_ctx[idx];
339 system_memset( (void *)p_ctx, 0x0, sizeof( struct _acamera_context_t ) );
340 // each context has unique id
341 p_ctx->context_id = idx;
342
343 // dump hw default configuration to the current context
344
345 p_ctx->sw_reg_map.isp_sw_config_map = system_sw_alloc( ACAMERA_CONTEXT_SIZE );
346
347 if ( p_ctx->sw_reg_map.isp_sw_config_map ) {
348 result = dma_channel_addresses_setup( g_firmware.dma_chan_isp_config, g_firmware.dma_chan_isp_metering, (void *)p_ctx->sw_reg_map.isp_sw_config_map, idx, settings->hw_isp_addr );
349 } else {
350 LOG( LOG_CRIT, "Software Context %d failed to allocate", idx );
351 result = -1;
352 }
353
354 if ( result )
355 break;
356
357 system_dma_copy_sg( g_firmware.dma_chan_isp_config, ISP_CONFIG_PING, SYS_DMA_FROM_DEVICE, 0, idx );
358 // init context
359 result = acamera_init_context( p_ctx, &settings[idx], &g_firmware );
360 if ( result == 0 ) {
361 // initialize ping
362 // system_dma_copy current software context to the ping and pong
363 if(acamera_isp_input_port_mode_status_read( 0 ) != ACAMERA_ISP_INPUT_PORT_MODE_REQUEST_SAFE_START)
364 {
365 system_dma_copy_sg( g_firmware.dma_chan_isp_config, ISP_CONFIG_PING, SYS_DMA_TO_DEVICE, 0, idx );
366 system_dma_copy_sg( g_firmware.dma_chan_isp_config, ISP_CONFIG_PONG, SYS_DMA_TO_DEVICE, 0, idx );
367 }
368 if ( result == 0 ) {
369 #if ISP_SENSOR_DRIVER_MODEL != 1
370 // avoid interrupt status check against the model
371 while ( acamera_isp_isp_global_interrupt_status_vector_read( 0 ) != 0 ) {
372 // driver is initialized. we can start processing interrupts
373 // wait until irq mask is cleared and start processing
374 acamera_isp_isp_global_interrupt_clear_write( 0, 0 );
375 acamera_isp_isp_global_interrupt_clear_write( 0, 1 );
376 }
377 #endif // #if ISP_SENSOR_DRIVER_MODEL != 1
378 if(acamera_isp_input_port_mode_status_read( 0 ) != ACAMERA_ISP_INPUT_PORT_MODE_REQUEST_SAFE_START)
379 acamera_isp_isp_global_interrupt_mask_vector_write( 0, ISP_IRQ_MASK_VECTOR );
380 g_firmware.initialized = 1;
381 } else {
382 LOG( LOG_CRIT, "One or more contexts were not initialized properly. " );
383 g_firmware.initialized = 0;
384 break;
385 }
386 } else {
387 LOG( LOG_CRIT, "Failed to initialized the context %d", (int)idx );
388 break;
389 }
390 }
391 } else {
392 result = -1;
393 LOG( LOG_CRIT, "Failed to initialize the system DMA engines" );
394 }
395 } else {
396 result = -1;
397 LOG( LOG_CRIT, "Failed to initialized the firmware context. Not enough memory. " );
398 }
399 } else {
400 LOG( LOG_CRIT, "Failed to initialized the BSP. Please implement the BSP layer and recompile the firmware" );
401 result = -1;
402 }
403
404 #if ACAMERA_ISP_PROFILING && ACAMERA_ISP_PROFILING_INIT
405 acamera_profiler_stop( 0, 1 );
406 acamera_profiler_report();
407 #endif
408
409 } else {
410 LOG( LOG_CRIT, "Input initializations settings are not correct" );
411 result = -1;
412 }
413 if(acamera_isp_input_port_mode_status_read( 0 ) != ACAMERA_ISP_INPUT_PORT_MODE_REQUEST_SAFE_START)
414 acamera_isp_isp_global_mcu_override_config_select_write( 0, 1 ); //put ping pong in slave mode
415 g_firmware.dma_flag_isp_config_completed = 1;
416 g_firmware.dma_flag_isp_metering_completed = 1;
417 return result;
418 }
419
acamera_update_cur_settings_to_isp(int port)420 void acamera_update_cur_settings_to_isp( int port )
421 {
422 if (port == 0xff) {
423 system_dma_copy_sg( g_firmware.dma_chan_isp_config, ISP_CONFIG_PING, SYS_DMA_TO_DEVICE, NULL, acamera_get_api_context() );
424 system_dma_copy_sg( g_firmware.dma_chan_isp_config, ISP_CONFIG_PONG, SYS_DMA_TO_DEVICE, NULL, acamera_get_api_context() );
425 } else if (port == ISP_CONFIG_PING) {
426 system_dma_copy_sg( g_firmware.dma_chan_isp_config, ISP_CONFIG_PING, SYS_DMA_TO_DEVICE, NULL, acamera_get_api_context() );
427 } else if (port == ISP_CONFIG_PONG) {
428 system_dma_copy_sg( g_firmware.dma_chan_isp_config, ISP_CONFIG_PONG, SYS_DMA_TO_DEVICE, NULL, acamera_get_api_context() );
429 }
430 }
431
acamera_reset_ping_pong_port(void)432 void acamera_reset_ping_pong_port(void)
433 {
434 acamera_isp_isp_global_mcu_ping_pong_config_select_write( 0, ISP_CONFIG_PING );
435 }
436
437 #endif /* #if USER_MODULE */
438
acamera_deinit(void)439 static void acamera_deinit( void )
440 {
441 int idx;
442 acamera_context_t *p_ctx;
443
444 #if FW_HAS_CONTROL_CHANNEL
445 ctrl_channel_deinit();
446 #endif
447
448 system_dma_destroy( g_firmware.dma_chan_isp_config );
449 system_dma_destroy( g_firmware.dma_chan_isp_metering );
450 for ( idx = 0; idx < g_firmware.context_number; idx++ ) {
451
452 p_ctx = (acamera_context_ptr_t)&g_firmware.fw_ctx[idx];
453
454 acamera_deinit_context( p_ctx );
455
456 if ( p_ctx->sw_reg_map.isp_sw_config_map != NULL ) {
457 system_sw_free( (void *)p_ctx->sw_reg_map.isp_sw_config_map );
458 p_ctx->sw_reg_map.isp_sw_config_map = NULL;
459 }
460 }
461 }
462
acamera_terminate()463 int32_t acamera_terminate()
464 {
465 acamera_logger_empty(); //empty the logger buffer and print remaining logs
466 acamera_deinit();
467 system_semaphore_destroy( g_firmware.sem_evt_avail );
468
469 return 0;
470 }
471
472
473 #if USER_MODULE
acamera_interrupt_handler()474 int32_t acamera_interrupt_handler()
475 {
476 return 0;
477 }
478 #else
479 // single context handler
480
start_processing_frame(void)481 static void start_processing_frame( void )
482 {
483 acamera_context_ptr_t p_ctx = (acamera_context_ptr_t)&g_firmware.fw_ctx[acamera_get_api_context()];
484
485 // new_frame event to start reading metering memory and run 3A
486 acamera_fw_raise_event( p_ctx, event_id_new_frame );
487 }
488
start_dropping_frame(void)489 static void start_dropping_frame( void )
490 {
491 acamera_context_ptr_t p_ctx = (acamera_context_ptr_t)&g_firmware.fw_ctx[acamera_get_api_context()];
492
493 acamera_fw_raise_event( p_ctx, event_id_drop_frame );
494 }
495
dma_complete_context_func(void * arg)496 static void dma_complete_context_func( void *arg )
497 {
498 g_firmware.dma_flag_isp_config_completed = 1;
499
500
501 if ( g_firmware.dma_flag_isp_config_completed && g_firmware.dma_flag_isp_metering_completed ) {
502 start_processing_frame();
503 }
504
505 system_dma_unmap_sg( arg );
506 }
507
dma_complete_metering_func(void * arg)508 static void dma_complete_metering_func( void *arg )
509 {
510 g_firmware.dma_flag_isp_metering_completed = 1;
511
512 if ( g_firmware.dma_flag_isp_config_completed && g_firmware.dma_flag_isp_metering_completed ) {
513 start_processing_frame();
514 }
515
516 system_dma_unmap_sg( arg );
517 // after we finish transfer context and metering we can start processing the current data
518 }
519
dma_drop_context_func(void * arg)520 static void dma_drop_context_func( void *arg )
521 {
522 g_firmware.dma_flag_isp_config_completed = 1;
523
524 if ( g_firmware.dma_flag_isp_config_completed && g_firmware.dma_flag_isp_metering_completed ) {
525 start_dropping_frame();
526 }
527
528 system_dma_unmap_sg( arg );
529 }
530
531 // single context handler
acamera_interrupt_handler()532 int32_t acamera_interrupt_handler()
533 {
534 int32_t result = 0;
535 int32_t irq_bit = ISP_INTERRUPT_EVENT_NONES_COUNT - 1;
536 int not_empty = 0;
537
538 acamera_context_ptr_t p_ctx = (acamera_context_ptr_t)&g_firmware.fw_ctx[acamera_get_api_context()];
539
540 // read the irq vector from isp
541 uint32_t irq_mask = acamera_isp_isp_global_interrupt_status_vector_read( 0 );
542
543 LOG( LOG_DEBUG, "IRQ MASK is %d", irq_mask );
544
545 // clear irq vector
546 acamera_isp_isp_global_interrupt_clear_write( 0, 0 );
547 acamera_isp_isp_global_interrupt_clear_write( 0, 1 );
548
549 if ( irq_mask > 0 ) {
550
551 #if defined( ISP_INTERRUPT_EVENT_BROKEN_FRAME ) && defined( ISP_INTERRUPT_EVENT_MULTICTX_ERROR ) && defined( ISP_INTERRUPT_EVENT_DMA_ERROR ) && defined( ISP_INTERRUPT_EVENT_WATCHDOG_EXP ) && defined( ISP_INTERRUPT_EVENT_FRAME_COLLISION )
552 //check for errors in the interrupt
553 if ( ( irq_mask & 1 << ISP_INTERRUPT_EVENT_BROKEN_FRAME ) ||
554 ( irq_mask & 1 << ISP_INTERRUPT_EVENT_MULTICTX_ERROR ) ||
555 ( irq_mask & 1 << ISP_INTERRUPT_EVENT_DMA_ERROR ) ||
556 ( irq_mask & 1 << ISP_INTERRUPT_EVENT_WATCHDOG_EXP ) ||
557 ( irq_mask & 1 << ISP_INTERRUPT_EVENT_FRAME_COLLISION ) ) {
558
559 LOG( LOG_ERR, "Found error resetting ISP. MASK is 0x%x", irq_mask );
560
561 system_irq_status(irq_mask);
562
563 acamera_fw_error_routine( p_ctx, irq_mask );
564 return -1; //skip other interrupts in case of error
565 }
566 #endif
567
568 while ( irq_mask > 0 && irq_bit >= 0 ) {
569 int32_t irq_is_1 = ( irq_mask & ( 1 << irq_bit ) );
570 irq_mask &= ~( 1 << irq_bit );
571 if ( irq_is_1 ) {
572 // process interrupts
573 if ( irq_bit == ISP_INTERRUPT_EVENT_ISP_START_FRAME_START ) {
574 if ( g_firmware.dma_flag_isp_metering_completed == 0 || g_firmware.dma_flag_isp_config_completed == 0 ) {
575 LOG( LOG_CRIT, "DMA is not finished, cfg: %d, meter: %d, skip this frame.", g_firmware.dma_flag_isp_config_completed, g_firmware.dma_flag_isp_metering_completed );
576 return -2;
577 }
578 not_empty = acamera_event_queue_not_empty( &p_ctx->fsm_mgr.event_queue );
579 // we must finish all previous processing before scheduling new dma
580 {
581 // switch to ping/pong contexts for the next frame
582 // these flags are used for sync of callbacks
583 g_firmware.dma_flag_isp_config_completed = 0;
584 g_firmware.dma_flag_isp_metering_completed = 0;
585
586 //if (!acamera_isp_isp_global_mcu_ping_pong_config_select_read(0)) { // cmodel compatibility
587 if ( acamera_isp_isp_global_ping_pong_config_select_read( 0 ) == ISP_CONFIG_PONG ) {
588 LOG( LOG_DEBUG, "Current config is pong" );
589 // |^^^^^^^^^|
590 // next ---> | PING |
591 // |_________|
592
593 // use ping for the next frame
594 acamera_isp_isp_global_mcu_ping_pong_config_select_write( 0, ISP_CONFIG_PING );
595 //
596 // |^^^^^^^^^|
597 // conf ---> | PONG |
598 // |_________|
599 if (!not_empty) {
600 // dma all stat memory only to the software context
601 system_dma_copy_sg( g_firmware.dma_chan_isp_metering, ISP_CONFIG_PING, SYS_DMA_FROM_DEVICE, dma_complete_metering_func, acamera_get_api_context());
602 system_dma_copy_sg( g_firmware.dma_chan_isp_config, ISP_CONFIG_PING, SYS_DMA_TO_DEVICE, dma_complete_context_func, acamera_get_api_context());
603 } else {
604 g_firmware.dma_flag_isp_metering_completed = 1;
605 system_dma_copy_sg( g_firmware.dma_chan_isp_config, ISP_CONFIG_PING, SYS_DMA_TO_DEVICE, dma_drop_context_func, acamera_get_api_context());
606 }
607 } else {
608 LOG( LOG_DEBUG, "Current config is ping" );
609 // |^^^^^^^^^|
610 // next ---> | PONG |
611 // |_________|
612
613 // use pong for the next frame
614 acamera_isp_isp_global_mcu_ping_pong_config_select_write( 0, ISP_CONFIG_PONG );
615
616 // |^^^^^^^^^|
617 // conf ---> | PING |
618 // |_________|
619
620 if (!not_empty) {
621 // dma all stat memory only to the software context
622 system_dma_copy_sg( g_firmware.dma_chan_isp_metering, ISP_CONFIG_PONG, SYS_DMA_FROM_DEVICE, dma_complete_metering_func, acamera_get_api_context() );
623 system_dma_copy_sg( g_firmware.dma_chan_isp_config, ISP_CONFIG_PONG, SYS_DMA_TO_DEVICE, dma_complete_context_func, acamera_get_api_context());
624 } else {
625 g_firmware.dma_flag_isp_metering_completed = 1;
626 system_dma_copy_sg( g_firmware.dma_chan_isp_config, ISP_CONFIG_PONG, SYS_DMA_TO_DEVICE, dma_drop_context_func, acamera_get_api_context() );
627 }
628 }
629 }
630 } else {
631 // unhandled irq
632 LOG( LOG_DEBUG, "Unhandled interrupt bit %d", irq_bit );
633 }
634 }
635 irq_bit--;
636 }
637 }
638
639 return result;
640 }
641 #endif // USER_MODULE
642
643
acamera_process(void)644 int32_t acamera_process( void )
645 {
646 int32_t result = 0;
647 int32_t idx = 0;
648
649 if ( g_firmware.initialized == 1 ) {
650 for ( idx = 0; idx < g_firmware.context_number; idx++ ) {
651 acamera_context_ptr_t p_ctx = ( acamera_context_ptr_t ) & ( g_firmware.fw_ctx[idx] );
652 acamera_fw_process( p_ctx );
653 }
654 } else {
655 result = -1;
656 LOG( LOG_CRIT, "Firmware was not initialized properly. Please initialize the firmware before call acamera_process" );
657 }
658
659 #if FW_HAS_CONTROL_CHANNEL
660 ctrl_channel_process();
661 #endif
662
663 system_semaphore_wait( g_firmware.sem_evt_avail, FW_EVT_QUEUE_TIMEOUT_MS );
664
665 return result;
666 }
667