From cc96f0b42543b1b43e229fc86b7eb213743713bc Mon Sep 17 00:00:00 2001 From: Bencheng Jing Date: Mon, 10 Dec 2018 17:07:06 +0800 Subject: [PATCH] amvecm: add local contrast iir SW algorithm [1/1] PD#SWPL-2587 Problem: local contrast SW algorithm Solution: add local contrast SW iir algorithm support Verify: x301 Change-Id: I8c80ce3fa5252585d5dd4a15e72beb9c0bfd5d7f Signed-off-by: Bencheng Jing --- .../amlogic/media/enhancement/amvecm/amvecm.c | 91 ++- .../media/enhancement/amvecm/local_contrast.c | 581 ++++++++++++++++-- .../media/enhancement/amvecm/local_contrast.h | 17 +- 3 files changed, 627 insertions(+), 62 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 496579e4d036..8b8103d07cab 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -5519,6 +5519,20 @@ static ssize_t amvecm_lc_show(struct class *cla, "echo dump_hist chosen hs he vs ve cnt > /sys/class/amvecm/lc\n"); len += sprintf(buf+len, "echo dump_curve cnt > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo lc_osd_setting show > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo lc_osd_setting set xxx ... xxx > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo osd_iir_en val > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo iir_refresh show > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo iir_refresh set xxx ... xxx > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo scene_change_th val > /sys/class/amvecm/lc\n"); + len += sprintf(buf+len, + "echo irr_dbg_en val > /sys/class/amvecm/lc\n"); return len; } @@ -5596,9 +5610,9 @@ static ssize_t amvecm_lc_store(struct class *cls, pr_info("unsupprt cmd!\n"); } else if (!strcmp(parm[0], "dump_hist")) { if (!strcmp(parm[1], "all")) { - /*dump all hist in one frame*/ + /*dump all hist of one frame*/ lc_hist_prcnt = 1; - amlc_debug = 0x2; + amlc_debug = 0x8; } else if (!strcmp(parm[1], "chosen")) { /*dump multiple frames in selected area*/ if (parm[6] == NULL) @@ -5618,13 +5632,83 @@ static ssize_t amvecm_lc_store(struct class *cls, if (kstrtoul(parm[6], 10, &val) < 0) goto free_buf; lc_hist_prcnt = val; - amlc_debug = 0x4; + amlc_debug = 0x6; } else pr_info("unsupprt cmd!\n"); } else if (!strcmp(parm[0], "dump_curve")) { if (kstrtoul(parm[1], 10, &val) < 0) goto free_buf; lc_curve_prcnt = val; + } else if (!strcmp(parm[0], "lc_osd_setting")) { + if (!strcmp(parm[1], "show")) { + pr_info("VNUM_STRT_BELOW: %d, VNUM_END_BELOW: %d\n", + vnum_start_below, vnum_end_below); + pr_info("VNUM_STRT_ABOVE: %d, VNUM_END_ABOVE: %d\n", + vnum_start_above, vnum_end_above); + pr_info("INVALID_BLK: %d, MIN_BV_PERCENT_TH: %d\n", + invalid_blk, min_bv_percent_th); + } else if (!strcmp(parm[1], "set")) { + if (parm[7] == NULL) + goto free_buf; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + vnum_start_below = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + vnum_end_below = val; + if (kstrtoul(parm[4], 10, &val) < 0) + goto free_buf; + vnum_start_above = val; + if (kstrtoul(parm[5], 10, &val) < 0) + goto free_buf; + vnum_end_above = val; + if (kstrtoul(parm[6], 10, &val) < 0) + goto free_buf; + invalid_blk = val; + if (kstrtoul(parm[7], 10, &val) < 0) + goto free_buf; + min_bv_percent_th = val; + } else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "osd_iir_en")) { + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + osd_iir_en = val; + } else if (!strcmp(parm[0], "iir_refresh")) { + if (!strcmp(parm[1], "show")) { + pr_info("current state: alpha1: %d, alpha2: %d, refresh_bit: %d, ts: %d\n", + alpha1, alpha2, refresh_bit, ts); + } else if (!strcmp(parm[1], "set")) { + if (parm[5] == NULL) + goto free_buf; + if (kstrtoul(parm[2], 10, &val) < 0) + goto free_buf; + alpha1 = val; + if (kstrtoul(parm[3], 10, &val) < 0) + goto free_buf; + alpha2 = val; + if (kstrtoul(parm[4], 10, &val) < 0) + goto free_buf; + refresh_bit = val; + if (kstrtoul(parm[5], 10, &val) < 0) + goto free_buf; + ts = val; + pr_info("after setting: alpha1: %d, alpha2: %d, refresh_bit: %d, ts: %d\n", + alpha1, alpha2, refresh_bit, ts); + } else + pr_info("unsupprt cmd!\n"); + } else if (!strcmp(parm[0], "scene_change_th")) { + pr_info("current value: %d\n", scene_change_th); + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + scene_change_th = val; + pr_info("setting value: %d\n", scene_change_th); + } else if (!strcmp(parm[0], "irr_dbg_en")) { + pr_info("current value: %d\n", amlc_iir_debug_en); + if (kstrtoul(parm[1], 10, &val) < 0) + goto free_buf; + amlc_iir_debug_en = val; + pr_info("setting value: %d\n", amlc_iir_debug_en); } else pr_info("unsupprt cmd!\n"); @@ -5632,6 +5716,7 @@ static ssize_t amvecm_lc_store(struct class *cls, return count; free_buf: + pr_info("Missing parameters !\n"); kfree(buf_orig); return -EINVAL; } diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c index 5b3d47d993ec..79359fe3dc0d 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.c +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.c @@ -10,6 +10,12 @@ #include "arch/vpp_regs.h" #include "local_contrast.h" +/*may define in other module*/ +#define CURV_NODES 6 +/*history message delay*/ +#define N 4 +/*hist bin num*/ +#define HIST_BIN 16 int amlc_debug; #define pr_amlc_dbg(fmt, args...)\ do {\ @@ -21,7 +27,39 @@ int lc_en; int lc_demo_mode; int lc_en_chflg = 0xff; static int lc_flag = 0xff; -static int *lc_szcurve; +int osd_iir_en = 1; +int amlc_iir_debug_en; +/*osd related setting */ +int vnum_start_below = 5; +int vnum_end_below = 6; +int vnum_start_above = 1; +int vnum_end_above = 2; +int invalid_blk = 2; +/*u10,7000/21600=0.324*1024=331 */ +int min_bv_percent_th = 331; +/*control the refresh speed*/ +int alpha1 = 32; +int alpha2 = 2; +int refresh_bit = 12; +int ts = 6; +/*need tuning according to real situation ! (0~512)*/ +int scene_change_th = 50; + +/*chose block to get hist*/ +unsigned int lc_hist_vs; +unsigned int lc_hist_ve; +unsigned int lc_hist_hs; +unsigned int lc_hist_he; +/*lc curve data and hist data*/ +static int *lc_szcurve;/*12*8*6+4*/ +static int *curve_nodes_cur; +static int *curve_nodes_pre; +static int *lc_hist;/*12*8*17*/ +static bool lc_malloc_ok; +/*print one or more frame data*/ +unsigned int lc_hist_prcnt; +unsigned int lc_curve_prcnt; + /*local contrast begin*/ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel, @@ -399,21 +437,11 @@ static void lc_config(int enable, lc_stts_en(enable, height, width, 0, 0, 1, 1, 4); } -static void read_lc_curve(void) +static void read_lc_curve(int blk_vnum, int blk_hnum) { - int blk_hnum; - int blk_vnum; int i, j; - unsigned int dwTemp; unsigned int temp1, temp2; - if (!lc_szcurve) { - pr_amlc_dbg("%s: lc_szcurve not init!", __func__); - return; - } - dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); - blk_hnum = (dwTemp >> 8) & 0x1f; - blk_vnum = (dwTemp) & 0x1f; WRITE_VPP_REG(LC_CURVE_RAM_CTRL, 1); WRITE_VPP_REG(LC_CURVE_RAM_ADDR, 0); for (i = 0; i < blk_vnum; i++) { @@ -444,11 +472,15 @@ static void lc_demo_wr_curve(int h_num, int v_num) for (i = 0; i < v_num; i++) { for (j = 0; j < h_num / 2; j++) { temp1 = lc_szcurve[6 * (i * h_num + j) + 0] | - (lc_szcurve[6 * (i * h_num + j) + 1] << 10) | - (lc_szcurve[6 * (i * h_num + j) + 2] << 20); + (lc_szcurve[6 * + (i * h_num + j) + 1] << 10) | + (lc_szcurve[6 * + (i * h_num + j) + 2] << 20); temp2 = lc_szcurve[6 * (i * h_num + j) + 3] | - (lc_szcurve[6 * (i * h_num + j) + 4] << 10) | - (lc_szcurve[6 * (i * h_num + j) + 5] << 20); + (lc_szcurve[6 * + (i * h_num + j) + 4] << 10) | + (lc_szcurve[6 * + (i * h_num + j) + 5] << 20); WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, temp1); WRITE_VPP_REG(SRSHARP1_LC_MAP_RAM_DATA, temp2); } @@ -500,10 +532,6 @@ static int set_lc_curve(int binit, int bcheck) int rflag; int temp, temp1; - if (!lc_szcurve) { - pr_amlc_dbg("%s: lc_szcurve not init!", __func__); - return -EINVAL; - } rflag = 0; hvTemp = READ_VPP_REG(SRSHARP1_LC_HV_NUM); h_num = (hvTemp >> 8) & 0x1f; @@ -561,37 +589,449 @@ static int set_lc_curve(int binit, int bcheck) return rflag; } - -static void lc_fw_curve_iir(struct vframe_s *vf) +/* + *function: detect osd and provide osd signal status + *output: + * osd_flag_cnt: signal indicate osd exist (process) + * frm_cnt: signal that record the sudden + * moment osd appear or disappear + */ +static int osd_det_func(int *osd_flag_cnt, + int *frm_cnt, + int blk_hist_sum, + int *lc_hist, + int blk_hnum, + int osd_vnum_strt, + int osd_vnum_end) { - if (!vf) - return; + int i, j; + int min_bin_value, min_bin_percent; + int osd_flag; + int valid_blk; + int percent_norm = (1<<10) - 1; + static int osd_hist_cnt; + + osd_flag = 0; + min_bin_value = 0; + + /*1.1, case 1: osd below,e.g. vnum=5,6(0~7)*/ + osd_hist_cnt = 0; + for (i = osd_vnum_strt; i <= osd_vnum_end; i++) {/*two line*/ + for (j = 0; j < blk_hnum; j++) { + min_bin_value = + lc_hist[(i*blk_hnum + j) * + (HIST_BIN + 1) + 0];/*first bin*/ + /*black osd means first bin value very large*/ + min_bin_percent = + (min_bin_value * percent_norm) / + (blk_hist_sum + 1); + if (min_bin_percent > min_bv_percent_th) + osd_hist_cnt++;/*black bin count*/ + if (amlc_debug == 0x2) + pr_info("v2-1:osd_hist_cnt:%d, min_bin_percent:%d, (th:%d)\n", + osd_hist_cnt, + min_bin_percent, + min_bv_percent_th); + } + } + /*how many block osd occupy*/ + valid_blk = (osd_vnum_end - osd_vnum_strt + 1) * blk_hnum - + invalid_blk; + /*we suppose when osd appear, + * 1)it came in certain area, + * 2)and almost all those area are black + */ + if (osd_hist_cnt > valid_blk) + osd_flag_cnt[1] = 1; + else + osd_flag_cnt[1] = 0; + /*detect the moment osd appear and disappear:*/ + osd_flag = ((osd_flag_cnt[1]&(~(osd_flag_cnt[0]))) + + ((~(osd_flag_cnt[1])) & osd_flag_cnt[0]));/*a^b*/ + /*set osd appear and disappear heavy iir time*/ + if (osd_flag && osd_iir_en) + *frm_cnt = 60 * ts; + + /*debug*/ + if ((amlc_iir_debug_en == 10) || (amlc_debug == 0x2)) { + pr_info("osd_log v2:osd_flag_cnt[0]:%d,osd_flag_cnt[1]:%d,osd_flag:%d,frm_cnt:%d\n", + osd_flag_cnt[0], + osd_flag_cnt[1], + osd_flag, + *frm_cnt); + if (*frm_cnt <= 0) + amlc_iir_debug_en = 0; + } + + return 0; } -/*print statistics hist and curve, vlsi suggest add*/ -unsigned int lc_hist_vs = 4; -unsigned int lc_hist_ve = 6; -unsigned int lc_hist_hs; -unsigned int lc_hist_he = 11; -unsigned int lc_hist_prcnt; -unsigned int lc_curve_prcnt; -static int *lc_hist; +/* + *note 1: osd appear in 5,6(0,1,2,...7) line in Vnum = 8 situation + * if Vnum changed, debug osd location, find + * vnum_start_below, vnum_end_below(osd below situation,above situation is same) + * + * note 2: here just consider 2 situation: osd appear below or appear above + * + * function: 2 situation osd detect and provide + * osd status signal(osd_flag_cnt&frm_cnt) + */ +static int osd_detect(int *osd_flag_cnt_above, + int *osd_flag_cnt_below, + int *frm_cnt_above, + int *frm_cnt_below, + int *lc_hist, + int blk_hnum) +{ + int k; + unsigned long blk_hist_sum = 0; -static void lc_read_region(void) + for (k = 0; k < HIST_BIN; k++) + blk_hist_sum += + lc_hist[(0*blk_hnum + 0) * + (HIST_BIN+1) + k];/*use blk[0,0],16bin*/ + /*above situation*/ + osd_det_func(osd_flag_cnt_above,/*out*/ + frm_cnt_above,/*out*/ + blk_hist_sum, + lc_hist, + blk_hnum, + vnum_start_above, + vnum_end_above); + /*below situation*/ + osd_det_func(osd_flag_cnt_below,/*out*/ + frm_cnt_below,/*out*/ + blk_hist_sum, + lc_hist, + blk_hnum, + vnum_start_below, + vnum_end_below); + + return 0; +} + +/*just temporarily define here to avoid grammar error*/ +static int video_scene_change_flag_en; +static int video_scene_change_flag; +/*function: detect global scene change signal + *output: scene_change_flag + */ +int global_scene_change(int *curve_nodes_cur, + int *curve_nodes_pre, + int blk_vnum, + int blk_hnum, + int *osd_flag_cnt_above, + int *osd_flag_cnt_below) +{ + int scene_change_flag; + static int scene_dif[N]; + static int frm_dif[N]; + /*store frame valid block for frm diff calc*/ + static int valid_blk_num[N]; + int frm_dif_osd, vnum_osd; + int addr_curv1; + int apl_cur, apl_pre; + int i, j; + + /*history message delay*/ + for (i = 0; i < N-1; i++) { + scene_dif[i] = scene_dif[i + 1]; + frm_dif[i] = frm_dif[i + 1]; + valid_blk_num[i] = valid_blk_num[i+1]; + } + + if (video_scene_change_flag_en) + scene_change_flag = + video_scene_change_flag;/*2.1 flag from front module*/ + else { + /* 2.2.1 use block APL to calculate frame dif: + * omap[5]: (yminV), minBV, pkBV, maxBV, (ymaxV),ypkBV + */ + frm_dif[N-1] = 0;/*update current result*/ + scene_dif[N-1] = 0; + valid_blk_num[N-1] = 0; + frm_dif_osd = 0; + vnum_osd = 0; + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + apl_cur = curve_nodes_cur[addr_curv1 * + CURV_NODES + 2];/*apl value*/ + apl_pre = curve_nodes_pre[addr_curv1 * + CURV_NODES + 2]; + frm_dif[N-1] += + abs(apl_cur - apl_pre);/*frame motion*/ + + /*when have osd, + * remove them to calc frame motion + */ + if ((osd_flag_cnt_below[1]) && + (i >= vnum_start_below) && + (i <= vnum_end_below)) { + frm_dif_osd += abs(apl_cur - apl_pre); + vnum_osd = + vnum_end_below - + vnum_start_below + 1; + + } + + if ((osd_flag_cnt_above[1]) && + (i >= vnum_start_above) && + (i <= vnum_end_above)) { + frm_dif_osd += abs(apl_cur - apl_pre); + vnum_osd = + vnum_end_above - + vnum_start_above + 1; + } + } + } + /*remove osd to calc frame motion */ + frm_dif[N - 1] = frm_dif[N - 1] - frm_dif_osd; + valid_blk_num[N-1] = (blk_vnum - vnum_osd) * blk_hnum; + /*debug*/ + if ((amlc_debug == 0x4)) { + pr_info("#vnum_osd = %d;\n", vnum_osd); + pr_info("#valid_blk_num[%d] = %d\n", + N-1, valid_blk_num[N-1]); + pr_info("#valid_blk_num[%d] = %d\n", + N-2, valid_blk_num[N-2]); + } + + /*2.2.2motion dif.if motion dif too large, + * we think scene changed + */ + scene_dif[N-1] = abs((frm_dif[N - 1] / (valid_blk_num[N-1]+1)) - + (frm_dif[N - 2] / (valid_blk_num[N-2]+1))); + + if (scene_dif[N-1] > scene_change_th) + scene_change_flag = 1; + else + scene_change_flag = 0; + + /*debug*/ + if ((scene_dif[N-1] > scene_change_th) && amlc_iir_debug_en) { + for (i = 0; i < N; i++) + pr_info(" valid_blk_num[%d] = %d,\n", + i, valid_blk_num[i]); + for (i = 0; i < N; i++) + pr_info(" frm_dif[%d] = %d,\n", + i, frm_dif[i]); + pr_info("\n\n"); + for (i = 0; i < N; i++) + pr_info(" scene_dif[%d] = %d,\n", + i, scene_dif[i]); + pr_info(" scene_change_flag =%d\n\n", + scene_change_flag); + } + } + return scene_change_flag; +} +/* + *function: set tiir alpha based on different situation + *input: scene_change_flag, frm_cnt(frm_cnt_above,frm_cnt_below) + *out:refresh_alpha[96] + */ +int cal_iir_alpha(int *refresh_alpha, + int blk_vnum, + int blk_hnum, + int refresh, + int scene_change_flag, + int frm_cnt_above, + int frm_cnt_below) +{ + int addr_curv1; + int osd_local_p, osd_local_m; + int i, j, k; + + /* 3.1 global scene change,highest priority */ + if (scene_change_flag) {/*only use current curve*/ + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + for (k = 0; k < CURV_NODES; k++) { + addr_curv1 = (i * blk_hnum + j); + refresh_alpha[addr_curv1] = refresh; + } + } + } + } else {/*time domain alpha blend, may need optimize*/ + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + refresh_alpha[addr_curv1] = + alpha1;/*normal iir*/ + } + } + } + + /*3.2 osd situation-1, osd below */ + if ((frm_cnt_below > 0)) { + osd_local_p = max(vnum_start_below - 1, 0); + osd_local_m = min(vnum_end_below + 1, blk_vnum); + + for (i = osd_local_p; i <= osd_local_m; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + /*osd around(-1,osd,+1) use heavy iir*/ + refresh_alpha[addr_curv1] = alpha2; + } + } + } + /*3.2 osd situation-2, osd above */ + if ((frm_cnt_above > 0)) { + osd_local_p = max(vnum_start_below - 1, 0); + osd_local_m = min(vnum_end_below + 1, blk_vnum); + + for (i = osd_local_p; i <= osd_local_m; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + /*osd around use heavy iir*/ + refresh_alpha[addr_curv1] = alpha2; + } + } + } + + return 0; +} +/*function: curve iir process + * out: curve_nodes_cur(after iir) + */ +int cal_curv_iir(int *curve_nodes_cur, + int *curve_nodes_pre, + int *refresh_alpha, + int blk_vnum, + int blk_hnum, + int refresh) +{ + int i, j, k; + int tmap[CURV_NODES]; + int addr_curv1, addr_curv2; + int node_cur, node_pre; + + for (i = 0; i < blk_vnum; i++) { + for (j = 0; j < blk_hnum; j++) { + addr_curv1 = (i * blk_hnum + j); + for (k = 0; k < CURV_NODES; k++) { + addr_curv2 = + (i * blk_hnum + j) * CURV_NODES + k; + node_cur =/*u12 calc*/ + (curve_nodes_cur[addr_curv2] << 2); + node_pre = (curve_nodes_pre[addr_curv2] << 2); + tmap[k] = + (node_cur * refresh_alpha[addr_curv1] + + node_pre * + (refresh - refresh_alpha[addr_curv1]) + + (1 << (refresh_bit - 1))) >> + refresh_bit; + /*output the iir result*/ + curve_nodes_cur[addr_curv2] = + (tmap[k] >> 2);/*back to u10*/ + /*delay for next iir*/ + curve_nodes_pre[addr_curv2] = + (tmap[k] >> 2); + } + } + } + return 0; +} + +/* + * attention ! + * note 1: + * video_scene_change_flag_en + * video_scene_change_flag + *should from front module,indicate scene changed; + * + * Note 2: OSD appear location + * vnum_start_below + * vnum_end_below (case1) + * vnum_start_above + * vnum_end_above (case2) + */ + + /* iir algorithm top level path */ +static void lc_fw_curve_iir(struct vframe_s *vf, + int *lc_hist, + int *lc_szcurve, + int blk_vnum, + int blk_hnum) +{ + int i; + int scene_change_flag; + /* osd detect */ + static int frm_cnt_below, frm_cnt_above; + static int osd_flag_cnt_below[2]; + static int osd_flag_cnt_above[2]; + /* alpha blend init */ + int refresh_alpha[96] = {0};/*96=vnum*hnum*/ + int refresh = 1 << refresh_bit; + + if (!vf) + return; + + /* pre: get curve nodes from szCurveInfo and save to curve_nodes_cur*/ + for (i = 0; i < 580; i++)/*12*8*6+4*/ + curve_nodes_cur[i] = lc_szcurve[i]; + + /* pre: osd flag delay*/ + osd_flag_cnt_below[0] = osd_flag_cnt_below[1]; + osd_flag_cnt_above[0] = osd_flag_cnt_above[1]; + + /* step 1: osd detect*/ + osd_detect( + osd_flag_cnt_above,/*out*/ + osd_flag_cnt_below,/*out*/ + &frm_cnt_above,/*out*/ + &frm_cnt_below,/*out: osd case heavy iir time */ + lc_hist, + blk_hnum); + + /*step 2: scene change signal get: two method*/ + scene_change_flag = global_scene_change( + curve_nodes_cur, + curve_nodes_pre, + blk_vnum, + blk_hnum, + osd_flag_cnt_above, + osd_flag_cnt_below); + + /* step 3: set tiir alpha based on different situation */ + cal_iir_alpha(refresh_alpha,/*out*/ + blk_vnum, + blk_hnum, + refresh, + scene_change_flag, + frm_cnt_above, + frm_cnt_below); + + /* step 4: iir filter */ + cal_curv_iir(curve_nodes_cur,/*out: iir-ed curve*/ + /*out: store previous frame curve */ + curve_nodes_pre, + refresh_alpha, + blk_vnum, + blk_hnum, + refresh); + + for (i = 0; i < 580; i++) + lc_szcurve[i] = curve_nodes_cur[i];/*output*/ + + frm_cnt_below--; + if (frm_cnt_below < 0) + frm_cnt_below = 0; + + frm_cnt_above--; + if (frm_cnt_above < 0) + frm_cnt_above = 0; + +} + +static void lc_read_region(int blk_vnum, int blk_hnum) { int i, j, k; int data32; int rgb_min, rgb_max; - int dwTemp, blk_hnum, blk_vnum; - if (!lc_hist) { - pr_amlc_dbg("%s: lc_hist not init!", __func__); - return; - } WRITE_VPP_REG_BITS(0x4037, 1, 14, 1); - dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); - blk_hnum = (dwTemp >> 8) & 0x1f; - blk_vnum = (dwTemp) & 0x1f; data32 = READ_VPP_REG(LC_STTS_HIST_START_RD_REGION); for (i = 0; i < blk_vnum; i++) @@ -599,15 +1039,17 @@ static void lc_read_region(void) data32 = READ_VPP_REG(LC_STTS_HIST_START_RD_REGION); if ((i >= lc_hist_vs) && (i <= lc_hist_ve) && (j >= lc_hist_hs) && (j <= lc_hist_he) && - (amlc_debug == 0x4)) + (amlc_debug == 0x6) && lc_hist_prcnt) pr_info("========[r,c](%2d,%2d)======\n", i, j); for (k = 0; k < 17; k++) { data32 = READ_VPP_REG(LC_STTS_HIST_READ_REGION); - lc_hist[(i*blk_hnum+j)*17 + k] = data32; + lc_hist[(i*blk_hnum+j)*17 + k] + = data32; if ((i >= lc_hist_vs) && (i <= lc_hist_ve) && (j >= lc_hist_hs) && (j <= lc_hist_he) - && (amlc_debug == 0x4)) { + && (amlc_debug == 0x6) && + lc_hist_prcnt) { /*print chosen hist*/ if (k == 16) {/*last bin*/ rgb_min = @@ -622,9 +1064,11 @@ static void lc_read_region(void) } } - if (amlc_debug == 0x2)/*print all hist data*/ + if ((amlc_debug == 0x8) && lc_hist_prcnt)/*print all hist data*/ for (i = 0; i < 8*12*17; i++) pr_info("%x\n", lc_hist[i]); + if (lc_hist_prcnt > 0) + lc_hist_prcnt--; } static void lc_prt_curve(void) @@ -656,15 +1100,29 @@ void lc_init(void) if (!lc_en) return; + lc_szcurve = kzalloc(580 * sizeof(int), GFP_KERNEL); if (!lc_szcurve) return; - lc_hist = kzalloc(1632 * sizeof(int), GFP_KERNEL); - if (!lc_hist) { + curve_nodes_cur = kzalloc(580 * sizeof(int), GFP_KERNEL); + if (!curve_nodes_cur) { kfree(lc_szcurve); return; } - + curve_nodes_pre = kzalloc(580 * sizeof(int), GFP_KERNEL); + if (!curve_nodes_pre) { + kfree(lc_szcurve); + kfree(curve_nodes_cur); + return; + } + lc_hist = kzalloc(1632 * sizeof(int), GFP_KERNEL); + if (!lc_hist) { + kfree(lc_szcurve); + kfree(curve_nodes_cur); + kfree(curve_nodes_pre); + return; + } + lc_malloc_ok = 1; lc_top_config(0, h_num, v_num, height, width); lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1); lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1); @@ -678,14 +1136,21 @@ void lc_process(struct vframe_s *vf, unsigned int sps_h_en, unsigned int sps_v_en) { + int blk_hnum, blk_vnum, dwTemp; + + dwTemp = READ_VPP_REG(LC_CURVE_HV_NUM); + blk_hnum = (dwTemp >> 8) & 0x1f; + blk_vnum = (dwTemp) & 0x1f; if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) return; - if (!lc_en) { lc_disable(); return; } - + if (!lc_malloc_ok) { + pr_amlc_dbg("%s: lc malloc fail", __func__); + return; + } if (vf == NULL) { if (lc_flag == 0xff) { lc_disable(); @@ -695,18 +1160,16 @@ void lc_process(struct vframe_s *vf, } lc_config(lc_en, vf, sps_h_en, sps_v_en); - - read_lc_curve(); - lc_fw_curve_iir(vf); - + /*get each block curve*/ + read_lc_curve(blk_vnum, blk_hnum); + /*do time domain iir*/ + lc_fw_curve_iir(vf, lc_hist, + lc_szcurve, blk_vnum, blk_hnum); if (lc_curve_prcnt > 0) { /*debug lc curve node*/ lc_prt_curve(); lc_curve_prcnt--; } - if (lc_hist_prcnt > 0) { /*debug hist*/ - lc_read_region(); - lc_hist_prcnt--; - } + lc_read_region(blk_vnum, blk_hnum); if (set_lc_curve(0, 1)) pr_amlc_dbg("%s: set lc curve fail", __func__); @@ -716,5 +1179,7 @@ void lc_process(struct vframe_s *vf, void lc_free(void) { kfree(lc_szcurve); + kfree(curve_nodes_cur); + kfree(curve_nodes_pre); kfree(lc_hist); } diff --git a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h index 12f3b02eb805..8564b0442a0a 100644 --- a/drivers/amlogic/media/enhancement/amvecm/local_contrast.h +++ b/drivers/amlogic/media/enhancement/amvecm/local_contrast.h @@ -54,7 +54,22 @@ extern unsigned int lc_hist_hs; extern unsigned int lc_hist_he; extern unsigned int lc_hist_prcnt; extern unsigned int lc_curve_prcnt; - +extern int osd_iir_en; +extern int amlc_iir_debug_en; +/*osd related setting */ +extern int vnum_start_below; +extern int vnum_end_below; +extern int vnum_start_above; +extern int vnum_end_above; +extern int invalid_blk; +/*u10,7000/21600=0.324*1024=331 */ +extern int min_bv_percent_th; +/*control the refresh speed*/ +extern int alpha1; +extern int alpha2; +extern int refresh_bit; +extern int ts; +extern int scene_change_th; extern void lc_init(void); extern void lc_process(struct vframe_s *vf,