vlock: add adj stable check
authorDezhi Kong <dezhi.kong@amlogic.com>
Wed, 25 Jul 2018 04:25:34 +0000 (12:25 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Tue, 18 Sep 2018 09:21:22 +0000 (02:21 -0700)
PD#170985: vlock: add pll adj stable check

1.add pll adj stable check avoid pll m adj
2.add vlock version info
3.add enc adj stable check avoid enc line adj repeate
4.add enc_max_line_switch default config
5.update pll default regmap setting
6.add pll adj value check avoid blink caused by big pll step adj
7.optimize enc pixel adj method
8.add support dts config vlock key parameters
9.move vlock process to start of vsync isr
10.optimize pll for txl vbyone

Change-Id: Ie6e0aaacd23bfd7178db48e6f0d7bbec426b271f
Signed-off-by: Dezhi Kong <dezhi.kong@amlogic.com>
31 files changed:
arch/arm/boot/dts/amlogic/mesontxl_p321-panel.dtsi
arch/arm/boot/dts/amlogic/txl_t962_p321.dts
arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts
arch/arm/boot/dts/amlogic/txlx_t962x_r311_1g.dts
arch/arm/boot/dts/amlogic/txlx_t962x_r311_2g.dts
arch/arm64/boot/dts/amlogic/mesontxl_p321-panel.dtsi
arch/arm64/boot/dts/amlogic/txl_t950_p341.dts
arch/arm64/boot/dts/amlogic/txl_t960_p346.dts
arch/arm64/boot/dts/amlogic/txl_t962_p320.dts
arch/arm64/boot/dts/amlogic/txl_t962_p321.dts
arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts
arch/arm64/boot/dts/amlogic/txlx_t962e_r321_buildroot.dts
arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts
arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts
arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts
drivers/amlogic/media/enhancement/amvecm/amvecm.c
drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h
drivers/amlogic/media/enhancement/amvecm/vlock.c
drivers/amlogic/media/enhancement/amvecm/vlock.h
drivers/amlogic/media/video_sink/video.c
drivers/amlogic/media/vout/lcd/lcd_clk_config.c
drivers/amlogic/media/vout/lcd/lcd_clk_config.h
drivers/amlogic/media/vout/lcd/lcd_common.c
drivers/amlogic/media/vout/lcd/lcd_common.h
drivers/amlogic/media/vout/lcd/lcd_debug.c
drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c
drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c
drivers/amlogic/media/vout/lcd/lcd_vout.c
include/linux/amlogic/media/vout/lcd/lcd_notify.h
include/linux/amlogic/media/vout/lcd/lcd_unifykey.h
include/linux/amlogic/media/vout/lcd/lcd_vout.h

index be35ec6..f3f1ba2 100644 (file)
                                0 0 0 100 /*panel power off*/
                                0xff 0 0 0>; /*ending*/
                        backlight_index = <3>;
+
+                       /*vlock_attr = <1 // vlock_en: 1=enable,0=disable */
+                       /*      0x4 // vlock work mode:           */
+                       /*               *bit0:auto ENC           */
+                       /*               *bit1:auto PLL           */
+                       /*               *bit2:manual PLL         */
+                       /*               *bit3:manual ENC         */
+                       /*               *bit4:manual soft ENC    */
+                       /*               *bit5:manual MIX PLL ENC */
+                       /*           */
+                       /*      1   // vlock_pll_m_limit */
+                       /*      3>; // vlock_line_limit  */
                };
        }; /* end of lcd */
 
index c811a5f..76dd63c 100644 (file)
                gamma_en = <1>;/*1:enabel ;0:disable*/
                wb_en = <1>;/*1:enabel ;0:disable*/
                cm_en = <1>;/*1:enabel ;0:disable*/
+               wb_sel = <1>;/*1:mtx ;0:gainoff*/
+               vlock_en = <1>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+                vlock_pll_m_limit = <1>;
+                vlock_line_limit = <3>;
        };
 
        tuner: tuner {
index 06224e6..9aa3be6 100644 (file)
                tx_op_color_primary = <0>;
                /*1:enabel osd lut 100 table;0:disable*/
                cfg_en_osd_100 = <1>;
+               vlock_en = <1>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+               vlock_pll_m_limit = <1>;
+               vlock_line_limit = <3>;
        };
        amdolby_vision {
                compatible = "amlogic, dolby_vision_txlx";
index f0651cc..6192078 100644 (file)
                wb_en = <1>;/*1:enabel ;0:disable*/
                cm_en = <1>;/*1:enabel ;0:disable*/
                wb_sel = <1>;/*1:mtx ;0:gainoff*/
+               vlock_en = <1>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+                vlock_pll_m_limit = <1>;
+                vlock_line_limit = <3>;
        };
        amdolby_vision {
                compatible = "amlogic, dolby_vision_txlx";
index 57dcbee..93ab8e9 100644 (file)
                wb_en = <1>;/*1:enabel ;0:disable*/
                cm_en = <1>;/*1:enabel ;0:disable*/
                wb_sel = <1>;/*1:mtx ;0:gainoff*/
+               vlock_en = <1>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+                vlock_pll_m_limit = <1>;
+                vlock_line_limit = <3>;
        };
        amdolby_vision {
                compatible = "amlogic, dolby_vision_txlx";
index 274f3e5..4d062ce 100644 (file)
                                0 0 0 100 /*panel power off*/
                                0xff 0 0 0>; /*ending*/
                        backlight_index = <3>;
+
+                       /*vlock_attr = <1 // vlock_en: 1=enable,0=disable */
+                       /*      0x4 // vlock work mode:           */
+                       /*               *bit0:auto ENC           */
+                       /*               *bit1:auto PLL           */
+                       /*               *bit2:manual PLL         */
+                       /*               *bit3:manual ENC         */
+                       /*               *bit4:manual soft ENC    */
+                       /*               *bit5:manual MIX PLL ENC */
+                       /*           */
+                       /*      1   // vlock_pll_m_limit */
+                       /*      3>; // vlock_line_limit  */
                };
        }; /* end of lcd */
 
index 2008afd..ebdb351 100644 (file)
                gamma_en = <1>;/*1:enabel ;0:disable*/
                wb_en = <1>;/*1:enabel ;0:disable*/
                cm_en = <1>;/*1:enabel ;0:disable*/
+               wb_sel = <1>;/*1:mtx ;0:gainoff*/
+               vlock_en = <1>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+                vlock_pll_m_limit = <1>;
+                vlock_line_limit = <3>;
        };
 
        tuner: tuner {
index 9efde02..fa832cc 100644 (file)
                gamma_en = <1>;/*1:enabel ;0:disable*/
                wb_en = <1>;/*1:enabel ;0:disable*/
                cm_en = <1>;/*1:enabel ;0:disable*/
+               wb_sel = <1>;/*1:mtx ;0:gainoff*/
+               vlock_en = <1>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+                vlock_pll_m_limit = <1>;
+                vlock_line_limit = <3>;
        };
 
        tuner: tuner {
index b8f61f1..48b6360 100644 (file)
                gamma_en = <1>;/*1:enabel ;0:disable*/
                wb_en = <1>;/*1:enabel ;0:disable*/
                cm_en = <1>;/*1:enabel ;0:disable*/
+               wb_sel = <1>;/*1:mtx ;0:gainoff*/
+               vlock_en = <1>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+                vlock_pll_m_limit = <1>;
+                vlock_line_limit = <3>;
        };
 
        tuner: tuner {
index b25f050..08d3550 100644 (file)
                gamma_en = <1>;/*1:enabel ;0:disable*/
                wb_en = <1>;/*1:enabel ;0:disable*/
                cm_en = <1>;/*1:enabel ;0:disable*/
+               wb_sel = <1>;/*1:mtx ;0:gainoff*/
+               vlock_en = <1>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+                vlock_pll_m_limit = <1>;
+                vlock_line_limit = <3>;
        };
 
        tuner: tuner {
index aeb3c54..e8eb091 100644 (file)
                tx_op_color_primary = <0>;
                /*1:enabel osd lut 100 table;0:disable*/
                cfg_en_osd_100 = <1>;
+               vlock_en = <1>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+               vlock_pll_m_limit = <1>;
+               vlock_line_limit = <3>;
        };
        amdolby_vision {
                compatible = "amlogic, dolby_vision_txlx";
index 03096db..76c5a37 100644 (file)
                tx_op_color_primary = <0>;
                /*1:enabel osd lut 100 table;0:disable*/
                cfg_en_osd_100 = <1>;
+
+               vlock_en = <0>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+               vlock_pll_m_limit = <1>;
+               vlock_line_limit = <3>;
        };
        amdolby_vision {
                compatible = "amlogic, dolby_vision_txlx";
index 99f95b9..7d37fd6 100644 (file)
                wb_en = <1>;/*1:enabel ;0:disable*/
                cm_en = <1>;/*1:enabel ;0:disable*/
                wb_sel = <1>;/*1:mtx ;0:gainoff*/
+               vlock_en = <1>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+                vlock_pll_m_limit = <1>;
+                vlock_line_limit = <3>;
        };
        amdolby_vision {
                compatible = "amlogic, dolby_vision_txlx";
index 6628ae2..b0b5f7f 100644 (file)
                wb_en = <1>;/*1:enabel ;0:disable*/
                cm_en = <1>;/*1:enabel ;0:disable*/
                wb_sel = <1>;/*1:mtx ;0:gainoff*/
+               vlock_en = <1>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+                vlock_pll_m_limit = <1>;
+                vlock_line_limit = <3>;
        };
        amdolby_vision {
                compatible = "amlogic, dolby_vision_txlx";
index 8697f1b..2d00975 100644 (file)
                wb_en = <1>;/*1:enabel ;0:disable*/
                cm_en = <1>;/*1:enabel ;0:disable*/
                wb_sel = <1>;/*1:mtx ;0:gainoff*/
+               vlock_en = <1>;/*1:enable;0:disable*/
+               vlock_mode = <0x4>;
+               /* vlock work mode:
+                *bit0:auto ENC
+                *bit1:auto PLL
+                *bit2:manual PLL
+                *bit3:manual ENC
+                *bit4:manual soft ENC
+                *bit5:manual MIX PLL ENC
+                */
+                vlock_pll_m_limit = <1>;
+                vlock_line_limit = <3>;
        };
        amdolby_vision {
                compatible = "amlogic, dolby_vision_txlx";
index 6334cd9..cd38124 100644 (file)
@@ -552,6 +552,10 @@ static ssize_t amvecm_vlock_show(struct class *cla,
        len += sprintf(buf+len,
                "echo vlock_delta_limit val(D) > /sys/class/amvecm/vlock\n");
        len += sprintf(buf+len,
+               "echo vlock_pll_m_limit val(D) > /sys/class/amvecm/vlock\n");
+       len += sprintf(buf+len,
+               "echo vlock_delta_cnt_limit val(D) > /sys/class/amvecm/vlock\n");
+       len += sprintf(buf+len,
                "echo vlock_debug val(0x111) > /sys/class/amvecm/vlock\n");
        len += sprintf(buf+len,
                "echo vlock_dynamic_adjust val(0/1) > /sys/class/amvecm/vlock\n");
@@ -621,6 +625,16 @@ static ssize_t amvecm_vlock_store(struct class *cla,
                        return -EINVAL;
                temp_val = val;
                sel = VLOCK_DELTA_LIMIT;
+       } else if (!strncmp(parm[0], "vlock_pll_m_limit", 17)) {
+               if (kstrtol(parm[1], 10, &val) < 0)
+                       return -EINVAL;
+               temp_val = val;
+               sel = VLOCK_PLL_M_LIMIT;
+       } else if (!strncmp(parm[0], "vlock_delta_cnt_limit", 21)) {
+               if (kstrtol(parm[1], 10, &val) < 0)
+                       return -EINVAL;
+               temp_val = val;
+               sel = VLOCK_DELTA_CNT_LIMIT;
        } else if (!strncmp(parm[0], "vlock_debug", 11)) {
                if (kstrtol(parm[1], 16, &val) < 0)
                        return -EINVAL;
@@ -5048,6 +5062,8 @@ static void aml_vecm_dt_parse(struct platform_device *pdev)
                        pr_info("Can't find  tx_op_color_primary.\n");
                else
                        tx_op_color_primary = val;
+               /*vlock param config*/
+               vlock_param_config(node);
        }
        /* init module status */
        amvecm_wb_init(wb_en);
index 96abe2a..bdd4737 100644 (file)
@@ -60,7 +60,7 @@ static struct vlock_regs_s vlock_pll_setting[VLOCK_DEFAULT_REG_SIZE] = {
        {0x3007,     0x00000000   },
        {0x3008,     0x00000000   },
        {0x3009,     0x00100000   },
-       {0x300a,     0x00008000   },
+       {0x300a,     0x00600000   },
        {0x300b,     0x00100000   },
        {0x300c,     0x00000000   },
        {0x300d,     0x00004000   },
index 6ec8dec..9e47876 100644 (file)
@@ -26,6 +26,9 @@
 #include <linux/amlogic/media/vout/vinfo.h>
 #include <linux/amlogic/media/vout/vout_notify.h>
 #include <linux/io.h>
+#ifdef CONFIG_AMLOGIC_LCD
+#include <linux/amlogic/media/vout/lcd/lcd_notify.h>
+#endif
 #include "arch/vpp_regs.h"
 #include "vlock.h"
 #include "amvecm_vlock_regmap.h"
@@ -45,8 +48,17 @@ unsigned int vlock_en = 1;
 static unsigned int vlock_adapt;
 static unsigned int vlock_dis_cnt_limit = 2;
 static unsigned int vlock_delta_limit = 2;
+/*limit vlock pll m adj*/
+static unsigned int vlock_pll_m_limit = 1;
+/*for 24MHZ clock, 50hz input, delta value (10) of(0x3011-0x3012) == 0.001HZ */
+static unsigned int vlock_delta_cnt_limit = 10;
+static unsigned int vlock_pll_stable_flag;
+static unsigned int vlock_enc_stable_flag;
 static unsigned int vlock_pll_stable_cnt;
-static unsigned int vlock_pll_stable_limit = 180;/*3s for 60hz input*/
+static unsigned int vlock_pll_stable_limit = 600;/*10s for 60hz input*/
+static unsigned int vlock_pll_adj_limit;
+static unsigned int vlock_pll_val_last;
+static unsigned int vlock_intput_type;
 /* [reg(0x3009) x linemax_num)]>>24 is the limit line of enc mode
  * change from 4 to 3,for 4 may cause shake issue for 60.3hz input
  */
@@ -78,6 +90,7 @@ static unsigned int enc_max_pixel_addr;
 static unsigned int enc_video_mode_addr;
 static unsigned int enc_video_mode_adv_addr;
 static unsigned int enc_max_line_switch_addr;
+static unsigned int pre_video_clk;
 
 static unsigned int vlock_dis_cnt_no_vf;
 static unsigned int vlock_dis_cnt_no_vf_limit = 5;
@@ -215,7 +228,7 @@ static void vlock_enable(bool enable)
        amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value);
 
        if (is_meson_gxtvbb_cpu()) {
-               if (vlock_mode == VLOCK_MODE_MANUAL_PLL) {
+               if (vlock_mode & VLOCK_MODE_MANUAL_PLL) {
                        amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 0, 20, 1);
                        /*vlsi suggest config:don't enable load signal,
                         *on gxtvbb this load signal will effect SSG,
@@ -229,7 +242,7 @@ static void vlock_enable(bool enable)
                        amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6,
                                enable, 20, 1);
        } else if (is_meson_txl_cpu() || is_meson_txlx_cpu()) {
-               if (vlock_mode == VLOCK_MODE_MANUAL_PLL)
+               if (vlock_mode & VLOCK_MODE_MANUAL_PLL)
                        amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL5, 0, 3, 1);
                else
                        amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL5,
@@ -253,9 +266,9 @@ static void vlock_setting(struct vframe_s *vf,
        unsigned int hiu_m_val, hiu_frac_val, temp_value;
 
        amvecm_hiu_reg_write(HHI_VID_LOCK_CLK_CNTL, 0x80);
-       if ((vlock_mode == VLOCK_MODE_AUTO_ENC) ||
-               (vlock_mode == VLOCK_MODE_MANUAL_ENC) ||
-               (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC)) {
+       if ((vlock_mode & (VLOCK_MODE_AUTO_ENC |
+               VLOCK_MODE_MANUAL_ENC |
+               VLOCK_MODE_MANUAL_SOFT_ENC))) {
                /*init default config for enc mode*/
                vlock_hw_reinit(vlock_enc_setting, VLOCK_DEFAULT_REG_SIZE);
                /*vlock line limit*/
@@ -265,12 +278,14 @@ static void vlock_setting(struct vframe_s *vf,
                /* disable to adjust pll */
                WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 29, 1);
                /* CFG_VID_LOCK_ADJ_EN enable */
-               if ((vlock_mode == VLOCK_MODE_MANUAL_ENC) ||
-                       (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC)) {
+               if ((vlock_mode & (VLOCK_MODE_MANUAL_ENC |
+                       VLOCK_MODE_MANUAL_SOFT_ENC))) {
                        /*auto vlock off*/
                        WRITE_VPP_REG_BITS(enc_max_line_switch_addr,
                                0, 13, 1);
                        WRITE_VPP_REG_BITS(enc_video_mode_adv_addr, 1, 14, 1);
+                       WRITE_VPP_REG_BITS(enc_max_line_switch_addr,
+                               pre_enc_max_pixel, 0, 13);
                } else {
                        WRITE_VPP_REG_BITS(enc_max_line_switch_addr,
                                1, 13, 1);
@@ -289,7 +304,7 @@ static void vlock_setting(struct vframe_s *vf,
                 *bit8~15:output freq
                 */
                if ((vf->type_original & VIDTYPE_TYPEMASK) &&
-                       (vlock_mode != VLOCK_MODE_MANUAL_SOFT_ENC))
+                       !(vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC))
                        input_hz = input_hz >> 1;
                freq_hz = input_hz | (output_hz << 8);
                WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, freq_hz, 0, 16);
@@ -310,8 +325,8 @@ static void vlock_setting(struct vframe_s *vf,
                        vlock_latch_en_cnt, 8, 8);
                WRITE_VPP_REG_BITS(enc_video_mode_addr, 0, 15, 1);
        }
-       if ((vlock_mode == VLOCK_MODE_AUTO_PLL) ||
-               (vlock_mode == VLOCK_MODE_MANUAL_PLL)) {
+       if ((vlock_mode & (VLOCK_MODE_AUTO_PLL |
+               VLOCK_MODE_MANUAL_PLL))) {
                /* av pal in,1080p60 hdmi out as default */
                vlock_hw_reinit(vlock_pll_setting, VLOCK_DEFAULT_REG_SIZE);
                /*
@@ -354,6 +369,10 @@ static void vlock_setting(struct vframe_s *vf,
                                + (hiu_frac_val << 2);
                }
                WRITE_VPP_REG_BITS(VPU_VLOCK_MX4096, reg_value, 0, 21);
+               /*vlock_pll_adj_limit = (reg_value * 0x8000) >> 24;*/
+               vlock_pll_adj_limit = reg_value >> VLOCK_PLL_ADJ_LIMIT;
+               vlock_pll_val_last = ((reg_value & 0x3fff000) << 4) |
+                       (reg_value & 0x3fff);
 
                /*enable vlock to adj pll*/
                /* CFG_VID_LOCK_ADJ_EN disable */
@@ -391,7 +410,7 @@ static void vlock_setting(struct vframe_s *vf,
 void vlock_vmode_check(void)
 {
        const struct vinfo_s *vinfo;
-       unsigned int tmp_value, hiu_reg_addr;
+       unsigned int t0, t1, hiu_reg_addr, cur_video_clk;
        char cur_vout_mode[64];
 
        if (vlock_en == 0)
@@ -402,22 +421,39 @@ void vlock_vmode_check(void)
                hiu_reg_addr = HHI_HDMI_PLL_CNTL2;
        vinfo = get_current_vinfo();
        vlock_vmode_changed = 0;
+       cur_video_clk = vinfo->video_clk;
        memset(cur_vout_mode, 0, sizeof(cur_vout_mode));
        if ((vinfo->name == NULL) ||
                (strlen(vinfo->name) > sizeof(cur_vout_mode)))
                return;
        strcpy(cur_vout_mode, vinfo->name);
        if (strcmp(cur_vout_mode, pre_vout_mode) != 0) {
-               if ((vlock_mode == VLOCK_MODE_MANUAL_PLL) ||
-                       (vlock_mode == VLOCK_MODE_AUTO_PLL)) {
-                       amvecm_hiu_reg_read(hiu_reg_addr, &tmp_value);
-                       pre_hiu_reg_frac = tmp_value & 0xfff;
-                       amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &tmp_value);
-                       pre_hiu_reg_m = tmp_value & 0x1ff;
+               if (vlock_mode & (VLOCK_MODE_MANUAL_PLL |
+                       VLOCK_MODE_AUTO_PLL)) {
+                       amvecm_hiu_reg_read(hiu_reg_addr, &t0);
+                       amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &t1);
+                       if (cur_video_clk != pre_video_clk) {
+                               pre_hiu_reg_frac = t0 & 0xfff;
+                               pre_hiu_reg_m = t1 & 0x1ff;
+                               pre_video_clk = cur_video_clk;
+                       } else {
+                               if ((t0 & 0xfff) != pre_hiu_reg_frac) {
+                                       t0 = (t0 & 0xfffff000) |
+                                               (pre_hiu_reg_frac & 0xfff);
+                                       amvecm_hiu_reg_write(hiu_reg_addr, t0);
+                               }
+                               if (((t1 & 0x1ff) != pre_hiu_reg_m) &&
+                                       (pre_hiu_reg_m != 0)) {
+                                       t1 = (t1 & 0xfffffe00) |
+                                               (pre_hiu_reg_m & 0x1ff);
+                                       amvecm_hiu_reg_write(HHI_HDMI_PLL_CNTL,
+                                               t1);
+                               }
+                       }
                }
-               if ((vlock_mode == VLOCK_MODE_MANUAL_ENC) ||
-                       (vlock_mode == VLOCK_MODE_AUTO_ENC) ||
-                       (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC)) {
+               if ((vlock_mode & (VLOCK_MODE_MANUAL_ENC |
+                       VLOCK_MODE_AUTO_ENC |
+                       VLOCK_MODE_MANUAL_SOFT_ENC))) {
                        switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL,
                                0, 2)) {
                        case 0:
@@ -475,17 +511,16 @@ static void vlock_disable_step1(void)
        /* VLOCK_CNTL_EN disable */
        vlock_enable(0);
        vlock_vmode_check();
-       if ((vlock_mode == VLOCK_MODE_MANUAL_PLL) ||
-               (vlock_mode == VLOCK_MODE_AUTO_PLL) ||
-               (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC)) {
+       if ((vlock_mode & (VLOCK_MODE_MANUAL_PLL |
+               VLOCK_MODE_AUTO_PLL |
+               VLOCK_MODE_MANUAL_SOFT_ENC))) {
                if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL)
                        hiu_reg_addr = HHI_HDMI_PLL_CNTL1;
                else
                        hiu_reg_addr = HHI_HDMI_PLL_CNTL2;
                amvecm_hiu_reg_read(hiu_reg_addr, &tmp_value);
                m_reg_value = tmp_value & 0xfff;
-               if ((m_reg_value != pre_hiu_reg_frac) &&
-                       (pre_hiu_reg_frac != 0)) {
+               if (m_reg_value != pre_hiu_reg_frac) {
                        tmp_value = (tmp_value & 0xfffff000) |
                                (pre_hiu_reg_frac & 0xfff);
                        amvecm_hiu_reg_write(hiu_reg_addr, tmp_value);
@@ -499,24 +534,23 @@ static void vlock_disable_step1(void)
                        amvecm_hiu_reg_write(HHI_HDMI_PLL_CNTL, tmp_value);
                }
        }
-       if ((vlock_mode == VLOCK_MODE_MANUAL_ENC) ||
-               (vlock_mode == VLOCK_MODE_AUTO_ENC) ||
-               (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC)) {
+       if ((vlock_mode & (VLOCK_MODE_MANUAL_ENC |
+               VLOCK_MODE_AUTO_ENC |
+               VLOCK_MODE_MANUAL_SOFT_ENC))) {
                err_accum = 0;
                WRITE_VPP_REG_BITS(enc_video_mode_adv_addr, 0, 14, 1);
                enc_max_line = READ_VPP_REG(enc_max_line_addr);
-               enc_max_pixel = READ_VPP_REG(enc_max_pixel_addr);
+               enc_max_pixel = READ_VPP_REG_BITS(enc_max_line_switch_addr,
+                       0, 13);
                if (!(vlock_debug & VLOCK_DEBUG_ENC_LINE_ADJ_DIS) &&
                        (enc_max_line != pre_enc_max_line) &&
                        (pre_enc_max_line != 0) && (enc_max_line_addr != 0))
                        WRITE_VPP_REG(enc_max_line_addr, pre_enc_max_line);
                if (!(vlock_debug & VLOCK_DEBUG_ENC_PIXEL_ADJ_DIS) &&
                        (enc_max_pixel != pre_enc_max_pixel) &&
-                       (enc_max_line_addr != 0) && (enc_max_pixel_addr != 0)) {
+                       (enc_max_line_switch_addr != 0))
                        WRITE_VPP_REG_BITS(enc_max_line_switch_addr,
                                0x1fff, 0, 13);
-                       WRITE_VPP_REG(enc_max_pixel_addr, pre_enc_max_pixel);
-               }
        }
        vlock_dis_cnt = vlock_dis_cnt_limit;
        memset(pre_vout_mode, 0, sizeof(pre_vout_mode));
@@ -526,7 +560,13 @@ static void vlock_disable_step1(void)
        pre_input_freq = 0;
        pre_output_freq = 0;
        vlock_state = VLOCK_STATE_DISABLE_STEP1_DONE;
-       vlock_mode = VLOCK_MODE_MANUAL_PLL;
+       if (vlock_mode & VLOCK_MODE_MANUAL_MIX_PLL_ENC) {
+               vlock_mode &= ~VLOCK_MODE_MANUAL_MIX_PLL_ENC;
+               vlock_mode |= VLOCK_MODE_MANUAL_PLL;
+       }
+       vlock_pll_stable_cnt = 0;
+       vlock_pll_stable_flag = 0;
+       vlock_enc_stable_flag = 0;
 }
 
 static void vlock_disable_step2(void)
@@ -578,6 +618,8 @@ static void vlock_enable_step1(struct vframe_s *vf, struct vinfo_s *vinfo,
        vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE;
        vlock_pll_stable_cnt = 0;
        vlock_log_cnt = 0;
+       vlock_pll_stable_flag = 0;
+       vlock_enc_stable_flag = 0;
 }
 
 void vlock_log_start(void)
@@ -784,25 +826,37 @@ static void vlock_enable_step3_soft_enc(void)
 
        line_adj = nT0 >> 14;
 
-       if (line_adj > vlock_line_limit)
-               line_adj = vlock_line_limit;
-       else if (line_adj < -vlock_line_limit)
-               line_adj = -vlock_line_limit;
-
        tfrac = nT0 - (line_adj << 14);
 
        pixel_adj = (tfrac * pre_enc_max_pixel + 8192) >> 14;
 
-       if ((pixel_adj + pre_enc_max_pixel) > 0x1fff) {
+       while ((pixel_adj < 0) && (pre_enc_max_pixel > 0)) {
+               line_adj = line_adj - 1;
+               pixel_adj = pre_enc_max_pixel + pixel_adj;
+       }
+
+       while (((pixel_adj + pre_enc_max_pixel) > 0x1fff) &&
+               (pre_enc_max_pixel > 0)) {
                line_adj = line_adj + 1;
                pixel_adj = pixel_adj - pre_enc_max_pixel;
        }
 
+       if (line_adj > vlock_line_limit)
+               line_adj = vlock_line_limit;
+       else if (line_adj < -vlock_line_limit)
+               line_adj = -vlock_line_limit;
+
        pixel_adj &= 0xfffffffe;/*clean bit0*/
 
-       WRITE_VPP_REG(ENCL_VIDEO_MAX_LNCNT, pre_enc_max_line + line_adj);
-       WRITE_VPP_REG(ENCL_MAX_LINE_SWITCH_POINT,
-               pre_enc_max_pixel + pixel_adj);
+       if (vlock_enc_stable_flag++ > VLOCK_ENC_STABLE_CNT)
+               vlock_enc_stable_flag = VLOCK_ENC_STABLE_CNT;
+       if ((vlock_enc_stable_flag < VLOCK_ENC_STABLE_CNT) &&
+               (!(vlock_debug & VLOCK_DEBUG_ENC_LINE_ADJ_DIS)))
+               WRITE_VPP_REG(ENCL_VIDEO_MAX_LNCNT,
+                       pre_enc_max_line + line_adj);
+       if (!(vlock_debug & VLOCK_DEBUG_ENC_PIXEL_ADJ_DIS))
+               WRITE_VPP_REG(ENCL_MAX_LINE_SWITCH_POINT,
+                       pre_enc_max_pixel + pixel_adj);
 
        last_i_vsync = READ_VPP_REG(0x3011);
 
@@ -819,10 +873,32 @@ static void vlock_enable_step3_soft_enc(void)
                vlock_log_cnt++;
        }
 }
-
+/*check pll adj value (0x3020),otherwise may cause blink*/
+static void vlock_pll_adj_limit_check(unsigned int *pll_val)
+{
+       unsigned int m_reg_value, pll_cur, pll_last, pll_ret;
+
+       m_reg_value = *pll_val;
+
+       if (m_reg_value != 0) {
+               pll_cur = ((m_reg_value & 0x3fff0000) >> 4) |
+                       (m_reg_value & 0x3fff);
+               pll_last = ((vlock_pll_val_last & 0x3fff0000) >> 4) |
+                       (vlock_pll_val_last & 0x3fff);
+               if (abs(pll_cur - pll_last) > vlock_pll_adj_limit) {
+                       if (pll_cur > pll_last)
+                               pll_ret = pll_last + vlock_pll_adj_limit;
+                       else
+                               pll_ret = pll_last - vlock_pll_adj_limit;
+                       *pll_val = ((pll_ret & 0x3fff000) << 4) |
+                               (pll_ret & 0x3fff);
+               }
+       }
+}
 static void vlock_enable_step3_pll(void)
 {
        unsigned int m_reg_value, tmp_value, abs_val, hiu_reg_addr;
+       unsigned int ia, oa, abs_cnt;
 
        if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL)
                hiu_reg_addr = HHI_HDMI_PLL_CNTL1;
@@ -854,8 +930,10 @@ static void vlock_enable_step3_pll(void)
 
        m_reg_value = READ_VPP_REG(VPU_VLOCK_RO_M_INT_FRAC);
        if (vlock_log_en && (vlock_log_cnt < vlock_log_size)) {
-               vlock_log[vlock_log_cnt]->pll_frac = (m_reg_value & 0xfff) >> 2;
-               vlock_log[vlock_log_cnt]->pll_m = (m_reg_value >> 16) & 0x1ff;
+               vlock_log[vlock_log_cnt]->pll_frac =
+                       (vlock_pll_val_last & 0xfff) >> 2;
+               vlock_log[vlock_log_cnt]->pll_m =
+                       (vlock_pll_val_last >> 16) & 0x1ff;
                vlock_reg_get();
                vlock_log_cnt++;
        }
@@ -866,6 +944,9 @@ static void vlock_enable_step3_pll(void)
                                __func__);
                return;
        }
+       /*check adjust delta limit*/
+       vlock_pll_adj_limit_check(&m_reg_value);
+
        /*vlsi suggest config:don't enable load signal,
         *on gxtvbb this load signal will effect SSG,
         *which may result in flashes black
@@ -873,6 +954,14 @@ static void vlock_enable_step3_pll(void)
        amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value);
        if (is_meson_gxtvbb_cpu() && (((tmp_value >> 21) & 0x3) != 2))
                amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 2, 21, 2);
+       /*add delta count check*/
+       /*for interlace input need div 2*/
+       if (vlock_intput_type)
+               ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST) / 2;
+       else
+               ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST);
+       oa = READ_VPP_REG(VPU_VLOCK_RO_VS_O_DIST);
+       abs_cnt = abs(ia - oa);
        /*frac*/
        amvecm_hiu_reg_read(hiu_reg_addr, &tmp_value);
        abs_val = abs(((m_reg_value & 0xfff) >> 2) - (tmp_value & 0xfff));
@@ -880,30 +969,40 @@ static void vlock_enable_step3_pll(void)
                pr_info("vlock frac delta:%d(0x%x,0x%x)\n",
                        abs_val, ((m_reg_value & 0xfff) >> 2),
                        (tmp_value & 0xfff));
-       if (abs_val >= vlock_delta_limit) {
+       if ((abs_val >= vlock_delta_limit) &&
+               (abs_cnt > vlock_delta_cnt_limit)) {
                tmp_value = (tmp_value & 0xfffff000) |
                        ((m_reg_value & 0xfff) >> 2);
                amvecm_hiu_reg_write(hiu_reg_addr, tmp_value);
+               vlock_pll_val_last &= 0xffff0000;
+               vlock_pll_val_last |= (m_reg_value & 0xfff);
        }
        /*check stable by diff frac*/
-       if (abs_val < (2 * vlock_delta_limit))
+       if ((abs_val < (2 * vlock_delta_limit)) &&
+               (abs_cnt < vlock_enc_adj_limit))
                vlock_pll_stable_cnt++;
        else
                vlock_pll_stable_cnt = 0;
+       if (vlock_pll_stable_flag++ > VLOCK_PLL_STABLE_CNT)
+               vlock_pll_stable_flag = VLOCK_PLL_STABLE_CNT;
        /*m*/
        amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &tmp_value);
-       abs_val = abs(((m_reg_value >> 16) & 0x1ff) - (tmp_value & 0x1ff));
+       abs_val = abs(((m_reg_value >> 16) & 0x1ff) - (pre_hiu_reg_m & 0x1ff));
        if ((abs_val > vlock_log_delta_m) && (vlock_log_delta_en&(1<<4)))
                pr_info("vlock m delta:%d(0x%x,0x%x)\n",
                        abs_val, ((m_reg_value >> 16) & 0x1ff),
                        (tmp_value & 0x1ff));
-       if (((m_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff)) {
+       if ((abs_val <= vlock_pll_m_limit) &&
+               (((m_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff)) &&
+               (abs_cnt > vlock_delta_cnt_limit)) {
                tmp_value = (tmp_value & 0xfffffe00) |
                        ((m_reg_value >> 16) & 0x1ff);
                amvecm_hiu_reg_write(HHI_HDMI_PLL_CNTL, tmp_value);
+               vlock_pll_val_last &= 0x0000ffff;
+               vlock_pll_val_last |= (m_reg_value & 0xffff0000);
        }
        /*check stable by diff m*/
-       if (abs_val)
+       if (((m_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff))
                vlock_pll_stable_cnt = 0;
 }
 /* won't change this function internal seqence,
@@ -965,14 +1064,16 @@ void amve_vlock_process(struct vframe_s *vf)
                        (vlock_state >= VLOCK_STATE_ENABLE_STEP1_DONE)) {
                        vlock_sync_limit_flag++;
                        if ((vlock_sync_limit_flag <= 3) &&
-                               (vlock_mode == VLOCK_MODE_MANUAL_ENC)) {
+                               ((vlock_mode & (VLOCK_MODE_MANUAL_ENC |
+                               VLOCK_MODE_MANUAL_PLL)))) {
                                WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1);
                                WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1);
                                WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM0, 0);
                                WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM1, 0);
                        }
                        if ((vlock_sync_limit_flag == 4) &&
-                               (vlock_mode == VLOCK_MODE_MANUAL_ENC)) {
+                               ((vlock_mode & (VLOCK_MODE_MANUAL_ENC |
+                               VLOCK_MODE_MANUAL_PLL)))) {
                                WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);
                                WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1);
                        }
@@ -998,32 +1099,35 @@ void amve_vlock_process(struct vframe_s *vf)
                        (vlock_sync_limit_flag > 5) &&
                        (vlock_state == VLOCK_STATE_ENABLE_STEP2_DONE) &&
                        (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) &&
-                       ((vlock_mode == VLOCK_MODE_MANUAL_PLL) ||
-                       (vlock_mode == VLOCK_MODE_MANUAL_ENC) ||
-                       (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC))) {
-                       if (vlock_mode == VLOCK_MODE_MANUAL_ENC)
+                       ((vlock_mode & (VLOCK_MODE_MANUAL_PLL |
+                       VLOCK_MODE_MANUAL_ENC |
+                       VLOCK_MODE_MANUAL_SOFT_ENC)))) {
+                       if (vlock_mode & VLOCK_MODE_MANUAL_ENC)
                                vlock_enable_step3_enc();
-                       else if (vlock_mode == VLOCK_MODE_MANUAL_PLL)
+                       else if (vlock_mode & VLOCK_MODE_MANUAL_PLL)
                                vlock_enable_step3_pll();
-                       else if (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC)
+                       else if (vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC)
                                vlock_enable_step3_soft_enc();
                        /*check stable*/
                        if ((vinfo->fr_adj_type != VOUT_FR_ADJ_HDMI) &&
                                (vinfo->width <= 1920) &&
                                !(vlock_debug & VLOCK_DEBUG_PLL2ENC_DIS) &&
+                               (vlock_mode &
+                               VLOCK_MODE_MANUAL_MIX_PLL_ENC) &&
                                (vlock_pll_stable_cnt >
                                vlock_pll_stable_limit)) {
                                /*reinit pre_vout_mode for trace mode check*/
                                memset(pre_vout_mode, 0, sizeof(pre_vout_mode));
-                               vlock_mode = VLOCK_MODE_MANUAL_SOFT_ENC;
+                               vlock_mode &= ~VLOCK_MODE_MANUAL_MIX_PLL_ENC;
+                               vlock_mode |= VLOCK_MODE_MANUAL_SOFT_ENC;
                                vlock_state = VLOCK_STATE_ENABLE_FORCE_RESET;
                                if (vlock_debug & VLOCK_DEBUG_INFO)
-                               pr_info("[%s]force reset for switch pll to enc mode!!!\n",
+                                       pr_info("[%s]force reset for switch pll to enc mode!!!\n",
                                        __func__);
                        }
                }
-               if (((vlock_mode == VLOCK_MODE_AUTO_PLL) ||
-                       (vlock_mode == VLOCK_MODE_AUTO_ENC)) &&
+               if (((vlock_mode & (VLOCK_MODE_AUTO_PLL |
+                       VLOCK_MODE_AUTO_ENC))) &&
                        vlock_log_en && (vlock_log_cnt < vlock_log_size) &&
                        (vlock_debug & VLOCK_DEBUG_AUTO_MODE_LOG_EN)) {
                        vlock_reg_get();
@@ -1058,14 +1162,14 @@ void amve_vlock_resume(void)
                (vlock_sync_limit_flag > 5) &&
                (vlock_state == VLOCK_STATE_ENABLE_STEP2_DONE) &&
                (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) &&
-               ((vlock_mode == VLOCK_MODE_MANUAL_PLL) ||
-               (vlock_mode == VLOCK_MODE_MANUAL_ENC) ||
-               (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC))) {
-               if (vlock_mode == VLOCK_MODE_MANUAL_ENC)
+               ((vlock_mode & (VLOCK_MODE_MANUAL_PLL |
+               VLOCK_MODE_MANUAL_ENC |
+               VLOCK_MODE_MANUAL_SOFT_ENC)))) {
+               if (vlock_mode & VLOCK_MODE_MANUAL_ENC)
                        vlock_enable_step3_enc();
-               else if (vlock_mode == VLOCK_MODE_MANUAL_PLL)
+               else if (vlock_mode & VLOCK_MODE_MANUAL_PLL)
                        vlock_enable_step3_pll();
-               else if (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC)
+               else if (vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC)
                        vlock_enable_step3_soft_enc();
        }
 }
@@ -1108,6 +1212,12 @@ void vlock_param_set(unsigned int val, enum vlock_param_e sel)
        case VLOCK_DELTA_LIMIT:
                vlock_delta_limit = val;
                break;
+       case VLOCK_PLL_M_LIMIT:
+               vlock_pll_m_limit = val;
+               break;
+       case VLOCK_DELTA_CNT_LIMIT:
+               vlock_delta_cnt_limit = val;
+               break;
        case VLOCK_DEBUG:
                vlock_debug = val;
                break;
@@ -1134,6 +1244,8 @@ void vlock_status(void)
        pr_info("vlock_adapt:%d\n", vlock_adapt);
        pr_info("vlock_dis_cnt_limit:%d\n", vlock_dis_cnt_limit);
        pr_info("vlock_delta_limit:%d\n", vlock_delta_limit);
+       pr_info("vlock_pll_m_limit:%d\n", vlock_pll_m_limit);
+       pr_info("vlock_delta_cnt_limit:%d\n", vlock_delta_cnt_limit);
        pr_info("vlock_debug:0x%x\n", vlock_debug);
        pr_info("vlock_dynamic_adjust:%d\n", vlock_dynamic_adjust);
        pr_info("vlock_state:%d\n", vlock_state);
@@ -1156,6 +1268,12 @@ void vlock_status(void)
        pr_info("vlock_pll_stable_cnt:%d\n", vlock_pll_stable_cnt);
        pr_info("vlock_pll_stable_limit:%d\n", vlock_pll_stable_limit);
        pr_info("vlock_enc_adj_limit:%d\n", vlock_enc_adj_limit);
+       pr_info("vlock_pll_stable_flag:%d\n", vlock_pll_stable_flag);
+       pr_info("vlock_enc_stable_flag:%d\n", vlock_enc_stable_flag);
+       pr_info("vlock_intput_type:%d\n", vlock_intput_type);
+       pr_info("vlock_pll_adj_limit:%d\n", vlock_pll_adj_limit);
+       pr_info("vlock_pll_val_last:%d\n", vlock_pll_val_last);
+       pr_info("vlock driver version :  %s\n", VLOCK_VER);
 }
 void vlock_reg_dump(void)
 {
@@ -1177,10 +1295,11 @@ void vlock_reg_dump(void)
 void vdin_vlock_input_sel(unsigned int type,
        enum vframe_source_type_e source_type)
 {
-       type = type & VIDTYPE_TYPEMASK;
-       if ((type == 0) || (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC))
+       vlock_intput_type = type & VIDTYPE_TYPEMASK;
+       if ((vlock_intput_type == 0) ||
+               (vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC))
                return;
-       if (type == VIDTYPE_INTERLACE_TOP) {
+       if (vlock_intput_type == VIDTYPE_INTERLACE_TOP) {
                if ((source_type == VFRAME_SOURCE_TYPE_TUNER) ||
                        (source_type == VFRAME_SOURCE_TYPE_CVBS))
                        /* Input Vsync source select from tv-decoder */
@@ -1192,5 +1311,50 @@ void vdin_vlock_input_sel(unsigned int type,
                WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 7, 16, 3);
 }
 EXPORT_SYMBOL(vdin_vlock_input_sel);
+
+void vlock_param_config(struct device_node *node)
+{
+#ifdef CONFIG_AMLOGIC_LCD
+       unsigned int param[LCD_VLOCK_PARAM_NUM] = {0};
+#endif
+       unsigned int val;
+       int ret;
+
+       ret = of_property_read_u32(node, "vlock_en", &val);
+       if (ret)
+               pr_info("Can't find  vlock_en.\n");
+       else
+               vlock_en = val;
+       ret = of_property_read_u32(node, "vlock_mode", &val);
+       if (ret)
+               pr_info("Can't find  vlock_mode.\n");
+       else
+               vlock_mode = val;
+       ret = of_property_read_u32(node, "vlock_pll_m_limit", &val);
+       if (ret)
+               pr_info("Can't find  vlock_pll_m_limit.\n");
+       else
+               vlock_pll_m_limit = val;
+       ret = of_property_read_u32(node, "vlock_line_limit", &val);
+       if (ret)
+               pr_info("Can't find  vlock_line_limit.\n");
+       else
+               vlock_line_limit = val;
+
+#ifdef CONFIG_AMLOGIC_LCD
+       aml_lcd_notifier_call_chain(LCD_EVENT_VLOCK_PARAM, &param);
+       if (param[0]) { /* lcd vlock param is valid */
+               vlock_en = param[1];
+               vlock_mode = param[2];
+               vlock_pll_m_limit = param[3];
+               vlock_line_limit = param[4];
+       }
+#endif
+
+       if (vlock_mode & VLOCK_MODE_MANUAL_MIX_PLL_ENC) {
+               vlock_mode &= ~VLOCK_MODE_MANUAL_MIX_PLL_ENC;
+               vlock_mode |= VLOCK_MODE_MANUAL_PLL;
+       }
+}
 /*video lock end*/
 
index d7bd385..68fa2b2 100644 (file)
 #ifndef __AM_VLOCK_H
 #define __AM_VLOCK_H
 
+#include <linux/device.h>
+#include <linux/of.h>
 #include <linux/amlogic/media/vfm/vframe.h>
 #include "linux/amlogic/media/amvecm/ve.h"
 
+#define VLOCK_VER "Ref.2018/09/04a"
+
 #define VLOCK_REG_NUM  33
 
 struct vlock_log_s {
@@ -43,6 +47,8 @@ enum vlock_param_e {
        VLOCK_MODE,
        VLOCK_DIS_CNT_LIMIT,
        VLOCK_DELTA_LIMIT,
+       VLOCK_PLL_M_LIMIT,
+       VLOCK_DELTA_CNT_LIMIT,
        VLOCK_DEBUG,
        VLOCK_DYNAMIC_ADJUST,
        VLOCK_STATE,
@@ -70,14 +76,19 @@ extern void vlock_log_print(void);
 #define VLOCK_STATE_ENABLE_FORCE_RESET 5
 
 /* video lock */
-#define VLOCK_MODE_AUTO_ENC 0
-#define VLOCK_MODE_AUTO_PLL 1
-#define VLOCK_MODE_MANUAL_PLL 2
-#define VLOCK_MODE_MANUAL_ENC 3
-#define VLOCK_MODE_MANUAL_SOFT_ENC 4
+#define VLOCK_MODE_AUTO_ENC (1 << 0)
+#define VLOCK_MODE_AUTO_PLL (1 << 1)
+#define VLOCK_MODE_MANUAL_PLL (1 << 2)
+#define VLOCK_MODE_MANUAL_ENC (1 << 3)
+#define VLOCK_MODE_MANUAL_SOFT_ENC (1 << 4)
+#define VLOCK_MODE_MANUAL_MIX_PLL_ENC (1 << 5)
 
 #define XTAL_VLOCK_CLOCK   24000000/*vlock use xtal clock*/
 
+#define VLOCK_PLL_STABLE_CNT   180/*vlock pll stabel cnt limit*/
+#define VLOCK_ENC_STABLE_CNT   180/*vlock enc stabel cnt limit*/
+#define VLOCK_PLL_ADJ_LIMIT 9/*vlock pll adj limit(0x300a default)*/
+
 /*vlock_debug mask*/
 #define VLOCK_DEBUG_INFO (1 << 0)
 #define VLOCK_DEBUG_FLUSH_REG_DIS (1 << 1)
@@ -99,5 +110,6 @@ extern int amvecm_hiu_reg_read(unsigned int reg, unsigned int *val);
 extern int amvecm_hiu_reg_write(unsigned int reg, unsigned int val);
 extern void vdin_vlock_input_sel(unsigned int type,
        enum vframe_source_type_e source_type);
+extern void vlock_param_config(struct device_node *node);
 #endif
 
index de27870..3a28c1c 100644 (file)
@@ -5051,6 +5051,10 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
        vsync_count++;
        timer_count++;
 
+#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
+       vlock_process(vf);/*need call every vsync*/
+#endif
+
        switch (READ_VCBUS_REG(VPU_VIU_VENC_MUX_CTRL) & 0x3) {
        case 0:
                enc_line = (READ_VCBUS_REG(ENCL_INFO_READ) >> 16) & 0x1fff;
@@ -5313,9 +5317,6 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
                /* determine the out frame is L or R or blank */
                judge_3d_fa_out_mode();
        }
-#if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
-       vlock_process(cur_dispbuf);
-#endif
        while (vf) {
                if (vpts_expire(cur_dispbuf, vf, toggle_cnt) || show_nosync) {
                        amlog_mask(LOG_MASK_TIMESTAMP,
index 91e80e2..454c328 100644 (file)
@@ -1661,6 +1661,7 @@ static void lcd_pll_frac_generate_gxtvbb(struct lcd_config_s *pconf)
 static int check_pll_txl(struct lcd_clk_config_s *cConf,
                unsigned int pll_fout)
 {
+       struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
        unsigned int m, n;
        unsigned int od1_sel, od2_sel, od3_sel, od1, od2, od3;
        unsigned int pll_fod2_in, pll_fod3_in, pll_fvco;
@@ -1697,7 +1698,15 @@ static int check_pll_txl(struct lcd_clk_config_s *cConf,
                                }
                                cConf->pll_fvco = pll_fvco;
                                n = 1;
-                               od_fb = cConf->od_fb;
+                               if (lcd_drv->data->chip_type == LCD_CHIP_TXL) {
+                                       if (pll_fvco < 3700000)
+                                               od_fb = 0;
+                                       else
+                                               od_fb = 1;
+                                       cConf->od_fb = od_fb;
+                               } else {
+                                       od_fb = cConf->od_fb;
+                               }
                                pll_fvco = pll_fvco / od_fb_table[od_fb];
                                m = pll_fvco / cConf->fin;
                                pll_frac = (pll_fvco % cConf->fin) *
@@ -1874,6 +1883,7 @@ static void lcd_pll_frac_generate_txl(struct lcd_config_s *pconf)
        od3 = od_table[cConf->pll_od3_sel];
        m = cConf->pll_m;
        n = cConf->pll_n;
+       od_fb = cConf->od_fb;
 
        if (lcd_debug_print_flag == 2) {
                LCDPR("m=%d, n=%d, od1=%d, od2=%d, od3=%d\n",
@@ -1925,7 +1935,6 @@ static void lcd_pll_frac_generate_txl(struct lcd_config_s *pconf)
                LCDPR("%s pll_fvco=%d\n", __func__, pll_fvco);
 
        cConf->pll_fvco = pll_fvco;
-       od_fb = cConf->od_fb; /* pll default */
        pll_fvco = pll_fvco / od_fb_table[od_fb];
        temp = cConf->fin * m / n;
        if (pll_fvco >= temp) {
index 8724af3..fb0b6bf 100644 (file)
@@ -242,8 +242,8 @@ enum div_sel_e {
 #define PLL_OD_SEL_MAX_TXL          3
 #define PLL_FREF_MIN_TXL            (5 * 1000)
 #define PLL_FREF_MAX_TXL            (25 * 1000)
-#define PLL_VCO_MIN_TXL             (3000 * 1000)
-#define PLL_VCO_MAX_TXL             (6000 * 1000)
+#define PLL_VCO_MIN_TXL             (2950 * 1000)
+#define PLL_VCO_MAX_TXL             (5900 * 1000)
 
 /* video */
 #define CLK_DIV_IN_MAX_TXL          (3100 * 1000)
index 54124b6..3f32095 100644 (file)
@@ -677,6 +677,50 @@ int lcd_power_load_from_unifykey(struct lcd_config_s *pconf,
        return 0;
 }
 
+int lcd_vlock_param_load_from_dts(struct lcd_config_s *pconf,
+               struct device_node *child)
+{
+       unsigned int para[4];
+       int ret;
+
+       ret = of_property_read_u32_array(child, "vlock_attr", &para[0], 4);
+       if (ret) {
+               pconf->lcd_control.vlock_param[0] = 0;
+       } else {
+               LCDPR("find vlock_attr\n");
+               pconf->lcd_control.vlock_param[0] = 1; /* vlock_param valid */
+               pconf->lcd_control.vlock_param[1] = para[0];
+               pconf->lcd_control.vlock_param[2] = para[1];
+               pconf->lcd_control.vlock_param[3] = para[2];
+               pconf->lcd_control.vlock_param[4] = para[3];
+       }
+
+       return 0;
+}
+
+int lcd_vlock_param_load_from_unifykey(struct lcd_config_s *pconf,
+               unsigned char *buf)
+{
+       unsigned char *p;
+
+       p = buf;
+
+       pconf->lcd_control.vlock_param[0] = 0;
+       pconf->lcd_control.vlock_param[1] = *(p + LCD_UKEY_VLOCK_VAL_0);
+       pconf->lcd_control.vlock_param[2] = *(p + LCD_UKEY_VLOCK_VAL_1);
+       pconf->lcd_control.vlock_param[3] = *(p + LCD_UKEY_VLOCK_VAL_2);
+       pconf->lcd_control.vlock_param[4] = *(p + LCD_UKEY_VLOCK_VAL_3);
+       if (pconf->lcd_control.vlock_param[1] ||
+               pconf->lcd_control.vlock_param[2] ||
+               pconf->lcd_control.vlock_param[3] ||
+               pconf->lcd_control.vlock_param[4]) {
+               LCDPR("find vlock_attr\n");
+               pconf->lcd_control.vlock_param[0] = 1;
+       }
+
+       return 0;
+}
+
 void lcd_optical_vinfo_update(void)
 {
        struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
index 20e343f..968b949 100644 (file)
@@ -91,6 +91,10 @@ extern int lcd_power_load_from_dts(struct lcd_config_s *pconf,
                struct device_node *child);
 extern int lcd_power_load_from_unifykey(struct lcd_config_s *pconf,
                unsigned char *buf, int key_len, int len);
+extern int lcd_vlock_param_load_from_dts(struct lcd_config_s *pconf,
+               struct device_node *child);
+extern int lcd_vlock_param_load_from_unifykey(struct lcd_config_s *pconf,
+               unsigned char *buf);
 
 extern void lcd_optical_vinfo_update(void);
 extern void lcd_timing_init_config(struct lcd_config_s *pconf);
index e123ec7..2f29580 100644 (file)
@@ -2253,6 +2253,26 @@ static ssize_t lcd_debug_dither_store(struct class *class,
        return count;
 }
 
+static ssize_t lcd_debug_vlock_show(struct class *class,
+               struct class_attribute *attr, char *buf)
+{
+       struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
+       ssize_t len = 0;
+
+       len = sprintf(buf, "custome vlock attr:\n"
+               "vlock_valid:        %d\n"
+               "vlock_en:           %d\n"
+               "vlock_work_mode:    %d\n"
+               "vlock_pll_m_limit:  %d\n"
+               "vlock_line_limit:   %d\n",
+               lcd_drv->lcd_config->lcd_control.vlock_param[0],
+               lcd_drv->lcd_config->lcd_control.vlock_param[1],
+               lcd_drv->lcd_config->lcd_control.vlock_param[2],
+               lcd_drv->lcd_config->lcd_control.vlock_param[3],
+               lcd_drv->lcd_config->lcd_control.vlock_param[4]);
+
+       return len;
+}
 
 #define LCD_DEBUG_DUMP_INFO         0
 #define LCD_DEBUG_DUMP_REG          1
@@ -2364,6 +2384,7 @@ static struct class_attribute lcd_debug_class_attrs[] = {
        __ATTR(reg,         0200, NULL, lcd_debug_reg_store),
        __ATTR(dither,      0644,
                lcd_debug_dither_show, lcd_debug_dither_store),
+       __ATTR(vlock,       0644, lcd_debug_vlock_show, NULL),
        __ATTR(dump,        0644,
                lcd_debug_dump_show, lcd_debug_dump_store),
        __ATTR(print,       0644, lcd_debug_print_show, lcd_debug_print_store),
index 221db17..856faa5 100644 (file)
@@ -892,6 +892,7 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf,
                break;
        }
 
+       lcd_vlock_param_load_from_dts(pconf, child);
        ret = lcd_power_load_from_dts(pconf, child);
 
        return ret;
@@ -1148,6 +1149,8 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf)
                }
        }
 
+       lcd_vlock_param_load_from_unifykey(pconf, para);
+
        /* step 3: check power sequence */
        ret = lcd_power_load_from_unifykey(pconf, para, key_len, len);
        if (ret < 0) {
index ef11430..f2e2ab6 100644 (file)
@@ -1014,6 +1014,7 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf,
                break;
        }
 
+       lcd_vlock_param_load_from_dts(pconf, child);
        ret = lcd_power_load_from_dts(pconf, child);
 
        return ret;
@@ -1235,6 +1236,8 @@ static int lcd_config_load_from_unifykey(struct lcd_config_s *pconf)
                }
        }
 
+       lcd_vlock_param_load_from_unifykey(pconf, para);
+
        /* step 3: check power sequence */
        ret = lcd_power_load_from_unifykey(pconf, para, key_len, len);
        if (ret < 0) {
index 30fc031..e726f0e 100644 (file)
@@ -164,6 +164,9 @@ static struct lcd_power_ctrl_s lcd_power_config = {
        },
 };
 
+/* index 0: valid flag */
+static unsigned int vlock_param[LCD_VLOCK_PARAM_NUM] = {0};
+
 static struct lcd_config_s lcd_config_dft = {
        .lcd_propname = lcd_propname,
        .lcd_basic = {
@@ -195,6 +198,7 @@ static struct lcd_config_s lcd_config_dft = {
                .lvds_config = &lcd_lvds_config,
                .vbyone_config = &lcd_vbyone_config,
                .mipi_config = &lcd_mipi_config,
+               .vlock_param = vlock_param,
        },
        .lcd_power = &lcd_power_config,
        .pinmux_flag = 0xff,
@@ -694,6 +698,26 @@ static struct notifier_block lcd_extern_select_nb = {
        .notifier_call = lcd_extern_select_notifier,
 };
 
+static int lcd_vlock_param_notifier(struct notifier_block *nb,
+               unsigned long event, void *data)
+{
+       unsigned int *param;
+
+       if ((event & LCD_EVENT_VLOCK_PARAM) == 0)
+               return NOTIFY_DONE;
+       /* LCDPR("%s: 0x%lx\n", __func__, event); */
+
+       param = (unsigned int *)data;
+       memcpy(param, vlock_param,
+               (LCD_VLOCK_PARAM_NUM * sizeof(unsigned int)));
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block lcd_vlock_param_nb = {
+       .notifier_call = lcd_vlock_param_notifier,
+};
+
 static int lcd_notifier_register(void)
 {
        int ret = 0;
@@ -723,6 +747,9 @@ static int lcd_notifier_register(void)
        ret = aml_lcd_notifier_register(&lcd_extern_select_nb);
        if (ret)
                LCDERR("register lcd_extern_select_nb failed\n");
+       ret = aml_lcd_notifier_register(&lcd_vlock_param_nb);
+       if (ret)
+               LCDERR("register lcd_vlock_param_nb failed\n");
 
        return 0;
 }
@@ -738,6 +765,7 @@ static void lcd_notifier_unregister(void)
 
        aml_lcd_notifier_unregister(&lcd_bl_select_nb);
        aml_lcd_notifier_unregister(&lcd_extern_select_nb);
+       aml_lcd_notifier_unregister(&lcd_vlock_param_nb);
 }
 /* **************************************** */
 
index 00b7f76..2d6e55b 100644 (file)
@@ -75,6 +75,9 @@
 /* lcd bist pattern test occurred */
 #define LCD_EVENT_TEST_PATTERN      (1 << 14)
 
+#define LCD_VLOCK_PARAM_NUM         5
+#define LCD_EVENT_VLOCK_PARAM       (1 << 16)
+
 
 extern int aml_lcd_notifier_register(struct notifier_block *nb);
 extern int aml_lcd_notifier_unregister(struct notifier_block *nb);
index 5e38698..70e2efb 100644 (file)
@@ -90,7 +90,10 @@ struct aml_lcd_unifykey_header_s {
 #define LCD_UKEY_V_PERIOD_MAX    (LCD_UKEY_MODEL_NAME + 67)
 #define LCD_UKEY_PCLK_MIN        (LCD_UKEY_MODEL_NAME + 69)
 #define LCD_UKEY_PCLK_MAX        (LCD_UKEY_MODEL_NAME + 73)
-#define LCD_UKEY_CUST_VAL_8      (LCD_UKEY_MODEL_NAME + 77)
+#define LCD_UKEY_VLOCK_VAL_0     (LCD_UKEY_MODEL_NAME + 77)
+#define LCD_UKEY_VLOCK_VAL_1     (LCD_UKEY_MODEL_NAME + 78)
+#define LCD_UKEY_VLOCK_VAL_2     (LCD_UKEY_MODEL_NAME + 79)
+#define LCD_UKEY_VLOCK_VAL_3     (LCD_UKEY_MODEL_NAME + 80)
 #define LCD_UKEY_CUST_VAL_9      (LCD_UKEY_MODEL_NAME + 81)
 /* interface (20Byte) */
 #define LCD_UKEY_IF_ATTR_0       (LCD_UKEY_MODEL_NAME + 85)/* +36+18+31 byte */
@@ -136,6 +139,7 @@ struct aml_lcd_unifykey_header_s {
 #define LCD_UKEY_PHY_ATTR_7     (LCD_UKEY_MODEL_NAME + 156)
 #define LCD_UKEY_PHY_ATTR_8     (LCD_UKEY_MODEL_NAME + 157)
 #define LCD_UKEY_PHY_ATTR_9     (LCD_UKEY_MODEL_NAME + 158)
+
 #define LCD_UKEY_DATA_LEN_V1        (LCD_UKEY_MODEL_NAME + 105)
 #define LCD_UKEY_DATA_LEN_V2        (LCD_UKEY_MODEL_NAME + 159)
 /* power (5Byte * n) */
index 79bc5d8..7348da4 100644 (file)
@@ -321,6 +321,7 @@ struct lcd_control_config_s {
        struct lvds_config_s *lvds_config;
        struct vbyone_config_s *vbyone_config;
        struct dsi_config_s *mipi_config;
+       unsigned int *vlock_param;
 };
 
 /* **********************************