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