1 /*
2  * Support for Intel Camera Imaging ISP subsystem.
3  * Copyright (c) 2015, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  */
14 
15 #include "ia_css_types.h"
16 #include "sh_css_defs.h"
17 #include "assert_support.h"
18 
19 #include "ia_css_ctc2.host.h"
20 
21 #define INEFFECTIVE_VAL 4096
22 #define BASIC_VAL 819
23 
24 /*Default configuration of parameters for Ctc2*/
25 const struct ia_css_ctc2_config default_ctc2_config = {
26 	INEFFECTIVE_VAL, INEFFECTIVE_VAL, INEFFECTIVE_VAL,
27 	INEFFECTIVE_VAL, INEFFECTIVE_VAL, INEFFECTIVE_VAL,
28 	BASIC_VAL * 2, BASIC_VAL * 4, BASIC_VAL * 6,
29 	BASIC_VAL * 8, INEFFECTIVE_VAL, INEFFECTIVE_VAL,
30 	BASIC_VAL >> 1, BASIC_VAL
31 };
32 
33 /* (dydx) = ctc2_slope(y1, y0, x1, x0)
34  * -----------------------------------------------
35  * Calculation of the Slope of a Line = ((y1 - y0) >> 8)/(x1 - x0)
36  *
37  * Note: y1, y0 , x1 & x0 must lie within the range 0 <-> 8191
38  */
39 static int ctc2_slope(int y1, int y0, int x1, int x0)
40 {
41 	const int shift_val = 8;
42 	const int max_slope = (1 << IA_CSS_CTC_COEF_SHIFT) - 1;
43 	int dy = y1 - y0;
44 	int dx = x1 - x0;
45 	int rounding = (dx + 1) >> 1;
46 	int dy_shift = dy << shift_val;
47 	int slope, dydx;
48 
49 	/*Protection for parameter values, & avoiding zero divisions*/
50 	assert(y0 >= 0 && y0 <= max_slope);
51 	assert(y1 >= 0 && y1 <= max_slope);
52 	assert(x0 >= 0 && x0 <= max_slope);
53 	assert(x1 > 0 && x1 <= max_slope);
54 	assert(dx > 0);
55 
56 	if (dy < 0)
57 		rounding = -rounding;
58 	slope = (int)(dy_shift + rounding) / dx;
59 
60 	/*the slope must lie within the range
61 	  (-max_slope-1) >= (dydx) >= (max_slope)
62 	*/
63 	if (slope <= -max_slope - 1) {
64 		dydx = -max_slope - 1;
65 	} else if (slope >= max_slope) {
66 		dydx = max_slope;
67 	} else {
68 		dydx = slope;
69 	}
70 
71 	return dydx;
72 }
73 
74 /* (void) = ia_css_ctc2_vmem_encode(*to, *from)
75  * -----------------------------------------------
76  * VMEM Encode Function to translate Y parameters from userspace into ISP space
77  */
78 void ia_css_ctc2_vmem_encode(struct ia_css_isp_ctc2_vmem_params *to,
79 			     const struct ia_css_ctc2_config *from,
80 			     size_t size)
81 {
82 	unsigned int i, j;
83 	const unsigned int shffl_blck = 4;
84 	const unsigned int length_zeros = 11;
85 	short dydx0, dydx1, dydx2, dydx3, dydx4;
86 
87 	(void)size;
88 	/*
89 	*  Calculation of slopes of lines interconnecting
90 	*  0.0 -> y_x1 -> y_x2 -> y _x3 -> y_x4 -> 1.0
91 	*/
92 	dydx0 = ctc2_slope(from->y_y1, from->y_y0,
93 			   from->y_x1, 0);
94 	dydx1 = ctc2_slope(from->y_y2, from->y_y1,
95 			   from->y_x2, from->y_x1);
96 	dydx2 = ctc2_slope(from->y_y3, from->y_y2,
97 			   from->y_x3, from->y_x2);
98 	dydx3 = ctc2_slope(from->y_y4, from->y_y3,
99 			   from->y_x4, from->y_x3);
100 	dydx4 = ctc2_slope(from->y_y5, from->y_y4,
101 			   SH_CSS_BAYER_MAXVAL, from->y_x4);
102 
103 	/*Fill 3 arrays with:
104 	 * - Luma input gain values y_y0, y_y1, y_y2, y_3, y_y4
105 	 * - Luma kneepoints 0, y_x1, y_x2, y_x3, y_x4
106 	 * - Calculated slopes dydx0, dyxd1, dydx2, dydx3, dydx4
107 	 *
108 	 * - Each 64-element array is divided in blocks of 16 elements:
109 	 *   the 5 parameters + zeros in the remaining 11 positions
110 	 * - All blocks of the same array will contain the same data
111 	 */
112 	for (i = 0; i < shffl_blck; i++) {
113 		to->y_x[0][(i << shffl_blck)]     = 0;
114 		to->y_x[0][(i << shffl_blck) + 1] = from->y_x1;
115 		to->y_x[0][(i << shffl_blck) + 2] = from->y_x2;
116 		to->y_x[0][(i << shffl_blck) + 3] = from->y_x3;
117 		to->y_x[0][(i << shffl_blck) + 4] = from->y_x4;
118 
119 		to->y_y[0][(i << shffl_blck)]     = from->y_y0;
120 		to->y_y[0][(i << shffl_blck) + 1] = from->y_y1;
121 		to->y_y[0][(i << shffl_blck) + 2] = from->y_y2;
122 		to->y_y[0][(i << shffl_blck) + 3] = from->y_y3;
123 		to->y_y[0][(i << shffl_blck) + 4] = from->y_y4;
124 
125 		to->e_y_slope[0][(i << shffl_blck)]    = dydx0;
126 		to->e_y_slope[0][(i << shffl_blck) + 1] = dydx1;
127 		to->e_y_slope[0][(i << shffl_blck) + 2] = dydx2;
128 		to->e_y_slope[0][(i << shffl_blck) + 3] = dydx3;
129 		to->e_y_slope[0][(i << shffl_blck) + 4] = dydx4;
130 
131 		for (j = 0; j < length_zeros; j++) {
132 			to->y_x[0][(i << shffl_blck) + 5 + j] = 0;
133 			to->y_y[0][(i << shffl_blck) + 5 + j] = 0;
134 			to->e_y_slope[0][(i << shffl_blck) + 5 + j] = 0;
135 		}
136 	}
137 }
138 
139 /* (void) = ia_css_ctc2_encode(*to, *from)
140  * -----------------------------------------------
141  * DMEM Encode Function to translate UV parameters from userspace into ISP space
142  */
143 void ia_css_ctc2_encode(struct ia_css_isp_ctc2_dmem_params *to,
144 			struct ia_css_ctc2_config *from,
145 			size_t size)
146 {
147 	(void)size;
148 
149 	to->uv_y0 = from->uv_y0;
150 	to->uv_y1 = from->uv_y1;
151 	to->uv_x0 = from->uv_x0;
152 	to->uv_x1 = from->uv_x1;
153 
154 	/*Slope Calculation*/
155 	to->uv_dydx = ctc2_slope(from->uv_y1, from->uv_y0,
156 				 from->uv_x1, from->uv_x0);
157 }
158