1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/slab.h>
17
18#include <math_support.h>
19#include "sh_css_param_shading.h"
20#include "ia_css_shading.h"
21#include "assert_support.h"
22#include "sh_css_defs.h"
23#include "sh_css_internal.h"
24#include "ia_css_debug.h"
25#include "ia_css_pipe_binarydesc.h"
26
27#include "sh_css_hrt.h"
28
29#include "platform_support.h"
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73static void
74crop_and_interpolate(unsigned int cropped_width,
75 unsigned int cropped_height,
76 unsigned int left_padding,
77 int right_padding,
78 int top_padding,
79 const struct ia_css_shading_table *in_table,
80 struct ia_css_shading_table *out_table,
81 enum ia_css_sc_color color)
82{
83 unsigned int i, j,
84 sensor_width,
85 sensor_height,
86 table_width,
87 table_height,
88 table_cell_h,
89 out_cell_size,
90 in_cell_size,
91 out_start_row,
92 padded_width;
93 int out_start_col,
94 table_cell_w;
95 unsigned short *in_ptr,
96 *out_ptr;
97
98 assert(in_table);
99 assert(out_table);
100
101 sensor_width = in_table->sensor_width;
102 sensor_height = in_table->sensor_height;
103 table_width = in_table->width;
104 table_height = in_table->height;
105 in_ptr = in_table->data[color];
106 out_ptr = out_table->data[color];
107
108 padded_width = cropped_width + left_padding + right_padding;
109 out_cell_size = CEIL_DIV(padded_width, out_table->width - 1);
110 in_cell_size = CEIL_DIV(sensor_width, table_width - 1);
111
112 out_start_col = ((int)sensor_width - (int)cropped_width) / 2 - left_padding;
113 out_start_row = ((int)sensor_height - (int)cropped_height) / 2 - top_padding;
114 table_cell_w = (int)((table_width - 1) * in_cell_size);
115 table_cell_h = (table_height - 1) * in_cell_size;
116
117 for (i = 0; i < out_table->height; i++) {
118 int ty, src_y0, src_y1;
119 unsigned int sy0, sy1, dy0, dy1, divy;
120
121
122
123 ty = out_start_row + i * out_cell_size;
124
125
126
127 src_y0 = ty / (int)in_cell_size;
128 if (in_cell_size < out_cell_size)
129 src_y1 = (ty + out_cell_size) / in_cell_size;
130 else
131 src_y1 = src_y0 + 1;
132 src_y0 = clamp(src_y0, 0, (int)table_height - 1);
133 src_y1 = clamp(src_y1, 0, (int)table_height - 1);
134 ty = min(clamp(ty, 0, (int)sensor_height - 1),
135 (int)table_cell_h);
136
137
138 sy0 = min(src_y0 * in_cell_size, sensor_height - 1);
139 sy1 = min(src_y1 * in_cell_size, sensor_height - 1);
140
141 dy0 = ty - sy0;
142 dy1 = sy1 - ty;
143 divy = sy1 - sy0;
144 if (divy == 0) {
145 dy0 = 1;
146 divy = 1;
147 }
148
149 for (j = 0; j < out_table->width; j++, out_ptr++) {
150 int tx, src_x0, src_x1;
151 unsigned int sx0, sx1, dx0, dx1, divx;
152 unsigned short s_ul, s_ur, s_ll, s_lr;
153
154
155 tx = out_start_col + j * out_cell_size;
156
157 src_x0 = tx / (int)in_cell_size;
158 if (in_cell_size < out_cell_size) {
159 src_x1 = (tx + out_cell_size) /
160 (int)in_cell_size;
161 } else {
162 src_x1 = src_x0 + 1;
163 }
164
165 src_x0 = clamp(src_x0, 0, (int)table_width - 1);
166 src_x1 = clamp(src_x1, 0, (int)table_width - 1);
167 tx = min(clamp(tx, 0, (int)sensor_width - 1),
168 (int)table_cell_w);
169
170
171 sx0 = min(src_x0 * in_cell_size, sensor_width - 1);
172 sx1 = min(src_x1 * in_cell_size, sensor_width - 1);
173
174
175 dx0 = tx - sx0;
176 dx1 = sx1 - tx;
177 divx = sx1 - sx0;
178
179
180
181
182 if (divx == 0) {
183 dx0 = 1;
184 divx = 1;
185 }
186
187
188 s_ul = in_ptr[(table_width * src_y0) + src_x0];
189 s_ur = in_ptr[(table_width * src_y0) + src_x1];
190 s_ll = in_ptr[(table_width * src_y1) + src_x0];
191 s_lr = in_ptr[(table_width * src_y1) + src_x1];
192
193 *out_ptr = (unsigned short)((dx0 * dy0 * s_lr + dx0 * dy1 * s_ur + dx1 * dy0 *
194 s_ll + dx1 * dy1 * s_ul) /
195 (divx * divy));
196 }
197 }
198}
199
200void
201sh_css_params_shading_id_table_generate(
202 struct ia_css_shading_table **target_table,
203 unsigned int table_width,
204 unsigned int table_height)
205{
206
207 unsigned int i, j;
208 struct ia_css_shading_table *result;
209
210 assert(target_table);
211
212 result = ia_css_shading_table_alloc(table_width, table_height);
213 if (!result) {
214 *target_table = NULL;
215 return;
216 }
217
218 for (i = 0; i < IA_CSS_SC_NUM_COLORS; i++) {
219 for (j = 0; j < table_height * table_width; j++)
220 result->data[i][j] = 1;
221 }
222 result->fraction_bits = 0;
223 *target_table = result;
224}
225
226void
227prepare_shading_table(const struct ia_css_shading_table *in_table,
228 unsigned int sensor_binning,
229 struct ia_css_shading_table **target_table,
230 const struct ia_css_binary *binary,
231 unsigned int bds_factor)
232{
233 unsigned int input_width, input_height, table_width, table_height, i;
234 unsigned int left_padding, top_padding, left_cropping;
235 unsigned int bds_numerator, bds_denominator;
236 int right_padding;
237
238 struct ia_css_shading_table *result;
239
240 assert(target_table);
241 assert(binary);
242
243 if (!in_table) {
244 sh_css_params_shading_id_table_generate(target_table,
245 binary->sctbl_legacy_width_per_color,
246 binary->sctbl_legacy_height);
247 return;
248 }
249
250
251
252
253
254
255 input_height = binary->in_frame_info.res.height;
256 input_width = binary->in_frame_info.res.width;
257 left_padding = binary->left_padding;
258 left_cropping = (binary->info->sp.pipeline.left_cropping == 0) ?
259 binary->dvs_envelope.width : 2 * ISP_VEC_NELEMS;
260
261 sh_css_bds_factor_get_numerator_denominator
262 (bds_factor, &bds_numerator, &bds_denominator);
263
264 left_padding = (left_padding + binary->info->sp.pipeline.left_cropping) *
265 bds_numerator / bds_denominator -
266 binary->info->sp.pipeline.left_cropping;
267 right_padding = (binary->internal_frame_info.res.width -
268 binary->effective_in_frame_res.width * bds_denominator /
269 bds_numerator - left_cropping) * bds_numerator / bds_denominator;
270 top_padding = binary->info->sp.pipeline.top_cropping * bds_numerator /
271 bds_denominator -
272 binary->info->sp.pipeline.top_cropping;
273
274#if !defined(USE_WINDOWS_BINNING_FACTOR)
275
276
277
278
279
280
281
282
283
284
285
286 input_width <<= sensor_binning;
287 input_height <<= sensor_binning;
288
289
290
291 left_padding <<= sensor_binning;
292 right_padding <<= sensor_binning;
293 top_padding <<= sensor_binning;
294#else
295 input_width *= sensor_binning;
296 input_height *= sensor_binning;
297 left_padding *= sensor_binning;
298 right_padding *= sensor_binning;
299 top_padding *= sensor_binning;
300#endif
301
302
303
304 input_width = min(input_width, in_table->sensor_width);
305 input_height = min(input_height, in_table->sensor_height);
306
307
308
309 table_width = binary->sctbl_legacy_width_per_color;
310 table_height = binary->sctbl_legacy_height;
311
312 result = ia_css_shading_table_alloc(table_width, table_height);
313 if (!result) {
314 *target_table = NULL;
315 return;
316 }
317 result->sensor_width = in_table->sensor_width;
318 result->sensor_height = in_table->sensor_height;
319 result->fraction_bits = in_table->fraction_bits;
320
321
322
323 for (i = 0; i < IA_CSS_SC_NUM_COLORS; i++) {
324 crop_and_interpolate(input_width, input_height,
325 left_padding, right_padding, top_padding,
326 in_table,
327 result, i);
328 }
329 *target_table = result;
330}
331
332struct ia_css_shading_table *
333ia_css_shading_table_alloc(
334 unsigned int width,
335 unsigned int height)
336{
337 unsigned int i;
338 struct ia_css_shading_table *me;
339
340 IA_CSS_ENTER("");
341
342 me = kmalloc(sizeof(*me), GFP_KERNEL);
343 if (!me)
344 return me;
345
346 me->width = width;
347 me->height = height;
348 me->sensor_width = 0;
349 me->sensor_height = 0;
350 me->fraction_bits = 0;
351 for (i = 0; i < IA_CSS_SC_NUM_COLORS; i++) {
352 me->data[i] =
353 kvmalloc(width * height * sizeof(*me->data[0]),
354 GFP_KERNEL);
355 if (!me->data[i]) {
356 unsigned int j;
357
358 for (j = 0; j < i; j++) {
359 kvfree(me->data[j]);
360 me->data[j] = NULL;
361 }
362 kfree(me);
363 return NULL;
364 }
365 }
366
367 IA_CSS_LEAVE("");
368 return me;
369}
370
371void
372ia_css_shading_table_free(struct ia_css_shading_table *table)
373{
374 unsigned int i;
375
376 if (!table)
377 return;
378
379
380
381
382 IA_CSS_ENTER("");
383
384 for (i = 0; i < IA_CSS_SC_NUM_COLORS; i++) {
385 if (table->data[i]) {
386 kvfree(table->data[i]);
387 table->data[i] = NULL;
388 }
389 }
390 kfree(table);
391
392 IA_CSS_LEAVE("");
393}
394