#include <linux/math.h>
#include <math_support.h>
#include <gdc_device.h> /* HR_GDC_N */
#include "hmm.h"
#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 "atomisp_internal.h"
#include "vf/vf_1.0/ia_css_vf.host.h"
#include "sc/sc_1.0/ia_css_sc.host.h"
#include "sdis/sdis_1.0/ia_css_sdis.host.h"
#include "fixedbds/fixedbds_1.0/ia_css_fixedbds_param.h" /* FRAC_ACC */
#include "camera/pipe/interface/ia_css_pipe_binarydesc.h"
#include "assert_support.h"
#define IMPLIES(a, b) (!(a) || (b)) /* A => B */
static struct ia_css_binary_xinfo *all_binaries;
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);
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) {
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) && (out_info) &&
(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) {
isp_tmp_internal_width = out_info->padded_width;
isp_tmp_internal_height = out_info->res.height;
}
}
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);
}
struct sh_css_shading_table_bayer_origin_compute_results {
u32 bayer_scale_hor_ratio_in;
u32 bayer_scale_hor_ratio_out;
u32 bayer_scale_ver_ratio_in;
u32 bayer_scale_ver_ratio_out;
u32 sc_bayer_origin_x_bqs_on_shading_table;
u32 sc_bayer_origin_y_bqs_on_shading_table;
};
static int
ia_css_binary_compute_shading_table_bayer_origin(
const struct ia_css_binary *binary,
unsigned int required_bds_factor,
const struct ia_css_stream_config *stream_config,
struct sh_css_shading_table_bayer_origin_compute_results *res)
{
int err;
struct u32_fract bds;
unsigned int left_padding_bqs;
unsigned int need_bds_factor_2_00;
unsigned int left_padding_adjusted_bqs;
unsigned int bad_bqs_on_left_before_bs;
unsigned int bad_bqs_on_left_after_bs;
unsigned int bad_bqs_on_top_before_bs;
unsigned int bad_bqs_on_top_after_bs;
err = sh_css_bds_factor_get_fract(required_bds_factor, &bds);
if (err)
return err;
if (stream_config->left_padding == -1)
left_padding_bqs = _ISP_BQS(binary->left_padding);
else
left_padding_bqs = (unsigned int)((int)ISP_VEC_NELEMS
- _ISP_BQS(stream_config->left_padding));
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);
if (need_bds_factor_2_00 && binary->info->sp.pipeline.left_cropping > 0)
left_padding_adjusted_bqs = left_padding_bqs + ISP_VEC_NELEMS;
else
left_padding_adjusted_bqs = left_padding_bqs;
bad_bqs_on_left_before_bs = 0;
bad_bqs_on_top_before_bs = 0;
bad_bqs_on_left_after_bs = 0;
bad_bqs_on_top_after_bs = 0;
res->sc_bayer_origin_x_bqs_on_shading_table =
((left_padding_adjusted_bqs + bad_bqs_on_left_before_bs)
* bds.denominator + bds.numerator / 2) / bds.numerator
+ bad_bqs_on_left_after_bs;
res->sc_bayer_origin_y_bqs_on_shading_table =
(bad_bqs_on_top_before_bs * bds.denominator + bds.numerator / 2) / bds.numerator
+ bad_bqs_on_top_after_bs;
res->bayer_scale_hor_ratio_in = bds.numerator;
res->bayer_scale_hor_ratio_out = bds.denominator;
res->bayer_scale_ver_ratio_in = bds.numerator;
res->bayer_scale_ver_ratio_out = bds.denominator;
return err;
}
static int
binary_get_shading_info_type_1(const struct ia_css_binary *binary,
unsigned int required_bds_factor,
const struct ia_css_stream_config *stream_config,
struct ia_css_shading_info *info)
{
int err;
struct sh_css_shading_table_bayer_origin_compute_results res;
assert(binary);
assert(info);
info->type = IA_CSS_SHADING_CORRECTION_TYPE_1;
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);
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)
return err;
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;
return err;
}
int
ia_css_binary_get_shading_info(const struct ia_css_binary *binary,
enum ia_css_shading_correction_type type,
unsigned int required_bds_factor,
const struct ia_css_stream_config *stream_config,
struct ia_css_shading_info *shading_info,
struct ia_css_pipe_config *pipe_config)
{
int err;
assert(binary);
assert(shading_info);
IA_CSS_ENTER_PRIVATE("binary=%p, type=%d, required_bds_factor=%d, stream_config=%p",
binary, type, required_bds_factor, stream_config);
if (type == IA_CSS_SHADING_CORRECTION_TYPE_1)
err = binary_get_shading_info_type_1(binary,
required_bds_factor,
stream_config,
shading_info);
else
err = -ENOTSUPP;
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);
assert(info);
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);
assert(info);
dvs_info = &info->dvs_grid.dvs_grid_info;
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;
}
int
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;
int err = 0;
IA_CSS_ENTER_PRIVATE("binary=%p, info=%p, pipe=%p",
binary, info, pipe);
assert(binary);
assert(info);
s3a_info = &info->s3a_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;
s3a_info->has_histogram = 0;
IA_CSS_LEAVE_ERR_PRIVATE(err);
return err;
}
static void
binary_init_pc_histogram(struct sh_css_pc_histogram *histo)
{
assert(histo);
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);
assert(info);
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);
}
static bool
binary_supports_output_format(const struct ia_css_binary_xinfo *info,
enum ia_css_frame_format format)
{
int i;
assert(info);
for (i = 0; i < info->num_output_formats; i++) {
if (info->output_formats[i] == format)
return true;
}
return false;
}
static bool
binary_supports_vf_format(const struct ia_css_binary_xinfo *info,
enum ia_css_frame_format format)
{
int i;
assert(info);
for (i = 0; i < info->num_vf_formats; i++) {
if (info->vf_formats[i] == format)
return true;
}
return false;
}
static bool
supports_bds_factor(u32 supported_factors,
uint32_t bds_factor)
{
return ((supported_factors & PACK_BDS_FACTOR(bds_factor)) != 0);
}
static int
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 int size = sh_css_blob_info[i].header.blob.size;
if ((!info) || (!binary_found))
return -EINVAL;
*info = sh_css_blob_info[i].header.info.isp;
*binary_found = blob;
info->blob_index = i;
if (!size)
return 0;
info->xmem_addr = sh_css_load_blob(blob, size);
if (!info->xmem_addr)
return -ENOMEM;
return 0;
}
int
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 0;
all_binaries = kvmalloc(num_of_isp_binaries * sizeof(*all_binaries),
GFP_KERNEL);
if (!all_binaries)
return -ENOMEM;
for (i = 0; i < num_of_isp_binaries; i++)
{
int ret;
struct ia_css_binary_xinfo *binary = &all_binaries[i];
bool binary_found;
ret = binary_init_info(binary, i, &binary_found);
if (ret)
return ret;
if (!binary_found)
continue;
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 0;
}
int
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;
}
kvfree(all_binaries);
return 0;
}
static int
binary_grid_deci_factor_log2(int width, int height)
{
#define MAX_SPEC_DECI_FACT_LOG2 5
#define MIN_SPEC_DECI_FACT_LOG2 3
#define DECI_FACT_LOG2_5_SMALLEST_FRAME_WIDTH_BQ 1280
#define DECI_FACT_LOG2_4_SMALLEST_FRAME_WIDTH_BQ 640
int smallest_factor;
int spec_factor;
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);
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--;
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;
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;
#if defined(ISP2401)
nr_of_left_paddings = 0;
#else
nr_of_left_paddings = 2 * ISP_VEC_NELEMS;
#endif
if (need_scaling) {
if (stream_config_left_padding != -1) {
rval =
CEIL_MUL(in_frame_width + nr_of_left_paddings,
2 * ISP_VEC_NELEMS);
} else {
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;
}
int
ia_css_binary_fill_info(const struct ia_css_binary_xinfo *xinfo,
bool online,
bool two_ppc,
enum atomisp_input_format stream_format,
const struct ia_css_frame_info *in_info,
const struct ia_css_frame_info *bds_out_info,
const struct ia_css_frame_info *out_info[],
const struct ia_css_frame_info *vf_info,
struct ia_css_binary *binary,
struct ia_css_resolution *dvs_env,
int stream_config_left_padding,
bool accelerator) {
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,
sc_3a_dis_width = 0,
sc_3a_dis_padded_width = 0,
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;
int err;
unsigned int i;
const struct ia_css_frame_info *bin_out_info = NULL;
assert(info);
assert(binary);
binary->info = xinfo;
if (!accelerator)
{
err = ia_css_isp_param_allocate_isp_parameters(
&binary->mem_params, &binary->css_params,
&info->mem_initializers);
if (err) {
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 && bin_out_info)
{
need_scaling = (in_info->res.width != bin_out_info->res.width) ||
(in_info->res.height != bin_out_info->res.height);
}
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_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;
if (bin_out_info)
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)
{
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;
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]) {
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 {
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) {
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;
if ((vf_info) && (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)
return -EINVAL;
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);
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 {
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 && in_info &&
bds_out_info->res.width != in_info->res.width)
{
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 = _ISP_SCTBL_WIDTH_PER_COLOR(sc_3a_dis_padded_width, s3a_log_deci);
binary->sctbl_aligned_width_per_color = SH_CSS_MAX_SCTBL_ALIGNED_WIDTH_PER_COLOR;
binary->sctbl_height = _ISP_SCTBL_HEIGHT(sc_3a_dis_height, s3a_log_deci);
} else
{
binary->sctbl_width_per_color = 0;
binary->sctbl_aligned_width_per_color = 0;
binary->sctbl_height = 0;
}
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 0;
}
static int __ia_css_binary_find(struct ia_css_binary_descr *descr,
struct ia_css_binary *binary) {
int mode;
bool online;
bool two_ppc;
enum atomisp_input_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;
bool need_ds, need_dz, need_dvs, need_xnr, need_dpc;
bool striped;
bool enable_yuv_ds;
bool enable_high_speed;
bool enable_dvs_6axis;
bool enable_reduced_pipe;
bool enable_capture_pp_bli;
int err = -EINVAL;
bool continuous;
unsigned int isp_pipe_version;
struct ia_css_resolution dvs_env, internal_res;
unsigned int i;
assert(descr);
assert(binary);
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)
return -EINVAL;
req_vf_info = descr->vf_info;
need_xnr = descr->enable_xnr;
need_ds = descr->enable_fractional_ds;
need_dz = false;
need_dvs = false;
need_dpc = descr->enable_dpc;
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;
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;
need_dvs = dvs_env.width || dvs_env.height;
}
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;
}
}
}
for (xcandidate = binary_infos[mode]; xcandidate;
xcandidate = xcandidate->next) {
struct ia_css_binary_info *candidate = &xcandidate->sp;
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);
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;
if ((req_vf_info) && !(candidate->enable.vf_veceven ||
candidate->vf_dec.is_variable ||
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;
}
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 &&
req_vf_info) {
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;
}
if (xcandidate->num_output_pins > 1 &&
req_vf_info &&
!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;
}
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;
}
if (xcandidate->num_output_pins == 1 &&
req_vf_info && candidate->enable.vf_veceven) {
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;
}
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)
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);
if (!err && xcandidate)
dev_dbg(atomisp_dev,
"Using binary %s (id %d), type %d, mode %d, continuous %s\n",
xcandidate->blob->name,
xcandidate->sp.id,
xcandidate->type,
xcandidate->sp.pipeline.mode,
xcandidate->sp.enable.continuous ? "true" : "false");
return err;
}
int ia_css_binary_find(struct ia_css_binary_descr *descr,
struct ia_css_binary *binary)
{
int ret = __ia_css_binary_find(descr, binary);
if (unlikely(ret)) {
dev_dbg(atomisp_dev, "Seeking for binary failed at:");
dump_stack();
}
return ret;
}
unsigned
ia_css_binary_max_vf_width(void)
{
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);
if (num_isp_binaries)
*num_isp_binaries = 0;
*binaries = all_binaries;
if (all_binaries && num_isp_binaries) {
if (sh_css_num_binaries > 0)
*num_isp_binaries = sh_css_num_binaries - 1;
}
}