• 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_logger.h"
21 #include "system_interrupts.h"
22 #include "system_stdlib.h"
23 #include "dma_writer_api.h"
24 #include "dma_writer.h"
25 #include "acamera_firmware_config.h"
26 #include "acamera.h"
27 
28 #ifdef LOG_MODULE
29 #undef LOG_MODULE
30 #define LOG_MODULE LOG_MODULE_DMA_WRITER
31 #endif
32 
33 #define TAG "DMA_WRITER"
34 
35 //#define DMA_PRINTF(a) printf a
36 #define DMA_PRINTF( a ) (void)0
37 
38 static dma_handle s_handle[FIRMWARE_CONTEXT_NUMBER];
39 static int32_t ctx_pos = 0;
dma_writer_create(void ** handle)40 dma_error dma_writer_create( void **handle )
41 {
42     dma_error result = edma_ok;
43     if ( handle != NULL ) {
44 
45         if ( ctx_pos < acamera_get_context_number() ) {
46             *handle = &s_handle[ctx_pos];
47             system_memset( (void *)*handle, 0, sizeof( dma_handle ) );
48             ctx_pos++;
49         } else {
50             *handle = NULL;
51             result = edma_fail;
52             LOG( LOG_CRIT, "dma context overshoot\n" );
53         }
54     } else {
55         result = edma_fail;
56     }
57     return result;
58 }
59 
dma_writer_exit(void * handle)60 void dma_writer_exit( void *handle )
61 {
62     ctx_pos = 0;
63 }
64 
dma_writer_update_state(dma_pipe * pipe)65 dma_error dma_writer_update_state( dma_pipe *pipe )
66 {
67     dma_error result = edma_ok;
68     if ( pipe != NULL ) {
69         LOG( LOG_DEBUG, "state update %dx%d\n", (int)pipe->settings.width, (int)pipe->settings.height );
70         if ( pipe->settings.width == 0 || pipe->settings.height == 0 ) {
71             result = edma_invalid_settings;
72             pipe->settings.enabled = 0;
73             pipe->api.p_acamera_isp_dma_writer_frame_write_on_write( pipe->settings.isp_base, pipe->settings.enabled ); //disable pipe on invalid settings
74             pipe->api.p_acamera_isp_dma_writer_frame_write_on_write_uv( pipe->settings.isp_base, pipe->settings.enabled );
75             return result;
76         }
77 
78 
79         //set default settings here
80         pipe->api.p_acamera_isp_dma_writer_max_bank_write( pipe->settings.isp_base, 0 );
81         pipe->api.p_acamera_isp_dma_writer_active_width_write( pipe->settings.isp_base, pipe->settings.width );
82         pipe->api.p_acamera_isp_dma_writer_active_height_write( pipe->settings.isp_base, pipe->settings.height );
83 
84         pipe->api.p_acamera_isp_dma_writer_max_bank_write_uv( pipe->settings.isp_base, 0 );
85         pipe->api.p_acamera_isp_dma_writer_active_width_write_uv( pipe->settings.isp_base, pipe->settings.width );
86         pipe->api.p_acamera_isp_dma_writer_active_height_write_uv( pipe->settings.isp_base, pipe->settings.height );
87     } else {
88         result = edma_fail;
89     }
90     return result;
91 }
92 
93 
dma_writer_get_settings(void * handle,dma_type type,dma_pipe_settings * settings)94 dma_error dma_writer_get_settings( void *handle, dma_type type, dma_pipe_settings *settings )
95 {
96     dma_error result = edma_ok;
97     if ( handle != NULL ) {
98         dma_handle *p_dma = (dma_handle *)handle;
99         system_memcpy( (void *)settings, &p_dma->pipe[type].settings, sizeof( dma_pipe_settings ) );
100     } else {
101         result = edma_fail;
102     }
103     return result;
104 }
105 
106 
dma_writer_set_settings(void * handle,dma_type type,dma_pipe_settings * settings)107 dma_error dma_writer_set_settings( void *handle, dma_type type, dma_pipe_settings *settings )
108 {
109     dma_error result = edma_ok;
110     if ( handle != NULL ) {
111         dma_handle *p_dma = (dma_handle *)handle;
112         system_memcpy( (void *)&p_dma->pipe[type].settings, settings, sizeof( dma_pipe_settings ) );
113         result = dma_writer_update_state( &p_dma->pipe[type] );
114 
115     } else {
116         LOG( LOG_ERR, "set settings handle null\n" );
117         result = edma_fail;
118     }
119     return result;
120 }
121 
dma_writer_get_ptr_settings(void * handle,dma_type type,dma_pipe_settings ** settings)122 dma_error dma_writer_get_ptr_settings( void *handle, dma_type type, dma_pipe_settings **settings )
123 {
124     dma_error result = edma_ok;
125     if ( handle != NULL ) {
126         dma_handle *p_dma = (dma_handle *)handle;
127         *settings = &p_dma->pipe[type].settings;
128     } else {
129         result = edma_fail;
130     }
131     return result;
132 }
133 
dma_writer_set_initialized(void * handle,dma_type type,uint8_t initialized)134 void dma_writer_set_initialized( void *handle, dma_type type, uint8_t initialized )
135 {
136     if ( handle != NULL ) {
137         dma_handle *p_dma = (dma_handle *)handle;
138         p_dma->pipe[type].state.initialized = initialized;
139     }
140 }
141 
dma_writer_init(void * handle,dma_type type,dma_pipe_settings * settings,dma_api * api)142 dma_error dma_writer_init( void *handle, dma_type type, dma_pipe_settings *settings, dma_api *api )
143 {
144     dma_error result = edma_ok;
145     if ( handle != NULL ) {
146         dma_handle *p_dma = (dma_handle *)handle;
147         p_dma->pipe[type].type = type;
148         system_memcpy( (void *)&p_dma->pipe[type].api, api, sizeof( dma_api ) );
149         result = dma_writer_set_settings( handle, type, settings );
150         result |= dma_writer_reset( handle, type );
151 
152         if ( result == edma_ok ) {
153             LOG( LOG_INFO, "%s: initialized a dma writer output. %dx%d ", TAG, (int)settings->width, (int)settings->height );
154         } else {
155             LOG( LOG_ERR, "%s: Failed to initialize a dma writer type:%d output. %dx%d ", TAG, (int)type, (int)settings->width, (int)settings->height );
156         }
157     } else {
158         result = edma_fail;
159     }
160     return result;
161 }
162 
dma_writer_init_frame_queue(dma_pipe * pipe)163 void dma_writer_init_frame_queue( dma_pipe *pipe )
164 { //init all buffer to inuse so we can remove it from the queue
165     int i;
166     for ( i = 0; i < MAX_DMA_QUEUE_FRAMES; i++ ) {
167         pipe->settings.frame_buf_queue[i].primary.status = dma_buf_purge;
168         pipe->settings.frame_buf_queue[i].secondary.status = dma_buf_purge;
169     }
170     DMA_PRINTF( ( "all frames to dma_buf_purge\n" ) );
171     return;
172 }
173 
dma_writer_reset(void * handle,dma_type type)174 dma_error dma_writer_reset( void *handle, dma_type type )
175 {
176     dma_error result = edma_ok;
177     if ( handle != NULL ) {
178         dma_handle *p_dma = (dma_handle *)handle;
179         dma_pipe *pipe = &p_dma->pipe[type];
180         pipe->state.buf_num_rdi = 0;
181         pipe->state.buf_num_wri = 0;
182         pipe->state.buf_num_size = 0;
183         pipe->settings.last_tframe = NULL;
184         pipe->settings.inqueue_tframe[0] = NULL;
185         pipe->settings.inqueue_tframe[1] = NULL;
186         pipe->settings.init_delay = 1;
187         dma_writer_init_frame_queue( pipe );
188         pipe->api.p_acamera_isp_dma_writer_frame_write_on_write( pipe->settings.isp_base, 0 );
189         pipe->api.p_acamera_isp_dma_writer_frame_write_on_write_uv( pipe->settings.isp_base, 0 );
190         pipe->settings.enabled = 0;
191         pipe->settings.c_fps = 0;
192         pipe->settings.t_fps = 0;
193         pipe->settings.inter_val = 0;
194         pipe->settings.back_tframe = NULL;
195     } else {
196         result = edma_fail;
197     }
198     return result;
199 }
200 
dma_writer_set_pipe_fps(void * handle,dma_type type,uint32_t c_fps,uint32_t t_fps)201 dma_error dma_writer_set_pipe_fps(void *handle, dma_type type,
202                                 uint32_t c_fps, uint32_t t_fps)
203 {
204     dma_handle *p_dma = NULL;
205     dma_pipe *pipe = NULL;
206     uint32_t inter_val = 0;
207 
208     if (handle == NULL || c_fps == 0 || t_fps == 0 || (t_fps > c_fps)) {
209         LOG(LOG_ERR, "Error input param\n");
210         return edma_wrong_parameters;
211     }
212 
213     p_dma = handle;
214     pipe = &p_dma->pipe[type];
215     pipe->settings.c_fps = c_fps;
216     pipe->settings.t_fps = t_fps;
217 
218     inter_val = c_fps / t_fps;
219     if (c_fps % t_fps != 0)
220         inter_val += 1;
221 
222     pipe->settings.inter_val = inter_val;
223 
224     LOG(LOG_INFO, "c_fps: %d, t_fps: %d, interval %d\n", c_fps, t_fps, inter_val);
225 
226     return edma_ok;
227 }
228 
229 
dma_writer_get_default_settings(void * handle,dma_type type,dma_pipe_settings * settings)230 dma_error dma_writer_get_default_settings( void *handle, dma_type type, dma_pipe_settings *settings )
231 {
232     dma_error result = edma_ok;
233     return result;
234 }
235 
dma_writer_write_frame_queue(void * handle,dma_type type,tframe_t * frame_buf_array,uint16_t frame_buf_len)236 uint16_t dma_writer_write_frame_queue( void *handle, dma_type type, tframe_t *frame_buf_array, uint16_t frame_buf_len )
237 {
238 
239     int i, set_i = 0;
240     dma_handle *p_dma = (dma_handle *)handle;
241     dma_pipe *pipe = &p_dma->pipe[type];
242 
243     if ( handle == NULL || frame_buf_array == NULL || pipe == NULL ) {
244         LOG( LOG_CRIT, "NULL detected handle:%p,frame_buf_array:%p,pipe:%p\n", handle, frame_buf_array, pipe );
245         return 0;
246     }
247 
248     if ( frame_buf_len == 0 )
249         return 0;
250 
251     int index = 0;
252     for ( i = 0; i < MAX_DMA_QUEUE_FRAMES; i++ ) {
253         index = ( i + pipe->state.buf_num_rdi ) % MAX_DMA_QUEUE_FRAMES;
254 
255         if ( pipe->settings.frame_buf_queue[index].primary.status == dma_buf_purge ) { //replace the buffer when it is in use
256             /* init tframe status first */
257             frame_buf_array[set_i].primary.status = dma_buf_purge;
258             frame_buf_array[set_i].secondary.status = dma_buf_purge;
259             pipe->settings.frame_buf_queue[index] = frame_buf_array[set_i];
260             pipe->settings.frame_buf_queue[index].primary.status = dma_buf_empty;
261             pipe->settings.frame_buf_queue[index].secondary.status = dma_buf_empty;
262             set_i++;
263         }
264         if ( set_i >= frame_buf_len ) {
265             set_i = i++;
266             break;
267         }
268     }
269 
270     if ( i > pipe->state.buf_num_size ) {
271         pipe->state.buf_num_size = i;
272         DMA_PRINTF( ( "dma buf_num_size changed %d\n", (int)pipe->state.buf_num_size ) );
273     }
274 
275     if ( pipe->settings.enabled == 0 ) {
276         DMA_PRINTF( ( "dma re-enabling\n" ) );
277         pipe->api.p_acamera_isp_dma_writer_bank0_base_write( pipe->settings.isp_base, pipe->settings.frame_buf_queue[set_i].primary.address );
278         pipe->api.p_acamera_isp_dma_writer_bank0_base_write_uv( pipe->settings.isp_base, pipe->settings.frame_buf_queue[set_i].secondary.address );
279         pipe->settings.inqueue_tframe[1] = &pipe->settings.frame_buf_queue[set_i];
280         pipe->settings.frame_buf_queue[set_i].primary.status = dma_buf_busy;
281         pipe->settings.enabled = 1;
282         if ( pipe->api.p_acamera_isp_dma_writer_format_read( pipe->settings.isp_base ) != DMA_FORMAT_DISABLE )
283             pipe->api.p_acamera_isp_dma_writer_frame_write_on_write( pipe->settings.isp_base, 1 );
284         else
285             pipe->api.p_acamera_isp_dma_writer_frame_write_on_write( pipe->settings.isp_base, 0 );
286 
287         pipe->api.p_acamera_isp_dma_writer_line_offset_write( pipe->settings.isp_base, pipe->settings.frame_buf_queue[set_i].primary.line_offset);
288 
289         //check if format is for UV
290         if ( pipe->api.p_acamera_isp_dma_writer_format_read_uv( pipe->settings.isp_base ) != DMA_FORMAT_DISABLE ) {
291             pipe->settings.frame_buf_queue[set_i].secondary.status = dma_buf_busy;
292             pipe->api.p_acamera_isp_dma_writer_frame_write_on_write_uv( pipe->settings.isp_base, 1 );
293 		    pipe->api.p_acamera_isp_dma_writer_line_offset_write_uv( pipe->settings.isp_base, pipe->settings.frame_buf_queue[set_i].secondary.line_offset);
294             LOG( LOG_DEBUG, "enabled uv %d", pipe->api.p_acamera_isp_dma_writer_format_read_uv( pipe->settings.isp_base ) );
295         } else {
296             //cannot enable
297             pipe->api.p_acamera_isp_dma_writer_frame_write_on_write_uv( pipe->settings.isp_base, 0 );
298             LOG( LOG_DEBUG, "cannot enable uv %d", pipe->api.p_acamera_isp_dma_writer_format_read_uv( pipe->settings.isp_base ) );
299         }
300     }
301     return i;
302 }
303 
dma_get_next_empty_frame(dma_pipe * pipe)304 tframe_t *dma_get_next_empty_frame( dma_pipe *pipe )
305 {
306     int i, index = 0, last_index;
307     for ( i = 0; i < MAX_DMA_QUEUE_FRAMES; i++ ) {
308         index = ( i + pipe->state.buf_num_wri ) % MAX_DMA_QUEUE_FRAMES;
309         last_index = pipe->state.buf_num_wri;
310         if ( pipe->settings.frame_buf_queue[index].primary.status == dma_buf_empty ) {
311             pipe->state.buf_num_wri = ( index + 1 ) % MAX_DMA_QUEUE_FRAMES;
312             //recover busy frames not returned by dma
313             if (( pipe->settings.frame_buf_queue[last_index].primary.status == dma_buf_busy )
314                 && (&pipe->settings.frame_buf_queue[last_index] != pipe->settings.last_tframe)
315                 && (&pipe->settings.frame_buf_queue[last_index] != pipe->settings.inqueue_tframe[0])
316                 && (&pipe->settings.frame_buf_queue[last_index] != pipe->settings.inqueue_tframe[1])) {
317                 pipe->settings.frame_buf_queue[last_index].primary.status = dma_buf_empty;
318                 pipe->settings.frame_buf_queue[last_index].secondary.status = dma_buf_empty;
319                 DMA_PRINTF( ( "recovered 0x%lx\n", pipe->settings.frame_buf_queue[last_index].primary.address ) );
320             }
321             return &( pipe->settings.frame_buf_queue[index] );
322         }
323     }
324 
325     return 0;
326 }
327 
328 
dma_get_next_ready_frame(dma_pipe * pipe)329 tframe_t *dma_get_next_ready_frame( dma_pipe *pipe )
330 {
331     int i, index;
332     for ( i = 0; i < MAX_DMA_QUEUE_FRAMES; i++ ) {
333         index = ( i + pipe->state.buf_num_rdi ) % MAX_DMA_QUEUE_FRAMES;
334         if ( pipe->settings.frame_buf_queue[index].primary.status == dma_buf_ready ) {
335             pipe->state.buf_num_rdi = ( index + 1 ) % MAX_DMA_QUEUE_FRAMES;
336             return &( pipe->settings.frame_buf_queue[index] );
337         }
338     }
339     return 0;
340 }
341 
342 
dma_writer_api_return_next_ready_frame(void * handle,dma_type type)343 tframe_t *dma_writer_api_return_next_ready_frame( void *handle, dma_type type )
344 {
345     dma_handle *p_dma = (dma_handle *)handle;
346     dma_pipe *pipe = &p_dma->pipe[type];
347     return dma_get_next_ready_frame( pipe );
348 }
349 
350 
351 extern int32_t acamera_get_api_context( void );
352 
353 //extern void dma_input_reset();
dma_writer_pipe_update(dma_pipe * pipe,bool drop_frame)354 dma_error dma_writer_pipe_update( dma_pipe *pipe , bool drop_frame)
355 {
356     dma_error result = edma_ok;
357     tframe_t *empty_frame = NULL;
358     uint32_t addr = 0;
359 #if ISP_HAS_FPGA_WRAPPER && ISP_CONTROLS_DMA_READER
360     uint32_t addr_uv = 0;
361 #endif
362     //only update if there are frames
363     if ( pipe != NULL && pipe->state.buf_num_size ) {
364         if ( pipe->state.initialized && pipe->settings.pause == 0 ) {
365 
366             //only check primary status
367             if ( pipe->settings.last_tframe ) {
368                 if (pipe->settings.init_delay > 0) {
369                     /* recycle the buffer as empty */
370                     pipe->settings.init_delay--;
371                     pipe->settings.last_tframe->primary.status = dma_buf_empty;
372                     pipe->settings.last_tframe->secondary.status = dma_buf_empty;
373                     pipe->settings.last_tframe = NULL;
374                 } else if (drop_frame) {
375                     /* recycle the buffer as empty */
376                     pipe->settings.last_tframe->primary.status = dma_buf_empty;
377                     pipe->settings.last_tframe->secondary.status = dma_buf_empty;
378                     pipe->settings.last_tframe = NULL;
379                 } else {
380                     addr = pipe->settings.last_tframe->primary.address;
381 #if ISP_HAS_FPGA_WRAPPER && ISP_CONTROLS_DMA_READER
382                     addr_uv = pipe->settings.last_tframe->secondary.address;
383 #endif
384                     pipe->settings.last_tframe->primary.status = dma_buf_ready;
385                     pipe->settings.last_tframe->secondary.status = dma_buf_ready;
386                 }
387                 LOG( LOG_DEBUG, "wbase_last_read:0x%lx\n", addr );
388             }
389 // update frame reader address
390 #if ISP_HAS_FPGA_WRAPPER && ISP_CONTROLS_DMA_READER
391             static uint32_t addr_late, addr_late1;
392             static uint32_t addr_late_uv, addr_late1_uv;
393             if ( pipe->settings.active && pipe->settings.ctx_id == acamera_get_api_context() && pipe->settings.last_tframe ) {
394                 pipe->api.p_acamera_fpga_frame_reader_rbase_write( pipe->settings.isp_base, addr_late + pipe->settings.read_offset );
395                 LOG( LOG_DEBUG, "ctx_id: %d, dma_pipe_type: %d, frame_reader_rbase: 0x%08x.", (int)pipe->settings.ctx_id, (int)pipe->type, (unsigned int)( addr_late + pipe->settings.read_offset ) );
396                 pipe->api.p_acamera_fpga_frame_reader_line_offset_write( pipe->settings.isp_base, pipe->settings.last_tframe->primary.line_offset );
397                 pipe->api.p_acamera_fpga_frame_reader_format_write( pipe->settings.isp_base, pipe->api.p_acamera_isp_dma_writer_format_read( pipe->settings.isp_base ) );
398                 pipe->api.p_acamera_fpga_frame_reader_rbase_load_write( pipe->settings.isp_base, 1 );
399                 pipe->api.p_acamera_fpga_frame_reader_rbase_load_write( pipe->settings.isp_base, 0 );
400 
401                 if ( pipe->api.p_acamera_isp_dma_writer_format_read_uv( pipe->settings.isp_base ) != DMA_FORMAT_DISABLE ) {
402                     pipe->api.p_acamera_fpga_frame_reader_rbase_write_uv( pipe->settings.isp_base, addr_late_uv + pipe->settings.read_offset );
403                     pipe->api.p_acamera_fpga_frame_reader_line_offset_write_uv( pipe->settings.isp_base, pipe->settings.last_tframe->secondary.line_offset );
404                     pipe->api.p_acamera_fpga_frame_reader_format_write_uv( pipe->settings.isp_base, pipe->api.p_acamera_isp_dma_writer_format_read_uv( pipe->settings.isp_base ) );
405                     pipe->api.p_acamera_fpga_frame_reader_rbase_load_write_uv( pipe->settings.isp_base, 1 );
406                     pipe->api.p_acamera_fpga_frame_reader_rbase_load_write_uv( pipe->settings.isp_base, 0 );
407                 }
408                 addr_late = addr_late1;
409                 addr_late1 = addr;
410 
411                 addr_late_uv = addr_late1_uv;
412                 addr_late1_uv = addr_uv;
413             }
414 #endif
415             pipe->settings.last_tframe = pipe->settings.inqueue_tframe[0];
416             pipe->settings.inqueue_tframe[0] = pipe->settings.inqueue_tframe[1];
417             pipe->settings.inqueue_tframe[1] = NULL;
418 
419             if (pipe->settings.back_tframe != NULL)
420                 empty_frame = pipe->settings.back_tframe;
421             else
422                 empty_frame = dma_get_next_empty_frame(pipe);
423 
424             if ( empty_frame != NULL ) {
425                 empty_frame->primary.type = pipe->api.p_acamera_isp_dma_writer_format_read( pipe->settings.isp_base );
426                 if ( empty_frame->primary.type != DMA_FORMAT_DISABLE ) {
427                     empty_frame->primary.width = pipe->api.p_acamera_isp_dma_writer_active_width_read( pipe->settings.isp_base );
428                     empty_frame->primary.height = pipe->api.p_acamera_isp_dma_writer_active_height_read( pipe->settings.isp_base );
429                     empty_frame->primary.line_offset = acamera_line_offset( empty_frame->primary.width, _get_pixel_width( empty_frame->primary.type ) );
430                     uint32_t frame_size = empty_frame->primary.line_offset * empty_frame->primary.height;
431                     addr = empty_frame->primary.address;
432                     pipe->settings.inqueue_tframe[1] = empty_frame;
433                     LOG( LOG_DEBUG, "next dma addr:0x%lx\n", addr );
434                     if ( pipe->settings.vflip ) {
435                         addr += frame_size - empty_frame->primary.line_offset;
436                         pipe->api.p_acamera_isp_dma_writer_line_offset_write( pipe->settings.isp_base, -(uint32_t)empty_frame->primary.line_offset );
437                     } else {
438                         pipe->api.p_acamera_isp_dma_writer_line_offset_write( pipe->settings.isp_base, empty_frame->primary.line_offset );
439                     }
440 
441                     //multicontext change in resolution
442                     pipe->api.p_acamera_isp_dma_writer_active_width_write( pipe->settings.isp_base, empty_frame->primary.width );
443                     pipe->api.p_acamera_isp_dma_writer_active_height_write( pipe->settings.isp_base, empty_frame->primary.height );
444 
445                     addr += pipe->settings.write_offset;
446                     if ( frame_size > empty_frame->primary.size ) { //check frame buffer size
447                         LOG( LOG_CRIT, "%s: frame_size greater than available buffer. fr %d vs %d ", TAG, (int)frame_size, (int)empty_frame->primary.size );
448                         result = edma_fail;
449                     } else {
450                         LOG( LOG_DEBUG, "ctx_id: %d, isp_base: %x, dma_pipe_type: %d, dma_writer_bank0_base_addr: 0x%08x.", (int)pipe->settings.ctx_id, (unsigned int)pipe->settings.isp_base, (int)pipe->type, (unsigned int)addr );
451                         pipe->api.p_acamera_isp_dma_writer_bank0_base_write( pipe->settings.isp_base, addr );
452                         empty_frame->primary.status = dma_buf_busy;
453                         pipe->settings.last_address = addr;
454                         pipe->api.p_acamera_isp_dma_writer_frame_write_on_write( pipe->settings.isp_base, 1 );
455                         /*if ( pipe->settings.enabled == 0 ) {
456 							pipe->api.p_acamera_isp_dma_writer_frame_write_on_write( pipe->settings.isp_base, 1 );
457 							pipe->settings.enabled = 1;
458 							DMA_PRINTF( ( "warning pipe is disabled, enabling" ) );
459 						}*/
460                     }
461                 }
462 
463                 empty_frame->secondary.type = pipe->api.p_acamera_isp_dma_writer_format_read_uv( pipe->settings.isp_base );
464                 if ( empty_frame->secondary.type != DMA_FORMAT_DISABLE ) {
465                     empty_frame->secondary.width = pipe->api.p_acamera_isp_dma_writer_active_width_read_uv( pipe->settings.isp_base );
466                     empty_frame->secondary.height = pipe->api.p_acamera_isp_dma_writer_active_height_read_uv( pipe->settings.isp_base );
467                     empty_frame->secondary.line_offset = acamera_line_offset( empty_frame->secondary.width, _get_pixel_width( empty_frame->secondary.type ) );
468                     uint32_t frame_size = empty_frame->secondary.line_offset * empty_frame->secondary.height;
469                     if (empty_frame->secondary.type == DMA_FORMAT_NV12_UV || empty_frame->secondary.type == DMA_FORMAT_NV12_VU)
470                         frame_size = frame_size / 2;
471                     addr = empty_frame->secondary.address;
472                     if ( pipe->settings.vflip ) {
473                         addr += frame_size - empty_frame->secondary.line_offset;
474                         pipe->api.p_acamera_isp_dma_writer_line_offset_write_uv( pipe->settings.isp_base, -(uint32_t)empty_frame->secondary.line_offset );
475                     } else {
476                         pipe->api.p_acamera_isp_dma_writer_line_offset_write_uv( pipe->settings.isp_base, empty_frame->secondary.line_offset );
477                     }
478 
479                     addr += pipe->settings.write_offset;
480                     if ( frame_size > empty_frame->secondary.size ) { //check frame buffer size
481                         LOG( LOG_CRIT, "%s: frame_size greater than available buffer. ds %d vs %d ", TAG, (int)frame_size, (int)empty_frame->secondary.size );
482                         result = edma_fail;
483                     } else {
484                         LOG( LOG_DEBUG, "ctx_id: %d, isp_base: %x, dma_pipe_type: %d, dma_writer_bank0_base_addr: 0x%08x.", (int)pipe->settings.ctx_id, (unsigned int)pipe->settings.isp_base, (int)pipe->type, (unsigned int)addr );
485                         pipe->api.p_acamera_isp_dma_writer_bank0_base_write_uv( pipe->settings.isp_base, addr );
486                         empty_frame->secondary.status = dma_buf_busy;
487                         pipe->settings.last_address = addr;
488                         pipe->api.p_acamera_isp_dma_writer_frame_write_on_write_uv( pipe->settings.isp_base, 1 );
489                         /*if ( pipe->settings.enabled == 0 ) {
490 							pipe->api.p_acamera_isp_dma_writer_frame_write_on_write_uv( pipe->settings.isp_base,  1 );
491 							//pipe->settings.enabled = 1;
492 							DMA_PRINTF( ( "warning pipe is disabled" ) );
493 						}*/
494                     }
495                 } else {
496                     pipe->api.p_acamera_isp_dma_writer_frame_write_on_write_uv( pipe->settings.isp_base, 0 );
497                 }
498 
499             } else {
500                 //no empty frames
501                 //LOG( LOG_CRIT, "NO EMPTY FRAMES on dma_pipe_type: %d\n", (int)pipe->type );
502                 pipe->api.p_acamera_isp_dma_writer_frame_write_on_write( pipe->settings.isp_base, 0 );
503                 pipe->api.p_acamera_isp_dma_writer_frame_write_on_write_uv( pipe->settings.isp_base, 0 );
504             }
505         }
506     } else {
507         result = edma_fail;
508     }
509     return result;
510 }
511 
dma_writer_pipe_set_fps(dma_pipe * pipe)512 dma_error dma_writer_pipe_set_fps(dma_pipe *pipe)
513 {
514     int frm_count = 0;
515     uint32_t inter_val = 0;
516     uint32_t c_fps = 0;
517     uint32_t t_fps = 0;
518 
519     if (pipe == NULL || pipe->settings.p_ctx == NULL) {
520         LOG(LOG_ERR, "Error input param:p_ctx %p\n", pipe->settings.p_ctx);
521         return edma_invalid_pipe;
522     }
523 
524     frm_count = pipe->settings.p_ctx->isp_frame_counter;
525     inter_val = pipe->settings.inter_val;
526     pipe->settings.back_tframe = NULL;
527     c_fps = pipe->settings.c_fps;
528     t_fps = pipe->settings.t_fps;
529 
530     if ((pipe->settings.inqueue_tframe[1] == NULL)
531         || (inter_val == 0) || (inter_val == 1))
532         return edma_ok;
533 
534     if (inter_val > 2) {
535         if (frm_count % inter_val != 0) {
536             pipe->api.p_acamera_isp_dma_writer_frame_write_on_write( pipe->settings.isp_base, 0 );
537             pipe->api.p_acamera_isp_dma_writer_frame_write_on_write_uv( pipe->settings.isp_base, 0 );
538             pipe->settings.back_tframe = pipe->settings.inqueue_tframe[1];
539             pipe->settings.inqueue_tframe[1] = NULL;
540         } else {
541             pipe->settings.back_tframe = NULL;
542         }
543     } else {
544         inter_val = c_fps  / (c_fps - t_fps);
545         if (frm_count % inter_val == 0) {
546             pipe->api.p_acamera_isp_dma_writer_frame_write_on_write( pipe->settings.isp_base, 0 );
547             pipe->api.p_acamera_isp_dma_writer_frame_write_on_write_uv( pipe->settings.isp_base, 0 );
548             pipe->settings.back_tframe = pipe->settings.inqueue_tframe[1];
549             pipe->settings.inqueue_tframe[1] = NULL;
550         } else {
551             pipe->settings.back_tframe = NULL;
552         }
553     }
554 
555     return edma_ok;
556 }
557 
dma_writer_pipe_process_interrupt(dma_pipe * pipe,uint32_t irq_event)558 dma_error dma_writer_pipe_process_interrupt( dma_pipe *pipe, uint32_t irq_event )
559 {
560     switch ( irq_event ) {
561     case ACAMERA_IRQ_FRAME_WRITER_FR:
562         if ( pipe->type == dma_fr ) {
563             dma_writer_pipe_update( pipe , false); // have to change last address and buffer ring
564             dma_writer_pipe_set_fps(pipe); //change the fps of fr path
565         }
566         break;
567     case ACAMERA_IRQ_FRAME_WRITER_DS:
568         if ( pipe->type == dma_ds1 || pipe->type == dma_ds2 ) {
569             dma_writer_pipe_update( pipe , false); // have to change last address and buffer ring
570             dma_writer_pipe_set_fps(pipe); //change the fps of ds1 path
571         }
572         break;
573     case ACAMERA_IRQ_FRAME_DROP_FR:
574         if ( pipe->type == dma_fr ) {
575             dma_writer_pipe_update( pipe , true); // have to change last address and buffer ring
576             dma_writer_pipe_set_fps(pipe); //change the fps of fr path
577         }
578         break;
579     case ACAMERA_IRQ_FRAME_DROP_DS:
580         if ( pipe->type == dma_ds1 || pipe->type == dma_ds2 ) {
581             dma_writer_pipe_update( pipe , true); // have to change last address and buffer ring
582             dma_writer_pipe_set_fps(pipe); //change the fps of ds1 path
583         }
584         break;
585     }
586     return 0;
587 }
588 
589 
dma_writer_process_interrupt(void * handle,uint32_t irq_event)590 dma_error dma_writer_process_interrupt( void *handle, uint32_t irq_event )
591 {
592     dma_error result = edma_ok;
593     uint32_t idx = 0;
594 
595     dma_handle *p_dma = (dma_handle *)handle;
596     if ( !p_dma ) {
597         LOG( LOG_ERR, "p_dma is NULL of event: %u", (unsigned int)irq_event );
598         return edma_fail;
599     }
600 
601     for ( idx = 0; idx < dma_max; idx++ ) {
602         if (p_dma->pipe[idx].state.initialized == 1)
603             dma_writer_pipe_process_interrupt( &p_dma->pipe[idx], irq_event );
604     }
605     return result;
606 }
607 
608 
dma_writer_return_metadata(void * handle,dma_type type)609 metadata_t *dma_writer_return_metadata( void *handle, dma_type type )
610 {
611     if ( handle != NULL ) {
612 
613         dma_handle *p_dma = (dma_handle *)handle;
614 
615         metadata_t *ret = &( p_dma->pipe[type].settings.curr_metadata );
616         return ret;
617     }
618     return 0;
619 }
620 
dma_writer_pipe_get_next_empty_buffer(void * handle,dma_type type)621 dma_error dma_writer_pipe_get_next_empty_buffer( void *handle, dma_type type )
622 {
623     dma_error result = edma_ok;
624 
625     if ( handle != NULL ) {
626         dma_handle *p_dma = (dma_handle *)handle;
627         dma_pipe *pipe = &p_dma->pipe[type];
628 
629         return dma_writer_pipe_update(pipe, false);
630     } else {
631         result = edma_fail;
632     }
633     return result;
634 }