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