• 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 "awb_manual_fsm.h"
22 #include "acamera_3aalg_preset.h"
23 #include "sbuf.h"
24 
25 #ifdef LOG_MODULE
26 #undef LOG_MODULE
27 #define LOG_MODULE LOG_MODULE_AWB_MANUAL
28 #endif
29 
30 extern void awb_set_new_param( AWB_fsm_ptr_t p_fsm, sbuf_awb_t *p_sbuf_awb );
31 
AWB_fsm_clear(AWB_fsm_t * p_fsm)32 void AWB_fsm_clear( AWB_fsm_t *p_fsm )
33 {
34     p_fsm->curr_AWB_ZONES = MAX_AWB_ZONES;
35     p_fsm->awb_enabled = 0;
36     p_fsm->p_high = 50;
37     p_fsm->high_temp = 50;
38     p_fsm->low_temp = 50;
39     p_fsm->avg_GR = 128;
40     p_fsm->avg_GB = 128;
41     p_fsm->stable_avg_RG = D50_DEFAULT;
42     p_fsm->stable_avg_BG = D50_DEFAULT;
43     p_fsm->temperature_detected = 5000;
44     p_fsm->light_source_detected = AWB_LIGHT_SOURCE_D50;
45     p_fsm->light_source_candidate = AWB_LIGHT_SOURCE_D50;
46     p_fsm->detect_light_source_frames_count = 0;
47     p_fsm->max_temp = 10000;
48     p_fsm->min_temp = 2100;
49     p_fsm->max_temp_rg = 256;
50     p_fsm->max_temp_bg = 256;
51     p_fsm->min_temp_rg = 256;
52     p_fsm->min_temp_bg = 256;
53     p_fsm->roi = 65535;
54     p_fsm->switch_light_source_detect_frames_quantity = AWB_DLS_SWITCH_LIGHT_SOURCE_DETECT_FRAMES_QUANTITY;
55     p_fsm->switch_light_source_change_frames_quantity = AWB_DLS_SWITCH_LIGHT_SOURCE_CHANGE_FRAMES_QUANTITY;
56 
57     p_fsm->cur_result_gain_frame_id = 0;
58     p_fsm->pre_result_gain_frame_id = 0;
59 
60 	p_fsm->wb[0] = 527;
61     p_fsm->wb[1] = 271;
62     p_fsm->wb[2] = 271;
63     p_fsm->wb[3] = 436;
64 }
65 
AWB_request_interrupt(AWB_fsm_ptr_t p_fsm,system_fw_interrupt_mask_t mask)66 void AWB_request_interrupt( AWB_fsm_ptr_t p_fsm, system_fw_interrupt_mask_t mask )
67 {
68     acamera_isp_interrupts_disable( ACAMERA_FSM2MGR_PTR( p_fsm ) );
69     p_fsm->mask.irq_mask |= mask;
70     acamera_isp_interrupts_enable( ACAMERA_FSM2MGR_PTR( p_fsm ) );
71 }
72 
73 
74 #if AWB_MODE_ID
get_awb_idx(uint32_t value)75 static uint32_t get_awb_idx( uint32_t value )
76 {
77     uint32_t res = 0;
78     // acamera awb scenes are always located in a certain order
79     // this order is
80     // {AWB_DAY_LIGHT}
81     // {AWB_CLOUDY}
82     // {AWB_INCANDESCENT}
83     // {AWB_FLOURESCENT}
84     // {AWB_TWILIGHT}
85     // {AWB_SHADE}
86     // {AWB_WARM_FLOURESCENT}
87     switch ( value ) {
88     case AWB_DAY_LIGHT:
89         res = 0;
90         break;
91     case AWB_CLOUDY:
92         res = 1;
93         break;
94     case AWB_INCANDESCENT:
95         res = 2;
96         break;
97     case AWB_FLOURESCENT:
98         res = 3;
99         break;
100     case AWB_TWILIGHT:
101         res = 4;
102         break;
103     case AWB_SHADE:
104         res = 5;
105         break;
106     case AWB_WARM_FLOURESCENT:
107         res = 6;
108         break;
109     default:
110         LOG( LOG_ERR, "Invalid AWB scene index. Please check your calibrations" );
111         break;
112     }
113     return res;
114 }
115 #endif
116 
AWB_set_mode(AWB_fsm_ptr_t p_fsm,uint32_t mode)117 static int AWB_set_mode( AWB_fsm_ptr_t p_fsm, uint32_t mode )
118 {
119     int rc = 0;
120 
121 #if AWB_MODE_ID
122     switch ( mode ) {
123     case AWB_MANUAL:
124         p_fsm->awb_enabled = 0;
125         ACAMERA_FSM2CTX_PTR( p_fsm )
126             ->stab.global_manual_awb = ( 1 );
127         p_fsm->mode = mode;
128         break;
129 
130     case AWB_AUTO:
131         p_fsm->awb_enabled = 1;
132         ACAMERA_FSM2CTX_PTR( p_fsm )
133             ->stab.global_manual_awb = ( 0 );
134         p_fsm->mode = mode;
135         break;
136 
137     case AWB_DAY_LIGHT:
138     case AWB_CLOUDY:
139     case AWB_INCANDESCENT:
140     case AWB_FLOURESCENT:
141     case AWB_TWILIGHT:
142     case AWB_SHADE:
143     case AWB_WARM_FLOURESCENT: {
144         modulation_entry_t *_calibration_awb_scene_presets = _GET_MOD_ENTRY16_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_AWB_SCENE_PRESETS );
145         uint32_t i = get_awb_idx( mode );
146         p_fsm->awb_enabled = 0;
147         p_fsm->mode = mode;
148         // Then set the red and blue values
149         ACAMERA_FSM2CTX_PTR( p_fsm )
150             ->stab.global_manual_awb = ( 1 );
151         uint32_t cr = _calibration_awb_scene_presets[i].x;
152         uint32_t cb = _calibration_awb_scene_presets[i].y;
153         // Change 9 bit into 7 bit
154         ACAMERA_FSM2CTX_PTR( p_fsm )
155             ->stab.global_awb_red_gain = cr;
156         ACAMERA_FSM2CTX_PTR( p_fsm )
157             ->stab.global_awb_blue_gain = cb;
158         break;
159     }
160     default:
161         rc = -1;
162         break;
163     }
164 #endif
165 
166     return rc;
167 }
168 
AWB_fsm_init(void * fsm,fsm_init_param_t * init_param)169 void AWB_fsm_init( void *fsm, fsm_init_param_t *init_param )
170 {
171     AWB_fsm_t *p_fsm = (AWB_fsm_t *)fsm;
172     p_fsm->cmn.p_fsm_mgr = init_param->p_fsm_mgr;
173     p_fsm->cmn.isp_base = init_param->isp_base;
174     p_fsm->p_fsm_mgr = init_param->p_fsm_mgr;
175 
176     AWB_fsm_clear( p_fsm );
177 
178     awb_init( p_fsm );
179     awb_coeffs_write( p_fsm );
180     AWB_request_interrupt( p_fsm, ACAMERA_IRQ_MASK( ACAMERA_IRQ_AWB_STATS ) );
181 }
182 
AWB_fsm_get_param(void * fsm,uint32_t param_id,void * input,uint32_t input_size,void * output,uint32_t output_size)183 int AWB_fsm_get_param( void *fsm, uint32_t param_id, void *input, uint32_t input_size, void *output, uint32_t output_size )
184 {
185     int rc = 0;
186     AWB_fsm_t *p_fsm = (AWB_fsm_t *)fsm;
187 
188     switch ( param_id ) {
189     case FSM_PARAM_GET_AWB_INFO: {
190         if ( !output || output_size != sizeof( fsm_param_awb_info_t ) ) {
191             LOG( LOG_ERR, "Invalid param, param_id: %d.", param_id );
192             rc = -1;
193             break;
194         }
195 
196         fsm_param_awb_info_t *p_info = (fsm_param_awb_info_t *)output;
197 
198         system_memcpy( p_info->wb_log2, p_fsm->wb_log2, sizeof( p_info->wb_log2 ) );
199         system_memcpy( p_info->awb_warming, p_fsm->awb_warming, sizeof( p_info->awb_warming ) );
200 
201         p_info->temperature_detected = p_fsm->temperature_detected;
202         p_info->p_high = p_fsm->p_high;
203         p_info->light_source_candidate = p_fsm->light_source_candidate;
204         p_info->avg_GR = p_fsm->avg_GR;
205         p_info->avg_GB = p_fsm->avg_GB;
206         p_info->rg_coef = p_fsm->rg_coef;
207         p_info->bg_coef = p_fsm->bg_coef;
208         p_info->result_gain_frame_id = p_fsm->pre_result_gain_frame_id;
209 
210         break;
211     }
212 
213     case FSM_PARAM_GET_AWB_MODE:
214         if ( !output || output_size != sizeof( uint32_t ) ) {
215             LOG( LOG_ERR, "Invalid param, param_id: %d.", param_id );
216             rc = -1;
217             break;
218         }
219 
220 #if AWB_MODE_ID
221         if ( !ACAMERA_FSM2CTX_PTR( p_fsm )->stab.global_manual_awb ) {
222             *(uint32_t *)output = AWB_AUTO;
223         } else {
224             *(uint32_t *)output = p_fsm->mode;
225         }
226 #endif
227 
228         break;
229 
230     default:
231         rc = -1;
232         break;
233     }
234 
235     return rc;
236 }
237 
AWB_fsm_set_param(void * fsm,uint32_t param_id,void * input,uint32_t input_size)238 int AWB_fsm_set_param( void *fsm, uint32_t param_id, void *input, uint32_t input_size )
239 {
240     int rc = 0;
241     AWB_fsm_t *p_fsm = (AWB_fsm_t *)fsm;
242 
243     switch ( param_id ) {
244     case FSM_PARAM_SET_AWB_NEW_PARAM: {
245         if ( !input || input_size != sizeof( sbuf_awb_t ) ) {
246             LOG( LOG_ERR, "Invalid param, param_id: %d.", param_id );
247             rc = -1;
248             break;
249         }
250 
251         awb_set_new_param( p_fsm, (sbuf_awb_t *)input );
252 
253         break;
254     }
255 
256     case FSM_PARAM_SET_AWB_MODE:
257         if ( !input || input_size != sizeof( uint32_t ) ) {
258             LOG( LOG_ERR, "Invalid param, param_id: %d.", param_id );
259             rc = -1;
260             break;
261         }
262 
263         rc = AWB_set_mode( p_fsm, *(uint32_t *)input );
264 
265         break;
266 
267     case FSM_PARAM_SET_AWB_INFO: {
268         if ( !input || input_size != sizeof( fsm_param_awb_info_t ) ) {
269             LOG( LOG_ERR, "Invalid param, param_id: %d.", param_id );
270             rc = -1;
271             break;
272         }
273 
274         fsm_param_awb_info_t *p_info = (fsm_param_awb_info_t *)input;
275 
276         if ( p_info->flag & AWB_INFO_TEMPERATURE_DETECTED ) {
277             p_fsm->temperature_detected = p_info->temperature_detected;
278         }
279 
280         if ( p_info->flag & AWB_INFO_P_HIGH ) {
281             p_fsm->p_high = p_info->p_high;
282         }
283 
284         if ( p_info->flag & AWB_INFO_LIGHT_SOURCE_CANDIDATE ) {
285             p_fsm->light_source_candidate = p_info->light_source_candidate;
286         }
287 
288         break;
289     }
290 
291     case FSM_PARAM_SET_AWB_ZONE_WEIGHT: {
292         if (!input || input_size == 0) {
293             LOG(LOG_ERR, "Invalid param. param id: %d.", param_id);
294             rc = -1;
295             break;
296         }
297 
298         unsigned char *u_awb_wg = input;
299 
300         rc = awb_set_zone_weight(p_fsm, u_awb_wg);
301         if (rc != 0)
302             LOG(LOG_ERR, "Failed to set ae zone weight");
303 
304         break;
305     }
306 	case FSM_PARAM_SET_AWB_PRESET:
307         if ( !input || input_size != sizeof( isp_awb_preset_t ) ) {
308             LOG( LOG_ERR, "Invalid param, param_id: %d.", param_id );
309             rc = -1;
310             break;
311         }
312 
313         isp_awb_preset_t *p_new = (isp_awb_preset_t *)input;
314         p_fsm->wb_log2[0] = p_new->wb_log2[0];
315         p_fsm->wb_log2[1] = p_new->wb_log2[1];
316         p_fsm->wb_log2[2] = p_new->wb_log2[2];
317         p_fsm->wb_log2[3] = p_new->wb_log2[3];
318 
319         p_fsm->wb[0] = p_new->wb[0];
320         p_fsm->wb[1] = p_new->wb[1];
321         p_fsm->wb[2] = p_new->wb[2];
322         p_fsm->wb[3] = p_new->wb[3];
323 		acamera_isp_white_balance_gain_00_write( p_fsm->cmn.isp_base, p_fsm->wb[0]);
324 		acamera_isp_white_balance_gain_01_write( p_fsm->cmn.isp_base, p_fsm->wb[1]);
325 		acamera_isp_white_balance_gain_10_write( p_fsm->cmn.isp_base, p_fsm->wb[2]);
326 		acamera_isp_white_balance_gain_11_write( p_fsm->cmn.isp_base, p_fsm->wb[3]);
327 
328 		break;
329     default:
330         rc = -1;
331         break;
332     }
333 
334     return rc;
335 }
336 
AWB_fsm_process_event(AWB_fsm_t * p_fsm,event_id_t event_id)337 uint8_t AWB_fsm_process_event( AWB_fsm_t *p_fsm, event_id_t event_id )
338 {
339     uint8_t b_event_processed = 0;
340     switch ( event_id ) {
341     default:
342         break;
343     case event_id_frame_end:
344         AWB_request_interrupt( p_fsm, ACAMERA_IRQ_MASK( ACAMERA_IRQ_AWB_STATS ) );
345         b_event_processed = 1;
346 
347         break;
348 
349     case event_id_awb_stats_ready:
350         AWB_request_interrupt( p_fsm, ACAMERA_IRQ_MASK( ACAMERA_IRQ_FRAME_END ) );
351         b_event_processed = 1;
352 
353         break;
354 
355     case event_id_awb_result_ready:
356         awb_update_ccm( p_fsm );
357         awb_normalise( p_fsm );
358         fsm_raise_event( p_fsm, event_id_WB_matrix_ready );
359         b_event_processed = 1;
360         break;
361     }
362 
363     return b_event_processed;
364 }
365