1 /*
2  * Support for Intel Camera Imaging ISP subsystem.
3  * Copyright (c) 2015, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  */
14 
15 #include <math_support.h>
16 #include <gdc_device.h>	/* HR_GDC_N */
17 
18 #include "hmm.h"
19 
20 #include "isp.h"	/* ISP_VEC_NELEMS */
21 
22 #include "ia_css_binary.h"
23 #include "ia_css_debug.h"
24 #include "ia_css_util.h"
25 #include "ia_css_isp_param.h"
26 #include "sh_css_internal.h"
27 #include "sh_css_sp.h"
28 #include "sh_css_firmware.h"
29 #include "sh_css_defs.h"
30 #include "sh_css_legacy.h"
31 
32 #include "vf/vf_1.0/ia_css_vf.host.h"
33 #include "sc/sc_1.0/ia_css_sc.host.h"
34 #include "sdis/sdis_1.0/ia_css_sdis.host.h"
35 #include "fixedbds/fixedbds_1.0/ia_css_fixedbds_param.h"	/* FRAC_ACC */
36 
37 #include "camera/pipe/interface/ia_css_pipe_binarydesc.h"
38 
39 
40 #include "assert_support.h"
41 
42 #define IMPLIES(a, b)           (!(a) || (b))   /* A => B */
43 
44 static struct ia_css_binary_xinfo *all_binaries; /* ISP binaries only (no SP) */
45 static struct ia_css_binary_xinfo
46 	*binary_infos[IA_CSS_BINARY_NUM_MODES] = { NULL, };
47 
48 static void
49 ia_css_binary_dvs_env(const struct ia_css_binary_info *info,
50 		      const struct ia_css_resolution *dvs_env,
51 		      struct ia_css_resolution *binary_dvs_env)
52 {
53 	if (info->enable.dvs_envelope) {
54 		assert(dvs_env);
55 		binary_dvs_env->width  = max(dvs_env->width, SH_CSS_MIN_DVS_ENVELOPE);
56 		binary_dvs_env->height = max(dvs_env->height, SH_CSS_MIN_DVS_ENVELOPE);
57 	}
58 }
59 
60 static void
61 ia_css_binary_internal_res(const struct ia_css_frame_info *in_info,
62 			   const struct ia_css_frame_info *bds_out_info,
63 			   const struct ia_css_frame_info *out_info,
64 			   const struct ia_css_resolution *dvs_env,
65 			   const struct ia_css_binary_info *info,
66 			   struct ia_css_resolution *internal_res)
67 {
68 	unsigned int isp_tmp_internal_width = 0,
69 		     isp_tmp_internal_height = 0;
70 	bool binary_supports_yuv_ds = info->enable.ds & 2;
71 	struct ia_css_resolution binary_dvs_env;
72 
73 	binary_dvs_env.width = 0;
74 	binary_dvs_env.height = 0;
75 	ia_css_binary_dvs_env(info, dvs_env, &binary_dvs_env);
76 
77 	if (binary_supports_yuv_ds) {
78 		if (in_info) {
79 			isp_tmp_internal_width = in_info->res.width
80 						 + info->pipeline.left_cropping + binary_dvs_env.width;
81 			isp_tmp_internal_height = in_info->res.height
82 						  + info->pipeline.top_cropping + binary_dvs_env.height;
83 		}
84 	} else if ((bds_out_info) && (out_info) &&
85 		   /* TODO: hack to make video_us case work. this should be reverted after
86 		   a nice solution in ISP */
87 		   (bds_out_info->res.width >= out_info->res.width)) {
88 		isp_tmp_internal_width = bds_out_info->padded_width;
89 		isp_tmp_internal_height = bds_out_info->res.height;
90 	} else {
91 		if (out_info) {
92 			isp_tmp_internal_width = out_info->padded_width;
93 			isp_tmp_internal_height = out_info->res.height;
94 		}
95 	}
96 
97 	/* We first calculate the resolutions used by the ISP. After that,
98 	 * we use those resolutions to compute sizes for tables etc. */
99 	internal_res->width = __ISP_INTERNAL_WIDTH(isp_tmp_internal_width,
100 			      (int)binary_dvs_env.width,
101 			      info->pipeline.left_cropping, info->pipeline.mode,
102 			      info->pipeline.c_subsampling,
103 			      info->output.num_chunks, info->pipeline.pipelining);
104 	internal_res->height = __ISP_INTERNAL_HEIGHT(isp_tmp_internal_height,
105 			       info->pipeline.top_cropping,
106 			       binary_dvs_env.height);
107 }
108 
109 /* ISP2400 */
110 /* Computation results of the origin coordinate of bayer on the shading table. */
111 struct sh_css_shading_table_bayer_origin_compute_results {
112 	u32 bayer_scale_hor_ratio_in;	/* Horizontal ratio (in) of bayer scaling. */
113 	u32 bayer_scale_hor_ratio_out;	/* Horizontal ratio (out) of bayer scaling. */
114 	u32 bayer_scale_ver_ratio_in;	/* Vertical ratio (in) of bayer scaling. */
115 	u32 bayer_scale_ver_ratio_out;	/* Vertical ratio (out) of bayer scaling. */
116 	u32 sc_bayer_origin_x_bqs_on_shading_table; /* X coordinate (in bqs) of bayer origin on shading table. */
117 	u32 sc_bayer_origin_y_bqs_on_shading_table; /* Y coordinate (in bqs) of bayer origin on shading table. */
118 };
119 
120 /* ISP2401 */
121 /* Requirements for the shading correction. */
122 struct sh_css_binary_sc_requirements {
123 	/* Bayer scaling factor, for the scaling which is applied before shading correction. */
124 	u32 bayer_scale_hor_ratio_in;  /* Horizontal ratio (in) of scaling applied BEFORE shading correction. */
125 	u32 bayer_scale_hor_ratio_out; /* Horizontal ratio (out) of scaling applied BEFORE shading correction. */
126 	u32 bayer_scale_ver_ratio_in;  /* Vertical ratio (in) of scaling applied BEFORE shading correction. */
127 	u32 bayer_scale_ver_ratio_out; /* Vertical ratio (out) of scaling applied BEFORE shading correction. */
128 
129 	/* ISP internal frame is composed of the real sensor data and the padding data. */
130 	u32 sensor_data_origin_x_bqs_on_internal; /* X origin (in bqs) of sensor data on internal frame
131 								at shading correction. */
132 	u32 sensor_data_origin_y_bqs_on_internal; /* Y origin (in bqs) of sensor data on internal frame
133 								at shading correction. */
134 };
135 
136 /* Get the requirements for the shading correction. */
137 static int
138 #ifndef ISP2401
139 ia_css_binary_compute_shading_table_bayer_origin(
140     const struct ia_css_binary *binary,				/* [in] */
141     unsigned int required_bds_factor,				/* [in] */
142     const struct ia_css_stream_config *stream_config,		/* [in] */
143     struct sh_css_shading_table_bayer_origin_compute_results *res)	/* [out] */
144 #else
145 sh_css_binary_get_sc_requirements(
146     const struct ia_css_binary *binary,			/* [in] */
147     unsigned int required_bds_factor,			/* [in] */
148     const struct ia_css_stream_config *stream_config,	/* [in] */
149     struct sh_css_binary_sc_requirements *scr)		/* [out] */
150 #endif
151 {
152 	int err;
153 
154 #ifndef ISP2401
155 	/* Numerator and denominator of the fixed bayer downscaling factor.
156 	(numerator >= denominator) */
157 #else
158 	/* Numerator and denominator of the fixed bayer downscaling factor. (numerator >= denominator) */
159 #endif
160 	unsigned int bds_num, bds_den;
161 
162 #ifndef ISP2401
163 	/* Horizontal/Vertical ratio of bayer scaling
164 	between input area and output area. */
165 	unsigned int bs_hor_ratio_in;
166 	unsigned int bs_hor_ratio_out;
167 	unsigned int bs_ver_ratio_in;
168 	unsigned int bs_ver_ratio_out;
169 #else
170 	/* Horizontal/Vertical ratio of bayer scaling between input area and output area. */
171 	unsigned int bs_hor_ratio_in, bs_hor_ratio_out, bs_ver_ratio_in, bs_ver_ratio_out;
172 #endif
173 
174 	/* Left padding set by InputFormatter. */
175 #ifndef ISP2401
176 	unsigned int left_padding_bqs;			/* in bqs */
177 #else
178 	unsigned int left_padding_bqs;
179 #endif
180 
181 #ifndef ISP2401
182 	/* Flag for the NEED_BDS_FACTOR_2_00 macro defined in isp kernels. */
183 	unsigned int need_bds_factor_2_00;
184 
185 	/* Left padding adjusted inside the isp. */
186 	unsigned int left_padding_adjusted_bqs;		/* in bqs */
187 
188 	/* Bad pixels caused by filters.
189 	NxN-filter (before/after bayer scaling) moves the image position
190 	to right/bottom directions by a few pixels.
191 	It causes bad pixels at left/top sides,
192 	and effective bayer size decreases. */
193 	unsigned int bad_bqs_on_left_before_bs;	/* in bqs */
194 	unsigned int bad_bqs_on_left_after_bs;	/* in bqs */
195 	unsigned int bad_bqs_on_top_before_bs;	/* in bqs */
196 	unsigned int bad_bqs_on_top_after_bs;	/* in bqs */
197 
198 	/* Get the numerator and denominator of bayer downscaling factor. */
199 	err = sh_css_bds_factor_get_numerator_denominator
200 	(required_bds_factor, &bds_num, &bds_den);
201 	if (err)
202 #else
203 	/* Flags corresponding to NEED_BDS_FACTOR_2_00/NEED_BDS_FACTOR_1_50/NEED_BDS_FACTOR_1_25 macros
204 	 * defined in isp kernels. */
205 	unsigned int need_bds_factor_2_00, need_bds_factor_1_50, need_bds_factor_1_25;
206 
207 	/* Left padding adjusted inside the isp kernels. */
208 	unsigned int left_padding_adjusted_bqs;
209 
210 	/* Top padding padded inside the isp kernel for bayer downscaling binaries. */
211 	unsigned int top_padding_bqs;
212 
213 	/* Bayer downscaling factor 1.0 by fixed-point. */
214 	int bds_frac_acc = FRAC_ACC;	/* FRAC_ACC is defined in ia_css_fixedbds_param.h. */
215 
216 	/* Right/Down shift amount caused by filters applied BEFORE shading corrertion. */
217 	unsigned int right_shift_bqs_before_bs; /* right shift before bayer scaling */
218 	unsigned int right_shift_bqs_after_bs;  /* right shift after bayer scaling */
219 	unsigned int down_shift_bqs_before_bs;  /* down shift before bayer scaling */
220 	unsigned int down_shift_bqs_after_bs;   /* down shift after bayer scaling */
221 
222 	/* Origin of the real sensor data area on the internal frame at shading correction. */
223 	unsigned int sensor_data_origin_x_bqs_on_internal;
224 	unsigned int sensor_data_origin_y_bqs_on_internal;
225 
226 	IA_CSS_ENTER_PRIVATE("binary=%p, required_bds_factor=%d, stream_config=%p",
227 			     binary, required_bds_factor, stream_config);
228 
229 	/* Get the numerator and denominator of the required bayer downscaling factor. */
230 	err = sh_css_bds_factor_get_numerator_denominator(required_bds_factor, &bds_num, &bds_den);
231 	if (err)
232 	{
233 		IA_CSS_LEAVE_ERR_PRIVATE(err);
234 #endif
235 		return err;
236 #ifdef ISP2401
237 }
238 #endif
239 
240 #ifndef ISP2401
241 /* Set the horizontal/vertical ratio of bayer scaling
242 between input area and output area. */
243 #else
244 IA_CSS_LOG("bds_num=%d, bds_den=%d", bds_num, bds_den);
245 
246 /* Set the horizontal/vertical ratio of bayer scaling between input area and output area. */
247 #endif
248 bs_hor_ratio_in  = bds_num;
249 bs_hor_ratio_out = bds_den;
250 bs_ver_ratio_in  = bds_num;
251 bs_ver_ratio_out = bds_den;
252 
253 #ifndef ISP2401
254 /* Set the left padding set by InputFormatter. (ifmtr.c) */
255 #else
256 /* Set the left padding set by InputFormatter. (ia_css_ifmtr_configure() in ifmtr.c) */
257 #endif
258 if (stream_config->left_padding == -1)
259 	left_padding_bqs = _ISP_BQS(binary->left_padding);
260 else
261 #ifndef ISP2401
262 	left_padding_bqs = (unsigned int)((int)ISP_VEC_NELEMS
263 					  - _ISP_BQS(stream_config->left_padding));
264 #else
265 	left_padding_bqs = (unsigned int)((int)ISP_VEC_NELEMS - _ISP_BQS(stream_config->left_padding));
266 #endif
267 
268 #ifndef ISP2401
269 /* Set the left padding adjusted inside the isp.
270 When bds_factor 2.00 is needed, some padding is added to left_padding
271 inside the isp, before bayer downscaling. (raw.isp.c)
272 (Hopefully, left_crop/left_padding/top_crop should be defined in css
273 appropriately, depending on bds_factor.)
274 */
275 #else
276 IA_CSS_LOG("stream.left_padding=%d, binary.left_padding=%d, left_padding_bqs=%d",
277 	   stream_config->left_padding, binary->left_padding, left_padding_bqs);
278 
279 /* Set the left padding adjusted inside the isp kernels.
280  * When the bds_factor isn't 1.00, the left padding size is adjusted inside the isp,
281  * before bayer downscaling. (scaled_hor_plane_index(), raw_compute_hphase() in raw.isp.c)
282  */
283 #endif
284 need_bds_factor_2_00 = ((binary->info->sp.bds.supported_bds_factors &
285 			 (PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_00) |
286 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_50) |
287 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_3_00) |
288 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_00) |
289 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_50) |
290 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_5_00) |
291 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_6_00) |
292 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_8_00))) != 0);
293 
294 #ifndef ISP2401
295 if (need_bds_factor_2_00 && binary->info->sp.pipeline.left_cropping > 0)
296 	left_padding_adjusted_bqs = left_padding_bqs + ISP_VEC_NELEMS;
297 else
298 #else
299 need_bds_factor_1_50 = ((binary->info->sp.bds.supported_bds_factors &
300 			 (PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_1_50) |
301 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_25) |
302 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_3_00) |
303 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_50) |
304 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_6_00))) != 0);
305 
306 need_bds_factor_1_25 = ((binary->info->sp.bds.supported_bds_factors &
307 			 (PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_1_25) |
308 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_50) |
309 			  PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_5_00))) != 0);
310 
311 if (binary->info->sp.pipeline.left_cropping > 0 &&
312     (need_bds_factor_2_00 || need_bds_factor_1_50 || need_bds_factor_1_25))
313 {
314 	/*
315 	 * downscale 2.0  -> first_vec_adjusted_bqs = 128
316 	 * downscale 1.5  -> first_vec_adjusted_bqs = 96
317 	 * downscale 1.25 -> first_vec_adjusted_bqs = 80
318 	 */
319 	unsigned int first_vec_adjusted_bqs
320 	= ISP_VEC_NELEMS * bs_hor_ratio_in / bs_hor_ratio_out;
321 	left_padding_adjusted_bqs = first_vec_adjusted_bqs
322 	- _ISP_BQS(binary->info->sp.pipeline.left_cropping);
323 } else
324 #endif
325 	left_padding_adjusted_bqs = left_padding_bqs;
326 
327 #ifndef ISP2401
328 /* Currently, the bad pixel caused by filters before bayer scaling
329 is NOT considered, because the bad pixel is subtle.
330 When some large filter is used in the future,
331 we need to consider the bad pixel.
332 
333 Currently, when bds_factor isn't 1.00, 3x3 anti-alias filter is applied
334 to each color plane(Gr/R/B/Gb) before bayer downscaling.
335 This filter moves each color plane to right/bottom directions
336 by 1 pixel at the most, depending on downscaling factor.
337 */
338 bad_bqs_on_left_before_bs = 0;
339 bad_bqs_on_top_before_bs = 0;
340 #else
341 IA_CSS_LOG("supported_bds_factors=%d, need_bds_factor:2_00=%d, 1_50=%d, 1_25=%d",
342 	   binary->info->sp.bds.supported_bds_factors,
343 	   need_bds_factor_2_00, need_bds_factor_1_50, need_bds_factor_1_25);
344 IA_CSS_LOG("left_cropping=%d, left_padding_adjusted_bqs=%d",
345 	   binary->info->sp.pipeline.left_cropping, left_padding_adjusted_bqs);
346 
347 /* Set the top padding padded inside the isp kernel for bayer downscaling binaries.
348  * When the bds_factor isn't 1.00, the top padding is padded inside the isp
349  * before bayer downscaling, because the top cropping size (input margin) is not enough.
350  * (calculate_input_line(), raw_compute_vphase(), dma_read_raw() in raw.isp.c)
351  * NOTE: In dma_read_raw(), the factor passed to raw_compute_vphase() is got by get_bds_factor_for_dma_read().
352  *       This factor is BDS_FPVAL_100/BDS_FPVAL_125/BDS_FPVAL_150/BDS_FPVAL_200.
353  */
354 top_padding_bqs = 0;
355 if (binary->info->sp.pipeline.top_cropping > 0 &&
356     (required_bds_factor == SH_CSS_BDS_FACTOR_1_25 ||
357      required_bds_factor == SH_CSS_BDS_FACTOR_1_50 ||
358      required_bds_factor == SH_CSS_BDS_FACTOR_2_00))
359 {
360 	/* Calculation from calculate_input_line() and raw_compute_vphase() in raw.isp.c. */
361 	int top_cropping_bqs = _ISP_BQS(binary->info->sp.pipeline.top_cropping);
362 	/* top cropping (in bqs) */
363 	int factor = bds_num * bds_frac_acc /
364 	bds_den;	/* downscaling factor by fixed-point */
365 	int top_padding_bqsxfrac_acc = (top_cropping_bqs * factor - top_cropping_bqs *
366 					bds_frac_acc)
367 	+ (2 * bds_frac_acc - factor);	/* top padding by fixed-point (in bqs) */
368 
369 	top_padding_bqs = (unsigned int)((top_padding_bqsxfrac_acc + bds_frac_acc / 2 -
370 					  1) / bds_frac_acc);
371 }
372 
373 IA_CSS_LOG("top_cropping=%d, top_padding_bqs=%d", binary->info->sp.pipeline.top_cropping, top_padding_bqs);
374 
375 /* Set the right/down shift amount caused by filters applied BEFORE bayer scaling,
376  * which scaling is applied BEFORE shading corrertion.
377  *
378  * When the bds_factor isn't 1.00, 3x3 anti-alias filter is applied to each color plane(Gr/R/B/Gb)
379  * before bayer downscaling.
380  * This filter shifts each color plane (Gr/R/B/Gb) to right/down directions by 1 pixel.
381  */
382 right_shift_bqs_before_bs = 0;
383 down_shift_bqs_before_bs = 0;
384 #endif
385 
386 #ifndef ISP2401
387 /* Currently, the bad pixel caused by filters after bayer scaling
388 is NOT considered, because the bad pixel is subtle.
389 When some large filter is used in the future,
390 we need to consider the bad pixel.
391 
392 Currently, when DPC&BNR is processed between bayer scaling and
393 shading correction, DPC&BNR moves each color plane to
394 right/bottom directions by 1 pixel.
395 */
396 bad_bqs_on_left_after_bs = 0;
397 bad_bqs_on_top_after_bs = 0;
398 #else
399 if (need_bds_factor_2_00 || need_bds_factor_1_50 || need_bds_factor_1_25)
400 {
401 	right_shift_bqs_before_bs = 1;
402 	down_shift_bqs_before_bs = 1;
403 }
404 
405 IA_CSS_LOG("right_shift_bqs_before_bs=%d, down_shift_bqs_before_bs=%d",
406 	   right_shift_bqs_before_bs, down_shift_bqs_before_bs);
407 
408 /* Set the right/down shift amount caused by filters applied AFTER bayer scaling,
409  * which scaling is applied BEFORE shading corrertion.
410  *
411  * When DPC&BNR is processed between bayer scaling and shading correction,
412  * DPC&BNR moves each color plane (Gr/R/B/Gb) to right/down directions by 1 pixel.
413  */
414 right_shift_bqs_after_bs = 0;
415 down_shift_bqs_after_bs = 0;
416 #endif
417 
418 #ifndef ISP2401
419 /* Calculate the origin of bayer (real sensor data area)
420 located on the shading table during the shading correction. */
421 res->sc_bayer_origin_x_bqs_on_shading_table
422 = ((left_padding_adjusted_bqs + bad_bqs_on_left_before_bs)
423    * bs_hor_ratio_out + bs_hor_ratio_in / 2) / bs_hor_ratio_in
424 + bad_bqs_on_left_after_bs;
425 /* "+ bs_hor_ratio_in/2": rounding for division by bs_hor_ratio_in */
426 res->sc_bayer_origin_y_bqs_on_shading_table
427 = (bad_bqs_on_top_before_bs
428    * bs_ver_ratio_out + bs_ver_ratio_in / 2) / bs_ver_ratio_in
429 + bad_bqs_on_top_after_bs;
430 /* "+ bs_ver_ratio_in/2": rounding for division by bs_ver_ratio_in */
431 
432 res->bayer_scale_hor_ratio_in  = (uint32_t)bs_hor_ratio_in;
433 res->bayer_scale_hor_ratio_out = (uint32_t)bs_hor_ratio_out;
434 res->bayer_scale_ver_ratio_in  = (uint32_t)bs_ver_ratio_in;
435 res->bayer_scale_ver_ratio_out = (uint32_t)bs_ver_ratio_out;
436 #else
437 if (binary->info->mem_offsets.offsets.param->dmem.dp.size != 0)   /* if DPC&BNR is enabled in the binary */
438 {
439 	right_shift_bqs_after_bs = 1;
440 	down_shift_bqs_after_bs = 1;
441 }
442 
443 IA_CSS_LOG("right_shift_bqs_after_bs=%d, down_shift_bqs_after_bs=%d",
444 	   right_shift_bqs_after_bs, down_shift_bqs_after_bs);
445 
446 /* Set the origin of the sensor data area on the internal frame at shading correction. */
447 {
448 	unsigned int bs_frac = bds_frac_acc;	/* scaling factor 1.0 in fixed point */
449 	unsigned int bs_out, bs_in;		/* scaling ratio in fixed point */
450 
451 	bs_out = bs_hor_ratio_out * bs_frac;
452 	bs_in = bs_hor_ratio_in * bs_frac;
453 	sensor_data_origin_x_bqs_on_internal
454 	= ((left_padding_adjusted_bqs + right_shift_bqs_before_bs) * bs_out + bs_in / 2) / bs_in
455 	+ right_shift_bqs_after_bs;	/* "+ bs_in/2": rounding */
456 
457 	bs_out = bs_ver_ratio_out * bs_frac;
458 	bs_in = bs_ver_ratio_in * bs_frac;
459 	sensor_data_origin_y_bqs_on_internal
460 	= ((top_padding_bqs + down_shift_bqs_before_bs) * bs_out + bs_in / 2) / bs_in
461 	+ down_shift_bqs_after_bs;	/* "+ bs_in/2": rounding */
462 }
463 
464 scr->bayer_scale_hor_ratio_in			= (uint32_t)bs_hor_ratio_in;
465 scr->bayer_scale_hor_ratio_out			= (uint32_t)bs_hor_ratio_out;
466 scr->bayer_scale_ver_ratio_in			= (uint32_t)bs_ver_ratio_in;
467 scr->bayer_scale_ver_ratio_out			= (uint32_t)bs_ver_ratio_out;
468 scr->sensor_data_origin_x_bqs_on_internal	= (uint32_t)sensor_data_origin_x_bqs_on_internal;
469 scr->sensor_data_origin_y_bqs_on_internal	= (uint32_t)sensor_data_origin_y_bqs_on_internal;
470 
471 IA_CSS_LOG("sc_requirements: %d, %d, %d, %d, %d, %d",
472 	   scr->bayer_scale_hor_ratio_in, scr->bayer_scale_hor_ratio_out,
473 	   scr->bayer_scale_ver_ratio_in, scr->bayer_scale_ver_ratio_out,
474 	   scr->sensor_data_origin_x_bqs_on_internal, scr->sensor_data_origin_y_bqs_on_internal);
475 #endif
476 
477 #ifdef ISP2401
478 IA_CSS_LEAVE_ERR_PRIVATE(err);
479 #endif
480 return err;
481 }
482 
483 /* Get the shading information of Shading Correction Type 1. */
484 static int
485 ia_css_binary_get_shading_info_type_1(const struct ia_css_binary
486 				      *binary,	/* [in] */
487 				      unsigned int required_bds_factor,			/* [in] */
488 				      const struct ia_css_stream_config *stream_config,	/* [in] */
489 #ifndef ISP2401
490 				      struct ia_css_shading_info *info)			/* [out] */
491 #else
492 				      struct ia_css_shading_info *shading_info,		/* [out] */
493 				      struct ia_css_pipe_config *pipe_config)			/* [out] */
494 #endif
495 {
496 	int err;
497 #ifndef ISP2401
498 	struct sh_css_shading_table_bayer_origin_compute_results res;
499 #else
500 	struct sh_css_binary_sc_requirements scr;
501 #endif
502 
503 #ifndef ISP2401
504 	assert(binary);
505 	assert(info);
506 #else
507 	u32 in_width_bqs, in_height_bqs, internal_width_bqs, internal_height_bqs;
508 	u32 num_hor_grids, num_ver_grids, bqs_per_grid_cell, tbl_width_bqs, tbl_height_bqs;
509 	u32 sensor_org_x_bqs_on_internal, sensor_org_y_bqs_on_internal, sensor_width_bqs, sensor_height_bqs;
510 	u32 sensor_center_x_bqs_on_internal, sensor_center_y_bqs_on_internal;
511 	u32 left, right, upper, lower;
512 	u32 adjust_left, adjust_right, adjust_upper, adjust_lower, adjust_width_bqs, adjust_height_bqs;
513 	u32 internal_org_x_bqs_on_tbl, internal_org_y_bqs_on_tbl;
514 	u32 sensor_org_x_bqs_on_tbl, sensor_org_y_bqs_on_tbl;
515 #endif
516 
517 #ifndef ISP2401
518 	info->type = IA_CSS_SHADING_CORRECTION_TYPE_1;
519 #else
520 	assert(binary);
521 	assert(stream_config);
522 	assert(shading_info);
523 	assert(pipe_config);
524 #endif
525 
526 #ifndef ISP2401
527 	info->info.type_1.enable	    = binary->info->sp.enable.sc;
528 	info->info.type_1.num_hor_grids	    = binary->sctbl_width_per_color;
529 	info->info.type_1.num_ver_grids	    = binary->sctbl_height;
530 	info->info.type_1.bqs_per_grid_cell = (1 << binary->deci_factor_log2);
531 #else
532 	IA_CSS_ENTER_PRIVATE("binary=%p, required_bds_factor=%d, stream_config=%p",
533 			     binary, required_bds_factor, stream_config);
534 #endif
535 
536 	/* Initialize by default values. */
537 #ifndef ISP2401
538 	info->info.type_1.bayer_scale_hor_ratio_in	= 1;
539 	info->info.type_1.bayer_scale_hor_ratio_out	= 1;
540 	info->info.type_1.bayer_scale_ver_ratio_in	= 1;
541 	info->info.type_1.bayer_scale_ver_ratio_out	= 1;
542 	info->info.type_1.sc_bayer_origin_x_bqs_on_shading_table = 0;
543 	info->info.type_1.sc_bayer_origin_y_bqs_on_shading_table = 0;
544 
545 	err = ia_css_binary_compute_shading_table_bayer_origin(
546 	    binary,
547 	    required_bds_factor,
548 	    stream_config,
549 	    &res);
550 	if (err)
551 #else
552 	*shading_info = DEFAULT_SHADING_INFO_TYPE_1;
553 
554 	err = sh_css_binary_get_sc_requirements(binary, required_bds_factor, stream_config, &scr);
555 	if (err)
556 	{
557 		IA_CSS_LEAVE_ERR_PRIVATE(err);
558 #endif
559 		return err;
560 #ifdef ISP2401
561 }
562 
563 IA_CSS_LOG("binary: id=%d, sctbl=%dx%d, deci=%d",
564 	   binary->info->sp.id, binary->sctbl_width_per_color, binary->sctbl_height, binary->deci_factor_log2);
565 IA_CSS_LOG("binary: in=%dx%d, in_padded_w=%d, int=%dx%d, int_padded_w=%d, out=%dx%d, out_padded_w=%d",
566 	   binary->in_frame_info.res.width, binary->in_frame_info.res.height, binary->in_frame_info.padded_width,
567 	   binary->internal_frame_info.res.width, binary->internal_frame_info.res.height,
568 	   binary->internal_frame_info.padded_width,
569 	   binary->out_frame_info[0].res.width, binary->out_frame_info[0].res.height,
570 	   binary->out_frame_info[0].padded_width);
571 
572 /* Set the input size from sensor, which includes left/top crop size. */
573 in_width_bqs	    = _ISP_BQS(binary->in_frame_info.res.width);
574 in_height_bqs	    = _ISP_BQS(binary->in_frame_info.res.height);
575 
576 /* Frame size internally used in ISP, including sensor data and padding.
577  * This is the frame size, to which the shading correction is applied.
578  */
579 internal_width_bqs  = _ISP_BQS(binary->internal_frame_info.res.width);
580 internal_height_bqs = _ISP_BQS(binary->internal_frame_info.res.height);
581 
582 /* Shading table. */
583 num_hor_grids = binary->sctbl_width_per_color;
584 num_ver_grids = binary->sctbl_height;
585 bqs_per_grid_cell = (1 << binary->deci_factor_log2);
586 tbl_width_bqs  = (num_hor_grids - 1) * bqs_per_grid_cell;
587 tbl_height_bqs = (num_ver_grids - 1) * bqs_per_grid_cell;
588 #endif
589 
590 #ifndef ISP2401
591 info->info.type_1.bayer_scale_hor_ratio_in	= res.bayer_scale_hor_ratio_in;
592 info->info.type_1.bayer_scale_hor_ratio_out	= res.bayer_scale_hor_ratio_out;
593 info->info.type_1.bayer_scale_ver_ratio_in	= res.bayer_scale_ver_ratio_in;
594 info->info.type_1.bayer_scale_ver_ratio_out	= res.bayer_scale_ver_ratio_out;
595 info->info.type_1.sc_bayer_origin_x_bqs_on_shading_table = res.sc_bayer_origin_x_bqs_on_shading_table;
596 info->info.type_1.sc_bayer_origin_y_bqs_on_shading_table = res.sc_bayer_origin_y_bqs_on_shading_table;
597 #else
598 IA_CSS_LOG("tbl_width_bqs=%d, tbl_height_bqs=%d", tbl_width_bqs, tbl_height_bqs);
599 #endif
600 
601 #ifdef ISP2401
602 /* Real sensor data area on the internal frame at shading correction.
603  * Filters and scaling are applied to the internal frame before shading correction, depending on the binary.
604  */
605 sensor_org_x_bqs_on_internal = scr.sensor_data_origin_x_bqs_on_internal;
606 sensor_org_y_bqs_on_internal = scr.sensor_data_origin_y_bqs_on_internal;
607 {
608 	unsigned int bs_frac = 8;	/* scaling factor 1.0 in fixed point (8 == FRAC_ACC macro in ISP) */
609 	unsigned int bs_out, bs_in;	/* scaling ratio in fixed point */
610 
611 	bs_out = scr.bayer_scale_hor_ratio_out * bs_frac;
612 	bs_in = scr.bayer_scale_hor_ratio_in * bs_frac;
613 	sensor_width_bqs  = (in_width_bqs * bs_out + bs_in / 2) / bs_in; /* "+ bs_in/2": rounding */
614 
615 	bs_out = scr.bayer_scale_ver_ratio_out * bs_frac;
616 	bs_in = scr.bayer_scale_ver_ratio_in * bs_frac;
617 	sensor_height_bqs = (in_height_bqs * bs_out + bs_in / 2) / bs_in; /* "+ bs_in/2": rounding */
618 }
619 
620 /* Center of the sensor data on the internal frame at shading correction. */
621 sensor_center_x_bqs_on_internal = sensor_org_x_bqs_on_internal + sensor_width_bqs / 2;
622 sensor_center_y_bqs_on_internal = sensor_org_y_bqs_on_internal + sensor_height_bqs / 2;
623 
624 /* Size of left/right/upper/lower sides of the sensor center on the internal frame. */
625 left  = sensor_center_x_bqs_on_internal;
626 right = internal_width_bqs - sensor_center_x_bqs_on_internal;
627 upper = sensor_center_y_bqs_on_internal;
628 lower = internal_height_bqs - sensor_center_y_bqs_on_internal;
629 
630 /* Align the size of left/right/upper/lower sides to a multiple of the grid cell size. */
631 adjust_left  = CEIL_MUL(left,  bqs_per_grid_cell);
632 adjust_right = CEIL_MUL(right, bqs_per_grid_cell);
633 adjust_upper = CEIL_MUL(upper, bqs_per_grid_cell);
634 adjust_lower = CEIL_MUL(lower, bqs_per_grid_cell);
635 
636 /* Shading table should cover the adjusted frame size. */
637 adjust_width_bqs  = adjust_left + adjust_right;
638 adjust_height_bqs = adjust_upper + adjust_lower;
639 
640 IA_CSS_LOG("adjust_width_bqs=%d, adjust_height_bqs=%d", adjust_width_bqs, adjust_height_bqs);
641 
642 if (adjust_width_bqs > tbl_width_bqs || adjust_height_bqs > tbl_height_bqs)
643 {
644 	IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
645 	return -EINVAL;
646 }
647 
648 /* Origin of the internal frame on the shading table. */
649 internal_org_x_bqs_on_tbl = adjust_left - left;
650 internal_org_y_bqs_on_tbl = adjust_upper - upper;
651 
652 /* Origin of the real sensor data area on the shading table. */
653 sensor_org_x_bqs_on_tbl = internal_org_x_bqs_on_tbl + sensor_org_x_bqs_on_internal;
654 sensor_org_y_bqs_on_tbl = internal_org_y_bqs_on_tbl + sensor_org_y_bqs_on_internal;
655 
656 /* The shading information necessary as API is stored in the shading_info. */
657 shading_info->info.type_1.num_hor_grids	    = num_hor_grids;
658 shading_info->info.type_1.num_ver_grids	    = num_ver_grids;
659 shading_info->info.type_1.bqs_per_grid_cell = bqs_per_grid_cell;
660 
661 shading_info->info.type_1.bayer_scale_hor_ratio_in  = scr.bayer_scale_hor_ratio_in;
662 shading_info->info.type_1.bayer_scale_hor_ratio_out = scr.bayer_scale_hor_ratio_out;
663 shading_info->info.type_1.bayer_scale_ver_ratio_in  = scr.bayer_scale_ver_ratio_in;
664 shading_info->info.type_1.bayer_scale_ver_ratio_out = scr.bayer_scale_ver_ratio_out;
665 
666 shading_info->info.type_1.isp_input_sensor_data_res_bqs.width  = in_width_bqs;
667 shading_info->info.type_1.isp_input_sensor_data_res_bqs.height = in_height_bqs;
668 
669 shading_info->info.type_1.sensor_data_res_bqs.width  = sensor_width_bqs;
670 shading_info->info.type_1.sensor_data_res_bqs.height = sensor_height_bqs;
671 
672 shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.x = (int32_t)sensor_org_x_bqs_on_tbl;
673 shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.y = (int32_t)sensor_org_y_bqs_on_tbl;
674 
675 /* The shading information related to ISP (but, not necessary as API) is stored in the pipe_config. */
676 pipe_config->internal_frame_origin_bqs_on_sctbl.x = (int32_t)internal_org_x_bqs_on_tbl;
677 pipe_config->internal_frame_origin_bqs_on_sctbl.y = (int32_t)internal_org_y_bqs_on_tbl;
678 
679 IA_CSS_LOG("shading_info: grids=%dx%d, cell=%d, scale=%d,%d,%d,%d, input=%dx%d, data=%dx%d, origin=(%d,%d)",
680 	   shading_info->info.type_1.num_hor_grids,
681 	   shading_info->info.type_1.num_ver_grids,
682 	   shading_info->info.type_1.bqs_per_grid_cell,
683 	   shading_info->info.type_1.bayer_scale_hor_ratio_in,
684 	   shading_info->info.type_1.bayer_scale_hor_ratio_out,
685 	   shading_info->info.type_1.bayer_scale_ver_ratio_in,
686 	   shading_info->info.type_1.bayer_scale_ver_ratio_out,
687 	   shading_info->info.type_1.isp_input_sensor_data_res_bqs.width,
688 	   shading_info->info.type_1.isp_input_sensor_data_res_bqs.height,
689 	   shading_info->info.type_1.sensor_data_res_bqs.width,
690 	   shading_info->info.type_1.sensor_data_res_bqs.height,
691 	   shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.x,
692 	   shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.y);
693 
694 IA_CSS_LOG("pipe_config: origin=(%d,%d)",
695 	   pipe_config->internal_frame_origin_bqs_on_sctbl.x,
696 	   pipe_config->internal_frame_origin_bqs_on_sctbl.y);
697 
698 IA_CSS_LEAVE_ERR_PRIVATE(err);
699 #endif
700 return err;
701 }
702 
703 int
704 ia_css_binary_get_shading_info(const struct ia_css_binary *binary,			/* [in] */
705 			       enum ia_css_shading_correction_type type,		/* [in] */
706 			       unsigned int required_bds_factor,			/* [in] */
707 			       const struct ia_css_stream_config *stream_config,	/* [in] */
708 			       struct ia_css_shading_info *shading_info,		/* [out] */
709 			       struct ia_css_pipe_config *pipe_config)			/* [out] */
710 {
711 	int err;
712 
713 	assert(binary);
714 	assert(shading_info);
715 
716 	IA_CSS_ENTER_PRIVATE("binary=%p, type=%d, required_bds_factor=%d, stream_config=%p",
717 			     binary, type, required_bds_factor, stream_config);
718 
719 	if (type == IA_CSS_SHADING_CORRECTION_TYPE_1)
720 #ifndef ISP2401
721 		err = ia_css_binary_get_shading_info_type_1(binary, required_bds_factor, stream_config,
722 							    shading_info);
723 #else
724 		err = ia_css_binary_get_shading_info_type_1(binary, required_bds_factor, stream_config,
725 			shading_info, pipe_config);
726 #endif
727 
728 	/* Other function calls can be added here when other shading correction types will be added in the future. */
729 
730 	else
731 		err = -ENOTSUPP;
732 
733 	IA_CSS_LEAVE_ERR_PRIVATE(err);
734 	return err;
735 }
736 
737 static void sh_css_binary_common_grid_info(const struct ia_css_binary *binary,
738 	struct ia_css_grid_info *info)
739 {
740 	assert(binary);
741 	assert(info);
742 
743 	info->isp_in_width = binary->internal_frame_info.res.width;
744 	info->isp_in_height = binary->internal_frame_info.res.height;
745 
746 	info->vamem_type = IA_CSS_VAMEM_TYPE_2;
747 }
748 
749 void
750 ia_css_binary_dvs_grid_info(const struct ia_css_binary *binary,
751 			    struct ia_css_grid_info *info,
752 			    struct ia_css_pipe *pipe)
753 {
754 	struct ia_css_dvs_grid_info *dvs_info;
755 
756 	(void)pipe;
757 	assert(binary);
758 	assert(info);
759 
760 	dvs_info = &info->dvs_grid.dvs_grid_info;
761 
762 	/* for DIS, we use a division instead of a ceil_div. If this is smaller
763 	 * than the 3a grid size, it indicates that the outer values are not
764 	 * valid for DIS.
765 	 */
766 	dvs_info->enable            = binary->info->sp.enable.dis;
767 	dvs_info->width             = binary->dis.grid.dim.width;
768 	dvs_info->height            = binary->dis.grid.dim.height;
769 	dvs_info->aligned_width     = binary->dis.grid.pad.width;
770 	dvs_info->aligned_height    = binary->dis.grid.pad.height;
771 	dvs_info->bqs_per_grid_cell = 1 << binary->dis.deci_factor_log2;
772 	dvs_info->num_hor_coefs     = binary->dis.coef.dim.width;
773 	dvs_info->num_ver_coefs     = binary->dis.coef.dim.height;
774 
775 	sh_css_binary_common_grid_info(binary, info);
776 }
777 
778 void
779 ia_css_binary_dvs_stat_grid_info(
780     const struct ia_css_binary *binary,
781     struct ia_css_grid_info *info,
782     struct ia_css_pipe *pipe)
783 {
784 	(void)pipe;
785 	sh_css_binary_common_grid_info(binary, info);
786 	return;
787 }
788 
789 int
790 ia_css_binary_3a_grid_info(const struct ia_css_binary *binary,
791 			   struct ia_css_grid_info *info,
792 			   struct ia_css_pipe *pipe) {
793 	struct ia_css_3a_grid_info *s3a_info;
794 	int err = 0;
795 
796 	IA_CSS_ENTER_PRIVATE("binary=%p, info=%p, pipe=%p",
797 			     binary, info, pipe);
798 
799 	assert(binary);
800 	assert(info);
801 	s3a_info = &info->s3a_grid;
802 
803 	/* 3A statistics grid */
804 	s3a_info->enable            = binary->info->sp.enable.s3a;
805 	s3a_info->width             = binary->s3atbl_width;
806 	s3a_info->height            = binary->s3atbl_height;
807 	s3a_info->aligned_width     = binary->s3atbl_isp_width;
808 	s3a_info->aligned_height    = binary->s3atbl_isp_height;
809 	s3a_info->bqs_per_grid_cell = (1 << binary->deci_factor_log2);
810 	s3a_info->deci_factor_log2  = binary->deci_factor_log2;
811 	s3a_info->elem_bit_depth    = SH_CSS_BAYER_BITS;
812 	s3a_info->use_dmem          = binary->info->sp.s3a.s3atbl_use_dmem;
813 #if defined(HAS_NO_HMEM)
814 	s3a_info->has_histogram     = 1;
815 #else
816 	s3a_info->has_histogram     = 0;
817 #endif
818 	IA_CSS_LEAVE_ERR_PRIVATE(err);
819 	return err;
820 }
821 
822 static void
823 binary_init_pc_histogram(struct sh_css_pc_histogram *histo)
824 {
825 	assert(histo);
826 
827 	histo->length = 0;
828 	histo->run = NULL;
829 	histo->stall = NULL;
830 }
831 
832 static void
833 binary_init_metrics(struct sh_css_binary_metrics *metrics,
834 		    const struct ia_css_binary_info *info)
835 {
836 	assert(metrics);
837 	assert(info);
838 
839 	metrics->mode = info->pipeline.mode;
840 	metrics->id   = info->id;
841 	metrics->next = NULL;
842 	binary_init_pc_histogram(&metrics->isp_histogram);
843 	binary_init_pc_histogram(&metrics->sp_histogram);
844 }
845 
846 /* move to host part of output module */
847 static bool
848 binary_supports_output_format(const struct ia_css_binary_xinfo *info,
849 			      enum ia_css_frame_format format)
850 {
851 	int i;
852 
853 	assert(info);
854 
855 	for (i = 0; i < info->num_output_formats; i++) {
856 		if (info->output_formats[i] == format)
857 			return true;
858 	}
859 	return false;
860 }
861 
862 static bool
863 binary_supports_vf_format(const struct ia_css_binary_xinfo *info,
864 			  enum ia_css_frame_format format)
865 {
866 	int i;
867 
868 	assert(info);
869 
870 	for (i = 0; i < info->num_vf_formats; i++) {
871 		if (info->vf_formats[i] == format)
872 			return true;
873 	}
874 	return false;
875 }
876 
877 /* move to host part of bds module */
878 static bool
879 supports_bds_factor(u32 supported_factors,
880 		    uint32_t bds_factor)
881 {
882 	return ((supported_factors & PACK_BDS_FACTOR(bds_factor)) != 0);
883 }
884 
885 static int
886 binary_init_info(struct ia_css_binary_xinfo *info, unsigned int i,
887 		 bool *binary_found) {
888 	const unsigned char *blob = sh_css_blob_info[i].blob;
889 	unsigned int size = sh_css_blob_info[i].header.blob.size;
890 
891 	if ((!info) || (!binary_found))
892 		return -EINVAL;
893 
894 	*info = sh_css_blob_info[i].header.info.isp;
895 	*binary_found = blob;
896 	info->blob_index = i;
897 	/* we don't have this binary, skip it */
898 	if (!size)
899 		return 0;
900 
901 	info->xmem_addr = sh_css_load_blob(blob, size);
902 	if (!info->xmem_addr)
903 		return -ENOMEM;
904 	return 0;
905 }
906 
907 /* When binaries are put at the beginning, they will only
908  * be selected if no other primary matches.
909  */
910 int
911 ia_css_binary_init_infos(void) {
912 	unsigned int i;
913 	unsigned int num_of_isp_binaries = sh_css_num_binaries - NUM_OF_SPS - NUM_OF_BLS;
914 
915 	if (num_of_isp_binaries == 0)
916 		return 0;
917 
918 	all_binaries = kvmalloc(num_of_isp_binaries * sizeof(*all_binaries),
919 				GFP_KERNEL);
920 	if (!all_binaries)
921 		return -ENOMEM;
922 
923 	for (i = 0; i < num_of_isp_binaries; i++)
924 	{
925 		int ret;
926 		struct ia_css_binary_xinfo *binary = &all_binaries[i];
927 		bool binary_found;
928 
929 		ret = binary_init_info(binary, i, &binary_found);
930 		if (ret)
931 			return ret;
932 		if (!binary_found)
933 			continue;
934 		/* Prepend new binary information */
935 		binary->next = binary_infos[binary->sp.pipeline.mode];
936 		binary_infos[binary->sp.pipeline.mode] = binary;
937 		binary->blob = &sh_css_blob_info[i];
938 		binary->mem_offsets = sh_css_blob_info[i].mem_offsets;
939 	}
940 	return 0;
941 }
942 
943 int
944 ia_css_binary_uninit(void) {
945 	unsigned int i;
946 	struct ia_css_binary_xinfo *b;
947 
948 	for (i = 0; i < IA_CSS_BINARY_NUM_MODES; i++)
949 	{
950 		for (b = binary_infos[i]; b; b = b->next) {
951 			if (b->xmem_addr)
952 				hmm_free(b->xmem_addr);
953 			b->xmem_addr = mmgr_NULL;
954 		}
955 		binary_infos[i] = NULL;
956 	}
957 	kvfree(all_binaries);
958 	return 0;
959 }
960 
961 /* @brief Compute decimation factor for 3A statistics and shading correction.
962  *
963  * @param[in]	width	Frame width in pixels.
964  * @param[in]	height	Frame height in pixels.
965  * @return	Log2 of decimation factor (= grid cell size) in bayer quads.
966  */
967 static int
968 binary_grid_deci_factor_log2(int width, int height)
969 {
970 	/* 3A/Shading decimation factor spcification (at August 2008)
971 	 * ------------------------------------------------------------------
972 	 * [Image Width (BQ)] [Decimation Factor (BQ)] [Resulting grid cells]
973 	#ifndef ISP2401
974 	 * 1280 ?c             32                       40 ?c
975 	 *  640 ?c 1279        16                       40 ?c 80
976 	 *      ?c  639         8                          ?c 80
977 	#else
978 	 * from 1280                   32                 from 40
979 	 * from  640 to 1279           16                 from 40 to 80
980 	 *           to  639            8                         to 80
981 	#endif
982 	 * ------------------------------------------------------------------
983 	 */
984 	/* Maximum and minimum decimation factor by the specification */
985 #define MAX_SPEC_DECI_FACT_LOG2		5
986 #define MIN_SPEC_DECI_FACT_LOG2		3
987 	/* the smallest frame width in bayer quads when decimation factor (log2) is 5 or 4, by the specification */
988 #define DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ	1280
989 #define DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ	640
990 
991 	int smallest_factor; /* the smallest factor (log2) where the number of cells does not exceed the limitation */
992 	int spec_factor;     /* the factor (log2) which satisfies the specification */
993 
994 	/* Currently supported maximum width and height are 5120(=80*64) and 3840(=60*64). */
995 	assert(ISP_BQ_GRID_WIDTH(width,
996 				 MAX_SPEC_DECI_FACT_LOG2) <= SH_CSS_MAX_BQ_GRID_WIDTH);
997 	assert(ISP_BQ_GRID_HEIGHT(height,
998 				  MAX_SPEC_DECI_FACT_LOG2) <= SH_CSS_MAX_BQ_GRID_HEIGHT);
999 
1000 	/* Compute the smallest factor. */
1001 	smallest_factor = MAX_SPEC_DECI_FACT_LOG2;
1002 	while (ISP_BQ_GRID_WIDTH(width,
1003 				 smallest_factor - 1) <= SH_CSS_MAX_BQ_GRID_WIDTH &&
1004 	       ISP_BQ_GRID_HEIGHT(height, smallest_factor - 1) <= SH_CSS_MAX_BQ_GRID_HEIGHT
1005 	       && smallest_factor > MIN_SPEC_DECI_FACT_LOG2)
1006 		smallest_factor--;
1007 
1008 	/* Get the factor by the specification. */
1009 	if (_ISP_BQS(width) >= DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ)
1010 		spec_factor = 5;
1011 	else if (_ISP_BQS(width) >= DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ)
1012 		spec_factor = 4;
1013 	else
1014 		spec_factor = 3;
1015 
1016 	/* If smallest_factor is smaller than or equal to spec_factor, choose spec_factor to follow the specification.
1017 	   If smallest_factor is larger than spec_factor, choose smallest_factor.
1018 
1019 		ex. width=2560, height=1920
1020 			smallest_factor=4, spec_factor=5
1021 			smallest_factor < spec_factor   ->   return spec_factor
1022 
1023 		ex. width=300, height=3000
1024 			smallest_factor=5, spec_factor=3
1025 			smallest_factor > spec_factor   ->   return smallest_factor
1026 	*/
1027 	return max(smallest_factor, spec_factor);
1028 
1029 #undef MAX_SPEC_DECI_FACT_LOG2
1030 #undef MIN_SPEC_DECI_FACT_LOG2
1031 #undef DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ
1032 #undef DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ
1033 }
1034 
1035 static int
1036 binary_in_frame_padded_width(int in_frame_width,
1037 			     int isp_internal_width,
1038 			     int dvs_env_width,
1039 			     int stream_config_left_padding,
1040 			     int left_cropping,
1041 			     bool need_scaling)
1042 {
1043 	int rval;
1044 	int nr_of_left_paddings;	/* number of paddings pixels on the left of an image line */
1045 
1046 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
1047 	/* the output image line of Input System 2401 does not have the left paddings  */
1048 	nr_of_left_paddings = 0;
1049 #else
1050 	/* in other cases, the left padding pixels are always 128 */
1051 	nr_of_left_paddings = 2 * ISP_VEC_NELEMS;
1052 #endif
1053 	if (need_scaling) {
1054 		/* In SDV use-case, we need to match left-padding of
1055 		 * primary and the video binary. */
1056 		if (stream_config_left_padding != -1) {
1057 			/* Different than before, we do left&right padding. */
1058 			rval =
1059 			    CEIL_MUL(in_frame_width + nr_of_left_paddings,
1060 				     2 * ISP_VEC_NELEMS);
1061 		} else {
1062 			/* Different than before, we do left&right padding. */
1063 			in_frame_width += dvs_env_width;
1064 			rval =
1065 			    CEIL_MUL(in_frame_width +
1066 				     (left_cropping ? nr_of_left_paddings : 0),
1067 				     2 * ISP_VEC_NELEMS);
1068 		}
1069 	} else {
1070 		rval = isp_internal_width;
1071 	}
1072 
1073 	return rval;
1074 }
1075 
1076 int
1077 ia_css_binary_fill_info(const struct ia_css_binary_xinfo *xinfo,
1078 			bool online,
1079 			bool two_ppc,
1080 			enum atomisp_input_format stream_format,
1081 			const struct ia_css_frame_info *in_info, /* can be NULL */
1082 			const struct ia_css_frame_info *bds_out_info, /* can be NULL */
1083 			const struct ia_css_frame_info *out_info[], /* can be NULL */
1084 			const struct ia_css_frame_info *vf_info, /* can be NULL */
1085 			struct ia_css_binary *binary,
1086 			struct ia_css_resolution *dvs_env,
1087 			int stream_config_left_padding,
1088 			bool accelerator) {
1089 	const struct ia_css_binary_info *info = &xinfo->sp;
1090 	unsigned int dvs_env_width = 0,
1091 	dvs_env_height = 0,
1092 	vf_log_ds = 0,
1093 	s3a_log_deci = 0,
1094 	bits_per_pixel = 0,
1095 	/* Resolution at SC/3A/DIS kernel. */
1096 	sc_3a_dis_width = 0,
1097 	/* Resolution at SC/3A/DIS kernel. */
1098 	sc_3a_dis_padded_width = 0,
1099 	/* Resolution at SC/3A/DIS kernel. */
1100 	sc_3a_dis_height = 0,
1101 	isp_internal_width = 0,
1102 	isp_internal_height = 0,
1103 	s3a_isp_width = 0;
1104 
1105 	bool need_scaling = false;
1106 	struct ia_css_resolution binary_dvs_env, internal_res;
1107 	int err;
1108 	unsigned int i;
1109 	const struct ia_css_frame_info *bin_out_info = NULL;
1110 
1111 	assert(info);
1112 	assert(binary);
1113 
1114 	binary->info = xinfo;
1115 	if (!accelerator)
1116 	{
1117 		/* binary->css_params has been filled by accelerator itself. */
1118 		err = ia_css_isp_param_allocate_isp_parameters(
1119 		    &binary->mem_params, &binary->css_params,
1120 		    &info->mem_initializers);
1121 		if (err) {
1122 			return err;
1123 		}
1124 	}
1125 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1126 	{
1127 		if (out_info[i] && (out_info[i]->res.width != 0)) {
1128 			bin_out_info = out_info[i];
1129 			break;
1130 		}
1131 	}
1132 	if (in_info && bin_out_info)
1133 	{
1134 		need_scaling = (in_info->res.width != bin_out_info->res.width) ||
1135 			       (in_info->res.height != bin_out_info->res.height);
1136 	}
1137 
1138 	/* binary_dvs_env has to be equal or larger than SH_CSS_MIN_DVS_ENVELOPE */
1139 	binary_dvs_env.width = 0;
1140 	binary_dvs_env.height = 0;
1141 	ia_css_binary_dvs_env(info, dvs_env, &binary_dvs_env);
1142 	dvs_env_width = binary_dvs_env.width;
1143 	dvs_env_height = binary_dvs_env.height;
1144 	binary->dvs_envelope.width  = dvs_env_width;
1145 	binary->dvs_envelope.height = dvs_env_height;
1146 
1147 	/* internal resolution calculation */
1148 	internal_res.width = 0;
1149 	internal_res.height = 0;
1150 	ia_css_binary_internal_res(in_info, bds_out_info, bin_out_info, dvs_env,
1151 				   info, &internal_res);
1152 	isp_internal_width = internal_res.width;
1153 	isp_internal_height = internal_res.height;
1154 
1155 	/* internal frame info */
1156 	if (bin_out_info) /* { */
1157 		binary->internal_frame_info.format = bin_out_info->format;
1158 	/* } */
1159 	binary->internal_frame_info.res.width       = isp_internal_width;
1160 	binary->internal_frame_info.padded_width    = CEIL_MUL(isp_internal_width, 2 * ISP_VEC_NELEMS);
1161 	binary->internal_frame_info.res.height      = isp_internal_height;
1162 	binary->internal_frame_info.raw_bit_depth   = bits_per_pixel;
1163 
1164 	if (in_info)
1165 	{
1166 		binary->effective_in_frame_res.width = in_info->res.width;
1167 		binary->effective_in_frame_res.height = in_info->res.height;
1168 
1169 		bits_per_pixel = in_info->raw_bit_depth;
1170 
1171 		/* input info */
1172 		binary->in_frame_info.res.width = in_info->res.width +
1173 						  info->pipeline.left_cropping;
1174 		binary->in_frame_info.res.height = in_info->res.height +
1175 						   info->pipeline.top_cropping;
1176 
1177 		binary->in_frame_info.res.width += dvs_env_width;
1178 		binary->in_frame_info.res.height += dvs_env_height;
1179 
1180 		binary->in_frame_info.padded_width =
1181 		    binary_in_frame_padded_width(in_info->res.width,
1182 						 isp_internal_width,
1183 						 dvs_env_width,
1184 						 stream_config_left_padding,
1185 						 info->pipeline.left_cropping,
1186 						 need_scaling);
1187 
1188 		binary->in_frame_info.format = in_info->format;
1189 		binary->in_frame_info.raw_bayer_order = in_info->raw_bayer_order;
1190 		binary->in_frame_info.crop_info = in_info->crop_info;
1191 	}
1192 
1193 	if (online)
1194 	{
1195 		bits_per_pixel = ia_css_util_input_format_bpp(
1196 				     stream_format, two_ppc);
1197 	}
1198 	binary->in_frame_info.raw_bit_depth = bits_per_pixel;
1199 
1200 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1201 	{
1202 		if (out_info[i]) {
1203 			binary->out_frame_info[i].res.width     = out_info[i]->res.width;
1204 			binary->out_frame_info[i].res.height    = out_info[i]->res.height;
1205 			binary->out_frame_info[i].padded_width  = out_info[i]->padded_width;
1206 			if (info->pipeline.mode == IA_CSS_BINARY_MODE_COPY) {
1207 				binary->out_frame_info[i].raw_bit_depth = bits_per_pixel;
1208 			} else {
1209 				/* Only relevant for RAW format.
1210 				 * At the moment, all outputs are raw, 16 bit per pixel, except for copy.
1211 				 * To do this cleanly, the binary should specify in its info
1212 				 * the bit depth per output channel.
1213 				 */
1214 				binary->out_frame_info[i].raw_bit_depth = 16;
1215 			}
1216 			binary->out_frame_info[i].format        = out_info[i]->format;
1217 		}
1218 	}
1219 
1220 	if (vf_info && (vf_info->res.width != 0))
1221 	{
1222 		err = ia_css_vf_configure(binary, bin_out_info,
1223 					  (struct ia_css_frame_info *)vf_info, &vf_log_ds);
1224 		if (err) {
1225 			if (!accelerator) {
1226 				ia_css_isp_param_destroy_isp_parameters(
1227 				    &binary->mem_params,
1228 				    &binary->css_params);
1229 			}
1230 			return err;
1231 		}
1232 	}
1233 	binary->vf_downscale_log2 = vf_log_ds;
1234 
1235 	binary->online            = online;
1236 	binary->input_format      = stream_format;
1237 
1238 	/* viewfinder output info */
1239 	if ((vf_info) && (vf_info->res.width != 0))
1240 	{
1241 		unsigned int vf_out_vecs, vf_out_width, vf_out_height;
1242 
1243 		binary->vf_frame_info.format = vf_info->format;
1244 		if (!bin_out_info)
1245 			return -EINVAL;
1246 		vf_out_vecs = __ISP_VF_OUTPUT_WIDTH_VECS(bin_out_info->padded_width,
1247 			      vf_log_ds);
1248 		vf_out_width = _ISP_VF_OUTPUT_WIDTH(vf_out_vecs);
1249 		vf_out_height = _ISP_VF_OUTPUT_HEIGHT(bin_out_info->res.height,
1250 						      vf_log_ds);
1251 
1252 		/* For preview mode, output pin is used instead of vf. */
1253 		if (info->pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW) {
1254 			binary->out_frame_info[0].res.width =
1255 			    (bin_out_info->res.width >> vf_log_ds);
1256 			binary->out_frame_info[0].padded_width = vf_out_width;
1257 			binary->out_frame_info[0].res.height   = vf_out_height;
1258 
1259 			binary->vf_frame_info.res.width    = 0;
1260 			binary->vf_frame_info.padded_width = 0;
1261 			binary->vf_frame_info.res.height   = 0;
1262 		} else {
1263 			/* we also store the raw downscaled width. This is
1264 			 * used for digital zoom in preview to zoom only on
1265 			 * the width that we actually want to keep, not on
1266 			 * the aligned width. */
1267 			binary->vf_frame_info.res.width =
1268 			    (bin_out_info->res.width >> vf_log_ds);
1269 			binary->vf_frame_info.padded_width = vf_out_width;
1270 			binary->vf_frame_info.res.height   = vf_out_height;
1271 		}
1272 	} else
1273 	{
1274 		binary->vf_frame_info.res.width    = 0;
1275 		binary->vf_frame_info.padded_width = 0;
1276 		binary->vf_frame_info.res.height   = 0;
1277 	}
1278 
1279 	if (info->enable.ca_gdc)
1280 	{
1281 		binary->morph_tbl_width =
1282 		    _ISP_MORPH_TABLE_WIDTH(isp_internal_width);
1283 		binary->morph_tbl_aligned_width  =
1284 		    _ISP_MORPH_TABLE_ALIGNED_WIDTH(isp_internal_width);
1285 		binary->morph_tbl_height =
1286 		    _ISP_MORPH_TABLE_HEIGHT(isp_internal_height);
1287 	} else
1288 	{
1289 		binary->morph_tbl_width  = 0;
1290 		binary->morph_tbl_aligned_width  = 0;
1291 		binary->morph_tbl_height = 0;
1292 	}
1293 
1294 	sc_3a_dis_width = binary->in_frame_info.res.width;
1295 	sc_3a_dis_padded_width = binary->in_frame_info.padded_width;
1296 	sc_3a_dis_height = binary->in_frame_info.res.height;
1297 	if (bds_out_info && in_info &&
1298 	    bds_out_info->res.width != in_info->res.width)
1299 	{
1300 		/* TODO: Next, "internal_frame_info" should be derived from
1301 		 * bds_out. So this part will change once it is in place! */
1302 		sc_3a_dis_width = bds_out_info->res.width + info->pipeline.left_cropping;
1303 		sc_3a_dis_padded_width = isp_internal_width;
1304 		sc_3a_dis_height = isp_internal_height;
1305 	}
1306 
1307 	s3a_isp_width = _ISP_S3A_ELEMS_ISP_WIDTH(sc_3a_dis_padded_width,
1308 			info->pipeline.left_cropping);
1309 	if (info->s3a.fixed_s3a_deci_log)
1310 	{
1311 		s3a_log_deci = info->s3a.fixed_s3a_deci_log;
1312 	} else
1313 	{
1314 		s3a_log_deci = binary_grid_deci_factor_log2(s3a_isp_width,
1315 			       sc_3a_dis_height);
1316 	}
1317 	binary->deci_factor_log2  = s3a_log_deci;
1318 
1319 	if (info->enable.s3a)
1320 	{
1321 		binary->s3atbl_width  =
1322 		    _ISP_S3ATBL_WIDTH(sc_3a_dis_width,
1323 				      s3a_log_deci);
1324 		binary->s3atbl_height =
1325 		    _ISP_S3ATBL_HEIGHT(sc_3a_dis_height,
1326 				       s3a_log_deci);
1327 		binary->s3atbl_isp_width =
1328 		    _ISP_S3ATBL_ISP_WIDTH(s3a_isp_width,
1329 					  s3a_log_deci);
1330 		binary->s3atbl_isp_height =
1331 		    _ISP_S3ATBL_ISP_HEIGHT(sc_3a_dis_height,
1332 					   s3a_log_deci);
1333 	} else
1334 	{
1335 		binary->s3atbl_width  = 0;
1336 		binary->s3atbl_height = 0;
1337 		binary->s3atbl_isp_width  = 0;
1338 		binary->s3atbl_isp_height = 0;
1339 	}
1340 
1341 	if (info->enable.sc)
1342 	{
1343 		if (!atomisp_hw_is_isp2401) {
1344 			binary->sctbl_width_per_color = _ISP2400_SCTBL_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci);
1345 			binary->sctbl_aligned_width_per_color = ISP2400_SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR;
1346 			binary->sctbl_height = _ISP2400_SCTBL_HEIGHT(sc_3a_dis_height, s3a_log_deci);
1347 		} else {
1348 			binary->sctbl_width_per_color = _ISP2401_SCTBL_WIDTH_PER_COLOR(isp_internal_width, s3a_log_deci);
1349 			binary->sctbl_aligned_width_per_color = ISP2401_SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR;
1350 			binary->sctbl_height = _ISP2401_SCTBL_HEIGHT(isp_internal_height, s3a_log_deci);
1351 			binary->sctbl_legacy_width_per_color  = _ISP_SCTBL_LEGACY_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci);
1352 			binary->sctbl_legacy_height = _ISP_SCTBL_LEGACY_HEIGHT(sc_3a_dis_height, s3a_log_deci);
1353 		}
1354 	} else
1355 	{
1356 		binary->sctbl_width_per_color         = 0;
1357 		binary->sctbl_aligned_width_per_color = 0;
1358 		binary->sctbl_height                  = 0;
1359 		if (atomisp_hw_is_isp2401) {
1360 			binary->sctbl_legacy_width_per_color  = 0;
1361 			binary->sctbl_legacy_height	      = 0;
1362 		}
1363 	}
1364 	ia_css_sdis_init_info(&binary->dis,
1365 			      sc_3a_dis_width,
1366 			      sc_3a_dis_padded_width,
1367 			      sc_3a_dis_height,
1368 			      info->pipeline.isp_pipe_version,
1369 			      info->enable.dis);
1370 	if (info->pipeline.left_cropping)
1371 		binary->left_padding = 2 * ISP_VEC_NELEMS - info->pipeline.left_cropping;
1372 	else
1373 		binary->left_padding = 0;
1374 
1375 	return 0;
1376 }
1377 
1378 int
1379 ia_css_binary_find(struct ia_css_binary_descr *descr,
1380 		   struct ia_css_binary *binary) {
1381 	int mode;
1382 	bool online;
1383 	bool two_ppc;
1384 	enum atomisp_input_format stream_format;
1385 	const struct ia_css_frame_info *req_in_info,
1386 		*req_bds_out_info,
1387 		*req_out_info[IA_CSS_BINARY_MAX_OUTPUT_PORTS],
1388 		*req_bin_out_info = NULL,
1389 		*req_vf_info;
1390 
1391 	struct ia_css_binary_xinfo *xcandidate;
1392 #ifndef ISP2401
1393 	bool need_ds, need_dz, need_dvs, need_xnr, need_dpc;
1394 #else
1395 	bool need_ds, need_dz, need_dvs, need_xnr, need_dpc, need_tnr;
1396 #endif
1397 	bool striped;
1398 	bool enable_yuv_ds;
1399 	bool enable_high_speed;
1400 	bool enable_dvs_6axis;
1401 	bool enable_reduced_pipe;
1402 	bool enable_capture_pp_bli;
1403 #ifdef ISP2401
1404 	bool enable_luma_only;
1405 #endif
1406 	int err = -EINVAL;
1407 	bool continuous;
1408 	unsigned int isp_pipe_version;
1409 	struct ia_css_resolution dvs_env, internal_res;
1410 	unsigned int i;
1411 
1412 	assert(descr);
1413 	/* MW: used after an error check, may accept NULL, but doubtfull */
1414 	assert(binary);
1415 
1416 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1417 			    "ia_css_binary_find() enter: descr=%p, (mode=%d), binary=%p\n",
1418 			    descr, descr->mode,
1419 			    binary);
1420 
1421 	mode = descr->mode;
1422 	online = descr->online;
1423 	two_ppc = descr->two_ppc;
1424 	stream_format = descr->stream_format;
1425 	req_in_info = descr->in_info;
1426 	req_bds_out_info = descr->bds_out_info;
1427 	for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1428 	{
1429 		req_out_info[i] = descr->out_info[i];
1430 		if (req_out_info[i] && (req_out_info[i]->res.width != 0))
1431 			req_bin_out_info = req_out_info[i];
1432 	}
1433 	if (!req_bin_out_info)
1434 		return -EINVAL;
1435 #ifndef ISP2401
1436 	req_vf_info = descr->vf_info;
1437 #else
1438 
1439 	if ((descr->vf_info) && (descr->vf_info->res.width == 0))
1440 		/* width==0 means that there is no vf pin (e.g. in SkyCam preview case) */
1441 		req_vf_info = NULL;
1442 	else
1443 		req_vf_info = descr->vf_info;
1444 #endif
1445 
1446 	need_xnr = descr->enable_xnr;
1447 	need_ds = descr->enable_fractional_ds;
1448 	need_dz = false;
1449 	need_dvs = false;
1450 	need_dpc = descr->enable_dpc;
1451 #ifdef ISP2401
1452 	need_tnr = descr->enable_tnr;
1453 #endif
1454 	enable_yuv_ds = descr->enable_yuv_ds;
1455 	enable_high_speed = descr->enable_high_speed;
1456 	enable_dvs_6axis  = descr->enable_dvs_6axis;
1457 	enable_reduced_pipe = descr->enable_reduced_pipe;
1458 	enable_capture_pp_bli = descr->enable_capture_pp_bli;
1459 #ifdef ISP2401
1460 	enable_luma_only = descr->enable_luma_only;
1461 #endif
1462 	continuous = descr->continuous;
1463 	striped = descr->striped;
1464 	isp_pipe_version = descr->isp_pipe_version;
1465 
1466 	dvs_env.width = 0;
1467 	dvs_env.height = 0;
1468 	internal_res.width = 0;
1469 	internal_res.height = 0;
1470 
1471 	if (mode == IA_CSS_BINARY_MODE_VIDEO)
1472 	{
1473 		dvs_env = descr->dvs_env;
1474 		need_dz = descr->enable_dz;
1475 		/* Video is the only mode that has a nodz variant. */
1476 		need_dvs = dvs_env.width || dvs_env.height;
1477 	}
1478 
1479 	/* print a map of the binary file */
1480 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,	"BINARY INFO:\n");
1481 	for (i = 0; i < IA_CSS_BINARY_NUM_MODES; i++)
1482 	{
1483 		xcandidate = binary_infos[i];
1484 		if (xcandidate) {
1485 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,	"%d:\n", i);
1486 			while (xcandidate) {
1487 				ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, " Name:%s Type:%d Cont:%d\n",
1488 						    xcandidate->blob->name, xcandidate->type,
1489 						    xcandidate->sp.enable.continuous);
1490 				xcandidate = xcandidate->next;
1491 			}
1492 		}
1493 	}
1494 
1495 	/* printf("sh_css_binary_find: pipe version %d\n", isp_pipe_version); */
1496 	for (xcandidate = binary_infos[mode]; xcandidate;
1497 	     xcandidate = xcandidate->next)
1498 	{
1499 		struct ia_css_binary_info *candidate = &xcandidate->sp;
1500 		/* printf("sh_css_binary_find: evaluating candidate:
1501 		 * %d\n",candidate->id); */
1502 		ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1503 				    "ia_css_binary_find() candidate = %p, mode = %d ID = %d\n",
1504 				    candidate, candidate->pipeline.mode, candidate->id);
1505 
1506 		/*
1507 		 * MW: Only a limited set of jointly configured binaries can
1508 		 * be used in a continuous preview/video mode unless it is
1509 		 * the copy mode and runs on SP.
1510 		*/
1511 		if (!candidate->enable.continuous &&
1512 		    continuous && (mode != IA_CSS_BINARY_MODE_COPY)) {
1513 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1514 					    "ia_css_binary_find() [%d] continue: !%d && %d && (%d != %d)\n",
1515 					    __LINE__, candidate->enable.continuous,
1516 					    continuous, mode,
1517 					    IA_CSS_BINARY_MODE_COPY);
1518 			continue;
1519 		}
1520 		if (striped && candidate->iterator.num_stripes == 1) {
1521 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1522 					    "ia_css_binary_find() [%d] continue: binary is not striped\n",
1523 					    __LINE__);
1524 			continue;
1525 		}
1526 
1527 		if (candidate->pipeline.isp_pipe_version != isp_pipe_version &&
1528 		    (mode != IA_CSS_BINARY_MODE_COPY) &&
1529 		    (mode != IA_CSS_BINARY_MODE_CAPTURE_PP) &&
1530 		    (mode != IA_CSS_BINARY_MODE_VF_PP)) {
1531 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1532 					    "ia_css_binary_find() [%d] continue: (%d != %d)\n",
1533 					    __LINE__,
1534 					    candidate->pipeline.isp_pipe_version, isp_pipe_version);
1535 			continue;
1536 		}
1537 		if (!candidate->enable.reduced_pipe && enable_reduced_pipe) {
1538 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1539 					    "ia_css_binary_find() [%d] continue: !%d && %d\n",
1540 					    __LINE__,
1541 					    candidate->enable.reduced_pipe,
1542 					    enable_reduced_pipe);
1543 			continue;
1544 		}
1545 		if (!candidate->enable.dvs_6axis && enable_dvs_6axis) {
1546 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1547 					    "ia_css_binary_find() [%d] continue: !%d && %d\n",
1548 					    __LINE__,
1549 					    candidate->enable.dvs_6axis,
1550 					    enable_dvs_6axis);
1551 			continue;
1552 		}
1553 		if (candidate->enable.high_speed && !enable_high_speed) {
1554 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1555 					    "ia_css_binary_find() [%d] continue: %d && !%d\n",
1556 					    __LINE__,
1557 					    candidate->enable.high_speed,
1558 					    enable_high_speed);
1559 			continue;
1560 		}
1561 		if (!candidate->enable.xnr && need_xnr) {
1562 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1563 					    "ia_css_binary_find() [%d] continue: %d && !%d\n",
1564 					    __LINE__,
1565 					    candidate->enable.xnr,
1566 					    need_xnr);
1567 			continue;
1568 		}
1569 		if (!(candidate->enable.ds & 2) && enable_yuv_ds) {
1570 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1571 					    "ia_css_binary_find() [%d] continue: !%d && %d\n",
1572 					    __LINE__,
1573 					    ((candidate->enable.ds & 2) != 0),
1574 					    enable_yuv_ds);
1575 			continue;
1576 		}
1577 		if ((candidate->enable.ds & 2) && !enable_yuv_ds) {
1578 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1579 					    "ia_css_binary_find() [%d] continue: %d && !%d\n",
1580 					    __LINE__,
1581 					    ((candidate->enable.ds & 2) != 0),
1582 					    enable_yuv_ds);
1583 			continue;
1584 		}
1585 
1586 		if (mode == IA_CSS_BINARY_MODE_VIDEO &&
1587 		    candidate->enable.ds && need_ds)
1588 			need_dz = false;
1589 
1590 		/* when we require vf output, we need to have vf_veceven */
1591 		if ((req_vf_info) && !(candidate->enable.vf_veceven ||
1592 				       /* or variable vf vec even */
1593 				       candidate->vf_dec.is_variable ||
1594 				       /* or more than one output pin. */
1595 				       xcandidate->num_output_pins > 1)) {
1596 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1597 					    "ia_css_binary_find() [%d] continue: (%p != NULL) && !(%d || %d || (%d >%d))\n",
1598 					    __LINE__, req_vf_info,
1599 					    candidate->enable.vf_veceven,
1600 					    candidate->vf_dec.is_variable,
1601 					    xcandidate->num_output_pins, 1);
1602 			continue;
1603 		}
1604 		if (!candidate->enable.dvs_envelope && need_dvs) {
1605 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1606 					    "ia_css_binary_find() [%d] continue: !%d && %d\n",
1607 					    __LINE__,
1608 					    candidate->enable.dvs_envelope, (int)need_dvs);
1609 			continue;
1610 		}
1611 		/* internal_res check considers input, output, and dvs envelope sizes */
1612 		ia_css_binary_internal_res(req_in_info, req_bds_out_info,
1613 					   req_bin_out_info, &dvs_env, candidate, &internal_res);
1614 		if (internal_res.width > candidate->internal.max_width) {
1615 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1616 					    "ia_css_binary_find() [%d] continue: (%d > %d)\n",
1617 					    __LINE__, internal_res.width,
1618 					    candidate->internal.max_width);
1619 			continue;
1620 		}
1621 		if (internal_res.height > candidate->internal.max_height) {
1622 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1623 					    "ia_css_binary_find() [%d] continue: (%d > %d)\n",
1624 					    __LINE__, internal_res.height,
1625 					    candidate->internal.max_height);
1626 			continue;
1627 		}
1628 		if (!candidate->enable.ds && need_ds && !(xcandidate->num_output_pins > 1)) {
1629 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1630 					    "ia_css_binary_find() [%d] continue: !%d && %d\n",
1631 					    __LINE__, candidate->enable.ds, (int)need_ds);
1632 			continue;
1633 		}
1634 		if (!candidate->enable.uds && !candidate->enable.dvs_6axis && need_dz) {
1635 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1636 					    "ia_css_binary_find() [%d] continue: !%d && !%d && %d\n",
1637 					    __LINE__, candidate->enable.uds,
1638 					    candidate->enable.dvs_6axis, (int)need_dz);
1639 			continue;
1640 		}
1641 		if (online && candidate->input.source == IA_CSS_BINARY_INPUT_MEMORY) {
1642 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1643 					    "ia_css_binary_find() [%d] continue: %d && (%d == %d)\n",
1644 					    __LINE__, online, candidate->input.source,
1645 					    IA_CSS_BINARY_INPUT_MEMORY);
1646 			continue;
1647 		}
1648 		if (!online && candidate->input.source == IA_CSS_BINARY_INPUT_SENSOR) {
1649 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1650 					    "ia_css_binary_find() [%d] continue: !%d && (%d == %d)\n",
1651 					    __LINE__, online, candidate->input.source,
1652 					    IA_CSS_BINARY_INPUT_SENSOR);
1653 			continue;
1654 		}
1655 		if (req_bin_out_info->res.width < candidate->output.min_width ||
1656 		    req_bin_out_info->res.width > candidate->output.max_width) {
1657 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1658 					    "ia_css_binary_find() [%d] continue: (%d > %d) || (%d < %d)\n",
1659 					    __LINE__,
1660 					    req_bin_out_info->padded_width,
1661 					    candidate->output.min_width,
1662 					    req_bin_out_info->padded_width,
1663 					    candidate->output.max_width);
1664 			continue;
1665 		}
1666 		if (xcandidate->num_output_pins > 1 &&
1667 		    /* in case we have a second output pin, */
1668 		    req_vf_info) { /* and we need vf output. */
1669 			if (req_vf_info->res.width > candidate->output.max_width) {
1670 				ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1671 						    "ia_css_binary_find() [%d] continue: (%d < %d)\n",
1672 						    __LINE__,
1673 						    req_vf_info->res.width,
1674 						    candidate->output.max_width);
1675 				continue;
1676 			}
1677 		}
1678 		if (req_in_info->padded_width > candidate->input.max_width) {
1679 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1680 					    "ia_css_binary_find() [%d] continue: (%d > %d)\n",
1681 					    __LINE__, req_in_info->padded_width,
1682 					    candidate->input.max_width);
1683 			continue;
1684 		}
1685 		if (!binary_supports_output_format(xcandidate, req_bin_out_info->format)) {
1686 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1687 					    "ia_css_binary_find() [%d] continue: !%d\n",
1688 					    __LINE__,
1689 					    binary_supports_output_format(xcandidate, req_bin_out_info->format));
1690 			continue;
1691 		}
1692 		if (xcandidate->num_output_pins > 1 &&
1693 		    /* in case we have a second output pin, */
1694 		    req_vf_info                   && /* and we need vf output. */
1695 		    /* check if the required vf format
1696 		    is supported. */
1697 		    !binary_supports_output_format(xcandidate, req_vf_info->format)) {
1698 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1699 					    "ia_css_binary_find() [%d] continue: (%d > %d) && (%p != NULL) && !%d\n",
1700 					    __LINE__, xcandidate->num_output_pins, 1,
1701 					    req_vf_info,
1702 					    binary_supports_output_format(xcandidate, req_vf_info->format));
1703 			continue;
1704 		}
1705 
1706 		/* Check if vf_veceven supports the requested vf format */
1707 		if (xcandidate->num_output_pins == 1 &&
1708 		    req_vf_info && candidate->enable.vf_veceven &&
1709 		    !binary_supports_vf_format(xcandidate, req_vf_info->format)) {
1710 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1711 					    "ia_css_binary_find() [%d] continue: (%d == %d) && (%p != NULL) && %d && !%d\n",
1712 					    __LINE__, xcandidate->num_output_pins, 1,
1713 					    req_vf_info, candidate->enable.vf_veceven,
1714 					    binary_supports_vf_format(xcandidate, req_vf_info->format));
1715 			continue;
1716 		}
1717 
1718 		/* Check if vf_veceven supports the requested vf width */
1719 		if (xcandidate->num_output_pins == 1 &&
1720 		    req_vf_info && candidate->enable.vf_veceven) { /* and we need vf output. */
1721 			if (req_vf_info->res.width > candidate->output.max_width) {
1722 				ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1723 						    "ia_css_binary_find() [%d] continue: (%d < %d)\n",
1724 						    __LINE__,
1725 						    req_vf_info->res.width,
1726 						    candidate->output.max_width);
1727 				continue;
1728 			}
1729 		}
1730 
1731 		if (!supports_bds_factor(candidate->bds.supported_bds_factors,
1732 					 descr->required_bds_factor)) {
1733 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1734 					    "ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n",
1735 					    __LINE__, candidate->bds.supported_bds_factors,
1736 					    descr->required_bds_factor);
1737 			continue;
1738 		}
1739 
1740 		if (!candidate->enable.dpc && need_dpc) {
1741 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1742 					    "ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n",
1743 					    __LINE__, candidate->enable.dpc,
1744 					    descr->enable_dpc);
1745 			continue;
1746 		}
1747 
1748 		if (candidate->uds.use_bci && enable_capture_pp_bli) {
1749 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1750 					    "ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n",
1751 					    __LINE__, candidate->uds.use_bci,
1752 					    descr->enable_capture_pp_bli);
1753 			continue;
1754 		}
1755 
1756 #ifdef ISP2401
1757 		if (candidate->enable.luma_only != enable_luma_only) {
1758 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1759 					    "ia_css_binary_find() [%d] continue: %d != %d\n",
1760 					    __LINE__, candidate->enable.luma_only,
1761 					    descr->enable_luma_only);
1762 			continue;
1763 		}
1764 
1765 		if (!candidate->enable.tnr && need_tnr) {
1766 			ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1767 					    "ia_css_binary_find() [%d] continue: !%d && %d\n",
1768 					    __LINE__, candidate->enable.tnr,
1769 					    descr->enable_tnr);
1770 			continue;
1771 		}
1772 
1773 #endif
1774 		/* reconfigure any variable properties of the binary */
1775 		err = ia_css_binary_fill_info(xcandidate, online, two_ppc,
1776 					      stream_format, req_in_info,
1777 					      req_bds_out_info,
1778 					      req_out_info, req_vf_info,
1779 					      binary, &dvs_env,
1780 					      descr->stream_config_left_padding,
1781 					      false);
1782 
1783 		if (err)
1784 			break;
1785 		binary_init_metrics(&binary->metrics, &binary->info->sp);
1786 		break;
1787 	}
1788 
1789 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1790 			    "ia_css_binary_find() selected = %p, mode = %d ID = %d\n",
1791 			    xcandidate, xcandidate ? xcandidate->sp.pipeline.mode : 0, xcandidate ? xcandidate->sp.id : 0);
1792 
1793 	ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1794 			    "ia_css_binary_find() leave: return_err=%d\n", err);
1795 
1796 	return err;
1797 }
1798 
1799 unsigned
1800 ia_css_binary_max_vf_width(void)
1801 {
1802 	/* This is (should be) true for IPU1 and IPU2 */
1803 	/* For IPU3 (SkyCam) this pointer is guaranteed to be NULL simply because such a binary does not exist  */
1804 	if (binary_infos[IA_CSS_BINARY_MODE_VF_PP])
1805 		return binary_infos[IA_CSS_BINARY_MODE_VF_PP]->sp.output.max_width;
1806 	return 0;
1807 }
1808 
1809 void
1810 ia_css_binary_destroy_isp_parameters(struct ia_css_binary *binary)
1811 {
1812 	if (binary) {
1813 		ia_css_isp_param_destroy_isp_parameters(&binary->mem_params,
1814 							&binary->css_params);
1815 	}
1816 }
1817 
1818 void
1819 ia_css_binary_get_isp_binaries(struct ia_css_binary_xinfo **binaries,
1820 			       uint32_t *num_isp_binaries)
1821 {
1822 	assert(binaries);
1823 
1824 	if (num_isp_binaries)
1825 		*num_isp_binaries = 0;
1826 
1827 	*binaries = all_binaries;
1828 	if (all_binaries && num_isp_binaries) {
1829 		/* -1 to account for sp binary which is not stored in all_binaries */
1830 		if (sh_css_num_binaries > 0)
1831 			*num_isp_binaries = sh_css_num_binaries - 1;
1832 	}
1833 }
1834