• 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 
22 #include "acamera_math.h"
23 #include "acamera_math.h"
24 #include "acamera_calibrations.h"
25 #include "acamera_command_api.h"
26 #include "matrix_yuv_fsm.h"
27 
28 #ifdef LOG_MODULE
29 #undef LOG_MODULE
30 #define LOG_MODULE LOG_MODULE_MATRIX_YUV
31 #endif
32 
vector_vector_add(int16_t * v1,int16_t * v2,int dim1)33 static void vector_vector_add( int16_t *v1, int16_t *v2, int dim1 )
34 {
35     int i;
36     for ( i = 0; i < dim1; ++i ) {
37         v2[i] = v1[i] + v2[i];
38     }
39 }
matrix_vector_multiply(int16_t * m,int16_t * v)40 static void matrix_vector_multiply( int16_t *m, int16_t *v )
41 {
42     int i, j;
43     const int dim1 = 3;
44     const int dim2 = 3;
45     int16_t result[3];
46     for ( i = 0; i < dim1; ++i ) {
47         int32_t temp = 0;
48         for ( j = 0; j < dim2; ++j )
49             temp += ( ( (int32_t)m[i * dim2 + j] * v[j] )  );
50         result[i] = (uint16_t)( ( temp + ( 1 << 7 ) ) >> 8 );
51     }
52     for ( i = 0; i < dim1; ++i )
53         v[i] = ACAMERA_MAX( -1023, ACAMERA_MIN( 1023, result[i] ) );
54 }
matrix_matrix_multiply(int16_t * a1,int16_t * a2)55 static void matrix_matrix_multiply( int16_t *a1, int16_t *a2 )
56 {
57     int i, j, k;
58     const int dim1 = 3;
59     const int dim2 = 3;
60     const int dim3 = 3;
61     int16_t result[3 * 3];
62 
63     memset( result, 0, sizeof( result ) );
64 
65     for ( i = 0; i < dim1; ++i ) {
66         for ( j = 0; j < dim3; ++j ) {
67             int32_t temp = 0;
68             for ( k = 0; k < dim2; ++k )
69                 temp += ( ( (int32_t)a1[i * dim2 + k] * a2[k * dim3 + j] ) );
70             result[i * dim3 + j] = (int16_t)( ( temp + ( 1 << 7 ) ) >> 8 );
71         }
72     }
73     for ( i = 0; i < 9; i++ )
74         a2[i] = result[i]; //ACAMERA_MAX(-511,ACAMERA_MIN(512,result[i]));
75 }
76 
color_matrix_complement_to_direct_16(int16_t v)77 static uint16_t color_matrix_complement_to_direct_16( int16_t v )
78 {
79     uint16_t result;
80 
81     if ( v >= 0 )
82         result = v;
83     else {
84         result = -v;
85         result |= ( 1 << 15 );
86     }
87     return result;
88 }
89 
matrix_yuv_clip(int16_t * input)90 static void matrix_yuv_clip( int16_t *input )
91 {
92     uint8_t i;
93     int16_t val;
94     for ( i = 0; i < 9; i++ ) {
95         val = ACAMERA_MAX( -511, ACAMERA_MIN( 512, input[i] ) );
96         input[i] = color_matrix_complement_to_direct_16( val );
97     }
98     for ( i = 9; i < 12; i++ ) {
99         val = ACAMERA_MAX( -1023, ACAMERA_MIN( 1023, input[i] ) );
100         input[i] = val;
101         if ( val < 0 ) {
102             val = 2048 + val;
103             input[i] = val;
104         }
105     }
106 }
matrix_yuv_fr_coefft_write_to_hardware(matrix_yuv_fsm_t * p_fsm)107 static void matrix_yuv_fr_coefft_write_to_hardware( matrix_yuv_fsm_t *p_fsm )
108 {
109     // set U and V channel to 0 in black and white mode
110     int i = 0;
111     if ( p_fsm->color_mode == BLACK_AND_WHITE ) {
112        for ( i = 3; i < 9; i++ ) {
113            p_fsm->fr_composite_yuv_matrix[i] = 0;
114        }
115        p_fsm->fr_composite_yuv_matrix[9] = 0;
116        p_fsm->fr_composite_yuv_matrix[10] = 512;
117        p_fsm->fr_composite_yuv_matrix[11] = 512;
118     }
119 
120     int16_t *yuv_matrix = p_fsm->fr_composite_yuv_matrix;
121     acamera_isp_fr_cs_conv_coefft_11_write( p_fsm->cmn.isp_base, yuv_matrix[0] );
122     acamera_isp_fr_cs_conv_coefft_12_write( p_fsm->cmn.isp_base, yuv_matrix[1] );
123     acamera_isp_fr_cs_conv_coefft_13_write( p_fsm->cmn.isp_base, yuv_matrix[2] );
124     acamera_isp_fr_cs_conv_coefft_21_write( p_fsm->cmn.isp_base, yuv_matrix[3] );
125     acamera_isp_fr_cs_conv_coefft_22_write( p_fsm->cmn.isp_base, yuv_matrix[4] );
126     acamera_isp_fr_cs_conv_coefft_23_write( p_fsm->cmn.isp_base, yuv_matrix[5] );
127     acamera_isp_fr_cs_conv_coefft_31_write( p_fsm->cmn.isp_base, yuv_matrix[6] );
128     acamera_isp_fr_cs_conv_coefft_32_write( p_fsm->cmn.isp_base, yuv_matrix[7] );
129     acamera_isp_fr_cs_conv_coefft_33_write( p_fsm->cmn.isp_base, yuv_matrix[8] );
130     acamera_isp_fr_cs_conv_coefft_o1_write( p_fsm->cmn.isp_base, yuv_matrix[9] );
131     acamera_isp_fr_cs_conv_coefft_o2_write( p_fsm->cmn.isp_base, yuv_matrix[10] );
132     acamera_isp_fr_cs_conv_coefft_o3_write( p_fsm->cmn.isp_base, yuv_matrix[11] );
133     acamera_isp_fr_cs_conv_enable_matrix_write( p_fsm->cmn.isp_base, 1 );
134     switch ( p_fsm->fr_pipe_output_format ) {
135     case PIPE_OUT_YUV422:
136         acamera_isp_fr_cs_conv_enable_filter_write( p_fsm->cmn.isp_base, 1 );
137         acamera_isp_fr_cs_conv_enable_horizontal_downsample_write( p_fsm->cmn.isp_base, 1 );
138         acamera_isp_fr_cs_conv_enable_vertical_downsample_write( p_fsm->cmn.isp_base, 0 );
139 
140         break;
141     case PIPE_OUT_YUV420:
142         acamera_isp_fr_cs_conv_enable_filter_write( p_fsm->cmn.isp_base, 1 );
143         acamera_isp_fr_cs_conv_enable_horizontal_downsample_write( p_fsm->cmn.isp_base, 1 );
144         acamera_isp_fr_cs_conv_enable_vertical_downsample_write( p_fsm->cmn.isp_base, 1 );
145 
146         break;
147     case PIPE_OUT_RGB:
148         acamera_isp_fr_cs_conv_coefft_11_write( p_fsm->cmn.isp_base, yuv_matrix[6] );
149         acamera_isp_fr_cs_conv_coefft_12_write( p_fsm->cmn.isp_base, yuv_matrix[7] );
150         acamera_isp_fr_cs_conv_coefft_13_write( p_fsm->cmn.isp_base, yuv_matrix[8] );
151         acamera_isp_fr_cs_conv_coefft_21_write( p_fsm->cmn.isp_base, yuv_matrix[3] );
152         acamera_isp_fr_cs_conv_coefft_22_write( p_fsm->cmn.isp_base, yuv_matrix[4] );
153         acamera_isp_fr_cs_conv_coefft_23_write( p_fsm->cmn.isp_base, yuv_matrix[5] );
154         acamera_isp_fr_cs_conv_coefft_31_write( p_fsm->cmn.isp_base, yuv_matrix[0] );
155         acamera_isp_fr_cs_conv_coefft_32_write( p_fsm->cmn.isp_base, yuv_matrix[1] );
156         acamera_isp_fr_cs_conv_coefft_33_write( p_fsm->cmn.isp_base, yuv_matrix[2] );
157         acamera_isp_fr_cs_conv_enable_filter_write( p_fsm->cmn.isp_base, 0 );
158         acamera_isp_fr_cs_conv_enable_horizontal_downsample_write( p_fsm->cmn.isp_base, 0 );
159         acamera_isp_fr_cs_conv_enable_vertical_downsample_write( p_fsm->cmn.isp_base, 0 );
160 
161         break;
162     case PIPE_OUT_YUV444:
163         acamera_isp_fr_cs_conv_enable_filter_write( p_fsm->cmn.isp_base, 0 );
164         acamera_isp_fr_cs_conv_enable_horizontal_downsample_write( p_fsm->cmn.isp_base, 0 );
165         acamera_isp_fr_cs_conv_enable_vertical_downsample_write( p_fsm->cmn.isp_base, 0 );
166 
167         break;
168     default:
169         acamera_isp_fr_cs_conv_enable_filter_write( p_fsm->cmn.isp_base, 0 );
170         acamera_isp_fr_cs_conv_enable_horizontal_downsample_write( p_fsm->cmn.isp_base, 0 );
171         acamera_isp_fr_cs_conv_enable_vertical_downsample_write( p_fsm->cmn.isp_base, 0 );
172         break;
173     }
174 }
175 
matrix_yuv_ds_write_to_hardware(matrix_yuv_fsm_t * p_fsm)176 static void matrix_yuv_ds_write_to_hardware( matrix_yuv_fsm_t *p_fsm )
177 {
178     // set U and V channel to 0 in black and white mode
179     int i = 0;
180     if ( p_fsm->color_mode == BLACK_AND_WHITE ) {
181        for ( i = 3; i < 9; i++ ) {
182            p_fsm->fr_composite_yuv_matrix[i] = 0;
183        }
184        p_fsm->fr_composite_yuv_matrix[9] = 0;
185        p_fsm->fr_composite_yuv_matrix[10] = 512;
186        p_fsm->fr_composite_yuv_matrix[11] = 512;
187     }
188 
189 #if ISP_HAS_DS1
190     int16_t *yuv_matrix = p_fsm->ds1_composite_yuv_matrix;
191     acamera_isp_ds1_cs_conv_coefft_11_write( p_fsm->cmn.isp_base, yuv_matrix[0] );
192     acamera_isp_ds1_cs_conv_coefft_12_write( p_fsm->cmn.isp_base, yuv_matrix[1] );
193     acamera_isp_ds1_cs_conv_coefft_13_write( p_fsm->cmn.isp_base, yuv_matrix[2] );
194     acamera_isp_ds1_cs_conv_coefft_21_write( p_fsm->cmn.isp_base, yuv_matrix[3] );
195     acamera_isp_ds1_cs_conv_coefft_22_write( p_fsm->cmn.isp_base, yuv_matrix[4] );
196     acamera_isp_ds1_cs_conv_coefft_23_write( p_fsm->cmn.isp_base, yuv_matrix[5] );
197     acamera_isp_ds1_cs_conv_coefft_31_write( p_fsm->cmn.isp_base, yuv_matrix[6] );
198     acamera_isp_ds1_cs_conv_coefft_32_write( p_fsm->cmn.isp_base, yuv_matrix[7] );
199     acamera_isp_ds1_cs_conv_coefft_33_write( p_fsm->cmn.isp_base, yuv_matrix[8] );
200     acamera_isp_ds1_cs_conv_coefft_o1_write( p_fsm->cmn.isp_base, yuv_matrix[9] );
201     acamera_isp_ds1_cs_conv_coefft_o2_write( p_fsm->cmn.isp_base, yuv_matrix[10] );
202     acamera_isp_ds1_cs_conv_coefft_o3_write( p_fsm->cmn.isp_base, yuv_matrix[11] );
203     acamera_isp_ds1_cs_conv_enable_matrix_write( p_fsm->cmn.isp_base, 1 );
204     switch ( p_fsm->ds1_pipe_output_format ) {
205     case PIPE_OUT_YUV422:
206         acamera_isp_ds1_cs_conv_enable_filter_write( p_fsm->cmn.isp_base, 1 );
207         acamera_isp_ds1_cs_conv_enable_horizontal_downsample_write( p_fsm->cmn.isp_base, 1 );
208         acamera_isp_ds1_cs_conv_enable_vertical_downsample_write( p_fsm->cmn.isp_base, 0 );
209         break;
210     case PIPE_OUT_YUV420:
211         acamera_isp_ds1_cs_conv_enable_filter_write( p_fsm->cmn.isp_base, 1 );
212         acamera_isp_ds1_cs_conv_enable_horizontal_downsample_write( p_fsm->cmn.isp_base, 1 );
213         acamera_isp_ds1_cs_conv_enable_vertical_downsample_write( p_fsm->cmn.isp_base, 1 );
214         break;
215     case PIPE_OUT_RGB:
216         acamera_isp_ds1_cs_conv_coefft_11_write( p_fsm->cmn.isp_base, yuv_matrix[6] );
217         acamera_isp_ds1_cs_conv_coefft_12_write( p_fsm->cmn.isp_base, yuv_matrix[7] );
218         acamera_isp_ds1_cs_conv_coefft_13_write( p_fsm->cmn.isp_base, yuv_matrix[8] );
219         acamera_isp_ds1_cs_conv_coefft_21_write( p_fsm->cmn.isp_base, yuv_matrix[3] );
220         acamera_isp_ds1_cs_conv_coefft_22_write( p_fsm->cmn.isp_base, yuv_matrix[4] );
221         acamera_isp_ds1_cs_conv_coefft_23_write( p_fsm->cmn.isp_base, yuv_matrix[5] );
222         acamera_isp_ds1_cs_conv_coefft_31_write( p_fsm->cmn.isp_base, yuv_matrix[0] );
223         acamera_isp_ds1_cs_conv_coefft_32_write( p_fsm->cmn.isp_base, yuv_matrix[1] );
224         acamera_isp_ds1_cs_conv_coefft_33_write( p_fsm->cmn.isp_base, yuv_matrix[2] );
225         acamera_isp_ds1_cs_conv_enable_filter_write( p_fsm->cmn.isp_base, 0 );
226         acamera_isp_ds1_cs_conv_enable_horizontal_downsample_write( p_fsm->cmn.isp_base, 0 );
227         acamera_isp_ds1_cs_conv_enable_vertical_downsample_write( p_fsm->cmn.isp_base, 0 );
228         break;
229     case PIPE_OUT_YUV444:
230         acamera_isp_ds1_cs_conv_enable_filter_write( p_fsm->cmn.isp_base, 0 );
231         acamera_isp_ds1_cs_conv_enable_horizontal_downsample_write( p_fsm->cmn.isp_base, 0 );
232         acamera_isp_ds1_cs_conv_enable_vertical_downsample_write( p_fsm->cmn.isp_base, 0 );
233         break;
234     default:
235         acamera_isp_ds1_cs_conv_enable_filter_write( p_fsm->cmn.isp_base, 0 );
236         acamera_isp_ds1_cs_conv_enable_horizontal_downsample_write( p_fsm->cmn.isp_base, 0 );
237         acamera_isp_ds1_cs_conv_enable_vertical_downsample_write( p_fsm->cmn.isp_base, 0 );
238         break;
239     }
240 #endif
241 }
242 
matrix_compute_brightness(uint8_t brightness_strength,int16_t * p_matrix)243 static void matrix_compute_brightness( uint8_t brightness_strength, int16_t *p_matrix )
244 {
245 
246     /*{
247        Chainging Brigntess in the RGB domain.So apply the same shift to all the Colors.
248        In Case if the PIPE output is YUV,the YUC transform matrix will apply the offset only on to the Y channel
249        and for the U and V the co-eff of you YUV transform matrix is such that it will add up to zero.
250         The idea here is to change Brigtness in RGB
251         by changing offset for RGB
252           0x100   0          0             brightness_shift
253           0     0x100     0              brightness_shift
254           0       0     0x100           brightness_shift
255     }
256     */
257     int16_t brightness_shift = 0;
258     uint8_t i = 0;
259     if ( brightness_strength < 128 ) {
260         brightness_shift = -( ( 0x3FF * ( 127 - brightness_strength ) ) / 127 );
261     } else {
262         brightness_shift = ( 0x3FF * ( brightness_strength - 128 ) ) / 127;
263     }
264     for ( i = 0; i < 12; i++ )
265         p_matrix[i] = 0x00;
266     for ( i = 0; i < 9; i += 4 ) {
267         p_matrix[i] = 0x100;
268     }
269     p_matrix[9] = brightness_shift;
270     p_matrix[10] = brightness_shift;
271     p_matrix[11] = brightness_shift;
272 }
matrix_compute_saturation(uint8_t saturation_strength,int16_t * p_matrix,matrix_yuv_fsm_t * p_fsm)273 static void matrix_compute_saturation( uint8_t saturation_strength, int16_t *p_matrix, matrix_yuv_fsm_t *p_fsm )
274 {
275     /*{
276         The idea here is to change Saturation only by changing the U anv V channels.
277         But we are applying on RGB
278         X25 = RGB2YUV\([1 0 0; 0 2 0; 0 0 2]*RGB2YUV)
279         X = (X25-eye(3))
280         That is the saturation_transfrom_mat.
281     }*/
282     int16_t saturation_transfrom_mat[12] = {179, -149, -28, -76, 104, -29, -75, -148, 226, 0, 0, 0};
283     int16_t saturation_scale = 0;
284     if ( saturation_strength < 128 )
285         saturation_scale = 256 * ( saturation_strength - 128 ) / 128;
286     else
287         saturation_scale = ( 256 * ( (uint16_t)saturation_strength - 128 ) ) / 128;
288     uint8_t i = 0;
289     for ( i = 0; i < 12; i++ )
290         p_matrix[i] = ( saturation_transfrom_mat[i] * saturation_scale ) >> 8;
291     p_matrix[0] += 0x100;
292     p_matrix[4] += 0x100;
293     p_matrix[8] += 0x100;
294 }
matrix_compute_contrast(uint8_t contrast_strength,int16_t * p_matrix)295 static void matrix_compute_contrast( uint8_t contrast_strength, int16_t *p_matrix )
296 {
297     /*{
298         The idea here is to change Contrast,by scaling  RGB space and changing offset
299           contrast_scale   0             0                contrast_shift
300           0             contrast_scale     0                        0
301           0                0         contrast_scale                 0
302     }
303     */
304     int16_t contrast_scale = 0;
305     int16_t contrast_shift = 0;
306     uint8_t i = 0;
307     if ( contrast_strength <= 128 ) {
308         contrast_scale = ( 256 * contrast_strength ) / 128;
309         contrast_shift = 512 - ( ( 512 * contrast_strength ) / 128 );
310     } else {
311         contrast_scale = 256 + ( ( 256 * ( contrast_strength - 128 ) ) / 128 );
312         contrast_shift = ( 512 * ( 128 - contrast_strength ) ) / 128;
313     }
314     for ( i = 0; i < 12; i++ )
315         p_matrix[i] = 0;
316 
317     p_matrix[0] = contrast_scale;
318     p_matrix[4] = contrast_scale;
319     p_matrix[8] = contrast_scale;
320     p_matrix[9] = contrast_shift;
321     p_matrix[10] = contrast_shift;
322     p_matrix[11] = contrast_shift;
323 }
324 
325 #define MUL_16_16( a, b ) ( ( int16_t )( ( (int32_t)a * (int32_t)b ) >> 15 ) )
get_cosine(int16_t theta,int16_t * p_hue_COS_TABLES)326 static int16_t get_cosine( int16_t theta, int16_t *p_hue_COS_TABLES )
327 {
328     int16_t result = 0;
329     int8_t index = 0;
330     int8_t sign = 0;
331     if ( theta >= 0 && theta <= 90 ) {
332         index = theta;
333         sign = 1;
334     } else if ( theta > 90 && theta <= 180 ) {
335         sign = -1;
336         index = 180 - theta;
337     } else if ( theta < 0 && theta >= -90 ) {
338         sign = 1;
339         index = -theta;
340     } else if ( theta < -90 && theta >= -180 ) {
341         sign = -1;
342         index = 180 + theta;
343     }
344     result = sign * ( p_hue_COS_TABLES[index] + ( 90 - index ) );
345     return result;
346 }
get_sine(int16_t theta,int16_t * p_hue_COS_TABLES)347 static int16_t get_sine( int16_t theta, int16_t *p_hue_COS_TABLES )
348 {
349     int16_t result = 0;
350     int8_t index = 0;
351     int8_t sign = 0;
352     if ( theta >= 0 && theta <= 90 ) {
353         index = 90 - theta;
354         sign = 1;
355     } else if ( theta > 90 && theta <= 180 ) {
356         sign = 1;
357         index = theta - 90;
358     } else if ( theta < -90 && theta >= -180 ) {
359         sign = -1;
360         index = -( theta + 90 );
361     } else if ( theta < 0 && theta >= -90 ) {
362         sign = -1;
363         index = 90 + theta;
364     }
365     result = sign * ( p_hue_COS_TABLES[index] + ( 90 - index ) );
366     return result;
367 }
matrix_compute_hue_saturation(uint16_t value,int16_t * p_matrix)368 static void matrix_compute_hue_saturation( uint16_t value, int16_t *p_matrix )
369 {
370     /*
371   The Hue Correction is applied in YIQ domain.RGB->YIQ->HUE_COORECTION->RGB
372   The entire transform matrix   YIQ2RGB*Hue_Corr*RGB2YIQ(Image),is simplified into one matrix, and given by the hue coeff which is 3x3 matrix and each column has 3 coeff
373   in the form  a0+b0*cosine+c0*sine.
374   All the tables used here are Q14 format.Results in Q8 format.
375 
376 */
377     int16_t HUE_COSTABLE[] = {
378         16294, 16293, 16286, 16275, 16258, 16237, 16210, 16179, 16143, 16101, 16055, 16004, 15948, 15887, 15821, 15751,
379         15675, 15595, 15510, 15420, 15326, 15227, 15123, 15015, 14902, 14784, 14662, 14535, 14404, 14269, 14129, 13985,
380         13836, 13684, 13527, 13366, 13201, 13032, 12859, 12682, 12501, 12316, 12128, 11935, 11740, 11540, 11337, 11131,
381         10921, 10708, 10491, 10272, 10049, 9823, 9594, 9362, 9128, 8890, 8650, 8407, 8162, 7914, 7664, 7411, 7156, 6899,
382         6640, 6379, 6116, 5851, 5584, 5315, 5045, 4773, 4500, 4225, 3950, 3673, 3394, 3115, 2835, 2554, 2272, 1990, 1707,
383         1423, 1139, 854, 570, 285, 0,
384     };
385     int16_t hue_coeff[] = {
386         4899, 11485, 2748, 9617, -9617, 5395, 1868, -1868, -8144, 4899, -4899, -5376, 9617, 6767, 581, 1868, -1868, 4795,
387         4899, -4899, 20473, 9617, -9617, -17143, 1868, 14516, -3329,
388     };
389     int16_t theta = (int16_t)value;
390     int16_t cosine = 0;
391     int16_t sine = 0;
392     uint8_t _index = 0;
393     const int16_t identity_matrix[12] = {0x0100, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x0000, 0x0000, 0x0100, 0, 0, 0};
394     for ( _index = 0; _index < 12; _index++ )
395         p_matrix[_index] = identity_matrix[_index];
396 
397     theta = theta - 180;
398     cosine = get_cosine( theta, HUE_COSTABLE );
399     sine = get_sine( theta, HUE_COSTABLE );
400     for ( _index = 0; _index < 9; _index++ ) {
401         p_matrix[_index] = ( hue_coeff[0 + ( _index * 3 )] >> 1 ) + MUL_16_16( hue_coeff[1 + ( _index * 3 )], cosine ) + MUL_16_16( hue_coeff[2 + ( _index * 3 )], sine );
402         p_matrix[_index] = p_matrix[_index] >> 5; //(Q13->Q8)
403         if (theta == 0)
404            p_matrix[_index] = identity_matrix[_index];
405     }
406 }
matrix_compute_color_mode(uint16_t mode,int16_t * p_color_mode_matrix,matrix_yuv_fsm_t * p_fsm)407 static void matrix_compute_color_mode( uint16_t mode, int16_t *p_color_mode_matrix, matrix_yuv_fsm_t *p_fsm )
408 {
409     const int16_t identity_matrix[12] = {0x0100, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x0000, 0x0000, 0x0100, 0, 0, 0};
410     uint8_t i;
411     for ( i = 0; i < 12; i++ )
412         p_color_mode_matrix[i] = identity_matrix[i];
413 #ifdef COLOR_MODE_ID
414     uint8_t j;
415 
416     switch ( mode ) {
417     case NORMAL:
418         for ( i = 0; i < 3; i++ ) {
419             for ( j = 0; j < 3; j++ ) {
420                 if ( i == j )
421                     p_color_mode_matrix[3 * i + j] = 0x100;
422                 else
423                     p_color_mode_matrix[3 * i + j] = 0;
424             }
425         }
426         for ( i = 9; i < 12; i++ )
427             p_color_mode_matrix[i] = 0;
428         break;
429     case BLACK_AND_WHITE:
430         for ( i = 0; i < 3; i++ ) {
431             for ( j = 0; j < 3; j++ ) {
432                 p_color_mode_matrix[3 * i + j] = p_fsm->rgb2yuv_matrix[j];
433             }
434         }
435         for ( i = 9; i < 12; i++ )
436             p_color_mode_matrix[i] = 0;
437         break;
438     case NEGATIVE:
439         for ( i = 0; i < 3; i++ ) {
440             for ( j = 0; j < 3; j++ ) {
441                 if ( i == j )
442                     p_color_mode_matrix[3 * i + j] = -0x100;
443                 else
444                     p_color_mode_matrix[3 * i + j] = 0;
445             }
446         }
447         for ( i = 9; i < 12; i++ )
448             p_color_mode_matrix[i] = 0x3ff;
449         break;
450     case SEPIA: // get values from IQ:
451         p_color_mode_matrix[0] = 0x75;
452         p_color_mode_matrix[1] = 0x15;
453         p_color_mode_matrix[2] = 0x05;
454         p_color_mode_matrix[3] = 0x20;
455         p_color_mode_matrix[4] = 0x70;
456         p_color_mode_matrix[5] = 0x05;
457         p_color_mode_matrix[6] = 0x20;
458         p_color_mode_matrix[7] = 0x20;
459         p_color_mode_matrix[8] = 0x05;
460         p_color_mode_matrix[9] = 0xD3;
461         p_color_mode_matrix[10] = 0x0;
462         p_color_mode_matrix[11] = 0x0;
463         break;
464     case VIVID:
465         for ( i = 0; i < 3; i++ ) {
466             for ( j = 0; j < 3; j++ ) {
467                 if ( i == j )
468                     p_color_mode_matrix[3 * i + j] = 0x100;
469                 else
470                     p_color_mode_matrix[3 * i + j] = 0;
471             }
472         }
473         for ( i = 9; i < 12; i++ )
474             p_color_mode_matrix[i] = 0;
475         break;
476     default:
477         break;
478     }
479 #endif
480 }
update_composite_matrix(int16_t * inp1,int16_t * res)481 static void update_composite_matrix( int16_t *inp1, int16_t *res )
482 {
483     matrix_matrix_multiply( inp1, res );
484     matrix_vector_multiply( inp1, res + 9 );
485 
486     vector_vector_add( inp1 + 9, res + 9, 3 );
487 }
compute_transfrom_matrix(matrix_yuv_fsm_t * p_fsm,int16_t * final_composite_yuv_matrix,uint8_t format)488 static void compute_transfrom_matrix( matrix_yuv_fsm_t *p_fsm, int16_t *final_composite_yuv_matrix, uint8_t format )
489 {
490     uint8_t i = 0;
491     uint16_t identity_matrix[12] = {0x0100, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x0000, 0x0000, 0x0100, 0, 0, 0};
492     for ( i = 0; i < 12; i++ ) {
493         final_composite_yuv_matrix[i] = identity_matrix[i];
494     }
495     update_composite_matrix( p_fsm->color_mode_matrix, final_composite_yuv_matrix );
496     update_composite_matrix( p_fsm->hue_correction_matrix, final_composite_yuv_matrix );
497     update_composite_matrix( p_fsm->saturation_matrix, final_composite_yuv_matrix );
498     update_composite_matrix( p_fsm->contrast_matrix, final_composite_yuv_matrix );
499     update_composite_matrix( p_fsm->brightness_matrix, final_composite_yuv_matrix );
500     if ( format != PIPE_OUT_RGB ) {
501         uint16_t *ptr_rgb2yuv = _GET_USHORT_PTR( ACAMERA_FSM2CTX_PTR( p_fsm ), CALIBRATION_RGB2YUV_CONVERSION );
502         for ( i = 0; i < 12; i++ )
503             p_fsm->rgb2yuv_matrix[i] = color_matrix_direct_to_complement( ptr_rgb2yuv[i] );
504         update_composite_matrix( p_fsm->rgb2yuv_matrix, final_composite_yuv_matrix );
505     }
506     matrix_yuv_clip( final_composite_yuv_matrix );
507 }
matrix_yuv_recompute(matrix_yuv_fsm_t * p_fsm)508 void matrix_yuv_recompute( matrix_yuv_fsm_t *p_fsm )
509 {
510 
511     matrix_compute_color_mode( p_fsm->color_mode, p_fsm->color_mode_matrix, p_fsm );
512     matrix_compute_brightness( p_fsm->brightness_strength, p_fsm->brightness_matrix );
513     matrix_compute_contrast( p_fsm->contrast_strength, p_fsm->contrast_matrix );
514     matrix_compute_saturation( p_fsm->saturation_strength, p_fsm->saturation_matrix, p_fsm );
515     matrix_compute_hue_saturation( p_fsm->hue_theta, p_fsm->hue_correction_matrix );
516     compute_transfrom_matrix( p_fsm, p_fsm->fr_composite_yuv_matrix, p_fsm->fr_pipe_output_format );
517 #if ISP_HAS_DS1
518     compute_transfrom_matrix( p_fsm, p_fsm->ds1_composite_yuv_matrix, p_fsm->ds1_pipe_output_format );
519 #endif
520 }
matrix_yuv_coefft_write_to_hardware(matrix_yuv_fsm_t * p_fsm)521 void matrix_yuv_coefft_write_to_hardware( matrix_yuv_fsm_t *p_fsm )
522 {
523     matrix_yuv_fr_coefft_write_to_hardware( p_fsm );
524     matrix_yuv_ds_write_to_hardware( p_fsm );
525 }
matrix_yuv_update(matrix_yuv_fsm_t * p_fsm)526 void matrix_yuv_update( matrix_yuv_fsm_t *p_fsm )
527 {
528     matrix_yuv_recompute( p_fsm );
529     matrix_yuv_coefft_write_to_hardware( p_fsm );
530 }
matrix_yuv_initialize(matrix_yuv_fsm_t * p_fsm)531 void matrix_yuv_initialize( matrix_yuv_fsm_t *p_fsm )
532 {
533     uint16_t identity_matrix[12] = {0x0100, 0x0000, 0x0000, 0x0000, 0x0100, 0x0000, 0x0000, 0x0000, 0x0100, 0, 0, 0};
534     uint8_t i = 0;
535     p_fsm->saturation_strength = 128;
536     p_fsm->contrast_strength = 128;
537     p_fsm->brightness_strength = 128;
538     p_fsm->hue_theta = 180;
539 #if defined( COLOR_MODE_ID )
540     p_fsm->color_mode = NORMAL;
541 #endif
542     for ( i = 0; i < 12; i++ ) {
543         p_fsm->rgb2yuv_matrix[i] = color_matrix_direct_to_complement( identity_matrix[i] );
544         p_fsm->brightness_matrix[i] = color_matrix_direct_to_complement( identity_matrix[i] );
545         p_fsm->contrast_matrix[i] = color_matrix_direct_to_complement( identity_matrix[i] );
546         p_fsm->hue_correction_matrix[i] = color_matrix_direct_to_complement( identity_matrix[i] );
547         p_fsm->fr_composite_yuv_matrix[i] = color_matrix_direct_to_complement( identity_matrix[i] );
548 #if ISP_HAS_DS1
549         p_fsm->ds1_composite_yuv_matrix[i] = color_matrix_direct_to_complement( identity_matrix[i] );
550 #endif
551     }
552 }
553 
554 
matrix_yuv_set_DS1_mode(const uint16_t format)555 void matrix_yuv_set_DS1_mode( const uint16_t format )
556 {
557 }
matrix_yuv_set_FR_mode(const uint16_t format)558 void matrix_yuv_set_FR_mode( const uint16_t format )
559 {
560 }
561