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