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