blob: 9f8a125f0d7407bc51d600e98e398bbc8aa93a48 [file] [log] [blame]
/*
* Support for Intel Camera Imaging ISP subsystem.
* Copyright (c) 2015, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <math_support.h>
#include <gdc_device.h> /* HR_GDC_N */
#include "isp.h" /* ISP_VEC_NELEMS */
#include "ia_css_binary.h"
#include "ia_css_debug.h"
#include "ia_css_util.h"
#include "ia_css_isp_param.h"
#include "sh_css_internal.h"
#include "sh_css_sp.h"
#include "sh_css_firmware.h"
#include "sh_css_defs.h"
#include "sh_css_legacy.h"
#include "vf/vf_1.0/ia_css_vf.host.h"
#ifdef ISP2401
#include "sc/sc_1.0/ia_css_sc.host.h"
#endif
#include "sdis/sdis_1.0/ia_css_sdis.host.h"
#ifdef ISP2401
#include "fixedbds/fixedbds_1.0/ia_css_fixedbds_param.h" /* FRAC_ACC */
#endif
#include "camera/pipe/interface/ia_css_pipe_binarydesc.h"
#include "memory_access.h"
#include "assert_support.h"
#define IMPLIES(a, b) (!(a) || (b)) /* A => B */
static struct ia_css_binary_xinfo *all_binaries; /* ISP binaries only (no SP) */
static struct ia_css_binary_xinfo
*binary_infos[IA_CSS_BINARY_NUM_MODES] = { NULL, };
static void
ia_css_binary_dvs_env(const struct ia_css_binary_info *info,
const struct ia_css_resolution *dvs_env,
struct ia_css_resolution *binary_dvs_env)
{
if (info->enable.dvs_envelope) {
assert(dvs_env != NULL);
binary_dvs_env->width = max(dvs_env->width, SH_CSS_MIN_DVS_ENVELOPE);
binary_dvs_env->height = max(dvs_env->height, SH_CSS_MIN_DVS_ENVELOPE);
}
}
static void
ia_css_binary_internal_res(const struct ia_css_frame_info *in_info,
const struct ia_css_frame_info *bds_out_info,
const struct ia_css_frame_info *out_info,
const struct ia_css_resolution *dvs_env,
const struct ia_css_binary_info *info,
struct ia_css_resolution *internal_res)
{
unsigned int isp_tmp_internal_width = 0,
isp_tmp_internal_height = 0;
bool binary_supports_yuv_ds = info->enable.ds & 2;
struct ia_css_resolution binary_dvs_env;
binary_dvs_env.width = 0;
binary_dvs_env.height = 0;
ia_css_binary_dvs_env(info, dvs_env, &binary_dvs_env);
if (binary_supports_yuv_ds) {
if (in_info != NULL) {
isp_tmp_internal_width = in_info->res.width
+ info->pipeline.left_cropping + binary_dvs_env.width;
isp_tmp_internal_height = in_info->res.height
+ info->pipeline.top_cropping + binary_dvs_env.height;
}
} else if ((bds_out_info != NULL) && (out_info != NULL) &&
/* TODO: hack to make video_us case work. this should be reverted after
a nice solution in ISP */
(bds_out_info->res.width >= out_info->res.width)) {
isp_tmp_internal_width = bds_out_info->padded_width;
isp_tmp_internal_height = bds_out_info->res.height;
} else {
if (out_info != NULL) {
isp_tmp_internal_width = out_info->padded_width;
isp_tmp_internal_height = out_info->res.height;
}
}
/* We first calculate the resolutions used by the ISP. After that,
* we use those resolutions to compute sizes for tables etc. */
internal_res->width = __ISP_INTERNAL_WIDTH(isp_tmp_internal_width,
(int)binary_dvs_env.width,
info->pipeline.left_cropping, info->pipeline.mode,
info->pipeline.c_subsampling,
info->output.num_chunks, info->pipeline.pipelining);
internal_res->height = __ISP_INTERNAL_HEIGHT(isp_tmp_internal_height,
info->pipeline.top_cropping,
binary_dvs_env.height);
}
#ifndef ISP2401
/* Computation results of the origin coordinate of bayer on the shading table. */
struct sh_css_shading_table_bayer_origin_compute_results {
uint32_t bayer_scale_hor_ratio_in; /* Horizontal ratio (in) of bayer scaling. */
uint32_t bayer_scale_hor_ratio_out; /* Horizontal ratio (out) of bayer scaling. */
uint32_t bayer_scale_ver_ratio_in; /* Vertical ratio (in) of bayer scaling. */
uint32_t bayer_scale_ver_ratio_out; /* Vertical ratio (out) of bayer scaling. */
uint32_t sc_bayer_origin_x_bqs_on_shading_table; /* X coordinate (in bqs) of bayer origin on shading table. */
uint32_t sc_bayer_origin_y_bqs_on_shading_table; /* Y coordinate (in bqs) of bayer origin on shading table. */
#else
/* Requirements for the shading correction. */
struct sh_css_binary_sc_requirements {
/* Bayer scaling factor, for the scaling which is applied before shading correction. */
uint32_t bayer_scale_hor_ratio_in; /* Horizontal ratio (in) of scaling applied BEFORE shading correction. */
uint32_t bayer_scale_hor_ratio_out; /* Horizontal ratio (out) of scaling applied BEFORE shading correction. */
uint32_t bayer_scale_ver_ratio_in; /* Vertical ratio (in) of scaling applied BEFORE shading correction. */
uint32_t bayer_scale_ver_ratio_out; /* Vertical ratio (out) of scaling applied BEFORE shading correction. */
/* ISP internal frame is composed of the real sensor data and the padding data. */
uint32_t sensor_data_origin_x_bqs_on_internal; /* X origin (in bqs) of sensor data on internal frame
at shading correction. */
uint32_t sensor_data_origin_y_bqs_on_internal; /* Y origin (in bqs) of sensor data on internal frame
at shading correction. */
#endif
};
/* Get the requirements for the shading correction. */
static enum ia_css_err
#ifndef ISP2401
ia_css_binary_compute_shading_table_bayer_origin(
const struct ia_css_binary *binary, /* [in] */
unsigned int required_bds_factor, /* [in] */
const struct ia_css_stream_config *stream_config, /* [in] */
struct sh_css_shading_table_bayer_origin_compute_results *res) /* [out] */
#else
sh_css_binary_get_sc_requirements(
const struct ia_css_binary *binary, /* [in] */
unsigned int required_bds_factor, /* [in] */
const struct ia_css_stream_config *stream_config, /* [in] */
struct sh_css_binary_sc_requirements *scr) /* [out] */
#endif
{
enum ia_css_err err;
#ifndef ISP2401
/* Numerator and denominator of the fixed bayer downscaling factor.
(numerator >= denominator) */
#else
/* Numerator and denominator of the fixed bayer downscaling factor. (numerator >= denominator) */
#endif
unsigned int bds_num, bds_den;
#ifndef ISP2401
/* Horizontal/Vertical ratio of bayer scaling
between input area and output area. */
unsigned int bs_hor_ratio_in;
unsigned int bs_hor_ratio_out;
unsigned int bs_ver_ratio_in;
unsigned int bs_ver_ratio_out;
#else
/* Horizontal/Vertical ratio of bayer scaling between input area and output area. */
unsigned int bs_hor_ratio_in, bs_hor_ratio_out, bs_ver_ratio_in, bs_ver_ratio_out;
#endif
/* Left padding set by InputFormatter. */
#ifndef ISP2401
unsigned int left_padding_bqs; /* in bqs */
#else
unsigned int left_padding_bqs;
#endif
#ifndef ISP2401
/* Flag for the NEED_BDS_FACTOR_2_00 macro defined in isp kernels. */
unsigned int need_bds_factor_2_00;
/* Left padding adjusted inside the isp. */
unsigned int left_padding_adjusted_bqs; /* in bqs */
/* Bad pixels caused by filters.
NxN-filter (before/after bayer scaling) moves the image position
to right/bottom directions by a few pixels.
It causes bad pixels at left/top sides,
and effective bayer size decreases. */
unsigned int bad_bqs_on_left_before_bs; /* in bqs */
unsigned int bad_bqs_on_left_after_bs; /* in bqs */
unsigned int bad_bqs_on_top_before_bs; /* in bqs */
unsigned int bad_bqs_on_top_after_bs; /* in bqs */
/* Get the numerator and denominator of bayer downscaling factor. */
err = sh_css_bds_factor_get_numerator_denominator
(required_bds_factor, &bds_num, &bds_den);
if (err != IA_CSS_SUCCESS)
#else
/* Flags corresponding to NEED_BDS_FACTOR_2_00/NEED_BDS_FACTOR_1_50/NEED_BDS_FACTOR_1_25 macros
* defined in isp kernels. */
unsigned int need_bds_factor_2_00, need_bds_factor_1_50, need_bds_factor_1_25;
/* Left padding adjusted inside the isp kernels. */
unsigned int left_padding_adjusted_bqs;
/* Top padding padded inside the isp kernel for bayer downscaling binaries. */
unsigned int top_padding_bqs;
/* Bayer downscaling factor 1.0 by fixed-point. */
int bds_frac_acc = FRAC_ACC; /* FRAC_ACC is defined in ia_css_fixedbds_param.h. */
/* Right/Down shift amount caused by filters applied BEFORE shading corrertion. */
unsigned int right_shift_bqs_before_bs; /* right shift before bayer scaling */
unsigned int right_shift_bqs_after_bs; /* right shift after bayer scaling */
unsigned int down_shift_bqs_before_bs; /* down shift before bayer scaling */
unsigned int down_shift_bqs_after_bs; /* down shift after bayer scaling */
/* Origin of the real sensor data area on the internal frame at shading correction. */
unsigned int sensor_data_origin_x_bqs_on_internal;
unsigned int sensor_data_origin_y_bqs_on_internal;
IA_CSS_ENTER_PRIVATE("binary=%p, required_bds_factor=%d, stream_config=%p",
binary, required_bds_factor, stream_config);
/* Get the numerator and denominator of the required bayer downscaling factor. */
err = sh_css_bds_factor_get_numerator_denominator(required_bds_factor, &bds_num, &bds_den);
if (err != IA_CSS_SUCCESS) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
#endif
return err;
#ifdef ISP2401
}
#endif
#ifndef ISP2401
/* Set the horizontal/vertical ratio of bayer scaling
between input area and output area. */
#else
IA_CSS_LOG("bds_num=%d, bds_den=%d", bds_num, bds_den);
/* Set the horizontal/vertical ratio of bayer scaling between input area and output area. */
#endif
bs_hor_ratio_in = bds_num;
bs_hor_ratio_out = bds_den;
bs_ver_ratio_in = bds_num;
bs_ver_ratio_out = bds_den;
#ifndef ISP2401
/* Set the left padding set by InputFormatter. (ifmtr.c) */
#else
/* Set the left padding set by InputFormatter. (ia_css_ifmtr_configure() in ifmtr.c) */
#endif
if (stream_config->left_padding == -1)
left_padding_bqs = _ISP_BQS(binary->left_padding);
else
#ifndef ISP2401
left_padding_bqs = (unsigned int)((int)ISP_VEC_NELEMS
- _ISP_BQS(stream_config->left_padding));
#else
left_padding_bqs = (unsigned int)((int)ISP_VEC_NELEMS - _ISP_BQS(stream_config->left_padding));
#endif
#ifndef ISP2401
/* Set the left padding adjusted inside the isp.
When bds_factor 2.00 is needed, some padding is added to left_padding
inside the isp, before bayer downscaling. (raw.isp.c)
(Hopefully, left_crop/left_padding/top_crop should be defined in css
appropriately, depending on bds_factor.)
*/
#else
IA_CSS_LOG("stream.left_padding=%d, binary.left_padding=%d, left_padding_bqs=%d",
stream_config->left_padding, binary->left_padding, left_padding_bqs);
/* Set the left padding adjusted inside the isp kernels.
* When the bds_factor isn't 1.00, the left padding size is adjusted inside the isp,
* before bayer downscaling. (scaled_hor_plane_index(), raw_compute_hphase() in raw.isp.c)
*/
#endif
need_bds_factor_2_00 = ((binary->info->sp.bds.supported_bds_factors &
(PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_00) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_50) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_3_00) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_00) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_50) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_5_00) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_6_00) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_8_00))) != 0);
#ifndef ISP2401
if (need_bds_factor_2_00 && binary->info->sp.pipeline.left_cropping > 0)
left_padding_adjusted_bqs = left_padding_bqs + ISP_VEC_NELEMS;
else
#else
need_bds_factor_1_50 = ((binary->info->sp.bds.supported_bds_factors &
(PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_1_50) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_25) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_3_00) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_4_50) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_6_00))) != 0);
need_bds_factor_1_25 = ((binary->info->sp.bds.supported_bds_factors &
(PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_1_25) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_2_50) |
PACK_BDS_FACTOR(SH_CSS_BDS_FACTOR_5_00))) != 0);
if (binary->info->sp.pipeline.left_cropping > 0 &&
(need_bds_factor_2_00 || need_bds_factor_1_50 || need_bds_factor_1_25)) {
/*
* downscale 2.0 -> first_vec_adjusted_bqs = 128
* downscale 1.5 -> first_vec_adjusted_bqs = 96
* downscale 1.25 -> first_vec_adjusted_bqs = 80
*/
unsigned int first_vec_adjusted_bqs
= ISP_VEC_NELEMS * bs_hor_ratio_in / bs_hor_ratio_out;
left_padding_adjusted_bqs = first_vec_adjusted_bqs
- _ISP_BQS(binary->info->sp.pipeline.left_cropping);
} else
#endif
left_padding_adjusted_bqs = left_padding_bqs;
#ifndef ISP2401
/* Currently, the bad pixel caused by filters before bayer scaling
is NOT considered, because the bad pixel is subtle.
When some large filter is used in the future,
we need to consider the bad pixel.
Currently, when bds_factor isn't 1.00, 3x3 anti-alias filter is applied
to each color plane(Gr/R/B/Gb) before bayer downscaling.
This filter moves each color plane to right/bottom directions
by 1 pixel at the most, depending on downscaling factor.
*/
bad_bqs_on_left_before_bs = 0;
bad_bqs_on_top_before_bs = 0;
#else
IA_CSS_LOG("supported_bds_factors=%d, need_bds_factor:2_00=%d, 1_50=%d, 1_25=%d",
binary->info->sp.bds.supported_bds_factors,
need_bds_factor_2_00, need_bds_factor_1_50, need_bds_factor_1_25);
IA_CSS_LOG("left_cropping=%d, left_padding_adjusted_bqs=%d",
binary->info->sp.pipeline.left_cropping, left_padding_adjusted_bqs);
/* Set the top padding padded inside the isp kernel for bayer downscaling binaries.
* When the bds_factor isn't 1.00, the top padding is padded inside the isp
* before bayer downscaling, because the top cropping size (input margin) is not enough.
* (calculate_input_line(), raw_compute_vphase(), dma_read_raw() in raw.isp.c)
* NOTE: In dma_read_raw(), the factor passed to raw_compute_vphase() is got by get_bds_factor_for_dma_read().
* This factor is BDS_FPVAL_100/BDS_FPVAL_125/BDS_FPVAL_150/BDS_FPVAL_200.
*/
top_padding_bqs = 0;
if (binary->info->sp.pipeline.top_cropping > 0 &&
(required_bds_factor == SH_CSS_BDS_FACTOR_1_25 ||
required_bds_factor == SH_CSS_BDS_FACTOR_1_50 ||
required_bds_factor == SH_CSS_BDS_FACTOR_2_00)) {
/* Calculation from calculate_input_line() and raw_compute_vphase() in raw.isp.c. */
int top_cropping_bqs = _ISP_BQS(binary->info->sp.pipeline.top_cropping);
/* top cropping (in bqs) */
int factor = bds_num * bds_frac_acc / bds_den; /* downscaling factor by fixed-point */
int top_padding_bqsxfrac_acc = (top_cropping_bqs * factor - top_cropping_bqs * bds_frac_acc)
+ (2 * bds_frac_acc - factor); /* top padding by fixed-point (in bqs) */
top_padding_bqs = (unsigned int)((top_padding_bqsxfrac_acc + bds_frac_acc/2 - 1) / bds_frac_acc);
}
IA_CSS_LOG("top_cropping=%d, top_padding_bqs=%d", binary->info->sp.pipeline.top_cropping, top_padding_bqs);
/* Set the right/down shift amount caused by filters applied BEFORE bayer scaling,
* which scaling is applied BEFORE shading corrertion.
*
* When the bds_factor isn't 1.00, 3x3 anti-alias filter is applied to each color plane(Gr/R/B/Gb)
* before bayer downscaling.
* This filter shifts each color plane (Gr/R/B/Gb) to right/down directions by 1 pixel.
*/
right_shift_bqs_before_bs = 0;
down_shift_bqs_before_bs = 0;
#endif
#ifndef ISP2401
/* Currently, the bad pixel caused by filters after bayer scaling
is NOT considered, because the bad pixel is subtle.
When some large filter is used in the future,
we need to consider the bad pixel.
Currently, when DPC&BNR is processed between bayer scaling and
shading correction, DPC&BNR moves each color plane to
right/bottom directions by 1 pixel.
*/
bad_bqs_on_left_after_bs = 0;
bad_bqs_on_top_after_bs = 0;
#else
if (need_bds_factor_2_00 || need_bds_factor_1_50 || need_bds_factor_1_25) {
right_shift_bqs_before_bs = 1;
down_shift_bqs_before_bs = 1;
}
IA_CSS_LOG("right_shift_bqs_before_bs=%d, down_shift_bqs_before_bs=%d",
right_shift_bqs_before_bs, down_shift_bqs_before_bs);
/* Set the right/down shift amount caused by filters applied AFTER bayer scaling,
* which scaling is applied BEFORE shading corrertion.
*
* When DPC&BNR is processed between bayer scaling and shading correction,
* DPC&BNR moves each color plane (Gr/R/B/Gb) to right/down directions by 1 pixel.
*/
right_shift_bqs_after_bs = 0;
down_shift_bqs_after_bs = 0;
#endif
#ifndef ISP2401
/* Calculate the origin of bayer (real sensor data area)
located on the shading table during the shading correction. */
res->sc_bayer_origin_x_bqs_on_shading_table
= ((left_padding_adjusted_bqs + bad_bqs_on_left_before_bs)
* bs_hor_ratio_out + bs_hor_ratio_in/2) / bs_hor_ratio_in
+ bad_bqs_on_left_after_bs;
/* "+ bs_hor_ratio_in/2": rounding for division by bs_hor_ratio_in */
res->sc_bayer_origin_y_bqs_on_shading_table
= (bad_bqs_on_top_before_bs
* bs_ver_ratio_out + bs_ver_ratio_in/2) / bs_ver_ratio_in
+ bad_bqs_on_top_after_bs;
/* "+ bs_ver_ratio_in/2": rounding for division by bs_ver_ratio_in */
res->bayer_scale_hor_ratio_in = (uint32_t)bs_hor_ratio_in;
res->bayer_scale_hor_ratio_out = (uint32_t)bs_hor_ratio_out;
res->bayer_scale_ver_ratio_in = (uint32_t)bs_ver_ratio_in;
res->bayer_scale_ver_ratio_out = (uint32_t)bs_ver_ratio_out;
#else
if (binary->info->mem_offsets.offsets.param->dmem.dp.size != 0) { /* if DPC&BNR is enabled in the binary */
right_shift_bqs_after_bs = 1;
down_shift_bqs_after_bs = 1;
}
IA_CSS_LOG("right_shift_bqs_after_bs=%d, down_shift_bqs_after_bs=%d",
right_shift_bqs_after_bs, down_shift_bqs_after_bs);
/* Set the origin of the sensor data area on the internal frame at shading correction. */
{
unsigned int bs_frac = bds_frac_acc; /* scaling factor 1.0 in fixed point */
unsigned int bs_out, bs_in; /* scaling ratio in fixed point */
bs_out = bs_hor_ratio_out * bs_frac;
bs_in = bs_hor_ratio_in * bs_frac;
sensor_data_origin_x_bqs_on_internal
= ((left_padding_adjusted_bqs + right_shift_bqs_before_bs) * bs_out + bs_in/2) / bs_in
+ right_shift_bqs_after_bs; /* "+ bs_in/2": rounding */
bs_out = bs_ver_ratio_out * bs_frac;
bs_in = bs_ver_ratio_in * bs_frac;
sensor_data_origin_y_bqs_on_internal
= ((top_padding_bqs + down_shift_bqs_before_bs) * bs_out + bs_in/2) / bs_in
+ down_shift_bqs_after_bs; /* "+ bs_in/2": rounding */
}
scr->bayer_scale_hor_ratio_in = (uint32_t)bs_hor_ratio_in;
scr->bayer_scale_hor_ratio_out = (uint32_t)bs_hor_ratio_out;
scr->bayer_scale_ver_ratio_in = (uint32_t)bs_ver_ratio_in;
scr->bayer_scale_ver_ratio_out = (uint32_t)bs_ver_ratio_out;
scr->sensor_data_origin_x_bqs_on_internal = (uint32_t)sensor_data_origin_x_bqs_on_internal;
scr->sensor_data_origin_y_bqs_on_internal = (uint32_t)sensor_data_origin_y_bqs_on_internal;
IA_CSS_LOG("sc_requirements: %d, %d, %d, %d, %d, %d",
scr->bayer_scale_hor_ratio_in, scr->bayer_scale_hor_ratio_out,
scr->bayer_scale_ver_ratio_in, scr->bayer_scale_ver_ratio_out,
scr->sensor_data_origin_x_bqs_on_internal, scr->sensor_data_origin_y_bqs_on_internal);
#endif
#ifdef ISP2401
IA_CSS_LEAVE_ERR_PRIVATE(err);
#endif
return err;
}
/* Get the shading information of Shading Correction Type 1. */
static enum ia_css_err
ia_css_binary_get_shading_info_type_1(const struct ia_css_binary *binary, /* [in] */
unsigned int required_bds_factor, /* [in] */
const struct ia_css_stream_config *stream_config, /* [in] */
#ifndef ISP2401
struct ia_css_shading_info *info) /* [out] */
#else
struct ia_css_shading_info *shading_info, /* [out] */
struct ia_css_pipe_config *pipe_config) /* [out] */
#endif
{
enum ia_css_err err;
#ifndef ISP2401
struct sh_css_shading_table_bayer_origin_compute_results res;
#else
struct sh_css_binary_sc_requirements scr;
struct ia_css_shading_info default_shading_info_type_1 = DEFAULT_SHADING_INFO_TYPE_1;
#endif
#ifndef ISP2401
assert(binary != NULL);
assert(info != NULL);
#else
uint32_t in_width_bqs, in_height_bqs, internal_width_bqs, internal_height_bqs;
uint32_t num_hor_grids, num_ver_grids, bqs_per_grid_cell, tbl_width_bqs, tbl_height_bqs;
uint32_t sensor_org_x_bqs_on_internal, sensor_org_y_bqs_on_internal, sensor_width_bqs, sensor_height_bqs;
uint32_t sensor_center_x_bqs_on_internal, sensor_center_y_bqs_on_internal;
uint32_t left, right, upper, lower;
uint32_t adjust_left, adjust_right, adjust_upper, adjust_lower, adjust_width_bqs, adjust_height_bqs;
uint32_t internal_org_x_bqs_on_tbl, internal_org_y_bqs_on_tbl;
uint32_t sensor_org_x_bqs_on_tbl, sensor_org_y_bqs_on_tbl;
#endif
#ifndef ISP2401
info->type = IA_CSS_SHADING_CORRECTION_TYPE_1;
#else
assert(binary != NULL);
assert(stream_config != NULL);
assert(shading_info != NULL);
assert(pipe_config != NULL);
#endif
#ifndef ISP2401
info->info.type_1.enable = binary->info->sp.enable.sc;
info->info.type_1.num_hor_grids = binary->sctbl_width_per_color;
info->info.type_1.num_ver_grids = binary->sctbl_height;
info->info.type_1.bqs_per_grid_cell = (1 << binary->deci_factor_log2);
#else
IA_CSS_ENTER_PRIVATE("binary=%p, required_bds_factor=%d, stream_config=%p",
binary, required_bds_factor, stream_config);
#endif
/* Initialize by default values. */
#ifndef ISP2401
info->info.type_1.bayer_scale_hor_ratio_in = 1;
info->info.type_1.bayer_scale_hor_ratio_out = 1;
info->info.type_1.bayer_scale_ver_ratio_in = 1;
info->info.type_1.bayer_scale_ver_ratio_out = 1;
info->info.type_1.sc_bayer_origin_x_bqs_on_shading_table = 0;
info->info.type_1.sc_bayer_origin_y_bqs_on_shading_table = 0;
err = ia_css_binary_compute_shading_table_bayer_origin(
binary,
required_bds_factor,
stream_config,
&res);
if (err != IA_CSS_SUCCESS)
#else
*shading_info = default_shading_info_type_1;
err = sh_css_binary_get_sc_requirements(binary, required_bds_factor, stream_config, &scr);
if (err != IA_CSS_SUCCESS) {
IA_CSS_LEAVE_ERR_PRIVATE(err);
#endif
return err;
#ifdef ISP2401
}
IA_CSS_LOG("binary: id=%d, sctbl=%dx%d, deci=%d",
binary->info->sp.id, binary->sctbl_width_per_color, binary->sctbl_height, binary->deci_factor_log2);
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",
binary->in_frame_info.res.width, binary->in_frame_info.res.height, binary->in_frame_info.padded_width,
binary->internal_frame_info.res.width, binary->internal_frame_info.res.height,
binary->internal_frame_info.padded_width,
binary->out_frame_info[0].res.width, binary->out_frame_info[0].res.height,
binary->out_frame_info[0].padded_width);
/* Set the input size from sensor, which includes left/top crop size. */
in_width_bqs = _ISP_BQS(binary->in_frame_info.res.width);
in_height_bqs = _ISP_BQS(binary->in_frame_info.res.height);
/* Frame size internally used in ISP, including sensor data and padding.
* This is the frame size, to which the shading correction is applied.
*/
internal_width_bqs = _ISP_BQS(binary->internal_frame_info.res.width);
internal_height_bqs = _ISP_BQS(binary->internal_frame_info.res.height);
/* Shading table. */
num_hor_grids = binary->sctbl_width_per_color;
num_ver_grids = binary->sctbl_height;
bqs_per_grid_cell = (1 << binary->deci_factor_log2);
tbl_width_bqs = (num_hor_grids - 1) * bqs_per_grid_cell;
tbl_height_bqs = (num_ver_grids - 1) * bqs_per_grid_cell;
#endif
#ifndef ISP2401
info->info.type_1.bayer_scale_hor_ratio_in = res.bayer_scale_hor_ratio_in;
info->info.type_1.bayer_scale_hor_ratio_out = res.bayer_scale_hor_ratio_out;
info->info.type_1.bayer_scale_ver_ratio_in = res.bayer_scale_ver_ratio_in;
info->info.type_1.bayer_scale_ver_ratio_out = res.bayer_scale_ver_ratio_out;
info->info.type_1.sc_bayer_origin_x_bqs_on_shading_table = res.sc_bayer_origin_x_bqs_on_shading_table;
info->info.type_1.sc_bayer_origin_y_bqs_on_shading_table = res.sc_bayer_origin_y_bqs_on_shading_table;
#else
IA_CSS_LOG("tbl_width_bqs=%d, tbl_height_bqs=%d", tbl_width_bqs, tbl_height_bqs);
#endif
#ifdef ISP2401
/* Real sensor data area on the internal frame at shading correction.
* Filters and scaling are applied to the internal frame before shading correction, depending on the binary.
*/
sensor_org_x_bqs_on_internal = scr.sensor_data_origin_x_bqs_on_internal;
sensor_org_y_bqs_on_internal = scr.sensor_data_origin_y_bqs_on_internal;
{
unsigned int bs_frac = 8; /* scaling factor 1.0 in fixed point (8 == FRAC_ACC macro in ISP) */
unsigned int bs_out, bs_in; /* scaling ratio in fixed point */
bs_out = scr.bayer_scale_hor_ratio_out * bs_frac;
bs_in = scr.bayer_scale_hor_ratio_in * bs_frac;
sensor_width_bqs = (in_width_bqs * bs_out + bs_in/2) / bs_in; /* "+ bs_in/2": rounding */
bs_out = scr.bayer_scale_ver_ratio_out * bs_frac;
bs_in = scr.bayer_scale_ver_ratio_in * bs_frac;
sensor_height_bqs = (in_height_bqs * bs_out + bs_in/2) / bs_in; /* "+ bs_in/2": rounding */
}
/* Center of the sensor data on the internal frame at shading correction. */
sensor_center_x_bqs_on_internal = sensor_org_x_bqs_on_internal + sensor_width_bqs / 2;
sensor_center_y_bqs_on_internal = sensor_org_y_bqs_on_internal + sensor_height_bqs / 2;
/* Size of left/right/upper/lower sides of the sensor center on the internal frame. */
left = sensor_center_x_bqs_on_internal;
right = internal_width_bqs - sensor_center_x_bqs_on_internal;
upper = sensor_center_y_bqs_on_internal;
lower = internal_height_bqs - sensor_center_y_bqs_on_internal;
/* Align the size of left/right/upper/lower sides to a multiple of the grid cell size. */
adjust_left = CEIL_MUL(left, bqs_per_grid_cell);
adjust_right = CEIL_MUL(right, bqs_per_grid_cell);
adjust_upper = CEIL_MUL(upper, bqs_per_grid_cell);
adjust_lower = CEIL_MUL(lower, bqs_per_grid_cell);
/* Shading table should cover the adjusted frame size. */
adjust_width_bqs = adjust_left + adjust_right;
adjust_height_bqs = adjust_upper + adjust_lower;
IA_CSS_LOG("adjust_width_bqs=%d, adjust_height_bqs=%d", adjust_width_bqs, adjust_height_bqs);
if (adjust_width_bqs > tbl_width_bqs || adjust_height_bqs > tbl_height_bqs) {
IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
return IA_CSS_ERR_INTERNAL_ERROR;
}
/* Origin of the internal frame on the shading table. */
internal_org_x_bqs_on_tbl = adjust_left - left;
internal_org_y_bqs_on_tbl = adjust_upper - upper;
/* Origin of the real sensor data area on the shading table. */
sensor_org_x_bqs_on_tbl = internal_org_x_bqs_on_tbl + sensor_org_x_bqs_on_internal;
sensor_org_y_bqs_on_tbl = internal_org_y_bqs_on_tbl + sensor_org_y_bqs_on_internal;
/* The shading information necessary as API is stored in the shading_info. */
shading_info->info.type_1.num_hor_grids = num_hor_grids;
shading_info->info.type_1.num_ver_grids = num_ver_grids;
shading_info->info.type_1.bqs_per_grid_cell = bqs_per_grid_cell;
shading_info->info.type_1.bayer_scale_hor_ratio_in = scr.bayer_scale_hor_ratio_in;
shading_info->info.type_1.bayer_scale_hor_ratio_out = scr.bayer_scale_hor_ratio_out;
shading_info->info.type_1.bayer_scale_ver_ratio_in = scr.bayer_scale_ver_ratio_in;
shading_info->info.type_1.bayer_scale_ver_ratio_out = scr.bayer_scale_ver_ratio_out;
shading_info->info.type_1.isp_input_sensor_data_res_bqs.width = in_width_bqs;
shading_info->info.type_1.isp_input_sensor_data_res_bqs.height = in_height_bqs;
shading_info->info.type_1.sensor_data_res_bqs.width = sensor_width_bqs;
shading_info->info.type_1.sensor_data_res_bqs.height = sensor_height_bqs;
shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.x = (int32_t)sensor_org_x_bqs_on_tbl;
shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.y = (int32_t)sensor_org_y_bqs_on_tbl;
/* The shading information related to ISP (but, not necessary as API) is stored in the pipe_config. */
pipe_config->internal_frame_origin_bqs_on_sctbl.x = (int32_t)internal_org_x_bqs_on_tbl;
pipe_config->internal_frame_origin_bqs_on_sctbl.y = (int32_t)internal_org_y_bqs_on_tbl;
IA_CSS_LOG("shading_info: grids=%dx%d, cell=%d, scale=%d,%d,%d,%d, input=%dx%d, data=%dx%d, origin=(%d,%d)",
shading_info->info.type_1.num_hor_grids,
shading_info->info.type_1.num_ver_grids,
shading_info->info.type_1.bqs_per_grid_cell,
shading_info->info.type_1.bayer_scale_hor_ratio_in,
shading_info->info.type_1.bayer_scale_hor_ratio_out,
shading_info->info.type_1.bayer_scale_ver_ratio_in,
shading_info->info.type_1.bayer_scale_ver_ratio_out,
shading_info->info.type_1.isp_input_sensor_data_res_bqs.width,
shading_info->info.type_1.isp_input_sensor_data_res_bqs.height,
shading_info->info.type_1.sensor_data_res_bqs.width,
shading_info->info.type_1.sensor_data_res_bqs.height,
shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.x,
shading_info->info.type_1.sensor_data_origin_bqs_on_sctbl.y);
IA_CSS_LOG("pipe_config: origin=(%d,%d)",
pipe_config->internal_frame_origin_bqs_on_sctbl.x,
pipe_config->internal_frame_origin_bqs_on_sctbl.y);
IA_CSS_LEAVE_ERR_PRIVATE(err);
#endif
return err;
}
enum ia_css_err
ia_css_binary_get_shading_info(const struct ia_css_binary *binary, /* [in] */
enum ia_css_shading_correction_type type, /* [in] */
unsigned int required_bds_factor, /* [in] */
const struct ia_css_stream_config *stream_config, /* [in] */
#ifndef ISP2401
struct ia_css_shading_info *info) /* [out] */
#else
struct ia_css_shading_info *shading_info, /* [out] */
struct ia_css_pipe_config *pipe_config) /* [out] */
#endif
{
enum ia_css_err err;
assert(binary != NULL);
#ifndef ISP2401
assert(info != NULL);
#else
assert(shading_info != NULL);
IA_CSS_ENTER_PRIVATE("binary=%p, type=%d, required_bds_factor=%d, stream_config=%p",
binary, type, required_bds_factor, stream_config);
#endif
if (type == IA_CSS_SHADING_CORRECTION_TYPE_1)
#ifndef ISP2401
err = ia_css_binary_get_shading_info_type_1(binary, required_bds_factor, stream_config, info);
#else
err = ia_css_binary_get_shading_info_type_1(binary, required_bds_factor, stream_config,
shading_info, pipe_config);
#endif
/* Other function calls can be added here when other shading correction types will be added in the future. */
else
err = IA_CSS_ERR_NOT_SUPPORTED;
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
static void sh_css_binary_common_grid_info(const struct ia_css_binary *binary,
struct ia_css_grid_info *info)
{
assert(binary != NULL);
assert(info != NULL);
info->isp_in_width = binary->internal_frame_info.res.width;
info->isp_in_height = binary->internal_frame_info.res.height;
info->vamem_type = IA_CSS_VAMEM_TYPE_2;
}
void
ia_css_binary_dvs_grid_info(const struct ia_css_binary *binary,
struct ia_css_grid_info *info,
struct ia_css_pipe *pipe)
{
struct ia_css_dvs_grid_info *dvs_info;
(void)pipe;
assert(binary != NULL);
assert(info != NULL);
dvs_info = &info->dvs_grid.dvs_grid_info;
/* for DIS, we use a division instead of a ceil_div. If this is smaller
* than the 3a grid size, it indicates that the outer values are not
* valid for DIS.
*/
dvs_info->enable = binary->info->sp.enable.dis;
dvs_info->width = binary->dis.grid.dim.width;
dvs_info->height = binary->dis.grid.dim.height;
dvs_info->aligned_width = binary->dis.grid.pad.width;
dvs_info->aligned_height = binary->dis.grid.pad.height;
dvs_info->bqs_per_grid_cell = 1 << binary->dis.deci_factor_log2;
dvs_info->num_hor_coefs = binary->dis.coef.dim.width;
dvs_info->num_ver_coefs = binary->dis.coef.dim.height;
sh_css_binary_common_grid_info(binary, info);
}
void
ia_css_binary_dvs_stat_grid_info(
const struct ia_css_binary *binary,
struct ia_css_grid_info *info,
struct ia_css_pipe *pipe)
{
(void)pipe;
sh_css_binary_common_grid_info(binary, info);
return;
}
enum ia_css_err
ia_css_binary_3a_grid_info(const struct ia_css_binary *binary,
struct ia_css_grid_info *info,
struct ia_css_pipe *pipe)
{
struct ia_css_3a_grid_info *s3a_info;
enum ia_css_err err = IA_CSS_SUCCESS;
IA_CSS_ENTER_PRIVATE("binary=%p, info=%p, pipe=%p",
binary, info, pipe);
assert(binary != NULL);
assert(info != NULL);
s3a_info = &info->s3a_grid;
/* 3A statistics grid */
s3a_info->enable = binary->info->sp.enable.s3a;
s3a_info->width = binary->s3atbl_width;
s3a_info->height = binary->s3atbl_height;
s3a_info->aligned_width = binary->s3atbl_isp_width;
s3a_info->aligned_height = binary->s3atbl_isp_height;
s3a_info->bqs_per_grid_cell = (1 << binary->deci_factor_log2);
s3a_info->deci_factor_log2 = binary->deci_factor_log2;
s3a_info->elem_bit_depth = SH_CSS_BAYER_BITS;
s3a_info->use_dmem = binary->info->sp.s3a.s3atbl_use_dmem;
#if defined(HAS_NO_HMEM)
s3a_info->has_histogram = 1;
#else
s3a_info->has_histogram = 0;
#endif
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
static void
binary_init_pc_histogram(struct sh_css_pc_histogram *histo)
{
assert(histo != NULL);
histo->length = 0;
histo->run = NULL;
histo->stall = NULL;
}
static void
binary_init_metrics(struct sh_css_binary_metrics *metrics,
const struct ia_css_binary_info *info)
{
assert(metrics != NULL);
assert(info != NULL);
metrics->mode = info->pipeline.mode;
metrics->id = info->id;
metrics->next = NULL;
binary_init_pc_histogram(&metrics->isp_histogram);
binary_init_pc_histogram(&metrics->sp_histogram);
}
/* move to host part of output module */
static bool
binary_supports_output_format(const struct ia_css_binary_xinfo *info,
enum ia_css_frame_format format)
{
int i;
assert(info != NULL);
for (i = 0; i < info->num_output_formats; i++) {
if (info->output_formats[i] == format)
return true;
}
return false;
}
#ifdef ISP2401
static bool
binary_supports_input_format(const struct ia_css_binary_xinfo *info,
enum ia_css_stream_format format)
{
assert(info != NULL);
(void)format;
return true;
}
#endif
static bool
binary_supports_vf_format(const struct ia_css_binary_xinfo *info,
enum ia_css_frame_format format)
{
int i;
assert(info != NULL);
for (i = 0; i < info->num_vf_formats; i++) {
if (info->vf_formats[i] == format)
return true;
}
return false;
}
/* move to host part of bds module */
static bool
supports_bds_factor(uint32_t supported_factors,
uint32_t bds_factor)
{
return ((supported_factors & PACK_BDS_FACTOR(bds_factor)) != 0);
}
static enum ia_css_err
binary_init_info(struct ia_css_binary_xinfo *info, unsigned int i,
bool *binary_found)
{
const unsigned char *blob = sh_css_blob_info[i].blob;
unsigned size = sh_css_blob_info[i].header.blob.size;
if ((info == NULL) || (binary_found == NULL))
return IA_CSS_ERR_INVALID_ARGUMENTS;
*info = sh_css_blob_info[i].header.info.isp;
*binary_found = blob != NULL;
info->blob_index = i;
/* we don't have this binary, skip it */
if (!size)
return IA_CSS_SUCCESS;
info->xmem_addr = sh_css_load_blob(blob, size);
if (!info->xmem_addr)
return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
return IA_CSS_SUCCESS;
}
/* When binaries are put at the beginning, they will only
* be selected if no other primary matches.
*/
enum ia_css_err
ia_css_binary_init_infos(void)
{
unsigned int i;
unsigned int num_of_isp_binaries = sh_css_num_binaries - NUM_OF_SPS - NUM_OF_BLS;
if (num_of_isp_binaries == 0)
return IA_CSS_SUCCESS;
all_binaries = sh_css_malloc(num_of_isp_binaries *
sizeof(*all_binaries));
if (all_binaries == NULL)
return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
for (i = 0; i < num_of_isp_binaries; i++) {
enum ia_css_err ret;
struct ia_css_binary_xinfo *binary = &all_binaries[i];
bool binary_found;
ret = binary_init_info(binary, i, &binary_found);
if (ret != IA_CSS_SUCCESS)
return ret;
if (!binary_found)
continue;
/* Prepend new binary information */
binary->next = binary_infos[binary->sp.pipeline.mode];
binary_infos[binary->sp.pipeline.mode] = binary;
binary->blob = &sh_css_blob_info[i];
binary->mem_offsets = sh_css_blob_info[i].mem_offsets;
}
return IA_CSS_SUCCESS;
}
enum ia_css_err
ia_css_binary_uninit(void)
{
unsigned int i;
struct ia_css_binary_xinfo *b;
for (i = 0; i < IA_CSS_BINARY_NUM_MODES; i++) {
for (b = binary_infos[i]; b; b = b->next) {
if (b->xmem_addr)
hmm_free(b->xmem_addr);
b->xmem_addr = mmgr_NULL;
}
binary_infos[i] = NULL;
}
sh_css_free(all_binaries);
return IA_CSS_SUCCESS;
}
/** @brief Compute decimation factor for 3A statistics and shading correction.
*
* @param[in] width Frame width in pixels.
* @param[in] height Frame height in pixels.
* @return Log2 of decimation factor (= grid cell size) in bayer quads.
*/
static int
binary_grid_deci_factor_log2(int width, int height)
{
/* 3A/Shading decimation factor spcification (at August 2008)
* ------------------------------------------------------------------
* [Image Width (BQ)] [Decimation Factor (BQ)] [Resulting grid cells]
#ifndef ISP2401
* 1280 ?c 32 40 ?c
* 640 ?c 1279 16 40 ?c 80
* ?c 639 8 ?c 80
#else
* from 1280 32 from 40
* from 640 to 1279 16 from 40 to 80
* to 639 8 to 80
#endif
* ------------------------------------------------------------------
*/
/* Maximum and minimum decimation factor by the specification */
#define MAX_SPEC_DECI_FACT_LOG2 5
#define MIN_SPEC_DECI_FACT_LOG2 3
/* the smallest frame width in bayer quads when decimation factor (log2) is 5 or 4, by the specification */
#define DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ 1280
#define DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ 640
int smallest_factor; /* the smallest factor (log2) where the number of cells does not exceed the limitation */
int spec_factor; /* the factor (log2) which satisfies the specification */
/* Currently supported maximum width and height are 5120(=80*64) and 3840(=60*64). */
assert(ISP_BQ_GRID_WIDTH(width, MAX_SPEC_DECI_FACT_LOG2) <= SH_CSS_MAX_BQ_GRID_WIDTH);
assert(ISP_BQ_GRID_HEIGHT(height, MAX_SPEC_DECI_FACT_LOG2) <= SH_CSS_MAX_BQ_GRID_HEIGHT);
/* Compute the smallest factor. */
smallest_factor = MAX_SPEC_DECI_FACT_LOG2;
while (ISP_BQ_GRID_WIDTH(width, smallest_factor - 1) <= SH_CSS_MAX_BQ_GRID_WIDTH &&
ISP_BQ_GRID_HEIGHT(height, smallest_factor - 1) <= SH_CSS_MAX_BQ_GRID_HEIGHT
&& smallest_factor > MIN_SPEC_DECI_FACT_LOG2)
smallest_factor--;
/* Get the factor by the specification. */
if (_ISP_BQS(width) >= DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ)
spec_factor = 5;
else if (_ISP_BQS(width) >= DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ)
spec_factor = 4;
else
spec_factor = 3;
/* If smallest_factor is smaller than or equal to spec_factor, choose spec_factor to follow the specification.
If smallest_factor is larger than spec_factor, choose smallest_factor.
ex. width=2560, height=1920
smallest_factor=4, spec_factor=5
smallest_factor < spec_factor -> return spec_factor
ex. width=300, height=3000
smallest_factor=5, spec_factor=3
smallest_factor > spec_factor -> return smallest_factor
*/
return max(smallest_factor, spec_factor);
#undef MAX_SPEC_DECI_FACT_LOG2
#undef MIN_SPEC_DECI_FACT_LOG2
#undef DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ
#undef DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ
}
static int
binary_in_frame_padded_width(int in_frame_width,
int isp_internal_width,
int dvs_env_width,
int stream_config_left_padding,
int left_cropping,
bool need_scaling)
{
int rval;
int nr_of_left_paddings; /* number of paddings pixels on the left of an image line */
#if defined(USE_INPUT_SYSTEM_VERSION_2401)
/* the output image line of Input System 2401 does not have the left paddings */
nr_of_left_paddings = 0;
#else
/* in other cases, the left padding pixels are always 128 */
nr_of_left_paddings = 2*ISP_VEC_NELEMS;
#endif
if (need_scaling) {
/* In SDV use-case, we need to match left-padding of
* primary and the video binary. */
if (stream_config_left_padding != -1) {
/* Different than before, we do left&right padding. */
rval =
CEIL_MUL(in_frame_width + nr_of_left_paddings,
2*ISP_VEC_NELEMS);
} else {
/* Different than before, we do left&right padding. */
in_frame_width += dvs_env_width;
rval =
CEIL_MUL(in_frame_width +
(left_cropping ? nr_of_left_paddings : 0),
2*ISP_VEC_NELEMS);
}
} else {
rval = isp_internal_width;
}
return rval;
}
enum ia_css_err
ia_css_binary_fill_info(const struct ia_css_binary_xinfo *xinfo,
bool online,
bool two_ppc,
enum ia_css_stream_format stream_format,
const struct ia_css_frame_info *in_info, /* can be NULL */
const struct ia_css_frame_info *bds_out_info, /* can be NULL */
const struct ia_css_frame_info *out_info[], /* can be NULL */
const struct ia_css_frame_info *vf_info, /* can be NULL */
struct ia_css_binary *binary,
struct ia_css_resolution *dvs_env,
int stream_config_left_padding,
bool accelerator)
{
const struct ia_css_binary_info *info = &xinfo->sp;
unsigned int dvs_env_width = 0,
dvs_env_height = 0,
vf_log_ds = 0,
s3a_log_deci = 0,
bits_per_pixel = 0,
/* Resolution at SC/3A/DIS kernel. */
sc_3a_dis_width = 0,
/* Resolution at SC/3A/DIS kernel. */
sc_3a_dis_padded_width = 0,
/* Resolution at SC/3A/DIS kernel. */
sc_3a_dis_height = 0,
isp_internal_width = 0,
isp_internal_height = 0,
s3a_isp_width = 0;
bool need_scaling = false;
struct ia_css_resolution binary_dvs_env, internal_res;
enum ia_css_err err;
unsigned int i;
const struct ia_css_frame_info *bin_out_info = NULL;
assert(info != NULL);
assert(binary != NULL);
binary->info = xinfo;
if (!accelerator) {
/* binary->css_params has been filled by accelerator itself. */
err = ia_css_isp_param_allocate_isp_parameters(
&binary->mem_params, &binary->css_params,
&info->mem_initializers);
if (err != IA_CSS_SUCCESS) {
return err;
}
}
for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
if (out_info[i] && (out_info[i]->res.width != 0)) {
bin_out_info = out_info[i];
break;
}
}
if (in_info != NULL && bin_out_info != NULL) {
need_scaling = (in_info->res.width != bin_out_info->res.width) ||
(in_info->res.height != bin_out_info->res.height);
}
/* binary_dvs_env has to be equal or larger than SH_CSS_MIN_DVS_ENVELOPE */
binary_dvs_env.width = 0;
binary_dvs_env.height = 0;
ia_css_binary_dvs_env(info, dvs_env, &binary_dvs_env);
dvs_env_width = binary_dvs_env.width;
dvs_env_height = binary_dvs_env.height;
binary->dvs_envelope.width = dvs_env_width;
binary->dvs_envelope.height = dvs_env_height;
/* internal resolution calculation */
internal_res.width = 0;
internal_res.height = 0;
ia_css_binary_internal_res(in_info, bds_out_info, bin_out_info, dvs_env,
info, &internal_res);
isp_internal_width = internal_res.width;
isp_internal_height = internal_res.height;
/* internal frame info */
if (bin_out_info != NULL) /* { */
binary->internal_frame_info.format = bin_out_info->format;
/* } */
binary->internal_frame_info.res.width = isp_internal_width;
binary->internal_frame_info.padded_width = CEIL_MUL(isp_internal_width, 2*ISP_VEC_NELEMS);
binary->internal_frame_info.res.height = isp_internal_height;
binary->internal_frame_info.raw_bit_depth = bits_per_pixel;
if (in_info != NULL) {
binary->effective_in_frame_res.width = in_info->res.width;
binary->effective_in_frame_res.height = in_info->res.height;
bits_per_pixel = in_info->raw_bit_depth;
/* input info */
binary->in_frame_info.res.width = in_info->res.width + info->pipeline.left_cropping;
binary->in_frame_info.res.height = in_info->res.height + info->pipeline.top_cropping;
binary->in_frame_info.res.width += dvs_env_width;
binary->in_frame_info.res.height += dvs_env_height;
binary->in_frame_info.padded_width =
binary_in_frame_padded_width(in_info->res.width,
isp_internal_width,
dvs_env_width,
stream_config_left_padding,
info->pipeline.left_cropping,
need_scaling);
binary->in_frame_info.format = in_info->format;
binary->in_frame_info.raw_bayer_order = in_info->raw_bayer_order;
binary->in_frame_info.crop_info = in_info->crop_info;
}
if (online) {
bits_per_pixel = ia_css_util_input_format_bpp(
stream_format, two_ppc);
}
binary->in_frame_info.raw_bit_depth = bits_per_pixel;
for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
if (out_info[i] != NULL) {
binary->out_frame_info[i].res.width = out_info[i]->res.width;
binary->out_frame_info[i].res.height = out_info[i]->res.height;
binary->out_frame_info[i].padded_width = out_info[i]->padded_width;
if (info->pipeline.mode == IA_CSS_BINARY_MODE_COPY) {
binary->out_frame_info[i].raw_bit_depth = bits_per_pixel;
} else {
/* Only relevant for RAW format.
* At the moment, all outputs are raw, 16 bit per pixel, except for copy.
* To do this cleanly, the binary should specify in its info
* the bit depth per output channel.
*/
binary->out_frame_info[i].raw_bit_depth = 16;
}
binary->out_frame_info[i].format = out_info[i]->format;
}
}
if (vf_info && (vf_info->res.width != 0)) {
err = ia_css_vf_configure(binary, bin_out_info, (struct ia_css_frame_info *)vf_info, &vf_log_ds);
if (err != IA_CSS_SUCCESS) {
if (!accelerator) {
ia_css_isp_param_destroy_isp_parameters(
&binary->mem_params,
&binary->css_params);
}
return err;
}
}
binary->vf_downscale_log2 = vf_log_ds;
binary->online = online;
binary->input_format = stream_format;
/* viewfinder output info */
if ((vf_info != NULL) && (vf_info->res.width != 0)) {
unsigned int vf_out_vecs, vf_out_width, vf_out_height;
binary->vf_frame_info.format = vf_info->format;
if (bin_out_info == NULL)
return IA_CSS_ERR_INTERNAL_ERROR;
vf_out_vecs = __ISP_VF_OUTPUT_WIDTH_VECS(bin_out_info->padded_width,
vf_log_ds);
vf_out_width = _ISP_VF_OUTPUT_WIDTH(vf_out_vecs);
vf_out_height = _ISP_VF_OUTPUT_HEIGHT(bin_out_info->res.height,
vf_log_ds);
/* For preview mode, output pin is used instead of vf. */
if (info->pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW) {
binary->out_frame_info[0].res.width =
(bin_out_info->res.width >> vf_log_ds);
binary->out_frame_info[0].padded_width = vf_out_width;
binary->out_frame_info[0].res.height = vf_out_height;
binary->vf_frame_info.res.width = 0;
binary->vf_frame_info.padded_width = 0;
binary->vf_frame_info.res.height = 0;
} else {
/* we also store the raw downscaled width. This is
* used for digital zoom in preview to zoom only on
* the width that we actually want to keep, not on
* the aligned width. */
binary->vf_frame_info.res.width =
(bin_out_info->res.width >> vf_log_ds);
binary->vf_frame_info.padded_width = vf_out_width;
binary->vf_frame_info.res.height = vf_out_height;
}
} else {
binary->vf_frame_info.res.width = 0;
binary->vf_frame_info.padded_width = 0;
binary->vf_frame_info.res.height = 0;
}
if (info->enable.ca_gdc) {
binary->morph_tbl_width =
_ISP_MORPH_TABLE_WIDTH(isp_internal_width);
binary->morph_tbl_aligned_width =
_ISP_MORPH_TABLE_ALIGNED_WIDTH(isp_internal_width);
binary->morph_tbl_height =
_ISP_MORPH_TABLE_HEIGHT(isp_internal_height);
} else {
binary->morph_tbl_width = 0;
binary->morph_tbl_aligned_width = 0;
binary->morph_tbl_height = 0;
}
sc_3a_dis_width = binary->in_frame_info.res.width;
sc_3a_dis_padded_width = binary->in_frame_info.padded_width;
sc_3a_dis_height = binary->in_frame_info.res.height;
if (bds_out_info != NULL && in_info != NULL &&
bds_out_info->res.width != in_info->res.width) {
/* TODO: Next, "internal_frame_info" should be derived from
* bds_out. So this part will change once it is in place! */
sc_3a_dis_width = bds_out_info->res.width + info->pipeline.left_cropping;
sc_3a_dis_padded_width = isp_internal_width;
sc_3a_dis_height = isp_internal_height;
}
s3a_isp_width = _ISP_S3A_ELEMS_ISP_WIDTH(sc_3a_dis_padded_width,
info->pipeline.left_cropping);
if (info->s3a.fixed_s3a_deci_log) {
s3a_log_deci = info->s3a.fixed_s3a_deci_log;
} else {
s3a_log_deci = binary_grid_deci_factor_log2(s3a_isp_width,
sc_3a_dis_height);
}
binary->deci_factor_log2 = s3a_log_deci;
if (info->enable.s3a) {
binary->s3atbl_width =
_ISP_S3ATBL_WIDTH(sc_3a_dis_width,
s3a_log_deci);
binary->s3atbl_height =
_ISP_S3ATBL_HEIGHT(sc_3a_dis_height,
s3a_log_deci);
binary->s3atbl_isp_width =
_ISP_S3ATBL_ISP_WIDTH(s3a_isp_width,
s3a_log_deci);
binary->s3atbl_isp_height =
_ISP_S3ATBL_ISP_HEIGHT(sc_3a_dis_height,
s3a_log_deci);
} else {
binary->s3atbl_width = 0;
binary->s3atbl_height = 0;
binary->s3atbl_isp_width = 0;
binary->s3atbl_isp_height = 0;
}
if (info->enable.sc) {
binary->sctbl_width_per_color =
#ifndef ISP2401
_ISP_SCTBL_WIDTH_PER_COLOR(sc_3a_dis_padded_width,
s3a_log_deci);
#else
_ISP_SCTBL_WIDTH_PER_COLOR(isp_internal_width, s3a_log_deci);
#endif
binary->sctbl_aligned_width_per_color =
SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR;
binary->sctbl_height =
#ifndef ISP2401
_ISP_SCTBL_HEIGHT(sc_3a_dis_height, s3a_log_deci);
#else
_ISP_SCTBL_HEIGHT(isp_internal_height, s3a_log_deci);
binary->sctbl_legacy_width_per_color =
_ISP_SCTBL_LEGACY_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci);
binary->sctbl_legacy_height =
_ISP_SCTBL_LEGACY_HEIGHT(sc_3a_dis_height, s3a_log_deci);
#endif
} else {
binary->sctbl_width_per_color = 0;
binary->sctbl_aligned_width_per_color = 0;
binary->sctbl_height = 0;
#ifdef ISP2401
binary->sctbl_legacy_width_per_color = 0;
binary->sctbl_legacy_height = 0;
#endif
}
ia_css_sdis_init_info(&binary->dis,
sc_3a_dis_width,
sc_3a_dis_padded_width,
sc_3a_dis_height,
info->pipeline.isp_pipe_version,
info->enable.dis);
if (info->pipeline.left_cropping)
binary->left_padding = 2 * ISP_VEC_NELEMS - info->pipeline.left_cropping;
else
binary->left_padding = 0;
return IA_CSS_SUCCESS;
}
enum ia_css_err
ia_css_binary_find(struct ia_css_binary_descr *descr,
struct ia_css_binary *binary)
{
int mode;
bool online;
bool two_ppc;
enum ia_css_stream_format stream_format;
const struct ia_css_frame_info *req_in_info,
*req_bds_out_info,
*req_out_info[IA_CSS_BINARY_MAX_OUTPUT_PORTS],
*req_bin_out_info = NULL,
*req_vf_info;
struct ia_css_binary_xinfo *xcandidate;
#ifndef ISP2401
bool need_ds, need_dz, need_dvs, need_xnr, need_dpc;
#else
bool need_ds, need_dz, need_dvs, need_xnr, need_dpc, need_tnr;
#endif
bool striped;
bool enable_yuv_ds;
bool enable_high_speed;
bool enable_dvs_6axis;
bool enable_reduced_pipe;
bool enable_capture_pp_bli;
#ifdef ISP2401
bool enable_luma_only;
#endif
enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
bool continuous;
unsigned int isp_pipe_version;
struct ia_css_resolution dvs_env, internal_res;
unsigned int i;
assert(descr != NULL);
/* MW: used after an error check, may accept NULL, but doubtfull */
assert(binary != NULL);
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() enter: descr=%p, (mode=%d), binary=%p\n",
descr, descr->mode,
binary);
mode = descr->mode;
online = descr->online;
two_ppc = descr->two_ppc;
stream_format = descr->stream_format;
req_in_info = descr->in_info;
req_bds_out_info = descr->bds_out_info;
for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) {
req_out_info[i] = descr->out_info[i];
if (req_out_info[i] && (req_out_info[i]->res.width != 0))
req_bin_out_info = req_out_info[i];
}
if (req_bin_out_info == NULL)
return IA_CSS_ERR_INTERNAL_ERROR;
#ifndef ISP2401
req_vf_info = descr->vf_info;
#else
if ((descr->vf_info != NULL) && (descr->vf_info->res.width == 0))
/* width==0 means that there is no vf pin (e.g. in SkyCam preview case) */
req_vf_info = NULL;
else
req_vf_info = descr->vf_info;
#endif
need_xnr = descr->enable_xnr;
need_ds = descr->enable_fractional_ds;
need_dz = false;
need_dvs = false;
need_dpc = descr->enable_dpc;
#ifdef ISP2401
need_tnr = descr->enable_tnr;
#endif
enable_yuv_ds = descr->enable_yuv_ds;
enable_high_speed = descr->enable_high_speed;
enable_dvs_6axis = descr->enable_dvs_6axis;
enable_reduced_pipe = descr->enable_reduced_pipe;
enable_capture_pp_bli = descr->enable_capture_pp_bli;
#ifdef ISP2401
enable_luma_only = descr->enable_luma_only;
#endif
continuous = descr->continuous;
striped = descr->striped;
isp_pipe_version = descr->isp_pipe_version;
dvs_env.width = 0;
dvs_env.height = 0;
internal_res.width = 0;
internal_res.height = 0;
if (mode == IA_CSS_BINARY_MODE_VIDEO) {
dvs_env = descr->dvs_env;
need_dz = descr->enable_dz;
/* Video is the only mode that has a nodz variant. */
need_dvs = dvs_env.width || dvs_env.height;
}
/* print a map of the binary file */
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "BINARY INFO:\n");
for (i = 0; i < IA_CSS_BINARY_NUM_MODES; i++) {
xcandidate = binary_infos[i];
if (xcandidate) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%d:\n", i);
while (xcandidate) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, " Name:%s Type:%d Cont:%d\n",
xcandidate->blob->name, xcandidate->type,
xcandidate->sp.enable.continuous);
xcandidate = xcandidate->next;
}
}
}
/* printf("sh_css_binary_find: pipe version %d\n", isp_pipe_version); */
for (xcandidate = binary_infos[mode]; xcandidate;
xcandidate = xcandidate->next) {
struct ia_css_binary_info *candidate = &xcandidate->sp;
/* printf("sh_css_binary_find: evaluating candidate:
* %d\n",candidate->id); */
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() candidate = %p, mode = %d ID = %d\n",
candidate, candidate->pipeline.mode, candidate->id);
/*
* MW: Only a limited set of jointly configured binaries can
* be used in a continuous preview/video mode unless it is
* the copy mode and runs on SP.
*/
if (!candidate->enable.continuous &&
continuous && (mode != IA_CSS_BINARY_MODE_COPY)) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: !%d && %d && (%d != %d)\n",
__LINE__, candidate->enable.continuous,
continuous, mode,
IA_CSS_BINARY_MODE_COPY);
continue;
}
if (striped && candidate->iterator.num_stripes == 1) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: binary is not striped\n",
__LINE__);
continue;
}
if (candidate->pipeline.isp_pipe_version != isp_pipe_version &&
(mode != IA_CSS_BINARY_MODE_COPY) &&
(mode != IA_CSS_BINARY_MODE_CAPTURE_PP) &&
(mode != IA_CSS_BINARY_MODE_VF_PP)) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: (%d != %d)\n",
__LINE__,
candidate->pipeline.isp_pipe_version, isp_pipe_version);
continue;
}
if (!candidate->enable.reduced_pipe && enable_reduced_pipe) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: !%d && %d\n",
__LINE__,
candidate->enable.reduced_pipe,
enable_reduced_pipe);
continue;
}
if (!candidate->enable.dvs_6axis && enable_dvs_6axis) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: !%d && %d\n",
__LINE__,
candidate->enable.dvs_6axis,
enable_dvs_6axis);
continue;
}
if (candidate->enable.high_speed && !enable_high_speed) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: %d && !%d\n",
__LINE__,
candidate->enable.high_speed,
enable_high_speed);
continue;
}
if (!candidate->enable.xnr && need_xnr) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: %d && !%d\n",
__LINE__,
candidate->enable.xnr,
need_xnr);
continue;
}
if (!(candidate->enable.ds & 2) && enable_yuv_ds) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: !%d && %d\n",
__LINE__,
((candidate->enable.ds & 2) != 0),
enable_yuv_ds);
continue;
}
if ((candidate->enable.ds & 2) && !enable_yuv_ds) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: %d && !%d\n",
__LINE__,
((candidate->enable.ds & 2) != 0),
enable_yuv_ds);
continue;
}
if (mode == IA_CSS_BINARY_MODE_VIDEO &&
candidate->enable.ds && need_ds)
need_dz = false;
/* when we require vf output, we need to have vf_veceven */
if ((req_vf_info != NULL) && !(candidate->enable.vf_veceven ||
/* or variable vf vec even */
candidate->vf_dec.is_variable ||
/* or more than one output pin. */
xcandidate->num_output_pins > 1)) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: (%p != NULL) && !(%d || %d || (%d >%d))\n",
__LINE__, req_vf_info,
candidate->enable.vf_veceven,
candidate->vf_dec.is_variable,
xcandidate->num_output_pins, 1);
continue;
}
if (!candidate->enable.dvs_envelope && need_dvs) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: !%d && %d\n",
__LINE__,
candidate->enable.dvs_envelope, (int)need_dvs);
continue;
}
/* internal_res check considers input, output, and dvs envelope sizes */
ia_css_binary_internal_res(req_in_info, req_bds_out_info,
req_bin_out_info, &dvs_env, candidate, &internal_res);
if (internal_res.width > candidate->internal.max_width) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: (%d > %d)\n",
__LINE__, internal_res.width,
candidate->internal.max_width);
continue;
}
if (internal_res.height > candidate->internal.max_height) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: (%d > %d)\n",
__LINE__, internal_res.height,
candidate->internal.max_height);
continue;
}
if (!candidate->enable.ds && need_ds && !(xcandidate->num_output_pins > 1)) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: !%d && %d\n",
__LINE__, candidate->enable.ds, (int)need_ds);
continue;
}
if (!candidate->enable.uds && !candidate->enable.dvs_6axis && need_dz) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: !%d && !%d && %d\n",
__LINE__, candidate->enable.uds,
candidate->enable.dvs_6axis, (int)need_dz);
continue;
}
if (online && candidate->input.source == IA_CSS_BINARY_INPUT_MEMORY) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: %d && (%d == %d)\n",
__LINE__, online, candidate->input.source,
IA_CSS_BINARY_INPUT_MEMORY);
continue;
}
if (!online && candidate->input.source == IA_CSS_BINARY_INPUT_SENSOR) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: !%d && (%d == %d)\n",
__LINE__, online, candidate->input.source,
IA_CSS_BINARY_INPUT_SENSOR);
continue;
}
if (req_bin_out_info->res.width < candidate->output.min_width ||
req_bin_out_info->res.width > candidate->output.max_width) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: (%d > %d) || (%d < %d)\n",
__LINE__,
req_bin_out_info->padded_width,
candidate->output.min_width,
req_bin_out_info->padded_width,
candidate->output.max_width);
continue;
}
if (xcandidate->num_output_pins > 1 && /* in case we have a second output pin, */
req_vf_info) { /* and we need vf output. */
if (req_vf_info->res.width > candidate->output.max_width) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: (%d < %d)\n",
__LINE__,
req_vf_info->res.width,
candidate->output.max_width);
continue;
}
}
if (req_in_info->padded_width > candidate->input.max_width) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: (%d > %d)\n",
__LINE__, req_in_info->padded_width,
candidate->input.max_width);
continue;
}
if (!binary_supports_output_format(xcandidate, req_bin_out_info->format)) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: !%d\n",
__LINE__,
binary_supports_output_format(xcandidate, req_bin_out_info->format));
continue;
}
#ifdef ISP2401
if (!binary_supports_input_format(xcandidate, descr->stream_format)) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: !%d\n",
__LINE__,
binary_supports_input_format(xcandidate, req_in_info->format));
continue;
}
#endif
if (xcandidate->num_output_pins > 1 && /* in case we have a second output pin, */
req_vf_info && /* and we need vf output. */
/* check if the required vf format
is supported. */
!binary_supports_output_format(xcandidate, req_vf_info->format)) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: (%d > %d) && (%p != NULL) && !%d\n",
__LINE__, xcandidate->num_output_pins, 1,
req_vf_info,
binary_supports_output_format(xcandidate, req_vf_info->format));
continue;
}
/* Check if vf_veceven supports the requested vf format */
if (xcandidate->num_output_pins == 1 &&
req_vf_info && candidate->enable.vf_veceven &&
!binary_supports_vf_format(xcandidate, req_vf_info->format)) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: (%d == %d) && (%p != NULL) && %d && !%d\n",
__LINE__, xcandidate->num_output_pins, 1,
req_vf_info, candidate->enable.vf_veceven,
binary_supports_vf_format(xcandidate, req_vf_info->format));
continue;
}
/* Check if vf_veceven supports the requested vf width */
if (xcandidate->num_output_pins == 1 &&
req_vf_info && candidate->enable.vf_veceven) { /* and we need vf output. */
if (req_vf_info->res.width > candidate->output.max_width) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: (%d < %d)\n",
__LINE__,
req_vf_info->res.width,
candidate->output.max_width);
continue;
}
}
if (!supports_bds_factor(candidate->bds.supported_bds_factors,
descr->required_bds_factor)) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n",
__LINE__, candidate->bds.supported_bds_factors,
descr->required_bds_factor);
continue;
}
if (!candidate->enable.dpc && need_dpc) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n",
__LINE__, candidate->enable.dpc,
descr->enable_dpc);
continue;
}
if (candidate->uds.use_bci && enable_capture_pp_bli) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: 0x%x & 0x%x)\n",
__LINE__, candidate->uds.use_bci,
descr->enable_capture_pp_bli);
continue;
}
#ifdef ISP2401
if (candidate->enable.luma_only != enable_luma_only) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: %d != %d\n",
__LINE__, candidate->enable.luma_only,
descr->enable_luma_only);
continue;
}
if(!candidate->enable.tnr && need_tnr) {
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() [%d] continue: !%d && %d\n",
__LINE__, candidate->enable.tnr,
descr->enable_tnr);
continue;
}
#endif
/* reconfigure any variable properties of the binary */
err = ia_css_binary_fill_info(xcandidate, online, two_ppc,
stream_format, req_in_info,
req_bds_out_info,
req_out_info, req_vf_info,
binary, &dvs_env,
descr->stream_config_left_padding,
false);
if (err != IA_CSS_SUCCESS)
break;
binary_init_metrics(&binary->metrics, &binary->info->sp);
break;
}
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() selected = %p, mode = %d ID = %d\n",
xcandidate, xcandidate ? xcandidate->sp.pipeline.mode : 0, xcandidate ? xcandidate->sp.id : 0);
ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
"ia_css_binary_find() leave: return_err=%d\n", err);
return err;
}
unsigned
ia_css_binary_max_vf_width(void)
{
/* This is (should be) true for IPU1 and IPU2 */
/* For IPU3 (SkyCam) this pointer is guarenteed to be NULL simply because such a binary does not exist */
if (binary_infos[IA_CSS_BINARY_MODE_VF_PP])
return binary_infos[IA_CSS_BINARY_MODE_VF_PP]->sp.output.max_width;
return 0;
}
void
ia_css_binary_destroy_isp_parameters(struct ia_css_binary *binary)
{
if (binary) {
ia_css_isp_param_destroy_isp_parameters(&binary->mem_params,
&binary->css_params);
}
}
void
ia_css_binary_get_isp_binaries(struct ia_css_binary_xinfo **binaries,
uint32_t *num_isp_binaries)
{
assert(binaries != NULL);
if (num_isp_binaries)
*num_isp_binaries = 0;
*binaries = all_binaries;
if (all_binaries && num_isp_binaries) {
/* -1 to account for sp binary which is not stored in all_binaries */
if (sh_css_num_binaries > 0)
*num_isp_binaries = sh_css_num_binaries - 1;
}
}