root/drivers/staging/media/atomisp/pci/sh_css_params.c
// SPDX-License-Identifier: GPL-2.0
/*
 * Support for Intel Camera Imaging ISP subsystem.
 * Copyright (c) 2015, Intel Corporation.
 */

#include <linux/math.h>

#include "gdc_device.h"         /* gdc_lut_store(), ... */
#include "isp.h"                        /* ISP_VEC_ELEMBITS */
#include "vamem.h"
#ifndef __INLINE_HMEM__
#define __INLINE_HMEM__
#endif
#include "hmem.h"
#define IA_CSS_INCLUDE_PARAMETERS
#define IA_CSS_INCLUDE_ACC_PARAMETERS

#include "hmm.h"
#include "sh_css_params.h"
#include "ia_css_queue.h"
#include "sw_event_global.h"            /* Event IDs */

#include "platform_support.h"
#include "assert_support.h"

#include "ia_css_stream.h"
#include "sh_css_params_internal.h"
#include "sh_css_param_shading.h"
#include "sh_css_param_dvs.h"
#include "ia_css_refcount.h"
#include "sh_css_internal.h"
#include "ia_css_control.h"
#include "ia_css_shading.h"
#include "sh_css_defs.h"
#include "sh_css_sp.h"
#include "ia_css_pipeline.h"
#include "ia_css_debug.h"

#include "ia_css_isp_param.h"
#include "ia_css_isp_params.h"
#include "ia_css_mipi.h"
#include "ia_css_morph.h"
#include "ia_css_host_data.h"
#include "ia_css_pipe.h"
#include "ia_css_pipe_binarydesc.h"

/* Include all kernel host interfaces for ISP1 */

#include "anr/anr_1.0/ia_css_anr.host.h"
#include "cnr/cnr_1.0/ia_css_cnr.host.h"
#include "csc/csc_1.0/ia_css_csc.host.h"
#include "de/de_1.0/ia_css_de.host.h"
#include "dp/dp_1.0/ia_css_dp.host.h"
#include "bnr/bnr_1.0/ia_css_bnr.host.h"
#include "dvs/dvs_1.0/ia_css_dvs.host.h"
#include "fpn/fpn_1.0/ia_css_fpn.host.h"
#include "gc/gc_1.0/ia_css_gc.host.h"
#include "macc/macc_1.0/ia_css_macc.host.h"
#include "ctc/ctc_1.0/ia_css_ctc.host.h"
#include "ob/ob_1.0/ia_css_ob.host.h"
#include "raw/raw_1.0/ia_css_raw.host.h"
#include "fixedbds/fixedbds_1.0/ia_css_fixedbds_param.h"
#include "s3a/s3a_1.0/ia_css_s3a.host.h"
#include "sc/sc_1.0/ia_css_sc.host.h"
#include "sdis/sdis_1.0/ia_css_sdis.host.h"
#include "tnr/tnr_1.0/ia_css_tnr.host.h"
#include "uds/uds_1.0/ia_css_uds_param.h"
#include "wb/wb_1.0/ia_css_wb.host.h"
#include "ynr/ynr_1.0/ia_css_ynr.host.h"
#include "xnr/xnr_1.0/ia_css_xnr.host.h"

/* Include additional kernel host interfaces for ISP2 */

#include "aa/aa_2/ia_css_aa2.host.h"
#include "anr/anr_2/ia_css_anr2.host.h"
#include "bh/bh_2/ia_css_bh.host.h"
#include "cnr/cnr_2/ia_css_cnr2.host.h"
#include "ctc/ctc1_5/ia_css_ctc1_5.host.h"
#include "de/de_2/ia_css_de2.host.h"
#include "gc/gc_2/ia_css_gc2.host.h"
#include "sdis/sdis_2/ia_css_sdis2.host.h"
#include "ynr/ynr_2/ia_css_ynr2.host.h"
#include "fc/fc_1.0/ia_css_formats.host.h"

#include "xnr/xnr_3.0/ia_css_xnr3.host.h"


#include "sh_css_frac.h"
#include "ia_css_bufq.h"

static size_t fpntbl_bytes(const struct ia_css_binary *binary)
{
        return array3_size(sizeof(char),
                           binary->in_frame_info.res.height,
                           binary->in_frame_info.padded_width);
}

static size_t sctbl_bytes(const struct ia_css_binary *binary)
{
        return size_mul(sizeof(unsigned short),
                        array3_size(binary->sctbl_height,
                                    binary->sctbl_aligned_width_per_color,
                                    IA_CSS_SC_NUM_COLORS));
}

static size_t morph_plane_bytes(const struct ia_css_binary *binary)
{
        return array3_size(SH_CSS_MORPH_TABLE_ELEM_BYTES,
                           binary->morph_tbl_aligned_width,
                           binary->morph_tbl_height);
}

/* We keep a second copy of the ptr struct for the SP to access.
   Again, this would not be necessary on the chip. */
static ia_css_ptr sp_ddr_ptrs;

/* sp group address on DDR */
static ia_css_ptr xmem_sp_group_ptrs;

static ia_css_ptr xmem_sp_stage_ptrs[IA_CSS_PIPE_ID_NUM]
[SH_CSS_MAX_STAGES];
static ia_css_ptr xmem_isp_stage_ptrs[IA_CSS_PIPE_ID_NUM]
[SH_CSS_MAX_STAGES];

static ia_css_ptr default_gdc_lut;
static int interleaved_lut_temp[4][HRT_GDC_N];

/* END DO NOT MOVE INTO VIMALS_WORLD */

/* Digital Zoom lookup table. See documentation for more details about the
 * contents of this table.
 */
static const int zoom_table[4][HRT_GDC_N] = {
        {
                0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,
                  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,
                  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,
                  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,
                  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,
                  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,
                  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,
                  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,
                  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,
                  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,
                  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,
                  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,
                  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,
                  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,
                  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,
                  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,
                  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,
                  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,
                  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,
                  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,
                  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,
                  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,
                  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,
                  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4,
                  -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4,
                  -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4,
                  -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4,
                  -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4,
                  -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4,
                  -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4,
                  -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4,
                  -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4,
                  -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4,
                  -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4,
                  -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4,
                  -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4,
                  -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4,
                  -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4,
                  -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4,
                  -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4,
                  -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4,
                  -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4,
                  -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4,
                  -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4,
                  -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4,
                  -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4,
                  -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4,
                  -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4,
                  -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4,
                  -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4,
                  -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4,
                  -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,
                  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,
                  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,
                  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,  -7 << 4,
                  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,
                  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,
                  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,
                  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4
        },
        {
                0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,
                  2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,
                  4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,
                  4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,
                  7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,
                  7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,
                  9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,
                  9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,
                  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,
                  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,
                  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,
                  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,
                  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,
                  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,
                  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,
                  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,
                  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,
                  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,
                  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,
                  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,
                  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,
                  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,
                  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,
                  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,
                  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,
                  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,
                  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,
                  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,
                  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,
                  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,
                  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,
                  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,
                  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,
                  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,
                  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,
                  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,
                  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,
                  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,
                  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,
                  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,
                  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,
                  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,
                  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,
                  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,
                  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,
                  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,
                  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,
                  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,
                  105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4,
                  105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4,
                  110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4,
                  110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4,
                  116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4,
                  116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4,
                  121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4,
                  121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4,
                  127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4,
                  127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4,
                  132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4,
                  132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4,
                  138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4,
                  138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4,
                  144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4,
                  144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4,
                  149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4,
                  149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4,
                  154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4,
                  154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4,
                  160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4,
                  160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4,
                  165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4,
                  165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4,
                  170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4,
                  170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4,
                  176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4,
                  176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4,
                  181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4,
                  181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4,
                  186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4,
                  186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4,
                  191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4,
                  191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4,
                  195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4,
                  195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4,
                  200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4,
                  200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4,
                  205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4,
                  205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4,
                  209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4,
                  209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4,
                  213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4,
                  213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4,
                  218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4,
                  218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4,
                  222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4,
                  222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4,
                  225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4,
                  225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4,
                  229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4,
                  229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4,
                  232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4,
                  232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4,
                  236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4,
                  236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4,
                  239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4,
                  239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4,
                  241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4,
                  241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4,
                  244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4,
                  244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4,
                  246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4,
                  246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4,
                  248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4,
                  248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4,
                  250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4,
                  250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4,
                  252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4,
                  252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4,
                  253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4,
                  253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4,
                  254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4,
                  254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4,
                  255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4,
                  255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4,
                  255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4,
                  255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4
        },
        {
                256 << 4, 256 << 4, 256 << 4, 256 << 4, 256 << 4, 256 << 4, 256 << 4, 256 << 4,
                    256 << 4, 256 << 4, 256 << 4, 256 << 4, 256 << 4, 256 << 4, 256 << 4, 256 << 4,
                    255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4,
                    255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4,
                    255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4,
                    255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4, 255 << 4,
                    254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4,
                    254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4, 254 << 4,
                    253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4,
                    253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4, 253 << 4,
                    252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4,
                    252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4, 252 << 4,
                    250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4,
                    250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4, 250 << 4,
                    248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4,
                    248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4, 248 << 4,
                    246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4,
                    246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4, 246 << 4,
                    244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4,
                    244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4, 244 << 4,
                    241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4,
                    241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4, 241 << 4,
                    239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4,
                    239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4, 239 << 4,
                    236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4,
                    236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4, 236 << 4,
                    232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4,
                    232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4, 232 << 4,
                    229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4,
                    229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4, 229 << 4,
                    225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4,
                    225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4, 225 << 4,
                    222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4,
                    222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4, 222 << 4,
                    218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4,
                    218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4, 218 << 4,
                    213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4,
                    213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4, 213 << 4,
                    209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4,
                    209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4, 209 << 4,
                    205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4,
                    205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4, 205 << 4,
                    200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4,
                    200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4, 200 << 4,
                    195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4,
                    195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4, 195 << 4,
                    191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4,
                    191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4, 191 << 4,
                    186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4,
                    186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4, 186 << 4,
                    181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4,
                    181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4, 181 << 4,
                    176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4,
                    176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4, 176 << 4,
                    170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4,
                    170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4, 170 << 4,
                    165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4,
                    165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4, 165 << 4,
                    160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4,
                    160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4, 160 << 4,
                    154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4,
                    154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4, 154 << 4,
                    149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4,
                    149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4, 149 << 4,
                    144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4,
                    144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4, 144 << 4,
                    138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4,
                    138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4, 138 << 4,
                    132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4,
                    132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4, 132 << 4,
                    127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4,
                    127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4, 127 << 4,
                    121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4,
                    121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4, 121 << 4,
                    116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4,
                    116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4, 116 << 4,
                    110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4,
                    110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4, 110 << 4,
                    105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4,
                    105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4, 105 << 4,
                    99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,
                    99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,  99 << 4,
                    94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,
                    94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,  94 << 4,
                    88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,
                    88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,  88 << 4,
                    83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,
                    83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,  83 << 4,
                    78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,
                    78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,  78 << 4,
                    73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,
                    73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,  73 << 4,
                    67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,
                    67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,  67 << 4,
                    62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,
                    62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,  62 << 4,
                    58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,
                    58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,  58 << 4,
                    53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,
                    53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,  53 << 4,
                    48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,
                    48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,  48 << 4,
                    43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,
                    43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,  43 << 4,
                    39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,
                    39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,  39 << 4,
                    35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,
                    35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,  35 << 4,
                    31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,
                    31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,  31 << 4,
                    27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,
                    27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,  27 << 4,
                    23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,
                    23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,  23 << 4,
                    19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,
                    19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,  19 << 4,
                    16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,
                    16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,  16 << 4,
                    12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,
                    12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,  12 << 4,
                    9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,
                    9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,   9 << 4,
                    7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,
                    7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,   7 << 4,
                    4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,
                    4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,   4 << 4,
                    2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,
                    2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4,   2 << 4
        },
        {
                0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,
                  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,
                  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,
                  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,
                  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,
                  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,
                  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,
                  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4,
                  -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4, -10 << 4,
                  -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4,
                  -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4,
                  -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4,
                  -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4,
                  -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4,
                  -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4,
                  -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4,
                  -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4,
                  -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4,
                  -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4,
                  -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4,
                  -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4,
                  -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4,
                  -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4, -19 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4, -18 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4, -17 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4, -16 << 4,
                  -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4,
                  -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4, -15 << 4,
                  -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4,
                  -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4,
                  -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4,
                  -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4, -14 << 4,
                  -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4,
                  -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4, -13 << 4,
                  -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4,
                  -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4,
                  -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4,
                  -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4,
                  -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4,
                  -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4, -12 << 4,
                  -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4,
                  -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4,
                  -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4,
                  -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4, -11 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,  -9 << 4,
                  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,
                  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,  -8 << 4,
                  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,
                  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,
                  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,
                  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,
                  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,
                  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,  -6 << 4,
                  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,
                  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,  -5 << 4,
                  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,
                  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,
                  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,
                  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,
                  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,
                  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,  -4 << 4,
                  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,
                  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,  -3 << 4,
                  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,
                  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,
                  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,
                  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,  -2 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,  -1 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  1 << 4,   1 << 4,   1 << 4,   1 << 4,   1 << 4,   1 << 4,   1 << 4,   1 << 4,
                  1 << 4,   1 << 4,   1 << 4,   1 << 4,   1 << 4,   1 << 4,   1 << 4,   1 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,
                  0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4,   0 << 4
        }
};

static const struct ia_css_dz_config default_dz_config = {
        HRT_GDC_N,
        HRT_GDC_N,
        {
                \
                {0, 0}, \
                {0, 0}, \
        }
};

static const struct ia_css_vector default_motion_config = {
        0,
        0
};

/* ------ deprecated(bz675) : from ------ */
static const struct ia_css_shading_settings default_shading_settings = {
        1       /* enable shading table conversion in the css
                (This matches the legacy way.) */
};

/* ------ deprecated(bz675) : to ------ */

struct ia_css_isp_skc_dvs_statistics {
        ia_css_ptr p_data;
};

static int
ref_sh_css_ddr_address_map(
    struct sh_css_ddr_address_map *map,
    struct sh_css_ddr_address_map *out);

static int
write_ia_css_isp_parameter_set_info_to_ddr(
    struct ia_css_isp_parameter_set_info *me,
    ia_css_ptr *out);

static int
free_ia_css_isp_parameter_set_info(ia_css_ptr ptr);

static int
sh_css_params_write_to_ddr_internal(
    struct ia_css_pipe *pipe,
    unsigned int pipe_id,
    struct ia_css_isp_parameters *params,
    const struct ia_css_pipeline_stage *stage,
    struct sh_css_ddr_address_map *ddr_map,
    struct sh_css_ddr_address_map_size *ddr_map_size);

static int
sh_css_create_isp_params(struct ia_css_stream *stream,
                         struct ia_css_isp_parameters **isp_params_out);

static bool
sh_css_init_isp_params_from_global(struct ia_css_stream *stream,
                                   struct ia_css_isp_parameters *params,
                                   bool use_default_config,
                                   struct ia_css_pipe *pipe_in);

static int
sh_css_init_isp_params_from_config(struct ia_css_pipe *pipe,
                                   struct ia_css_isp_parameters *params,
                                   const struct ia_css_isp_config *config,
                                   struct ia_css_pipe *pipe_in);

static int
sh_css_set_global_isp_config_on_pipe(
    struct ia_css_pipe *curr_pipe,
    const struct ia_css_isp_config *config,
    struct ia_css_pipe *pipe);

static int
sh_css_set_per_frame_isp_config_on_pipe(
    struct ia_css_stream *stream,
    const struct ia_css_isp_config *config,
    struct ia_css_pipe *pipe);

static int
sh_css_update_uds_and_crop_info_based_on_zoom_region(
    const struct ia_css_binary_info *info,
    const struct ia_css_frame_info *in_frame_info,
    const struct ia_css_frame_info *out_frame_info,
    const struct ia_css_resolution *dvs_env,
    const struct ia_css_dz_config *zoom,
    const struct ia_css_vector *motion_vector,
    struct sh_css_uds_info *uds,                /* out */
    struct sh_css_crop_pos *sp_out_crop_pos,    /* out */
    struct ia_css_resolution pipe_in_res,
    bool enable_zoom);

ia_css_ptr
sh_css_params_ddr_address_map(void)
{
        return sp_ddr_ptrs;
}

/* ****************************************************
 * Each coefficient is stored as 7bits to fit 2 of them into one
 * ISP vector element, so we will store 4 coefficents on every
 * memory word (32bits)
 *
 * 0: Coefficient 0 used bits
 * 1: Coefficient 1 used bits
 * 2: Coefficient 2 used bits
 * 3: Coefficient 3 used bits
 * x: not used
 *
 * xx33333332222222 | xx11111110000000
 *
 * ***************************************************
 */
static struct ia_css_host_data *
convert_allocate_fpntbl(struct ia_css_isp_parameters *params)
{
        unsigned int i, j;
        short *data_ptr;
        struct ia_css_host_data *me;
        unsigned int isp_format_data_size;
        u32 *isp_format_data_ptr;

        assert(params);

        data_ptr = params->fpn_config.data;
        isp_format_data_size = params->fpn_config.height * params->fpn_config.width *
                               sizeof(uint32_t);

        me = ia_css_host_data_allocate(isp_format_data_size);

        if (!me)
                return NULL;

        isp_format_data_ptr = (uint32_t *)me->address;

        for (i = 0; i < params->fpn_config.height; i++) {
                for (j = 0;
                     j < params->fpn_config.width;
                     j += 4, data_ptr += 4, isp_format_data_ptr++) {
                        int data = data_ptr[0] << 0 |
                                   data_ptr[1] << 7 |
                                   data_ptr[2] << 16 |
                                   data_ptr[3] << 23;
                        *isp_format_data_ptr = data;
                }
        }
        return me;
}

static int
store_fpntbl(struct ia_css_isp_parameters *params, ia_css_ptr ptr)
{
        struct ia_css_host_data *isp_data;

        assert(params);
        assert(ptr != mmgr_NULL);

        isp_data = convert_allocate_fpntbl(params);
        if (!isp_data) {
                IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
                return -ENOMEM;
        }
        ia_css_params_store_ia_css_host_data(ptr, isp_data);

        ia_css_host_data_free(isp_data);
        return 0;
}

static void
convert_raw_to_fpn(struct ia_css_isp_parameters *params)
{
        int maxval = 0;
        unsigned int i;

        assert(params);

        /* Find the maximum value in the table */
        for (i = 0; i < params->fpn_config.height * params->fpn_config.width; i++) {
                int val = params->fpn_config.data[i];
                /* Make sure FPN value can be represented in 13-bit unsigned
                 * number (ISP precision - 1), but note that actual input range
                 * depends on precision of input frame data.
                 */
                if (val < 0) {
                        /* Checkpatch patch */
                        val = 0;
                } else if (val >= (1 << 13)) {
                        /* Checkpatch patch */
                        /* MW: BUG, is "13" a system or application property */
                        val = (1 << 13) - 1;
                }
                maxval = max(maxval, val);
        }
        /* Find the lowest shift value to remap the values in the range
         * 0..maxval to 0..2^shiftval*63.
         */
        params->fpn_config.shift = 0;
        while (maxval > 63) {
                /* MW: BUG, is "63" a system or application property */
                maxval >>= 1;
                params->fpn_config.shift++;
        }
        /* Adjust the values in the table for the shift value */
        for (i = 0; i < params->fpn_config.height * params->fpn_config.width; i++)
                ((unsigned short *)params->fpn_config.data)[i] >>= params->fpn_config.shift;
}

static void
ia_css_process_kernel(struct ia_css_stream *stream,
                      struct ia_css_isp_parameters *params,
                      void (*process)(unsigned int pipe_id,
                                      const struct ia_css_pipeline_stage *stage,
                                      struct ia_css_isp_parameters *params))
{
        int i;

        for (i = 0; i < stream->num_pipes; i++) {
                struct ia_css_pipe *pipe = stream->pipes[i];
                struct ia_css_pipeline *pipeline = ia_css_pipe_get_pipeline(pipe);
                struct ia_css_pipeline_stage *stage;

                /* update the other buffers to the pipe specific copies */
                for (stage = pipeline->stages; stage; stage = stage->next) {
                        if (!stage || !stage->binary) continue;
                        process(pipeline->pipe_id, stage, params);
                }
        }
}

static int
sh_css_select_dp_10bpp_config(const struct ia_css_pipe *pipe,
                              bool *is_dp_10bpp)
{
        int err = 0;
        /* Currently we check if 10bpp DPC configuration is required based
         * on the use case,i.e. if BDS and DPC is both enabled. The more cleaner
         * design choice would be to expose the type of DPC (either 10bpp or 13bpp)
         * using the binary info, but the current control flow does not allow this
         * implementation. (This is because the configuration is set before a
         * binary is selected, and the binary info is not available)
         */
        if ((!pipe) || (!is_dp_10bpp)) {
                IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
                err = -EINVAL;
        } else {
                *is_dp_10bpp = false;

                /* check if DPC is enabled from the host */
                if (pipe->config.enable_dpc) {
                        /*check if BDS is enabled*/
                        unsigned int required_bds_factor = SH_CSS_BDS_FACTOR_1_00;

                        if ((pipe->config.bayer_ds_out_res.width != 0) &&
                            (pipe->config.bayer_ds_out_res.height != 0)) {
                                if (0 == binarydesc_calculate_bds_factor(
                                        pipe->config.input_effective_res,
                                        pipe->config.bayer_ds_out_res,
                                        &required_bds_factor)) {
                                        if (required_bds_factor != SH_CSS_BDS_FACTOR_1_00) {
                                                /*we use 10bpp BDS configuration*/
                                                *is_dp_10bpp = true;
                                        }
                                }
                        }
                }
        }

        return err;
}

int
sh_css_set_black_frame(struct ia_css_stream *stream,
                       const struct ia_css_frame *raw_black_frame)
{
        struct ia_css_isp_parameters *params;
        /* this function desperately needs to be moved to the ISP or SP such
         * that it can use the DMA.
         */
        unsigned int height, width, y, x, k, data;
        ia_css_ptr ptr;

        assert(stream);
        assert(raw_black_frame);

        params = stream->isp_params_configs;
        height = raw_black_frame->frame_info.res.height;
        width = raw_black_frame->frame_info.padded_width;

        ptr = raw_black_frame->data
        + raw_black_frame->planes.raw.offset;

        IA_CSS_ENTER_PRIVATE("black_frame=%p", raw_black_frame);

        if (params->fpn_config.data &&
            (params->fpn_config.width != width || params->fpn_config.height != height)) {
                kvfree(params->fpn_config.data);
                params->fpn_config.data = NULL;
        }
        if (!params->fpn_config.data) {
                params->fpn_config.data = kvmalloc(array3_size(height, width, sizeof(short)),
                                                   GFP_KERNEL);
                if (!params->fpn_config.data) {
                        IA_CSS_ERROR("out of memory");
                        IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
                        return -ENOMEM;
                }
                params->fpn_config.width = width;
                params->fpn_config.height = height;
                params->fpn_config.shift = 0;
        }

        /* store raw to fpntbl */
        for (y = 0; y < height; y++) {
                for (x = 0; x < width; x += (ISP_VEC_NELEMS * 2)) {
                        int ofs = y * width + x;

                        for (k = 0; k < ISP_VEC_NELEMS; k += 2) {
                                hmm_load(ptr, (void *)(&data), sizeof(int));
                                params->fpn_config.data[ofs + 2 * k] =
                                    (short)(data & 0xFFFF);
                                params->fpn_config.data[ofs + 2 * k + 2] =
                                    (short)((data >> 16) & 0xFFFF);
                                ptr += sizeof(int);     /* byte system address */
                        }
                        for (k = 0; k < ISP_VEC_NELEMS; k += 2) {
                                hmm_load(ptr, (void *)(&data), sizeof(int));
                                params->fpn_config.data[ofs + 2 * k + 1] =
                                    (short)(data & 0xFFFF);
                                params->fpn_config.data[ofs + 2 * k + 3] =
                                    (short)((data >> 16) & 0xFFFF);
                                ptr += sizeof(int);     /* byte system address */
                        }
                }
        }

        /* raw -> fpn */
        convert_raw_to_fpn(params);

        /* overwrite isp parameter */
        ia_css_process_kernel(stream, params, ia_css_kernel_process_param[IA_CSS_FPN_ID]);

        IA_CSS_LEAVE_ERR_PRIVATE(0);

        return 0;
}

bool
sh_css_params_set_binning_factor(struct ia_css_stream *stream,
                                 unsigned int binning_fact)
{
        struct ia_css_isp_parameters *params;

        IA_CSS_ENTER_PRIVATE("void");
        assert(stream);

        params = stream->isp_params_configs;

        if (params->sensor_binning != binning_fact) {
                params->sensor_binning = binning_fact;
                params->sc_table_changed = true;
        }

        IA_CSS_LEAVE_PRIVATE("void");

        return params->sc_table_changed;
}

static void
sh_css_set_shading_table(struct ia_css_stream *stream,
                         struct ia_css_isp_parameters *params,
                         const struct ia_css_shading_table *table)
{
        IA_CSS_ENTER_PRIVATE("");
        if (!table)
                return;
        assert(stream);

        if (!table->enable)
                table = NULL;

        if (table != params->sc_table) {
                params->sc_table = table;
                params->sc_table_changed = true;
                /* Not very clean, this goes to sh_css.c to invalidate the
                 * shading table for all pipes. Should replaced by a loop
                 * and a pipe-specific call.
                 */
                if (!params->output_frame)
                        sh_css_invalidate_shading_tables(stream);
        }

        IA_CSS_LEAVE_PRIVATE("void");
}

void
ia_css_params_store_ia_css_host_data(
    ia_css_ptr ddr_addr,
    struct ia_css_host_data *data)
{
        assert(data);
        assert(data->address);
        assert(ddr_addr != mmgr_NULL);

        IA_CSS_ENTER_PRIVATE("");

        hmm_store(ddr_addr,
                   (void *)(data->address),
                   (size_t)data->size);

        IA_CSS_LEAVE_PRIVATE("void");
}

struct ia_css_host_data *
ia_css_params_alloc_convert_sctbl(
    const struct ia_css_pipeline_stage *stage,
    const struct ia_css_shading_table *shading_table)
{
        const struct ia_css_binary *binary = stage->binary;
        struct ia_css_host_data    *sctbl;
        unsigned int i, j, aligned_width;
        unsigned int sctbl_size;
        short int    *ptr;

        assert(binary);
        assert(shading_table);

        IA_CSS_ENTER_PRIVATE("");

        if (!shading_table) {
                IA_CSS_LEAVE_PRIVATE("void");
                return NULL;
        }

        aligned_width = binary->sctbl_aligned_width_per_color;
        sctbl_size = shading_table->height * IA_CSS_SC_NUM_COLORS * aligned_width *
                     sizeof(short);

        sctbl = ia_css_host_data_allocate((size_t)sctbl_size);

        if (!sctbl)
                return NULL;
        ptr = (short int *)sctbl->address;
        memset(ptr,
               0,
               sctbl_size);

        for (i = 0; i < shading_table->height; i++) {
                for (j = 0; j < IA_CSS_SC_NUM_COLORS; j++) {
                        memcpy(ptr,
                               &shading_table->data[j]
                               [i * shading_table->width],
                               shading_table->width * sizeof(short));
                        ptr += aligned_width;
                }
        }

        IA_CSS_LEAVE_PRIVATE("void");
        return sctbl;
}

int ia_css_params_store_sctbl(
    const struct ia_css_pipeline_stage *stage,
    ia_css_ptr sc_tbl,
    const struct ia_css_shading_table  *sc_config)
{
        struct ia_css_host_data *isp_sc_tbl;

        IA_CSS_ENTER_PRIVATE("");

        if (!sc_config) {
                IA_CSS_LEAVE_PRIVATE("void");
                return 0;
        }

        isp_sc_tbl = ia_css_params_alloc_convert_sctbl(stage, sc_config);
        if (!isp_sc_tbl) {
                IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
                return -ENOMEM;
        }
        /* store the shading table to ddr */
        ia_css_params_store_ia_css_host_data(sc_tbl, isp_sc_tbl);
        ia_css_host_data_free(isp_sc_tbl);

        IA_CSS_LEAVE_PRIVATE("void");

        return 0;
}

static void
sh_css_enable_pipeline(const struct ia_css_binary *binary)
{
        if (!binary)
                return;

        IA_CSS_ENTER_PRIVATE("");

        ia_css_isp_param_enable_pipeline(&binary->mem_params);

        IA_CSS_LEAVE_PRIVATE("void");
}

static int
ia_css_process_zoom_and_motion(
    struct ia_css_isp_parameters *params,
    const struct ia_css_pipeline_stage *first_stage)
{
        /* first_stage can be  NULL */
        const struct ia_css_pipeline_stage *stage;
        int err = 0;
        struct ia_css_resolution pipe_in_res;

        pipe_in_res.width = 0;
        pipe_in_res.height = 0;

        assert(params);

        IA_CSS_ENTER_PRIVATE("");

        /* Go through all stages to udate uds and cropping */
        for (stage = first_stage; stage; stage = stage->next) {
                struct ia_css_binary *binary;
                /* note: the var below is made static as it is quite large;
                   if it is not static it ends up on the stack which could
                   cause issues for drivers
                */
                static struct ia_css_binary tmp_binary;

                const struct ia_css_binary_xinfo *info = NULL;

                binary = stage->binary;
                if (binary) {
                        info = binary->info;
                } else {
                        const struct sh_css_binary_args *args = &stage->args;
                        const struct ia_css_frame_info *out_infos[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};

                        out_infos[0] = ia_css_frame_get_info(args->out_frame[0]);

                        info = &stage->firmware->info.isp;
                        ia_css_binary_fill_info(info, false, false,
                                                ATOMISP_INPUT_FORMAT_RAW_10,
                                                ia_css_frame_get_info(args->in_frame),
                                                NULL,
                                                out_infos,
                                                ia_css_frame_get_info(args->out_vf_frame),
                                                &tmp_binary,
                                                NULL,
                                                -1, true);
                        binary = &tmp_binary;
                        binary->info = info;
                }

                if (stage == first_stage) {
                        /* we will use pipe_in_res to scale the zoom crop region if needed */
                        pipe_in_res = binary->effective_in_frame_res;
                }

                assert(stage->stage_num < SH_CSS_MAX_STAGES);
                if (params->dz_config.zoom_region.resolution.width == 0 &&
                    params->dz_config.zoom_region.resolution.height == 0) {
                        sh_css_update_uds_and_crop_info(
                            &info->sp,
                            &binary->in_frame_info,
                            &binary->out_frame_info[0],
                            &binary->dvs_envelope,
                            &params->dz_config,
                            &params->motion_config,
                            &params->uds[stage->stage_num].uds,
                            &params->uds[stage->stage_num].crop_pos,
                            stage->enable_zoom);
                } else {
                        err = sh_css_update_uds_and_crop_info_based_on_zoom_region(
                                  &info->sp,
                                  &binary->in_frame_info,
                                  &binary->out_frame_info[0],
                                  &binary->dvs_envelope,
                                  &params->dz_config,
                                  &params->motion_config,
                                  &params->uds[stage->stage_num].uds,
                                  &params->uds[stage->stage_num].crop_pos,
                                  pipe_in_res,
                                  stage->enable_zoom);
                        if (err)
                                return err;
                }
        }
        params->isp_params_changed = true;

        IA_CSS_LEAVE_PRIVATE("void");
        return err;
}

static void
sh_css_set_gamma_table(struct ia_css_isp_parameters *params,
                       const struct ia_css_gamma_table *table)
{
        if (!table)
                return;
        IA_CSS_ENTER_PRIVATE("table=%p", table);

        assert(params);
        params->gc_table = *table;
        params->config_changed[IA_CSS_GC_ID] = true;

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_get_gamma_table(const struct ia_css_isp_parameters *params,
                       struct ia_css_gamma_table *table)
{
        if (!table)
                return;
        IA_CSS_ENTER_PRIVATE("table=%p", table);

        assert(params);
        *table = params->gc_table;

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_set_ctc_table(struct ia_css_isp_parameters *params,
                     const struct ia_css_ctc_table *table)
{
        if (!table)
                return;

        IA_CSS_ENTER_PRIVATE("table=%p", table);

        assert(params);
        params->ctc_table = *table;
        params->config_changed[IA_CSS_CTC_ID] = true;

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_get_ctc_table(const struct ia_css_isp_parameters *params,
                     struct ia_css_ctc_table *table)
{
        if (!table)
                return;

        IA_CSS_ENTER_PRIVATE("table=%p", table);

        assert(params);
        *table = params->ctc_table;

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_set_macc_table(struct ia_css_isp_parameters *params,
                      const struct ia_css_macc_table *table)
{
        if (!table)
                return;

        IA_CSS_ENTER_PRIVATE("table=%p", table);

        assert(params);
        params->macc_table = *table;
        params->config_changed[IA_CSS_MACC_ID] = true;

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_get_macc_table(const struct ia_css_isp_parameters *params,
                      struct ia_css_macc_table *table)
{
        if (!table)
                return;

        IA_CSS_ENTER_PRIVATE("table=%p", table);

        assert(params);
        *table = params->macc_table;

        IA_CSS_LEAVE_PRIVATE("void");
}

void ia_css_morph_table_free(
    struct ia_css_morph_table *me)
{
        unsigned int i;

        if (!me)
                return;

        IA_CSS_ENTER("");

        for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) {
                if (me->coordinates_x[i]) {
                        kvfree(me->coordinates_x[i]);
                        me->coordinates_x[i] = NULL;
                }
                if (me->coordinates_y[i]) {
                        kvfree(me->coordinates_y[i]);
                        me->coordinates_y[i] = NULL;
                }
        }

        kvfree(me);
        IA_CSS_LEAVE("void");
}

struct ia_css_morph_table *ia_css_morph_table_allocate(
    unsigned int width,
    unsigned int height)
{
        unsigned int i;
        struct ia_css_morph_table *me;

        IA_CSS_ENTER("");

        me = kvmalloc_obj(*me);
        if (!me) {
                IA_CSS_ERROR("out of memory");
                return me;
        }

        for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) {
                me->coordinates_x[i] = NULL;
                me->coordinates_y[i] = NULL;
        }

        for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) {
                me->coordinates_x[i] = kvmalloc(height * width *
                                                sizeof(*me->coordinates_x[i]),
                                                GFP_KERNEL);
                me->coordinates_y[i] = kvmalloc(height * width *
                                                sizeof(*me->coordinates_y[i]),
                                                GFP_KERNEL);

                if ((!me->coordinates_x[i]) ||
                    (!me->coordinates_y[i])) {
                        ia_css_morph_table_free(me);
                        me = NULL;
                        return me;
                }
        }
        me->width = width;
        me->height = height;
        IA_CSS_LEAVE("");
        return me;
}

static int sh_css_params_default_morph_table(
    struct ia_css_morph_table **table,
    const struct ia_css_binary *binary)
{
        /* MW 2400 advanced requires different scaling */
        unsigned int i, j, k, step, width, height;
        short start_x[IA_CSS_MORPH_TABLE_NUM_PLANES] = { -8, 0, -8, 0, 0, -8 },
                start_y[IA_CSS_MORPH_TABLE_NUM_PLANES] = { 0, 0, -8, -8, -8, 0 };
        struct ia_css_morph_table *tab;

        assert(table);
        assert(binary);

        IA_CSS_ENTER_PRIVATE("");

        step = (ISP_VEC_NELEMS / 16) * 128;
        width = binary->morph_tbl_width;
        height = binary->morph_tbl_height;

        tab = ia_css_morph_table_allocate(width, height);
        if (!tab)
                return -ENOMEM;

        for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) {
                short val_y = start_y[i];

                for (j = 0; j < height; j++) {
                        short val_x = start_x[i];
                        unsigned short *x_ptr, *y_ptr;

                        x_ptr = &tab->coordinates_x[i][j * width];
                        y_ptr = &tab->coordinates_y[i][j * width];
                        for (k = 0; k < width;
                             k++, x_ptr++, y_ptr++, val_x += (short)step) {
                                if (k == 0)
                                        *x_ptr = 0;
                                else if (k == width - 1)
                                        *x_ptr = val_x + 2 * start_x[i];
                                else
                                        *x_ptr = val_x;
                                if (j == 0)
                                        *y_ptr = 0;
                                else
                                        *y_ptr = val_y;
                        }
                        val_y += (short)step;
                }
        }
        *table = tab;

        IA_CSS_LEAVE_ERR_PRIVATE(0);

        return 0;
}

static void
sh_css_set_morph_table(struct ia_css_isp_parameters *params,
                       const struct ia_css_morph_table *table)
{
        if (!table)
                return;

        IA_CSS_ENTER_PRIVATE("table=%p", table);

        assert(params);
        if (table->enable == false)
                table = NULL;
        params->morph_table = table;
        params->morph_table_changed = true;
        IA_CSS_LEAVE_PRIVATE("void");
}

void
ia_css_translate_3a_statistics(
    struct ia_css_3a_statistics               *host_stats,
    const struct ia_css_isp_3a_statistics_map *isp_stats)
{
        IA_CSS_ENTER("");
        if (host_stats->grid.use_dmem) {
                IA_CSS_LOG("3A: DMEM");
                ia_css_s3a_dmem_decode(host_stats, isp_stats->dmem_stats);
        } else {
                IA_CSS_LOG("3A: VMEM");
                ia_css_s3a_vmem_decode(host_stats, isp_stats->vmem_stats_hi,
                                       isp_stats->vmem_stats_lo);
        }
        IA_CSS_LOG("3A: HMEM");
        ia_css_s3a_hmem_decode(host_stats, isp_stats->hmem_stats);

        IA_CSS_LEAVE("void");
}

void
ia_css_isp_3a_statistics_map_free(struct ia_css_isp_3a_statistics_map *me)
{
        if (me) {
                if (me->data_allocated) {
                        kvfree(me->data_ptr);
                        me->data_ptr = NULL;
                        me->data_allocated = false;
                }
                kvfree(me);
        }
}

struct ia_css_isp_3a_statistics_map *
ia_css_isp_3a_statistics_map_allocate(
    const struct ia_css_isp_3a_statistics *isp_stats,
    void *data_ptr)
{
        struct ia_css_isp_3a_statistics_map *me;
        /* Windows compiler does not like adding sizes to a void *
         * so we use a local char * instead. */
        char *base_ptr;

        me = kvmalloc_obj(*me);
        if (!me) {
                IA_CSS_LEAVE("cannot allocate memory");
                goto err;
        }

        me->data_ptr = data_ptr;
        me->data_allocated = !data_ptr;
        if (!data_ptr) {
                me->data_ptr = kvmalloc(isp_stats->size, GFP_KERNEL);
                if (!me->data_ptr) {
                        IA_CSS_LEAVE("cannot allocate memory");
                        goto err;
                }
        }
        base_ptr = me->data_ptr;

        me->size = isp_stats->size;
        /* GCC complains when we assign a char * to a void *, so these
         * casts are necessary unfortunately. */
        me->dmem_stats    = (void *)base_ptr;
        me->vmem_stats_hi = (void *)(base_ptr + isp_stats->dmem_size);
        me->vmem_stats_lo = (void *)(base_ptr + isp_stats->dmem_size +
                                     isp_stats->vmem_size);
        me->hmem_stats    = (void *)(base_ptr + isp_stats->dmem_size +
                                     2 * isp_stats->vmem_size);

        IA_CSS_LEAVE("map=%p", me);
        return me;

err:
        kvfree(me);
        return NULL;
}

int
ia_css_get_3a_statistics(struct ia_css_3a_statistics           *host_stats,
                         const struct ia_css_isp_3a_statistics *isp_stats)
{
        struct ia_css_isp_3a_statistics_map *map;
        int ret = 0;

        IA_CSS_ENTER("host_stats=%p, isp_stats=%p", host_stats, isp_stats);

        assert(host_stats);
        assert(isp_stats);

        map = ia_css_isp_3a_statistics_map_allocate(isp_stats, NULL);
        if (map) {
                hmm_load(isp_stats->data_ptr, map->data_ptr, isp_stats->size);
                ia_css_translate_3a_statistics(host_stats, map);
                ia_css_isp_3a_statistics_map_free(map);
        } else {
                IA_CSS_ERROR("out of memory");
                ret = -ENOMEM;
        }

        IA_CSS_LEAVE_ERR(ret);
        return ret;
}

/* Parameter encoding is not yet orthogonal.
   This function hnadles some of the exceptions.
*/
static void
ia_css_set_param_exceptions(const struct ia_css_pipe *pipe,
                            struct ia_css_isp_parameters *params)
{
        assert(params);

        /* Copy also to DP. Should be done by the driver. */
        params->dp_config.gr = params->wb_config.gr;
        params->dp_config.r  = params->wb_config.r;
        params->dp_config.b  = params->wb_config.b;
        params->dp_config.gb = params->wb_config.gb;
}

static void
sh_css_set_nr_config(struct ia_css_isp_parameters *params,
                     const struct ia_css_nr_config *config)
{
        if (!config)
                return;
        assert(params);

        IA_CSS_ENTER_PRIVATE("config=%p", config);

        ia_css_nr_debug_dtrace(config, IA_CSS_DEBUG_TRACE_PRIVATE);
        params->nr_config = *config;
        params->yee_config.nr = *config;
        params->config_changed[IA_CSS_NR_ID]  = true;
        params->config_changed[IA_CSS_YEE_ID] = true;
        params->config_changed[IA_CSS_BNR_ID] = true;

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_set_ee_config(struct ia_css_isp_parameters *params,
                     const struct ia_css_ee_config *config)
{
        if (!config)
                return;
        assert(params);

        IA_CSS_ENTER_PRIVATE("config=%p", config);
        ia_css_ee_debug_dtrace(config, IA_CSS_DEBUG_TRACE_PRIVATE);

        params->ee_config = *config;
        params->yee_config.ee = *config;
        params->config_changed[IA_CSS_YEE_ID] = true;

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_get_ee_config(const struct ia_css_isp_parameters *params,
                     struct ia_css_ee_config *config)
{
        if (!config)
                return;

        IA_CSS_ENTER_PRIVATE("config=%p", config);

        assert(params);
        *config = params->ee_config;

        ia_css_ee_debug_dtrace(config, IA_CSS_DEBUG_TRACE_PRIVATE);
        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_set_pipe_dvs_6axis_config(const struct ia_css_pipe *pipe,
                                 struct ia_css_isp_parameters *params,
                                 const struct ia_css_dvs_6axis_config  *dvs_config)
{
        if (!dvs_config)
                return;
        assert(params);
        assert(pipe);
        assert(dvs_config->height_y == dvs_config->height_uv);
        assert((dvs_config->width_y - 1) == 2 * (dvs_config->width_uv - 1));
        assert(pipe->mode < IA_CSS_PIPE_ID_NUM);

        IA_CSS_ENTER_PRIVATE("dvs_config=%p", dvs_config);

        copy_dvs_6axis_table(params->pipe_dvs_6axis_config[pipe->mode], dvs_config);

        params->pipe_dvs_6axis_config_changed[pipe->mode] = true;

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_get_pipe_dvs_6axis_config(const struct ia_css_pipe *pipe,
                                 const struct ia_css_isp_parameters *params,
                                 struct ia_css_dvs_6axis_config *dvs_config)
{
        if (!dvs_config)
                return;
        assert(params);
        assert(pipe);
        assert(dvs_config->height_y == dvs_config->height_uv);
        assert((dvs_config->width_y - 1) == 2 * dvs_config->width_uv - 1);

        IA_CSS_ENTER_PRIVATE("dvs_config=%p", dvs_config);

        if ((pipe->mode < IA_CSS_PIPE_ID_NUM) &&
            (dvs_config->width_y == params->pipe_dvs_6axis_config[pipe->mode]->width_y) &&
            (dvs_config->height_y == params->pipe_dvs_6axis_config[pipe->mode]->height_y) &&
            (dvs_config->width_uv == params->pipe_dvs_6axis_config[pipe->mode]->width_uv) &&
            (dvs_config->height_uv == params->pipe_dvs_6axis_config[pipe->mode]->height_uv)
            &&
            dvs_config->xcoords_y &&
            dvs_config->ycoords_y &&
            dvs_config->xcoords_uv &&
            dvs_config->ycoords_uv) {
                copy_dvs_6axis_table(dvs_config, params->pipe_dvs_6axis_config[pipe->mode]);
        }

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_set_baa_config(struct ia_css_isp_parameters *params,
                      const struct ia_css_aa_config *config)
{
        if (!config)
                return;
        assert(params);

        IA_CSS_ENTER_PRIVATE("config=%p", config);

        params->bds_config = *config;
        params->config_changed[IA_CSS_BDS_ID] = true;

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_get_baa_config(const struct ia_css_isp_parameters *params,
                      struct ia_css_aa_config *config)
{
        if (!config)
                return;
        assert(params);

        IA_CSS_ENTER_PRIVATE("config=%p", config);

        *config = params->bds_config;

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_set_dz_config(struct ia_css_isp_parameters *params,
                     const struct ia_css_dz_config *config)
{
        if (!config)
                return;
        assert(params);

        IA_CSS_ENTER_PRIVATE("dx=%d, dy=%d", config->dx, config->dy);

        assert(config->dx <= HRT_GDC_N);
        assert(config->dy <= HRT_GDC_N);

        params->dz_config = *config;
        params->dz_config_changed = true;
        /* JK: Why isp params changed?? */
        params->isp_params_changed = true;

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_get_dz_config(const struct ia_css_isp_parameters *params,
                     struct ia_css_dz_config *config)
{
        if (!config)
                return;
        assert(params);

        IA_CSS_ENTER_PRIVATE("config=%p", config);

        *config = params->dz_config;

        IA_CSS_LEAVE_PRIVATE("dx=%d, dy=%d", config->dx, config->dy);
}

static void
sh_css_set_motion_vector(struct ia_css_isp_parameters *params,
                         const struct ia_css_vector *motion)
{
        if (!motion)
                return;
        assert(params);

        IA_CSS_ENTER_PRIVATE("x=%d, y=%d", motion->x, motion->y);

        params->motion_config = *motion;
        /* JK: Why do isp params change? */
        params->motion_config_changed = true;
        params->isp_params_changed = true;

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
sh_css_get_motion_vector(const struct ia_css_isp_parameters *params,
                         struct ia_css_vector *motion)
{
        if (!motion)
                return;
        assert(params);

        IA_CSS_ENTER_PRIVATE("motion=%p", motion);

        *motion = params->motion_config;

        IA_CSS_LEAVE_PRIVATE("x=%d, y=%d", motion->x, motion->y);
}

struct ia_css_isp_config *
sh_css_pipe_isp_config_get(struct ia_css_pipe *pipe)
{
        if (!pipe) {
                IA_CSS_ERROR("pipe=%p", NULL);
                return NULL;
        }
        return pipe->config.p_isp_config;
}

int
ia_css_stream_set_isp_config(
    struct ia_css_stream *stream,
    const struct ia_css_isp_config *config)
{
        return ia_css_stream_set_isp_config_on_pipe(stream, config, NULL);
}

int
ia_css_stream_set_isp_config_on_pipe(
    struct ia_css_stream *stream,
    const struct ia_css_isp_config *config,
    struct ia_css_pipe *pipe)
{
        int err = 0;

        if ((!stream) || (!config))
                return -EINVAL;

        IA_CSS_ENTER("stream=%p, config=%p, pipe=%p", stream, config, pipe);

        if (config->output_frame)
                err = sh_css_set_per_frame_isp_config_on_pipe(stream, config, pipe);
        else
                err = sh_css_set_global_isp_config_on_pipe(stream->pipes[0], config, pipe);

        IA_CSS_LEAVE_ERR(err);
        return err;
}

int
ia_css_pipe_set_isp_config(struct ia_css_pipe *pipe,
                           struct ia_css_isp_config *config)
{
        struct ia_css_pipe *pipe_in = pipe;
        int err = 0;

        IA_CSS_ENTER("pipe=%p", pipe);

        if ((!pipe) || (!pipe->stream))
                return -EINVAL;

        ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "config=%p\n", config);

        if (config->output_frame)
                err = sh_css_set_per_frame_isp_config_on_pipe(pipe->stream, config, pipe);
        else
                err = sh_css_set_global_isp_config_on_pipe(pipe, config, pipe_in);
        IA_CSS_LEAVE_ERR(err);
        return err;
}

static int
sh_css_set_global_isp_config_on_pipe(
    struct ia_css_pipe *curr_pipe,
    const struct ia_css_isp_config *config,
    struct ia_css_pipe *pipe)
{
        int err = 0;
        int err1 = 0;
        int err2 = 0;

        IA_CSS_ENTER_PRIVATE("stream=%p, config=%p, pipe=%p", curr_pipe, config, pipe);

        err1 = sh_css_init_isp_params_from_config(curr_pipe, curr_pipe->stream->isp_params_configs, config, pipe);

        /* Now commit all changes to the SP */
        err2 = sh_css_param_update_isp_params(curr_pipe, curr_pipe->stream->isp_params_configs, sh_css_sp_is_running(), pipe);

        /* The following code is intentional. The sh_css_init_isp_params_from_config interface
         * throws an error when both DPC and BDS is enabled. The CSS API must pass this error
         * information to the caller, ie. the host. We do not return this error immediately,
         * but instead continue with updating the ISP params to enable testing of features
         * which are currently in TR phase. */

        err = (err1 != 0) ? err1 : ((err2 != 0) ? err2 : err);

        IA_CSS_LEAVE_ERR_PRIVATE(err);
        return err;
}

static int
sh_css_set_per_frame_isp_config_on_pipe(
    struct ia_css_stream *stream,
    const struct ia_css_isp_config *config,
    struct ia_css_pipe *pipe)
{
        unsigned int i;
        bool per_frame_config_created = false;
        int err = 0;
        int err1 = 0;
        int err2 = 0;
        int err3 = 0;

        struct sh_css_ddr_address_map *ddr_ptrs;
        struct sh_css_ddr_address_map_size *ddr_ptrs_size;
        struct ia_css_isp_parameters *params;

        IA_CSS_ENTER_PRIVATE("stream=%p, config=%p, pipe=%p", stream, config, pipe);

        if (!pipe) {
                err = -EINVAL;
                goto exit;
        }

        /* create per-frame ISP params object with default values
         * from stream->isp_params_configs if one doesn't already exist
        */
        if (!stream->per_frame_isp_params_configs) {
                err = sh_css_create_isp_params(stream,
                                               &stream->per_frame_isp_params_configs);
                if (err)
                        goto exit;
                per_frame_config_created = true;
        }

        params = stream->per_frame_isp_params_configs;

        /* update new ISP params object with the new config */
        if (!sh_css_init_isp_params_from_global(stream, params, false, pipe)) {
                err1 = -EINVAL;
        }

        err2 = sh_css_init_isp_params_from_config(stream->pipes[0], params, config, pipe);

        if (per_frame_config_created) {
                ddr_ptrs = &params->ddr_ptrs;
                ddr_ptrs_size = &params->ddr_ptrs_size;
                /* create per pipe reference to general ddr_ptrs */
                for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
                        ref_sh_css_ddr_address_map(ddr_ptrs, &params->pipe_ddr_ptrs[i]);
                        params->pipe_ddr_ptrs_size[i] = *ddr_ptrs_size;
                }
        }

        /* now commit to ddr */
        err3 = sh_css_param_update_isp_params(stream->pipes[0], params, sh_css_sp_is_running(), pipe);

        /* The following code is intentional. The sh_css_init_sp_params_from_config and
         * sh_css_init_isp_params_from_config throws an error when both DPC and BDS is enabled.
         * The CSS API must pass this error information to the caller, ie. the host.
         * We do not return this error immediately, but instead continue with updating the ISP params
         *  to enable testing of features which are currently in TR phase. */
        err = (err1 != 0) ? err1 :
              (err2 != 0) ? err2 :
              (err3 != 0) ? err3 : err;
exit:
        IA_CSS_LEAVE_ERR_PRIVATE(err);
        return err;
}

static int
sh_css_init_isp_params_from_config(struct ia_css_pipe *pipe,
                                   struct ia_css_isp_parameters *params,
                                   const struct ia_css_isp_config *config,
                                   struct ia_css_pipe *pipe_in)
{
        int err = 0;
        bool is_dp_10bpp = true;

        assert(pipe);

        IA_CSS_ENTER_PRIVATE("pipe=%p, config=%p, params=%p", pipe, config, params);

        ia_css_set_configs(params, config);

        sh_css_set_nr_config(params, config->nr_config);
        sh_css_set_ee_config(params, config->ee_config);
        sh_css_set_baa_config(params, config->baa_config);
        if ((pipe->mode < IA_CSS_PIPE_ID_NUM) &&
            (params->pipe_dvs_6axis_config[pipe->mode]))
                sh_css_set_pipe_dvs_6axis_config(pipe, params, config->dvs_6axis_config);
        sh_css_set_dz_config(params, config->dz_config);
        sh_css_set_motion_vector(params, config->motion_vector);
        sh_css_set_shading_table(pipe->stream, params, config->shading_table);
        sh_css_set_morph_table(params, config->morph_table);
        sh_css_set_macc_table(params, config->macc_table);
        sh_css_set_gamma_table(params, config->gamma_table);
        sh_css_set_ctc_table(params, config->ctc_table);
        /* ------ deprecated(bz675) : from ------ */
        sh_css_set_shading_settings(params, config->shading_settings);
        /* ------ deprecated(bz675) : to ------ */

        params->dis_coef_table_changed = (config->dvs_coefs);
        params->dvs2_coef_table_changed = (config->dvs2_coefs);

        params->output_frame = config->output_frame;
        params->isp_parameters_id = config->isp_config_id;

        if (0 ==
            sh_css_select_dp_10bpp_config(pipe, &is_dp_10bpp)) {
                /* return an error when both DPC and BDS is enabled by the
                 * user. */
                /* we do not exit from this point immediately to allow internal
                 * firmware feature testing. */
                if (is_dp_10bpp) {
                        err = -EINVAL;
                }
        } else {
                err = -EINVAL;
                goto exit;
        }

        ia_css_set_param_exceptions(pipe, params);

exit:
        IA_CSS_LEAVE_ERR_PRIVATE(err);
        return err;
}

void
ia_css_stream_get_isp_config(
    const struct ia_css_stream *stream,
    struct ia_css_isp_config *config)
{
        IA_CSS_ENTER("void");
        ia_css_pipe_get_isp_config(stream->pipes[0], config);
        IA_CSS_LEAVE("void");
}

void
ia_css_pipe_get_isp_config(struct ia_css_pipe *pipe,
                           struct ia_css_isp_config *config)
{
        struct ia_css_isp_parameters *params = NULL;

        assert(config);

        IA_CSS_ENTER("config=%p", config);

        params = pipe->stream->isp_params_configs;
        assert(params);

        ia_css_get_configs(params, config);

        sh_css_get_ee_config(params, config->ee_config);
        sh_css_get_baa_config(params, config->baa_config);
        sh_css_get_pipe_dvs_6axis_config(pipe, params, config->dvs_6axis_config);
        sh_css_get_macc_table(params, config->macc_table);
        sh_css_get_gamma_table(params, config->gamma_table);
        sh_css_get_ctc_table(params, config->ctc_table);
        sh_css_get_dz_config(params, config->dz_config);
        sh_css_get_motion_vector(params, config->motion_vector);
        /* ------ deprecated(bz675) : from ------ */
        sh_css_get_shading_settings(params, config->shading_settings);
        /* ------ deprecated(bz675) : to ------ */

        config->output_frame = params->output_frame;
        config->isp_config_id = params->isp_parameters_id;

        IA_CSS_LEAVE("void");
}

/*
 * coding style says the return of "mmgr_NULL" is the error signal
 *
 * Deprecated: Implement mmgr_realloc()
 */
static bool realloc_isp_css_mm_buf(
    ia_css_ptr *curr_buf,
    size_t *curr_size,
    size_t needed_size,
    bool force,
    int *err)
{
        s32 id;

        *err = 0;
        /* Possible optimization: add a function sh_css_isp_css_mm_realloc()
         * and implement on top of hmm. */

        IA_CSS_ENTER_PRIVATE("void");

        if (!force && *curr_size >= needed_size) {
                IA_CSS_LEAVE_PRIVATE("false");
                return false;
        }
        /* don't reallocate if single ref to buffer and same size */
        if (*curr_size == needed_size && ia_css_refcount_is_single(*curr_buf)) {
                IA_CSS_LEAVE_PRIVATE("false");
                return false;
        }

        id = IA_CSS_REFCOUNT_PARAM_BUFFER;
        ia_css_refcount_decrement(id, *curr_buf);
        *curr_buf = ia_css_refcount_increment(id, hmm_alloc(needed_size));
        if (!*curr_buf) {
                *err = -ENOMEM;
                *curr_size = 0;
        } else {
                *curr_size = needed_size;
        }
        IA_CSS_LEAVE_PRIVATE("true");
        return true;
}

static bool reallocate_buffer(
    ia_css_ptr *curr_buf,
    size_t *curr_size,
    size_t needed_size,
    bool force,
    int *err)
{
        bool ret;

        IA_CSS_ENTER_PRIVATE("void");

        ret = realloc_isp_css_mm_buf(curr_buf,
                                     curr_size, needed_size, force, err);

        IA_CSS_LEAVE_PRIVATE("ret=%d", ret);
        return ret;
}

struct ia_css_isp_3a_statistics *
ia_css_isp_3a_statistics_allocate(const struct ia_css_3a_grid_info *grid)
{
        struct ia_css_isp_3a_statistics *me;

        IA_CSS_ENTER("grid=%p", grid);

        assert(grid);

        /* MW: Does "grid->enable" also control the histogram output ?? */
        if (!grid->enable)
                return NULL;

        me = kvzalloc_objs(*me, 1);
        if (!me)
                goto err;

        if (grid->use_dmem) {
                me->dmem_size = sizeof(struct ia_css_3a_output) *
                                grid->aligned_width *
                                grid->aligned_height;
        } else {
                me->vmem_size = ISP_S3ATBL_HI_LO_STRIDE_BYTES *
                                grid->aligned_height;
        }
        me->hmem_size = sizeof_hmem(HMEM0_ID);

        /* All subsections need to be aligned to the system bus width */
        me->dmem_size = CEIL_MUL(me->dmem_size, HIVE_ISP_DDR_WORD_BYTES);
        me->vmem_size = CEIL_MUL(me->vmem_size, HIVE_ISP_DDR_WORD_BYTES);
        me->hmem_size = CEIL_MUL(me->hmem_size, HIVE_ISP_DDR_WORD_BYTES);

        me->size = me->dmem_size + me->vmem_size * 2 + me->hmem_size;
        me->data_ptr = hmm_alloc(me->size);
        if (me->data_ptr == mmgr_NULL) {
                kvfree(me);
                me = NULL;
                goto err;
        }
        if (me->dmem_size)
                me->data.dmem.s3a_tbl = me->data_ptr;
        if (me->vmem_size) {
                me->data.vmem.s3a_tbl_hi = me->data_ptr + me->dmem_size;
                me->data.vmem.s3a_tbl_lo = me->data_ptr + me->dmem_size + me->vmem_size;
        }
        if (me->hmem_size)
                me->data_hmem.rgby_tbl = me->data_ptr + me->dmem_size + 2 * me->vmem_size;

err:
        IA_CSS_LEAVE("return=%p", me);
        return me;
}

void
ia_css_isp_3a_statistics_free(struct ia_css_isp_3a_statistics *me)
{
        if (me) {
                hmm_free(me->data_ptr);
                kvfree(me);
        }
}

struct ia_css_isp_skc_dvs_statistics *ia_css_skc_dvs_statistics_allocate(void)
{
        return NULL;
}

struct ia_css_metadata *
ia_css_metadata_allocate(const struct ia_css_metadata_info *metadata_info)
{
        struct ia_css_metadata *md = NULL;

        IA_CSS_ENTER("");

        if (metadata_info->size == 0)
                return NULL;

        md = kvmalloc_obj(*md);
        if (!md)
                goto error;

        md->info = *metadata_info;
        md->exp_id = 0;
        md->address = hmm_alloc(metadata_info->size);
        if (md->address == mmgr_NULL)
                goto error;

        IA_CSS_LEAVE("return=%p", md);
        return md;

error:
        ia_css_metadata_free(md);
        IA_CSS_LEAVE("return=%p", NULL);
        return NULL;
}

void
ia_css_metadata_free(struct ia_css_metadata *me)
{
        if (me) {
                /* The enter and leave macros are placed inside
                 * the condition to avoid false logging of metadata
                 * free events when metadata is disabled.
                 * We found this to be confusing during development
                 * and debugging. */
                IA_CSS_ENTER("me=%p", me);
                hmm_free(me->address);
                kvfree(me);
                IA_CSS_LEAVE("void");
        }
}

void
ia_css_metadata_free_multiple(unsigned int num_bufs,
                              struct ia_css_metadata **bufs)
{
        unsigned int i;

        if (bufs) {
                for (i = 0; i < num_bufs; i++)
                        ia_css_metadata_free(bufs[i]);
        }
}

static unsigned int g_param_buffer_dequeue_count;
static unsigned int g_param_buffer_enqueue_count;

int
ia_css_stream_isp_parameters_init(struct ia_css_stream *stream)
{
        int err = 0;
        unsigned int i;
        struct sh_css_ddr_address_map *ddr_ptrs;
        struct sh_css_ddr_address_map_size *ddr_ptrs_size;
        struct ia_css_isp_parameters *params;

        assert(stream);
        IA_CSS_ENTER_PRIVATE("void");

        if (!stream) {
                IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
                return -EINVAL;
        }
        /* TMP: tracking of paramsets */
        g_param_buffer_dequeue_count = 0;
        g_param_buffer_enqueue_count = 0;

        stream->per_frame_isp_params_configs = NULL;
        err = sh_css_create_isp_params(stream,
                                       &stream->isp_params_configs);
        if (err)
                goto ERR;

        params = stream->isp_params_configs;
        if (!sh_css_init_isp_params_from_global(stream, params, true, NULL)) {
                /* we do not return the error immediately to enable internal
                 * firmware feature testing */
                err = -EINVAL;
        }

        ddr_ptrs = &params->ddr_ptrs;
        ddr_ptrs_size = &params->ddr_ptrs_size;

        /* create per pipe reference to general ddr_ptrs */
        for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
                ref_sh_css_ddr_address_map(ddr_ptrs, &params->pipe_ddr_ptrs[i]);
                params->pipe_ddr_ptrs_size[i] = *ddr_ptrs_size;
        }

ERR:
        IA_CSS_LEAVE_ERR_PRIVATE(err);
        return err;
}

static void
ia_css_set_sdis_config(
    struct ia_css_isp_parameters *params,
    const struct ia_css_dvs_coefficients *dvs_coefs)
{
        ia_css_set_sdis_horicoef_config(params, dvs_coefs);
        ia_css_set_sdis_vertcoef_config(params, dvs_coefs);
        ia_css_set_sdis_horiproj_config(params, dvs_coefs);
        ia_css_set_sdis_vertproj_config(params, dvs_coefs);
}

static void
ia_css_set_sdis2_config(
    struct ia_css_isp_parameters *params,
    const struct ia_css_dvs2_coefficients *dvs2_coefs)
{
        ia_css_set_sdis2_horicoef_config(params, dvs2_coefs);
        ia_css_set_sdis2_vertcoef_config(params, dvs2_coefs);
        ia_css_set_sdis2_horiproj_config(params, dvs2_coefs);
        ia_css_set_sdis2_vertproj_config(params, dvs2_coefs);
}

static int
sh_css_create_isp_params(struct ia_css_stream *stream,
                         struct ia_css_isp_parameters **isp_params_out)
{
        bool succ = true;
        unsigned int i;
        struct sh_css_ddr_address_map *ddr_ptrs;
        struct sh_css_ddr_address_map_size *ddr_ptrs_size;
        int err;
        size_t params_size;
        struct ia_css_isp_parameters *params =
        kvmalloc_obj(struct ia_css_isp_parameters);

        if (!params) {
                *isp_params_out = NULL;
                err = -ENOMEM;
                IA_CSS_ERROR("%s:%d error: cannot allocate memory", __FILE__, __LINE__);
                IA_CSS_LEAVE_ERR_PRIVATE(err);
                return err;
        } else {
                memset(params, 0, sizeof(struct ia_css_isp_parameters));
        }

        ddr_ptrs = &params->ddr_ptrs;
        ddr_ptrs_size = &params->ddr_ptrs_size;

        for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
                memset(&params->pipe_ddr_ptrs[i], 0,
                       sizeof(params->pipe_ddr_ptrs[i]));
                memset(&params->pipe_ddr_ptrs_size[i], 0,
                       sizeof(params->pipe_ddr_ptrs_size[i]));
        }

        memset(ddr_ptrs, 0, sizeof(*ddr_ptrs));
        memset(ddr_ptrs_size, 0, sizeof(*ddr_ptrs_size));

        params_size = sizeof(params->uds);
        ddr_ptrs_size->isp_param = params_size;
        ddr_ptrs->isp_param =
        ia_css_refcount_increment(IA_CSS_REFCOUNT_PARAM_BUFFER,
                                  hmm_alloc(params_size));
        succ &= (ddr_ptrs->isp_param != mmgr_NULL);

        ddr_ptrs_size->macc_tbl = sizeof(struct ia_css_macc_table);
        ddr_ptrs->macc_tbl =
        ia_css_refcount_increment(IA_CSS_REFCOUNT_PARAM_BUFFER,
                                  hmm_alloc(sizeof(struct ia_css_macc_table)));
        succ &= (ddr_ptrs->macc_tbl != mmgr_NULL);

        *isp_params_out = params;

        if (!succ)
                return -ENOMEM;

        return 0;
}

static bool
sh_css_init_isp_params_from_global(struct ia_css_stream *stream,
                                   struct ia_css_isp_parameters *params,
                                   bool use_default_config,
                                   struct ia_css_pipe *pipe_in)
{
        bool retval = true;
        int i = 0;
        bool is_dp_10bpp = true;
        unsigned int isp_pipe_version = ia_css_pipe_get_isp_pipe_version(
                                            stream->pipes[0]);
        struct ia_css_isp_parameters *stream_params = stream->isp_params_configs;

        if (!use_default_config && !stream_params) {
                retval = false;
                goto exit;
        }

        params->output_frame = NULL;
        params->isp_parameters_id = 0;

        if (use_default_config) {
                ia_css_set_xnr3_config(params, &default_xnr3_config);

                sh_css_set_nr_config(params, &default_nr_config);
                sh_css_set_ee_config(params, &default_ee_config);
                if (isp_pipe_version == SH_CSS_ISP_PIPE_VERSION_1)
                        sh_css_set_macc_table(params, &default_macc_table);
                else if (isp_pipe_version == SH_CSS_ISP_PIPE_VERSION_2_2)
                        sh_css_set_macc_table(params, &default_macc2_table);
                sh_css_set_gamma_table(params, &default_gamma_table);
                sh_css_set_ctc_table(params, &default_ctc_table);
                sh_css_set_baa_config(params, &default_baa_config);
                sh_css_set_dz_config(params, &default_dz_config);
                /* ------ deprecated(bz675) : from ------ */
                sh_css_set_shading_settings(params, &default_shading_settings);
                /* ------ deprecated(bz675) : to ------ */

                ia_css_set_s3a_config(params, &default_3a_config);
                ia_css_set_wb_config(params, &default_wb_config);
                ia_css_set_csc_config(params, &default_cc_config);
                ia_css_set_tnr_config(params, &default_tnr_config);
                ia_css_set_ob_config(params, &default_ob_config);
                ia_css_set_dp_config(params, &default_dp_config);

                ia_css_set_param_exceptions(pipe_in, params);

                ia_css_set_de_config(params, &default_de_config);
                ia_css_set_gc_config(params, &default_gc_config);
                ia_css_set_anr_config(params, &default_anr_config);
                ia_css_set_anr2_config(params, &default_anr_thres);
                ia_css_set_ce_config(params, &default_ce_config);
                ia_css_set_xnr_table_config(params, &default_xnr_table);
                ia_css_set_ecd_config(params, &default_ecd_config);
                ia_css_set_ynr_config(params, &default_ynr_config);
                ia_css_set_fc_config(params, &default_fc_config);
                ia_css_set_cnr_config(params, &default_cnr_config);
                ia_css_set_macc_config(params, &default_macc_config);
                ia_css_set_ctc_config(params, &default_ctc_config);
                ia_css_set_aa_config(params, &default_aa_config);
                ia_css_set_r_gamma_config(params, &default_r_gamma_table);
                ia_css_set_g_gamma_config(params, &default_g_gamma_table);
                ia_css_set_b_gamma_config(params, &default_b_gamma_table);
                ia_css_set_yuv2rgb_config(params, &default_yuv2rgb_cc_config);
                ia_css_set_rgb2yuv_config(params, &default_rgb2yuv_cc_config);
                ia_css_set_xnr_config(params, &default_xnr_config);
                ia_css_set_sdis_config(params, &default_sdis_config);
                ia_css_set_sdis2_config(params, &default_sdis2_config);
                ia_css_set_formats_config(params, &default_formats_config);

                params->fpn_config.data = NULL;
                params->config_changed[IA_CSS_FPN_ID] = true;
                params->fpn_config.enabled = 0;

                params->motion_config = default_motion_config;
                params->motion_config_changed = true;

                params->morph_table = NULL;
                params->morph_table_changed = true;

                params->sc_table = NULL;
                params->sc_table_changed = true;

                ia_css_sdis2_clear_coefficients(&params->dvs2_coefs);
                params->dvs2_coef_table_changed = true;

                ia_css_sdis_clear_coefficients(&params->dvs_coefs);
                params->dis_coef_table_changed = true;
        } else {
                ia_css_set_xnr3_config(params, &stream_params->xnr3_config);

                sh_css_set_nr_config(params, &stream_params->nr_config);
                sh_css_set_ee_config(params, &stream_params->ee_config);
                if (isp_pipe_version == SH_CSS_ISP_PIPE_VERSION_1)
                        sh_css_set_macc_table(params, &stream_params->macc_table);
                else if (isp_pipe_version == SH_CSS_ISP_PIPE_VERSION_2_2)
                        sh_css_set_macc_table(params, &stream_params->macc_table);
                sh_css_set_gamma_table(params, &stream_params->gc_table);
                sh_css_set_ctc_table(params, &stream_params->ctc_table);
                sh_css_set_baa_config(params, &stream_params->bds_config);
                sh_css_set_dz_config(params, &stream_params->dz_config);
                /* ------ deprecated(bz675) : from ------ */
                sh_css_set_shading_settings(params, &stream_params->shading_settings);
                /* ------ deprecated(bz675) : to ------ */

                ia_css_set_s3a_config(params, &stream_params->s3a_config);
                ia_css_set_wb_config(params, &stream_params->wb_config);
                ia_css_set_csc_config(params, &stream_params->cc_config);
                ia_css_set_tnr_config(params, &stream_params->tnr_config);
                ia_css_set_ob_config(params, &stream_params->ob_config);
                ia_css_set_dp_config(params, &stream_params->dp_config);
                ia_css_set_de_config(params, &stream_params->de_config);
                ia_css_set_gc_config(params, &stream_params->gc_config);
                ia_css_set_anr_config(params, &stream_params->anr_config);
                ia_css_set_anr2_config(params, &stream_params->anr_thres);
                ia_css_set_ce_config(params, &stream_params->ce_config);
                ia_css_set_xnr_table_config(params, &stream_params->xnr_table);
                ia_css_set_ecd_config(params, &stream_params->ecd_config);
                ia_css_set_ynr_config(params, &stream_params->ynr_config);
                ia_css_set_fc_config(params, &stream_params->fc_config);
                ia_css_set_cnr_config(params, &stream_params->cnr_config);
                ia_css_set_macc_config(params, &stream_params->macc_config);
                ia_css_set_ctc_config(params, &stream_params->ctc_config);
                ia_css_set_aa_config(params, &stream_params->aa_config);
                ia_css_set_r_gamma_config(params, &stream_params->r_gamma_table);
                ia_css_set_g_gamma_config(params, &stream_params->g_gamma_table);
                ia_css_set_b_gamma_config(params, &stream_params->b_gamma_table);
                ia_css_set_yuv2rgb_config(params, &stream_params->yuv2rgb_cc_config);
                ia_css_set_rgb2yuv_config(params, &stream_params->rgb2yuv_cc_config);
                ia_css_set_xnr_config(params, &stream_params->xnr_config);
                ia_css_set_formats_config(params, &stream_params->formats_config);

                for (i = 0; i < stream->num_pipes; i++) {
                        if (0 ==
                            sh_css_select_dp_10bpp_config(stream->pipes[i], &is_dp_10bpp)) {
                                /* set the return value as false if both DPC and
                                 * BDS is enabled by the user. But we do not return
                                 * the value immediately to enable internal firmware
                                 * feature testing. */
                                retval = !is_dp_10bpp;
                                /* FIXME: should it ignore this error? */
                        } else {
                                retval = false;
                                goto exit;
                        }
                }

                ia_css_set_param_exceptions(pipe_in, params);

                params->fpn_config.data = stream_params->fpn_config.data;
                params->config_changed[IA_CSS_FPN_ID] =
                    stream_params->config_changed[IA_CSS_FPN_ID];
                params->fpn_config.enabled = stream_params->fpn_config.enabled;

                sh_css_set_motion_vector(params, &stream_params->motion_config);
                sh_css_set_morph_table(params, stream_params->morph_table);

                if (stream_params->sc_table) {
                        sh_css_set_shading_table(stream, params, stream_params->sc_table);
                } else {
                        params->sc_table = NULL;
                        params->sc_table_changed = true;
                }

                /* Only IA_CSS_PIPE_ID_VIDEO & IA_CSS_PIPE_ID_CAPTURE will support dvs_6axis_config*/
                for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
                        if (stream_params->pipe_dvs_6axis_config[i]) {
                                if (params->pipe_dvs_6axis_config[i]) {
                                        copy_dvs_6axis_table(params->pipe_dvs_6axis_config[i],
                                                             stream_params->pipe_dvs_6axis_config[i]);
                                } else {
                                        params->pipe_dvs_6axis_config[i] =
                                            generate_dvs_6axis_table_from_config(stream_params->pipe_dvs_6axis_config[i]);
                                }
                        }
                }
                ia_css_set_sdis_config(params, &stream_params->dvs_coefs);
                params->dis_coef_table_changed = stream_params->dis_coef_table_changed;

                ia_css_set_sdis2_config(params, &stream_params->dvs2_coefs);
                params->dvs2_coef_table_changed = stream_params->dvs2_coef_table_changed;
                params->sensor_binning = stream_params->sensor_binning;
        }

exit:
        return retval;
}

int
sh_css_params_init(void)
{
        int i, p;

        IA_CSS_ENTER_PRIVATE("void");

        /* TMP: tracking of paramsets */
        g_param_buffer_dequeue_count = 0;
        g_param_buffer_enqueue_count = 0;

        for (p = 0; p < IA_CSS_PIPE_ID_NUM; p++) {
                for (i = 0; i < SH_CSS_MAX_STAGES; i++) {
                        xmem_sp_stage_ptrs[p][i] =
                        ia_css_refcount_increment(-1,
                                                  hmm_alloc(sizeof(struct sh_css_sp_stage)));
                        xmem_isp_stage_ptrs[p][i] =
                        ia_css_refcount_increment(-1,
                                                  hmm_alloc(sizeof(struct sh_css_sp_stage)));

                        if ((xmem_sp_stage_ptrs[p][i] == mmgr_NULL) ||
                            (xmem_isp_stage_ptrs[p][i] == mmgr_NULL)) {
                                sh_css_params_uninit();
                                IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
                                return -ENOMEM;
                        }

                        hmm_set(xmem_sp_stage_ptrs[p][i], 0, sizeof(struct sh_css_sp_stage));
                        hmm_set(xmem_isp_stage_ptrs[p][i], 0, sizeof(struct sh_css_sp_stage));
                }
        }

        ia_css_config_gamma_table();
        ia_css_config_ctc_table();
        ia_css_config_rgb_gamma_tables();
        ia_css_config_xnr_table();

        sp_ddr_ptrs = ia_css_refcount_increment(-1,
                                                hmm_alloc(CEIL_MUL(sizeof(struct sh_css_ddr_address_map),
                                                                   HIVE_ISP_DDR_WORD_BYTES)));
        xmem_sp_group_ptrs = ia_css_refcount_increment(-1,
                                                       hmm_alloc(sizeof(struct sh_css_sp_group)));

        if ((sp_ddr_ptrs == mmgr_NULL) ||
            (xmem_sp_group_ptrs == mmgr_NULL)) {
                ia_css_uninit();
                IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
                return -ENOMEM;
        }
        hmm_set(sp_ddr_ptrs, 0, CEIL_MUL(sizeof(struct sh_css_ddr_address_map),
                                         HIVE_ISP_DDR_WORD_BYTES));
        hmm_set(xmem_sp_group_ptrs, 0, sizeof(struct sh_css_sp_group));
        IA_CSS_LEAVE_ERR_PRIVATE(0);
        return 0;
}

static void host_lut_store(const void *lut)
{
        unsigned int i;

        for (i = 0; i < N_GDC_ID; i++)
                gdc_lut_store((gdc_ID_t)i, (const int (*)[HRT_GDC_N]) lut);
}

int ia_css_pipe_set_bci_scaler_lut(struct ia_css_pipe *pipe,
        const void *lut)
{
        int err = 0;
        bool stream_started = false;

        IA_CSS_ENTER("pipe=%p lut=%p", pipe, lut);

        if (!lut || !pipe) {
                err = -EINVAL;
                IA_CSS_LEAVE("err=%d", err);
                return err;
        }

        /* If the pipe belongs to a stream and the stream has started, it is not
         * safe to store lut to gdc HW. If pipe->stream is NULL, then no stream is
         * created with this pipe, so it is safe to do this operation as long as
         * ia_css_init() has been called. */
        if (pipe->stream && pipe->stream->started) {
                ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
                                    "unable to set scaler lut since stream has started\n");
                stream_started = true;
                err = -ENOTSUPP;
        }

        /* Free any existing tables. */
        if (pipe->scaler_pp_lut != mmgr_NULL) {
                hmm_free(pipe->scaler_pp_lut);
                pipe->scaler_pp_lut = mmgr_NULL;
        }

        if (!stream_started) {
                pipe->scaler_pp_lut = hmm_alloc(sizeof(zoom_table));

                if (pipe->scaler_pp_lut == mmgr_NULL) {
                        ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
                                            "unable to allocate scaler_pp_lut\n");
                        err = -ENOMEM;
                } else {
                        gdc_lut_convert_to_isp_format((const int(*)[HRT_GDC_N])lut,
                                                      interleaved_lut_temp);
                        hmm_store(pipe->scaler_pp_lut,
                                   (int *)interleaved_lut_temp,
                                   sizeof(zoom_table));
                }
        }

        IA_CSS_LEAVE("lut(%u) err=%d", pipe->scaler_pp_lut, err);
        return err;
}

/* if pipe is NULL, returns default lut addr. */
ia_css_ptr sh_css_pipe_get_pp_gdc_lut(const struct ia_css_pipe *pipe)
{
        assert(pipe);

        if (pipe->scaler_pp_lut != mmgr_NULL)
                return pipe->scaler_pp_lut;
        else
                return sh_css_params_get_default_gdc_lut();
}

int sh_css_params_map_and_store_default_gdc_lut(void)
{
        int err = 0;

        IA_CSS_ENTER_PRIVATE("void");

        /* Is table already mapped? Nothing to do if it is mapped. */
        if (default_gdc_lut != mmgr_NULL)
                return err;

        host_lut_store((void *)zoom_table);

        default_gdc_lut = hmm_alloc(sizeof(zoom_table));

        if (default_gdc_lut == mmgr_NULL)
                return -ENOMEM;

        gdc_lut_convert_to_isp_format((const int(*)[HRT_GDC_N])zoom_table,
                                      interleaved_lut_temp);
        hmm_store(default_gdc_lut, (int *)interleaved_lut_temp,
                   sizeof(zoom_table));

        IA_CSS_LEAVE_PRIVATE("lut(%u) err=%d", default_gdc_lut, err);
        return err;
}

void sh_css_params_free_default_gdc_lut(void)
{
        IA_CSS_ENTER_PRIVATE("void");

        if (default_gdc_lut != mmgr_NULL) {
                hmm_free(default_gdc_lut);
                default_gdc_lut = mmgr_NULL;
        }

        IA_CSS_LEAVE_PRIVATE("void");
}

ia_css_ptr sh_css_params_get_default_gdc_lut(void)
{
        return default_gdc_lut;
}

static void free_param_set_callback(
    ia_css_ptr ptr)
{
        IA_CSS_ENTER_PRIVATE("void");

        free_ia_css_isp_parameter_set_info(ptr);

        IA_CSS_LEAVE_PRIVATE("void");
}

static void free_buffer_callback(
    ia_css_ptr ptr)
{
        IA_CSS_ENTER_PRIVATE("void");

        hmm_free(ptr);

        IA_CSS_LEAVE_PRIVATE("void");
}

void
sh_css_param_clear_param_sets(void)
{
        IA_CSS_ENTER_PRIVATE("void");

        ia_css_refcount_clear(IA_CSS_REFCOUNT_PARAM_SET_POOL, &free_param_set_callback);

        IA_CSS_LEAVE_PRIVATE("void");
}

/*
 * MW: we can define hmm_free() to return a NULL
 * then you can write ptr = hmm_free(ptr);
 */
#define safe_free(id, x)      \
        do {                  \
                ia_css_refcount_decrement(id, x);     \
                (x) = mmgr_NULL;  \
        } while (0)

static void free_map(struct sh_css_ddr_address_map *map)
{
        unsigned int i;

        ia_css_ptr *addrs = (ia_css_ptr *)map;

        IA_CSS_ENTER_PRIVATE("void");

        /* free buffers */
        for (i = 0; i < (sizeof(struct sh_css_ddr_address_map_size) /
                         sizeof(size_t)); i++) {
                if (addrs[i] == mmgr_NULL)
                        continue;
                safe_free(IA_CSS_REFCOUNT_PARAM_BUFFER, addrs[i]);
        }

        IA_CSS_LEAVE_PRIVATE("void");
}

void
ia_css_stream_isp_parameters_uninit(struct ia_css_stream *stream)
{
        int i;
        struct ia_css_isp_parameters *params = stream->isp_params_configs;
        struct ia_css_isp_parameters *per_frame_params =
                    stream->per_frame_isp_params_configs;

        IA_CSS_ENTER_PRIVATE("void");
        if (!params) {
                IA_CSS_LEAVE_PRIVATE("isp_param_configs is NULL");
                return;
        }

        /* free existing ddr_ptr maps */
        for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
                free_map(&params->pipe_ddr_ptrs[i]);
                if (per_frame_params)
                        free_map(&per_frame_params->pipe_ddr_ptrs[i]);
                /* Free up theDVS table memory blocks before recomputing new table */
                if (params->pipe_dvs_6axis_config[i])
                        free_dvs_6axis_table(&params->pipe_dvs_6axis_config[i]);
                if (per_frame_params && per_frame_params->pipe_dvs_6axis_config[i])
                        free_dvs_6axis_table(&per_frame_params->pipe_dvs_6axis_config[i]);
        }
        free_map(&params->ddr_ptrs);
        if (per_frame_params)
                free_map(&per_frame_params->ddr_ptrs);

        if (params->fpn_config.data) {
                kvfree(params->fpn_config.data);
                params->fpn_config.data = NULL;
        }

        /* Free up sc_config (temporal shading table) if it is allocated. */
        if (params->sc_config) {
                ia_css_shading_table_free(params->sc_config);
                params->sc_config = NULL;
        }
        if (per_frame_params) {
                if (per_frame_params->sc_config) {
                        ia_css_shading_table_free(per_frame_params->sc_config);
                        per_frame_params->sc_config = NULL;
                }
        }

        kvfree(params);
        kvfree(per_frame_params);
        stream->isp_params_configs = NULL;
        stream->per_frame_isp_params_configs = NULL;

        IA_CSS_LEAVE_PRIVATE("void");
}

void
sh_css_params_uninit(void)
{
        unsigned int p, i;

        IA_CSS_ENTER_PRIVATE("void");

        ia_css_refcount_decrement(-1, sp_ddr_ptrs);
        sp_ddr_ptrs = mmgr_NULL;
        ia_css_refcount_decrement(-1, xmem_sp_group_ptrs);
        xmem_sp_group_ptrs = mmgr_NULL;

        for (p = 0; p < IA_CSS_PIPE_ID_NUM; p++)
                for (i = 0; i < SH_CSS_MAX_STAGES; i++) {
                        ia_css_refcount_decrement(-1, xmem_sp_stage_ptrs[p][i]);
                        xmem_sp_stage_ptrs[p][i] = mmgr_NULL;
                        ia_css_refcount_decrement(-1, xmem_isp_stage_ptrs[p][i]);
                        xmem_isp_stage_ptrs[p][i] = mmgr_NULL;
                }

        /* go through the pools to clear references */
        ia_css_refcount_clear(IA_CSS_REFCOUNT_PARAM_SET_POOL, &free_param_set_callback);
        ia_css_refcount_clear(IA_CSS_REFCOUNT_PARAM_BUFFER, &free_buffer_callback);
        ia_css_refcount_clear(-1, &free_buffer_callback);

        IA_CSS_LEAVE_PRIVATE("void");
}

static struct ia_css_host_data *
convert_allocate_morph_plane(
    unsigned short *data,
    unsigned int width,
    unsigned int height,
    unsigned int aligned_width)
{
        unsigned int i, j, padding, w;
        struct ia_css_host_data *me;
        unsigned int isp_data_size;
        u16 *isp_data_ptr;

        IA_CSS_ENTER_PRIVATE("void");

        /* currently we don't have morph table interpolation yet,
         * so we allow a wider table to be used. This will be removed
         * in the future. */
        if (width > aligned_width) {
                padding = 0;
                w = aligned_width;
        } else {
                padding = aligned_width - width;
                w = width;
        }
        isp_data_size = height * (w + padding) * sizeof(uint16_t);

        me = ia_css_host_data_allocate((size_t)isp_data_size);

        if (!me) {
                IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
                return NULL;
        }

        isp_data_ptr = (uint16_t *)me->address;

        memset(isp_data_ptr, 0, (size_t)isp_data_size);

        for (i = 0; i < height; i++) {
                for (j = 0; j < w; j++)
                        *isp_data_ptr++ = (uint16_t)data[j];
                isp_data_ptr += padding;
                data += width;
        }

        IA_CSS_LEAVE_PRIVATE("void");
        return me;
}

static int
store_morph_plane(
    unsigned short *data,
    unsigned int width,
    unsigned int height,
    ia_css_ptr dest,
    unsigned int aligned_width)
{
        struct ia_css_host_data *isp_data;

        assert(dest != mmgr_NULL);

        isp_data = convert_allocate_morph_plane(data, width, height, aligned_width);
        if (!isp_data) {
                IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
                return -ENOMEM;
        }
        ia_css_params_store_ia_css_host_data(dest, isp_data);

        ia_css_host_data_free(isp_data);
        return 0;
}

static void sh_css_update_isp_params_to_ddr(
    struct ia_css_isp_parameters *params,
    ia_css_ptr ddr_ptr)
{
        size_t size = sizeof(params->uds);

        IA_CSS_ENTER_PRIVATE("void");

        assert(params);

        hmm_store(ddr_ptr, &params->uds, size);
        IA_CSS_LEAVE_PRIVATE("void");
}

static void sh_css_update_isp_mem_params_to_ddr(
    const struct ia_css_binary *binary,
    ia_css_ptr ddr_mem_ptr,
    size_t size,
    enum ia_css_isp_memories mem)
{
        const struct ia_css_host_data *params;

        IA_CSS_ENTER_PRIVATE("void");

        params = ia_css_isp_param_get_mem_init(&binary->mem_params,
                                               IA_CSS_PARAM_CLASS_PARAM, mem);
        hmm_store(ddr_mem_ptr, params->address, size);

        IA_CSS_LEAVE_PRIVATE("void");
}

void ia_css_dequeue_param_buffers(/*unsigned int pipe_num*/ void)
{
        unsigned int i;
        ia_css_ptr cpy;
        enum sh_css_queue_id param_queue_ids[3] = {     IA_CSS_PARAMETER_SET_QUEUE_ID,
                                                    IA_CSS_PER_FRAME_PARAMETER_SET_QUEUE_ID,
                                                    SH_CSS_INVALID_QUEUE_ID
                                                  };

        IA_CSS_ENTER_PRIVATE("void");

        if (!sh_css_sp_is_running()) {
                IA_CSS_LEAVE_PRIVATE("sp is not running");
                /* SP is not running. The queues are not valid */
                return;
        }

        for (i = 0; SH_CSS_INVALID_QUEUE_ID != param_queue_ids[i]; i++) {
                cpy = (ia_css_ptr)0;
                /* clean-up old copy */
                while (ia_css_bufq_dequeue_buffer(param_queue_ids[i],
                                                  (uint32_t *)&cpy) == 0) {
                        /* TMP: keep track of dequeued param set count
                         */
                        g_param_buffer_dequeue_count++;
                        ia_css_bufq_enqueue_psys_event(
                            IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED,
                            0,
                            param_queue_ids[i],
                            0);

                        IA_CSS_LOG("dequeued param set %x from %d, release ref", cpy, 0);
                        free_ia_css_isp_parameter_set_info(cpy);
                        cpy = (ia_css_ptr)0;
                }
        }

        IA_CSS_LEAVE_PRIVATE("void");
}

static void
process_kernel_parameters(unsigned int pipe_id,
                          struct ia_css_pipeline_stage *stage,
                          struct ia_css_isp_parameters *params,
                          unsigned int isp_pipe_version,
                          unsigned int raw_bit_depth)
{
        unsigned int param_id;

        (void)isp_pipe_version;
        (void)raw_bit_depth;

        sh_css_enable_pipeline(stage->binary);

        if (params->config_changed[IA_CSS_OB_ID]) {
                ia_css_ob_configure(&params->stream_configs.ob,
                                    isp_pipe_version, raw_bit_depth);
        }
        if (params->config_changed[IA_CSS_S3A_ID]) {
                ia_css_s3a_configure(raw_bit_depth);
        }
        /* Copy stage uds parameters to config, since they can differ per stage.
         */
        params->crop_config.crop_pos = params->uds[stage->stage_num].crop_pos;
        params->uds_config.crop_pos  = params->uds[stage->stage_num].crop_pos;
        params->uds_config.uds       = params->uds[stage->stage_num].uds;
        /* Call parameter process functions for all kernels */
        /* Skip SC, since that is called on a temp sc table */
        for (param_id = 0; param_id < IA_CSS_NUM_PARAMETER_IDS; param_id++) {
                if (param_id == IA_CSS_SC_ID) continue;
                if (params->config_changed[param_id])
                        ia_css_kernel_process_param[param_id](pipe_id, stage, params);
        }
}

int
sh_css_param_update_isp_params(struct ia_css_pipe *curr_pipe,
                               struct ia_css_isp_parameters *params,
                               bool commit,
                               struct ia_css_pipe *pipe_in)
{
        int err = 0;
        ia_css_ptr cpy;
        int i;
        unsigned int raw_bit_depth = 10;
        unsigned int isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_1;
        bool acc_cluster_params_changed = false;
        unsigned int thread_id, pipe_num;

        (void)acc_cluster_params_changed;

        assert(curr_pipe);

        IA_CSS_ENTER_PRIVATE("pipe=%p, isp_parameters_id=%d", pipe_in, params->isp_parameters_id);
        raw_bit_depth = ia_css_stream_input_format_bits_per_pixel(curr_pipe->stream);

        /* now make the map available to the sp */
        if (!commit) {
                IA_CSS_LEAVE_ERR_PRIVATE(err);
                return err;
        }
        /* enqueue a copies of the mem_map to
           the designated pipelines */
        for (i = 0; i < curr_pipe->stream->num_pipes; i++) {
                struct ia_css_pipe *pipe;
                struct sh_css_ddr_address_map *cur_map;
                struct sh_css_ddr_address_map_size *cur_map_size;
                struct ia_css_isp_parameter_set_info isp_params_info;
                struct ia_css_pipeline *pipeline;
                struct ia_css_pipeline_stage *stage;

                enum sh_css_queue_id queue_id;

                pipe = curr_pipe->stream->pipes[i];
                pipeline = ia_css_pipe_get_pipeline(pipe);
                pipe_num = ia_css_pipe_get_pipe_num(pipe);
                isp_pipe_version = ia_css_pipe_get_isp_pipe_version(pipe);
                ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);

                ia_css_query_internal_queue_id(params->output_frame
                                               ? IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET
                                               : IA_CSS_BUFFER_TYPE_PARAMETER_SET,
                                               thread_id, &queue_id);
                if (!sh_css_sp_is_running()) {
                        /* SP is not running. The queues are not valid */
                        err = -EBUSY;
                        break;
                }
                cur_map = &params->pipe_ddr_ptrs[pipeline->pipe_id];
                cur_map_size = &params->pipe_ddr_ptrs_size[pipeline->pipe_id];

                /* TODO: Normally, zoom and motion parameters shouldn't
                 * be part of "isp_params" as it is resolution/pipe dependent
                 * Therefore, move the zoom config elsewhere (e.g. shading
                 * table can be taken as an example! @GC
                 * */
                {
                        /* we have to do this per pipeline because */
                        /* the processing is a.o. resolution dependent */
                        err = ia_css_process_zoom_and_motion(params,
                                                             pipeline->stages);
                        if (err)
                                return err;
                }
                /* check if to actually update the parameters for this pipe */
                /* When API change is implemented making good distinction between
                * stream config and pipe config this skipping code can be moved out of the #ifdef */
                if (pipe_in && (pipe != pipe_in)) {
                        IA_CSS_LOG("skipping pipe %p", pipe);
                        continue;
                }

                /* BZ 125915, should be moved till after "update other buff" */
                /* update the other buffers to the pipe specific copies */
                for (stage = pipeline->stages; stage; stage = stage->next) {
                        unsigned int mem;

                        if (!stage || !stage->binary)
                                continue;

                        process_kernel_parameters(pipeline->pipe_id,
                                                  stage, params,
                                                  isp_pipe_version, raw_bit_depth);

                        err = sh_css_params_write_to_ddr_internal(
                                  pipe,
                                  pipeline->pipe_id,
                                  params,
                                  stage,
                                  cur_map,
                                  cur_map_size);

                        if (err)
                                break;
                        for (mem = 0; mem < IA_CSS_NUM_MEMORIES; mem++) {
                                params->isp_mem_params_changed
                                [pipeline->pipe_id][stage->stage_num][mem] = false;
                        }
                } /* for */
                if (err)
                        break;
                /* update isp_params to pipe specific copies */
                if (params->isp_params_changed) {
                        reallocate_buffer(&cur_map->isp_param,
                                          &cur_map_size->isp_param,
                                          cur_map_size->isp_param,
                                          true,
                                          &err);
                        if (err)
                                break;
                        sh_css_update_isp_params_to_ddr(params, cur_map->isp_param);
                }

                /* last make referenced copy */
                err = ref_sh_css_ddr_address_map(
                          cur_map,
                          &isp_params_info.mem_map);
                if (err)
                        break;

                /* Update Parameters ID */
                isp_params_info.isp_parameters_id = params->isp_parameters_id;

                /* Update output frame pointer */
                isp_params_info.output_frame_ptr =
                    (params->output_frame) ? params->output_frame->data : mmgr_NULL;

                /* now write the copy to ddr */
                err = write_ia_css_isp_parameter_set_info_to_ddr(&isp_params_info, &cpy);
                if (err)
                        break;

                /* enqueue the set to sp */
                IA_CSS_LOG("queue param set %x to %d", cpy, thread_id);

                err = ia_css_bufq_enqueue_buffer(thread_id, queue_id, (uint32_t)cpy);
                if (err) {
                        free_ia_css_isp_parameter_set_info(cpy);
                        IA_CSS_LOG("pfp: FAILED to add config id %d for OF %d to q %d on thread %d",
                                   isp_params_info.isp_parameters_id,
                                   isp_params_info.output_frame_ptr,
                                   queue_id, thread_id);
                        break;
                } else {
                        /* TMP: check discrepancy between nr of enqueued
                         * parameter sets and dequeued sets
                         */
                        g_param_buffer_enqueue_count++;
                        assert(g_param_buffer_enqueue_count < g_param_buffer_dequeue_count + 50);
                        /*
                         * Tell the SP which queues are not empty,
                         * by sending the software event.
                         */
                        if (!sh_css_sp_is_running()) {
                                /* SP is not running. The queues are not valid */
                                IA_CSS_LEAVE_ERR_PRIVATE(-EBUSY);
                                return -EBUSY;
                        }
                        ia_css_bufq_enqueue_psys_event(
                            IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED,
                            (uint8_t)thread_id,
                            (uint8_t)queue_id,
                            0);
                        IA_CSS_LOG("pfp: added config id %d for OF %d to q %d on thread %d",
                                   isp_params_info.isp_parameters_id,
                                   isp_params_info.output_frame_ptr,
                                   queue_id, thread_id);
                }
                /* clean-up old copy */
                ia_css_dequeue_param_buffers(/*pipe_num*/);
                params->pipe_dvs_6axis_config_changed[pipeline->pipe_id] = false;
        } /* end for each 'active' pipeline */
        /* clear the changed flags after all params
        for all pipelines have been updated */
        params->isp_params_changed = false;
        params->sc_table_changed = false;
        params->dis_coef_table_changed = false;
        params->dvs2_coef_table_changed = false;
        params->morph_table_changed = false;
        params->dz_config_changed = false;
        params->motion_config_changed = false;
        /* ------ deprecated(bz675) : from ------ */
        params->shading_settings_changed = false;
        /* ------ deprecated(bz675) : to ------ */

        memset(&params->config_changed[0], 0, sizeof(params->config_changed));

        IA_CSS_LEAVE_ERR_PRIVATE(err);
        return err;
}

static int
sh_css_params_write_to_ddr_internal(
    struct ia_css_pipe *pipe,
    unsigned int pipe_id,
    struct ia_css_isp_parameters *params,
    const struct ia_css_pipeline_stage *stage,
    struct sh_css_ddr_address_map *ddr_map,
    struct sh_css_ddr_address_map_size *ddr_map_size)
{
        int err;
        const struct ia_css_binary *binary;

        unsigned int stage_num;
        unsigned int mem;
        bool buff_realloced;

        /* struct is > 128 bytes so it should not be on stack (see checkpatch) */
        static struct ia_css_macc_table converted_macc_table;

        IA_CSS_ENTER_PRIVATE("void");
        assert(params);
        assert(ddr_map);
        assert(ddr_map_size);
        assert(stage);

        binary = stage->binary;
        assert(binary);

        stage_num = stage->stage_num;

        if (binary->info->sp.enable.fpnr) {
                buff_realloced = reallocate_buffer(&ddr_map->fpn_tbl,
                                                   &ddr_map_size->fpn_tbl,
                                                   fpntbl_bytes(binary),
                                                   params->config_changed[IA_CSS_FPN_ID],
                                                   &err);
                if (err) {
                        IA_CSS_LEAVE_ERR_PRIVATE(err);
                        return err;
                }
                if (params->config_changed[IA_CSS_FPN_ID] || buff_realloced) {
                        if (params->fpn_config.enabled) {
                                err = store_fpntbl(params, ddr_map->fpn_tbl);
                                if (err) {
                                        IA_CSS_LEAVE_ERR_PRIVATE(err);
                                        return err;
                                }
                        }
                }
        }

        if (binary->info->sp.enable.sc) {
                u32 enable_conv;

                enable_conv = params->shading_settings.enable_shading_table_conversion;

                buff_realloced = reallocate_buffer(&ddr_map->sc_tbl,
                                                   &ddr_map_size->sc_tbl,
                                                   sctbl_bytes(binary),
                                                   params->sc_table_changed,
                                                   &err);
                if (err) {
                        IA_CSS_LEAVE_ERR_PRIVATE(err);
                        return err;
                }

                if (params->shading_settings_changed ||
                    params->sc_table_changed || buff_realloced) {
                        if (enable_conv == 0) {
                                if (params->sc_table) {
                                        /* store the shading table to ddr */
                                        err = ia_css_params_store_sctbl(stage, ddr_map->sc_tbl, params->sc_table);
                                        if (err) {
                                                IA_CSS_LEAVE_ERR_PRIVATE(err);
                                                return err;
                                        }
                                        /* set sc_config to isp */
                                        params->sc_config = (struct ia_css_shading_table *)params->sc_table;
                                        ia_css_kernel_process_param[IA_CSS_SC_ID](pipe_id, stage, params);
                                        params->sc_config = NULL;
                                } else {
                                        /* generate the identical shading table */
                                        if (params->sc_config) {
                                                ia_css_shading_table_free(params->sc_config);
                                                params->sc_config = NULL;
                                        }
                                        sh_css_params_shading_id_table_generate(&params->sc_config,
                                                                                binary->sctbl_width_per_color,
                                                                                binary->sctbl_height);
                                        if (!params->sc_config) {
                                                IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
                                                return -ENOMEM;
                                        }

                                        /* store the shading table to ddr */
                                        err = ia_css_params_store_sctbl(stage, ddr_map->sc_tbl, params->sc_config);
                                        if (err) {
                                                IA_CSS_LEAVE_ERR_PRIVATE(err);
                                                return err;
                                        }

                                        /* set sc_config to isp */
                                        ia_css_kernel_process_param[IA_CSS_SC_ID](pipe_id, stage, params);

                                        /* free the shading table */
                                        ia_css_shading_table_free(params->sc_config);
                                        params->sc_config = NULL;
                                }
                        } else { /* legacy */
                                /* ------ deprecated(bz675) : from ------ */
                                /* shading table is full resolution, reduce */
                                if (params->sc_config) {
                                        ia_css_shading_table_free(params->sc_config);
                                        params->sc_config = NULL;
                                }
                                prepare_shading_table(
                                    (const struct ia_css_shading_table *)params->sc_table,
                                    params->sensor_binning,
                                    &params->sc_config,
                                    binary, pipe->required_bds_factor);
                                if (!params->sc_config) {
                                        IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
                                        return -ENOMEM;
                                }

                                /* store the shading table to ddr */
                                err = ia_css_params_store_sctbl(stage, ddr_map->sc_tbl, params->sc_config);
                                if (err) {
                                        IA_CSS_LEAVE_ERR_PRIVATE(err);
                                        return err;
                                }

                                /* set sc_config to isp */
                                ia_css_kernel_process_param[IA_CSS_SC_ID](pipe_id, stage, params);

                                /* free the shading table */
                                ia_css_shading_table_free(params->sc_config);
                                params->sc_config = NULL;
                                /* ------ deprecated(bz675) : to ------ */
                        }
                }
        }

        if (params->config_changed[IA_CSS_MACC_ID] && binary->info->sp.enable.macc) {
                unsigned int i, j, idx;
                static const unsigned int idx_map[] = {
                        0, 1, 3, 2, 6, 7, 5, 4, 12, 13, 15, 14, 10, 11, 9, 8
                };

                for (i = 0; i < IA_CSS_MACC_NUM_AXES; i++) {
                        idx = 4 * idx_map[i];
                        j   = 4 * i;

                        if (binary->info->sp.pipeline.isp_pipe_version == SH_CSS_ISP_PIPE_VERSION_1) {
                                converted_macc_table.data[idx] =
                                    (int16_t)sDIGIT_FITTING(params->macc_table.data[j],
                                                            13, SH_CSS_MACC_COEF_SHIFT);
                                converted_macc_table.data[idx + 1] =
                                    (int16_t)sDIGIT_FITTING(params->macc_table.data[j + 1],
                                                            13, SH_CSS_MACC_COEF_SHIFT);
                                converted_macc_table.data[idx + 2] =
                                    (int16_t)sDIGIT_FITTING(params->macc_table.data[j + 2],
                                                            13, SH_CSS_MACC_COEF_SHIFT);
                                converted_macc_table.data[idx + 3] =
                                    (int16_t)sDIGIT_FITTING(params->macc_table.data[j + 3],
                                                            13, SH_CSS_MACC_COEF_SHIFT);
                        } else if (binary->info->sp.pipeline.isp_pipe_version ==
                                   SH_CSS_ISP_PIPE_VERSION_2_2) {
                                converted_macc_table.data[idx] =
                                    params->macc_table.data[j];
                                converted_macc_table.data[idx + 1] =
                                    params->macc_table.data[j + 1];
                                converted_macc_table.data[idx + 2] =
                                    params->macc_table.data[j + 2];
                                converted_macc_table.data[idx + 3] =
                                    params->macc_table.data[j + 3];
                        }
                }
                reallocate_buffer(&ddr_map->macc_tbl,
                                  &ddr_map_size->macc_tbl,
                                  ddr_map_size->macc_tbl,
                                  true,
                                  &err);
                if (err) {
                        IA_CSS_LEAVE_ERR_PRIVATE(err);
                        return err;
                }
                hmm_store(ddr_map->macc_tbl,
                           converted_macc_table.data,
                           sizeof(converted_macc_table.data));
        }

        if (binary->info->sp.enable.dvs_6axis) {
                /* because UV is packed into the Y plane, calc total
                 * YYU size = /2 gives size of UV-only,
                 * total YYU size = UV-only * 3.
                 */
                buff_realloced = reallocate_buffer(
                                     &ddr_map->dvs_6axis_params_y,
                                     &ddr_map_size->dvs_6axis_params_y,
                                     (size_t)((DVS_6AXIS_BYTES(binary) / 2) * 3),
                                     params->pipe_dvs_6axis_config_changed[pipe_id],
                                     &err);
                if (err) {
                        IA_CSS_LEAVE_ERR_PRIVATE(err);
                        return err;
                }

                if (params->pipe_dvs_6axis_config_changed[pipe_id] || buff_realloced) {
                        const struct ia_css_frame_info *dvs_in_frame_info;

                        if (stage->args.delay_frames[0]) {
                                /*When delay frames are present(as in case of video),
                                they are used for dvs. Configure DVS using those params*/
                                dvs_in_frame_info = &stage->args.delay_frames[0]->frame_info;
                        } else {
                                /*Otherwise, use input frame to configure DVS*/
                                dvs_in_frame_info = &stage->args.in_frame->frame_info;
                        }

                        /* Generate default DVS unity table on start up*/
                        if (!params->pipe_dvs_6axis_config[pipe_id]) {
                                struct ia_css_resolution dvs_offset = {0};

                                dvs_offset.width = (PIX_SHIFT_FILTER_RUN_IN_X + binary->dvs_envelope.width) / 2;
                                dvs_offset.height = (PIX_SHIFT_FILTER_RUN_IN_Y + binary->dvs_envelope.height) / 2;

                                params->pipe_dvs_6axis_config[pipe_id] =
                                    generate_dvs_6axis_table(&binary->out_frame_info[0].res, &dvs_offset);
                                if (!params->pipe_dvs_6axis_config[pipe_id]) {
                                        IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
                                        return -ENOMEM;
                                }
                                params->pipe_dvs_6axis_config_changed[pipe_id] = true;

                                store_dvs_6axis_config(params->pipe_dvs_6axis_config[pipe_id],
                                                    binary,
                                                    dvs_in_frame_info,
                                                    ddr_map->dvs_6axis_params_y);
                                params->isp_params_changed = true;
                        }
                }
        }

        if (binary->info->sp.enable.ca_gdc) {
                unsigned int i;
                ia_css_ptr *virt_addr_tetra_x[

                IA_CSS_MORPH_TABLE_NUM_PLANES];
                size_t *virt_size_tetra_x[

                IA_CSS_MORPH_TABLE_NUM_PLANES];
                ia_css_ptr *virt_addr_tetra_y[

                IA_CSS_MORPH_TABLE_NUM_PLANES];
                size_t *virt_size_tetra_y[

                IA_CSS_MORPH_TABLE_NUM_PLANES];

                virt_addr_tetra_x[0] = &ddr_map->tetra_r_x;
                virt_addr_tetra_x[1] = &ddr_map->tetra_gr_x;
                virt_addr_tetra_x[2] = &ddr_map->tetra_gb_x;
                virt_addr_tetra_x[3] = &ddr_map->tetra_b_x;
                virt_addr_tetra_x[4] = &ddr_map->tetra_ratb_x;
                virt_addr_tetra_x[5] = &ddr_map->tetra_batr_x;

                virt_size_tetra_x[0] = &ddr_map_size->tetra_r_x;
                virt_size_tetra_x[1] = &ddr_map_size->tetra_gr_x;
                virt_size_tetra_x[2] = &ddr_map_size->tetra_gb_x;
                virt_size_tetra_x[3] = &ddr_map_size->tetra_b_x;
                virt_size_tetra_x[4] = &ddr_map_size->tetra_ratb_x;
                virt_size_tetra_x[5] = &ddr_map_size->tetra_batr_x;

                virt_addr_tetra_y[0] = &ddr_map->tetra_r_y;
                virt_addr_tetra_y[1] = &ddr_map->tetra_gr_y;
                virt_addr_tetra_y[2] = &ddr_map->tetra_gb_y;
                virt_addr_tetra_y[3] = &ddr_map->tetra_b_y;
                virt_addr_tetra_y[4] = &ddr_map->tetra_ratb_y;
                virt_addr_tetra_y[5] = &ddr_map->tetra_batr_y;

                virt_size_tetra_y[0] = &ddr_map_size->tetra_r_y;
                virt_size_tetra_y[1] = &ddr_map_size->tetra_gr_y;
                virt_size_tetra_y[2] = &ddr_map_size->tetra_gb_y;
                virt_size_tetra_y[3] = &ddr_map_size->tetra_b_y;
                virt_size_tetra_y[4] = &ddr_map_size->tetra_ratb_y;
                virt_size_tetra_y[5] = &ddr_map_size->tetra_batr_y;

                buff_realloced = false;
                for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) {
                        buff_realloced |=
                            reallocate_buffer(virt_addr_tetra_x[i],
                                            virt_size_tetra_x[i],
                                            morph_plane_bytes(binary),
                                            params->morph_table_changed,
                                            &err);
                        if (err) {
                                IA_CSS_LEAVE_ERR_PRIVATE(err);
                                return err;
                        }
                        buff_realloced |=
                            reallocate_buffer(virt_addr_tetra_y[i],
                                            virt_size_tetra_y[i],
                                            morph_plane_bytes(binary),
                                            params->morph_table_changed,
                                            &err);
                        if (err) {
                                IA_CSS_LEAVE_ERR_PRIVATE(err);
                                return err;
                        }
                }
                if (params->morph_table_changed || buff_realloced) {
                        const struct ia_css_morph_table *table = params->morph_table;
                        struct ia_css_morph_table *id_table = NULL;

                        if ((table) &&
                            (table->width < binary->morph_tbl_width ||
                            table->height < binary->morph_tbl_height)) {
                                table = NULL;
                        }
                        if (!table) {
                                err = sh_css_params_default_morph_table(&id_table,
                                                                        binary);
                                if (err) {
                                        IA_CSS_LEAVE_ERR_PRIVATE(err);
                                        return err;
                                }
                                table = id_table;
                        }

                        for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) {
                                store_morph_plane(table->coordinates_x[i],
                                                table->width,
                                                table->height,
                                                *virt_addr_tetra_x[i],
                                                binary->morph_tbl_aligned_width);
                                store_morph_plane(table->coordinates_y[i],
                                                table->width,
                                                table->height,
                                                *virt_addr_tetra_y[i],
                                                binary->morph_tbl_aligned_width);
                        }
                        if (id_table)
                                ia_css_morph_table_free(id_table);
                }
        }

        /* After special cases like SC, FPN since they may change parameters */
        for (mem = 0; mem < N_IA_CSS_MEMORIES; mem++) {
                const struct ia_css_isp_data *isp_data =
                    ia_css_isp_param_get_isp_mem_init(&binary->info->sp.mem_initializers,
                                                    IA_CSS_PARAM_CLASS_PARAM, mem);
                size_t size = isp_data->size;

                if (!size) continue;
                buff_realloced = reallocate_buffer(&ddr_map->isp_mem_param[stage_num][mem],
                                                &ddr_map_size->isp_mem_param[stage_num][mem],
                                                size,
                                                params->isp_mem_params_changed[pipe_id][stage_num][mem],
                                                &err);
                if (err) {
                        IA_CSS_LEAVE_ERR_PRIVATE(err);
                        return err;
                }
                if (params->isp_mem_params_changed[pipe_id][stage_num][mem] || buff_realloced) {
                        sh_css_update_isp_mem_params_to_ddr(binary,
                                                            ddr_map->isp_mem_param[stage_num][mem],
                                                            ddr_map_size->isp_mem_param[stage_num][mem], mem);
                }
        }

        IA_CSS_LEAVE_ERR_PRIVATE(0);
        return 0;
}

const struct ia_css_fpn_table *ia_css_get_fpn_table(struct ia_css_stream
        *stream)
{
        struct ia_css_isp_parameters *params;

        IA_CSS_ENTER_LEAVE("void");
        assert(stream);

        params = stream->isp_params_configs;

        return &params->fpn_config;
}

struct ia_css_shading_table *ia_css_get_shading_table(struct ia_css_stream
        *stream)
{
        struct ia_css_shading_table *table = NULL;
        struct ia_css_isp_parameters *params;

        IA_CSS_ENTER("void");

        assert(stream);

        params = stream->isp_params_configs;
        if (!params)
                return NULL;

        if (params->shading_settings.enable_shading_table_conversion == 0) {
                if (params->sc_table) {
                        table = (struct ia_css_shading_table *)params->sc_table;
                } else {
                        const struct ia_css_binary *binary
                            = ia_css_stream_get_shading_correction_binary(stream);
                        if (binary) {
                                /* generate the identical shading table */
                                if (params->sc_config) {
                                        ia_css_shading_table_free(params->sc_config);
                                        params->sc_config = NULL;
                                }
                                sh_css_params_shading_id_table_generate(&params->sc_config,
                                                                        binary->sctbl_width_per_color,
                                                                        binary->sctbl_height);
                                table = params->sc_config;
                                /* The sc_config will be freed in the
                                 * ia_css_stream_isp_parameters_uninit function. */
                        }
                }
        } else {
                /* ------ deprecated(bz675) : from ------ */
                const struct ia_css_binary *binary
                    = ia_css_stream_get_shading_correction_binary(stream);
                struct ia_css_pipe *pipe;

                /**********************************************************************/
                /* following code is copied from function ia_css_stream_get_shading_correction_binary()
                 * to match with the binary */
                pipe = stream->pipes[0];

                if (stream->num_pipes == 2) {
                        assert(stream->pipes[1]);
                        if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
                            stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
                                pipe = stream->pipes[1];
                }
                /**********************************************************************/
                if (binary) {
                        if (params->sc_config) {
                                ia_css_shading_table_free(params->sc_config);
                                params->sc_config = NULL;
                        }
                        prepare_shading_table(
                            (const struct ia_css_shading_table *)params->sc_table,
                            params->sensor_binning,
                            &params->sc_config,
                            binary, pipe->required_bds_factor);

                        table = params->sc_config;
                        /* The sc_config will be freed in the
                         * ia_css_stream_isp_parameters_uninit function. */
                }
                /* ------ deprecated(bz675) : to ------ */
        }

        IA_CSS_LEAVE("table=%p", table);

        return table;
}

ia_css_ptr sh_css_store_sp_group_to_ddr(void)
{
        u8 *write_buf;
        u8 *buf_ptr;

        IA_CSS_ENTER_LEAVE_PRIVATE("void");

        write_buf = kzalloc(sizeof(u8) * 8192, GFP_KERNEL);
        if (!write_buf)
                return 0;

        buf_ptr = write_buf;
        if (IS_ISP2401) {
                memcpy(buf_ptr, &sh_css_sp_group.config, 3);
                buf_ptr += 3;
                *buf_ptr++ = sh_css_sp_group.config.enable_isys_event_queue;
                *buf_ptr++ = sh_css_sp_group.config.disable_cont_vf;
                memset(buf_ptr, 0, 3);
                buf_ptr += 3; /* Padding 3 bytes for struct sh_css_sp_config*/
        } else {
                memcpy(buf_ptr, &sh_css_sp_group.config, sizeof(sh_css_sp_group.config));
                buf_ptr += sizeof(sh_css_sp_group.config);
        }

        memcpy(buf_ptr, &sh_css_sp_group.pipe, sizeof(sh_css_sp_group.pipe));
        buf_ptr += sizeof(sh_css_sp_group.pipe);

        if (IS_ISP2401) {
                memcpy(buf_ptr, &sh_css_sp_group.pipe_io, sizeof(sh_css_sp_group.pipe_io));
                buf_ptr += sizeof(sh_css_sp_group.pipe_io);
                memcpy(buf_ptr, &sh_css_sp_group.pipe_io_status,
                       sizeof(sh_css_sp_group.pipe_io_status));
                buf_ptr += sizeof(sh_css_sp_group.pipe_io_status);
        }

        memcpy(buf_ptr, &sh_css_sp_group.debug, sizeof(sh_css_sp_group.debug));
        buf_ptr += sizeof(sh_css_sp_group.debug);

        hmm_store(xmem_sp_group_ptrs,
                  write_buf,
                  buf_ptr - write_buf);

        kfree(write_buf);
        return xmem_sp_group_ptrs;
}

ia_css_ptr sh_css_store_sp_stage_to_ddr(
    unsigned int pipe,
    unsigned int stage)
{
        IA_CSS_ENTER_LEAVE_PRIVATE("void");
        hmm_store(xmem_sp_stage_ptrs[pipe][stage],
                   &sh_css_sp_stage,
                   sizeof(struct sh_css_sp_stage));
        return xmem_sp_stage_ptrs[pipe][stage];
}

ia_css_ptr sh_css_store_isp_stage_to_ddr(
    unsigned int pipe,
    unsigned int stage)
{
        IA_CSS_ENTER_LEAVE_PRIVATE("void");
        hmm_store(xmem_isp_stage_ptrs[pipe][stage],
                   &sh_css_isp_stage,
                   sizeof(struct sh_css_isp_stage));
        return xmem_isp_stage_ptrs[pipe][stage];
}

static int ref_sh_css_ddr_address_map(
    struct sh_css_ddr_address_map *map,
    struct sh_css_ddr_address_map *out)
{
        int err = 0;
        unsigned int i;

        /* we will use a union to copy things; overlaying an array
           with the struct; that way adding fields in the struct
           will keep things working, and we will not get type errors.
        */
        union {
                struct sh_css_ddr_address_map *map;
                ia_css_ptr *addrs;
        } in_addrs, to_addrs;

        IA_CSS_ENTER_PRIVATE("void");
        assert(map);
        assert(out);

        in_addrs.map = map;
        to_addrs.map = out;

        assert(sizeof(struct sh_css_ddr_address_map_size) / sizeof(size_t) ==
               sizeof(struct sh_css_ddr_address_map) / sizeof(ia_css_ptr));

        /* copy map using size info */
        for (i = 0; i < (sizeof(struct sh_css_ddr_address_map_size) /
                         sizeof(size_t)); i++) {
                if (in_addrs.addrs[i] == mmgr_NULL)
                        to_addrs.addrs[i] = mmgr_NULL;
                else
                        to_addrs.addrs[i] = ia_css_refcount_increment(IA_CSS_REFCOUNT_PARAM_BUFFER,
                                            in_addrs.addrs[i]);
        }

        IA_CSS_LEAVE_ERR_PRIVATE(err);
        return err;
}

static int write_ia_css_isp_parameter_set_info_to_ddr(
    struct ia_css_isp_parameter_set_info *me,
    ia_css_ptr *out)
{
        int err = 0;
        bool succ;

        IA_CSS_ENTER_PRIVATE("void");

        assert(me);
        assert(out);

        *out = ia_css_refcount_increment(IA_CSS_REFCOUNT_PARAM_SET_POOL,
                                         hmm_alloc(sizeof(struct ia_css_isp_parameter_set_info)));
        succ = (*out != mmgr_NULL);
        if (succ)
                hmm_store(*out,
                           me, sizeof(struct ia_css_isp_parameter_set_info));
        else
                err = -ENOMEM;

        IA_CSS_LEAVE_ERR_PRIVATE(err);
        return err;
}

static int
free_ia_css_isp_parameter_set_info(
    ia_css_ptr ptr)
{
        int err = 0;
        struct ia_css_isp_parameter_set_info isp_params_info;
        unsigned int i;
        ia_css_ptr *addrs = (ia_css_ptr *)&isp_params_info.mem_map;

        IA_CSS_ENTER_PRIVATE("ptr = %u", ptr);

        /* sanity check - ptr must be valid */
        if (!ia_css_refcount_is_valid(ptr)) {
                IA_CSS_ERROR("%s: IA_CSS_REFCOUNT_PARAM_SET_POOL(0x%x) invalid arg", __func__,
                             ptr);
                err = -EINVAL;
                IA_CSS_LEAVE_ERR_PRIVATE(err);
                return err;
        }

        hmm_load(ptr, &isp_params_info.mem_map, sizeof(struct sh_css_ddr_address_map));
        /* copy map using size info */
        for (i = 0; i < (sizeof(struct sh_css_ddr_address_map_size) /
                         sizeof(size_t)); i++) {
                if (addrs[i] == mmgr_NULL)
                        continue;

                /* sanity check - ptr must be valid */
                if (!ia_css_refcount_is_valid(addrs[i])) {
                        IA_CSS_ERROR("%s: IA_CSS_REFCOUNT_PARAM_BUFFER(0x%x) invalid arg", __func__,
                                     ptr);
                        err = -EINVAL;
                        continue;
                }

                ia_css_refcount_decrement(IA_CSS_REFCOUNT_PARAM_BUFFER, addrs[i]);
        }
        ia_css_refcount_decrement(IA_CSS_REFCOUNT_PARAM_SET_POOL, ptr);

        IA_CSS_LEAVE_ERR_PRIVATE(err);
        return err;
}

/* Mark all parameters as changed to force recomputing the derived ISP parameters */
void
sh_css_invalidate_params(struct ia_css_stream *stream)
{
        struct  ia_css_isp_parameters *params;
        unsigned int i, j, mem;

        IA_CSS_ENTER_PRIVATE("void");
        assert(stream);

        params = stream->isp_params_configs;
        params->isp_params_changed = true;
        for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
                for (j = 0; j < SH_CSS_MAX_STAGES; j++) {
                        for (mem = 0; mem < N_IA_CSS_MEMORIES; mem++) {
                                params->isp_mem_params_changed[i][j][mem] = true;
                        }
                }
        }

        memset(&params->config_changed[0], 1, sizeof(params->config_changed));
        params->dis_coef_table_changed = true;
        params->dvs2_coef_table_changed = true;
        params->morph_table_changed = true;
        params->sc_table_changed = true;
        params->dz_config_changed = true;
        params->motion_config_changed = true;

        /*Free up theDVS table memory blocks before recomputing new table  */
        for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
                if (params->pipe_dvs_6axis_config[i]) {
                        free_dvs_6axis_table(&params->pipe_dvs_6axis_config[i]);
                        params->pipe_dvs_6axis_config_changed[i] = true;
                }
        }

        IA_CSS_LEAVE_PRIVATE("void");
}

void
sh_css_update_uds_and_crop_info(
    const struct ia_css_binary_info *info,
    const struct ia_css_frame_info *in_frame_info,
    const struct ia_css_frame_info *out_frame_info,
    const struct ia_css_resolution *dvs_env,
    const struct ia_css_dz_config *zoom,
    const struct ia_css_vector *motion_vector,
    struct sh_css_uds_info *uds,                /* out */
    struct sh_css_crop_pos *sp_out_crop_pos,    /* out */

    bool enable_zoom)
{
        IA_CSS_ENTER_PRIVATE("void");

        assert(info);
        assert(in_frame_info);
        assert(out_frame_info);
        assert(dvs_env);
        assert(zoom);
        assert(motion_vector);
        assert(uds);
        assert(sp_out_crop_pos);

        uds->curr_dx   = enable_zoom ? (uint16_t)zoom->dx : HRT_GDC_N;
        uds->curr_dy   = enable_zoom ? (uint16_t)zoom->dy : HRT_GDC_N;

        if (info->enable.dvs_envelope) {
                unsigned int crop_x = 0,
                             crop_y = 0,
                             uds_xc = 0,
                             uds_yc = 0,
                             env_width, env_height;
                int half_env_x, half_env_y;
                int motion_x = motion_vector->x;
                int motion_y = motion_vector->y;
                bool upscale_x = in_frame_info->res.width < out_frame_info->res.width;
                bool upscale_y = in_frame_info->res.height < out_frame_info->res.height;

                if (info->enable.uds && !info->enable.ds) {
                        /**
                         * we calculate with the envelope that we can actually
                         * use, the min dvs envelope is for the filter
                         * initialization.
                         */
                        env_width  = dvs_env->width -
                                     SH_CSS_MIN_DVS_ENVELOPE;
                        env_height = dvs_env->height -
                                     SH_CSS_MIN_DVS_ENVELOPE;
                        half_env_x = env_width / 2;
                        half_env_y = env_height / 2;
                        /**
                         * for digital zoom, we use the dvs envelope and make
                         * sure that we don't include the 8 leftmost pixels or
                         * 8 topmost rows.
                         */
                        if (upscale_x) {
                                uds_xc = (in_frame_info->res.width
                                          + env_width
                                          + SH_CSS_MIN_DVS_ENVELOPE) / 2;
                        } else {
                                uds_xc = (out_frame_info->res.width
                                          + env_width) / 2
                                         + SH_CSS_MIN_DVS_ENVELOPE;
                        }
                        if (upscale_y) {
                                uds_yc = (in_frame_info->res.height
                                          + env_height
                                          + SH_CSS_MIN_DVS_ENVELOPE) / 2;
                        } else {
                                uds_yc = (out_frame_info->res.height
                                          + env_height) / 2
                                         + SH_CSS_MIN_DVS_ENVELOPE;
                        }
                        /* clip the motion vector to +/- half the envelope */
                        motion_x = clamp(motion_x, -half_env_x, half_env_x);
                        motion_y = clamp(motion_y, -half_env_y, half_env_y);
                        uds_xc += motion_x;
                        uds_yc += motion_y;
                        /* uds can be pipelined, remove top lines */
                        crop_y = 2;
                } else if (info->enable.ds) {
                        env_width  = dvs_env->width;
                        env_height = dvs_env->height;
                        half_env_x = env_width / 2;
                        half_env_y = env_height / 2;
                        /* clip the motion vector to +/- half the envelope */
                        motion_x = clamp(motion_x, -half_env_x, half_env_x);
                        motion_y = clamp(motion_y, -half_env_y, half_env_y);
                        /* for video with downscaling, the envelope is included
                            in the input resolution. */
                        uds_xc = in_frame_info->res.width / 2 + motion_x;
                        uds_yc = in_frame_info->res.height / 2 + motion_y;
                        crop_x = info->pipeline.left_cropping;
                        /* ds == 2 (yuv_ds) can be pipelined, remove top
                           lines */
                        if (info->enable.ds & 1)
                                crop_y = info->pipeline.top_cropping;
                        else
                                crop_y = 2;
                } else {
                        /* video nodz: here we can only crop. We make sure we
                           crop at least the first 8x8 pixels away. */
                        env_width  = dvs_env->width -
                                     SH_CSS_MIN_DVS_ENVELOPE;
                        env_height = dvs_env->height -
                                     SH_CSS_MIN_DVS_ENVELOPE;
                        half_env_x = env_width / 2;
                        half_env_y = env_height / 2;
                        motion_x = clamp(motion_x, -half_env_x, half_env_x);
                        motion_y = clamp(motion_y, -half_env_y, half_env_y);
                        crop_x = SH_CSS_MIN_DVS_ENVELOPE
                                 + half_env_x + motion_x;
                        crop_y = SH_CSS_MIN_DVS_ENVELOPE
                                 + half_env_y + motion_y;
                }

                /* Must enforce that the crop position is even */
                crop_x = round_down(crop_x, 2);
                crop_y = round_down(crop_y, 2);
                uds_xc = round_down(uds_xc, 2);
                uds_yc = round_down(uds_yc, 2);

                uds->xc = (uint16_t)uds_xc;
                uds->yc = (uint16_t)uds_yc;
                sp_out_crop_pos->x = (uint16_t)crop_x;
                sp_out_crop_pos->y = (uint16_t)crop_y;
        } else {
                /* for down scaling, we always use the center of the image */
                uds->xc = (uint16_t)in_frame_info->res.width / 2;
                uds->yc = (uint16_t)in_frame_info->res.height / 2;
                sp_out_crop_pos->x = (uint16_t)info->pipeline.left_cropping;
                sp_out_crop_pos->y = (uint16_t)info->pipeline.top_cropping;
        }
        IA_CSS_LEAVE_PRIVATE("void");
}

static int
sh_css_update_uds_and_crop_info_based_on_zoom_region(
    const struct ia_css_binary_info *info,
    const struct ia_css_frame_info *in_frame_info,
    const struct ia_css_frame_info *out_frame_info,
    const struct ia_css_resolution *dvs_env,
    const struct ia_css_dz_config *zoom,
    const struct ia_css_vector *motion_vector,
    struct sh_css_uds_info *uds,                /* out */
    struct sh_css_crop_pos *sp_out_crop_pos,    /* out */
    struct ia_css_resolution pipe_in_res,
    bool enable_zoom)
{
        unsigned int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
        int err = 0;
        /* Note:
        * Filter_Envelope = 0 for NND/LUT
        * Filter_Envelope = 1 for BCI
        * Filter_Envelope = 3 for BLI
        * Currently, not considering this filter envelope because, In uds.sp.c is recalculating
        * the dx/dy based on filter envelope and other information (ia_css_uds_sp_scale_params)
        * Ideally, That should be done on host side not on sp side.
        */
        unsigned int filter_envelope = 0;

        IA_CSS_ENTER_PRIVATE("void");

        assert(info);
        assert(in_frame_info);
        assert(out_frame_info);
        assert(dvs_env);
        assert(zoom);
        assert(motion_vector);
        assert(uds);
        assert(sp_out_crop_pos);
        x0 = zoom->zoom_region.origin.x;
        y0 = zoom->zoom_region.origin.y;
        x1 = zoom->zoom_region.resolution.width + x0;
        y1 = zoom->zoom_region.resolution.height + y0;

        if ((x0 > x1) || (y0 > y1) || (x1 > pipe_in_res.width) || (y1 > pipe_in_res.height))
                return -EINVAL;

        if (!enable_zoom) {
                uds->curr_dx = HRT_GDC_N;
                uds->curr_dy = HRT_GDC_N;
        }

        if (info->enable.dvs_envelope) {
                /* Zoom region is only supported by the UDS module on ISP
                 * 2 and higher. It is not supported in video mode on ISP 1 */
                return -EINVAL;
        } else {
                if (enable_zoom) {
                        /* A. Calculate dx/dy based on crop region using in_frame_info
                        * Scale the crop region if in_frame_info to the stage is not same as
                        * actual effective input of the pipeline
                        */
                        if (in_frame_info->res.width != pipe_in_res.width ||
                            in_frame_info->res.height != pipe_in_res.height) {
                                x0 = (x0 * in_frame_info->res.width) / (pipe_in_res.width);
                                y0 = (y0 * in_frame_info->res.height) / (pipe_in_res.height);
                                x1 = (x1 * in_frame_info->res.width) / (pipe_in_res.width);
                                y1 = (y1 * in_frame_info->res.height) / (pipe_in_res.height);
                        }
                        uds->curr_dx =
                            ((x1 - x0 - filter_envelope) * HRT_GDC_N) / in_frame_info->res.width;
                        uds->curr_dy =
                            ((y1 - y0 - filter_envelope) * HRT_GDC_N) / in_frame_info->res.height;

                        /* B. Calculate xc/yc based on crop region */
                        uds->xc = (uint16_t)x0 + (((x1) - (x0)) / 2);
                        uds->yc = (uint16_t)y0 + (((y1) - (y0)) / 2);
                } else {
                        uds->xc = (uint16_t)in_frame_info->res.width / 2;
                        uds->yc = (uint16_t)in_frame_info->res.height / 2;
                }

                ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
                                    "uds->curr_dx=%d, uds->xc=%d, uds->yc=%d\n",
                                    uds->curr_dx, uds->xc, uds->yc);
                ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "x0=%d, y0=%d, x1=%d, y1=%d\n",
                                    x0, y0, x1, y1);
                sp_out_crop_pos->x = (uint16_t)info->pipeline.left_cropping;
                sp_out_crop_pos->y = (uint16_t)info->pipeline.top_cropping;
        }
        IA_CSS_LEAVE_PRIVATE("void");
        return err;
}

struct ia_css_3a_statistics *
ia_css_3a_statistics_allocate(const struct ia_css_3a_grid_info *grid)
{
        struct ia_css_3a_statistics *me;
        int grid_size;

        IA_CSS_ENTER("grid=%p", grid);

        assert(grid);

        me = kvzalloc_objs(*me, 1);
        if (!me)
                goto err;

        me->grid = *grid;
        grid_size = grid->width * grid->height;
        me->data = kvmalloc(grid_size * sizeof(*me->data), GFP_KERNEL);
        if (!me->data)
                goto err;
        /* No weighted histogram, no structure, treat the histogram data as a byte dump in a byte array */
        me->rgby_data = kvmalloc(sizeof_hmem(HMEM0_ID), GFP_KERNEL);
        if (!me->rgby_data)
                goto err;

        IA_CSS_LEAVE("return=%p", me);
        return me;
err:
        ia_css_3a_statistics_free(me);

        IA_CSS_LEAVE("return=%p", NULL);
        return NULL;
}

void
ia_css_3a_statistics_free(struct ia_css_3a_statistics *me)
{
        if (me) {
                kvfree(me->rgby_data);
                kvfree(me->data);
                kvfree(me);
        }
}

struct ia_css_dvs_statistics *
ia_css_dvs_statistics_allocate(const struct ia_css_dvs_grid_info *grid)
{
        struct ia_css_dvs_statistics *me;

        assert(grid);

        me = kvzalloc_objs(*me, 1);
        if (!me)
                goto err;

        me->grid = *grid;
        me->hor_proj = kvmalloc(grid->height * IA_CSS_DVS_NUM_COEF_TYPES *
                                sizeof(*me->hor_proj), GFP_KERNEL);
        if (!me->hor_proj)
                goto err;

        me->ver_proj = kvmalloc(grid->width * IA_CSS_DVS_NUM_COEF_TYPES *
                                sizeof(*me->ver_proj), GFP_KERNEL);
        if (!me->ver_proj)
                goto err;

        return me;
err:
        ia_css_dvs_statistics_free(me);
        return NULL;
}

void
ia_css_dvs_statistics_free(struct ia_css_dvs_statistics *me)
{
        if (me) {
                kvfree(me->hor_proj);
                kvfree(me->ver_proj);
                kvfree(me);
        }
}

struct ia_css_dvs_coefficients *
ia_css_dvs_coefficients_allocate(const struct ia_css_dvs_grid_info *grid)
{
        struct ia_css_dvs_coefficients *me;

        assert(grid);

        me = kvzalloc_objs(*me, 1);
        if (!me)
                goto err;

        me->grid = *grid;

        me->hor_coefs = kvmalloc(grid->num_hor_coefs *
                                 IA_CSS_DVS_NUM_COEF_TYPES *
                                 sizeof(*me->hor_coefs), GFP_KERNEL);
        if (!me->hor_coefs)
                goto err;

        me->ver_coefs = kvmalloc(grid->num_ver_coefs *
                                 IA_CSS_DVS_NUM_COEF_TYPES *
                                 sizeof(*me->ver_coefs), GFP_KERNEL);
        if (!me->ver_coefs)
                goto err;

        return me;
err:
        ia_css_dvs_coefficients_free(me);
        return NULL;
}

void
ia_css_dvs_coefficients_free(struct ia_css_dvs_coefficients *me)
{
        if (me) {
                kvfree(me->hor_coefs);
                kvfree(me->ver_coefs);
                kvfree(me);
        }
}

struct ia_css_dvs2_statistics *
ia_css_dvs2_statistics_allocate(const struct ia_css_dvs_grid_info *grid)
{
        struct ia_css_dvs2_statistics *me;

        assert(grid);

        me = kvzalloc_objs(*me, 1);
        if (!me)
                goto err;

        me->grid = *grid;

        me->hor_prod.odd_real = kvmalloc(grid->aligned_width *
                                         grid->aligned_height *
                                         sizeof(*me->hor_prod.odd_real),
                                         GFP_KERNEL);
        if (!me->hor_prod.odd_real)
                goto err;

        me->hor_prod.odd_imag = kvmalloc(grid->aligned_width *
                                         grid->aligned_height *
                                         sizeof(*me->hor_prod.odd_imag),
                                         GFP_KERNEL);
        if (!me->hor_prod.odd_imag)
                goto err;

        me->hor_prod.even_real = kvmalloc(grid->aligned_width *
                                          grid->aligned_height *
                                          sizeof(*me->hor_prod.even_real),
                                          GFP_KERNEL);
        if (!me->hor_prod.even_real)
                goto err;

        me->hor_prod.even_imag = kvmalloc(grid->aligned_width *
                                          grid->aligned_height *
                                          sizeof(*me->hor_prod.even_imag),
                                          GFP_KERNEL);
        if (!me->hor_prod.even_imag)
                goto err;

        me->ver_prod.odd_real = kvmalloc(grid->aligned_width *
                                         grid->aligned_height *
                                         sizeof(*me->ver_prod.odd_real),
                                         GFP_KERNEL);
        if (!me->ver_prod.odd_real)
                goto err;

        me->ver_prod.odd_imag = kvmalloc(grid->aligned_width *
                                         grid->aligned_height *
                                         sizeof(*me->ver_prod.odd_imag),
                                         GFP_KERNEL);
        if (!me->ver_prod.odd_imag)
                goto err;

        me->ver_prod.even_real = kvmalloc(grid->aligned_width *
                                          grid->aligned_height *
                                          sizeof(*me->ver_prod.even_real),
                                          GFP_KERNEL);
        if (!me->ver_prod.even_real)
                goto err;

        me->ver_prod.even_imag = kvmalloc(grid->aligned_width *
                                          grid->aligned_height *
                                          sizeof(*me->ver_prod.even_imag),
                                          GFP_KERNEL);
        if (!me->ver_prod.even_imag)
                goto err;

        return me;
err:
        ia_css_dvs2_statistics_free(me);
        return NULL;
}

void
ia_css_dvs2_statistics_free(struct ia_css_dvs2_statistics *me)
{
        if (me) {
                kvfree(me->hor_prod.odd_real);
                kvfree(me->hor_prod.odd_imag);
                kvfree(me->hor_prod.even_real);
                kvfree(me->hor_prod.even_imag);
                kvfree(me->ver_prod.odd_real);
                kvfree(me->ver_prod.odd_imag);
                kvfree(me->ver_prod.even_real);
                kvfree(me->ver_prod.even_imag);
                kvfree(me);
        }
}

struct ia_css_dvs2_coefficients *
ia_css_dvs2_coefficients_allocate(const struct ia_css_dvs_grid_info *grid)
{
        struct ia_css_dvs2_coefficients *me;

        assert(grid);

        me = kvzalloc_objs(*me, 1);
        if (!me)
                goto err;

        me->grid = *grid;

        me->hor_coefs.odd_real = kvmalloc(grid->num_hor_coefs *
                                          sizeof(*me->hor_coefs.odd_real),
                                          GFP_KERNEL);
        if (!me->hor_coefs.odd_real)
                goto err;

        me->hor_coefs.odd_imag = kvmalloc(grid->num_hor_coefs *
                                          sizeof(*me->hor_coefs.odd_imag),
                                          GFP_KERNEL);
        if (!me->hor_coefs.odd_imag)
                goto err;

        me->hor_coefs.even_real = kvmalloc(grid->num_hor_coefs *
                                           sizeof(*me->hor_coefs.even_real),
                                           GFP_KERNEL);
        if (!me->hor_coefs.even_real)
                goto err;

        me->hor_coefs.even_imag = kvmalloc(grid->num_hor_coefs *
                                           sizeof(*me->hor_coefs.even_imag),
                                           GFP_KERNEL);
        if (!me->hor_coefs.even_imag)
                goto err;

        me->ver_coefs.odd_real = kvmalloc(grid->num_ver_coefs *
                                          sizeof(*me->ver_coefs.odd_real),
                                          GFP_KERNEL);
        if (!me->ver_coefs.odd_real)
                goto err;

        me->ver_coefs.odd_imag = kvmalloc(grid->num_ver_coefs *
                                          sizeof(*me->ver_coefs.odd_imag),
                                          GFP_KERNEL);
        if (!me->ver_coefs.odd_imag)
                goto err;

        me->ver_coefs.even_real = kvmalloc(grid->num_ver_coefs *
                                           sizeof(*me->ver_coefs.even_real),
                                           GFP_KERNEL);
        if (!me->ver_coefs.even_real)
                goto err;

        me->ver_coefs.even_imag = kvmalloc(grid->num_ver_coefs *
                                           sizeof(*me->ver_coefs.even_imag),
                                           GFP_KERNEL);
        if (!me->ver_coefs.even_imag)
                goto err;

        return me;
err:
        ia_css_dvs2_coefficients_free(me);
        return NULL;
}

void
ia_css_dvs2_coefficients_free(struct ia_css_dvs2_coefficients *me)
{
        if (me) {
                kvfree(me->hor_coefs.odd_real);
                kvfree(me->hor_coefs.odd_imag);
                kvfree(me->hor_coefs.even_real);
                kvfree(me->hor_coefs.even_imag);
                kvfree(me->ver_coefs.odd_real);
                kvfree(me->ver_coefs.odd_imag);
                kvfree(me->ver_coefs.even_real);
                kvfree(me->ver_coefs.even_imag);
                kvfree(me);
        }
}

struct ia_css_dvs_6axis_config *
ia_css_dvs2_6axis_config_allocate(const struct ia_css_stream *stream)
{
        struct ia_css_dvs_6axis_config *dvs_config = NULL;
        struct ia_css_isp_parameters *params = NULL;
        unsigned int width_y;
        unsigned int height_y;
        unsigned int width_uv;
        unsigned int height_uv;

        assert(stream);
        params = stream->isp_params_configs;

        /* Backward compatibility by default consider pipe as Video*/
        if (!params || !params->pipe_dvs_6axis_config[IA_CSS_PIPE_ID_VIDEO])
                goto err;

        dvs_config = kvzalloc_objs(struct ia_css_dvs_6axis_config, 1);
        if (!dvs_config)
                goto err;

        dvs_config->width_y = width_y =
                                  params->pipe_dvs_6axis_config[IA_CSS_PIPE_ID_VIDEO]->width_y;
        dvs_config->height_y = height_y =
                                   params->pipe_dvs_6axis_config[IA_CSS_PIPE_ID_VIDEO]->height_y;
        dvs_config->width_uv = width_uv =
                                   params->pipe_dvs_6axis_config[IA_CSS_PIPE_ID_VIDEO]->width_uv;
        dvs_config->height_uv = height_uv =
                                    params->pipe_dvs_6axis_config[IA_CSS_PIPE_ID_VIDEO]->height_uv;
        IA_CSS_LOG("table Y: W %d H %d", width_y, height_y);
        IA_CSS_LOG("table UV: W %d H %d", width_uv, height_uv);
        dvs_config->xcoords_y = kvmalloc(width_y * height_y * sizeof(uint32_t),
                                         GFP_KERNEL);
        if (!dvs_config->xcoords_y)
                goto err;

        dvs_config->ycoords_y = kvmalloc(width_y * height_y * sizeof(uint32_t),
                                         GFP_KERNEL);
        if (!dvs_config->ycoords_y)
                goto err;

        dvs_config->xcoords_uv = kvmalloc(width_uv * height_uv *
                                          sizeof(uint32_t),
                                          GFP_KERNEL);
        if (!dvs_config->xcoords_uv)
                goto err;

        dvs_config->ycoords_uv = kvmalloc(width_uv * height_uv *
                                          sizeof(uint32_t),
                                          GFP_KERNEL);
        if (!dvs_config->ycoords_uv)
                goto err;

        return dvs_config;
err:
        ia_css_dvs2_6axis_config_free(dvs_config);
        return NULL;
}

void
ia_css_dvs2_6axis_config_free(struct ia_css_dvs_6axis_config *dvs_6axis_config)
{
        if (dvs_6axis_config) {
                kvfree(dvs_6axis_config->xcoords_y);
                kvfree(dvs_6axis_config->ycoords_y);
                kvfree(dvs_6axis_config->xcoords_uv);
                kvfree(dvs_6axis_config->ycoords_uv);
                kvfree(dvs_6axis_config);
        }
}

void
ia_css_en_dz_capt_pipe(struct ia_css_stream *stream, bool enable)
{
        struct ia_css_pipe *pipe;
        struct ia_css_pipeline *pipeline;
        struct ia_css_pipeline_stage *stage;
        enum ia_css_pipe_id pipe_id;
        int err;
        int i;

        if (!stream)
                return;

        for (i = 0; i < stream->num_pipes; i++) {
                pipe = stream->pipes[i];
                pipeline = ia_css_pipe_get_pipeline(pipe);
                pipe_id = pipeline->pipe_id;

                if (pipe_id == IA_CSS_PIPE_ID_CAPTURE) {
                        err = ia_css_pipeline_get_stage(pipeline, IA_CSS_BINARY_MODE_CAPTURE_PP,
                                                        &stage);
                        if (!err)
                                stage->enable_zoom = enable;
                        break;
                }
        }
}