• 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_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