deinterlace: pq: add save db value interface [1/2]
authorJihong Sui <jihong.sui@amlogic.com>
Sun, 29 Sep 2019 10:56:32 +0000 (18:56 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Tue, 29 Oct 2019 10:34:59 +0000 (03:34 -0700)
PD#SWPL-15705

Problem:
VLSI finetue TL1 1080i mtn setting.

Solution:
a. add di_gmv in vframe type;
b. add interface for save db setting and switch;
-api:void di_patch_mov_setreg(unsigned int nub, unsigned int *preg)
-for set register that you want to save from db;
-preg: register list that you want to save from db; < 5
-api:bool di_api_mov_sel(unsigned int mode, unsigned int *pdate)
-to set register that you save;
-mode:0:value from db;1: setting from pq
-*pdate: data from pq, value/mask
- pdate need keep same order from preg;
c. add interface for switch 1080i comb setting
-void di_set_comb_mode(unsigned int mode)
-mode:0: set nothing; 1:fix_tl1_1080i_sawtooth_patch;
2: new 1080i setting;

Verify:
tl1

Change-Id: I8e0f084d33757ab0e48fb49aececc020dae5c62d
Signed-off-by: Jihong Sui <jihong.sui@amlogic.com>
drivers/amlogic/media/deinterlace/deinterlace.c
drivers/amlogic/media/deinterlace/deinterlace.h
drivers/amlogic/media/deinterlace/deinterlace_dbg.c
drivers/amlogic/media/deinterlace/deinterlace_hw.c
drivers/amlogic/media/deinterlace/deinterlace_mtn.c
drivers/amlogic/media/deinterlace/deinterlace_mtn.h
drivers/amlogic/media/deinterlace/di_pqa.h
drivers/amlogic/media/di_multi/deinterlace.c
drivers/amlogic/media/di_multi/deinterlace.h

index 9f1bcba..1401ba7 100644 (file)
@@ -2448,6 +2448,173 @@ static void di_cma_release(struct di_dev_s *devp)
                        __func__, rels_cnt, delta_time, start_time, end_time);
 }
 #endif
+
+static void di_patch_mov_ini(void)
+{
+       struct di_patch_mov_s *pmov;
+
+       if (!de_devp)
+               return;
+
+       pmov = &de_devp->mov;
+       if (!cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
+               pmov->en_support = false;
+               return;
+       }
+       pmov->en_support = true;
+       pmov->mode = -1;
+       pmov->nub = 0;
+}
+
+bool di_patch_mov_db(unsigned int addr, unsigned int val)
+{
+       bool ret = false;
+       int i;
+       struct di_patch_mov_s *pmov;
+       struct di_patch_mov_d_s *pmv;
+
+       if (!de_devp)
+               return ret;
+
+       pmov = &de_devp->mov;
+
+       if (!pmov->en_support || !pmov->nub)
+               return ret;
+
+       for (i = 0; i < pmov->nub; i++) {
+               if (addr == pmov->reg_addr[i]) {
+                       pmv = &pmov->val_db[i];
+                       pmv->val = val;
+                       pmv->en = true;
+                       pmv->mask = 0xffffffff;
+                       ret = true;
+               }
+       }
+       return ret;
+}
+
+void di_patch_mov_setreg(unsigned int nub, unsigned int *preg)
+{
+       struct di_patch_mov_s *pmov;
+       unsigned int i;
+
+       if (!de_devp)
+               return;
+
+       pmov = &de_devp->mov;
+
+       if (!pmov->en_support)
+               return;
+
+       pmov->nub = nub;
+       if (nub > DI_PATCH_MOV_MAX_NUB) {
+               pr_error("err: %s:nub is overflow %d\n",
+                        __func__, nub);
+               pmov->nub = DI_PATCH_MOV_MAX_NUB;
+       }
+
+       pmov->mode = -1;
+       for (i = 0; i < pmov->nub; i++) {
+               pmov->reg_addr[i] = preg[i];
+               di_pr_info("reg:0x%x\n", preg[i]);
+       }
+}
+EXPORT_SYMBOL(di_patch_mov_setreg);
+
+/**************************************************
+ * pdate:
+ *     value / mask
+ *     value / mask
+ *     need keep same order with di_patch_mov_setreg
+ **************************************************/
+bool di_api_mov_sel(unsigned int mode, unsigned int *pdate)
+{
+       struct di_patch_mov_s *pmov;
+       int i;
+       struct di_patch_mov_d_s *pmv;
+       bool ret = true;
+
+       if (!de_devp)
+               return false;
+
+       pmov = &de_devp->mov;
+
+       if (!pmov               ||
+           !pmov->en_support   ||
+           !init_flag)
+               return false;
+
+       switch (mode) {
+       case 0:/*setting from db*/
+               pmov->mode = 0;
+               pmov->update = 1;
+               break;
+       case 1:/*setting from pq*/
+               pmov->update = 0;
+               for (i = 0; i < pmov->nub; i++) {
+                       pmv = &pmov->val_pq[i];
+                       pmv->val = pdate[i * 2];
+                       pmv->mask = pdate[i * 2 + 1];
+                       pmv->en = true;
+               }
+               pmov->mode = 1;
+               pmov->update = true;
+
+               break;
+       default:
+               ret = false;
+               break;
+       }
+       return ret;
+}
+EXPORT_SYMBOL(di_api_mov_sel);
+
+static void di_patch_mov_setting(void)
+{
+       struct di_patch_mov_s *pmov;
+       int i;
+       struct di_patch_mov_d_s *pmv;
+       unsigned int val;
+
+       if (!de_devp)
+               return;
+
+       pmov = &de_devp->mov;
+
+       if (!pmov               ||
+           !pmov->en_support   ||
+           pmov->mode < 0      ||
+           pmov->mode > 1      ||
+           !pmov->update)
+               return;
+
+       if (pmov->mode == 0)
+               pmv = &pmov->val_db[0];
+       else
+               pmv = &pmov->val_pq[0];
+
+       for (i = 0; i < pmov->nub; i++) {
+               if (pmv->en) {
+                       if (pmv->mask != 0xffffffff) {
+                               val = ((RDMA_RD(pmov->reg_addr[i]) &
+                                       (~(pmv->mask))) |
+                                       (pmv->val & pmv->mask));
+                       } else {
+                               val = pmv->val;
+                       }
+                       DI_Wr(pmov->reg_addr[i], val);
+               }
+               pmv++;
+       }
+       pmov->update = 0;
+}
+
+void di_set_comb_mode(unsigned int mode)
+{
+       di_pre_stru.comb_mode = mode;
+}
+EXPORT_SYMBOL(di_set_comb_mode);
+
 static int di_init_buf(int width, int height, unsigned char prog_flag)
 {
        int i;
@@ -3391,6 +3558,7 @@ static void pre_de_process(void)
                di_pre_stru.input_size_change_flag = false;
        }
 
+       di_patch_mov_setting();
        if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
                if (de_devp->nrds_enable) {
                        nr_ds_mif_config();
@@ -4633,10 +4801,10 @@ jiffies_to_msecs(jiffies_64 - vframe->ready_jiffies64));
                return 0;
        }
        if (is_meson_tl1_cpu()  &&
-           combing_fix_en      &&
+           di_pre_stru.comb_mode &&
            flg_1080i) {
                di_pre_stru.combing_fix_en = false;
-               fix_tl1_1080i_sawtooth_patch();
+               fix_tl1_1080i_patch_sel(di_pre_stru.comb_mode);
        } else {
                di_pre_stru.combing_fix_en = combing_fix_en;
        }
@@ -8670,6 +8838,7 @@ static int di_probe(struct platform_device *pdev)
        di_patch_post_update_mc_sw(DI_MC_SW_IC, true);
 
        dil_attach_ext_api(&di_ext);
+       di_patch_mov_ini();
 
        di_pr_info("%s:ok\n", __func__);
        return ret;
index 2cae178..d93e312 100644 (file)
@@ -220,6 +220,29 @@ extern bool is_vsync_rdma_enable(void);
 #define TABLE_LEN_MAX 10000
 #define TABLE_FLG_END  (0xfffffffe)
 
+/******************************************
+ * patch for TV-10258 multiwave group issue
+ *****************************************/
+#define DI_PATCH_MOV_MAX_NUB   5
+
+struct di_patch_mov_d_s {
+       unsigned int val;
+       unsigned int mask;
+       bool    en;
+};
+
+struct di_patch_mov_s {
+       unsigned int reg_addr[DI_PATCH_MOV_MAX_NUB];
+       struct di_patch_mov_d_s val_db[DI_PATCH_MOV_MAX_NUB];
+       struct di_patch_mov_d_s val_pq[DI_PATCH_MOV_MAX_NUB];
+       int     mode;/*-1 : not set; 0: set from db, 1: set from pq*/
+       bool    en_support;
+       bool    update;
+       unsigned int nub;
+};
+
+bool di_patch_mov_db(unsigned int addr, unsigned int val);
+
 struct di_dev_s {
        dev_t                      devt;
        struct cdev                cdev; /* The cdev structure */
@@ -254,6 +277,7 @@ struct di_dev_s {
        struct page                     *total_pages;
        atomic_t                        mem_flag;
        struct dentry *dbg_root;        /*dbg_fs*/
+       struct di_patch_mov_s mov;
 };
 
 struct di_pre_stru_s {
@@ -378,6 +402,8 @@ struct di_pre_stru_s {
        unsigned int retry_cnt;
        /*****************/
        bool combing_fix_en;
+       unsigned int comb_mode;
+       /*struct di_patch_mov_s mov;*/
 };
 
 struct di_post_stru_s {
index 191f686..ac68b40 100644 (file)
@@ -589,6 +589,8 @@ static int dump_di_pre_stru_seq(struct seq_file *seq, void *v)
                di_pre_stru_p->invert_flag ? "true" : "false");
        seq_printf(seq, "%-25s = %s\n", "combing_fix_en",
                   di_pre_stru_p->combing_fix_en ? "true" : "false");
+       seq_printf(seq, "%-25s = %d\n", "comb_mode",
+                  di_pre_stru_p->comb_mode);
 
        return 0;
 }
@@ -881,6 +883,7 @@ void dump_vframe(struct vframe_s *vf)
        pr_info("pixel_ratio %d list %p\n",
                vf->pixel_ratio, &vf->list);
        pr_info("di_pulldown 0x%x\n", vf->di_pulldown);
+       pr_info("di_gmv 0x%x\n", vf->di_gmv);
 }
 
 void print_di_buf(struct di_buf_s *di_buf, int format)
@@ -1077,6 +1080,30 @@ void dump_afbcd_reg(void)
                VD2_AFBCD1_MISC_CTRL, RDMA_RD(VD2_AFBCD1_MISC_CTRL));
 }
 
+static int dbg_patch_mov_data_show(struct seq_file *seq, void *v)
+{
+       struct di_dev_s *de_devp = get_di_de_devp();
+       struct di_patch_mov_s *pmov = &de_devp->mov;
+       int i;
+
+       seq_printf(seq, "mode:%d\n", pmov->mode);
+       seq_printf(seq, "en_support:%d\n", pmov->en_support);
+       seq_printf(seq, "number:%d\n", pmov->nub);
+       seq_printf(seq, "update:%d\n", pmov->update);
+       for (i = 0; i < DI_PATCH_MOV_MAX_NUB; i++) {
+               seq_printf(seq, "index:[%d]\n", i);
+               seq_printf(seq, "\treg:0x%x\n", pmov->reg_addr[i]);
+               if (i < pmov->nub)
+                       seq_printf(seq, "\t\t= 0x%x\n",
+                                  RDMA_RD(pmov->reg_addr[i]));
+               seq_printf(seq, "\tdb_val:0x%x\n", pmov->val_db[i].val);
+               seq_printf(seq, "\tdb_en :0x%x\n", pmov->val_db[i].en);
+               seq_printf(seq, "\tpq_val:0x%x\n", pmov->val_pq[i].val);
+               seq_printf(seq, "\tpq_val:0x%x\n", pmov->val_pq[i].en);
+       }
+       return 0;
+}
+
 /*2018-08-17 add debugfs*/
 /*same as dump_state*/
 static int seq_file_di_state_show(struct seq_file *seq, void *v)
@@ -1256,6 +1283,7 @@ DEFINE_SHOW_DI(seq_file_dump_di_reg);
 DEFINE_SHOW_DI(seq_file_dump_mif_size_state);
 DEFINE_SHOW_DI(seq_file_afbc);
 DEFINE_SHOW_DI(reg_cue_int);
+DEFINE_SHOW_DI(dbg_patch_mov_data);
 
 struct di_debugfs_files_t {
        const char *name;
@@ -1269,6 +1297,7 @@ static struct di_debugfs_files_t di_debugfs_files[] = {
        {"dumpmif", S_IFREG | 0644, &seq_file_dump_mif_size_state_fops},
        {"dumpafbc", S_IFREG | 0644, &seq_file_afbc_fops},
        {"reg_cue", S_IFREG | 0644, &reg_cue_int_fops},
+       {"dumpmov", S_IFREG | 0644, &dbg_patch_mov_data_fops},
 };
 
 void di_debugfs_init(void)
index 172de4f..b4a2e2f 100644 (file)
@@ -3878,6 +3878,7 @@ void di_load_regs(struct di_pq_parm_s *di_pq_ptr)
        unsigned int table_name = 0, nr_table = 0;
        bool ctrl_reg_flag = false;
        struct am_reg_s *regs_p = NULL;
+       bool mov_flg = false;
 
        if (pq_load_dbg == 1)
                return;
@@ -3926,7 +3927,9 @@ void di_load_regs(struct di_pq_parm_s *di_pq_ptr)
                }
                if (table_name & nr_table)
                        ctrl_reg_flag = set_nr_ctrl_reg_table(addr, value);
-               if (!ctrl_reg_flag)
+               if (table_name & TABLE_NAME_DI)
+                       mov_flg = di_patch_mov_db(addr, value);
+               if (!ctrl_reg_flag && !mov_flg)
                        DI_Wr(addr, value);
                if (pq_load_dbg == 2)
                        pr_info("[%u][0x%x] = [0x%x] %s\n", i, addr,
index 5d19a12..12e029a 100644 (file)
@@ -807,7 +807,7 @@ MODULE_PARM_DESC(di_debug_readreg, "di_debug_readreg");
 /*from VLSI yanling.liu, the patch fix TL1 1080I in some dark */
 /*scenes and roller coasters have small sawtooth, when turn off*/
 /*combing_fix_en, set the registers*/
-void fix_tl1_1080i_sawtooth_patch(void)
+static void fix_tl1_1080i_sawtooth_patch(void)
 {
        DI_Wr(0x1741, 0x0A0A1A22);
        DI_Wr(0x1742, 0x0a100101);
@@ -822,6 +822,35 @@ void fix_tl1_1080i_sawtooth_patch(void)
        DI_Wr(0x17af, 0x60020a60);
 }
 
+static void fix_tl1_1080i_patch2(void)
+{
+       DI_Wr(0x1741, 0x010a010a);
+       DI_Wr(0x1742, 0x01010101);
+       DI_Wr(0x1743, 0x00000101);
+       DI_Wr(0x1744, 0x00000101);
+       DI_Wr(0x17a9, 0x01010102);
+       DI_Wr(0x17aa, 0x02020101);
+       DI_Wr(0x17ab, 0x010a010a);
+       DI_Wr(0x17ac, 0x010a0102);
+       DI_Wr(0x17ad, 0x08080808);
+       DI_Wr(0x17ae, 0x01010101);
+       DI_Wr(0x17af, 0xff00031f);
+}
+
+void fix_tl1_1080i_patch_sel(unsigned int mode)
+{
+       switch (mode) {
+       case 0:/*not set*/
+               break;
+       case 1:
+               fix_tl1_1080i_sawtooth_patch();
+               break;
+       case 2:
+               fix_tl1_1080i_patch2();
+               break;
+       }
+}
+
 static int combing_cnt;
 int combing_diff_min = 2000;
 int combing_diff_max = 2000;
@@ -987,7 +1016,7 @@ module_param_named(cmb_adpset_cnt, cmb_adpset_cnt, int, 0644);
 static const struct mtn_op_s di_ops_mtn = {
        .mtn_int_combing_glbmot         = mtn_int_combing_glbmot,
        .adpative_combing_exit          = adpative_combing_exit,
-       .fix_tl1_1080i_sawtooth_patch   = fix_tl1_1080i_sawtooth_patch,
+       .fix_tl1_1080i_patch_sel        = fix_tl1_1080i_patch_sel,
        .adaptive_combing_fixing        = adaptive_combing_fixing,
        .adpative_combing_config        = adpative_combing_config,
        .com_patch_pre_sw_set           = com_patch_pre_sw_set,
index 8c7c6d2..0592f5d 100644 (file)
@@ -39,7 +39,7 @@ struct combing_status_s *adpative_combing_config(unsigned int width,
        unsigned int height,
        enum vframe_source_type_e src_type, bool prog,
        enum tvin_sig_fmt_e fmt);
-extern void fix_tl1_1080i_sawtooth_patch(void);
+void fix_tl1_1080i_patch_sel(unsigned int mode);
 int adaptive_combing_fixing(
        struct combing_status_s *cmb_status,
        unsigned int field_diff, unsigned int frame_diff,
index 74d669b..fcf3e54 100644 (file)
@@ -111,7 +111,7 @@ bool di_attach_ops_nr(const struct nr_op_s **ops);
 struct mtn_op_s {
        void (*mtn_int_combing_glbmot)(void);
        void (*adpative_combing_exit)(void);
-       void (*fix_tl1_1080i_sawtooth_patch)(void);
+       void (*fix_tl1_1080i_patch_sel)(unsigned int mode);
        int (*adaptive_combing_fixing)(
                struct combing_status_s *cmb_status,
                unsigned int field_diff, unsigned int frame_diff,
index 21b129d..1190401 100644 (file)
@@ -4404,10 +4404,10 @@ unsigned char dim_pre_de_buf_config(unsigned int channel)
                return 0;
        }
        if (is_meson_tl1_cpu()                  &&
-           di_mpr(combing_fix_en)              &&
+           ppre->comb_mode                     &&
            flg_1080i) {
                ppre->combing_fix_en = false;
-               get_ops_mtn()->fix_tl1_1080i_sawtooth_patch();
+               get_ops_mtn()->fix_tl1_1080i_patch_sel(ppre->comb_mode);
        } else {
                ppre->combing_fix_en = di_mpr(combing_fix_en);
        }
index a529710..96abc67 100644 (file)
@@ -414,6 +414,7 @@ struct di_pre_stru_s {
        /* combing adaptive */
        struct combing_status_s *mtn_status;
        bool combing_fix_en;
+       unsigned int comb_mode;
 };
 
 struct di_post_stru_s {