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