amvecm: fix LC super white/black pattern issue [1/2]
authorXihai Zhu <xihai.zhu@amlogic.com>
Thu, 1 Aug 2019 07:33:13 +0000 (03:33 -0400)
committerJianxin Pan <jianxin.pan@amlogic.com>
Fri, 16 Aug 2019 15:09:12 +0000 (08:09 -0700)
PD#SWPL-12142

Problem:
signal level of 107% block of super white/black pattern
diff via enable/disable LC

Solution:
it is special limit range pattern but some pixels
value > 235, use full range matrix to avoid clipping,
this is per VLSI'e suggestion

Verify:
tl1

Change-Id: I82d26105a2404218b0c575a578874f88ae75d6c9
Signed-off-by: Xihai Zhu <xihai.zhu@amlogic.com>
drivers/amlogic/media/enhancement/amvecm/amvecm.c
drivers/amlogic/media/enhancement/amvecm/local_contrast.c
drivers/amlogic/media/enhancement/amvecm/local_contrast.h

index 5af2d9a..3918863 100644 (file)
@@ -6338,6 +6338,20 @@ static ssize_t amvecm_lc_store(struct class *cls,
                        goto free_buf;
                tune_curve_en = val;
                pr_info("tune_curve_en = %d\n", tune_curve_en);
+       } else if (!strcmp(parm[0], "detect_signal_range_en")) {
+               if (kstrtoul(parm[1], 10, &val) < 0)
+                       goto free_buf;
+               amlc_debug = 0xe;
+               detect_signal_range_en = val;
+               pr_info("detect_signal_range_en = %d\n",
+                               detect_signal_range_en);
+       } else if (!strcmp(parm[0], "detect_signal_range_threshold")) {
+               if (kstrtoul(parm[1], 10, &val) < 0)
+                       goto free_buf;
+               amlc_debug = 0xe;
+               detect_signal_range_threshold = val;
+               pr_info("detect_signal_range_threshold = %d\n",
+                               detect_signal_range_threshold);
        } else
                pr_info("unsupprt cmd!\n");
 
index ee8e7a3..fe78d04 100644 (file)
@@ -125,6 +125,8 @@ static unsigned int lc_satur_off[63] = {
 /*};*/
 
 int tune_curve_en = 2;
+int detect_signal_range_en = 2;
+int detect_signal_range_threshold = 1000;
 
 /*local contrast begin*/
 static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel,
@@ -290,6 +292,58 @@ static void lc_mtx_set(enum lc_mtx_sel_e mtx_sel,
                        WRITE_VPP_REG(matrix_pre_offset2, 0x00000600);
                }
                break;
+       case LC_MTX_RGB_YUV709:
+               if (mtx_sel & (INP_MTX | OUTP_MTX)) {
+                       WRITE_VPP_REG(matrix_coef00_01, 0x00da02dc);
+                       WRITE_VPP_REG(matrix_coef02_10, 0x004a1f8a);
+                       WRITE_VPP_REG(matrix_coef11_12, 0x1e760200);
+                       WRITE_VPP_REG(matrix_coef20_21, 0x02001e2f);
+                       WRITE_VPP_REG(matrix_coef22, 0x00001fd1);
+                       if (bitdepth == 10) {
+                               WRITE_VPP_REG(matrix_offset0_1, 0x200);
+                               WRITE_VPP_REG(matrix_clip, 0x3ff);
+                       } else {
+                               WRITE_VPP_REG(matrix_offset0_1, 0x800);
+                               WRITE_VPP_REG(matrix_clip, 0xfff);
+                       }
+               } else if (mtx_sel & STAT_MTX) {
+                       WRITE_VPP_REG(matrix_coef00_01, 0x00bb0275);
+                       WRITE_VPP_REG(matrix_coef02_10, 0x003f1f99);
+                       WRITE_VPP_REG(matrix_coef11_12, 0x1ea601c2);
+                       WRITE_VPP_REG(matrix_coef20_21, 0x01c21e67);
+                       WRITE_VPP_REG(matrix_coef22, 0x00001fd7);
+                       WRITE_VPP_REG(matrix_offset0_1, 0x00400200);
+                       WRITE_VPP_REG(matrix_offset2, 0x00000200);
+                       WRITE_VPP_REG(matrix_pre_offset0_1, 0x0);
+                       WRITE_VPP_REG(matrix_pre_offset2, 0x0);
+               }
+               break;
+       case LC_MTX_YUV709_RGB:
+               if (mtx_sel & (INP_MTX | OUTP_MTX)) {
+                       WRITE_VPP_REG(matrix_coef00_01, 0x01000000);
+                       WRITE_VPP_REG(matrix_coef02_10, 0x01930100);
+                       WRITE_VPP_REG(matrix_coef11_12, 0x1fd01f88);
+                       WRITE_VPP_REG(matrix_coef20_21, 0x010001db);
+                       WRITE_VPP_REG(matrix_coef22, 0x0);
+                       if (bitdepth == 10) {
+                               WRITE_VPP_REG(matrix_pre_offset0_1, 0x200);
+                               WRITE_VPP_REG(matrix_clip, 0x3ff);
+                       } else {
+                               WRITE_VPP_REG(matrix_pre_offset0_1, 0x800);
+                               WRITE_VPP_REG(matrix_clip, 0xfff);
+                       }
+               } else if (mtx_sel & STAT_MTX) {
+                       WRITE_VPP_REG(matrix_coef00_01, 0x04000000);
+                       WRITE_VPP_REG(matrix_coef02_10, 0x064d0400);
+                       WRITE_VPP_REG(matrix_coef11_12, 0x1f411e21);
+                       WRITE_VPP_REG(matrix_coef20_21, 0x0400076d);
+                       WRITE_VPP_REG(matrix_coef22, 0x0);
+                       WRITE_VPP_REG(matrix_offset0_1, 0x0);
+                       WRITE_VPP_REG(matrix_offset2, 0x0);
+                       WRITE_VPP_REG(matrix_pre_offset0_1, 0x00000600);
+                       WRITE_VPP_REG(matrix_pre_offset2, 0x00000600);
+               }
+               break;
        case LC_MTX_NULL:
                if (mtx_sel & (INP_MTX | OUTP_MTX)) {
                        WRITE_VPP_REG(matrix_coef00_01, 0x04000000);
@@ -392,7 +446,9 @@ static void lc_stts_en(int enable,
        int hist_mode,
        int lpf_en,
        int din_sel,
-       int bitdepth)
+       int bitdepth,
+       int flag,
+       int flag_full)
 {
        int data32;
 
@@ -405,7 +461,17 @@ static void lc_stts_en(int enable,
        data32 = data32 | ((lpf_en & 0x1) << 21);
        WRITE_VPP_REG(LC_STTS_HIST_REGION_IDX, data32);
 
-       lc_mtx_set(STAT_MTX, LC_MTX_YUV709L_RGB, enable, bitdepth);
+       if (flag == 0x3)
+               lc_mtx_set(STAT_MTX, LC_MTX_YUV601L_RGB,
+                               enable, bitdepth);
+       else {
+               if (flag_full == 1)
+                       lc_mtx_set(STAT_MTX, LC_MTX_YUV709_RGB,
+                                       enable, bitdepth);
+               else
+                       lc_mtx_set(STAT_MTX, LC_MTX_YUV709L_RGB,
+                                       enable, bitdepth);
+       }
 
        WRITE_VPP_REG_BITS(LC_STTS_CTRL0, din_sel, 3, 3);
        /*lc hist stts enable*/
@@ -495,7 +561,8 @@ static void lc_blk_bdry_config(unsigned int height, unsigned int width)
 }
 
 static void lc_top_config(int enable, int h_num, int v_num,
-       unsigned int height, unsigned int width, int bitdepth, int flag)
+       unsigned int height, unsigned int width, int bitdepth,
+       int flag, int flag_full)
 {
        /*lcinput_ysel*/
        WRITE_VPP_REG_BITS(SRSHARP1_LC_INPUT_MUX, 5, 4, 3);
@@ -525,8 +592,14 @@ static void lc_top_config(int enable, int h_num, int v_num,
        } else {
                /* all other cases use 709 by default */
                /* to do, should we handle bg2020 separately? */
-               lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1, bitdepth);
-               lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1, bitdepth);
+               /* for special signal, keep full range to avoid clipping */
+               if (flag_full == 1) {
+                       lc_mtx_set(INP_MTX, LC_MTX_YUV709_RGB, 1, bitdepth);
+                       lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709, 1, bitdepth);
+               } else {
+                       lc_mtx_set(INP_MTX, LC_MTX_YUV709L_RGB, 1, bitdepth);
+                       lc_mtx_set(OUTP_MTX, LC_MTX_RGB_YUV709L, 1, bitdepth);
+               }
        }
 
 }
@@ -547,6 +620,29 @@ static void lc_disable(void)
        lc_en_chflg = 0x0;
 }
 
+/* detect super white and super black currently */
+static int signal_detect(unsigned short *hist)
+{
+       unsigned short bin0, bin1, bin62, bin63;
+
+       bin0 = hist[0];
+       bin1 = hist[1];
+       bin62 = hist[62];
+       bin63 = hist[63];
+
+       if (amlc_debug == 0xe) {
+               pr_info("bin0=%d bin1=%d bin62=%d bin63=%d\n",
+                               bin0, bin1, bin62, bin63);
+               amlc_debug = 0x0;
+       }
+
+       if (((bin0 + bin1) > detect_signal_range_threshold) ||
+            ((bin62 + bin63) > detect_signal_range_threshold))
+               return 1;
+
+       return 0;
+}
+
 static void lc_config(int enable,
        struct vframe_s *vf,
        unsigned int sps_h_en,
@@ -557,8 +653,8 @@ static void lc_config(int enable,
 {
        int h_num, v_num;
        unsigned int height, width;
-       static unsigned int vf_height, vf_width;
-       unsigned int flag;
+       static unsigned int vf_height, vf_width, flag_full_pre;
+       unsigned int flag, flag_full;
 
        h_num = 12;
        v_num = 8;
@@ -569,20 +665,34 @@ static void lc_config(int enable,
                return;
        }
 
+       /* try to detect out of spec signal level */
+       flag_full = 0;
+       if (detect_signal_range_en == 2)
+               flag_full = signal_detect(vf->prop.hist.vpp_gamma);
+       else
+               flag_full = detect_signal_range_en;
+
+       if (flag_full != flag_full_pre) {
+               pr_info("signal changed, flag_full:%d->%d\n",
+                               flag_full_pre, flag_full);
+       }
+
        if ((vf_height == vf->height) &&
-               (vf_width == vf->width)) {
-               if (!lc_en_chflg)
-                       lc_en_chflg = 0xff;
-               else
+               (vf_width == vf->width) &&
+               (flag_full == flag_full_pre) &&
+               lc_en_chflg) {
                        return;
        }
 
+       flag_full_pre = flag_full;
        height = sps_h_in << sps_h_en;
        width = sps_w_in << sps_v_en;
 
        vf_height = vf->height;
        vf_width = vf->width;
 
+       lc_en_chflg = 0xff;
+
 /*
  *     bit 29: present_flag
  *     bit 23-16: color_primaries
@@ -597,14 +707,16 @@ static void lc_config(int enable,
                /* signal_type is not present */
                /* use default value bt709 */
                flag = 0x1;
-       lc_top_config(enable, h_num, v_num, height, width, bitdepth, flag);
+       lc_top_config(enable, h_num, v_num, height,
+                               width, bitdepth, flag, flag_full);
 
        width = sps_w_in;
        height = sps_h_in;
 
        lc_curve_ctrl_config(enable, height, width);
        lc_stts_blk_config(enable, height, width);
-       lc_stts_en(enable, height, width, 0, 0, 1, 1, 4, bitdepth);
+       lc_stts_en(enable, height, width, 0, 0, 1, 1, 4,
+                               bitdepth, flag, flag_full);
 }
 
 static void tune_nodes_patch(int *omap, int *ihistogram, int reg_lmtrat_sigbin)
@@ -1453,7 +1565,7 @@ void lc_init(int bitdepth)
        if (!lc_en)
                return;
 
-       lc_top_config(0, h_num, v_num, height, width, bitdepth, 1);
+       lc_top_config(0, h_num, v_num, height, width, bitdepth, 1, 0);
        WRITE_VPP_REG_BITS(LC_CURVE_RAM_CTRL, 0, 0, 1);
 
        /*default LC low parameters*/
@@ -1519,7 +1631,6 @@ void lc_process(struct vframe_s *vf,
                lc_disable();
                return;
        }
-
        if (vf == NULL) {
                if (lc_flag == 0xff) {
                        lc_disable();
index 23a0182..600b3ec 100644 (file)
@@ -39,6 +39,8 @@ enum lc_mtx_csc_e {
        LC_MTX_RGB_YUV709L = 0x2,
        LC_MTX_YUV601L_RGB = 0x3,
        LC_MTX_RGB_YUV601L = 0x4,
+       LC_MTX_YUV709_RGB  = 0x5,
+       LC_MTX_RGB_YUV709  = 0x6,
        LC_MTX_MAX
 };
 
@@ -64,6 +66,8 @@ struct lc_alg_param_s {
 extern int amlc_debug;
 extern int lc_reg_lmtrat_sigbin;
 extern int tune_curve_en;
+extern int detect_signal_range_en;
+extern int detect_signal_range_threshold;
 extern int lc_en;
 extern int lc_demo_mode;
 extern unsigned int lc_hist_vs;