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