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