1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Support for Intel Camera Imaging ISP subsystem.
4 * Copyright (c) 2015, Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 */
15
16 #include <math_support.h>
17 #include <gdc_device.h> /* HR_GDC_N */
18
19 #include "hmm.h"
20
21 #include "isp.h" /* ISP_VEC_NELEMS */
22
23 #include "ia_css_binary.h"
24 #include "ia_css_debug.h"
25 #include "ia_css_util.h"
26 #include "ia_css_isp_param.h"
27 #include "sh_css_internal.h"
28 #include "sh_css_sp.h"
29 #include "sh_css_firmware.h"
30 #include "sh_css_defs.h"
31 #include "sh_css_legacy.h"
32
33 #include "atomisp_internal.h"
34
35 #include "vf/vf_1.0/ia_css_vf.host.h"
36 #include "sc/sc_1.0/ia_css_sc.host.h"
37 #include "sdis/sdis_1.0/ia_css_sdis.host.h"
38 #include "fixedbds/fixedbds_1.0/ia_css_fixedbds_param.h" /* FRAC_ACC */
39
40 #include "camera/pipe/interface/ia_css_pipe_binarydesc.h"
41
42 #include "assert_support.h"
43
44 #define IMPLIES(a, b) (!(a) || (b)) /* A => B */
45
46 static struct ia_css_binary_xinfo *all_binaries; /* ISP binaries only (no SP) */
47 static struct ia_css_binary_xinfo
48 *binary_infos[IA_CSS_BINARY_NUM_MODES] = { NULL, };
49
50 static void
ia_css_binary_dvs_env(const struct ia_css_binary_info * info,const struct ia_css_resolution * dvs_env,struct ia_css_resolution * binary_dvs_env)51 ia_css_binary_dvs_env(const struct ia_css_binary_info *info,
52 const struct ia_css_resolution *dvs_env,
53 struct ia_css_resolution *binary_dvs_env)
54 {
55 if (info->enable.dvs_envelope) {
56 assert(dvs_env);
57 binary_dvs_env->width = max(dvs_env->width, SH_CSS_MIN_DVS_ENVELOPE);
58 binary_dvs_env->height = max(dvs_env->height, SH_CSS_MIN_DVS_ENVELOPE);
59 }
60 }
61
62 static void
ia_css_binary_internal_res(const struct ia_css_frame_info * in_info,const struct ia_css_frame_info * bds_out_info,const struct ia_css_frame_info * out_info,const struct ia_css_resolution * dvs_env,const struct ia_css_binary_info * info,struct ia_css_resolution * internal_res)63 ia_css_binary_internal_res(const struct ia_css_frame_info *in_info,
64 const struct ia_css_frame_info *bds_out_info,
65 const struct ia_css_frame_info *out_info,
66 const struct ia_css_resolution *dvs_env,
67 const struct ia_css_binary_info *info,
68 struct ia_css_resolution *internal_res)
69 {
70 unsigned int isp_tmp_internal_width = 0,
71 isp_tmp_internal_height = 0;
72 bool binary_supports_yuv_ds = info->enable.ds & 2;
73 struct ia_css_resolution binary_dvs_env;
74
75 binary_dvs_env.width = 0;
76 binary_dvs_env.height = 0;
77 ia_css_binary_dvs_env(info, dvs_env, &binary_dvs_env);
78
79 if (binary_supports_yuv_ds) {
80 if (in_info) {
81 isp_tmp_internal_width = in_info->res.width
82 + info->pipeline.left_cropping + binary_dvs_env.width;
83 isp_tmp_internal_height = in_info->res.height
84 + info->pipeline.top_cropping + binary_dvs_env.height;
85 }
86 } else if ((bds_out_info) && (out_info) &&
87 /* TODO: hack to make video_us case work. this should be reverted after
88 a nice solution in ISP */
89 (bds_out_info->res.width >= out_info->res.width)) {
90 isp_tmp_internal_width = bds_out_info->padded_width;
91 isp_tmp_internal_height = bds_out_info->res.height;
92 } else {
93 if (out_info) {
94 isp_tmp_internal_width = out_info->padded_width;
95 isp_tmp_internal_height = out_info->res.height;
96 }
97 }
98
99 /* We first calculate the resolutions used by the ISP. After that,
100 * we use those resolutions to compute sizes for tables etc. */
101 internal_res->width = __ISP_INTERNAL_WIDTH(isp_tmp_internal_width,
102 (int)binary_dvs_env.width,
103 info->pipeline.left_cropping, info->pipeline.mode,
104 info->pipeline.c_subsampling,
105 info->output.num_chunks, info->pipeline.pipelining);
106 internal_res->height = __ISP_INTERNAL_HEIGHT(isp_tmp_internal_height,
107 info->pipeline.top_cropping,
108 binary_dvs_env.height);
109 }
110
111 /* ISP2400 */
112 /* Computation results of the origin coordinate of bayer on the shading table. */
113 struct sh_css_shading_table_bayer_origin_compute_results {
114 u32 bayer_scale_hor_ratio_in; /* Horizontal ratio (in) of bayer scaling. */
115 u32 bayer_scale_hor_ratio_out; /* Horizontal ratio (out) of bayer scaling. */
116 u32 bayer_scale_ver_ratio_in; /* Vertical ratio (in) of bayer scaling. */
117 u32 bayer_scale_ver_ratio_out; /* Vertical ratio (out) of bayer scaling. */
118 u32 sc_bayer_origin_x_bqs_on_shading_table; /* X coordinate (in bqs) of bayer origin on shading table. */
119 u32 sc_bayer_origin_y_bqs_on_shading_table; /* Y coordinate (in bqs) of bayer origin on shading table. */
120 };
121
122 /* ISP2401 */
123 /* Requirements for the shading correction. */
124 struct sh_css_binary_sc_requirements {
125 /* Bayer scaling factor, for the scaling which is applied before shading correction. */
126 u32 bayer_scale_hor_ratio_in; /* Horizontal ratio (in) of scaling applied BEFORE shading correction. */
127 u32 bayer_scale_hor_ratio_out; /* Horizontal ratio (out) of scaling applied BEFORE shading correction. */
128 u32 bayer_scale_ver_ratio_in; /* Vertical ratio (in) of scaling applied BEFORE shading correction. */
129 u32 bayer_scale_ver_ratio_out; /* Vertical ratio (out) of scaling applied BEFORE shading correction. */
130
131 /* ISP internal frame is composed of the real sensor data and the padding data. */
132 u32 sensor_data_origin_x_bqs_on_internal; /* X origin (in bqs) of sensor data on internal frame
133 at shading correction. */
134 u32 sensor_data_origin_y_bqs_on_internal; /* Y origin (in bqs) of sensor data on internal frame
135 at shading correction. */
136 };
137
138 /* ISP2400: Get the requirements for the shading correction. */
139 static int
ia_css_binary_compute_shading_table_bayer_origin(const struct ia_css_binary * binary,unsigned int required_bds_factor,const struct ia_css_stream_config * stream_config,struct sh_css_shading_table_bayer_origin_compute_results * res)140 ia_css_binary_compute_shading_table_bayer_origin(
141 const struct ia_css_binary *binary, /* [in] */
142 unsigned int required_bds_factor, /* [in] */
143 const struct ia_css_stream_config *stream_config, /* [in] */
144 struct sh_css_shading_table_bayer_origin_compute_results *res) /* [out] */
145 {
146 int err;
147
148 /* Numerator and denominator of the fixed bayer downscaling factor.
149 (numerator >= denominator) */
150 unsigned int bds_num, bds_den;
151
152 /* Horizontal/Vertical ratio of bayer scaling
153 between input area and output area. */
154 unsigned int bs_hor_ratio_in;
155 unsigned int bs_hor_ratio_out;
156 unsigned int bs_ver_ratio_in;
157 unsigned int bs_ver_ratio_out;
158
159 /* Left padding set by InputFormatter. */
160 unsigned int left_padding_bqs; /* in bqs */
161
162 /* Flag for the NEED_BDS_FACTOR_2_00 macro defined in isp kernels. */
163 unsigned int need_bds_factor_2_00;
164
165 /* Left padding adjusted inside the isp. */
166 unsigned int left_padding_adjusted_bqs; /* in bqs */
167
168 /* Bad pixels caused by filters.
169 NxN-filter (before/after bayer scaling) moves the image position
170 to right/bottom directions by a few pixels.
171 It causes bad pixels at left/top sides,
172 and effective bayer size decreases. */
173 unsigned int bad_bqs_on_left_before_bs; /* in bqs */
174 unsigned int bad_bqs_on_left_after_bs; /* in bqs */
175 unsigned int bad_bqs_on_top_before_bs; /* in bqs */
176 unsigned int bad_bqs_on_top_after_bs; /* in bqs */
177
178 /* Get the numerator and denominator of bayer downscaling factor. */
179 err = sh_css_bds_factor_get_numerator_denominator
180 (required_bds_factor, &bds_num, &bds_den);
181 if (err)
182 return err;
183
184 /* Set the horizontal/vertical ratio of bayer scaling
185 between input area and output area. */
186 bs_hor_ratio_in = bds_num;
187 bs_hor_ratio_out = bds_den;
188 bs_ver_ratio_in = bds_num;
189 bs_ver_ratio_out = bds_den;
190
191 /* Set the left padding set by InputFormatter. (ifmtr.c) */
192 if (stream_config->left_padding == -1)
193 left_padding_bqs = _ISP_BQS(binary->left_padding);
194 else
195 left_padding_bqs = (unsigned int)((int)ISP_VEC_NELEMS
196 - _ISP_BQS(stream_config->left_padding));
197
198 /* Set the left padding adjusted inside the isp.
199 When bds_factor 2.00 is needed, some padding is added to left_padding
200 inside the isp, before bayer downscaling. (raw.isp.c)
201 (Hopefully, left_crop/left_padding/top_crop should be defined in css
202 appropriately, depending on bds_factor.)
203 */
204 need_bds_factor_2_00 = ((binary->info->sp.bds.supported_bds_factors &
205 (PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_00) |
206 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_50) |
207 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_3_00) |
208 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_00) |
209 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_50) |
210 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_5_00) |
211 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_6_00) |
212 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_8_00))) != 0);
213
214 if (need_bds_factor_2_00 && binary->info->sp.pipeline.left_cropping > 0)
215 left_padding_adjusted_bqs = left_padding_bqs + ISP_VEC_NELEMS;
216 else
217 left_padding_adjusted_bqs = left_padding_bqs;
218
219 /* Currently, the bad pixel caused by filters before bayer scaling
220 is NOT considered, because the bad pixel is subtle.
221 When some large filter is used in the future,
222 we need to consider the bad pixel.
223
224 Currently, when bds_factor isn't 1.00, 3x3 anti-alias filter is applied
225 to each color plane(Gr/R/B/Gb) before bayer downscaling.
226 This filter moves each color plane to right/bottom directions
227 by 1 pixel at the most, depending on downscaling factor.
228 */
229 bad_bqs_on_left_before_bs = 0;
230 bad_bqs_on_top_before_bs = 0;
231
232 /* Currently, the bad pixel caused by filters after bayer scaling
233 is NOT considered, because the bad pixel is subtle.
234 When some large filter is used in the future,
235 we need to consider the bad pixel.
236
237 Currently, when DPC&BNR is processed between bayer scaling and
238 shading correction, DPC&BNR moves each color plane to
239 right/bottom directions by 1 pixel.
240 */
241 bad_bqs_on_left_after_bs = 0;
242 bad_bqs_on_top_after_bs = 0;
243
244 /* Calculate the origin of bayer (real sensor data area)
245 located on the shading table during the shading correction. */
246 res->sc_bayer_origin_x_bqs_on_shading_table =
247 ((left_padding_adjusted_bqs + bad_bqs_on_left_before_bs)
248 * bs_hor_ratio_out + bs_hor_ratio_in / 2) / bs_hor_ratio_in
249 + bad_bqs_on_left_after_bs;
250 /* "+ bs_hor_ratio_in/2": rounding for division by bs_hor_ratio_in */
251 res->sc_bayer_origin_y_bqs_on_shading_table =
252 (bad_bqs_on_top_before_bs * bs_ver_ratio_out + bs_ver_ratio_in / 2) / bs_ver_ratio_in
253 + bad_bqs_on_top_after_bs;
254 /* "+ bs_ver_ratio_in/2": rounding for division by bs_ver_ratio_in */
255
256 res->bayer_scale_hor_ratio_in = (uint32_t)bs_hor_ratio_in;
257 res->bayer_scale_hor_ratio_out = (uint32_t)bs_hor_ratio_out;
258 res->bayer_scale_ver_ratio_in = (uint32_t)bs_ver_ratio_in;
259 res->bayer_scale_ver_ratio_out = (uint32_t)bs_ver_ratio_out;
260
261 return err;
262 }
263
264 /* ISP2401: Get the requirements for the shading correction. */
265 static int
sh_css_binary_get_sc_requirements(const struct ia_css_binary * binary,unsigned int required_bds_factor,const struct ia_css_stream_config * stream_config,struct sh_css_binary_sc_requirements * scr)266 sh_css_binary_get_sc_requirements(const struct ia_css_binary *binary, /* [in] */
267 unsigned int required_bds_factor, /* [in] */
268 const struct ia_css_stream_config *stream_config, /* [in] */
269 struct sh_css_binary_sc_requirements *scr) /* [out] */
270 {
271 int err;
272
273 /* Numerator and denominator of the fixed bayer downscaling factor. (numerator >= denominator) */
274 unsigned int bds_num, bds_den;
275
276 /* Horizontal/Vertical ratio of bayer scaling between input area and output area. */
277 unsigned int bs_hor_ratio_in, bs_hor_ratio_out, bs_ver_ratio_in, bs_ver_ratio_out;
278
279 /* Left padding set by InputFormatter. */
280 unsigned int left_padding_bqs;
281
282 /* Flags corresponding to NEED_BDS_FACTOR_2_00/NEED_BDS_FACTOR_1_50/NEED_BDS_FACTOR_1_25 macros
283 * defined in isp kernels. */
284 unsigned int need_bds_factor_2_00, need_bds_factor_1_50, need_bds_factor_1_25;
285
286 /* Left padding adjusted inside the isp kernels. */
287 unsigned int left_padding_adjusted_bqs;
288
289 /* Top padding padded inside the isp kernel for bayer downscaling binaries. */
290 unsigned int top_padding_bqs;
291
292 /* Bayer downscaling factor 1.0 by fixed-point. */
293 int bds_frac_acc = FRAC_ACC; /* FRAC_ACC is defined in ia_css_fixedbds_param.h. */
294
295 /* Right/Down shift amount caused by filters applied BEFORE shading corrertion. */
296 unsigned int right_shift_bqs_before_bs; /* right shift before bayer scaling */
297 unsigned int right_shift_bqs_after_bs; /* right shift after bayer scaling */
298 unsigned int down_shift_bqs_before_bs; /* down shift before bayer scaling */
299 unsigned int down_shift_bqs_after_bs; /* down shift after bayer scaling */
300
301 /* Origin of the real sensor data area on the internal frame at shading correction. */
302 unsigned int sensor_data_origin_x_bqs_on_internal;
303 unsigned int sensor_data_origin_y_bqs_on_internal;
304
305 unsigned int bs_frac = bds_frac_acc; /* scaling factor 1.0 in fixed point */
306 unsigned int bs_out, bs_in; /* scaling ratio in fixed point */
307
308 IA_CSS_ENTER_PRIVATE("binary=%p, required_bds_factor=%d, stream_config=%p",
309 binary, required_bds_factor, stream_config);
310
311 /* Get the numerator and denominator of the required bayer downscaling factor. */
312 err = sh_css_bds_factor_get_numerator_denominator(required_bds_factor,
313 &bds_num, &bds_den);
314 if (err) {
315 IA_CSS_LEAVE_ERR_PRIVATE(err);
316 return err;
317 }
318
319 IA_CSS_LOG("bds_num=%d, bds_den=%d", bds_num, bds_den);
320
321 /* Set the horizontal/vertical ratio of bayer scaling between input area and output area. */
322 bs_hor_ratio_in = bds_num;
323 bs_hor_ratio_out = bds_den;
324 bs_ver_ratio_in = bds_num;
325 bs_ver_ratio_out = bds_den;
326
327 /* Set the left padding set by InputFormatter. (ia_css_ifmtr_configure() in ifmtr.c) */
328 if (stream_config->left_padding == -1)
329 left_padding_bqs = _ISP_BQS(binary->left_padding);
330 else
331 left_padding_bqs = (unsigned int)((int)ISP_VEC_NELEMS - _ISP_BQS(stream_config->left_padding));
332
333 IA_CSS_LOG("stream.left_padding=%d, binary.left_padding=%d, left_padding_bqs=%d",
334 stream_config->left_padding, binary->left_padding,
335 left_padding_bqs);
336
337 /* Set the left padding adjusted inside the isp kernels.
338 * When the bds_factor isn't 1.00, the left padding size is adjusted inside the isp,
339 * before bayer downscaling. (scaled_hor_plane_index(), raw_compute_hphase() in raw.isp.c)
340 */
341 need_bds_factor_2_00 = ((binary->info->sp.bds.supported_bds_factors &
342 (PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_00) |
343 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_50) |
344 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_3_00) |
345 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_00) |
346 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_50) |
347 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_5_00) |
348 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_6_00) |
349 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_8_00))) != 0);
350
351 need_bds_factor_1_50 = ((binary->info->sp.bds.supported_bds_factors &
352 (PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_1_50) |
353 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_25) |
354 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_3_00) |
355 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_50) |
356 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_6_00))) != 0);
357
358 need_bds_factor_1_25 = ((binary->info->sp.bds.supported_bds_factors &
359 (PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_1_25) |
360 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_50) |
361 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_5_00))) != 0);
362
363 if (binary->info->sp.pipeline.left_cropping > 0 &&
364 (need_bds_factor_2_00 || need_bds_factor_1_50 || need_bds_factor_1_25)) {
365 /*
366 * downscale 2.0 -> first_vec_adjusted_bqs = 128
367 * downscale 1.5 -> first_vec_adjusted_bqs = 96
368 * downscale 1.25 -> first_vec_adjusted_bqs = 80
369 */
370 unsigned int first_vec_adjusted_bqs = ISP_VEC_NELEMS * bs_hor_ratio_in / bs_hor_ratio_out;
371 left_padding_adjusted_bqs = first_vec_adjusted_bqs
372 - _ISP_BQS(binary->info->sp.pipeline.left_cropping);
373 } else {
374 left_padding_adjusted_bqs = left_padding_bqs;
375 }
376
377 IA_CSS_LOG("supported_bds_factors=%d, need_bds_factor:2_00=%d, 1_50=%d, 1_25=%d",
378 binary->info->sp.bds.supported_bds_factors,
379 need_bds_factor_2_00, need_bds_factor_1_50,
380 need_bds_factor_1_25);
381 IA_CSS_LOG("left_cropping=%d, left_padding_adjusted_bqs=%d",
382 binary->info->sp.pipeline.left_cropping,
383 left_padding_adjusted_bqs);
384
385 /* Set the top padding padded inside the isp kernel for bayer downscaling binaries.
386 * When the bds_factor isn't 1.00, the top padding is padded inside the isp
387 * before bayer downscaling, because the top cropping size (input margin) is not enough.
388 * (calculate_input_line(), raw_compute_vphase(), dma_read_raw() in raw.isp.c)
389 * NOTE: In dma_read_raw(), the factor passed to raw_compute_vphase() is got by get_bds_factor_for_dma_read().
390 * This factor is BDS_FPVAL_100/BDS_FPVAL_125/BDS_FPVAL_150/BDS_FPVAL_200.
391 */
392 top_padding_bqs = 0;
393 if (binary->info->sp.pipeline.top_cropping > 0 &&
394 (required_bds_factor == SH_CSS_BDS_FACTOR_1_25 ||
395 required_bds_factor == SH_CSS_BDS_FACTOR_1_50 ||
396 required_bds_factor == SH_CSS_BDS_FACTOR_2_00)) {
397 /* Calculation from calculate_input_line() and raw_compute_vphase() in raw.isp.c. */
398 int top_cropping_bqs = _ISP_BQS(binary->info->sp.pipeline.top_cropping);
399 /* top cropping (in bqs) */
400 int factor = bds_num * bds_frac_acc /
401 bds_den; /* downscaling factor by fixed-point */
402 int top_padding_bqsxfrac_acc = (top_cropping_bqs * factor - top_cropping_bqs *
403 bds_frac_acc)
404 + (2 * bds_frac_acc - factor); /* top padding by fixed-point (in bqs) */
405
406 top_padding_bqs = (unsigned int)((top_padding_bqsxfrac_acc + bds_frac_acc / 2 -
407 1) / bds_frac_acc);
408 }
409
410 IA_CSS_LOG("top_cropping=%d, top_padding_bqs=%d",
411 binary->info->sp.pipeline.top_cropping, top_padding_bqs);
412
413 /* Set the right/down shift amount caused by filters applied BEFORE bayer scaling,
414 * which scaling is applied BEFORE shading corrertion.
415 *
416 * When the bds_factor isn't 1.00, 3x3 anti-alias filter is applied to each color plane(Gr/R/B/Gb)
417 * before bayer downscaling.
418 * This filter shifts each color plane (Gr/R/B/Gb) to right/down directions by 1 pixel.
419 */
420 right_shift_bqs_before_bs = 0;
421 down_shift_bqs_before_bs = 0;
422
423 if (need_bds_factor_2_00 || need_bds_factor_1_50 || need_bds_factor_1_25) {
424 right_shift_bqs_before_bs = 1;
425 down_shift_bqs_before_bs = 1;
426 }
427
428 IA_CSS_LOG("right_shift_bqs_before_bs=%d, down_shift_bqs_before_bs=%d",
429 right_shift_bqs_before_bs, down_shift_bqs_before_bs);
430
431 /* Set the right/down shift amount caused by filters applied AFTER bayer scaling,
432 * which scaling is applied BEFORE shading corrertion.
433 *
434 * When DPC&BNR is processed between bayer scaling and shading correction,
435 * DPC&BNR moves each color plane (Gr/R/B/Gb) to right/down directions by 1 pixel.
436 */
437 right_shift_bqs_after_bs = 0;
438 down_shift_bqs_after_bs = 0;
439
440 /* if DPC&BNR is enabled in the binary */
441 if (binary->info->mem_offsets.offsets.param->dmem.dp.size != 0) {
442 right_shift_bqs_after_bs = 1;
443 down_shift_bqs_after_bs = 1;
444 }
445
446 IA_CSS_LOG("right_shift_bqs_after_bs=%d, down_shift_bqs_after_bs=%d",
447 right_shift_bqs_after_bs, down_shift_bqs_after_bs);
448
449 bs_out = bs_hor_ratio_out * bs_frac;
450 bs_in = bs_hor_ratio_in * bs_frac;
451 sensor_data_origin_x_bqs_on_internal =
452 ((left_padding_adjusted_bqs + right_shift_bqs_before_bs) * bs_out + bs_in / 2) / bs_in
453 + right_shift_bqs_after_bs; /* "+ bs_in/2": rounding */
454
455 bs_out = bs_ver_ratio_out * bs_frac;
456 bs_in = bs_ver_ratio_in * bs_frac;
457 sensor_data_origin_y_bqs_on_internal =
458 ((top_padding_bqs + down_shift_bqs_before_bs) * bs_out + bs_in / 2) / bs_in
459 + down_shift_bqs_after_bs; /* "+ bs_in/2": rounding */
460
461 scr->bayer_scale_hor_ratio_in = (uint32_t)bs_hor_ratio_in;
462 scr->bayer_scale_hor_ratio_out = (uint32_t)bs_hor_ratio_out;
463 scr->bayer_scale_ver_ratio_in = (uint32_t)bs_ver_ratio_in;
464 scr->bayer_scale_ver_ratio_out = (uint32_t)bs_ver_ratio_out;
465 scr->sensor_data_origin_x_bqs_on_internal = (uint32_t)sensor_data_origin_x_bqs_on_internal;
466 scr->sensor_data_origin_y_bqs_on_internal = (uint32_t)sensor_data_origin_y_bqs_on_internal;
467
468 IA_CSS_LOG("sc_requirements: %d, %d, %d, %d, %d, %d",
469 scr->bayer_scale_hor_ratio_in,
470 scr->bayer_scale_hor_ratio_out,
471 scr->bayer_scale_ver_ratio_in, scr->bayer_scale_ver_ratio_out,
472 scr->sensor_data_origin_x_bqs_on_internal,
473 scr->sensor_data_origin_y_bqs_on_internal);
474
475 IA_CSS_LEAVE_ERR_PRIVATE(err);
476 return err;
477 }
478
479 /* Get the shading information of Shading Correction Type 1. */
480 static int
isp2400_binary_get_shading_info_type_1(const struct ia_css_binary * binary,unsigned int required_bds_factor,const struct ia_css_stream_config * stream_config,struct ia_css_shading_info * info)481 isp2400_binary_get_shading_info_type_1(const struct ia_css_binary *binary, /* [in] */
482 unsigned int required_bds_factor, /* [in] */
483 const struct ia_css_stream_config *stream_config, /* [in] */
484 struct ia_css_shading_info *info) /* [out] */
485 {
486 int err;
487 struct sh_css_shading_table_bayer_origin_compute_results res;
488
489 assert(binary);
490 assert(info);
491
492 info->type = IA_CSS_SHADING_CORRECTION_TYPE_1;
493
494 info->info.type_1.enable = binary->info->sp.enable.sc;
495 info->info.type_1.num_hor_grids = binary->sctbl_width_per_color;
496 info->info.type_1.num_ver_grids = binary->sctbl_height;
497 info->info.type_1.bqs_per_grid_cell = (1 << binary->deci_factor_log2);
498
499 /* Initialize by default values. */
500 info->info.type_1.bayer_scale_hor_ratio_in = 1;
501 info->info.type_1.bayer_scale_hor_ratio_out = 1;
502 info->info.type_1.bayer_scale_ver_ratio_in = 1;
503 info->info.type_1.bayer_scale_ver_ratio_out = 1;
504 info->info.type_1.sc_bayer_origin_x_bqs_on_shading_table = 0;
505 info->info.type_1.sc_bayer_origin_y_bqs_on_shading_table = 0;
506
507 err = ia_css_binary_compute_shading_table_bayer_origin(
508 binary,
509 required_bds_factor,
510 stream_config,
511 &res);
512 if (err)
513 return err;
514
515 info->info.type_1.bayer_scale_hor_ratio_in = res.bayer_scale_hor_ratio_in;
516 info->info.type_1.bayer_scale_hor_ratio_out = res.bayer_scale_hor_ratio_out;
517 info->info.type_1.bayer_scale_ver_ratio_in = res.bayer_scale_ver_ratio_in;
518 info->info.type_1.bayer_scale_ver_ratio_out = res.bayer_scale_ver_ratio_out;
519 info->info.type_1.sc_bayer_origin_x_bqs_on_shading_table = res.sc_bayer_origin_x_bqs_on_shading_table;
520 info->info.type_1.sc_bayer_origin_y_bqs_on_shading_table = res.sc_bayer_origin_y_bqs_on_shading_table;
521
522 return err;
523 }
524
525 /* Get the shading information of Shading Correction Type 1. */
526 static int
isp2401_binary_get_shading_info_type_1(const struct ia_css_binary * binary,unsigned int required_bds_factor,const struct ia_css_stream_config * stream_config,struct ia_css_shading_info * shading_info,struct ia_css_pipe_config * pipe_config)527 isp2401_binary_get_shading_info_type_1(const struct ia_css_binary *binary, /* [in] */
528 unsigned int required_bds_factor, /* [in] */
529 const struct ia_css_stream_config *stream_config, /* [in] */
530 struct ia_css_shading_info *shading_info, /* [out] */
531 struct ia_css_pipe_config *pipe_config) /* [out] */
532 {
533 int err;
534 struct sh_css_binary_sc_requirements scr;
535
536 u32 in_width_bqs, in_height_bqs, internal_width_bqs, internal_height_bqs;
537 u32 num_hor_grids, num_ver_grids, bqs_per_grid_cell, tbl_width_bqs, tbl_height_bqs;
538 u32 sensor_org_x_bqs_on_internal, sensor_org_y_bqs_on_internal, sensor_width_bqs, sensor_height_bqs;
539 u32 sensor_center_x_bqs_on_internal, sensor_center_y_bqs_on_internal;
540 u32 left, right, upper, lower;
541 u32 adjust_left, adjust_right, adjust_upper, adjust_lower, adjust_width_bqs, adjust_height_bqs;
542 u32 internal_org_x_bqs_on_tbl, internal_org_y_bqs_on_tbl;
543 u32 sensor_org_x_bqs_on_tbl, sensor_org_y_bqs_on_tbl;
544
545 assert(binary);
546 assert(stream_config);
547 assert(shading_info);
548 assert(pipe_config);
549
550 IA_CSS_ENTER_PRIVATE("binary=%p, required_bds_factor=%d, stream_config=%p",
551 binary, required_bds_factor, stream_config);
552
553 /* Initialize by default values. */
554 *shading_info = DEFAULT_SHADING_INFO_TYPE_1;
555
556 err = sh_css_binary_get_sc_requirements(binary, required_bds_factor, stream_config, &scr);
557 if (err) {
558 IA_CSS_LEAVE_ERR_PRIVATE(err);
559 return err;
560 }
561
562 IA_CSS_LOG("binary: id=%d, sctbl=%dx%d, deci=%d",
563 binary->info->sp.id, binary->sctbl_width_per_color, binary->sctbl_height, binary->deci_factor_log2);
564 IA_CSS_LOG("binary: in=%dx%d, in_padded_w=%d, int=%dx%d, int_padded_w=%d, out=%dx%d, out_padded_w=%d",
565 binary->in_frame_info.res.width, binary->in_frame_info.res.height, binary->in_frame_info.padded_width,
566 binary->internal_frame_info.res.width, binary->internal_frame_info.res.height,
567 binary->internal_frame_info.padded_width,
568 binary->out_frame_info[0].res.width, binary->out_frame_info[0].res.height,
569 binary->out_frame_info[0].padded_width);
570
571 /* Set the input size from sensor, which includes left/top crop size. */
572 in_width_bqs = _ISP_BQS(binary->in_frame_info.res.width);
573 in_height_bqs = _ISP_BQS(binary->in_frame_info.res.height);
574
575 /*
576 * Frame size internally used in ISP, including sensor data and padding.
577 * This is the frame size, to which the shading correction is applied.
578 */
579 internal_width_bqs = _ISP_BQS(binary->internal_frame_info.res.width);
580 internal_height_bqs = _ISP_BQS(binary->internal_frame_info.res.height);
581
582 /* Shading table. */
583 num_hor_grids = binary->sctbl_width_per_color;
584 num_ver_grids = binary->sctbl_height;
585 bqs_per_grid_cell = (1 << binary->deci_factor_log2);
586 tbl_width_bqs = (num_hor_grids - 1) * bqs_per_grid_cell;
587 tbl_height_bqs = (num_ver_grids - 1) * bqs_per_grid_cell;
588
589 IA_CSS_LOG("tbl_width_bqs=%d, tbl_height_bqs=%d", tbl_width_bqs, tbl_height_bqs);
590
591 /*
592 * Real sensor data area on the internal frame at shading correction.
593 * Filters and scaling are applied to the internal frame before
594 * shading correction, depending on the binary.
595 */
596 sensor_org_x_bqs_on_internal = scr.sensor_data_origin_x_bqs_on_internal;
597 sensor_org_y_bqs_on_internal = scr.sensor_data_origin_y_bqs_on_internal;
598 {
599 unsigned int bs_frac = 8; /* scaling factor 1.0 in fixed point (8 == FRAC_ACC macro in ISP) */
600 unsigned int bs_out, bs_in; /* scaling ratio in fixed point */
601
602 bs_out = scr.bayer_scale_hor_ratio_out * bs_frac;
603 bs_in = scr.bayer_scale_hor_ratio_in * bs_frac;
604 sensor_width_bqs = (in_width_bqs * bs_out + bs_in / 2) / bs_in; /* "+ bs_in/2": rounding */
605
606 bs_out = scr.bayer_scale_ver_ratio_out * bs_frac;
607 bs_in = scr.bayer_scale_ver_ratio_in * bs_frac;
608 sensor_height_bqs = (in_height_bqs * bs_out + bs_in / 2) / bs_in; /* "+ bs_in/2": rounding */
609 }
610
611 /* Center of the sensor data on the internal frame at shading correction. */
612 sensor_center_x_bqs_on_internal = sensor_org_x_bqs_on_internal + sensor_width_bqs / 2;
613 sensor_center_y_bqs_on_internal = sensor_org_y_bqs_on_internal + sensor_height_bqs / 2;
614
615 /* Size of left/right/upper/lower sides of the sensor center on the internal frame. */
616 left = sensor_center_x_bqs_on_internal;
617 right = internal_width_bqs - sensor_center_x_bqs_on_internal;
618 upper = sensor_center_y_bqs_on_internal;
619 lower = internal_height_bqs - sensor_center_y_bqs_on_internal;
620
621 /* Align the size of left/right/upper/lower sides to a multiple of the grid cell size. */
622 adjust_left = CEIL_MUL(left, bqs_per_grid_cell);
623 adjust_right = CEIL_MUL(right, bqs_per_grid_cell);
624 adjust_upper = CEIL_MUL(upper, bqs_per_grid_cell);
625 adjust_lower = CEIL_MUL(lower, bqs_per_grid_cell);
626
627 /* Shading table should cover the adjusted frame size. */
628 adjust_width_bqs = adjust_left + adjust_right;
629 adjust_height_bqs = adjust_upper + adjust_lower;
630
631 IA_CSS_LOG("adjust_width_bqs=%d, adjust_height_bqs=%d", adjust_width_bqs, adjust_height_bqs);
632
633 if (adjust_width_bqs > tbl_width_bqs || adjust_height_bqs > tbl_height_bqs) {
634 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
635 return -EINVAL;
636 }
637
638 /* Origin of the internal frame on the shading table. */
639 internal_org_x_bqs_on_tbl = adjust_left - left;
640 internal_org_y_bqs_on_tbl = adjust_upper - upper;
641
642 /* Origin of the real sensor data area on the shading table. */
643 sensor_org_x_bqs_on_tbl = internal_org_x_bqs_on_tbl + sensor_org_x_bqs_on_internal;
644 sensor_org_y_bqs_on_tbl = internal_org_y_bqs_on_tbl + sensor_org_y_bqs_on_internal;
645
646 /* The shading information necessary as API is stored in the shading_info. */
647 shading_info->info.type_1.num_hor_grids = num_hor_grids;
648 shading_info->info.type_1.num_ver_grids = num_ver_grids;
649 shading_info->info.type_1.bqs_per_grid_cell = bqs_per_grid_cell;
650
651 shading_info->info.type_1.bayer_scale_hor_ratio_in = scr.bayer_scale_hor_ratio_in;
652 shading_info->info.type_1.bayer_scale_hor_ratio_out = scr.bayer_scale_hor_ratio_out;
653 shading_info->info.type_1.bayer_scale_ver_ratio_in = scr.bayer_scale_ver_ratio_in;
654 shading_info->info.type_1.bayer_scale_ver_ratio_out = scr.bayer_scale_ver_ratio_out;
655
656 shading_info->info.type_1.isp_input_sensor_data_res_bqs.width = in_width_bqs;
657 shading_info->info.type_1.isp_input_sensor_data_res_bqs.height = in_height_bqs;
658
659 shading_info->info.type_1.sensor_data_res_bqs.width = sensor_width_bqs;
660 shading_info->info.type_1.sensor_data_res_bqs.height = sensor_height_bqs;
661
662 shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.x = (int32_t)sensor_org_x_bqs_on_tbl;
663 shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.y = (int32_t)sensor_org_y_bqs_on_tbl;
664
665 /* The shading information related to ISP (but, not necessary as API) is stored in the pipe_config. */
666 pipe_config->internal_frame_origin_bqs_on_sctbl.x = (int32_t)internal_org_x_bqs_on_tbl;
667 pipe_config->internal_frame_origin_bqs_on_sctbl.y = (int32_t)internal_org_y_bqs_on_tbl;
668
669 IA_CSS_LOG("shading_info: grids=%dx%d, cell=%d, scale=%d,%d,%d,%d, input=%dx%d, data=%dx%d, origin=(%d,%d)",
670 shading_info->info.type_1.num_hor_grids,
671 shading_info->info.type_1.num_ver_grids,
672 shading_info->info.type_1.bqs_per_grid_cell,
673 shading_info->info.type_1.bayer_scale_hor_ratio_in,
674 shading_info->info.type_1.bayer_scale_hor_ratio_out,
675 shading_info->info.type_1.bayer_scale_ver_ratio_in,
676 shading_info->info.type_1.bayer_scale_ver_ratio_out,
677 shading_info->info.type_1.isp_input_sensor_data_res_bqs.width,
678 shading_info->info.type_1.isp_input_sensor_data_res_bqs.height,
679 shading_info->info.type_1.sensor_data_res_bqs.width,
680 shading_info->info.type_1.sensor_data_res_bqs.height,
681 shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.x,
682 shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.y);
683
684 IA_CSS_LOG("pipe_config: origin=(%d,%d)",
685 pipe_config->internal_frame_origin_bqs_on_sctbl.x,
686 pipe_config->internal_frame_origin_bqs_on_sctbl.y);
687
688 IA_CSS_LEAVE_ERR_PRIVATE(err);
689 return err;
690 }
691
692
693 int
ia_css_binary_get_shading_info(const struct ia_css_binary * binary,enum ia_css_shading_correction_type type,unsigned int required_bds_factor,const struct ia_css_stream_config * stream_config,struct ia_css_shading_info * shading_info,struct ia_css_pipe_config * pipe_config)694 ia_css_binary_get_shading_info(const struct ia_css_binary *binary, /* [in] */
695 enum ia_css_shading_correction_type type, /* [in] */
696 unsigned int required_bds_factor, /* [in] */
697 const struct ia_css_stream_config *stream_config, /* [in] */
698 struct ia_css_shading_info *shading_info, /* [out] */
699 struct ia_css_pipe_config *pipe_config) /* [out] */
700 {
701 int err;
702
703 assert(binary);
704 assert(shading_info);
705
706 IA_CSS_ENTER_PRIVATE("binary=%p, type=%d, required_bds_factor=%d, stream_config=%p",
707 binary, type, required_bds_factor, stream_config);
708
709 if (type != IA_CSS_SHADING_CORRECTION_TYPE_1) {
710 err = -ENOTSUPP;
711
712 IA_CSS_LEAVE_ERR_PRIVATE(err);
713 return err;
714 }
715
716 if (!IS_ISP2401)
717 err = isp2400_binary_get_shading_info_type_1(binary,
718 required_bds_factor,
719 stream_config,
720 shading_info);
721 else
722 err = isp2401_binary_get_shading_info_type_1(binary,
723 required_bds_factor,
724 stream_config,
725 shading_info,
726 pipe_config);
727
728 IA_CSS_LEAVE_ERR_PRIVATE(err);
729 return err;
730 }
731
sh_css_binary_common_grid_info(const struct ia_css_binary * binary,struct ia_css_grid_info * info)732 static void sh_css_binary_common_grid_info(const struct ia_css_binary *binary,
733 struct ia_css_grid_info *info)
734 {
735 assert(binary);
736 assert(info);
737
738 info->isp_in_width = binary->internal_frame_info.res.width;
739 info->isp_in_height = binary->internal_frame_info.res.height;
740
741 info->vamem_type = IA_CSS_VAMEM_TYPE_2;
742 }
743
744 void
ia_css_binary_dvs_grid_info(const struct ia_css_binary * binary,struct ia_css_grid_info * info,struct ia_css_pipe * pipe)745 ia_css_binary_dvs_grid_info(const struct ia_css_binary *binary,
746 struct ia_css_grid_info *info,
747 struct ia_css_pipe *pipe)
748 {
749 struct ia_css_dvs_grid_info *dvs_info;
750
751 (void)pipe;
752 assert(binary);
753 assert(info);
754
755 dvs_info = &info->dvs_grid.dvs_grid_info;
756
757 /* for DIS, we use a division instead of a ceil_div. If this is smaller
758 * than the 3a grid size, it indicates that the outer values are not
759 * valid for DIS.
760 */
761 dvs_info->enable = binary->info->sp.enable.dis;
762 dvs_info->width = binary->dis.grid.dim.width;
763 dvs_info->height = binary->dis.grid.dim.height;
764 dvs_info->aligned_width = binary->dis.grid.pad.width;
765 dvs_info->aligned_height = binary->dis.grid.pad.height;
766 dvs_info->bqs_per_grid_cell = 1 << binary->dis.deci_factor_log2;
767 dvs_info->num_hor_coefs = binary->dis.coef.dim.width;
768 dvs_info->num_ver_coefs = binary->dis.coef.dim.height;
769
770 sh_css_binary_common_grid_info(binary, info);
771 }
772
773 void
ia_css_binary_dvs_stat_grid_info(const struct ia_css_binary * binary,struct ia_css_grid_info * info,struct ia_css_pipe * pipe)774 ia_css_binary_dvs_stat_grid_info(
775 const struct ia_css_binary *binary,
776 struct ia_css_grid_info *info,
777 struct ia_css_pipe *pipe)
778 {
779 (void)pipe;
780 sh_css_binary_common_grid_info(binary, info);
781 return;
782 }
783
784 int
ia_css_binary_3a_grid_info(const struct ia_css_binary * binary,struct ia_css_grid_info * info,struct ia_css_pipe * pipe)785 ia_css_binary_3a_grid_info(const struct ia_css_binary *binary,
786 struct ia_css_grid_info *info,
787 struct ia_css_pipe *pipe) {
788 struct ia_css_3a_grid_info *s3a_info;
789 int err = 0;
790
791 IA_CSS_ENTER_PRIVATE("binary=%p, info=%p, pipe=%p",
792 binary, info, pipe);
793
794 assert(binary);
795 assert(info);
796 s3a_info = &info->s3a_grid;
797
798 /* 3A statistics grid */
799 s3a_info->enable = binary->info->sp.enable.s3a;
800 s3a_info->width = binary->s3atbl_width;
801 s3a_info->height = binary->s3atbl_height;
802 s3a_info->aligned_width = binary->s3atbl_isp_width;
803 s3a_info->aligned_height = binary->s3atbl_isp_height;
804 s3a_info->bqs_per_grid_cell = (1 << binary->deci_factor_log2);
805 s3a_info->deci_factor_log2 = binary->deci_factor_log2;
806 s3a_info->elem_bit_depth = SH_CSS_BAYER_BITS;
807 s3a_info->use_dmem = binary->info->sp.s3a.s3atbl_use_dmem;
808 #if defined(HAS_NO_HMEM)
809 s3a_info->has_histogram = 1;
810 #else
811 s3a_info->has_histogram = 0;
812 #endif
813 IA_CSS_LEAVE_ERR_PRIVATE(err);
814 return err;
815 }
816
817 static void
binary_init_pc_histogram(struct sh_css_pc_histogram * histo)818 binary_init_pc_histogram(struct sh_css_pc_histogram *histo)
819 {
820 assert(histo);
821
822 histo->length = 0;
823 histo->run = NULL;
824 histo->stall = NULL;
825 }
826
827 static void
binary_init_metrics(struct sh_css_binary_metrics * metrics,const struct ia_css_binary_info * info)828 binary_init_metrics(struct sh_css_binary_metrics *metrics,
829 const struct ia_css_binary_info *info)
830 {
831 assert(metrics);
832 assert(info);
833
834 metrics->mode = info->pipeline.mode;
835 metrics->id = info->id;
836 metrics->next = NULL;
837 binary_init_pc_histogram(&metrics->isp_histogram);
838 binary_init_pc_histogram(&metrics->sp_histogram);
839 }
840
841 /* move to host part of output module */
842 static bool
binary_supports_output_format(const struct ia_css_binary_xinfo * info,enum ia_css_frame_format format)843 binary_supports_output_format(const struct ia_css_binary_xinfo *info,
844 enum ia_css_frame_format format)
845 {
846 int i;
847
848 assert(info);
849
850 for (i = 0; i < info->num_output_formats; i++) {
851 if (info->output_formats[i] == format)
852 return true;
853 }
854 return false;
855 }
856
857 static bool
binary_supports_vf_format(const struct ia_css_binary_xinfo * info,enum ia_css_frame_format format)858 binary_supports_vf_format(const struct ia_css_binary_xinfo *info,
859 enum ia_css_frame_format format)
860 {
861 int i;
862
863 assert(info);
864
865 for (i = 0; i < info->num_vf_formats; i++) {
866 if (info->vf_formats[i] == format)
867 return true;
868 }
869 return false;
870 }
871
872 /* move to host part of bds module */
873 static bool
supports_bds_factor(u32 supported_factors,uint32_t bds_factor)874 supports_bds_factor(u32 supported_factors,
875 uint32_t bds_factor)
876 {
877 return ((supported_factors & PACK_BDS_FACTOR(bds_factor)) != 0);
878 }
879
880 static int
binary_init_info(struct ia_css_binary_xinfo * info,unsigned int i,bool * binary_found)881 binary_init_info(struct ia_css_binary_xinfo *info, unsigned int i,
882 bool *binary_found) {
883 const unsigned char *blob = sh_css_blob_info[i].blob;
884 unsigned int size = sh_css_blob_info[i].header.blob.size;
885
886 if ((!info) || (!binary_found))
887 return -EINVAL;
888
889 *info = sh_css_blob_info[i].header.info.isp;
890 *binary_found = blob;
891 info->blob_index = i;
892 /* we don't have this binary, skip it */
893 if (!size)
894 return 0;
895
896 info->xmem_addr = sh_css_load_blob(blob, size);
897 if (!info->xmem_addr)
898 return -ENOMEM;
899 return 0;
900 }
901
902 /* When binaries are put at the beginning, they will only
903 * be selected if no other primary matches.
904 */
905 int
ia_css_binary_init_infos(void)906 ia_css_binary_init_infos(void) {
907 unsigned int i;
908 unsigned int num_of_isp_binaries = sh_css_num_binaries - NUM_OF_SPS - NUM_OF_BLS;
909
910 if (num_of_isp_binaries == 0)
911 return 0;
912
913 all_binaries = kvmalloc(num_of_isp_binaries * sizeof(*all_binaries),
914 GFP_KERNEL);
915 if (!all_binaries)
916 return -ENOMEM;
917
918 for (i = 0; i < num_of_isp_binaries; i++)
919 {
920 int ret;
921 struct ia_css_binary_xinfo *binary = &all_binaries[i];
922 bool binary_found;
923
924 ret = binary_init_info(binary, i, &binary_found);
925 if (ret)
926 return ret;
927 if (!binary_found)
928 continue;
929 /* Prepend new binary information */
930 binary->next = binary_infos[binary->sp.pipeline.mode];
931 binary_infos[binary->sp.pipeline.mode] = binary;
932 binary->blob = &sh_css_blob_info[i];
933 binary->mem_offsets = sh_css_blob_info[i].mem_offsets;
934 }
935 return 0;
936 }
937
938 int
ia_css_binary_uninit(void)939 ia_css_binary_uninit(void) {
940 unsigned int i;
941 struct ia_css_binary_xinfo *b;
942
943 for (i = 0; i < IA_CSS_BINARY_NUM_MODES; i++)
944 {
945 for (b = binary_infos[i]; b; b = b->next) {
946 if (b->xmem_addr)
947 hmm_free(b->xmem_addr);
948 b->xmem_addr = mmgr_NULL;
949 }
950 binary_infos[i] = NULL;
951 }
952 kvfree(all_binaries);
953 return 0;
954 }
955
956 /* @brief Compute decimation factor for 3A statistics and shading correction.
957 *
958 * @param[in] width Frame width in pixels.
959 * @param[in] height Frame height in pixels.
960 * @return Log2 of decimation factor (= grid cell size) in bayer quads.
961 */
962 static int
binary_grid_deci_factor_log2(int width,int height)963 binary_grid_deci_factor_log2(int width, int height)
964 {
965 /* 3A/Shading decimation factor spcification (at August 2008)
966 * ------------------------------------------------------------------
967 * [Image Width (BQ)] [Decimation Factor (BQ)] [Resulting grid cells]
968 #ifndef ISP2401
969 * 1280 ?c 32 40 ?c
970 * 640 ?c 1279 16 40 ?c 80
971 * ?c 639 8 ?c 80
972 #else
973 * from 1280 32 from 40
974 * from 640 to 1279 16 from 40 to 80
975 * to 639 8 to 80
976 #endif
977 * ------------------------------------------------------------------
978 */
979 /* Maximum and minimum decimation factor by the specification */
980 #define MAX_SPEC_DECI_FACT_LOG2 5
981 #define MIN_SPEC_DECI_FACT_LOG2 3
982 /* the smallest frame width in bayer quads when decimation factor (log2) is 5 or 4, by the specification */
983 #define DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ 1280
984 #define DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ 640
985
986 int smallest_factor; /* the smallest factor (log2) where the number of cells does not exceed the limitation */
987 int spec_factor; /* the factor (log2) which satisfies the specification */
988
989 /* Currently supported maximum width and height are 5120(=80*64) and 3840(=60*64). */
990 assert(ISP_BQ_GRID_WIDTH(width,
991 MAX_SPEC_DECI_FACT_LOG2) <= SH_CSS_MAX_BQ_GRID_WIDTH);
992 assert(ISP_BQ_GRID_HEIGHT(height,
993 MAX_SPEC_DECI_FACT_LOG2) <= SH_CSS_MAX_BQ_GRID_HEIGHT);
994
995 /* Compute the smallest factor. */
996 smallest_factor = MAX_SPEC_DECI_FACT_LOG2;
997 while (ISP_BQ_GRID_WIDTH(width,
998 smallest_factor - 1) <= SH_CSS_MAX_BQ_GRID_WIDTH &&
999 ISP_BQ_GRID_HEIGHT(height, smallest_factor - 1) <= SH_CSS_MAX_BQ_GRID_HEIGHT
1000 && smallest_factor > MIN_SPEC_DECI_FACT_LOG2)
1001 smallest_factor--;
1002
1003 /* Get the factor by the specification. */
1004 if (_ISP_BQS(width) >= DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ)
1005 spec_factor = 5;
1006 else if (_ISP_BQS(width) >= DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ)
1007 spec_factor = 4;
1008 else
1009 spec_factor = 3;
1010
1011 /* If smallest_factor is smaller than or equal to spec_factor, choose spec_factor to follow the specification.
1012 If smallest_factor is larger than spec_factor, choose smallest_factor.
1013
1014 ex. width=2560, height=1920
1015 smallest_factor=4, spec_factor=5
1016 smallest_factor < spec_factor -> return spec_factor
1017
1018 ex. width=300, height=3000
1019 smallest_factor=5, spec_factor=3
1020 smallest_factor > spec_factor -> return smallest_factor
1021 */
1022 return max(smallest_factor, spec_factor);
1023
1024 #undef MAX_SPEC_DECI_FACT_LOG2
1025 #undef MIN_SPEC_DECI_FACT_LOG2
1026 #undef DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ
1027 #undef DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ
1028 }
1029
1030 static int
binary_in_frame_padded_width(int in_frame_width,int isp_internal_width,int dvs_env_width,int stream_config_left_padding,int left_cropping,bool need_scaling)1031 binary_in_frame_padded_width(int in_frame_width,
1032 int isp_internal_width,
1033 int dvs_env_width,
1034 int stream_config_left_padding,
1035 int left_cropping,
1036 bool need_scaling)
1037 {
1038 int rval;
1039 int nr_of_left_paddings; /* number of paddings pixels on the left of an image line */
1040
1041 #if defined(ISP2401)
1042 /* the output image line of Input System 2401 does not have the left paddings */
1043 nr_of_left_paddings = 0;
1044 #else
1045 /* in other cases, the left padding pixels are always 128 */
1046 nr_of_left_paddings = 2 * ISP_VEC_NELEMS;
1047 #endif
1048 if (need_scaling) {
1049 /* In SDV use-case, we need to match left-padding of
1050 * primary and the video binary. */
1051 if (stream_config_left_padding != -1) {
1052 /* Different than before, we do left&right padding. */
1053 rval =
1054 CEIL_MUL(in_frame_width + nr_of_left_paddings,
1055 2 * ISP_VEC_NELEMS);
1056 } else {
1057 /* Different than before, we do left&right padding. */
1058 in_frame_width += dvs_env_width;
1059 rval =
1060 CEIL_MUL(in_frame_width +
1061 (left_cropping ? nr_of_left_paddings : 0),
1062 2 * ISP_VEC_NELEMS);
1063 }
1064 } else {
1065 rval = isp_internal_width;
1066 }
1067
1068 return rval;
1069 }
1070
1071 int
ia_css_binary_fill_info(const struct ia_css_binary_xinfo * xinfo,bool online,bool two_ppc,enum atomisp_input_format stream_format,const struct ia_css_frame_info * in_info,const struct ia_css_frame_info * bds_out_info,const struct ia_css_frame_info * out_info[],const struct ia_css_frame_info * vf_info,struct ia_css_binary * binary,struct ia_css_resolution * dvs_env,int stream_config_left_padding,bool accelerator)1072 ia_css_binary_fill_info(const struct ia_css_binary_xinfo *xinfo,
1073 bool online,
1074 bool two_ppc,
1075 enum atomisp_input_format stream_format,
1076 const struct ia_css_frame_info *in_info, /* can be NULL */
1077 const struct ia_css_frame_info *bds_out_info, /* can be NULL */
1078 const struct ia_css_frame_info *out_info[], /* can be NULL */
1079 const struct ia_css_frame_info *vf_info, /* can be NULL */
1080 struct ia_css_binary *binary,
1081 struct ia_css_resolution *dvs_env,
1082 int stream_config_left_padding,
1083 bool accelerator) {
1084 const struct ia_css_binary_info *info = &xinfo->sp;
1085 unsigned int dvs_env_width = 0,
1086 dvs_env_height = 0,
1087 vf_log_ds = 0,
1088 s3a_log_deci = 0,
1089 bits_per_pixel = 0,
1090 /* Resolution at SC/3A/DIS kernel. */
1091 sc_3a_dis_width = 0,
1092 /* Resolution at SC/3A/DIS kernel. */
1093 sc_3a_dis_padded_width = 0,
1094 /* Resolution at SC/3A/DIS kernel. */
1095 sc_3a_dis_height = 0,
1096 isp_internal_width = 0,
1097 isp_internal_height = 0,
1098 s3a_isp_width = 0;
1099
1100 bool need_scaling = false;
1101 struct ia_css_resolution binary_dvs_env, internal_res;
1102 int err;
1103 unsigned int i;
1104 const struct ia_css_frame_info *bin_out_info = NULL;
1105
1106 assert(info);
1107 assert(binary);
1108
1109 binary->info = xinfo;
1110 if (!accelerator)
1111 {
1112 /* binary->css_params has been filled by accelerator itself. */
1113 err = ia_css_isp_param_allocate_isp_parameters(
1114 &binary->mem_params, &binary->css_params,
1115 &info->mem_initializers);
1116 if (err) {
1117 return err;
1118 }
1119 }
1120 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1121 {
1122 if (out_info[i] && (out_info[i]->res.width != 0)) {
1123 bin_out_info = out_info[i];
1124 break;
1125 }
1126 }
1127 if (in_info && bin_out_info)
1128 {
1129 need_scaling = (in_info->res.width != bin_out_info->res.width) ||
1130 (in_info->res.height != bin_out_info->res.height);
1131 }
1132
1133 /* binary_dvs_env has to be equal or larger than SH_CSS_MIN_DVS_ENVELOPE */
1134 binary_dvs_env.width = 0;
1135 binary_dvs_env.height = 0;
1136 ia_css_binary_dvs_env(info, dvs_env, &binary_dvs_env);
1137 dvs_env_width = binary_dvs_env.width;
1138 dvs_env_height = binary_dvs_env.height;
1139 binary->dvs_envelope.width = dvs_env_width;
1140 binary->dvs_envelope.height = dvs_env_height;
1141
1142 /* internal resolution calculation */
1143 internal_res.width = 0;
1144 internal_res.height = 0;
1145 ia_css_binary_internal_res(in_info, bds_out_info, bin_out_info, dvs_env,
1146 info, &internal_res);
1147 isp_internal_width = internal_res.width;
1148 isp_internal_height = internal_res.height;
1149
1150 /* internal frame info */
1151 if (bin_out_info) /* { */
1152 binary->internal_frame_info.format = bin_out_info->format;
1153 /* } */
1154 binary->internal_frame_info.res.width = isp_internal_width;
1155 binary->internal_frame_info.padded_width = CEIL_MUL(isp_internal_width, 2 * ISP_VEC_NELEMS);
1156 binary->internal_frame_info.res.height = isp_internal_height;
1157 binary->internal_frame_info.raw_bit_depth = bits_per_pixel;
1158
1159 if (in_info)
1160 {
1161 binary->effective_in_frame_res.width = in_info->res.width;
1162 binary->effective_in_frame_res.height = in_info->res.height;
1163
1164 bits_per_pixel = in_info->raw_bit_depth;
1165
1166 /* input info */
1167 binary->in_frame_info.res.width = in_info->res.width +
1168 info->pipeline.left_cropping;
1169 binary->in_frame_info.res.height = in_info->res.height +
1170 info->pipeline.top_cropping;
1171
1172 binary->in_frame_info.res.width += dvs_env_width;
1173 binary->in_frame_info.res.height += dvs_env_height;
1174
1175 binary->in_frame_info.padded_width =
1176 binary_in_frame_padded_width(in_info->res.width,
1177 isp_internal_width,
1178 dvs_env_width,
1179 stream_config_left_padding,
1180 info->pipeline.left_cropping,
1181 need_scaling);
1182
1183 binary->in_frame_info.format = in_info->format;
1184 binary->in_frame_info.raw_bayer_order = in_info->raw_bayer_order;
1185 binary->in_frame_info.crop_info = in_info->crop_info;
1186 }
1187
1188 if (online)
1189 {
1190 bits_per_pixel = ia_css_util_input_format_bpp(
1191 stream_format, two_ppc);
1192 }
1193 binary->in_frame_info.raw_bit_depth = bits_per_pixel;
1194
1195 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1196 {
1197 if (out_info[i]) {
1198 binary->out_frame_info[i].res.width = out_info[i]->res.width;
1199 binary->out_frame_info[i].res.height = out_info[i]->res.height;
1200 binary->out_frame_info[i].padded_width = out_info[i]->padded_width;
1201 if (info->pipeline.mode == IA_CSS_BINARY_MODE_COPY) {
1202 binary->out_frame_info[i].raw_bit_depth = bits_per_pixel;
1203 } else {
1204 /* Only relevant for RAW format.
1205 * At the moment, all outputs are raw, 16 bit per pixel, except for copy.
1206 * To do this cleanly, the binary should specify in its info
1207 * the bit depth per output channel.
1208 */
1209 binary->out_frame_info[i].raw_bit_depth = 16;
1210 }
1211 binary->out_frame_info[i].format = out_info[i]->format;
1212 }
1213 }
1214
1215 if (vf_info && (vf_info->res.width != 0))
1216 {
1217 err = ia_css_vf_configure(binary, bin_out_info,
1218 (struct ia_css_frame_info *)vf_info, &vf_log_ds);
1219 if (err) {
1220 if (!accelerator) {
1221 ia_css_isp_param_destroy_isp_parameters(
1222 &binary->mem_params,
1223 &binary->css_params);
1224 }
1225 return err;
1226 }
1227 }
1228 binary->vf_downscale_log2 = vf_log_ds;
1229
1230 binary->online = online;
1231 binary->input_format = stream_format;
1232
1233 /* viewfinder output info */
1234 if ((vf_info) && (vf_info->res.width != 0))
1235 {
1236 unsigned int vf_out_vecs, vf_out_width, vf_out_height;
1237
1238 binary->vf_frame_info.format = vf_info->format;
1239 if (!bin_out_info)
1240 return -EINVAL;
1241 vf_out_vecs = __ISP_VF_OUTPUT_WIDTH_VECS(bin_out_info->padded_width,
1242 vf_log_ds);
1243 vf_out_width = _ISP_VF_OUTPUT_WIDTH(vf_out_vecs);
1244 vf_out_height = _ISP_VF_OUTPUT_HEIGHT(bin_out_info->res.height,
1245 vf_log_ds);
1246
1247 /* For preview mode, output pin is used instead of vf. */
1248 if (info->pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW) {
1249 binary->out_frame_info[0].res.width =
1250 (bin_out_info->res.width >> vf_log_ds);
1251 binary->out_frame_info[0].padded_width = vf_out_width;
1252 binary->out_frame_info[0].res.height = vf_out_height;
1253
1254 binary->vf_frame_info.res.width = 0;
1255 binary->vf_frame_info.padded_width = 0;
1256 binary->vf_frame_info.res.height = 0;
1257 } else {
1258 /* we also store the raw downscaled width. This is
1259 * used for digital zoom in preview to zoom only on
1260 * the width that we actually want to keep, not on
1261 * the aligned width. */
1262 binary->vf_frame_info.res.width =
1263 (bin_out_info->res.width >> vf_log_ds);
1264 binary->vf_frame_info.padded_width = vf_out_width;
1265 binary->vf_frame_info.res.height = vf_out_height;
1266 }
1267 } else
1268 {
1269 binary->vf_frame_info.res.width = 0;
1270 binary->vf_frame_info.padded_width = 0;
1271 binary->vf_frame_info.res.height = 0;
1272 }
1273
1274 if (info->enable.ca_gdc)
1275 {
1276 binary->morph_tbl_width =
1277 _ISP_MORPH_TABLE_WIDTH(isp_internal_width);
1278 binary->morph_tbl_aligned_width =
1279 _ISP_MORPH_TABLE_ALIGNED_WIDTH(isp_internal_width);
1280 binary->morph_tbl_height =
1281 _ISP_MORPH_TABLE_HEIGHT(isp_internal_height);
1282 } else
1283 {
1284 binary->morph_tbl_width = 0;
1285 binary->morph_tbl_aligned_width = 0;
1286 binary->morph_tbl_height = 0;
1287 }
1288
1289 sc_3a_dis_width = binary->in_frame_info.res.width;
1290 sc_3a_dis_padded_width = binary->in_frame_info.padded_width;
1291 sc_3a_dis_height = binary->in_frame_info.res.height;
1292 if (bds_out_info && in_info &&
1293 bds_out_info->res.width != in_info->res.width)
1294 {
1295 /* TODO: Next, "internal_frame_info" should be derived from
1296 * bds_out. So this part will change once it is in place! */
1297 sc_3a_dis_width = bds_out_info->res.width + info->pipeline.left_cropping;
1298 sc_3a_dis_padded_width = isp_internal_width;
1299 sc_3a_dis_height = isp_internal_height;
1300 }
1301
1302 s3a_isp_width = _ISP_S3A_ELEMS_ISP_WIDTH(sc_3a_dis_padded_width,
1303 info->pipeline.left_cropping);
1304 if (info->s3a.fixed_s3a_deci_log)
1305 {
1306 s3a_log_deci = info->s3a.fixed_s3a_deci_log;
1307 } else
1308 {
1309 s3a_log_deci = binary_grid_deci_factor_log2(s3a_isp_width,
1310 sc_3a_dis_height);
1311 }
1312 binary->deci_factor_log2 = s3a_log_deci;
1313
1314 if (info->enable.s3a)
1315 {
1316 binary->s3atbl_width =
1317 _ISP_S3ATBL_WIDTH(sc_3a_dis_width,
1318 s3a_log_deci);
1319 binary->s3atbl_height =
1320 _ISP_S3ATBL_HEIGHT(sc_3a_dis_height,
1321 s3a_log_deci);
1322 binary->s3atbl_isp_width =
1323 _ISP_S3ATBL_ISP_WIDTH(s3a_isp_width,
1324 s3a_log_deci);
1325 binary->s3atbl_isp_height =
1326 _ISP_S3ATBL_ISP_HEIGHT(sc_3a_dis_height,
1327 s3a_log_deci);
1328 } else
1329 {
1330 binary->s3atbl_width = 0;
1331 binary->s3atbl_height = 0;
1332 binary->s3atbl_isp_width = 0;
1333 binary->s3atbl_isp_height = 0;
1334 }
1335
1336 if (info->enable.sc)
1337 {
1338 if (!IS_ISP2401) {
1339 binary->sctbl_width_per_color = _ISP2400_SCTBL_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci);
1340 binary->sctbl_aligned_width_per_color = ISP2400_SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR;
1341 binary->sctbl_height = _ISP2400_SCTBL_HEIGHT(sc_3a_dis_height, s3a_log_deci);
1342 } else {
1343 binary->sctbl_width_per_color = _ISP2401_SCTBL_WIDTH_PER_COLOR(isp_internal_width, s3a_log_deci);
1344 binary->sctbl_aligned_width_per_color = ISP2401_SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR;
1345 binary->sctbl_height = _ISP2401_SCTBL_HEIGHT(isp_internal_height, s3a_log_deci);
1346 binary->sctbl_legacy_width_per_color = _ISP_SCTBL_LEGACY_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci);
1347 binary->sctbl_legacy_height = _ISP_SCTBL_LEGACY_HEIGHT(sc_3a_dis_height, s3a_log_deci);
1348 }
1349 } else
1350 {
1351 binary->sctbl_width_per_color = 0;
1352 binary->sctbl_aligned_width_per_color = 0;
1353 binary->sctbl_height = 0;
1354 if (IS_ISP2401) {
1355 binary->sctbl_legacy_width_per_color = 0;
1356 binary->sctbl_legacy_height = 0;
1357 }
1358 }
1359 ia_css_sdis_init_info(&binary->dis,
1360 sc_3a_dis_width,
1361 sc_3a_dis_padded_width,
1362 sc_3a_dis_height,
1363 info->pipeline.isp_pipe_version,
1364 info->enable.dis);
1365 if (info->pipeline.left_cropping)
1366 binary->left_padding = 2 * ISP_VEC_NELEMS - info->pipeline.left_cropping;
1367 else
1368 binary->left_padding = 0;
1369
1370 return 0;
1371 }
1372
__ia_css_binary_find(struct ia_css_binary_descr * descr,struct ia_css_binary * binary)1373 static int __ia_css_binary_find(struct ia_css_binary_descr *descr,
1374 struct ia_css_binary *binary) {
1375 int mode;
1376 bool online;
1377 bool two_ppc;
1378 enum atomisp_input_format stream_format;
1379 const struct ia_css_frame_info *req_in_info,
1380 *req_bds_out_info,
1381 *req_out_info[IA_CSS_BINARY_MAX_OUTPUT_PORTS],
1382 *req_bin_out_info = NULL,
1383 *req_vf_info;
1384
1385 struct ia_css_binary_xinfo *xcandidate;
1386 #ifndef ISP2401
1387 bool need_ds, need_dz, need_dvs, need_xnr, need_dpc;
1388 #else
1389 bool need_ds, need_dz, need_dvs, need_xnr, need_dpc, need_tnr;
1390 #endif
1391 bool striped;
1392 bool enable_yuv_ds;
1393 bool enable_high_speed;
1394 bool enable_dvs_6axis;
1395 bool enable_reduced_pipe;
1396 bool enable_capture_pp_bli;
1397 #ifdef ISP2401
1398 bool enable_luma_only;
1399 #endif
1400 int err = -EINVAL;
1401 bool continuous;
1402 unsigned int isp_pipe_version;
1403 struct ia_css_resolution dvs_env, internal_res;
1404 unsigned int i;
1405
1406 assert(descr);
1407 /* MW: used after an error check, may accept NULL, but doubtfull */
1408 assert(binary);
1409
1410 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1411 "ia_css_binary_find() enter: descr=%p, (mode=%d), binary=%p\n",
1412 descr, descr->mode,
1413 binary);
1414
1415 mode = descr->mode;
1416 online = descr->online;
1417 two_ppc = descr->two_ppc;
1418 stream_format = descr->stream_format;
1419 req_in_info = descr->in_info;
1420 req_bds_out_info = descr->bds_out_info;
1421 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1422 {
1423 req_out_info[i] = descr->out_info[i];
1424 if (req_out_info[i] && (req_out_info[i]->res.width != 0))
1425 req_bin_out_info = req_out_info[i];
1426 }
1427 if (!req_bin_out_info)
1428 return -EINVAL;
1429 #ifndef ISP2401
1430 req_vf_info = descr->vf_info;
1431 #else
1432
1433 if ((descr->vf_info) && (descr->vf_info->res.width == 0))
1434 /* width==0 means that there is no vf pin (e.g. in SkyCam preview case) */
1435 req_vf_info = NULL;
1436 else
1437 req_vf_info = descr->vf_info;
1438 #endif
1439
1440 need_xnr = descr->enable_xnr;
1441 need_ds = descr->enable_fractional_ds;
1442 need_dz = false;
1443 need_dvs = false;
1444 need_dpc = descr->enable_dpc;
1445 #ifdef ISP2401
1446 need_tnr = descr->enable_tnr;
1447 #endif
1448 enable_yuv_ds = descr->enable_yuv_ds;
1449 enable_high_speed = descr->enable_high_speed;
1450 enable_dvs_6axis = descr->enable_dvs_6axis;
1451 enable_reduced_pipe = descr->enable_reduced_pipe;
1452 enable_capture_pp_bli = descr->enable_capture_pp_bli;
1453 #ifdef ISP2401
1454 enable_luma_only = descr->enable_luma_only;
1455 #endif
1456 continuous = descr->continuous;
1457 striped = descr->striped;
1458 isp_pipe_version = descr->isp_pipe_version;
1459
1460 dvs_env.width = 0;
1461 dvs_env.height = 0;
1462 internal_res.width = 0;
1463 internal_res.height = 0;
1464
1465 if (mode == IA_CSS_BINARY_MODE_VIDEO)
1466 {
1467 dvs_env = descr->dvs_env;
1468 need_dz = descr->enable_dz;
1469 /* Video is the only mode that has a nodz variant. */
1470 need_dvs = dvs_env.width || dvs_env.height;
1471 }
1472
1473 /* print a map of the binary file */
1474 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "BINARY INFO:\n");
1475 for (i = 0; i < IA_CSS_BINARY_NUM_MODES; i++)
1476 {
1477 xcandidate = binary_infos[i];
1478 if (xcandidate) {
1479 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%d:\n", i);
1480 while (xcandidate) {
1481 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, " Name:%s Type:%d Cont:%d\n",
1482 xcandidate->blob->name, xcandidate->type,
1483 xcandidate->sp.enable.continuous);
1484 xcandidate = xcandidate->next;
1485 }
1486 }
1487 }
1488
1489 /* printf("sh_css_binary_find: pipe version %d\n", isp_pipe_version); */
1490 for (xcandidate = binary_infos[mode]; xcandidate;
1491 xcandidate = xcandidate->next)
1492 {
1493 struct ia_css_binary_info *candidate = &xcandidate->sp;
1494 /* printf("sh_css_binary_find: evaluating candidate:
1495 * %d\n",candidate->id); */
1496 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1497 "ia_css_binary_find() candidate = %p, mode = %d ID = %d\n",
1498 candidate, candidate->pipeline.mode, candidate->id);
1499
1500 /*
1501 * MW: Only a limited set of jointly configured binaries can
1502 * be used in a continuous preview/video mode unless it is
1503 * the copy mode and runs on SP.
1504 */
1505 if (!candidate->enable.continuous &&
1506 continuous && (mode != IA_CSS_BINARY_MODE_COPY)) {
1507 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1508 "ia_css_binary_find() [%d] continue: !%d && %d && (%d != %d)\n",
1509 __LINE__, candidate->enable.continuous,
1510 continuous, mode,
1511 IA_CSS_BINARY_MODE_COPY);
1512 continue;
1513 }
1514 if (striped && candidate->iterator.num_stripes == 1) {
1515 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1516 "ia_css_binary_find() [%d] continue: binary is not striped\n",
1517 __LINE__);
1518 continue;
1519 }
1520
1521 if (candidate->pipeline.isp_pipe_version != isp_pipe_version &&
1522 (mode != IA_CSS_BINARY_MODE_COPY) &&
1523 (mode != IA_CSS_BINARY_MODE_CAPTURE_PP) &&
1524 (mode != IA_CSS_BINARY_MODE_VF_PP)) {
1525 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1526 "ia_css_binary_find() [%d] continue: (%d != %d)\n",
1527 __LINE__,
1528 candidate->pipeline.isp_pipe_version, isp_pipe_version);
1529 continue;
1530 }
1531 if (!candidate->enable.reduced_pipe && enable_reduced_pipe) {
1532 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1533 "ia_css_binary_find() [%d] continue: !%d && %d\n",
1534 __LINE__,
1535 candidate->enable.reduced_pipe,
1536 enable_reduced_pipe);
1537 continue;
1538 }
1539 if (!candidate->enable.dvs_6axis && enable_dvs_6axis) {
1540 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1541 "ia_css_binary_find() [%d] continue: !%d && %d\n",
1542 __LINE__,
1543 candidate->enable.dvs_6axis,
1544 enable_dvs_6axis);
1545 continue;
1546 }
1547 if (candidate->enable.high_speed && !enable_high_speed) {
1548 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1549 "ia_css_binary_find() [%d] continue: %d && !%d\n",
1550 __LINE__,
1551 candidate->enable.high_speed,
1552 enable_high_speed);
1553 continue;
1554 }
1555 if (!candidate->enable.xnr && need_xnr) {
1556 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1557 "ia_css_binary_find() [%d] continue: %d && !%d\n",
1558 __LINE__,
1559 candidate->enable.xnr,
1560 need_xnr);
1561 continue;
1562 }
1563 if (!(candidate->enable.ds & 2) && enable_yuv_ds) {
1564 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1565 "ia_css_binary_find() [%d] continue: !%d && %d\n",
1566 __LINE__,
1567 ((candidate->enable.ds & 2) != 0),
1568 enable_yuv_ds);
1569 continue;
1570 }
1571 if ((candidate->enable.ds & 2) && !enable_yuv_ds) {
1572 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1573 "ia_css_binary_find() [%d] continue: %d && !%d\n",
1574 __LINE__,
1575 ((candidate->enable.ds & 2) != 0),
1576 enable_yuv_ds);
1577 continue;
1578 }
1579
1580 if (mode == IA_CSS_BINARY_MODE_VIDEO &&
1581 candidate->enable.ds && need_ds)
1582 need_dz = false;
1583
1584 /* when we require vf output, we need to have vf_veceven */
1585 if ((req_vf_info) && !(candidate->enable.vf_veceven ||
1586 /* or variable vf vec even */
1587 candidate->vf_dec.is_variable ||
1588 /* or more than one output pin. */
1589 xcandidate->num_output_pins > 1)) {
1590 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1591 "ia_css_binary_find() [%d] continue: (%p != NULL) && !(%d || %d || (%d >%d))\n",
1592 __LINE__, req_vf_info,
1593 candidate->enable.vf_veceven,
1594 candidate->vf_dec.is_variable,
1595 xcandidate->num_output_pins, 1);
1596 continue;
1597 }
1598 if (!candidate->enable.dvs_envelope && need_dvs) {
1599 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1600 "ia_css_binary_find() [%d] continue: !%d && %d\n",
1601 __LINE__,
1602 candidate->enable.dvs_envelope, (int)need_dvs);
1603 continue;
1604 }
1605 /* internal_res check considers input, output, and dvs envelope sizes */
1606 ia_css_binary_internal_res(req_in_info, req_bds_out_info,
1607 req_bin_out_info, &dvs_env, candidate, &internal_res);
1608 if (internal_res.width > candidate->internal.max_width) {
1609 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1610 "ia_css_binary_find() [%d] continue: (%d > %d)\n",
1611 __LINE__, internal_res.width,
1612 candidate->internal.max_width);
1613 continue;
1614 }
1615 if (internal_res.height > candidate->internal.max_height) {
1616 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1617 "ia_css_binary_find() [%d] continue: (%d > %d)\n",
1618 __LINE__, internal_res.height,
1619 candidate->internal.max_height);
1620 continue;
1621 }
1622 if (!candidate->enable.ds && need_ds && !(xcandidate->num_output_pins > 1)) {
1623 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1624 "ia_css_binary_find() [%d] continue: !%d && %d\n",
1625 __LINE__, candidate->enable.ds, (int)need_ds);
1626 continue;
1627 }
1628 if (!candidate->enable.uds && !candidate->enable.dvs_6axis && need_dz) {
1629 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1630 "ia_css_binary_find() [%d] continue: !%d && !%d && %d\n",
1631 __LINE__, candidate->enable.uds,
1632 candidate->enable.dvs_6axis, (int)need_dz);
1633 continue;
1634 }
1635 if (online && candidate->input.source == IA_CSS_BINARY_INPUT_MEMORY) {
1636 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1637 "ia_css_binary_find() [%d] continue: %d && (%d == %d)\n",
1638 __LINE__, online, candidate->input.source,
1639 IA_CSS_BINARY_INPUT_MEMORY);
1640 continue;
1641 }
1642 if (!online && candidate->input.source == IA_CSS_BINARY_INPUT_SENSOR) {
1643 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1644 "ia_css_binary_find() [%d] continue: !%d && (%d == %d)\n",
1645 __LINE__, online, candidate->input.source,
1646 IA_CSS_BINARY_INPUT_SENSOR);
1647 continue;
1648 }
1649 if (req_bin_out_info->res.width < candidate->output.min_width ||
1650 req_bin_out_info->res.width > candidate->output.max_width) {
1651 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1652 "ia_css_binary_find() [%d] continue: (%d > %d) || (%d < %d)\n",
1653 __LINE__,
1654 req_bin_out_info->padded_width,
1655 candidate->output.min_width,
1656 req_bin_out_info->padded_width,
1657 candidate->output.max_width);
1658 continue;
1659 }
1660 if (xcandidate->num_output_pins > 1 &&
1661 /* in case we have a second output pin, */
1662 req_vf_info) { /* and we need vf output. */
1663 if (req_vf_info->res.width > candidate->output.max_width) {
1664 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1665 "ia_css_binary_find() [%d] continue: (%d < %d)\n",
1666 __LINE__,
1667 req_vf_info->res.width,
1668 candidate->output.max_width);
1669 continue;
1670 }
1671 }
1672 if (req_in_info->padded_width > candidate->input.max_width) {
1673 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1674 "ia_css_binary_find() [%d] continue: (%d > %d)\n",
1675 __LINE__, req_in_info->padded_width,
1676 candidate->input.max_width);
1677 continue;
1678 }
1679 if (!binary_supports_output_format(xcandidate, req_bin_out_info->format)) {
1680 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1681 "ia_css_binary_find() [%d] continue: !%d\n",
1682 __LINE__,
1683 binary_supports_output_format(xcandidate, req_bin_out_info->format));
1684 continue;
1685 }
1686 if (xcandidate->num_output_pins > 1 &&
1687 /* in case we have a second output pin, */
1688 req_vf_info && /* and we need vf output. */
1689 /* check if the required vf format
1690 is supported. */
1691 !binary_supports_output_format(xcandidate, req_vf_info->format)) {
1692 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1693 "ia_css_binary_find() [%d] continue: (%d > %d) && (%p != NULL) && !%d\n",
1694 __LINE__, xcandidate->num_output_pins, 1,
1695 req_vf_info,
1696 binary_supports_output_format(xcandidate, req_vf_info->format));
1697 continue;
1698 }
1699
1700 /* Check if vf_veceven supports the requested vf format */
1701 if (xcandidate->num_output_pins == 1 &&
1702 req_vf_info && candidate->enable.vf_veceven &&
1703 !binary_supports_vf_format(xcandidate, req_vf_info->format)) {
1704 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1705 "ia_css_binary_find() [%d] continue: (%d == %d) && (%p != NULL) && %d && !%d\n",
1706 __LINE__, xcandidate->num_output_pins, 1,
1707 req_vf_info, candidate->enable.vf_veceven,
1708 binary_supports_vf_format(xcandidate, req_vf_info->format));
1709 continue;
1710 }
1711
1712 /* Check if vf_veceven supports the requested vf width */
1713 if (xcandidate->num_output_pins == 1 &&
1714 req_vf_info && candidate->enable.vf_veceven) { /* and we need vf output. */
1715 if (req_vf_info->res.width > candidate->output.max_width) {
1716 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1717 "ia_css_binary_find() [%d] continue: (%d < %d)\n",
1718 __LINE__,
1719 req_vf_info->res.width,
1720 candidate->output.max_width);
1721 continue;
1722 }
1723 }
1724
1725 if (!supports_bds_factor(candidate->bds.supported_bds_factors,
1726 descr->required_bds_factor)) {
1727 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1728 "ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n",
1729 __LINE__, candidate->bds.supported_bds_factors,
1730 descr->required_bds_factor);
1731 continue;
1732 }
1733
1734 if (!candidate->enable.dpc && need_dpc) {
1735 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1736 "ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n",
1737 __LINE__, candidate->enable.dpc,
1738 descr->enable_dpc);
1739 continue;
1740 }
1741
1742 if (candidate->uds.use_bci && enable_capture_pp_bli) {
1743 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1744 "ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n",
1745 __LINE__, candidate->uds.use_bci,
1746 descr->enable_capture_pp_bli);
1747 continue;
1748 }
1749
1750 #ifdef ISP2401
1751 if (candidate->enable.luma_only != enable_luma_only) {
1752 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1753 "ia_css_binary_find() [%d] continue: %d != %d\n",
1754 __LINE__, candidate->enable.luma_only,
1755 descr->enable_luma_only);
1756 continue;
1757 }
1758
1759 if (!candidate->enable.tnr && need_tnr) {
1760 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1761 "ia_css_binary_find() [%d] continue: !%d && %d\n",
1762 __LINE__, candidate->enable.tnr,
1763 descr->enable_tnr);
1764 continue;
1765 }
1766
1767 #endif
1768 /* reconfigure any variable properties of the binary */
1769 err = ia_css_binary_fill_info(xcandidate, online, two_ppc,
1770 stream_format, req_in_info,
1771 req_bds_out_info,
1772 req_out_info, req_vf_info,
1773 binary, &dvs_env,
1774 descr->stream_config_left_padding,
1775 false);
1776
1777 if (err)
1778 break;
1779 binary_init_metrics(&binary->metrics, &binary->info->sp);
1780 break;
1781 }
1782
1783 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1784 "ia_css_binary_find() selected = %p, mode = %d ID = %d\n",
1785 xcandidate, xcandidate ? xcandidate->sp.pipeline.mode : 0, xcandidate ? xcandidate->sp.id : 0);
1786
1787 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1788 "ia_css_binary_find() leave: return_err=%d\n", err);
1789
1790 if (!err && xcandidate)
1791 dev_dbg(atomisp_dev,
1792 "Using binary %s (id %d), type %d, mode %d, continuous %s\n",
1793 xcandidate->blob->name,
1794 xcandidate->sp.id,
1795 xcandidate->type,
1796 xcandidate->sp.pipeline.mode,
1797 xcandidate->sp.enable.continuous ? "true" : "false");
1798
1799
1800 return err;
1801 }
1802
ia_css_binary_find(struct ia_css_binary_descr * descr,struct ia_css_binary * binary)1803 int ia_css_binary_find(struct ia_css_binary_descr *descr,
1804 struct ia_css_binary *binary)
1805 {
1806 int ret = __ia_css_binary_find(descr, binary);
1807
1808 if (unlikely(ret)) {
1809 dev_dbg(atomisp_dev, "Seeking for binary failed at:");
1810 dump_stack();
1811 }
1812
1813 return ret;
1814 }
1815
1816 unsigned
ia_css_binary_max_vf_width(void)1817 ia_css_binary_max_vf_width(void)
1818 {
1819 /* This is (should be) true for IPU1 and IPU2 */
1820 /* For IPU3 (SkyCam) this pointer is guaranteed to be NULL simply because such a binary does not exist */
1821 if (binary_infos[IA_CSS_BINARY_MODE_VF_PP])
1822 return binary_infos[IA_CSS_BINARY_MODE_VF_PP]->sp.output.max_width;
1823 return 0;
1824 }
1825
1826 void
ia_css_binary_destroy_isp_parameters(struct ia_css_binary * binary)1827 ia_css_binary_destroy_isp_parameters(struct ia_css_binary *binary)
1828 {
1829 if (binary) {
1830 ia_css_isp_param_destroy_isp_parameters(&binary->mem_params,
1831 &binary->css_params);
1832 }
1833 }
1834
1835 void
ia_css_binary_get_isp_binaries(struct ia_css_binary_xinfo ** binaries,uint32_t * num_isp_binaries)1836 ia_css_binary_get_isp_binaries(struct ia_css_binary_xinfo **binaries,
1837 uint32_t *num_isp_binaries)
1838 {
1839 assert(binaries);
1840
1841 if (num_isp_binaries)
1842 *num_isp_binaries = 0;
1843
1844 *binaries = all_binaries;
1845 if (all_binaries && num_isp_binaries) {
1846 /* -1 to account for sp binary which is not stored in all_binaries */
1847 if (sh_css_num_binaries > 0)
1848 *num_isp_binaries = sh_css_num_binaries - 1;
1849 }
1850 }
1851