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