• 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.h"
22 #include "acamera_command_api.h"
23 #include "acamera_math.h"
24 
25 #include "isp_config_seq.h"
26 #include "acamera_sbus_api.h"
27 
28 #include "acamera_fr_gamma_rgb_mem_config.h"
29 
30 #if ISP_HAS_DS1
31 #include "acamera_ds1_gamma_rgb_mem_config.h"
32 #endif
33 
34 #include "acamera_isp_config.h"
35 
36 
37 #include "general_fsm.h"
38 
39 #include "acamera_ca_correction_filter_mem_config.h"
40 #include "acamera_ca_correction_mesh_mem_config.h"
41 
42 #include "acamera_lut3d_mem_config.h"
43 
44 
45 #if defined( CALIBRATION_DECOMPANDER0_MEM )
46 #include "acamera_decompander0_mem_config.h"
47 #endif
48 
49 #if defined( CALIBRATION_DECOMPANDER1_MEM )
50 #include "acamera_decompander1_mem_config.h"
51 #endif
52 
53 #if defined( CALIBRATION_SHADING_RADIAL_R )
54 #include "acamera_radial_shading_mem_config.h"
55 #endif
56 
57 #ifdef LOG_MODULE
58 #undef LOG_MODULE
59 #define LOG_MODULE LOG_MODULE_GENERAL
60 #endif
61 
62 #define CAC_MEM_LUT_LEN 4096
63 
64 #define BIT_SHIFT( v, s ) ( ( s > 0 ) ? ( v << s ) : ( v >> ( -s ) ) )
65 
66 typedef uint16_t( CAC_MEM_LUT_T )[][10];
67 
signed_bitshift(int32_t val,int32_t shift)68 static int32_t signed_bitshift( int32_t val, int32_t shift )
69 {
70     int32_t out_val = 0;
71     uint8_t val_sign = val < 0;
72 
73     val = (val > 0) ? val : -val;
74 
75     if ( val_sign ) {
76         out_val = -BIT_SHIFT( val, shift );
77     } else {
78         out_val = BIT_SHIFT( val, shift );
79     }
80 
81     return out_val;
82 }
83 
general_cac_memory_lut_reload(general_fsm_ptr_t p_fsm)84 static void general_cac_memory_lut_reload( general_fsm_ptr_t p_fsm )
85 {
86     uint32_t cac_mem_len = _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CA_CORRECTION_MEM );
87     const CAC_MEM_LUT_T *p_calibration_ca_model = (const CAC_MEM_LUT_T *)_GET_USHORT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CA_CORRECTION_MEM );
88     const uint16_t *p_calibration_cac_cfg = _GET_USHORT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CA_CORRECTION );
89 
90     uint16_t calibration_ca_min_correction = p_calibration_cac_cfg[0];
91     uint16_t calibration_ca_mesh_width = p_calibration_cac_cfg[1];
92     uint16_t calibration_ca_mesh_height = p_calibration_cac_cfg[2];
93 
94     uint8_t cfa_pattern = acamera_isp_top_cfa_pattern_read( p_fsm->cmn.isp_base );
95 
96     uint8_t line_offset = calibration_ca_mesh_width;
97     uint16_t plane_offset = calibration_ca_mesh_width * calibration_ca_mesh_height;
98 
99     int32_t ca_model[10] = {0};
100     int32_t mesh_vars[9] = {0};
101     uint16_t component;
102     uint8_t term;
103     uint8_t plane_count;
104     uint32_t plane_offset_val;
105     uint8_t x;
106     uint8_t y;
107     uint16_t vh_shift;
108     uint16_t lut_index = 0;
109 
110     if ( CAC_MEM_LUT_LEN != ( ACAMERA_CA_CORRECTION_MESH_MEM_SIZE >> 2 ) ) {
111         LOG( LOG_CRIT, "cac_mem_lut size mismatch, hw_size: %d, expected: %d.", ( ACAMERA_CA_CORRECTION_MESH_MEM_SIZE >> 2 ), CAC_MEM_LUT_LEN );
112         return;
113     }
114 
115     // configure mesh size and reset the table
116     acamera_isp_ca_correction_mesh_width_write( p_fsm->cmn.isp_base, calibration_ca_mesh_width );
117     acamera_isp_ca_correction_mesh_height_write( p_fsm->cmn.isp_base, calibration_ca_mesh_height );
118     acamera_isp_ca_correction_line_offset_write( p_fsm->cmn.isp_base, calibration_ca_mesh_width );
119     acamera_isp_ca_correction_plane_offset_write( p_fsm->cmn.isp_base, calibration_ca_mesh_width * calibration_ca_mesh_height );
120 
121     // reset to 0
122     for ( lut_index = 0; lut_index < CAC_MEM_LUT_LEN; lut_index++ ) {
123         acamera_ca_correction_mesh_mem_array_data_write( p_fsm->cmn.isp_base, lut_index, 0 );
124     }
125 
126     switch ( cfa_pattern ) {
127     case 0: // RGGB
128         plane_count = 2;
129         break;
130     case 1: // RCCC
131         plane_count = 1;
132         break;
133     default: // RGBIr
134         plane_count = 3;
135         break;
136     }
137 
138     LOG( LOG_DEBUG, "cfa_pattern: %d, plane_count: %d, cac_mem_len: %d", cfa_pattern, plane_count, cac_mem_len );
139 
140     for ( component = 0; component < plane_count * 2; component++ ) {
141         // Generate s15.0 ca_model (int32) from u16.0 ca_model_u (uint16)
142         for ( term = 0; term < 10; term++ ) {
143             if ( ( *p_calibration_ca_model )[component][term] < 32768 )
144                 ca_model[term] = ( *p_calibration_ca_model )[component][term];
145             else
146                 ca_model[term] = ( *p_calibration_ca_model )[component][term] - 65536;
147         }
148 
149         plane_offset_val = plane_offset * ( component>>1 );
150         vh_shift = ( component % 2 ) * 8;
151 
152         for ( x = 0; x < calibration_ca_mesh_width; x++ ) {
153             for ( y = 0; y < calibration_ca_mesh_height; y++ ) {
154                 int32_t z32 = 0;
155                 int16_t z16 = 0;
156                 int16_t z_norm = 0;
157                 int32_t product = 0;
158                 uint8_t z_sign = 0;
159                 uint32_t zu32 = 0;
160                 uint8_t lut_shift = 0;
161                 uint32_t old_value = 0;
162                 uint32_t new_value = 0;
163 
164                 // Apply model - this polynomial:
165                 // z = b0*x^3 + b1*x^2*y + b2*x*y^2 + b3*y^3 + b4*x^2 + b5*x*y + b6*y^2 + b7*x + b8*y +b9
166 
167                 // mesh_vars(:,1:4) are u18.0, coeffs(1:4) are s-10.23 so product is s8.23
168                 // mesh_vars(:,5:7) are u12.0, coeffs(5:7) are s-3.17 so product is s9.17
169                 // mesh_vars(:,8:9) are u6.0, coeffs(8:9) are s2.11 so product is s8.11
170                 // mesh_vars(:,10) are u1.0, coeffs(10) is s6.5 so product is s6.5
171 
172                 mesh_vars[8] = y;
173                 mesh_vars[7] = x;
174                 mesh_vars[6] = y * y;
175                 mesh_vars[5] = x * y;
176                 mesh_vars[4] = x * x;
177                 mesh_vars[3] = mesh_vars[6] * y;
178                 mesh_vars[2] = mesh_vars[5] * y;
179                 mesh_vars[1] = mesh_vars[4] * y;
180                 mesh_vars[0] = mesh_vars[4] * x;
181 
182                 for ( term = 0; term < 4; term++ ) {
183                     product = mesh_vars[term] * ca_model[term];
184                     product = signed_bitshift( product, -4 );
185                     z32 = z32 + product;
186                 }
187 
188                 // Drop precision to match next set of coefficients
189                 z32 = signed_bitshift( z32, -2 );
190 
191                 for ( term = 4; term < 7; term++ ) {
192                     product = mesh_vars[term] * ca_model[term];
193                     z32 = z32 + product;
194                 }
195 
196                 // Drop precision to match next set of coefficients
197                 z32 = signed_bitshift( z32, -6 );
198 
199                 for ( term = 7; term < 9; term++ ) {
200                     product = mesh_vars[term] * ca_model[term];
201                     z32 = z32 + product;
202                 }
203 
204                 // Drop precision to match error model (precision of coeff 10 is also set to match this)
205                 z32 = signed_bitshift( z32, -4 );
206 
207                 z32 = z32 + ca_model[9];
208 
209                 // Clip to s4.7 range
210                 z32 = MAX( z32, -2048 );
211                 z32 = MIN( z32, 2047 );
212 
213                 // Cast z from int32 to int16 here. Its size is only 12 bits.
214                 z16 = (int16_t)z32;
215 
216                 // Apply periodic linear approximation of error model
217                 // z = z - 0.1*sin(pi*z)
218                 // Approximation between is z = z+0.25z_norm
219 
220                 // z_norm is equivalent position of z within linear range of +/-0.5
221                 if ( ( z16 + 128 ) < 0 ) {
222                     z_norm = ( ( z16 + 128 ) % 256 ) - 128;
223                     z_norm = 256 + z_norm;
224                 } else {
225                     z_norm = ( ( z16 + 128 ) % 256 ) - 128;
226                 }
227 
228                 if ( z_norm < -64 ) {
229                     z_norm = -128 - z_norm;
230                 } else if ( z_norm > 64 ) {
231                     z_norm = 128 - z_norm;
232                 }
233 
234                 // Shift by -2 is like multiplying by 0.25z_norm
235                 z_norm = signed_bitshift( z_norm, -2 );
236                 z16 = z16 - z_norm;
237 
238                 z16 = signed_bitshift( z16, -2 );
239 
240                 // Now manipulate z to the format of the mesh (u4.4, 2s complement)
241 
242                 z_sign = z16 < 0;
243 
244                 // Round z to 4 bits precision
245                 z16 = (z16>0) ? z16 : -z16;
246                 z16 = ( z16 % 2 ) + ( z16>>1 );
247 
248                 // Apply ca_min_correction (clip small corrections to 0)
249                 if ( z16 <= calibration_ca_min_correction ) {
250                     z_sign = 0;
251                     z16 = 0;
252                 }
253 
254                 if ( z16 > 127 ) {
255                     z16 = 127;
256                 }
257 
258                 // Convert to 2s complement
259                 if ( z_sign ) {
260                     z16 = 256 - z16;
261                 }
262 
263                 // Cast z from int16 to uint32 here
264                 zu32 = (uint32_t)z16;
265 
266                 // Work out which LUT entry this z value should be placed in
267                 lut_index = plane_offset_val + y * line_offset + x;
268 
269                 // Shift increases by 16 bits for odd entries
270                 lut_shift = vh_shift + ( lut_index % 2 ) * 16;
271 
272                 // Find location within half sized array (2 blocks per register)
273                 lut_index = ( lut_index>>1 );
274 
275                 // Clip to size of LUT (in case of error)
276                 lut_index = lut_index & 4095;
277 
278                 old_value = acamera_ca_correction_mesh_mem_array_data_read( p_fsm->cmn.isp_base, lut_index );
279                 new_value = old_value + BIT_SHIFT( zu32, lut_shift );
280                 acamera_ca_correction_mesh_mem_array_data_write( p_fsm->cmn.isp_base, lut_index, new_value );
281             }
282         }
283     }
284 
285     acamera_isp_ca_correction_mesh_reload_write( p_fsm->cmn.isp_base, 0 );
286     acamera_isp_ca_correction_mesh_reload_write( p_fsm->cmn.isp_base, 1 );
287     acamera_isp_ca_correction_mesh_reload_write( p_fsm->cmn.isp_base, 0 );
288 
289     return;
290 }
291 
acamera_reload_isp_calibratons(general_fsm_ptr_t p_fsm)292 void acamera_reload_isp_calibratons( general_fsm_ptr_t p_fsm )
293 {
294     int32_t i = 0;
295     (void)i; // no unused warninig
296 
297 //temp lut to test new FS module
298 #if ISP_WDR_SWITCH == 0
299     uint32_t mode = p_fsm->wdr_mode;
300     if ( mode != WDR_MODE_LINEAR ) {
301         LOG( LOG_ERR, "Failed to apply wdr switch. Firmware doesn't support WDR mode." );
302     }
303 #endif
304 
305     const uint16_t *gamma_lut = _GET_USHORT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_GAMMA );
306     const uint32_t gamma_lut_len = _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_GAMMA );
307 
308     uint32_t exp_gamma_size = ( ( ACAMERA_FR_GAMMA_RGB_MEM_SIZE / ( ACAMERA_FR_GAMMA_RGB_MEM_ARRAY_DATA_DATASIZE >> 3 ) >> 1 ) + 1 );
309 
310     if ( gamma_lut_len != exp_gamma_size )
311         LOG( LOG_CRIT, "wrong elements number in gamma_rgb -> current size %d but expected %d", (int)gamma_lut_len, (int)exp_gamma_size );
312 
313     for ( i = 0; i < gamma_lut_len; i++ ) {
314         acamera_fr_gamma_rgb_mem_array_data_write( p_fsm->cmn.isp_base, i, gamma_lut[i] );
315 #if ISP_HAS_DS1
316         acamera_ds1_gamma_rgb_mem_array_data_write( p_fsm->cmn.isp_base, i, gamma_lut[i] );
317 #endif
318     }
319 
320     const uint8_t *demosaic_lut = _GET_UCHAR_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_DEMOSAIC );
321 
322     for ( i = 0; i < _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_DEMOSAIC ); i++ ) {
323         acamera_isp_demosaic_rgb_noise_profile_lut_weight_lut_write( p_fsm->cmn.isp_base, i, demosaic_lut[i] );
324     }
325 
326     const uint8_t *np_lut_wdr = _GET_UCHAR_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_WDR_NP_LUT );
327     const uint8_t *np_lut = _GET_UCHAR_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_NOISE_PROFILE );
328 
329     for ( i = 0; i < _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_NOISE_PROFILE ); i++ ) {
330 
331         acamera_isp_sinter_noise_profile_lut_weight_lut_write( p_fsm->cmn.isp_base, i, np_lut[i] );
332         acamera_isp_temper_noise_profile_lut_weight_lut_write( p_fsm->cmn.isp_base, i, np_lut[i] );
333 
334         acamera_isp_frame_stitch_np_lut_vs_weight_lut_write( p_fsm->cmn.isp_base, i, np_lut_wdr[i] );
335         acamera_isp_frame_stitch_np_lut_s_weight_lut_write( p_fsm->cmn.isp_base, i, np_lut_wdr[i] );
336         acamera_isp_frame_stitch_np_lut_m_weight_lut_write( p_fsm->cmn.isp_base, i, np_lut_wdr[i] );
337         acamera_isp_frame_stitch_np_lut_l_weight_lut_write( p_fsm->cmn.isp_base, i, np_lut_wdr[i] );
338     }
339 
340 #if ISP_HAS_COLOR_MATRIX_FSM
341     acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_SHADING_MESH_RELOAD, NULL, 0 );
342 
343     {
344         // this wdr_switch is called when change resolution happens.
345         // we need to reload ccm matrix in the case when several set of
346         // settings are supported for each resolution
347         acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_CCM_CHANGE, NULL, 0 );
348     }
349 #endif
350 
351 #if defined( ISP_HAS_IRIDIX_FSM ) || defined( ISP_HAS_IRIDIX8_FSM )
352     acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_IRIDIX_INIT, NULL, 0 );
353 #endif
354 
355     // Load purple fringe
356     const uint8_t *lut_pf = _GET_UCHAR_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_PF_RADIAL_LUT );
357     for ( i = 0; i < _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_PF_RADIAL_LUT ); i++ ) {
358         acamera_isp_pf_correction_shading_shading_lut_write( p_fsm->cmn.isp_base, i, lut_pf[i] );
359     }
360 
361     const uint16_t *p_pf_radial_params = (uint16_t *)_GET_USHORT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_PF_RADIAL_PARAMS );
362     acamera_isp_pf_correction_center_x_write( p_fsm->cmn.isp_base, p_pf_radial_params[0] );
363     acamera_isp_pf_correction_center_y_write( p_fsm->cmn.isp_base, p_pf_radial_params[1] );
364     acamera_isp_pf_correction_off_center_mult_write( p_fsm->cmn.isp_base, p_pf_radial_params[2] );
365 
366 #if defined( ACAMERA_CA_CORRECTION_FILTER_MEM_ARRAY_DATA_DEFAULT )
367     uint32_t ca_filter_mem_len = _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CA_FILTER_MEM );
368     const uint32_t *p_ca_filter_mem = _GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CA_FILTER_MEM );
369     for ( i = 0; i < ca_filter_mem_len; i++ ) {
370         acamera_ca_correction_filter_mem_array_data_write( p_fsm->cmn.isp_base, i, p_ca_filter_mem[i] );
371     }
372 #endif
373 
374     if ( acamera_isp_isp_global_parameter_status_cac_read( p_fsm->cmn.isp_base ) == 0 ) {
375 #if defined( ACAMERA_CA_CORRECTION_MESH_MEM_ARRAY_DATA_DEFAULT )
376         general_cac_memory_lut_reload( p_fsm );
377 #endif
378     }
379 
380     if ( acamera_isp_isp_global_parameter_status_lut_3d_read( p_fsm->cmn.isp_base ) == 0 ) {
381 #if defined( ACAMERA_LUT3D_MEM_ARRAY_DATA_DEFAULT )
382         uint32_t lut3d_mem_len = _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_LUT3D_MEM );
383         const uint32_t *p_lut3d_mem = _GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_LUT3D_MEM );
384         for ( i = 0; i < lut3d_mem_len; i++ ) {
385             acamera_lut3d_mem_array_data_write( p_fsm->cmn.isp_base, i, p_lut3d_mem[i] );
386         }
387 #endif
388     }
389 
390 #if defined( CALIBRATION_DECOMPANDER0_MEM )
391     for ( i = 0; i < _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_DECOMPANDER0_MEM ); i++ ) {
392         acamera_decompander0_mem_array_data_write( p_fsm->cmn.isp_base, i, _GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_DECOMPANDER0_MEM )[i] );
393     }
394 #endif
395 
396 #if defined( CALIBRATION_DECOMPANDER1_MEM )
397     for ( i = 0; i < _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_DECOMPANDER1_MEM ); i++ ) {
398         acamera_decompander1_mem_array_data_write( p_fsm->cmn.isp_base, i, _GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_DECOMPANDER1_MEM )[i] );
399     }
400 #endif
401 
402 #if defined( CALIBRATION_SHADING_RADIAL_R ) && defined( CALIBRATION_SHADING_RADIAL_G ) && defined( CALIBRATION_SHADING_RADIAL_B )
403     uint32_t len = _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_SHADING_RADIAL_R );
404     uint16_t * p_lut = _GET_USHORT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_SHADING_RADIAL_R );
405     uint32_t bank_offset = 0;
406     for ( i = 0; i < len; i++ ) {
407         acamera_radial_shading_mem_array_data_write( p_fsm->cmn.isp_base, bank_offset + i, p_lut[i] );
408     }
409 
410     len = _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_SHADING_RADIAL_G );
411     p_lut = _GET_USHORT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_SHADING_RADIAL_G );
412     bank_offset += 256;
413     for ( i = 0; i < len; i++ ) {
414         acamera_radial_shading_mem_array_data_write( p_fsm->cmn.isp_base, bank_offset + i, p_lut[i] );
415     }
416 
417     len = _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_SHADING_RADIAL_B );
418     p_lut = _GET_USHORT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_SHADING_RADIAL_B );
419     bank_offset += 256;
420     for ( i = 0; i < len; i++ ) {
421         acamera_radial_shading_mem_array_data_write( p_fsm->cmn.isp_base, bank_offset + i, p_lut[i] );
422     }
423 #endif
424 
425 #if defined(CALIBRATION_SHADING_RADIAL_CENTRE_AND_MULT)
426     uint16_t len_cm = _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_SHADING_RADIAL_CENTRE_AND_MULT );
427     uint16_t *radial_shading_lut_cm = _GET_USHORT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_SHADING_RADIAL_CENTRE_AND_MULT );
428 
429     if ( len_cm == 16 ) {
430         //R
431         acamera_isp_radial_shading_centerr_x_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[0] );
432         acamera_isp_radial_shading_centerr_y_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[1] );
433         acamera_isp_radial_shading_off_center_multrx_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[2] );
434         acamera_isp_radial_shading_off_center_multry_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[3] );
435         //G
436         acamera_isp_radial_shading_centerg_x_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[4] );
437         acamera_isp_radial_shading_centerg_y_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[5] );
438         acamera_isp_radial_shading_off_center_multgx_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[6] );
439         acamera_isp_radial_shading_off_center_multgy_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[7] );
440         //B
441         acamera_isp_radial_shading_centerb_x_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[8] );
442         acamera_isp_radial_shading_centerb_y_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[9] );
443         acamera_isp_radial_shading_off_center_multbx_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[10] );
444         acamera_isp_radial_shading_off_center_multby_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[11] );
445         //IR
446         acamera_isp_radial_shading_centerir_x_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[12] );
447         acamera_isp_radial_shading_centerir_y_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[13] );
448         acamera_isp_radial_shading_off_center_multirx_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[14] );
449         acamera_isp_radial_shading_off_center_multiry_write( p_fsm->cmn.isp_base, radial_shading_lut_cm[15] );
450     } else {
451         LOG( LOG_ERR, "CALIBRATION_SHADING_RADIAL_CENTRE_AND_MULT has wrong size %d but expected 16", len_cm );
452     }
453 #endif
454 
455     p_fsm->gamma2_enable = _GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_GAMMA_THRESHOLD )[0];
456 #if FW_HAS_CUSTOM_SETTINGS
457     // the custom initialization may be required for a context
458     const acam_reg_t *p_custom_settings_context = (const acam_reg_t *)_GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_CUSTOM_SETTINGS_CONTEXT );
459     acamera_load_sw_sequence( ACAMERA_FSM2CTX_PTR( p_fsm )->settings.isp_base, &p_custom_settings_context, 0 );
460 #endif
461 }
462 
463 
general_fsm_process_interrupt(general_fsm_const_ptr_t p_fsm,uint8_t irq_event)464 void general_fsm_process_interrupt( general_fsm_const_ptr_t p_fsm, uint8_t irq_event )
465 {
466     if ( acamera_fsm_util_is_irq_event_ignored( (fsm_irq_mask_t *)( &p_fsm->mask ), irq_event ) )
467         return;
468     switch ( irq_event ) {
469     case ACAMERA_IRQ_FRAME_START:
470         general_frame_start( (general_fsm_ptr_t)p_fsm );
471         break;
472     case ACAMERA_IRQ_FRAME_END:
473         general_frame_end( (general_fsm_ptr_t)p_fsm );
474         break;
475     }
476 }
477 
general_set_wdr_mode(general_fsm_ptr_t p_fsm)478 void general_set_wdr_mode( general_fsm_ptr_t p_fsm )
479 {
480 #if ISP_BINARY_SEQUENCE == 0 //remove compile error
481     (void)seq_table;
482 #endif
483 
484 	if(p_fsm->p_fsm_mgr == NULL)
485 		return;
486 
487     switch ( p_fsm->wdr_mode ) {
488     case WDR_MODE_LINEAR:
489 #ifdef SENSOR_ISP_SEQUENCE_DEFAULT_LINEAR
490         LOG( LOG_CRIT, "Setting Linear Binary Sequence\n" );
491         acamera_load_sw_sequence( p_fsm->cmn.isp_base, ACAMERA_FSM2CTX_PTR( p_fsm )->isp_sequence, SENSOR_ISP_SEQUENCE_DEFAULT_LINEAR );
492 #endif
493 
494 #if defined( SENSOR_ISP_SEQUENCE_DEFAULT_FPGA_LINEAR ) && ISP_HAS_FPGA_WRAPPER
495         LOG( LOG_CRIT, "Setting Linear Binary Sequence for FPGA\n" );
496         acamera_load_isp_sequence( 0, ACAMERA_FSM2CTX_PTR( p_fsm )->isp_sequence, SENSOR_ISP_SEQUENCE_DEFAULT_FPGA_LINEAR );
497 #endif
498         break;
499 
500     case WDR_MODE_FS_LIN: {
501 
502 #if defined( SENSOR_ISP_SEQUENCE_DEFAULT_FS_LIN_2EXP ) || defined( SENSOR_ISP_SEQUENCE_DEFAULT_FS_LIN_3EXP ) || defined( SENSOR_ISP_SEQUENCE_DEFAULT_FS_LIN_4EXP )
503         if ( 2 == p_fsm->cur_exp_number ) {
504             acamera_load_sw_sequence( p_fsm->cmn.isp_base, ACAMERA_FSM2CTX_PTR( p_fsm )->isp_sequence, SENSOR_ISP_SEQUENCE_DEFAULT_FS_LIN_2EXP );
505             LOG( LOG_CRIT, "Setting FS_Lin_2Exp Binary Sequence." );
506         } else if ( 3 == p_fsm->cur_exp_number ) {
507             acamera_load_sw_sequence( p_fsm->cmn.isp_base, ACAMERA_FSM2CTX_PTR( p_fsm )->isp_sequence, SENSOR_ISP_SEQUENCE_DEFAULT_FS_LIN_3EXP );
508             LOG( LOG_CRIT, "Setting FS_Lin_3Exp Binary Sequence." );
509         } else if ( 4 == p_fsm->cur_exp_number ) {
510             acamera_load_sw_sequence( p_fsm->cmn.isp_base, ACAMERA_FSM2CTX_PTR( p_fsm )->isp_sequence, SENSOR_ISP_SEQUENCE_DEFAULT_FS_LIN_4EXP );
511             LOG( LOG_CRIT, "Setting FS_Lin_4Exp Binary Sequence." );
512         }
513 #endif
514 
515 #if defined( SENSOR_ISP_SEQUENCE_DEFAULT_FPGA_FS_LIN ) && ISP_HAS_FPGA_WRAPPER
516         LOG( LOG_CRIT, "Setting FS Lin Binary Sequence for FPGA\n" );
517         acamera_load_isp_sequence( 0, ACAMERA_FSM2CTX_PTR( p_fsm )->isp_sequence, SENSOR_ISP_SEQUENCE_DEFAULT_FPGA_FS_LIN );
518 #endif
519         break;
520     }
521 
522     case WDR_MODE_NATIVE:
523 #ifdef SENSOR_ISP_SEQUENCE_DEFAULT_NATIVE
524         acamera_load_sw_sequence( p_fsm->cmn.isp_base, ACAMERA_FSM2CTX_PTR( p_fsm )->isp_sequence, SENSOR_ISP_SEQUENCE_DEFAULT_NATIVE );
525 #endif
526         break;
527     }
528 }
529 
general_initialize(general_fsm_ptr_t p_fsm)530 void general_initialize( general_fsm_ptr_t p_fsm )
531 {
532 
533     // initialize isp sbus to get access to isp memory
534     // in api function REGISTERS_SOURCE_ID
535     acamera_sbus_init( &p_fsm->isp_sbus, sbus_isp );
536     p_fsm->isp_sbus.mask = SBUS_MASK_SAMPLE_8BITS | SBUS_MASK_ADDR_16BITS | SBUS_MASK_SAMPLE_32BITS;
537 
538 // API related
539 #ifdef COLOR_MODE_ID
540     p_fsm->api_color_mode = NORMAL;
541 #endif
542 #ifdef SCENE_MODE_ID
543     p_fsm->api_scene_mode = AUTO;
544 #endif
545 
546 #if defined REGISTERS_SOURCE_ID && defined SENSOR
547     p_fsm->api_reg_source = SENSOR;
548 #endif
549 
550     p_fsm->gamma2_enable = 0;
551 
552     general_set_wdr_mode( p_fsm );
553 
554     p_fsm->mask.repeat_irq_mask = ACAMERA_IRQ_MASK( ACAMERA_IRQ_FRAME_START ) | ACAMERA_IRQ_MASK( ACAMERA_IRQ_FRAME_END );
555     // Finally request interrupts
556     general_request_interrupt( p_fsm, p_fsm->mask.repeat_irq_mask );
557 }
558 
559 #if ISP_WDR_SWITCH
560 
adjust_exposure(general_fsm_ptr_t p_fsm,int32_t corr)561 static void adjust_exposure( general_fsm_ptr_t p_fsm, int32_t corr )
562 {
563 #if defined( ISP_HAS_CMOS_FSM )
564     acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_CMOS_ADJUST_EXP, &corr, sizeof( corr ) );
565 
566 #if defined( ISP_HAS_AE_BALANCED_FSM )
567     acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_AE_ADJUST_EXP, &corr, sizeof( corr ) );
568 #endif
569 
570     fsm_param_ae_info_t ae_info;
571     fsm_param_exposure_target_t exp;
572 
573     acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_AE_INFO, NULL, 0, &ae_info, sizeof( ae_info ) );
574 
575     exp.exposure_log2 = ae_info.exposure_log2;
576     exp.exposure_ratio = ae_info.exposure_ratio;
577     acamera_fsm_mgr_set_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_SET_EXPOSURE_TARGET, &exp, sizeof( exp ) );
578 
579     acamera_fsm_mgr_raise_event( ACAMERA_FSM2MGR_PTR( p_fsm ), event_id_exposure_changed );
580 #endif // ISP_HAS_CMOS_FSM
581 }
582 
583 #endif
584 
general_dynamic_gamma_update(general_fsm_ptr_t p_fsm)585 void general_dynamic_gamma_update( general_fsm_ptr_t p_fsm)
586 {
587  // update gamma here
588     const uint16_t *gamma_ev1 = _GET_USHORT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_GAMMA_EV1 );
589     const uint16_t *gamma_ev2 = _GET_USHORT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_GAMMA_EV2 );
590     if (gamma_ev1 == NULL || gamma_ev2 == NULL)
591         return;
592     const uint32_t gamma_len_ev1 = _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_GAMMA_EV1 );
593     const uint32_t gamma_len_ev2 = _GET_LEN( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_GAMMA_EV2 );
594 
595     uint32_t expected_gamma_size = ( ( ACAMERA_FR_GAMMA_RGB_MEM_SIZE / ( ACAMERA_FR_GAMMA_RGB_MEM_ARRAY_DATA_DATASIZE >> 3 ) >> 1 ) + 1 );
596 
597     if ( (gamma_len_ev1 == expected_gamma_size) && (gamma_len_ev2 == expected_gamma_size) ) {
598         fsm_param_ae_info_t ae_info;
599         uint32_t i = 0;
600         // get current exposure value
601         acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_AE_INFO, NULL, 0, &ae_info, sizeof( ae_info ) );
602         uint32_t exposure_log2 = ae_info.exposure_log2;
603         uint32_t ev1_thresh = _GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_GAMMA_THRESHOLD )[1] ;
604         uint32_t ev2_thresh = _GET_UINT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_GAMMA_THRESHOLD )[2] ;
605 
606         modulation_entry_32_t p_table[2];
607         p_table[0].x = ev1_thresh;
608         p_table[1].x = ev2_thresh;
609         // Use EV1 gamma curve if EV < EV1_THRESHOLD
610         // Use EV2 gamma curve if EV > EV2_THRESHOLD
611         // Do alpha blending between EV1 and EV2 when EV1_THRESHOLD < EV < EV2_THRESHOLD
612         for ( i = 0; i < expected_gamma_size; i++ ) {
613             p_table[0].y = gamma_ev1[i];
614             p_table[1].y = gamma_ev2[i];
615             // do alpha blending between two gammas for bin [i]
616             uint16_t gamma_bin = acamera_calc_modulation_u32( exposure_log2, p_table, 2);
617             LOG( LOG_DEBUG, "Gamma update: ev %d, ev1 %d, ev2 %d, ref_gamma_ev1 %d, ref_gamma_ev2 %d, result %d", exposure_log2, ev1_thresh, ev2_thresh, gamma_ev1[i], gamma_ev2[i], gamma_bin );
618             // update the hardware gamma curve for fr and ds
619             acamera_fr_gamma_rgb_mem_array_data_write( p_fsm->cmn.isp_base, i, gamma_bin );
620     #if ISP_HAS_DS1
621             acamera_ds1_gamma_rgb_mem_array_data_write( p_fsm->cmn.isp_base, i, gamma_bin );
622     #endif
623         }
624     } else {
625         // wrong gamma lut size
626         LOG( LOG_ERR, "wrong elements number in gamma_rgb_ev1 or ev2 -> ev1 size %d, ev2 size, expected %d", (int)gamma_len_ev1, (int)gamma_len_ev2, (int)expected_gamma_size );
627     }
628 }
629 
general_frame_start(general_fsm_ptr_t p_fsm)630 void general_frame_start( general_fsm_ptr_t p_fsm )
631 {
632     if ( p_fsm->gamma2_enable )
633         general_dynamic_gamma_update(p_fsm);
634 
635 #if ISP_WDR_SWITCH
636 
637     if ( p_fsm->wdr_auto_mode ) {
638         fsm_param_ae_hist_info_t ae_hist_info;
639         // init to NULL in case no AE configured and caused wrong access via wild pointer
640         ae_hist_info.fullhist = NULL;
641 
642         acamera_fsm_mgr_get_param( p_fsm->cmn.p_fsm_mgr, FSM_PARAM_GET_AE_HIST_INFO, NULL, 0, &ae_hist_info, sizeof( ae_hist_info ) );
643 
644         int i;
645         uint32_t exposure_edge = 0;
646         for ( i = ISP_FULL_HISTOGRAM_SIZE - 10; i < ISP_FULL_HISTOGRAM_SIZE; i++ ) {
647             exposure_edge += ae_hist_info.fullhist[i];
648         }
649         if ( p_fsm->wdr_mode == WDR_MODE_LINEAR ) {
650             for ( i = 0; i < 10; i++ ) {
651                 exposure_edge += ae_hist_info.fullhist[i];
652             }
653             exposure_edge = exposure_edge * 1000 / ae_hist_info.fullhist_sum;
654             if ( exposure_edge > WDR_SWITCH_THRESHOLD + WDR_SWITCH_THRESHOLD_HISTERESIS ) {
655                 if ( ++p_fsm->wdr_mode_frames > WDR_SWITCH_FRAMES ) {
656                     p_fsm->wdr_mode_req = WDR_AUTO_SWITCH_TO;
657                     p_fsm->wdr_mode_frames = 0;
658 
659                     adjust_exposure( p_fsm, -WDR_SWITCH_EXPOSURE_CORRECTION );
660                 }
661             } else {
662                 p_fsm->wdr_mode_frames = 0;
663             }
664         } else {
665             for ( i = 0; i < 50; i++ ) // in HDR mode histogramm is square rooted, so 10 is equal to 50 ~= (10/256)^2*256
666             {
667                 exposure_edge += ae_hist_info.fullhist[i];
668             }
669             exposure_edge = exposure_edge * 1000 / ae_hist_info.fullhist_sum;
670             if ( exposure_edge <= WDR_SWITCH_THRESHOLD - WDR_SWITCH_THRESHOLD_HISTERESIS ) {
671                 if ( ++p_fsm->wdr_mode_frames > WDR_SWITCH_FRAMES ) {
672                     p_fsm->wdr_mode_req = WDR_MODE_LINEAR;
673                     p_fsm->wdr_mode_frames = 0;
674 
675                     adjust_exposure( p_fsm, WDR_SWITCH_EXPOSURE_CORRECTION );
676                 }
677             } else {
678                 p_fsm->wdr_mode_frames = 0;
679             }
680         }
681     }
682 #endif
683 }
684 
general_frame_end(general_fsm_ptr_t p_fsm)685 void general_frame_end( general_fsm_ptr_t p_fsm )
686 {
687 #if ISP_WDR_SWITCH
688 
689     // Called on frame end
690     if ( p_fsm->wdr_mode_req != p_fsm->wdr_mode ) {
691         p_fsm->wdr_mode = p_fsm->wdr_mode_req;
692 
693         general_set_wdr_mode( p_fsm );
694 
695         p_fsm->wdr_mode_frames = 0;
696     }
697 #endif
698 }
699 
general_calc_fe_lut_output(general_fsm_ptr_t p_fsm,uint16_t val)700 uint32_t general_calc_fe_lut_output( general_fsm_ptr_t p_fsm, uint16_t val )
701 {
702     // calculation the output of the FE LUT(s) for input {val}
703     uint32_t result = val;
704 #if ISP_WDR_SWITCH
705     // New switching system
706     result = val;
707 #else
708 
709     // Standard old system - just use sqrt
710     result = acamera_sqrt32( val );
711 #endif
712     return result;
713 }
714 
general_calc_fe_lut_input(general_fsm_ptr_t p_fsm,uint16_t val)715 uint32_t general_calc_fe_lut_input( general_fsm_ptr_t p_fsm, uint16_t val )
716 {
717 // calculation the input of the FE LUT(s) for output {val}
718 #if ISP_WDR_SWITCH
719     return val;
720 #else
721     // Standard old system - just use sqrt
722     return val * val;
723 #endif
724 }
725