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