mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
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 <bencheng.jing@amlogic.com>
This commit is contained in:
committed by
Jianxin Pan
parent
c6412a36ec
commit
cc96f0b425
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user