• 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 <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/init.h>
23 #include <linux/kthread.h>
24 #include <linux/sched.h>
25 #include <linux/err.h>
26 #include <linux/errno.h>
27 
28 #include "acamera.h"
29 #include "acamera_firmware_api.h"
30 #include "acamera_firmware_config.h"
31 #include "acamera_command_api.h"
32 #include "acamera_control_config.h"
33 #include "system_control.h"
34 #if ISP_HAS_CONNECTION_DEBUG
35 #include "acamera_cmd_interface.h"
36 #endif
37 
38 #if ISP_HAS_STREAM_CONNECTION
39 #include "acamera_connection.h"
40 #endif
41 
42 #include "application_command_api.h"
43 
44 /* Entire main_firmware is not used when V4L2 interface is enabled.
45  * All relevent functions and codes here can be found in fw-interface.c
46  */
47 // the settings for each firmware context were pre-generated and
48 // saved in the header file. They are given as a reference and should be changed
49 // according to the customer needs.
50 #include "runtime_initialization_settings.h"
51 
52 extern uint8_t *isp_kaddr;
53 extern resource_size_t isp_paddr;
54 extern unsigned int temper_line_offset;
55 extern unsigned int temper_frame_num;
56 extern unsigned int temper_frame_size;
57 
58 static struct task_struct *isp_fw_process_thread = NULL;
59 
60 #if !V4L2_INTERFACE_BUILD //all these callbacks are managed by v4l2
61 // This function can be used to customize initialization process.
62 // It is called by the firmware at the end o2f context initialization.
63 // The input pointer to a context can be used to differentiate contexts
custom_initialization(uint32_t ctx_num)64 void custom_initialization( uint32_t ctx_num )
65 {
66 }
67 
68 
69 // The driver can provide the full set of metadata parameters
70 // The callback_meta function should be set in initalization settings to support it.
callback_meta(uint32_t ctx_num,const void * fw_metadata)71 void callback_meta( uint32_t ctx_num, const void *fw_metadata )
72 {
73 }
74 
75 
76 // The ISP pipeline can have several outputs such as Full Resolution, DownScaler1, DownScaler2 etc
77 // It is possible to set the firmware up for returning metadata on each output frame from
78 // the specific channel. This callbacks must be set in acamera_settings structure and passed to the firmware in
79 // acamera_init api function
80 // The pointer to the context can be used to differentiate contexts
81 
82 // Callback from FR output pipe
callback_fr(uint32_t ctx_num,tframe_t * tframe,const metadata_t * metadata)83 void callback_fr( uint32_t ctx_num, tframe_t *tframe, const metadata_t *metadata )
84 {
85 }
86 
87 // Callback from DS1 output pipe
callback_ds1(uint32_t ctx_num,tframe_t * tframe,const metadata_t * metadata)88 void callback_ds1( uint32_t ctx_num, tframe_t *tframe, const metadata_t *metadata )
89 {
90 }
91 
92 // Callback from DS2 output pipe
callback_ds2(uint32_t ctx_num,tframe_t * tframe,const metadata_t * metadata)93 void callback_ds2( uint32_t ctx_num, tframe_t *tframe, const metadata_t *metadata )
94 {
95 }
96 
97 #endif
98 
99 #if ISP_HAS_STREAM_CONNECTION && CONNECTION_IN_THREAD
100 
101 static struct task_struct *isp_fw_connections_thread = NULL;
102 
connection_thread(void * foo)103 static int connection_thread( void *foo )
104 {
105     LOG( LOG_CRIT, "connection_thread start" );
106 
107     acamera_connection_init();
108 
109     while ( !kthread_should_stop() ) {
110         acamera_connection_process();
111     }
112 
113     acamera_connection_destroy();
114 
115     LOG( LOG_CRIT, "connection_thread stop" );
116 
117     return 0;
118 }
119 #endif
120 
isp_fw_process(void * data)121 static int isp_fw_process( void *data )
122 {
123     LOG( LOG_CRIT, "isp_fw_process start" );
124 
125 #if ISP_HAS_STREAM_CONNECTION && !CONNECTION_IN_THREAD
126     acamera_connection_init();
127 #endif
128 
129     while ( !kthread_should_stop() ) {
130         acamera_process();
131 
132 #if ISP_HAS_STREAM_CONNECTION && !CONNECTION_IN_THREAD
133         acamera_connection_process();
134 #endif
135     }
136 
137 #if ISP_HAS_STREAM_CONNECTION && !CONNECTION_IN_THREAD
138     acamera_connection_destroy();
139 #endif
140 
141     LOG( LOG_CRIT, "isp_fw_process stop" );
142     return 0;
143 }
144 
145 
146 // this is a main application IRQ handler to drive firmware
147 // The main purpose is to redirect irq events to the
148 // appropriate firmware context.
149 // There are several type of firmware IRQ which may happen.
150 // The other events are platform specific. The firmware can support several external irq events or
151 // does not support any. It totally depends on the system configuration and firmware compile time settings.
152 // Please see the ACamera Porting Guide for details.
interrupt_handler(void * data,uint32_t mask)153 static void interrupt_handler( void *data, uint32_t mask )
154 {
155     acamera_interrupt_handler();
156 }
157 
isp_update_setting(void)158 void isp_update_setting(void)
159 {
160     aframe_t *aframe = NULL;
161     uint32_t fr_num = 0;
162     resource_size_t paddr = 0;
163     int i = 0,j = 0;
164 
165     if (isp_paddr == 0 || isp_kaddr == NULL) {
166         pr_err("%s: Error input isp cma addr\n", __func__);
167         return;
168     }
169 
170     paddr = isp_paddr;
171     for(j = 0; j < FIRMWARE_CONTEXT_NUMBER; j++)
172     {
173 		aframe = settings[j].temper_frames;
174 	    fr_num = settings[j].temper_frames_number;
175 
176 	    for (i = 0; i < fr_num; i++) {
177 	        aframe[i].address = paddr;
178 	        aframe[i].size = temper_frame_size;
179 
180 	        paddr = aframe[i].address + temper_frame_size;
181 
182 	        aframe[i].line_offset = temper_line_offset;
183 	    }
184 
185 	    settings[j].temper_frames_number = temper_frame_num;
186     }
187 }
188 
isp_fw_init(uint32_t hw_isp_addr)189 int isp_fw_init( uint32_t hw_isp_addr )
190 {
191     int result = 0;
192     uint32_t i;
193 
194     isp_update_setting();
195 
196     for ( i = 0; i < FIRMWARE_CONTEXT_NUMBER; i++ ) {
197         settings[i].hw_isp_addr = hw_isp_addr;
198     }
199 
200     // The firmware supports multicontext.
201     // It means that the customer can use the same firmware for controlling
202     // several instances of different sensors/isp. To initialise a context
203     // the structure acamera_settings must be filled properly.
204     // the total number of initialized context must not exceed FIRMWARE_CONTEXT_NUMBER
205     // all contexts are numerated from 0 till ctx_number - 1
206     result = acamera_init( settings, FIRMWARE_CONTEXT_NUMBER );
207 
208     if ( result == 0 ) {
209         //application_command(TGENERAL, ACTIVE_CONTEXT, 0, COMMAND_GET, &prev_ctx_num);
210 
211         // set the interrupt handler. The last parameter may be used
212         // to specify the context. The system must call this interrupt_handler
213         // function whenever the ISP interrupt happens.
214         // This interrupt handling procedure is only advisable and is used in ACamera demo application.
215         // It can be changed by a customer discretion.
216         system_interrupt_set_handler( interrupt_handler, NULL );
217     } else {
218         LOG( LOG_ERR, "Failed to start firmware processing thread. " );
219     }
220 
221     if ( result == 0 ) {
222 
223 #if ISP_HAS_STREAM_CONNECTION && CONNECTION_IN_THREAD
224         isp_fw_connections_thread = kthread_run( connection_thread, NULL, "isp_connection" );
225 #endif
226         isp_fw_process_thread = kthread_run( isp_fw_process, NULL, "isp_process" );
227     }
228 
229     return IS_ERR(isp_fw_process_thread) ? -1 : 0;
230 }
231 
isp_fw_exit(void)232 void isp_fw_exit( void )
233 {
234 #if ISP_HAS_STREAM_CONNECTION && CONNECTION_IN_THREAD
235     if ( isp_fw_connections_thread )
236         kthread_stop( isp_fw_connections_thread );
237 #endif
238 
239     if ( isp_fw_process_thread ) {
240         kthread_stop( isp_fw_process_thread );
241     }
242 
243     // this api function will free
244     // all resources allocated by the firmware
245     acamera_terminate();
246 
247     bsp_destroy();
248 }
249