You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

356 lines
15 KiB

#include "rk_aiq_isp39_modules.h"
//////////////////////////////////////////////////////////////////////////
#define RKCNR_V31_MAX_DOWN_SCALE 8
// iir params
#define RKCNR_V31_FIX_BIT_BF_RATIO 10
#define RKCNR_V31_FIX_BIT_IIR_WGT 6//10
#define RKCNR_V31_FIX_BIT_INV_SIGMA 15
#define RKCNR_V31_FIX_BIT_SLOPE 7
#define RKCNR_V31_FIX_BIT_WGT_RATIO 3
#define RKCNR_V31_FIX_BIT_INT_TO_FLOAT 7
// gain params
#define RKCNR_V31_SIGMA_FIX_BIT 8
#define RKCNR_V31_LOCAL_GAIN_FIX_BITS 4
#define RKCNR_V31_G_GAIN_FIX_BITS 4
#define RKCNR_V31_G_GAIN_ALPHA_FIX_BITS 3
#define RKCNR_V31_GAIN_ISO_FIX_BITS 7
// 3x3 bf params
#define RKCNR_V31_FIX_BIT_GAUS_RATIO 10
#define RKCNR_V31_sgmRatio 6
#define RKCNR_V31_log2e 6
#define RKCNR_V31_uvgain 4
#define RKCNR_V31_exp2_lut_y 7
#define RKCNR_V31_bfRatio RKCNR_V31_exp2_lut_y
// saturation adj param fix bit
#define RKCNR_V31_FIX_BIT_SATURATION 10
// global alpha fix bit
#define RKCNR_V31_FIX_BIT_GLOBAL_ALPHA 10
// div sum wgt fix bit
#define RKCNR_V31_FIX_BIT_DIV_SUM_WGT 22//
#define RKCNR_V31_FIX_BIT_DIST_SCALE 7
//////////////////////////////////////////////////////////////////////////
// params
#define RKCNR_V31_THUMB_BF_RADIUS 3
#define RKCNR_V31_IIR_RADIUSY 1
#define RKCNR_V31_IIR_RADIUSX 3//1
#define RKCNR_V31_BF_RADIUS 1
#define RKCNR_V31_IIR_COEFF_NUM 10
#define RKCNR_V31_SGM_ADJ_TABLE_LEN 13
// extend of down scale yuv, 3x3 IIR, 3x3 bf
#define RKCNR_V31_DS_EXTEND_Y (RKCNR_V31_IIR_RADIUSY)
#define RKCNR_V31_DS_EXTEND_X (RKCNR_V31_IIR_RADIUSX)
#define RKCNR_V31_GAUS_RADIUS 2
#define RKCNR_V31_CLIP_RADIUS 1
#define cnr_422_5x5_gaus 0 // 422: 5x3 or 5x5 gaussian filter
// global alpha fix bit
#define RKCNR_V32_FIX_BIT_GLOBAL_ALPHA 10
#define Math_LOG2(x) (log((double)x) / log((double)2))
void cnr_CreateKernelCoeffs_V32(int radius_x, int radius_y, float rsigma, uint8_t *kernel_coeffs, int fix_bits)
{
double e = 2.71828182845905;
float coeff_float[(2 * radius_y + 1) * (2 * radius_x + 1)];
float sumTable = 0;
for(int y = -radius_y; y <= radius_y; y ++)
{
for(int x = -radius_x; x <= radius_x; x ++)
{
float dis = y * y + x * x;
float coeff = pow(e, -dis / 2.0 / rsigma / rsigma);
coeff_float[(y + radius_y) * (2 * radius_x + 1) + x + radius_x] = coeff;
sumTable += coeff;
}
}
int sum_coeff = 0;
for (int i = 0; i < (2 * radius_x + 1) * (2 * radius_y + 1); i++) {
float coeff = coeff_float[i];
coeff = coeff / sumTable;
coeff = ROUND_F(coeff * (1 << fix_bits));
kernel_coeffs[i] = coeff;
sum_coeff += coeff;
}
// check coeff
int offset = (1 << fix_bits) - sum_coeff;
kernel_coeffs[radius_y * (2 * radius_x + 1) + radius_x] = kernel_coeffs[radius_y * (2 * radius_x + 1) + radius_x] + offset;
}
void rk_aiq_cnr34_params_cvt(void* attr, isp_params_t* isp_params, common_cvt_info_t *cvtinfo)
{
float fStrength = 1.0;
int i, tmp;
#if RKAIQ_HAVE_CNR_V31
struct isp39_cnr_cfg *pFix = &isp_params->isp_cfg->others.cnr_cfg;
#elif RKAIQ_HAVE_CNR_V35
struct isp33_cnr_cfg *pFix = &isp_params->isp_cfg->others.cnr_cfg;
#elif RKAIQ_HAVE_CNR_V36
struct isp35_cnr_cfg *pFix = &isp_params->isp_cfg->others.cnr_cfg;
#endif
cnr_param_t *cnr_param = (cnr_param_t *) attr;
cnr_params_dyn_t* pdyn = &cnr_param->dyn;
int rows = cvtinfo->rawHeight;
int cols = cvtinfo->rawWidth;
// CNR_CTRL
if (pdyn->loNrGuide_preProc.hw_cnrT_ds_mode == cnr_ds_4x4_mode ) {
pFix->thumb_mode = 1;
} else {
pFix->thumb_mode = 3;
}
pFix->yuv422_mode = 0;
// pFix->exgain_bypass = pSelect->hw_cnrT_exgain_bypass;
pFix->hiflt_wgt0_mode = pdyn->hiNr_bifilt.hw_cnrT_filtWgtZero_mode;
#if defined(RKAIQ_HAVE_CNR_V35) || defined(RKAIQ_HAVE_CNR_V36)
pFix->local_alpha_dis = !pdyn->hiNr_locFiltAlpha.hw_cnrT_locFiltAlpha_en;
#endif
pFix->loflt_coeff = (pdyn->loNrGuide_iirFilt.hw_cnrT_filtSpatial_wgt[0] & 0x01 << 0)
| ((pdyn->loNrGuide_iirFilt.hw_cnrT_filtSpatial_wgt[1] & 0x01) << 1)
| ((pdyn->loNrGuide_iirFilt.hw_cnrT_filtSpatial_wgt[2] & 0x01) << 2)
| ((pdyn->loNrGuide_iirFilt.hw_cnrT_filtSpatial_wgt[2] & 0x01) << 3)
| ((pdyn->loNrGuide_iirFilt.hw_cnrT_filtSpatial_wgt[1] & 0x01) << 4)
| ((pdyn->loNrGuide_iirFilt.hw_cnrT_filtSpatial_wgt[0] & 0x01) << 5);
// CNR_EXGAIN
tmp = pdyn->locSgmStrg.hw_cnrT_locSgmStrg_scale * (1 << RKCNR_V31_GAIN_ISO_FIX_BITS);
pFix->local_gain_scale = CLIP(tmp, 0, 0xff);
tmp = pdyn->locSgmStrg.hw_cnrT_glbSgmStrg_alpha * (1 << RKCNR_V31_G_GAIN_ALPHA_FIX_BITS);
pFix->global_gain_alpha = CLIP(tmp, 0, 0x8);
tmp = pdyn->locSgmStrg.hw_cnrT_glbSgmStrg_val * (1 << RKCNR_V31_G_GAIN_FIX_BITS);
pFix->global_gain = CLIP(tmp, 0, 0x3ff);
/* CNR_THUMB1 */
int yuvBit = 10;
int scale = (1 << yuvBit) - 1;
int log2e = (int)(0.8493f * (1 << (RKCNR_V31_log2e + RKCNR_V31_SIGMA_FIX_BIT)));
int rkcnr_sw_cnrT_loFltUV_gain = ROUND_F((1 << RKCNR_V31_uvgain) * pdyn->loNrGuide_preProc.hw_cnrT_uvEdg_strg);
int thumbBFilterSigma = ROUND_F(pdyn->loNrGuide_bifilt.sw_cnrT_rgeSgm_val * scale * fStrength);
thumbBFilterSigma = (int)(0.8493f * (1 << RKCNR_V31_FIX_BIT_INV_SIGMA) / thumbBFilterSigma);
tmp = thumbBFilterSigma * ((1 << RKCNR_V31_uvgain) - rkcnr_sw_cnrT_loFltUV_gain * 2);
tmp = ROUND_INT(tmp, 6);
pFix->lobfflt_vsigma_y = CLIP(tmp, 0, 0x3fff);
tmp = thumbBFilterSigma * rkcnr_sw_cnrT_loFltUV_gain;
tmp = ROUND_INT(tmp, 6); // (diff * sigma) >> tmp = (diff * (sigma >> 6))
pFix->lobfflt_vsigma_uv = CLIP(tmp, 0, 0x3fff);
/* CNR_THUMB_BF_RATIO */
tmp = ROUND_F((1 << RKCNR_V31_FIX_BIT_BF_RATIO) * pdyn->loNrGuide_bifilt.hw_cnrT_bifiltOut_alpha * fStrength);
pFix->lobfflt_alpha = CLIP(tmp, 0, 0x7ff);
/* CNR_LBF_WEITD */
if (pdyn->loNrGuide_bifilt.sw_cnrT_filtCfg_mode == cnr_cfgByFiltStrg_mode) {
uint8_t gaus_tmp[7];
cnr_CreateKernelCoeffs_V32(RKCNR_V31_THUMB_BF_RADIUS, 0, pdyn->loNrGuide_bifilt.sw_cnrT_filtSpatial_strg, gaus_tmp, RKCNR_V31_exp2_lut_y);
pFix->thumb_bf_coeff0 = CLIP(gaus_tmp[0], 0, 0xff);
pFix->thumb_bf_coeff1 = CLIP(gaus_tmp[1], 0, 0xff);
pFix->thumb_bf_coeff2 = CLIP(gaus_tmp[2], 0, 0xff);
pFix->thumb_bf_coeff3 = CLIP(gaus_tmp[3], 0, 0xff);
} else {
tmp = ROUND_F(pdyn->loNrGuide_bifilt.hw_cnrT_filtSpatial_wgt[0] * (1 << RKCNR_V31_exp2_lut_y));
pFix->thumb_bf_coeff0 = CLIP(tmp, 0, 0xff);
tmp = ROUND_F(pdyn->loNrGuide_bifilt.hw_cnrT_filtSpatial_wgt[1] * (1 << RKCNR_V31_exp2_lut_y));
pFix->thumb_bf_coeff1 = CLIP(tmp, 0, 0xff);
tmp = ROUND_F(pdyn->loNrGuide_bifilt.hw_cnrT_filtSpatial_wgt[2] * (1 << RKCNR_V31_exp2_lut_y));
pFix->thumb_bf_coeff2 = CLIP(tmp, 0, 0xff);
tmp = ROUND_F(pdyn->loNrGuide_bifilt.hw_cnrT_filtSpatial_wgt[3] * (1 << RKCNR_V31_exp2_lut_y));
pFix->thumb_bf_coeff3 = CLIP(tmp, 0, 0xff);
}
/* CNR_IIR_PARA1 */
tmp = ROUND_F((1 << RKCNR_V31_FIX_BIT_SLOPE) * pdyn->loNrGuide_iirFilt.hw_cnrT_sgm2NhoodWgt_slope);
pFix->loflt_wgt_slope = CLIP(tmp, 0, 0x3ff);
tmp = ROUND_F(1.2011 * (1 << RKCNR_V31_FIX_BIT_INV_SIGMA) / (pdyn->loNrGuide_iirFilt.sw_cnrT_rgeSgm_val * scale * fStrength));
int tmptmp = tmp * pFix->loflt_wgt_slope;
int shiftBit = Math_LOG2(tmptmp) - RKCNR_V31_FIX_BIT_INT_TO_FLOAT;
shiftBit = MAX(shiftBit, 0);
tmp = RKCNR_V31_FIX_BIT_INV_SIGMA - shiftBit;
if (tmp < 0) {
tmp = ABS(tmp) + (1 << 5);
}
pFix->exp_x_shift_bit = CLIP(tmp, 0, 0x3f);
tmp = ROUND_F((float)tmptmp / (1 << shiftBit));
pFix->loflt_vsigma = CLIP(tmp, 0, 0xff);
tmp = ROUND_F((1 << RKCNR_V31_uvgain) * pdyn->loNrGuide_preProc.hw_cnrT_uvEdg_strg);
pFix->loflt_uv_gain = CLIP(tmp, 0, 0xf);
/* CNR_IIR_PARA2 */
tmp = ROUND_F((1 << RKCNR_V31_FIX_BIT_IIR_WGT) * pdyn->loNrGuide_iirFilt.hw_cnrT_nhoodWgtZero_thred);
pFix->loflt_wgt_min_thred = CLIP(tmp, 0, 0x3f);
tmp = ROUND_F((1 << 3) * pdyn->loNrGuide_iirFilt. hw_cnrT_iirFiltStrg_maxLimit);
pFix->loflt_wgt_max_limit = CLIP(tmp, 0, 0x7f);
/* CNR_GAUS_COE */
float gaus_table[6];
uint8_t gaus_reg[6];
if(pdyn->hiNr_preLpf.sw_cnrT_filtCfg_mode == cnr_cfgByFiltStrg_mode) {
float dis_table_5x5[6] = { 0.0, 1.0, 2.0, 4.0, 5.0, 8.0 };
float dis_table_5x3[6] = { 0.0, 1.0, 4.0, 1.0, 2.0, 5.0 };
float sigma = pdyn->hiNr_preLpf.sw_cnrT_filtSpatial_strg;
double e = 2.71828182845905;
float sumTable = 0;
if (0 == !pFix->yuv422_mode) {
for (int k = 0; k < 6; k++) {
float tmp = pow(e, -dis_table_5x5[k] / 2.0 / sigma / sigma);
gaus_table[k] = tmp;
}
} else {
for (int k = 0; k < 6; k++) {
float tmp = pow(e, -dis_table_5x3[k] / 2.0 / sigma / sigma);
gaus_table[k] = tmp;
}
}
} else {
for(int k = 0; k < 6; k++) {
gaus_table[k] = pdyn->hiNr_preLpf.hw_cnrT_filtSpatial_wgt[k];
}
}
//check gaus params
float sumTable = 0;
if (0 == !pFix->yuv422_mode) {
sumTable = gaus_table[0]
+ 4 * gaus_table[1]
+ 4 * gaus_table[2]
+ 4 * gaus_table[3]
+ 8 * gaus_table[4]
+ 4 * gaus_table[5];
} else {
sumTable = gaus_table[0]
+ 2 * gaus_table[1]
+ 2 * gaus_table[2]
+ 2 * gaus_table[3]
+ 4 * gaus_table[4]
+ 4 * gaus_table[5];
}
for (int k = 0; k < 6; k++) {
gaus_table[k] = gaus_table[k] / sumTable;
tmp = ROUND_F(gaus_table[k] * (1 << 8));
gaus_reg[k] = CLIP(tmp, 0, 0x7f);
}
int sum_coeff = 0;
if (0 == !pFix->yuv422_mode) {
sum_coeff = gaus_reg[0]
+ 4 * gaus_reg[1]
+ 4 * gaus_reg[2]
+ 4 * gaus_reg[3]
+ 8 * gaus_reg[4]
+ 4 * gaus_reg[5];
} else {
sum_coeff = gaus_reg[0]
+ 2 * gaus_reg[1]
+ 2 * gaus_reg[2]
+ 2 * gaus_reg[3]
+ 4 * gaus_reg[4]
+ 4 * gaus_reg[5];
}
int offset = (1 << 8) - sum_coeff;
gaus_reg[0] = gaus_reg[0] + offset;
for(int i = 0; i < 6; i++) {
tmp = gaus_reg[5 - i];
pFix->gaus_flt_coeff[i] = CLIP(tmp, 0, 0x7f);
}
/* CNR_GAUS_RATIO */
tmp = ROUND_F((1 << RKCNR_V31_FIX_BIT_GAUS_RATIO) * pdyn->hiNr_preLpf.hw_cnrT_lpfOut_alpha);
pFix->gaus_flt_alpha = CLIP(tmp, 0, 0x7ff);
tmp = ROUND_F((1 << RKCNR_V31_exp2_lut_y) * pdyn->hiNr_bifilt.hw_cnrT_nhoodWgt_minLimit);
pFix->hiflt_wgt_min_limit = CLIP(tmp, 0, 0xff);
tmp = ROUND_F((1 << RKCNR_V31_FIX_BIT_GLOBAL_ALPHA) * pdyn->hiNr_bifilt.hw_cnrT_bifiltOut_alpha);
pFix->hiflt_alpha = CLIP(tmp, 0, 0x7ff);
/* CNR_BF_PARA1 */
tmp = ROUND_F((1 << RKCNR_V31_uvgain) * pdyn->hiNr_bifilt.hw_cnrT_uvEdg_strg);
pFix->hiflt_uv_gain = CLIP(tmp, 0, 0x7f);
/* CNR_BF_PARA2 */
tmp = pdyn->hiNr_bifilt.hw_cnrT_satAdj_offset;
pFix->adj_offset = CLIP(tmp, 0, 0x1ff);
tmp = ROUND_F((1 << RKCNR_V31_FIX_BIT_SATURATION) * pdyn->hiNr_bifilt.hw_cnrT_satAdj_scale);
pFix->adj_scale = CLIP(tmp, 0, 0x7fff);
/* CNR_SIGMA */
for(int i = 0; i < 13; i++) {
tmp = ROUND_F(pdyn->hiNr_bifilt.hw_cnrT_locSgmStrg2SgmRat_val[i] * (1 << RKCNR_V31_sgmRatio));
pFix->sgm_ratio[i] = CLIP(tmp, 0, 0xff);
}
#if RKAIQ_HAVE_CNR_V36
/* CNR_IIR_GLOBAL_GAIN */
// mode0 : global, cnr_glbSgmRatio_only_mode; mode1 : global, local, cnr_glbSgmRat_locSgmStrg_mode; mode2 : local, cnr_locSgmStrg2SgmRat_mode;
if(pdyn->loNrGuide_iirFilt.sw_cnrT_rgeSgmRatio_mode == cnr_glbSgmRatio_only_mode)
{
pFix->loflt_global_sgm_ratio_alpha = 1.0 * (1 << RKCNR_V31_G_GAIN_ALPHA_FIX_BITS);
}
else if(pdyn->loNrGuide_iirFilt.sw_cnrT_rgeSgmRatio_mode == cnr_locSgmStrg2SgmRat_mode)
{
pFix->loflt_global_sgm_ratio_alpha = 0.0 * (1 << RKCNR_V31_G_GAIN_ALPHA_FIX_BITS);
}
else
{
tmp = pdyn->loNrGuide_iirFilt.hw_cnrT_glbSgmRatio_alpha * (1 << RKCNR_V31_G_GAIN_ALPHA_FIX_BITS);
pFix->loflt_global_sgm_ratio_alpha = CLIP(tmp, 0, 0x8);
}
#else
/* CNR_IIR_GLOBAL_GAIN */
// ic not support iir local gain, the value is always 0x8.
pFix->loflt_global_sgm_ratio_alpha = 0x8;
#endif
tmp = pdyn->loNrGuide_iirFilt.hw_cnrT_glbSgm_ratio * (1 << RKCNR_V31_sgmRatio);
pFix->loflt_global_sgm_ratio = CLIP(tmp, 0, 0xff);
#if defined(RKAIQ_HAVE_CNR_V35) || defined(RKAIQ_HAVE_CNR_V36)
tmp = ROUND_F((1.0 - pdyn->hiNr_locFiltAlpha.hw_cnrT_locFiltAlpha_minLimit) * (1 << RKCNR_V32_FIX_BIT_GLOBAL_ALPHA));
pFix->bf_alpha_max_limit = CLIP(tmp, 0, 0x7ff);
tmp = ROUND_F((1.0 / sqrt(pdyn->hiNr_locFiltAlpha.hw_cnrT_locFiltAlpha_maxLimit) * (1 << 14)));
pFix->bf_merge_max_limit = CLIP(tmp, 0, 0x3fff);
#endif
/* CNR_SIGMA */
for(int i = 0; i < 13; i++) {
tmp = ROUND_F(pdyn->hiNr_bifilt.hw_cnrT_locSgmStrg2CtrWgt_scale[i] * (1 << RKCNR_V31_bfRatio));
pFix->cur_wgt[i] = CLIP(tmp, 0, 0xff);
}
/* CNR_SIGMA */
for(int i = 0; i < 8; i++) {
tmp = ROUND_F(pdyn->hw_cnrC_luma2HiNrSgm_curve.idx[i]);
pFix->hiflt_vsigma_idx[i] = CLIP(tmp, 0, 0x3ff);
tmp = log2e / (pdyn->hw_cnrC_luma2HiNrSgm_curve.val[i] * scale);
pFix->hiflt_vsigma[i] = CLIP(tmp, 0, 0x3fff);
}
#if RKAIQ_HAVE_CNR_V36
for (int i = 0; i < 13; i++) {
tmp = ROUND_F(pdyn->loNrGuide_iirFilt.hw_cnrT_locSgmStrg2SgmRat_val[i] * (1 << RKCNR_V31_sgmRatio));
pFix->lo_flt_vsigma[i] = CLIP(tmp, 0, 0xff);
}
tmp = pdyn->hiNr_locFiltAlpha.hw_cnrT_hueSatAdj_en;
pFix->hsv_alpha_en = CLIP(tmp, 0, 1);
for (int i = 0; i < 10; i++) {
tmp = ROUND_F(pdyn->hiNr_locFiltAlpha.hw_cnrT_hue2NrOutAlpha[i] * (1 << 7));
pFix->hsv_adj_alpha_table[i] = CLIP(tmp, 0, 0x80);
}
for (int i = 0; i < 10; i++) {
tmp = ROUND_F(pdyn->hiNr_locFiltAlpha.hw_cnrT_sat2NrOutAlpha[i] * (1 << 7));
pFix->sat_adj_alpha_table[i] = CLIP(tmp, 0, 0x80);
}
for (int i = 0; i < 10; i++) {
tmp = ROUND_F(pdyn->hiNr_locFiltAlpha.hw_cnrT_locSgmStrg2NrOutAlpha[i] * (1 << 4));
pFix->gain_adj_alpha_table[i] = CLIP(tmp, 0, 0xff);
}
#endif
return;
}