xref: /linux/drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c (revision 3fd6c59042dbba50391e30862beac979491145fe)
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