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 /* Computation results of the origin coordinate of bayer on the shading table. */
112 struct sh_css_shading_table_bayer_origin_compute_results {
113 u32 bayer_scale_hor_ratio_in; /* Horizontal ratio (in) of bayer scaling. */
114 u32 bayer_scale_hor_ratio_out; /* Horizontal ratio (out) of bayer scaling. */
115 u32 bayer_scale_ver_ratio_in; /* Vertical ratio (in) of bayer scaling. */
116 u32 bayer_scale_ver_ratio_out; /* Vertical ratio (out) of bayer scaling. */
117 u32 sc_bayer_origin_x_bqs_on_shading_table; /* X coordinate (in bqs) of bayer origin on shading table. */
118 u32 sc_bayer_origin_y_bqs_on_shading_table; /* Y coordinate (in bqs) of bayer origin on shading table. */
119 };
120
121 /* Get the requirements for the shading correction. */
122 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)123 ia_css_binary_compute_shading_table_bayer_origin(
124 const struct ia_css_binary *binary, /* [in] */
125 unsigned int required_bds_factor, /* [in] */
126 const struct ia_css_stream_config *stream_config, /* [in] */
127 struct sh_css_shading_table_bayer_origin_compute_results *res) /* [out] */
128 {
129 int err;
130
131 /* Numerator and denominator of the fixed bayer downscaling factor.
132 (numerator >= denominator) */
133 unsigned int bds_num, bds_den;
134
135 /* Horizontal/Vertical ratio of bayer scaling
136 between input area and output area. */
137 unsigned int bs_hor_ratio_in;
138 unsigned int bs_hor_ratio_out;
139 unsigned int bs_ver_ratio_in;
140 unsigned int bs_ver_ratio_out;
141
142 /* Left padding set by InputFormatter. */
143 unsigned int left_padding_bqs; /* in bqs */
144
145 /* Flag for the NEED_BDS_FACTOR_2_00 macro defined in isp kernels. */
146 unsigned int need_bds_factor_2_00;
147
148 /* Left padding adjusted inside the isp. */
149 unsigned int left_padding_adjusted_bqs; /* in bqs */
150
151 /* Bad pixels caused by filters.
152 NxN-filter (before/after bayer scaling) moves the image position
153 to right/bottom directions by a few pixels.
154 It causes bad pixels at left/top sides,
155 and effective bayer size decreases. */
156 unsigned int bad_bqs_on_left_before_bs; /* in bqs */
157 unsigned int bad_bqs_on_left_after_bs; /* in bqs */
158 unsigned int bad_bqs_on_top_before_bs; /* in bqs */
159 unsigned int bad_bqs_on_top_after_bs; /* in bqs */
160
161 /* Get the numerator and denominator of bayer downscaling factor. */
162 err = sh_css_bds_factor_get_numerator_denominator
163 (required_bds_factor, &bds_num, &bds_den);
164 if (err)
165 return err;
166
167 /* Set the horizontal/vertical ratio of bayer scaling
168 between input area and output area. */
169 bs_hor_ratio_in = bds_num;
170 bs_hor_ratio_out = bds_den;
171 bs_ver_ratio_in = bds_num;
172 bs_ver_ratio_out = bds_den;
173
174 /* Set the left padding set by InputFormatter. (ifmtr.c) */
175 if (stream_config->left_padding == -1)
176 left_padding_bqs = _ISP_BQS(binary->left_padding);
177 else
178 left_padding_bqs = (unsigned int)((int)ISP_VEC_NELEMS
179 - _ISP_BQS(stream_config->left_padding));
180
181 /* Set the left padding adjusted inside the isp.
182 When bds_factor 2.00 is needed, some padding is added to left_padding
183 inside the isp, before bayer downscaling. (raw.isp.c)
184 (Hopefully, left_crop/left_padding/top_crop should be defined in css
185 appropriately, depending on bds_factor.)
186 */
187 need_bds_factor_2_00 = ((binary->info->sp.bds.supported_bds_factors &
188 (PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_00) |
189 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_50) |
190 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_3_00) |
191 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_00) |
192 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_50) |
193 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_5_00) |
194 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_6_00) |
195 PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_8_00))) != 0);
196
197 if (need_bds_factor_2_00 && binary->info->sp.pipeline.left_cropping > 0)
198 left_padding_adjusted_bqs = left_padding_bqs + ISP_VEC_NELEMS;
199 else
200 left_padding_adjusted_bqs = left_padding_bqs;
201
202 /* Currently, the bad pixel caused by filters before bayer scaling
203 is NOT considered, because the bad pixel is subtle.
204 When some large filter is used in the future,
205 we need to consider the bad pixel.
206
207 Currently, when bds_factor isn't 1.00, 3x3 anti-alias filter is applied
208 to each color plane(Gr/R/B/Gb) before bayer downscaling.
209 This filter moves each color plane to right/bottom directions
210 by 1 pixel at the most, depending on downscaling factor.
211 */
212 bad_bqs_on_left_before_bs = 0;
213 bad_bqs_on_top_before_bs = 0;
214
215 /* Currently, the bad pixel caused by filters after bayer scaling
216 is NOT considered, because the bad pixel is subtle.
217 When some large filter is used in the future,
218 we need to consider the bad pixel.
219
220 Currently, when DPC&BNR is processed between bayer scaling and
221 shading correction, DPC&BNR moves each color plane to
222 right/bottom directions by 1 pixel.
223 */
224 bad_bqs_on_left_after_bs = 0;
225 bad_bqs_on_top_after_bs = 0;
226
227 /* Calculate the origin of bayer (real sensor data area)
228 located on the shading table during the shading correction. */
229 res->sc_bayer_origin_x_bqs_on_shading_table =
230 ((left_padding_adjusted_bqs + bad_bqs_on_left_before_bs)
231 * bs_hor_ratio_out + bs_hor_ratio_in / 2) / bs_hor_ratio_in
232 + bad_bqs_on_left_after_bs;
233 /* "+ bs_hor_ratio_in/2": rounding for division by bs_hor_ratio_in */
234 res->sc_bayer_origin_y_bqs_on_shading_table =
235 (bad_bqs_on_top_before_bs * bs_ver_ratio_out + bs_ver_ratio_in / 2) / bs_ver_ratio_in
236 + bad_bqs_on_top_after_bs;
237 /* "+ bs_ver_ratio_in/2": rounding for division by bs_ver_ratio_in */
238
239 res->bayer_scale_hor_ratio_in = (uint32_t)bs_hor_ratio_in;
240 res->bayer_scale_hor_ratio_out = (uint32_t)bs_hor_ratio_out;
241 res->bayer_scale_ver_ratio_in = (uint32_t)bs_ver_ratio_in;
242 res->bayer_scale_ver_ratio_out = (uint32_t)bs_ver_ratio_out;
243
244 return err;
245 }
246
247 /* Get the shading information of Shading Correction Type 1. */
248 static int
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)249 binary_get_shading_info_type_1(const struct ia_css_binary *binary, /* [in] */
250 unsigned int required_bds_factor, /* [in] */
251 const struct ia_css_stream_config *stream_config, /* [in] */
252 struct ia_css_shading_info *info) /* [out] */
253 {
254 int err;
255 struct sh_css_shading_table_bayer_origin_compute_results res;
256
257 assert(binary);
258 assert(info);
259
260 info->type = IA_CSS_SHADING_CORRECTION_TYPE_1;
261
262 info->info.type_1.enable = binary->info->sp.enable.sc;
263 info->info.type_1.num_hor_grids = binary->sctbl_width_per_color;
264 info->info.type_1.num_ver_grids = binary->sctbl_height;
265 info->info.type_1.bqs_per_grid_cell = (1 << binary->deci_factor_log2);
266
267 /* Initialize by default values. */
268 info->info.type_1.bayer_scale_hor_ratio_in = 1;
269 info->info.type_1.bayer_scale_hor_ratio_out = 1;
270 info->info.type_1.bayer_scale_ver_ratio_in = 1;
271 info->info.type_1.bayer_scale_ver_ratio_out = 1;
272 info->info.type_1.sc_bayer_origin_x_bqs_on_shading_table = 0;
273 info->info.type_1.sc_bayer_origin_y_bqs_on_shading_table = 0;
274
275 err = ia_css_binary_compute_shading_table_bayer_origin(
276 binary,
277 required_bds_factor,
278 stream_config,
279 &res);
280 if (err)
281 return err;
282
283 info->info.type_1.bayer_scale_hor_ratio_in = res.bayer_scale_hor_ratio_in;
284 info->info.type_1.bayer_scale_hor_ratio_out = res.bayer_scale_hor_ratio_out;
285 info->info.type_1.bayer_scale_ver_ratio_in = res.bayer_scale_ver_ratio_in;
286 info->info.type_1.bayer_scale_ver_ratio_out = res.bayer_scale_ver_ratio_out;
287 info->info.type_1.sc_bayer_origin_x_bqs_on_shading_table = res.sc_bayer_origin_x_bqs_on_shading_table;
288 info->info.type_1.sc_bayer_origin_y_bqs_on_shading_table = res.sc_bayer_origin_y_bqs_on_shading_table;
289
290 return err;
291 }
292
293
294 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)295 ia_css_binary_get_shading_info(const struct ia_css_binary *binary, /* [in] */
296 enum ia_css_shading_correction_type type, /* [in] */
297 unsigned int required_bds_factor, /* [in] */
298 const struct ia_css_stream_config *stream_config, /* [in] */
299 struct ia_css_shading_info *shading_info, /* [out] */
300 struct ia_css_pipe_config *pipe_config) /* [out] */
301 {
302 int err;
303
304 assert(binary);
305 assert(shading_info);
306
307 IA_CSS_ENTER_PRIVATE("binary=%p, type=%d, required_bds_factor=%d, stream_config=%p",
308 binary, type, required_bds_factor, stream_config);
309
310 if (type == IA_CSS_SHADING_CORRECTION_TYPE_1)
311 err = binary_get_shading_info_type_1(binary,
312 required_bds_factor,
313 stream_config,
314 shading_info);
315 else
316 err = -ENOTSUPP;
317
318 IA_CSS_LEAVE_ERR_PRIVATE(err);
319 return err;
320 }
321
sh_css_binary_common_grid_info(const struct ia_css_binary * binary,struct ia_css_grid_info * info)322 static void sh_css_binary_common_grid_info(const struct ia_css_binary *binary,
323 struct ia_css_grid_info *info)
324 {
325 assert(binary);
326 assert(info);
327
328 info->isp_in_width = binary->internal_frame_info.res.width;
329 info->isp_in_height = binary->internal_frame_info.res.height;
330
331 info->vamem_type = IA_CSS_VAMEM_TYPE_2;
332 }
333
334 void
ia_css_binary_dvs_grid_info(const struct ia_css_binary * binary,struct ia_css_grid_info * info,struct ia_css_pipe * pipe)335 ia_css_binary_dvs_grid_info(const struct ia_css_binary *binary,
336 struct ia_css_grid_info *info,
337 struct ia_css_pipe *pipe)
338 {
339 struct ia_css_dvs_grid_info *dvs_info;
340
341 (void)pipe;
342 assert(binary);
343 assert(info);
344
345 dvs_info = &info->dvs_grid.dvs_grid_info;
346
347 /* for DIS, we use a division instead of a ceil_div. If this is smaller
348 * than the 3a grid size, it indicates that the outer values are not
349 * valid for DIS.
350 */
351 dvs_info->enable = binary->info->sp.enable.dis;
352 dvs_info->width = binary->dis.grid.dim.width;
353 dvs_info->height = binary->dis.grid.dim.height;
354 dvs_info->aligned_width = binary->dis.grid.pad.width;
355 dvs_info->aligned_height = binary->dis.grid.pad.height;
356 dvs_info->bqs_per_grid_cell = 1 << binary->dis.deci_factor_log2;
357 dvs_info->num_hor_coefs = binary->dis.coef.dim.width;
358 dvs_info->num_ver_coefs = binary->dis.coef.dim.height;
359
360 sh_css_binary_common_grid_info(binary, info);
361 }
362
363 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)364 ia_css_binary_dvs_stat_grid_info(
365 const struct ia_css_binary *binary,
366 struct ia_css_grid_info *info,
367 struct ia_css_pipe *pipe)
368 {
369 (void)pipe;
370 sh_css_binary_common_grid_info(binary, info);
371 return;
372 }
373
374 int
ia_css_binary_3a_grid_info(const struct ia_css_binary * binary,struct ia_css_grid_info * info,struct ia_css_pipe * pipe)375 ia_css_binary_3a_grid_info(const struct ia_css_binary *binary,
376 struct ia_css_grid_info *info,
377 struct ia_css_pipe *pipe) {
378 struct ia_css_3a_grid_info *s3a_info;
379 int err = 0;
380
381 IA_CSS_ENTER_PRIVATE("binary=%p, info=%p, pipe=%p",
382 binary, info, pipe);
383
384 assert(binary);
385 assert(info);
386 s3a_info = &info->s3a_grid;
387
388 /* 3A statistics grid */
389 s3a_info->enable = binary->info->sp.enable.s3a;
390 s3a_info->width = binary->s3atbl_width;
391 s3a_info->height = binary->s3atbl_height;
392 s3a_info->aligned_width = binary->s3atbl_isp_width;
393 s3a_info->aligned_height = binary->s3atbl_isp_height;
394 s3a_info->bqs_per_grid_cell = (1 << binary->deci_factor_log2);
395 s3a_info->deci_factor_log2 = binary->deci_factor_log2;
396 s3a_info->elem_bit_depth = SH_CSS_BAYER_BITS;
397 s3a_info->use_dmem = binary->info->sp.s3a.s3atbl_use_dmem;
398 s3a_info->has_histogram = 0;
399 IA_CSS_LEAVE_ERR_PRIVATE(err);
400 return err;
401 }
402
403 static void
binary_init_pc_histogram(struct sh_css_pc_histogram * histo)404 binary_init_pc_histogram(struct sh_css_pc_histogram *histo)
405 {
406 assert(histo);
407
408 histo->length = 0;
409 histo->run = NULL;
410 histo->stall = NULL;
411 }
412
413 static void
binary_init_metrics(struct sh_css_binary_metrics * metrics,const struct ia_css_binary_info * info)414 binary_init_metrics(struct sh_css_binary_metrics *metrics,
415 const struct ia_css_binary_info *info)
416 {
417 assert(metrics);
418 assert(info);
419
420 metrics->mode = info->pipeline.mode;
421 metrics->id = info->id;
422 metrics->next = NULL;
423 binary_init_pc_histogram(&metrics->isp_histogram);
424 binary_init_pc_histogram(&metrics->sp_histogram);
425 }
426
427 /* move to host part of output module */
428 static bool
binary_supports_output_format(const struct ia_css_binary_xinfo * info,enum ia_css_frame_format format)429 binary_supports_output_format(const struct ia_css_binary_xinfo *info,
430 enum ia_css_frame_format format)
431 {
432 int i;
433
434 assert(info);
435
436 for (i = 0; i < info->num_output_formats; i++) {
437 if (info->output_formats[i] == format)
438 return true;
439 }
440 return false;
441 }
442
443 static bool
binary_supports_vf_format(const struct ia_css_binary_xinfo * info,enum ia_css_frame_format format)444 binary_supports_vf_format(const struct ia_css_binary_xinfo *info,
445 enum ia_css_frame_format format)
446 {
447 int i;
448
449 assert(info);
450
451 for (i = 0; i < info->num_vf_formats; i++) {
452 if (info->vf_formats[i] == format)
453 return true;
454 }
455 return false;
456 }
457
458 /* move to host part of bds module */
459 static bool
supports_bds_factor(u32 supported_factors,uint32_t bds_factor)460 supports_bds_factor(u32 supported_factors,
461 uint32_t bds_factor)
462 {
463 return ((supported_factors & PACK_BDS_FACTOR(bds_factor)) != 0);
464 }
465
466 static int
binary_init_info(struct ia_css_binary_xinfo * info,unsigned int i,bool * binary_found)467 binary_init_info(struct ia_css_binary_xinfo *info, unsigned int i,
468 bool *binary_found) {
469 const unsigned char *blob = sh_css_blob_info[i].blob;
470 unsigned int size = sh_css_blob_info[i].header.blob.size;
471
472 if ((!info) || (!binary_found))
473 return -EINVAL;
474
475 *info = sh_css_blob_info[i].header.info.isp;
476 *binary_found = blob;
477 info->blob_index = i;
478 /* we don't have this binary, skip it */
479 if (!size)
480 return 0;
481
482 info->xmem_addr = sh_css_load_blob(blob, size);
483 if (!info->xmem_addr)
484 return -ENOMEM;
485 return 0;
486 }
487
488 /* When binaries are put at the beginning, they will only
489 * be selected if no other primary matches.
490 */
491 int
ia_css_binary_init_infos(void)492 ia_css_binary_init_infos(void) {
493 unsigned int i;
494 unsigned int num_of_isp_binaries = sh_css_num_binaries - NUM_OF_SPS - NUM_OF_BLS;
495
496 if (num_of_isp_binaries == 0)
497 return 0;
498
499 all_binaries = kvmalloc(num_of_isp_binaries * sizeof(*all_binaries),
500 GFP_KERNEL);
501 if (!all_binaries)
502 return -ENOMEM;
503
504 for (i = 0; i < num_of_isp_binaries; i++)
505 {
506 int ret;
507 struct ia_css_binary_xinfo *binary = &all_binaries[i];
508 bool binary_found;
509
510 ret = binary_init_info(binary, i, &binary_found);
511 if (ret)
512 return ret;
513 if (!binary_found)
514 continue;
515 /* Prepend new binary information */
516 binary->next = binary_infos[binary->sp.pipeline.mode];
517 binary_infos[binary->sp.pipeline.mode] = binary;
518 binary->blob = &sh_css_blob_info[i];
519 binary->mem_offsets = sh_css_blob_info[i].mem_offsets;
520 }
521 return 0;
522 }
523
524 int
ia_css_binary_uninit(void)525 ia_css_binary_uninit(void) {
526 unsigned int i;
527 struct ia_css_binary_xinfo *b;
528
529 for (i = 0; i < IA_CSS_BINARY_NUM_MODES; i++)
530 {
531 for (b = binary_infos[i]; b; b = b->next) {
532 if (b->xmem_addr)
533 hmm_free(b->xmem_addr);
534 b->xmem_addr = mmgr_NULL;
535 }
536 binary_infos[i] = NULL;
537 }
538 kvfree(all_binaries);
539 return 0;
540 }
541
542 /* @brief Compute decimation factor for 3A statistics and shading correction.
543 *
544 * @param[in] width Frame width in pixels.
545 * @param[in] height Frame height in pixels.
546 * @return Log2 of decimation factor (= grid cell size) in bayer quads.
547 */
548 static int
binary_grid_deci_factor_log2(int width,int height)549 binary_grid_deci_factor_log2(int width, int height)
550 {
551 /* 3A/Shading decimation factor spcification (at August 2008)
552 * ------------------------------------------------------------------
553 * [Image Width (BQ)] [Decimation Factor (BQ)] [Resulting grid cells]
554 * 1280 ?c 32 40 ?c
555 * 640 ?c 1279 16 40 ?c 80
556 * ?c 639 8 ?c 80
557 * ------------------------------------------------------------------
558 */
559 /* Maximum and minimum decimation factor by the specification */
560 #define MAX_SPEC_DECI_FACT_LOG2 5
561 #define MIN_SPEC_DECI_FACT_LOG2 3
562 /* the smallest frame width in bayer quads when decimation factor (log2) is 5 or 4, by the specification */
563 #define DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ 1280
564 #define DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ 640
565
566 int smallest_factor; /* the smallest factor (log2) where the number of cells does not exceed the limitation */
567 int spec_factor; /* the factor (log2) which satisfies the specification */
568
569 /* Currently supported maximum width and height are 5120(=80*64) and 3840(=60*64). */
570 assert(ISP_BQ_GRID_WIDTH(width,
571 MAX_SPEC_DECI_FACT_LOG2) <= SH_CSS_MAX_BQ_GRID_WIDTH);
572 assert(ISP_BQ_GRID_HEIGHT(height,
573 MAX_SPEC_DECI_FACT_LOG2) <= SH_CSS_MAX_BQ_GRID_HEIGHT);
574
575 /* Compute the smallest factor. */
576 smallest_factor = MAX_SPEC_DECI_FACT_LOG2;
577 while (ISP_BQ_GRID_WIDTH(width,
578 smallest_factor - 1) <= SH_CSS_MAX_BQ_GRID_WIDTH &&
579 ISP_BQ_GRID_HEIGHT(height, smallest_factor - 1) <= SH_CSS_MAX_BQ_GRID_HEIGHT
580 && smallest_factor > MIN_SPEC_DECI_FACT_LOG2)
581 smallest_factor--;
582
583 /* Get the factor by the specification. */
584 if (_ISP_BQS(width) >= DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ)
585 spec_factor = 5;
586 else if (_ISP_BQS(width) >= DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ)
587 spec_factor = 4;
588 else
589 spec_factor = 3;
590
591 /* If smallest_factor is smaller than or equal to spec_factor, choose spec_factor to follow the specification.
592 If smallest_factor is larger than spec_factor, choose smallest_factor.
593
594 ex. width=2560, height=1920
595 smallest_factor=4, spec_factor=5
596 smallest_factor < spec_factor -> return spec_factor
597
598 ex. width=300, height=3000
599 smallest_factor=5, spec_factor=3
600 smallest_factor > spec_factor -> return smallest_factor
601 */
602 return max(smallest_factor, spec_factor);
603
604 #undef MAX_SPEC_DECI_FACT_LOG2
605 #undef MIN_SPEC_DECI_FACT_LOG2
606 #undef DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ
607 #undef DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ
608 }
609
610 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)611 binary_in_frame_padded_width(int in_frame_width,
612 int isp_internal_width,
613 int dvs_env_width,
614 int stream_config_left_padding,
615 int left_cropping,
616 bool need_scaling)
617 {
618 int rval;
619 int nr_of_left_paddings; /* number of paddings pixels on the left of an image line */
620
621 #if defined(ISP2401)
622 /* the output image line of Input System 2401 does not have the left paddings */
623 nr_of_left_paddings = 0;
624 #else
625 /* in other cases, the left padding pixels are always 128 */
626 nr_of_left_paddings = 2 * ISP_VEC_NELEMS;
627 #endif
628 if (need_scaling) {
629 /* In SDV use-case, we need to match left-padding of
630 * primary and the video binary. */
631 if (stream_config_left_padding != -1) {
632 /* Different than before, we do left&right padding. */
633 rval =
634 CEIL_MUL(in_frame_width + nr_of_left_paddings,
635 2 * ISP_VEC_NELEMS);
636 } else {
637 /* Different than before, we do left&right padding. */
638 in_frame_width += dvs_env_width;
639 rval =
640 CEIL_MUL(in_frame_width +
641 (left_cropping ? nr_of_left_paddings : 0),
642 2 * ISP_VEC_NELEMS);
643 }
644 } else {
645 rval = isp_internal_width;
646 }
647
648 return rval;
649 }
650
651 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)652 ia_css_binary_fill_info(const struct ia_css_binary_xinfo *xinfo,
653 bool online,
654 bool two_ppc,
655 enum atomisp_input_format stream_format,
656 const struct ia_css_frame_info *in_info, /* can be NULL */
657 const struct ia_css_frame_info *bds_out_info, /* can be NULL */
658 const struct ia_css_frame_info *out_info[], /* can be NULL */
659 const struct ia_css_frame_info *vf_info, /* can be NULL */
660 struct ia_css_binary *binary,
661 struct ia_css_resolution *dvs_env,
662 int stream_config_left_padding,
663 bool accelerator) {
664 const struct ia_css_binary_info *info = &xinfo->sp;
665 unsigned int dvs_env_width = 0,
666 dvs_env_height = 0,
667 vf_log_ds = 0,
668 s3a_log_deci = 0,
669 bits_per_pixel = 0,
670 /* Resolution at SC/3A/DIS kernel. */
671 sc_3a_dis_width = 0,
672 /* Resolution at SC/3A/DIS kernel. */
673 sc_3a_dis_padded_width = 0,
674 /* Resolution at SC/3A/DIS kernel. */
675 sc_3a_dis_height = 0,
676 isp_internal_width = 0,
677 isp_internal_height = 0,
678 s3a_isp_width = 0;
679
680 bool need_scaling = false;
681 struct ia_css_resolution binary_dvs_env, internal_res;
682 int err;
683 unsigned int i;
684 const struct ia_css_frame_info *bin_out_info = NULL;
685
686 assert(info);
687 assert(binary);
688
689 binary->info = xinfo;
690 if (!accelerator)
691 {
692 /* binary->css_params has been filled by accelerator itself. */
693 err = ia_css_isp_param_allocate_isp_parameters(
694 &binary->mem_params, &binary->css_params,
695 &info->mem_initializers);
696 if (err) {
697 return err;
698 }
699 }
700 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
701 {
702 if (out_info[i] && (out_info[i]->res.width != 0)) {
703 bin_out_info = out_info[i];
704 break;
705 }
706 }
707 if (in_info && bin_out_info)
708 {
709 need_scaling = (in_info->res.width != bin_out_info->res.width) ||
710 (in_info->res.height != bin_out_info->res.height);
711 }
712
713 /* binary_dvs_env has to be equal or larger than SH_CSS_MIN_DVS_ENVELOPE */
714 binary_dvs_env.width = 0;
715 binary_dvs_env.height = 0;
716 ia_css_binary_dvs_env(info, dvs_env, &binary_dvs_env);
717 dvs_env_width = binary_dvs_env.width;
718 dvs_env_height = binary_dvs_env.height;
719 binary->dvs_envelope.width = dvs_env_width;
720 binary->dvs_envelope.height = dvs_env_height;
721
722 /* internal resolution calculation */
723 internal_res.width = 0;
724 internal_res.height = 0;
725 ia_css_binary_internal_res(in_info, bds_out_info, bin_out_info, dvs_env,
726 info, &internal_res);
727 isp_internal_width = internal_res.width;
728 isp_internal_height = internal_res.height;
729
730 /* internal frame info */
731 if (bin_out_info) /* { */
732 binary->internal_frame_info.format = bin_out_info->format;
733 /* } */
734 binary->internal_frame_info.res.width = isp_internal_width;
735 binary->internal_frame_info.padded_width = CEIL_MUL(isp_internal_width, 2 * ISP_VEC_NELEMS);
736 binary->internal_frame_info.res.height = isp_internal_height;
737 binary->internal_frame_info.raw_bit_depth = bits_per_pixel;
738
739 if (in_info)
740 {
741 binary->effective_in_frame_res.width = in_info->res.width;
742 binary->effective_in_frame_res.height = in_info->res.height;
743
744 bits_per_pixel = in_info->raw_bit_depth;
745
746 /* input info */
747 binary->in_frame_info.res.width = in_info->res.width +
748 info->pipeline.left_cropping;
749 binary->in_frame_info.res.height = in_info->res.height +
750 info->pipeline.top_cropping;
751
752 binary->in_frame_info.res.width += dvs_env_width;
753 binary->in_frame_info.res.height += dvs_env_height;
754
755 binary->in_frame_info.padded_width =
756 binary_in_frame_padded_width(in_info->res.width,
757 isp_internal_width,
758 dvs_env_width,
759 stream_config_left_padding,
760 info->pipeline.left_cropping,
761 need_scaling);
762
763 binary->in_frame_info.format = in_info->format;
764 binary->in_frame_info.raw_bayer_order = in_info->raw_bayer_order;
765 binary->in_frame_info.crop_info = in_info->crop_info;
766 }
767
768 if (online)
769 {
770 bits_per_pixel = ia_css_util_input_format_bpp(
771 stream_format, two_ppc);
772 }
773 binary->in_frame_info.raw_bit_depth = bits_per_pixel;
774
775 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
776 {
777 if (out_info[i]) {
778 binary->out_frame_info[i].res.width = out_info[i]->res.width;
779 binary->out_frame_info[i].res.height = out_info[i]->res.height;
780 binary->out_frame_info[i].padded_width = out_info[i]->padded_width;
781 if (info->pipeline.mode == IA_CSS_BINARY_MODE_COPY) {
782 binary->out_frame_info[i].raw_bit_depth = bits_per_pixel;
783 } else {
784 /* Only relevant for RAW format.
785 * At the moment, all outputs are raw, 16 bit per pixel, except for copy.
786 * To do this cleanly, the binary should specify in its info
787 * the bit depth per output channel.
788 */
789 binary->out_frame_info[i].raw_bit_depth = 16;
790 }
791 binary->out_frame_info[i].format = out_info[i]->format;
792 }
793 }
794
795 if (vf_info && (vf_info->res.width != 0))
796 {
797 err = ia_css_vf_configure(binary, bin_out_info,
798 (struct ia_css_frame_info *)vf_info, &vf_log_ds);
799 if (err) {
800 if (!accelerator) {
801 ia_css_isp_param_destroy_isp_parameters(
802 &binary->mem_params,
803 &binary->css_params);
804 }
805 return err;
806 }
807 }
808 binary->vf_downscale_log2 = vf_log_ds;
809
810 binary->online = online;
811 binary->input_format = stream_format;
812
813 /* viewfinder output info */
814 if ((vf_info) && (vf_info->res.width != 0))
815 {
816 unsigned int vf_out_vecs, vf_out_width, vf_out_height;
817
818 binary->vf_frame_info.format = vf_info->format;
819 if (!bin_out_info)
820 return -EINVAL;
821 vf_out_vecs = __ISP_VF_OUTPUT_WIDTH_VECS(bin_out_info->padded_width,
822 vf_log_ds);
823 vf_out_width = _ISP_VF_OUTPUT_WIDTH(vf_out_vecs);
824 vf_out_height = _ISP_VF_OUTPUT_HEIGHT(bin_out_info->res.height,
825 vf_log_ds);
826
827 /* For preview mode, output pin is used instead of vf. */
828 if (info->pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW) {
829 binary->out_frame_info[0].res.width =
830 (bin_out_info->res.width >> vf_log_ds);
831 binary->out_frame_info[0].padded_width = vf_out_width;
832 binary->out_frame_info[0].res.height = vf_out_height;
833
834 binary->vf_frame_info.res.width = 0;
835 binary->vf_frame_info.padded_width = 0;
836 binary->vf_frame_info.res.height = 0;
837 } else {
838 /* we also store the raw downscaled width. This is
839 * used for digital zoom in preview to zoom only on
840 * the width that we actually want to keep, not on
841 * the aligned width. */
842 binary->vf_frame_info.res.width =
843 (bin_out_info->res.width >> vf_log_ds);
844 binary->vf_frame_info.padded_width = vf_out_width;
845 binary->vf_frame_info.res.height = vf_out_height;
846 }
847 } else
848 {
849 binary->vf_frame_info.res.width = 0;
850 binary->vf_frame_info.padded_width = 0;
851 binary->vf_frame_info.res.height = 0;
852 }
853
854 if (info->enable.ca_gdc)
855 {
856 binary->morph_tbl_width =
857 _ISP_MORPH_TABLE_WIDTH(isp_internal_width);
858 binary->morph_tbl_aligned_width =
859 _ISP_MORPH_TABLE_ALIGNED_WIDTH(isp_internal_width);
860 binary->morph_tbl_height =
861 _ISP_MORPH_TABLE_HEIGHT(isp_internal_height);
862 } else
863 {
864 binary->morph_tbl_width = 0;
865 binary->morph_tbl_aligned_width = 0;
866 binary->morph_tbl_height = 0;
867 }
868
869 sc_3a_dis_width = binary->in_frame_info.res.width;
870 sc_3a_dis_padded_width = binary->in_frame_info.padded_width;
871 sc_3a_dis_height = binary->in_frame_info.res.height;
872 if (bds_out_info && in_info &&
873 bds_out_info->res.width != in_info->res.width)
874 {
875 /* TODO: Next, "internal_frame_info" should be derived from
876 * bds_out. So this part will change once it is in place! */
877 sc_3a_dis_width = bds_out_info->res.width + info->pipeline.left_cropping;
878 sc_3a_dis_padded_width = isp_internal_width;
879 sc_3a_dis_height = isp_internal_height;
880 }
881
882 s3a_isp_width = _ISP_S3A_ELEMS_ISP_WIDTH(sc_3a_dis_padded_width,
883 info->pipeline.left_cropping);
884 if (info->s3a.fixed_s3a_deci_log)
885 {
886 s3a_log_deci = info->s3a.fixed_s3a_deci_log;
887 } else
888 {
889 s3a_log_deci = binary_grid_deci_factor_log2(s3a_isp_width,
890 sc_3a_dis_height);
891 }
892 binary->deci_factor_log2 = s3a_log_deci;
893
894 if (info->enable.s3a)
895 {
896 binary->s3atbl_width =
897 _ISP_S3ATBL_WIDTH(sc_3a_dis_width,
898 s3a_log_deci);
899 binary->s3atbl_height =
900 _ISP_S3ATBL_HEIGHT(sc_3a_dis_height,
901 s3a_log_deci);
902 binary->s3atbl_isp_width =
903 _ISP_S3ATBL_ISP_WIDTH(s3a_isp_width,
904 s3a_log_deci);
905 binary->s3atbl_isp_height =
906 _ISP_S3ATBL_ISP_HEIGHT(sc_3a_dis_height,
907 s3a_log_deci);
908 } else
909 {
910 binary->s3atbl_width = 0;
911 binary->s3atbl_height = 0;
912 binary->s3atbl_isp_width = 0;
913 binary->s3atbl_isp_height = 0;
914 }
915
916 if (info->enable.sc)
917 {
918 binary->sctbl_width_per_color = _ISP_SCTBL_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci);
919 binary->sctbl_aligned_width_per_color = SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR;
920 binary->sctbl_height = _ISP_SCTBL_HEIGHT(sc_3a_dis_height, s3a_log_deci);
921 } else
922 {
923 binary->sctbl_width_per_color = 0;
924 binary->sctbl_aligned_width_per_color = 0;
925 binary->sctbl_height = 0;
926 }
927 ia_css_sdis_init_info(&binary->dis,
928 sc_3a_dis_width,
929 sc_3a_dis_padded_width,
930 sc_3a_dis_height,
931 info->pipeline.isp_pipe_version,
932 info->enable.dis);
933 if (info->pipeline.left_cropping)
934 binary->left_padding = 2 * ISP_VEC_NELEMS - info->pipeline.left_cropping;
935 else
936 binary->left_padding = 0;
937
938 return 0;
939 }
940
__ia_css_binary_find(struct ia_css_binary_descr * descr,struct ia_css_binary * binary)941 static int __ia_css_binary_find(struct ia_css_binary_descr *descr,
942 struct ia_css_binary *binary) {
943 int mode;
944 bool online;
945 bool two_ppc;
946 enum atomisp_input_format stream_format;
947 const struct ia_css_frame_info *req_in_info,
948 *req_bds_out_info,
949 *req_out_info[IA_CSS_BINARY_MAX_OUTPUT_PORTS],
950 *req_bin_out_info = NULL,
951 *req_vf_info;
952
953 struct ia_css_binary_xinfo *xcandidate;
954 bool need_ds, need_dz, need_dvs, need_xnr, need_dpc;
955 bool striped;
956 bool enable_yuv_ds;
957 bool enable_high_speed;
958 bool enable_dvs_6axis;
959 bool enable_reduced_pipe;
960 bool enable_capture_pp_bli;
961 int err = -EINVAL;
962 bool continuous;
963 unsigned int isp_pipe_version;
964 struct ia_css_resolution dvs_env, internal_res;
965 unsigned int i;
966
967 assert(descr);
968 /* MW: used after an error check, may accept NULL, but doubtfull */
969 assert(binary);
970
971 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
972 "ia_css_binary_find() enter: descr=%p, (mode=%d), binary=%p\n",
973 descr, descr->mode,
974 binary);
975
976 mode = descr->mode;
977 online = descr->online;
978 two_ppc = descr->two_ppc;
979 stream_format = descr->stream_format;
980 req_in_info = descr->in_info;
981 req_bds_out_info = descr->bds_out_info;
982 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
983 req_out_info[i] = descr->out_info[i];
984 if (req_out_info[i] && (req_out_info[i]->res.width != 0))
985 req_bin_out_info = req_out_info[i];
986 }
987 if (!req_bin_out_info)
988 return -EINVAL;
989 req_vf_info = descr->vf_info;
990
991 need_xnr = descr->enable_xnr;
992 need_ds = descr->enable_fractional_ds;
993 need_dz = false;
994 need_dvs = false;
995 need_dpc = descr->enable_dpc;
996
997 enable_yuv_ds = descr->enable_yuv_ds;
998 enable_high_speed = descr->enable_high_speed;
999 enable_dvs_6axis = descr->enable_dvs_6axis;
1000 enable_reduced_pipe = descr->enable_reduced_pipe;
1001 enable_capture_pp_bli = descr->enable_capture_pp_bli;
1002 continuous = descr->continuous;
1003 striped = descr->striped;
1004 isp_pipe_version = descr->isp_pipe_version;
1005
1006 dvs_env.width = 0;
1007 dvs_env.height = 0;
1008 internal_res.width = 0;
1009 internal_res.height = 0;
1010
1011 if (mode == IA_CSS_BINARY_MODE_VIDEO) {
1012 dvs_env = descr->dvs_env;
1013 need_dz = descr->enable_dz;
1014 /* Video is the only mode that has a nodz variant. */
1015 need_dvs = dvs_env.width || dvs_env.height;
1016 }
1017
1018 /* print a map of the binary file */
1019 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "BINARY INFO:\n");
1020 for (i = 0; i < IA_CSS_BINARY_NUM_MODES; i++) {
1021 xcandidate = binary_infos[i];
1022 if (xcandidate) {
1023 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%d:\n", i);
1024 while (xcandidate) {
1025 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, " Name:%s Type:%d Cont:%d\n",
1026 xcandidate->blob->name, xcandidate->type,
1027 xcandidate->sp.enable.continuous);
1028 xcandidate = xcandidate->next;
1029 }
1030 }
1031 }
1032
1033 /* printf("sh_css_binary_find: pipe version %d\n", isp_pipe_version); */
1034 for (xcandidate = binary_infos[mode]; xcandidate;
1035 xcandidate = xcandidate->next) {
1036 struct ia_css_binary_info *candidate = &xcandidate->sp;
1037 /* printf("sh_css_binary_find: evaluating candidate:
1038 * %d\n",candidate->id); */
1039 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1040 "ia_css_binary_find() candidate = %p, mode = %d ID = %d\n",
1041 candidate, candidate->pipeline.mode, candidate->id);
1042
1043 /*
1044 * MW: Only a limited set of jointly configured binaries can
1045 * be used in a continuous preview/video mode unless it is
1046 * the copy mode and runs on SP.
1047 */
1048 if (!candidate->enable.continuous &&
1049 continuous && (mode != IA_CSS_BINARY_MODE_COPY)) {
1050 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1051 "ia_css_binary_find() [%d] continue: !%d && %d && (%d != %d)\n",
1052 __LINE__, candidate->enable.continuous,
1053 continuous, mode,
1054 IA_CSS_BINARY_MODE_COPY);
1055 continue;
1056 }
1057 if (striped && candidate->iterator.num_stripes == 1) {
1058 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1059 "ia_css_binary_find() [%d] continue: binary is not striped\n",
1060 __LINE__);
1061 continue;
1062 }
1063
1064 if (candidate->pipeline.isp_pipe_version != isp_pipe_version &&
1065 (mode != IA_CSS_BINARY_MODE_COPY) &&
1066 (mode != IA_CSS_BINARY_MODE_CAPTURE_PP) &&
1067 (mode != IA_CSS_BINARY_MODE_VF_PP)) {
1068 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1069 "ia_css_binary_find() [%d] continue: (%d != %d)\n",
1070 __LINE__,
1071 candidate->pipeline.isp_pipe_version, isp_pipe_version);
1072 continue;
1073 }
1074 if (!candidate->enable.reduced_pipe && enable_reduced_pipe) {
1075 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1076 "ia_css_binary_find() [%d] continue: !%d && %d\n",
1077 __LINE__,
1078 candidate->enable.reduced_pipe,
1079 enable_reduced_pipe);
1080 continue;
1081 }
1082 if (!candidate->enable.dvs_6axis && enable_dvs_6axis) {
1083 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1084 "ia_css_binary_find() [%d] continue: !%d && %d\n",
1085 __LINE__,
1086 candidate->enable.dvs_6axis,
1087 enable_dvs_6axis);
1088 continue;
1089 }
1090 if (candidate->enable.high_speed && !enable_high_speed) {
1091 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1092 "ia_css_binary_find() [%d] continue: %d && !%d\n",
1093 __LINE__,
1094 candidate->enable.high_speed,
1095 enable_high_speed);
1096 continue;
1097 }
1098 if (!candidate->enable.xnr && need_xnr) {
1099 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1100 "ia_css_binary_find() [%d] continue: %d && !%d\n",
1101 __LINE__,
1102 candidate->enable.xnr,
1103 need_xnr);
1104 continue;
1105 }
1106 if (!(candidate->enable.ds & 2) && enable_yuv_ds) {
1107 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1108 "ia_css_binary_find() [%d] continue: !%d && %d\n",
1109 __LINE__,
1110 ((candidate->enable.ds & 2) != 0),
1111 enable_yuv_ds);
1112 continue;
1113 }
1114 if ((candidate->enable.ds & 2) && !enable_yuv_ds) {
1115 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1116 "ia_css_binary_find() [%d] continue: %d && !%d\n",
1117 __LINE__,
1118 ((candidate->enable.ds & 2) != 0),
1119 enable_yuv_ds);
1120 continue;
1121 }
1122
1123 if (mode == IA_CSS_BINARY_MODE_VIDEO &&
1124 candidate->enable.ds && need_ds)
1125 need_dz = false;
1126
1127 /* when we require vf output, we need to have vf_veceven */
1128 if ((req_vf_info) && !(candidate->enable.vf_veceven ||
1129 /* or variable vf vec even */
1130 candidate->vf_dec.is_variable ||
1131 /* or more than one output pin. */
1132 xcandidate->num_output_pins > 1)) {
1133 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1134 "ia_css_binary_find() [%d] continue: (%p != NULL) && !(%d || %d || (%d >%d))\n",
1135 __LINE__, req_vf_info,
1136 candidate->enable.vf_veceven,
1137 candidate->vf_dec.is_variable,
1138 xcandidate->num_output_pins, 1);
1139 continue;
1140 }
1141 if (!candidate->enable.dvs_envelope && need_dvs) {
1142 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1143 "ia_css_binary_find() [%d] continue: !%d && %d\n",
1144 __LINE__,
1145 candidate->enable.dvs_envelope, (int)need_dvs);
1146 continue;
1147 }
1148 /* internal_res check considers input, output, and dvs envelope sizes */
1149 ia_css_binary_internal_res(req_in_info, req_bds_out_info,
1150 req_bin_out_info, &dvs_env, candidate, &internal_res);
1151 if (internal_res.width > candidate->internal.max_width) {
1152 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1153 "ia_css_binary_find() [%d] continue: (%d > %d)\n",
1154 __LINE__, internal_res.width,
1155 candidate->internal.max_width);
1156 continue;
1157 }
1158 if (internal_res.height > candidate->internal.max_height) {
1159 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1160 "ia_css_binary_find() [%d] continue: (%d > %d)\n",
1161 __LINE__, internal_res.height,
1162 candidate->internal.max_height);
1163 continue;
1164 }
1165 if (!candidate->enable.ds && need_ds && !(xcandidate->num_output_pins > 1)) {
1166 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1167 "ia_css_binary_find() [%d] continue: !%d && %d\n",
1168 __LINE__, candidate->enable.ds, (int)need_ds);
1169 continue;
1170 }
1171 if (!candidate->enable.uds && !candidate->enable.dvs_6axis && need_dz) {
1172 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1173 "ia_css_binary_find() [%d] continue: !%d && !%d && %d\n",
1174 __LINE__, candidate->enable.uds,
1175 candidate->enable.dvs_6axis, (int)need_dz);
1176 continue;
1177 }
1178 if (online && candidate->input.source == IA_CSS_BINARY_INPUT_MEMORY) {
1179 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1180 "ia_css_binary_find() [%d] continue: %d && (%d == %d)\n",
1181 __LINE__, online, candidate->input.source,
1182 IA_CSS_BINARY_INPUT_MEMORY);
1183 continue;
1184 }
1185 if (!online && candidate->input.source == IA_CSS_BINARY_INPUT_SENSOR) {
1186 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1187 "ia_css_binary_find() [%d] continue: !%d && (%d == %d)\n",
1188 __LINE__, online, candidate->input.source,
1189 IA_CSS_BINARY_INPUT_SENSOR);
1190 continue;
1191 }
1192 if (req_bin_out_info->res.width < candidate->output.min_width ||
1193 req_bin_out_info->res.width > candidate->output.max_width) {
1194 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1195 "ia_css_binary_find() [%d] continue: (%d > %d) || (%d < %d)\n",
1196 __LINE__,
1197 req_bin_out_info->padded_width,
1198 candidate->output.min_width,
1199 req_bin_out_info->padded_width,
1200 candidate->output.max_width);
1201 continue;
1202 }
1203 if (xcandidate->num_output_pins > 1 &&
1204 /* in case we have a second output pin, */
1205 req_vf_info) { /* and we need vf output. */
1206 if (req_vf_info->res.width > candidate->output.max_width) {
1207 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1208 "ia_css_binary_find() [%d] continue: (%d < %d)\n",
1209 __LINE__,
1210 req_vf_info->res.width,
1211 candidate->output.max_width);
1212 continue;
1213 }
1214 }
1215 if (req_in_info->padded_width > candidate->input.max_width) {
1216 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1217 "ia_css_binary_find() [%d] continue: (%d > %d)\n",
1218 __LINE__, req_in_info->padded_width,
1219 candidate->input.max_width);
1220 continue;
1221 }
1222 if (!binary_supports_output_format(xcandidate, req_bin_out_info->format)) {
1223 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1224 "ia_css_binary_find() [%d] continue: !%d\n",
1225 __LINE__,
1226 binary_supports_output_format(xcandidate, req_bin_out_info->format));
1227 continue;
1228 }
1229 if (xcandidate->num_output_pins > 1 &&
1230 /* in case we have a second output pin, */
1231 req_vf_info && /* and we need vf output. */
1232 /* check if the required vf format
1233 is supported. */
1234 !binary_supports_output_format(xcandidate, req_vf_info->format)) {
1235 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1236 "ia_css_binary_find() [%d] continue: (%d > %d) && (%p != NULL) && !%d\n",
1237 __LINE__, xcandidate->num_output_pins, 1,
1238 req_vf_info,
1239 binary_supports_output_format(xcandidate, req_vf_info->format));
1240 continue;
1241 }
1242
1243 /* Check if vf_veceven supports the requested vf format */
1244 if (xcandidate->num_output_pins == 1 &&
1245 req_vf_info && candidate->enable.vf_veceven &&
1246 !binary_supports_vf_format(xcandidate, req_vf_info->format)) {
1247 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1248 "ia_css_binary_find() [%d] continue: (%d == %d) && (%p != NULL) && %d && !%d\n",
1249 __LINE__, xcandidate->num_output_pins, 1,
1250 req_vf_info, candidate->enable.vf_veceven,
1251 binary_supports_vf_format(xcandidate, req_vf_info->format));
1252 continue;
1253 }
1254
1255 /* Check if vf_veceven supports the requested vf width */
1256 if (xcandidate->num_output_pins == 1 &&
1257 req_vf_info && candidate->enable.vf_veceven) { /* and we need vf output. */
1258 if (req_vf_info->res.width > candidate->output.max_width) {
1259 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1260 "ia_css_binary_find() [%d] continue: (%d < %d)\n",
1261 __LINE__,
1262 req_vf_info->res.width,
1263 candidate->output.max_width);
1264 continue;
1265 }
1266 }
1267
1268 if (!supports_bds_factor(candidate->bds.supported_bds_factors,
1269 descr->required_bds_factor)) {
1270 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1271 "ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n",
1272 __LINE__, candidate->bds.supported_bds_factors,
1273 descr->required_bds_factor);
1274 continue;
1275 }
1276
1277 if (!candidate->enable.dpc && need_dpc) {
1278 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1279 "ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n",
1280 __LINE__, candidate->enable.dpc,
1281 descr->enable_dpc);
1282 continue;
1283 }
1284
1285 if (candidate->uds.use_bci && enable_capture_pp_bli) {
1286 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1287 "ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n",
1288 __LINE__, candidate->uds.use_bci,
1289 descr->enable_capture_pp_bli);
1290 continue;
1291 }
1292
1293 /* reconfigure any variable properties of the binary */
1294 err = ia_css_binary_fill_info(xcandidate, online, two_ppc,
1295 stream_format, req_in_info,
1296 req_bds_out_info,
1297 req_out_info, req_vf_info,
1298 binary, &dvs_env,
1299 descr->stream_config_left_padding,
1300 false);
1301
1302 if (err)
1303 break;
1304 binary_init_metrics(&binary->metrics, &binary->info->sp);
1305 break;
1306 }
1307
1308 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1309 "ia_css_binary_find() selected = %p, mode = %d ID = %d\n",
1310 xcandidate, xcandidate ? xcandidate->sp.pipeline.mode : 0, xcandidate ? xcandidate->sp.id : 0);
1311
1312 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1313 "ia_css_binary_find() leave: return_err=%d\n", err);
1314
1315 if (!err && xcandidate)
1316 dev_dbg(atomisp_dev,
1317 "Using binary %s (id %d), type %d, mode %d, continuous %s\n",
1318 xcandidate->blob->name,
1319 xcandidate->sp.id,
1320 xcandidate->type,
1321 xcandidate->sp.pipeline.mode,
1322 xcandidate->sp.enable.continuous ? "true" : "false");
1323
1324
1325 return err;
1326 }
1327
ia_css_binary_find(struct ia_css_binary_descr * descr,struct ia_css_binary * binary)1328 int ia_css_binary_find(struct ia_css_binary_descr *descr,
1329 struct ia_css_binary *binary)
1330 {
1331 int ret = __ia_css_binary_find(descr, binary);
1332
1333 if (unlikely(ret)) {
1334 dev_dbg(atomisp_dev, "Seeking for binary failed at:");
1335 dump_stack();
1336 }
1337
1338 return ret;
1339 }
1340
1341 unsigned
ia_css_binary_max_vf_width(void)1342 ia_css_binary_max_vf_width(void)
1343 {
1344 /* This is (should be) true for IPU1 and IPU2 */
1345 /* For IPU3 (SkyCam) this pointer is guaranteed to be NULL simply because such a binary does not exist */
1346 if (binary_infos[IA_CSS_BINARY_MODE_VF_PP])
1347 return binary_infos[IA_CSS_BINARY_MODE_VF_PP]->sp.output.max_width;
1348 return 0;
1349 }
1350
1351 void
ia_css_binary_destroy_isp_parameters(struct ia_css_binary * binary)1352 ia_css_binary_destroy_isp_parameters(struct ia_css_binary *binary)
1353 {
1354 if (binary) {
1355 ia_css_isp_param_destroy_isp_parameters(&binary->mem_params,
1356 &binary->css_params);
1357 }
1358 }
1359
1360 void
ia_css_binary_get_isp_binaries(struct ia_css_binary_xinfo ** binaries,uint32_t * num_isp_binaries)1361 ia_css_binary_get_isp_binaries(struct ia_css_binary_xinfo **binaries,
1362 uint32_t *num_isp_binaries)
1363 {
1364 assert(binaries);
1365
1366 if (num_isp_binaries)
1367 *num_isp_binaries = 0;
1368
1369 *binaries = all_binaries;
1370 if (all_binaries && num_isp_binaries) {
1371 /* -1 to account for sp binary which is not stored in all_binaries */
1372 if (sh_css_num_binaries > 0)
1373 *num_isp_binaries = sh_css_num_binaries - 1;
1374 }
1375 }
1376