2 * Support for Intel Camera Imaging ISP subsystem.
3 * Copyright (c) 2015, Intel Corporation.
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.
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
15 #include <linux/slab.h>
17 #include <math_support.h>
18 #include "sh_css_param_shading.h"
19 #include "ia_css_shading.h"
20 #include "assert_support.h"
21 #include "sh_css_defs.h"
22 #include "sh_css_internal.h"
23 #include "ia_css_debug.h"
24 #include "ia_css_pipe_binarydesc.h"
26 #include "sh_css_hrt.h"
28 #include "platform_support.h"
30 /* Bilinear interpolation on shading tables:
31 * For each target point T, we calculate the 4 surrounding source points:
32 * ul (upper left), ur (upper right), ll (lower left) and lr (lower right).
33 * We then calculate the distances from the T to the source points: x0, x1,
35 * We then calculate the value of T:
36 * dx0*dy0*Slr + dx0*dy1*Sur + dx1*dy0*Sll + dx1*dy1*Sul.
37 * We choose a grid size of 1x1 which means:
42 * .<----->|<------------->.
55 * The area that the ISP operates on can include padding both on the left
56 * and the right. We need to padd the shading table such that the shading
57 * values end up on the correct pixel values. This means we must padd the
58 * shading table to match the ISP padding.
59 * We can have 5 cases:
60 * 1. All 4 points fall in the left padding.
61 * 2. The left 2 points fall in the left padding.
62 * 3. All 4 points fall in the cropped (target) region.
63 * 4. The right 2 points fall in the right padding.
64 * 5. All 4 points fall in the right padding.
65 * Cases 1 and 5 are easy to handle: we simply use the
66 * value 1 in the shading table.
67 * Cases 2 and 4 require interpolation that takes into
68 * account how far into the padding area the pixels
69 * fall. We extrapolate the shading table into the
70 * padded area and then interpolate.
73 crop_and_interpolate(unsigned int cropped_width,
74 unsigned int cropped_height,
75 unsigned int left_padding,
78 const struct ia_css_shading_table *in_table,
79 struct ia_css_shading_table *out_table,
80 enum ia_css_sc_color color)
92 int out_start_col, /* can be negative to indicate padded space */
94 unsigned short *in_ptr,
97 assert(in_table != NULL);
98 assert(out_table != NULL);
100 sensor_width = in_table->sensor_width;
101 sensor_height = in_table->sensor_height;
102 table_width = in_table->width;
103 table_height = in_table->height;
104 in_ptr = in_table->data[color];
105 out_ptr = out_table->data[color];
107 padded_width = cropped_width + left_padding + right_padding;
108 out_cell_size = CEIL_DIV(padded_width, out_table->width - 1);
109 in_cell_size = CEIL_DIV(sensor_width, table_width - 1);
111 out_start_col = ((int)sensor_width - (int)cropped_width)/2 - left_padding;
112 out_start_row = ((int)sensor_height - (int)cropped_height)/2 - top_padding;
113 table_cell_w = (int)((table_width-1) * in_cell_size);
114 table_cell_h = (table_height-1) * in_cell_size;
116 for (i = 0; i < out_table->height; i++) {
117 int ty, src_y0, src_y1;
118 unsigned int sy0, sy1, dy0, dy1, divy;
120 /* calculate target point and make sure it falls within
122 ty = out_start_row + i * out_cell_size;
124 /* calculate closest source points in shading table and
125 make sure they fall within the table */
126 src_y0 = ty / (int)in_cell_size;
127 if (in_cell_size < out_cell_size)
128 src_y1 = (ty + out_cell_size) / in_cell_size;
131 src_y0 = clamp(src_y0, 0, (int)table_height-1);
132 src_y1 = clamp(src_y1, 0, (int)table_height-1);
133 ty = min(clamp(ty, 0, (int)sensor_height-1),
136 /* calculate closest source points for distance computation */
137 sy0 = min(src_y0 * in_cell_size, sensor_height-1);
138 sy1 = min(src_y1 * in_cell_size, sensor_height-1);
139 /* calculate distance between source and target pixels */
148 for (j = 0; j < out_table->width; j++, out_ptr++) {
149 int tx, src_x0, src_x1;
150 unsigned int sx0, sx1, dx0, dx1, divx;
151 unsigned short s_ul, s_ur, s_ll, s_lr;
153 /* calculate target point */
154 tx = out_start_col + j * out_cell_size;
155 /* calculate closest source points. */
156 src_x0 = tx / (int)in_cell_size;
157 if (in_cell_size < out_cell_size) {
158 src_x1 = (tx + out_cell_size) /
163 /* if src points fall in padding, select closest ones.*/
164 src_x0 = clamp(src_x0, 0, (int)table_width-1);
165 src_x1 = clamp(src_x1, 0, (int)table_width-1);
166 tx = min(clamp(tx, 0, (int)sensor_width-1),
168 /* calculate closest source points for distance
170 sx0 = min(src_x0 * in_cell_size, sensor_width-1);
171 sx1 = min(src_x1 * in_cell_size, sensor_width-1);
172 /* calculate distances between source and target
177 /* if we're at the edge, we just use the closest
178 point still in the grid. We make up for the divider
179 in this case by setting the distance to
180 out_cell_size, since it's actually 0. */
186 /* get source pixel values */
187 s_ul = in_ptr[(table_width*src_y0)+src_x0];
188 s_ur = in_ptr[(table_width*src_y0)+src_x1];
189 s_ll = in_ptr[(table_width*src_y1)+src_x0];
190 s_lr = in_ptr[(table_width*src_y1)+src_x1];
192 *out_ptr = (unsigned short) ((dx0*dy0*s_lr + dx0*dy1*s_ur + dx1*dy0*s_ll + dx1*dy1*s_ul) /
199 sh_css_params_shading_id_table_generate(
200 struct ia_css_shading_table **target_table,
202 const struct ia_css_binary *binary)
204 unsigned int table_width,
205 unsigned int table_height)
208 /* initialize table with ones, shift becomes zero */
210 unsigned int i, j, table_width, table_height;
214 struct ia_css_shading_table *result;
216 assert(target_table != NULL);
218 assert(binary != NULL);
222 table_width = binary->sctbl_width_per_color;
223 table_height = binary->sctbl_height;
225 result = ia_css_shading_table_alloc(table_width, table_height);
226 if (result == NULL) {
227 *target_table = NULL;
231 for (i = 0; i < IA_CSS_SC_NUM_COLORS; i++) {
232 for (j = 0; j < table_height * table_width; j++)
233 result->data[i][j] = 1;
235 result->fraction_bits = 0;
236 *target_table = result;
240 prepare_shading_table(const struct ia_css_shading_table *in_table,
241 unsigned int sensor_binning,
242 struct ia_css_shading_table **target_table,
243 const struct ia_css_binary *binary,
244 unsigned int bds_factor)
246 unsigned int input_width,
255 unsigned int bds_numerator, bds_denominator;
258 struct ia_css_shading_table *result;
260 assert(target_table != NULL);
261 assert(binary != NULL);
265 sh_css_params_shading_id_table_generate(target_table, binary);
267 sh_css_params_shading_id_table_generate(target_table,
268 binary->sctbl_legacy_width_per_color, binary->sctbl_legacy_height);
273 padded_width = binary->in_frame_info.padded_width;
274 /* We use the ISP input resolution for the shading table because
275 shading correction is performed in the bayer domain (before bayer
277 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
278 padded_width = CEIL_MUL(binary->effective_in_frame_res.width + 2*ISP_VEC_NELEMS,
281 input_height = binary->in_frame_info.res.height;
282 input_width = binary->in_frame_info.res.width;
283 left_padding = binary->left_padding;
284 left_cropping = (binary->info->sp.pipeline.left_cropping == 0) ?
285 binary->dvs_envelope.width : 2*ISP_VEC_NELEMS;
287 sh_css_bds_factor_get_numerator_denominator
288 (bds_factor, &bds_numerator, &bds_denominator);
290 left_padding = (left_padding + binary->info->sp.pipeline.left_cropping) * bds_numerator / bds_denominator - binary->info->sp.pipeline.left_cropping;
291 right_padding = (binary->internal_frame_info.res.width - binary->effective_in_frame_res.width * bds_denominator / bds_numerator - left_cropping) * bds_numerator / bds_denominator;
292 top_padding = binary->info->sp.pipeline.top_cropping * bds_numerator / bds_denominator - binary->info->sp.pipeline.top_cropping;
294 #if !defined(USE_WINDOWS_BINNING_FACTOR)
295 /* @deprecated{This part of the code will be replaced by the code
296 * in the #else section below to make the calculation same across
298 * Android and Windows platforms interpret the binning_factor parameter
299 * differently. In Android, the binning factor is expressed in the form
300 * 2^N * 2^N, whereas in Windows platform, the binning factor is N*N}
303 /* We take into account the binning done by the sensor. We do this
304 by cropping the non-binned part of the shading table and then
305 increasing the size of a grid cell with this same binning factor. */
306 input_width <<= sensor_binning;
307 input_height <<= sensor_binning;
308 /* We also scale the padding by the same binning factor. This will
309 make it much easier later on to calculate the padding of the
311 left_padding <<= sensor_binning;
312 right_padding <<= sensor_binning;
313 top_padding <<= sensor_binning;
315 input_width *= sensor_binning;
316 input_height *= sensor_binning;
317 left_padding *= sensor_binning;
318 right_padding *= sensor_binning;
319 top_padding *= sensor_binning;
320 #endif /*USE_WINDOWS_BINNING_FACTOR*/
322 /* during simulation, the used resolution can exceed the sensor
323 resolution, so we clip it. */
324 input_width = min(input_width, in_table->sensor_width);
325 input_height = min(input_height, in_table->sensor_height);
328 table_width = binary->sctbl_width_per_color;
329 table_height = binary->sctbl_height;
331 /* This prepare_shading_table() function is called only in legacy API (not in new API).
332 Then, the legacy shading table width and height should be used. */
333 table_width = binary->sctbl_legacy_width_per_color;
334 table_height = binary->sctbl_legacy_height;
337 result = ia_css_shading_table_alloc(table_width, table_height);
338 if (result == NULL) {
339 *target_table = NULL;
342 result->sensor_width = in_table->sensor_width;
343 result->sensor_height = in_table->sensor_height;
344 result->fraction_bits = in_table->fraction_bits;
346 /* now we crop the original shading table and then interpolate to the
347 requested resolution and decimation factor. */
348 for (i = 0; i < IA_CSS_SC_NUM_COLORS; i++) {
349 crop_and_interpolate(input_width, input_height,
350 left_padding, right_padding, top_padding,
354 *target_table = result;
357 struct ia_css_shading_table *
358 ia_css_shading_table_alloc(
363 struct ia_css_shading_table *me;
367 me = kmalloc(sizeof(*me), GFP_KERNEL);
369 IA_CSS_ERROR("out of memory");
375 me->sensor_width = 0;
376 me->sensor_height = 0;
377 me->fraction_bits = 0;
378 for (i = 0; i < IA_CSS_SC_NUM_COLORS; i++) {
380 sh_css_malloc(width * height * sizeof(*me->data[0]));
381 if (me->data[i] == NULL) {
383 for (j = 0; j < i; j++) {
384 sh_css_free(me->data[j]);
397 ia_css_shading_table_free(struct ia_css_shading_table *table)
404 /* We only output logging when the table is not NULL, otherwise
405 * logs will give the impression that a table was freed.
409 for (i = 0; i < IA_CSS_SC_NUM_COLORS; i++) {
410 if (table->data[i]) {
411 sh_css_free(table->data[i]);
412 table->data[i] = NULL;