diff --git a/MAINTAINERS b/MAINTAINERS index 92ed2d4adb7d..88582bb40033 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14464,3 +14464,9 @@ M: xing wang F: arch/arm64/boot/dts/amlogic/g12a_* F: include/linux/amlogic/media/sound/spdif_info.h F: sound/soc/amlogic/auge* + +AMLOGIC TVIN vlock +M: Wenfeng Guo +F: drivers/amlogic/media/enhancement/amvecm/vlock.c +F: drivers/amlogic/media/enhancement/amvecm/vlock.h + diff --git a/drivers/amlogic/media/enhancement/amvecm/Makefile b/drivers/amlogic/media/enhancement/amvecm/Makefile index a24b8a38a1b8..85d4a90ef5ec 100644 --- a/drivers/amlogic/media/enhancement/amvecm/Makefile +++ b/drivers/amlogic/media/enhancement/amvecm/Makefile @@ -3,5 +3,5 @@ # obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) += am_vecm.o -am_vecm-objs := amve.o amcm.o amcsc.o amvecm.o keystone_correction.o bitdepth.o set_hdr2_v0.o dnlp_cal.o +am_vecm-objs := amve.o amcm.o amcsc.o amvecm.o keystone_correction.o bitdepth.o set_hdr2_v0.o dnlp_cal.o vlock.o diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.c b/drivers/amlogic/media/enhancement/amvecm/amve.c index d4b9f3c218e8..a8d4507db123 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.c +++ b/drivers/amlogic/media/enhancement/amvecm/amve.c @@ -33,7 +33,6 @@ #include "arch/ve_regs.h" #include "amve.h" #include "amve_gamma_table.h" -#include "amvecm_vlock_regmap.h" #include #include "dnlp_cal.h" @@ -91,30 +90,6 @@ struct tcon_rgb_ogo_s video_rgb_ogo = { #define FLAG_LVDS_FREQ_SW1 (1 << 6) - -int amvecm_hiu_reg_read(unsigned int reg, unsigned int *val) -{ - *val = readl(amvecm_hiu_reg_base+((reg - 0x1000)<<2)); - return 0; -} - -int amvecm_hiu_reg_write(unsigned int reg, unsigned int val) -{ - writel(val, (amvecm_hiu_reg_base+((reg - 0x1000)<<2))); - return 0; -} -static int amvecm_hiu_reg_write_bits(unsigned int reg, unsigned int value, - unsigned int start, unsigned int len) -{ - unsigned int rd_val; - - amvecm_hiu_reg_read(reg, &rd_val); - amvecm_hiu_reg_write(reg, ((rd_val & - ~(((1L << (len)) - 1) << (start))) | - (((value) & ((1L << (len)) - 1)) << (start)))); - return 0; -} - int dnlp_en;/* 0:disabel;1:enable */ module_param(dnlp_en, int, 0664); MODULE_PARM_DESC(dnlp_en, "\n enable or disable dnlp\n"); @@ -142,67 +117,6 @@ int video_rgb_ogo_xvy_mtx_latch; static unsigned int assist_cnt;/* ASSIST_SPARE8_REG1; */ -/* video lock */ -/* 0:enc;1:pll;2:manual pll */ -unsigned int vlock_mode = VLOCK_MODE_MANUAL_PLL; -unsigned int vlock_en = 1; - -/*0:only support 50->50;60->60;24->24;30->30;*/ -/*1:support 24/30/50/60/100/120 mix,such as 50->60;*/ -static unsigned int vlock_adapt; -static unsigned int vlock_dis_cnt_limit = 2; -static unsigned int vlock_delta_limit = 2; -/*vlock_debug:bit0:disable info;bit1:format change info;bit2:force reset*/ -static unsigned int vlock_debug; -static unsigned int vlock_dynamic_adjust = 1; - -static unsigned int vlock_sync_limit_flag; -static unsigned int vlock_state = VLOCK_STATE_NULL;/*1/2/3:vlock step*/ -static enum vmode_e pre_vmode = VMODE_INIT_NULL; -static enum vframe_source_type_e pre_source_type = - VFRAME_SOURCE_TYPE_OTHERS; -static enum vframe_source_mode_e pre_source_mode = - VFRAME_SOURCE_MODE_OTHERS; -static unsigned int pre_input_freq; -static unsigned int pre_output_freq; -static unsigned int vlock_dis_cnt; -static char pre_vout_mode[64]; -static bool vlock_vmode_changed; -static unsigned int pre_hiu_reg_m; -static unsigned int pre_hiu_reg_frac; -static unsigned int vlock_dis_cnt_no_vf; -static unsigned int vlock_dis_cnt_no_vf_limit = 5; - -static unsigned int vlock_log_cnt;/*cnt base: vlock_log_s*/ -static unsigned int vlock_log_size = 60;/*size base: vlock_log_s*/ -static unsigned int vlock_log_delta_frac = 100; -static unsigned int vlock_log_delta_ivcnt = 0xff; -static unsigned int vlock_log_delta_ovcnt = 0xff; -static unsigned int vlock_log_delta_vcnt = 0xff; -static unsigned int vlock_log_last_ivcnt; -static unsigned int vlock_log_last_ovcnt; -static unsigned int vlock_log_delta_m; -static unsigned int vlock_log_delta_en; -module_param(vlock_log_size, uint, 0664); -MODULE_PARM_DESC(vlock_log_size, "\n vlock_log_size\n"); -module_param(vlock_log_cnt, uint, 0664); -MODULE_PARM_DESC(vlock_log_cnt, "\n vlock_log_cnt\n"); -module_param(vlock_log_delta_frac, uint, 0664); -MODULE_PARM_DESC(vlock_log_delta_frac, "\n vlock_log_delta_frac\n"); -module_param(vlock_log_delta_m, uint, 0664); -MODULE_PARM_DESC(vlock_log_delta_m, "\n vlock_log_delta_m\n"); -module_param(vlock_log_delta_en, uint, 0664); -MODULE_PARM_DESC(vlock_log_delta_en, "\n vlock_log_delta_en\n"); - -module_param(vlock_log_delta_ivcnt, uint, 0664); -MODULE_PARM_DESC(vlock_log_delta_ivcnt, "\n vlock_log_delta_ivcnt\n"); - -module_param(vlock_log_delta_ovcnt, uint, 0664); -MODULE_PARM_DESC(vlock_log_delta_ovcnt, "\n vlock_log_delta_ovcnt\n"); - -module_param(vlock_log_delta_vcnt, uint, 0664); -MODULE_PARM_DESC(vlock_log_delta_vcnt, "\n vlock_log_delta_vcnt\n"); -static unsigned int vlock_log_en; /* 3d sync parts begin */ unsigned int sync_3d_h_start; unsigned int sync_3d_h_end; @@ -1070,610 +984,6 @@ void ve_ogo_param_update(void) vecm_latch_flag |= FLAG_RGB_OGO; } -static unsigned int vlock_check_input_hz(struct vframe_s *vf) -{ - unsigned int ret_hz = 0; - unsigned int duration = vf->duration; - - if ((vf->source_type != VFRAME_SOURCE_TYPE_CVBS) && - (vf->source_type != VFRAME_SOURCE_TYPE_HDMI)) - ret_hz = 0; - else if (vf->source_type == VFRAME_SOURCE_TYPE_HDMI) { - if (duration != 0) - ret_hz = (96000 + duration/2)/duration; - } else if (vf->source_type == VFRAME_SOURCE_TYPE_CVBS) { - if (vf->source_mode == VFRAME_SOURCE_MODE_NTSC) - ret_hz = 60; - else if ((vf->source_mode == VFRAME_SOURCE_MODE_PAL) || - (vf->source_mode == VFRAME_SOURCE_MODE_SECAM)) - ret_hz = 50; - else - ret_hz = 0; - } - return ret_hz; -} - -static unsigned int vlock_check_output_hz(unsigned int sync_duration_num) -{ - unsigned int ret_hz = 0; - - switch (sync_duration_num) { - case 24: - ret_hz = 24; - break; - case 30: - ret_hz = 30; - break; - case 50: - ret_hz = 50; - break; - case 60: - ret_hz = 60; - break; - case 100: - ret_hz = 100; - break; - case 120: - ret_hz = 120; - break; - default: - ret_hz = 0; - break; - } - return ret_hz; -} -static void vlock_enable(bool enable) -{ - unsigned int tmp_value; - - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value); - if (is_meson_gxtvbb_cpu()) { - if (vlock_mode == VLOCK_MODE_MANUAL_PLL) { - amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 0, 20, 1); - if (is_meson_gxtvbb_cpu() && - (((tmp_value >> 21) & 0x3) != 2)) - amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, - 2, 21, 2); - } else - 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) - amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL5, 0, 3, 1); - else - amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL5, - enable, 3, 1); - } -} -static void vlock_setting(struct vframe_s *vf, - unsigned int input_hz, unsigned int output_hz) -{ - unsigned int freq_hz = 0, hiu_reg_value_2_addr = HHI_HDMI_PLL_CNTL2; - unsigned int reg_value = 0, hiu_reg_value, hiu_reg_value_2; - unsigned int hiu_m_val, hiu_frac_val; - - amvecm_hiu_reg_write(HHI_VID_LOCK_CLK_CNTL, 0x80); - if (vlock_mode == VLOCK_MODE_ENC) { - am_set_regmap(&vlock_enc_lcd720x480); - /* VLOCK_CNTL_EN disable */ - vlock_enable(0); - /* disable to adjust pll */ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 29, 1); - /* CFG_VID_LOCK_ADJ_EN enable */ - WRITE_VPP_REG_BITS(ENCL_MAX_LINE_SWITCH_POINT, 1, 13, 1); - /* enable to adjust pll */ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 30, 1); - /*clear accum1 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); - /*clear accum0 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); - } - if ((vlock_mode == VLOCK_MODE_AUTO_PLL) || - (vlock_mode == VLOCK_MODE_MANUAL_PLL)) { - /* av pal in,1080p60 hdmi out as default */ - if ((vlock_debug & 0x1000) == 0) - am_set_regmap(&vlock_pll_in50hz_out60hz); - /*set input & output freq*/ - /*bit0~7:input freq*/ - /*bit8~15:output freq*/ - freq_hz = input_hz | (output_hz << 8); - WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, freq_hz, 0, 16); - /*Ifrm_cnt_mod:0x3001(bit23~16);*/ - /*(output_freq/input_freq)*Ifrm_cnt_mod must be integer*/ - if (vlock_adapt == 0) - WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, 1, 16, 8); - else - WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, - input_hz, 16, 8); - /*set PLL M_INT;PLL M_frac*/ - /* WRITE_VPP_REG_BITS(VPU_VLOCK_MX4096, */ - /* READ_CBUS_REG_BITS(HHI_HDMI_PLL_CNTL,0,9),12,9); */ - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &hiu_reg_value); - amvecm_hiu_reg_read(hiu_reg_value_2_addr, - &hiu_reg_value_2); - if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { - hiu_m_val = hiu_reg_value & 0x1FF; - hiu_frac_val = hiu_reg_value_2 & 0x3FF; - if (hiu_reg_value_2 & 0x800) { - hiu_m_val -= 1; - if (hiu_reg_value_2 & 0x400) - hiu_m_val -= 1; - hiu_frac_val = 0x400 - - ((~(hiu_frac_val - 1)) & 0x3ff); - } else if (hiu_reg_value_2 & 0x400) { - hiu_m_val += 1; - } - reg_value = (hiu_m_val << 12) - + (hiu_frac_val << 2); - } - WRITE_VPP_REG_BITS(VPU_VLOCK_MX4096, reg_value, 0, 21); - - /* vlock module output goes to which module */ - switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, 0, 2)) { - case 0:/* ENCL */ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 26, 2); - break; - case 1:/* ENCI */ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 2, 26, 2); - break; - case 2: /* ENCP */ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 26, 2); - break; - default: - break; - } - /*enable vlock to adj pll*/ - /* CFG_VID_LOCK_ADJ_EN disable */ - WRITE_VPP_REG_BITS(ENCL_MAX_LINE_SWITCH_POINT, 0, 13, 1); - /* disable to adjust pll */ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 30, 1); - /* VLOCK_CNTL_EN enable */ - vlock_enable(1); - /* enable to adjust pll */ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 29, 1); - } - if ((vf->source_type == VFRAME_SOURCE_TYPE_TUNER) || - (vf->source_type == VFRAME_SOURCE_TYPE_CVBS)) - /* Input Vsync source select from tv-decoder */ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 2, 16, 3); - else if (vf->source_type == VFRAME_SOURCE_TYPE_HDMI) - /* Input Vsync source select from hdmi-rx */ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 16, 3); - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 31, 1); -} -void vlock_vmode_check(void) -{ - const struct vinfo_s *vinfo; - unsigned int tmp_value, hiu_reg_addr; - char cur_vout_mode[64]; - - if (vlock_en == 0) - return; - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) - hiu_reg_addr = HHI_HDMI_PLL_CNTL1; - else - hiu_reg_addr = HHI_HDMI_PLL_CNTL2; - - vinfo = get_current_vinfo(); - vlock_vmode_changed = 0; - memset(cur_vout_mode, 0, sizeof(cur_vout_mode)); - strcpy(cur_vout_mode, vinfo->name); - if (strcmp(cur_vout_mode, pre_vout_mode) != 0) { - 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_debug & 0x10) - pr_info("[%s]:vout mode changed:%s==>%s\n", - __func__, pre_vout_mode, cur_vout_mode); - memset(pre_vout_mode, 0, sizeof(pre_vout_mode)); - strcpy(pre_vout_mode, cur_vout_mode); - vlock_vmode_changed = 1; - } -} -static void vlock_disable_step1(void) -{ - unsigned int m_reg_value, tmp_value; - unsigned int hiu_reg_addr; - - /* VLOCK_CNTL_EN disable */ - vlock_enable(0); - vlock_vmode_check(); - 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_m != 0)) { - tmp_value = (tmp_value & 0xfffff000) | - (pre_hiu_reg_frac & 0xfff); - amvecm_hiu_reg_write(hiu_reg_addr, tmp_value); - } - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &tmp_value); - m_reg_value = tmp_value & 0x1ff; - if ((m_reg_value != pre_hiu_reg_m) && - (pre_hiu_reg_m != 0)) { - tmp_value = (tmp_value & 0xfffffe00) | - (pre_hiu_reg_m & 0x1ff); - amvecm_hiu_reg_write(HHI_HDMI_PLL_CNTL, tmp_value); - } - vlock_dis_cnt = vlock_dis_cnt_limit; - memset(pre_vout_mode, 0, sizeof(pre_vout_mode)); - pre_vmode = VMODE_INIT_NULL; - pre_source_type = VFRAME_SOURCE_TYPE_OTHERS; - pre_source_mode = VFRAME_SOURCE_MODE_OTHERS; - pre_input_freq = 0; - pre_output_freq = 0; - vlock_state = VLOCK_STATE_DISABLE_STEP1_DONE; -} - -static void vlock_disable_step2(void) -{ - unsigned int temp_val; - /* need delay to disable follow regs(vlsi suggest!!!) */ - if (vlock_dis_cnt > 0) - vlock_dis_cnt--; - if (vlock_dis_cnt == 0) { - /* disable to adjust pll */ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 29, 1); - /* CFG_VID_LOCK_ADJ_EN disable */ - WRITE_VPP_REG_BITS(ENCL_MAX_LINE_SWITCH_POINT, - 0, 13, 1); - /* disable to adjust pll */ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 30, 1); - /* disable vid_lock_en */ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 31, 1); - vlock_state = VLOCK_STATE_DISABLE_STEP2_DONE; - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &temp_val); - if (is_meson_gxtvbb_cpu() && (((temp_val >> 21) & 0x3) != 0)) - amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 0, 21, 2); - } -} -static void vlock_enable_step1(struct vframe_s *vf, struct vinfo_s *vinfo, - unsigned int input_hz, unsigned int output_hz) -{ - vlock_setting(vf, input_hz, output_hz); - if (vlock_debug & 0x10) { - pr_info("%s:vmode/source_type/source_mode/input_freq/output_freq:\n", - __func__); - pr_info("\t%d/%d/%d/%d/%d=>%d/%d/%d/%d/%d\n", - pre_vmode, pre_source_type, pre_source_mode, - pre_input_freq, pre_output_freq, - vinfo->mode, vf->source_type, vf->source_mode, - input_hz, output_hz); - } - pre_vmode = vinfo->mode; - pre_source_type = vf->source_type; - pre_source_mode = vf->source_mode; - pre_input_freq = input_hz; - pre_output_freq = output_hz; - vlock_sync_limit_flag = 0; - vlock_vmode_changed = 0; - vlock_dis_cnt = 0; - vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE; - vlock_log_cnt = 0; -} -#define VLOCK_REG_NUM 33 -struct vlock_log_s { - unsigned int pll_m; - unsigned int pll_frac; - unsigned int vlock_regs[VLOCK_REG_NUM]; -}; -struct vlock_log_s *vlock_log; - -void vlock_log_start(void) -{ - unsigned int size_mem; - - size_mem = vlock_log_size * sizeof(struct vlock_log_s); - vlock_log = kzalloc(size_mem, GFP_KERNEL); - - if (vlock_log == NULL) { - kfree(vlock_log); - return; - } - - vlock_log_en = 1; - pr_info("%s done\n", __func__); -} -void vlock_log_stop(void) -{ - if (vlock_log != NULL) - kfree(vlock_log); - vlock_log_en = 0; - pr_info("%s done\n", __func__); -} -void vlock_log_print(void) -{ - unsigned int i, j; - - for (i = 0; i < vlock_log_size; i++) { - pr_info("\n*******[%d]pll_m:0x%x,pll_frac:0x%x*******\n", - i, vlock_log[i].pll_m, vlock_log[i].pll_frac); - for (j = 0; j < VLOCK_REG_NUM;) { - if ((j%8 == 0) && ((j + 7) < VLOCK_REG_NUM)) { - pr_info("0x%08x\t0x%08x\t0x%08x\t0x%08x\t0x%08x\t0x%08x\t0x%08x\t0x%08x\n", - vlock_log[i].vlock_regs[j], - vlock_log[i].vlock_regs[j+1], - vlock_log[i].vlock_regs[j+2], - vlock_log[i].vlock_regs[j+3], - vlock_log[i].vlock_regs[j+4], - vlock_log[i].vlock_regs[j+5], - vlock_log[i].vlock_regs[j+6], - vlock_log[i].vlock_regs[j+7]); - j += 8; - } else { - pr_info("0x%08x\t", - vlock_log[i].vlock_regs[j]); - j++; - } - - } - } - pr_info("%s done\n", __func__); -} - -static void vlock_enable_step3(void) -{ - unsigned int m_reg_value, tmp_value, abs_val; - unsigned int hiu_reg_addr, i; - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) - hiu_reg_addr = HHI_HDMI_PLL_CNTL1; - else - hiu_reg_addr = HHI_HDMI_PLL_CNTL2; - - /*vs_i*/ - tmp_value = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); - abs_val = abs(vlock_log_last_ivcnt - tmp_value); - if ((abs_val > vlock_log_delta_ivcnt) && - (vlock_log_delta_en & (1 << 0))) - pr_info("%s: abs_ivcnt over 0x%x:0x%x(last:0x%x,cur:0x%x)\n", - __func__, vlock_log_delta_ivcnt, - abs_val, vlock_log_last_ivcnt, tmp_value); - vlock_log_last_ivcnt = tmp_value; - /*vs_o*/ - tmp_value = READ_VPP_REG(VPU_VLOCK_RO_VS_O_DIST); - abs_val = abs(vlock_log_last_ovcnt - tmp_value); - if ((abs_val > vlock_log_delta_ovcnt) && - (vlock_log_delta_en & (1 << 1))) - pr_info("%s: abs_ovcnt over 0x%x:0x%x(last:0x%x,cur:0x%x)\n", - __func__, vlock_log_delta_ovcnt, - abs_val, vlock_log_last_ivcnt, tmp_value); - vlock_log_last_ovcnt = tmp_value; - /*delta_vs*/ - abs_val = abs(vlock_log_last_ovcnt - vlock_log_last_ivcnt); - if ((abs_val > vlock_log_delta_vcnt) && (vlock_log_delta_en & (1 << 2))) - pr_info("%s: abs_vcnt over 0x%x:0x%x(ivcnt:0x%x,ovcnt:0x%x)\n", - __func__, vlock_log_delta_vcnt, - abs_val, vlock_log_last_ivcnt, vlock_log_last_ovcnt); - - 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; - for (i = 0; i < VLOCK_REG_NUM; i++) - vlock_log[vlock_log_cnt].vlock_regs[i] = - READ_VPP_REG(0x3000 + i); - vlock_log_cnt++; - } - if (m_reg_value == 0) { - vlock_state = VLOCK_STATE_ENABLE_FORCE_RESET; - if (vlock_debug & 0x100) - pr_info("%s:vlock work abnormal! force reset vlock\n", - __func__); - return; - } - /*vlsi suggest config:don't enable load signal,*/ - /*on gxtvbb this load signal will effect SSG,*/ - /*which may result in flashes black*/ - 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); - /*frac*/ - amvecm_hiu_reg_read(hiu_reg_addr, &tmp_value); - abs_val = abs(((m_reg_value & 0xfff) >> 2) - (tmp_value & 0xfff)); - if ((abs_val > vlock_log_delta_frac) && - (vlock_log_delta_en & (1 << 3))) - 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) { - tmp_value = (tmp_value & 0xfffff000) | - ((m_reg_value & 0xfff) >> 2); - amvecm_hiu_reg_write(hiu_reg_addr, tmp_value); - } - /*m*/ - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &tmp_value); - abs_val = abs(((m_reg_value >> 16) & 0x1ff) - (tmp_value & 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)) { - tmp_value = (tmp_value & 0xfffffe00) | - ((m_reg_value >> 16) & 0x1ff); - amvecm_hiu_reg_write(HHI_HDMI_PLL_CNTL, tmp_value); - } -} -/* won't change this function internal seqence,*/ -/* if really need change,please be carefull */ -void amve_vlock_process(struct vframe_s *vf) -{ - struct vinfo_s *vinfo; - unsigned int input_hz, output_hz, input_vs_cnt; - - if (vecm_latch_flag & FLAG_VLOCK_DIS) { - vlock_disable_step1(); - vlock_en = 0; - vecm_latch_flag &= ~FLAG_VLOCK_DIS; - if (vlock_debug & 0x1) - pr_info("[%s]disable vlock module!!!\n", __func__); - return; - } - vinfo = get_current_vinfo(); - input_hz = vlock_check_input_hz(vf); - output_hz = vlock_check_output_hz(vinfo->sync_duration_num); - vlock_dis_cnt_no_vf = 0; - if (vecm_latch_flag & FLAG_VLOCK_EN) { - vlock_enable_step1(vf, vinfo, input_hz, output_hz); - vlock_en = 1; - vecm_latch_flag &= ~FLAG_VLOCK_EN; - } - if (vlock_state == VLOCK_STATE_DISABLE_STEP1_DONE) { - vlock_disable_step2(); - return; - } - if (vlock_en == 1) { - if (((input_hz != output_hz) && (vlock_adapt == 0)) || - (input_hz == 0) || (output_hz == 0) || - (((vf->type_original & VIDTYPE_TYPEMASK) - != VIDTYPE_PROGRESSIVE) && - is_meson_txlx_package_962E())) { - if ((vlock_state != VLOCK_STATE_DISABLE_STEP2_DONE) && - (vlock_state != VLOCK_STATE_NULL)) - vlock_disable_step1(); - if (vlock_debug & 0x1) - pr_info("[%s]auto disable vlock module for no support case!!!\n", - __func__); - return; - } - vlock_vmode_check(); - if ((vinfo->mode != pre_vmode) || - (vf->source_type != pre_source_type) || - (vf->source_mode != pre_source_mode) || - (input_hz != pre_input_freq) || - (output_hz != pre_output_freq) || - vlock_vmode_changed || - (vlock_state == VLOCK_STATE_ENABLE_FORCE_RESET)) - vlock_enable_step1(vf, vinfo, input_hz, output_hz); - if ((vlock_sync_limit_flag < 10) && - (vlock_state >= VLOCK_STATE_ENABLE_STEP1_DONE)) - vlock_sync_limit_flag++; - if ((vlock_sync_limit_flag == 5) && - (vlock_state == VLOCK_STATE_ENABLE_STEP1_DONE)) { - /*input_vs_cnt =*/ - /*READ_VPP_REG_BITS(VPU_VLOCK_RO_VS_I_DIST,*/ - /* 0, 28);*/ - input_vs_cnt = XTAL_VLOCK_CLOCK/input_hz; - WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MAX, - input_vs_cnt*125/100); - WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MIN, - input_vs_cnt*70/100); - /*cal accum1 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); - /*cal accum0 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); - vlock_state = VLOCK_STATE_ENABLE_STEP2_DONE; - } else if (vlock_dynamic_adjust && - (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_enable_step3(); - } - } -} - -void amve_vlock_resume(void) -{ - if ((vlock_en == 0) || (vlock_state == - VLOCK_STATE_DISABLE_STEP2_DONE) || - (vlock_state == VLOCK_STATE_NULL)) - return; - if (vlock_state == VLOCK_STATE_DISABLE_STEP1_DONE) { - vlock_disable_step2(); - return; - } - vlock_dis_cnt_no_vf++; - if ((vlock_state != VLOCK_STATE_DISABLE_STEP2_DONE) && - (vlock_dis_cnt_no_vf > vlock_dis_cnt_no_vf_limit)) { - vlock_disable_step1(); - vlock_dis_cnt_no_vf = 0; - if (vlock_debug & 0x1) - pr_info("[%s]auto disable vlock module for no vframe & run disable step1.!!!\n", - __func__); - } - if (vlock_debug & 0x1) - pr_info("[%s]auto disable vlock module for no vframe!!!\n", - __func__); - if (vlock_dynamic_adjust && - (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_enable_step3(); -} - -void vlock_param_set(unsigned int val, enum vlock_param_e sel) -{ - switch (sel) { - case VLOCK_EN: - vlock_en = val; - break; - case VLOCK_ADAPT: - vlock_adapt = val; - break; - case VLOCK_MODE: - vlock_mode = val; - break; - case VLOCK_DIS_CNT_LIMIT: - vlock_dis_cnt_limit = val; - break; - case VLOCK_DELTA_LIMIT: - vlock_delta_limit = val; - break; - case VLOCK_DEBUG: - vlock_debug = val; - break; - case VLOCK_DYNAMIC_ADJUST: - vlock_dynamic_adjust = val; - break; - case VLOCK_DIS_CNT_NO_VF_LIMIT: - vlock_dis_cnt_no_vf_limit = val; - break; - default: - pr_info("%s:unknown vlock param:%d\n", __func__, sel); - break; - } - -} -void vlock_status(void) -{ - pr_info("\n current vlock parameters status:\n"); - pr_info("vlock_mode:%d\n", vlock_mode); - pr_info("vlock_en:%d\n", vlock_en); - 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_debug:0x%x\n", vlock_debug); - pr_info("vlock_dynamic_adjust:%d\n", vlock_dynamic_adjust); - pr_info("vlock_state:%d\n", vlock_state); - pr_info("vlock_sync_limit_flag:%d\n", vlock_sync_limit_flag); - pr_info("pre_vmode:%d\n", pre_vmode); - pr_info("pre_hiu_reg_m:0x%x\n", pre_hiu_reg_m); - pr_info("pre_hiu_reg_frac:0x%x\n", pre_hiu_reg_frac); - pr_info("vlock_dis_cnt:%d\n", vlock_dis_cnt); - pr_info("pre_vout_mode:%s\n", pre_vout_mode); - pr_info("vlock_dis_cnt_no_vf:%d\n", vlock_dis_cnt_no_vf); - pr_info("vlock_dis_cnt_no_vf_limit:%d\n", vlock_dis_cnt_no_vf_limit); -} -void vlock_reg_dump(void) -{ - unsigned int addr; - - pr_info("----dump vlock reg----\n"); - for (addr = (0x3000); addr <= (0x3020); addr++) - pr_info("[0x%x]vcbus[0x%04x]=0x%08x\n", - (0xd0100000+(addr<<2)), addr, - READ_VPP_REG(addr)); -} -/*video lock end*/ - /* sharpness process begin */ void sharpness_process(struct vframe_s *vf) { diff --git a/drivers/amlogic/media/enhancement/amvecm/amve.h b/drivers/amlogic/media/enhancement/amvecm/amve.h index 2719cdf5a198..53cb6d161a97 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amve.h +++ b/drivers/amlogic/media/enhancement/amvecm/amve.h @@ -56,19 +56,6 @@ struct ve_regs_s { unsigned int mode:1; unsigned int rsv:5; }; -enum vlock_param_e { - VLOCK_EN = 0x0, - VLOCK_ADAPT, - VLOCK_MODE, - VLOCK_DIS_CNT_LIMIT, - VLOCK_DELTA_LIMIT, - VLOCK_DEBUG, - VLOCK_DYNAMIC_ADJUST, - VLOCK_STATE, - VLOCK_SYNC_LIMIT_FLAG, - VLOCK_DIS_CNT_NO_VF_LIMIT, - VLOCK_PARAM_MAX, -}; extern struct ve_hist_s video_ve_hist; extern unsigned int ve_size; @@ -126,17 +113,6 @@ extern void amvecm_color_process(signed int sat_val, signed int hue_val, struct vframe_s *vf); extern void amvecm_3d_black_process(void); extern void amvecm_3d_sync_process(void); -extern void amve_vlock_process(struct vframe_s *vf); -extern void amve_vlock_resume(void); -extern void vlock_param_set(unsigned int val, enum vlock_param_e sel); -extern void vlock_status(void); -extern void vlock_reg_dump(void); -extern void vlock_log_start(void); -extern void vlock_log_stop(void); -extern void vlock_log_print(void); - -int amvecm_hiu_reg_read(unsigned int reg, unsigned int *val); -int amvecm_hiu_reg_write(unsigned int reg, unsigned int val); extern unsigned int vecm_latch_flag; extern unsigned int cm_size; extern unsigned int sync_3d_h_start; @@ -148,7 +124,6 @@ extern unsigned int sync_3d_out_inv; extern unsigned int sync_3d_black_color; extern unsigned int sync_3d_sync_to_vbo; -extern void __iomem *amvecm_hiu_reg_base; #ifndef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA #define VSYNC_WR_MPEG_REG(adr, val) WRITE_VPP_REG(adr, val) @@ -162,23 +137,6 @@ extern int VSYNC_WR_MPEG_REG(u32 adr, u32 val); /* unsigned long long ve_get_vs_cnt(void); */ /* #endif */ extern int video_rgb_ogo_xvy_mtx; - -#define VLOCK_STATE_NULL 0 -#define VLOCK_STATE_ENABLE_STEP1_DONE 1 -#define VLOCK_STATE_ENABLE_STEP2_DONE 2 -#define VLOCK_STATE_DISABLE_STEP1_DONE 3 -#define VLOCK_STATE_DISABLE_STEP2_DONE 4 -#define VLOCK_STATE_ENABLE_FORCE_RESET 5 - -/* video lock */ -#define VLOCK_MODE_ENC 0 -#define VLOCK_MODE_AUTO_PLL 1 -#define VLOCK_MODE_MANUAL_PLL 2 -#define XTAL_VLOCK_CLOCK 24000000/*vlock use xtal clock*/ - -/* 0:enc;1:pll;2:manual pll */ -extern unsigned int vlock_mode; -extern unsigned int vlock_en; extern unsigned int dnlp_sel; extern void ve_dnlp_load_reg(void); diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 2f5fe4778aae..bf3beef5125c 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -57,6 +57,7 @@ #include "bitdepth.h" #include #include "dnlp_cal.h" +#include "vlock.h" #define pr_amvecm_dbg(fmt, args...)\ do {\ @@ -525,6 +526,8 @@ static ssize_t amvecm_vlock_show(struct class *cla, "echo vlock_dynamic_adjust val(0/1) > /sys/class/amvecm/vlock\n"); len += sprintf(buf+len, "echo vlock_dis_cnt_no_vf_limit val(D) > /sys/class/amvecm/vlock\n"); + len += sprintf(buf+len, + "echo vlock_line_limit val(D) > /sys/class/amvecm/vlock\n"); len += sprintf(buf+len, "echo enable > /sys/class/amvecm/vlock\n"); len += sprintf(buf+len, @@ -597,11 +600,21 @@ static ssize_t amvecm_vlock_store(struct class *cla, return -EINVAL; temp_val = val; sel = VLOCK_DYNAMIC_ADJUST; + } else if (!strncmp(parm[0], "vlock_line_limit", 17)) { + if (kstrtol(parm[1], 10, &val) < 0) + return -EINVAL; + temp_val = val; + sel = VLOCK_LINE_LIMIT; } else if (!strncmp(parm[0], "vlock_dis_cnt_no_vf_limit", 25)) { if (kstrtol(parm[1], 10, &val) < 0) return -EINVAL; temp_val = val; sel = VLOCK_DIS_CNT_NO_VF_LIMIT; + } else if (!strncmp(parm[0], "vlock_line_limit", 16)) { + if (kstrtol(parm[1], 10, &val) < 0) + return -EINVAL; + temp_val = val; + sel = VLOCK_LINE_LIMIT; } else if (!strncmp(parm[0], "enable", 6)) { vecm_latch_flag |= FLAG_VLOCK_EN; } else if (!strncmp(parm[0], "disable", 7)) { @@ -4598,9 +4611,17 @@ static int aml_vecm_probe(struct platform_device *pdev) /*config vlock mode*/ /*todo:txlx & g9tv support auto pll,*/ /*but support not good,need vlsi support optimize*/ - if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + if (is_meson_txhd_cpu()) vlock_mode = VLOCK_MODE_MANUAL_PLL; - else + else if (is_meson_txlx_cpu() && !is_meson_txlx_package_962E()) { + struct vinfo_s *vinfo = get_current_vinfo(); + + if (vinfo->width > 1920) + vlock_mode = VLOCK_MODE_MANUAL_PLL; + else + vlock_mode = VLOCK_MODE_MANUAL_SOFT_ENC; + + } else vlock_mode = VLOCK_MODE_MANUAL_PLL; if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || is_meson_txlx_cpu() diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h index f1df9884ac49..d06b472e8e6d 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h @@ -20,24 +20,22 @@ #include -/* #if (MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV) */ -/* TV_ENC_LCD720x480 */ -static struct am_regs_s vlock_enc_lcd720x480 = { +static struct am_regs_s vlock_enc_setting = { 20, { /* optimize */ - {REG_TYPE_VCBUS, 0x3000, 0xffffffff, 0xE0f50f1b }, + {REG_TYPE_VCBUS, 0x3000, 0xffffffff, 0xE3f50f10 }, {REG_TYPE_VCBUS, 0x3001, 0xffffffff, 0x41E3c3c }, {REG_TYPE_VCBUS, 0x3002, 0xffffffff, 0x6000000 }, - {REG_TYPE_VCBUS, 0x3003, 0xffffffff, 0x40280280 }, + {REG_TYPE_VCBUS, 0x3003, 0xffffffff, 0x20680680 }, {REG_TYPE_VCBUS, 0x3004, 0xffffffff, 0x280280 }, {REG_TYPE_VCBUS, 0x3005, 0xffffffff, 0x8020000 }, {REG_TYPE_VCBUS, 0x3006, 0xffffffff, 0x0008000 }, - {REG_TYPE_VCBUS, 0x3007, 0xffffffff, 0x6000000 }, - {REG_TYPE_VCBUS, 0x3008, 0xffffffff, 0x6000000 }, + {REG_TYPE_VCBUS, 0x3007, 0xffffffff, 0x0000000 }, + {REG_TYPE_VCBUS, 0x3008, 0xffffffff, 0x0000000 }, {REG_TYPE_VCBUS, 0x3009, 0xffffffff, 0x0008000 }, {REG_TYPE_VCBUS, 0x300a, 0xffffffff, 0x8000000 }, - {REG_TYPE_VCBUS, 0x300b, 0xffffffff, 0x0008000 }, + {REG_TYPE_VCBUS, 0x300b, 0xffffffff, 0x000a000 }, {REG_TYPE_VCBUS, 0x300c, 0xffffffff, 0xa000000 }, {REG_TYPE_VCBUS, 0x300d, 0xffffffff, 0x0004000 }, {REG_TYPE_VCBUS, 0x3010, 0xffffffff, 0x20001000 }, @@ -49,22 +47,21 @@ static struct am_regs_s vlock_enc_lcd720x480 = { {0} } }; -/* out:TV_ENC_LCD1920x1080P60;in:50hz pal av */ -static struct am_regs_s vlock_pll_in50hz_out60hz = { +static struct am_regs_s vlock_pll_setting = { 20, { /* optimize */ - {REG_TYPE_VCBUS, 0x3000, 0xffffffff, 0x07f13f1b }, + {REG_TYPE_VCBUS, 0x3000, 0xffffffff, 0x07f13f1a }, {REG_TYPE_VCBUS, 0x3001, 0xffffffff, 0x04053c32 }, {REG_TYPE_VCBUS, 0x3002, 0xffffffff, 0x06000000 }, - {REG_TYPE_VCBUS, 0x3003, 0xffffffff, 0x20680680 }, + {REG_TYPE_VCBUS, 0x3003, 0xffffffff, 0x20780780 }, {REG_TYPE_VCBUS, 0x3004, 0xffffffff, 0x00000000 }, {REG_TYPE_VCBUS, 0x3005, 0xffffffff, 0x00080000 }, {REG_TYPE_VCBUS, 0x3006, 0xffffffff, 0x00070000 }, {REG_TYPE_VCBUS, 0x3007, 0xffffffff, 0x00000000 }, {REG_TYPE_VCBUS, 0x3008, 0xffffffff, 0x00000000 }, {REG_TYPE_VCBUS, 0x3009, 0xffffffff, 0x00100000 }, - {REG_TYPE_VCBUS, 0x300a, 0xffffffff, 0x00004000 }, + {REG_TYPE_VCBUS, 0x300a, 0xffffffff, 0x00008000 }, {REG_TYPE_VCBUS, 0x300b, 0xffffffff, 0x00100000 }, {REG_TYPE_VCBUS, 0x300c, 0xffffffff, 0x00000000 }, {REG_TYPE_VCBUS, 0x300d, 0xffffffff, 0x00004000 }, @@ -78,7 +75,5 @@ static struct am_regs_s vlock_pll_in50hz_out60hz = { } }; -/* #endif */ - #endif diff --git a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h index 3de8fc95111f..6c9992030e2b 100644 --- a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h +++ b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h @@ -534,12 +534,26 @@ #define HHI_HDMI_PLL_CNTL2 0x10c9 #define HHI_VID_LOCK_CLK_CNTL 0x10f2 #define HHI_HDMI_PLL_CNTL6 0x10cd +/* for vlock enc mode adjust begin */ +#define ENCL_VIDEO_MAX_LNCNT 0x1cbb +#define ENCL_VIDEO_MAX_PXCNT 0x1cb0 #define ENCL_MAX_LINE_SWITCH_POINT 0x1cc8 -/* #define P_ENCL_MAX_LINE_SWITCH_POINT */ -/* VCBUS_REG_ADDR(ENCL_MAX_LINE_SWITCH_POINT) */ +#define ENCL_VIDEO_MODE 0x1ca7 +#define ENCL_VIDEO_MODE_ADV 0x1ca8 + +#define ENCP_VIDEO_MAX_LNCNT 0x1bae +#define ENCP_VIDEO_MAX_PXCNT 0x1b97 +#define ENCP_VIDEO_MODE 0x1b8d +#define ENCP_MAX_LINE_SWITCH_POINT 0x1c0f + +#define ENCT_VIDEO_MAX_LNCNT 0x1c7b +#define ENCT_VIDEO_MAX_PXCNT 0x1c70 +#define ENCT_VIDEO_MODE 0x1c67 +#define ENCT_MAX_LINE_SWITCH_POINT 0x1c88 +/* for vlock enc mode adjust end */ + #define HHI_VID_LOCK_CLK_CNTL 0x10f2 -#define ENCL_VIDEO_MAX_LNCNT 0x1cbb #define VDIN_MEAS_VS_COUNT_LO 0x125c /*after GXL new add CNTL1,same with CNTL2 on G9TV/GXTVBB*/ #define HHI_HDMI_PLL_CNTL1 0x10c9 diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.c b/drivers/amlogic/media/enhancement/amvecm/vlock.c new file mode 100644 index 000000000000..14b8e4a32674 --- /dev/null +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.c @@ -0,0 +1,1111 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/vlock.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "arch/vpp_regs.h" +#include "vlock.h" +#include "amvecm_vlock_regmap.h" +#include "amcm.h" + +/* video lock */ +/* 0:enc;1:pll; + * 2:manual pll; + * 3:manual_enc mode(only support lvds/vx1) + */ +unsigned int vlock_mode = VLOCK_MODE_MANUAL_PLL; +unsigned int vlock_en = 1; +/* + *0:only support 50->50;60->60;24->24;30->30; + *1:support 24/30/50/60/100/120 mix,such as 50->60; + */ +static unsigned int vlock_adapt; +static unsigned int vlock_dis_cnt_limit = 2; +static unsigned int vlock_delta_limit = 2; +/* [reg(0x3009) x linemax_num)]>>24 is the limit line of enc mode */ +static signed int vlock_line_limit = 4; +/* 0x3009 default setting for 2 line(1080p-output) is 0x8000 */ +static unsigned int vlock_capture_limit = 0x8000; +static unsigned int vlock_debug; +static unsigned int vlock_dynamic_adjust = 1; + +static unsigned int vlock_sync_limit_flag; +static unsigned int vlock_state = VLOCK_STATE_NULL;/*1/2/3:vlock step*/ +static enum vmode_e pre_vmode = VMODE_INIT_NULL; +static enum vframe_source_type_e pre_source_type = + VFRAME_SOURCE_TYPE_OTHERS; +static enum vframe_source_mode_e pre_source_mode = + VFRAME_SOURCE_MODE_OTHERS; +static unsigned int pre_input_freq; +static unsigned int pre_output_freq; +static unsigned int vlock_dis_cnt; +static char pre_vout_mode[64]; +static bool vlock_vmode_changed; +static unsigned int pre_hiu_reg_m; +static unsigned int pre_hiu_reg_frac; +static signed int pre_enc_max_line; +static signed int pre_enc_max_pixel; +static unsigned int enc_max_line_addr; +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 vlock_dis_cnt_no_vf; +static unsigned int vlock_dis_cnt_no_vf_limit = 5; + +static unsigned int vlock_log_cnt;/*cnt base: vlock_log_s*/ +static unsigned int vlock_log_size = 60;/*size base: vlock_log_s*/ +static unsigned int vlock_log_delta_frac = 100; +static unsigned int vlock_log_delta_ivcnt = 0xff; +static unsigned int vlock_log_delta_ovcnt = 0xff; +static unsigned int vlock_log_delta_vcnt = 0xff; +static unsigned int vlock_log_last_ivcnt; +static unsigned int vlock_log_last_ovcnt; +static unsigned int vlock_log_delta_m; +static unsigned int vlock_log_delta_en; +module_param(vlock_log_size, uint, 0664); +MODULE_PARM_DESC(vlock_log_size, "\n vlock_log_size\n"); +module_param(vlock_log_cnt, uint, 0664); +MODULE_PARM_DESC(vlock_log_cnt, "\n vlock_log_cnt\n"); +module_param(vlock_log_delta_frac, uint, 0664); +MODULE_PARM_DESC(vlock_log_delta_frac, "\n vlock_log_delta_frac\n"); +module_param(vlock_log_delta_m, uint, 0664); +MODULE_PARM_DESC(vlock_log_delta_m, "\n vlock_log_delta_m\n"); +module_param(vlock_log_delta_en, uint, 0664); +MODULE_PARM_DESC(vlock_log_delta_en, "\n vlock_log_delta_en\n"); + +module_param(vlock_log_delta_ivcnt, uint, 0664); +MODULE_PARM_DESC(vlock_log_delta_ivcnt, "\n vlock_log_delta_ivcnt\n"); + +module_param(vlock_log_delta_ovcnt, uint, 0664); +MODULE_PARM_DESC(vlock_log_delta_ovcnt, "\n vlock_log_delta_ovcnt\n"); + +module_param(vlock_log_delta_vcnt, uint, 0664); +MODULE_PARM_DESC(vlock_log_delta_vcnt, "\n vlock_log_delta_vcnt\n"); + +static unsigned int vlock_frac; +module_param(vlock_frac, uint, 0664); +MODULE_PARM_DESC(vlock_frac, "\n vlock_frac\n"); +static unsigned int vlock_frac_delta; +module_param(vlock_frac_delta, uint, 0664); +MODULE_PARM_DESC(vlock_frac_delta, "\n vlock_frac_delta\n"); + +static unsigned int vlock_latch_en_cnt = 20; +module_param(vlock_latch_en_cnt, uint, 0664); +MODULE_PARM_DESC(vlock_latch_en_cnt, "\n vlock_latch_en_cnt\n"); + +static unsigned int vlock_log_en; +struct vlock_log_s **vlock_log; + +static signed int err_accum; +static unsigned int last_i_vsync; + +int amvecm_hiu_reg_read(unsigned int reg, unsigned int *val) +{ + *val = readl(amvecm_hiu_reg_base+((reg - 0x1000)<<2)); + return 0; +} + +int amvecm_hiu_reg_write(unsigned int reg, unsigned int val) +{ + writel(val, (amvecm_hiu_reg_base+((reg - 0x1000)<<2))); + return 0; +} +static int amvecm_hiu_reg_write_bits(unsigned int reg, unsigned int value, + unsigned int start, unsigned int len) +{ + unsigned int rd_val; + + amvecm_hiu_reg_read(reg, &rd_val); + amvecm_hiu_reg_write(reg, ((rd_val & + ~(((1L << (len)) - 1) << (start))) | + (((value) & ((1L << (len)) - 1)) << (start)))); + return 0; +} + + +static unsigned int vlock_check_input_hz(struct vframe_s *vf) +{ + unsigned int ret_hz = 0; + unsigned int duration = vf->duration; + + if ((vf->source_type != VFRAME_SOURCE_TYPE_CVBS) && + (vf->source_type != VFRAME_SOURCE_TYPE_HDMI)) + ret_hz = 0; + else if (vf->source_type == VFRAME_SOURCE_TYPE_HDMI) { + if (duration != 0) + ret_hz = (96000 + duration/2)/duration; + } else if (vf->source_type == VFRAME_SOURCE_TYPE_CVBS) { + if (vf->source_mode == VFRAME_SOURCE_MODE_NTSC) + ret_hz = 60; + else if ((vf->source_mode == VFRAME_SOURCE_MODE_PAL) || + (vf->source_mode == VFRAME_SOURCE_MODE_SECAM)) + ret_hz = 50; + else + ret_hz = 0; + } + return ret_hz; +} + +static unsigned int vlock_check_output_hz(unsigned int sync_duration_num) +{ + unsigned int ret_hz = 0; + + switch (sync_duration_num) { + case 24: + ret_hz = 24; + break; + case 30: + ret_hz = 30; + break; + case 50: + ret_hz = 50; + break; + case 60: + ret_hz = 60; + break; + case 100: + ret_hz = 100; + break; + case 120: + ret_hz = 120; + break; + default: + ret_hz = 0; + break; + } + return ret_hz; +} +/*vlock is support eq_after gxbb,but which is useful only for tv chip + *after gxl,the enable/disable reg_bit is changed + */ +static void vlock_enable(bool enable) +{ + unsigned int tmp_value; + + amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value); + + if (is_meson_gxtvbb_cpu()) { + 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, + *which may result in flashes black + */ + if (is_meson_gxtvbb_cpu() && + (((tmp_value >> 21) & 0x3) != 2)) + amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, + 2, 21, 2); + } else + 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) + amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL5, 0, 3, 1); + else + amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL5, + enable, 3, 1); + } +} +static void vlock_setting(struct vframe_s *vf, + unsigned int input_hz, unsigned int output_hz) +{ + unsigned int freq_hz = 0, hiu_reg_value_2_addr = HHI_HDMI_PLL_CNTL2; + unsigned int reg_value = 0, hiu_reg_value, hiu_reg_value_2; + 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_debug & VLOCK_DEBUG_FLUSH_REG_DIS) == 0) + am_set_regmap(&vlock_enc_setting); + /*vlock line limit*/ + WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT, vlock_capture_limit); + /* VLOCK_CNTL_EN disable */ + vlock_enable(0); + /* 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)) { + /*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); + } else { + WRITE_VPP_REG_BITS(enc_max_line_switch_addr, + 1, 13, 1); + WRITE_VPP_REG_BITS(enc_video_mode_adv_addr, 0, 14, 1); + } + /* enable to adjust pll */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 30, 1); + /*clear accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + /*clear accum0 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + /*@20180314 new add*/ + /* + *set input & output freq + *bit0~7:input freq + *bit8~15:output freq + */ + if ((vf->type_original & VIDTYPE_TYPEMASK) && + (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); + /* + *Ifrm_cnt_mod:0x3001(bit23~16); + *(output_freq/input_freq)*Ifrm_cnt_mod must be integer + */ + if (vlock_adapt == 0) + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, 1, 16, 8); + else + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, + input_hz, 16, 8); + temp_value = READ_VPP_REG(enc_max_line_addr); + WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, temp_value, 0, 14); + temp_value = READ_VPP_REG(enc_max_pixel_addr); + WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, temp_value, 16, 14); + WRITE_VPP_REG_BITS(VPU_VLOCK_ADJ_EN_SYNC_CTRL, + 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)) { + /* av pal in,1080p60 hdmi out as default */ + if ((vlock_debug & VLOCK_DEBUG_FLUSH_REG_DIS) == 0) + am_set_regmap(&vlock_pll_setting); + /* + *set input & output freq + *bit0~7:input freq + *bit8~15:output freq + */ + if (vf->type_original & VIDTYPE_TYPEMASK) + input_hz = input_hz >> 1; + freq_hz = input_hz | (output_hz << 8); + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, freq_hz, 0, 16); + /* + *Ifrm_cnt_mod:0x3001(bit23~16); + *(output_freq/input_freq)*Ifrm_cnt_mod must be integer + */ + if (vlock_adapt == 0) + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, 1, 16, 8); + else + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, + input_hz, 16, 8); + /*set PLL M_INT;PLL M_frac*/ + /* WRITE_VPP_REG_BITS(VPU_VLOCK_MX4096, */ + /* READ_CBUS_REG_BITS(HHI_HDMI_PLL_CNTL,0,9),12,9); */ + amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &hiu_reg_value); + amvecm_hiu_reg_read(hiu_reg_value_2_addr, + &hiu_reg_value_2); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { + hiu_m_val = hiu_reg_value & 0x1FF; + hiu_frac_val = hiu_reg_value_2 & 0x3FF; + if (hiu_reg_value_2 & 0x800) { + hiu_m_val -= 1; + if (hiu_reg_value_2 & 0x400) + hiu_m_val -= 1; + hiu_frac_val = 0x400 - + ((~(hiu_frac_val - 1)) & 0x3ff); + } else if (hiu_reg_value_2 & 0x400) { + hiu_m_val += 1; + } + reg_value = (hiu_m_val << 12) + + (hiu_frac_val << 2); + } + WRITE_VPP_REG_BITS(VPU_VLOCK_MX4096, reg_value, 0, 21); + + /*enable vlock to adj pll*/ + /* CFG_VID_LOCK_ADJ_EN disable */ + WRITE_VPP_REG_BITS(ENCL_MAX_LINE_SWITCH_POINT, 0, 13, 1); + /* disable to adjust pll */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 30, 1); + /* VLOCK_CNTL_EN enable */ + vlock_enable(1); + /* enable to adjust pll */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 29, 1); + } + /* vlock module output goes to which module */ + switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, 0, 2)) { + case 0:/* ENCL */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 26, 2); + break; + case 1:/* ENCI */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 2, 26, 2); + break; + case 2: /* ENCP */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 26, 2); + break; + default: + break; + } + if ((vf->source_type == VFRAME_SOURCE_TYPE_TUNER) || + (vf->source_type == VFRAME_SOURCE_TYPE_CVBS)) + /* Input Vsync source select from tv-decoder */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 2, 16, 3); + else if (vf->source_type == VFRAME_SOURCE_TYPE_HDMI) + /* Input Vsync source select from hdmi-rx */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 16, 3); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 31, 1); +} +void vlock_vmode_check(void) +{ + const struct vinfo_s *vinfo; + unsigned int tmp_value, hiu_reg_addr; + char cur_vout_mode[64]; + + if (vlock_en == 0) + return; + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) + hiu_reg_addr = HHI_HDMI_PLL_CNTL1; + else + hiu_reg_addr = HHI_HDMI_PLL_CNTL2; + vinfo = get_current_vinfo(); + vlock_vmode_changed = 0; + memset(cur_vout_mode, 0, sizeof(cur_vout_mode)); + 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_ENC) || + (vlock_mode == VLOCK_MODE_AUTO_ENC) || + (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC)) { + switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, + 0, 2)) { + case 0: + enc_max_line_addr = ENCL_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCL_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCL_VIDEO_MODE; + enc_video_mode_adv_addr = ENCL_VIDEO_MODE_ADV; + enc_max_line_switch_addr = + ENCL_MAX_LINE_SWITCH_POINT; + break; + #if 0 /*enc mode not adapt to ENCP and ENCT*/ + case 2: + enc_max_line_addr = ENCP_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCP_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCP_VIDEO_MODE; + enc_max_line_switch_addr = + ENCP_MAX_LINE_SWITCH_POINT; + break; + case 3: + enc_max_line_addr = ENCT_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCT_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCT_VIDEO_MODE; + enc_max_line_switch_addr = + ENCT_MAX_LINE_SWITCH_POINT; + break; + #endif + default: + enc_max_line_addr = ENCL_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCL_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCL_VIDEO_MODE; + enc_video_mode_adv_addr = ENCL_VIDEO_MODE_ADV; + enc_max_line_switch_addr = + ENCL_MAX_LINE_SWITCH_POINT; + break; + } + pre_enc_max_line = READ_VPP_REG(enc_max_line_addr); + pre_enc_max_pixel = READ_VPP_REG(enc_max_pixel_addr); + vlock_capture_limit = ((1 << 12) * vlock_line_limit) / + vinfo->vtotal + 1; + vlock_capture_limit <<= 12; + } + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s]:vout mode changed:%s==>%s\n", + __func__, pre_vout_mode, cur_vout_mode); + memset(pre_vout_mode, 0, sizeof(pre_vout_mode)); + strcpy(pre_vout_mode, cur_vout_mode); + vlock_vmode_changed = 1; + } +} +static void vlock_disable_step1(void) +{ + unsigned int m_reg_value, tmp_value, enc_max_line, enc_max_pixel; + unsigned int hiu_reg_addr; + + /* VLOCK_CNTL_EN disable */ + vlock_enable(0); + vlock_vmode_check(); + if ((vlock_mode == VLOCK_MODE_MANUAL_PLL) || + (vlock_mode == VLOCK_MODE_AUTO_PLL)) { + 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_m != 0)) { + tmp_value = (tmp_value & 0xfffff000) | + (pre_hiu_reg_frac & 0xfff); + amvecm_hiu_reg_write(hiu_reg_addr, tmp_value); + } + amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &tmp_value); + m_reg_value = tmp_value & 0x1ff; + if ((m_reg_value != pre_hiu_reg_m) && + (pre_hiu_reg_m != 0)) { + tmp_value = (tmp_value & 0xfffffe00) | + (pre_hiu_reg_m & 0x1ff); + 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)) { + 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); + 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)) { + 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)); + pre_vmode = VMODE_INIT_NULL; + pre_source_type = VFRAME_SOURCE_TYPE_OTHERS; + pre_source_mode = VFRAME_SOURCE_MODE_OTHERS; + pre_input_freq = 0; + pre_output_freq = 0; + vlock_state = VLOCK_STATE_DISABLE_STEP1_DONE; +} + +static void vlock_disable_step2(void) +{ + unsigned int temp_val; + /* need delay to disable follow regs(vlsi suggest!!!) */ + if (vlock_dis_cnt > 0) + vlock_dis_cnt--; + if (vlock_dis_cnt == 0) { + /* disable to adjust pll */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 29, 1); + /* CFG_VID_LOCK_ADJ_EN disable */ + WRITE_VPP_REG_BITS(ENCL_MAX_LINE_SWITCH_POINT, + 0, 13, 1); + /* disable to adjust pll */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 30, 1); + /* disable vid_lock_en */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 31, 1); + vlock_state = VLOCK_STATE_DISABLE_STEP2_DONE; + amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &temp_val); + if (is_meson_gxtvbb_cpu() && (((temp_val >> 21) & 0x3) != 0)) + amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 0, 21, 2); + } +} +static void vlock_enable_step1(struct vframe_s *vf, struct vinfo_s *vinfo, + unsigned int input_hz, unsigned int output_hz) +{ + vlock_setting(vf, input_hz, output_hz); + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("%s:vmode/source_type/source_mode/input_freq/output_freq:\n", + __func__); + pr_info("\t%d/%d/%d/%d/%d=>%d/%d/%d/%d/%d\n", + pre_vmode, pre_source_type, pre_source_mode, + pre_input_freq, pre_output_freq, + vinfo->mode, vf->source_type, vf->source_mode, + input_hz, output_hz); + } + pre_vmode = vinfo->mode; + pre_source_type = vf->source_type; + pre_source_mode = vf->source_mode; + pre_input_freq = input_hz; + pre_output_freq = output_hz; + vlock_sync_limit_flag = 0; + vlock_vmode_changed = 0; + vlock_dis_cnt = 0; + vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE; + vlock_log_cnt = 0; +} + +void vlock_log_start(void) +{ + unsigned int i; + + vlock_log = kmalloc_array(vlock_log_size, sizeof(struct vlock_log_s *), + GFP_KERNEL); + if (vlock_log == NULL) + return; + for (i = 0; i < vlock_log_size; i++) { + vlock_log[i] = kmalloc(sizeof(struct vlock_log_s), GFP_KERNEL); + if (vlock_log[i] == NULL) { + pr_info("%s:vlock_log[%d] kmalloc fail!!!\n", + __func__, i); + return; + } + } + vlock_log_en = 1; + pr_info("%s done\n", __func__); +} +void vlock_log_stop(void) +{ + unsigned int i; + + for (i = 0; i < vlock_log_size; i++) + kfree(vlock_log[i]); + kfree(vlock_log); + vlock_log_en = 0; + pr_info("%s done\n", __func__); +} +void vlock_log_print(void) +{ + unsigned int i, j; + + if (vlock_log[0] == NULL) + return; + for (i = 0; i < vlock_log_size; i++) { + pr_info("\n*******[%d]pll_m:0x%x,pll_frac:0x%x*******\n", + i, vlock_log[i]->pll_m, vlock_log[i]->pll_frac); + pr_info("*******enc_line_max:0x%x,line_num_adj:%d*******\n", + vlock_log[i]->enc_line_max, vlock_log[i]->line_num_adj); + pr_info("*******enc_pixel_max:0x%x,pixel_num_adj:%d*******\n", + vlock_log[i]->enc_pixel_max, + vlock_log[i]->pixel_num_adj); + pr_info("*******nT0:%d(0x%x),vdif_err:%d(0x%x),err_sum:%d(0x%x),margin:%d(0x%x)*******\n", + vlock_log[i]->nT0, vlock_log[i]->nT0, + vlock_log[i]->vdif_err, vlock_log[i]->vdif_err, + vlock_log[i]->err_sum, vlock_log[i]->err_sum, + vlock_log[i]->margin, vlock_log[i]->margin); + for (j = 0; j < VLOCK_REG_NUM;) { + if ((j%8 == 0) && ((j + 7) < VLOCK_REG_NUM)) { + pr_info("0x%08x\t0x%08x\t0x%08x\t0x%08x\t0x%08x\t0x%08x\t0x%08x\t0x%08x\n", + vlock_log[i]->vlock_regs[j], + vlock_log[i]->vlock_regs[j+1], + vlock_log[i]->vlock_regs[j+2], + vlock_log[i]->vlock_regs[j+3], + vlock_log[i]->vlock_regs[j+4], + vlock_log[i]->vlock_regs[j+5], + vlock_log[i]->vlock_regs[j+6], + vlock_log[i]->vlock_regs[j+7]); + j += 8; + } else { + pr_info("0x%08x\t", + vlock_log[i]->vlock_regs[j]); + j++; + } + + } + } + pr_info("%s done\n", __func__); +} +void vlock_reg_get(void) +{ + unsigned int i; + + for (i = 0; i < VLOCK_REG_NUM; i++) + vlock_log[vlock_log_cnt]->vlock_regs[i] = + READ_VPP_REG(0x3000 + i); +} +static void vlock_enable_step3_enc(void) +{ + unsigned int line_num = 0, enc_max_line = 0, polity_line_num = 0; + unsigned int pixel_num = 0, enc_max_pixel = 0, polity_pixel_num = 0; + + /*vlock pixel num adjust*/ + if (!(vlock_debug & VLOCK_DEBUG_ENC_PIXEL_ADJ_DIS)) { + polity_pixel_num = READ_VPP_REG_BITS(VPU_VLOCK_RO_LINE_PIX_ADJ, + 13, 1); + pixel_num = READ_VPP_REG_BITS(VPU_VLOCK_RO_LINE_PIX_ADJ, 0, 14); + if (polity_pixel_num) { + pixel_num = (~(pixel_num - 1)) & 0x3fff; + enc_max_pixel = pre_enc_max_pixel - pixel_num; + } else { + enc_max_pixel = pre_enc_max_pixel + pixel_num; + } + if (enc_max_pixel > 0x1fff) + WRITE_VPP_REG_BITS(enc_max_line_switch_addr, + pixel_num, 0, 13); + else + WRITE_VPP_REG_BITS(enc_max_line_switch_addr, + enc_max_pixel, 0, 13); + } + /*vlock line num adjust*/ + if (!(vlock_debug & VLOCK_DEBUG_ENC_LINE_ADJ_DIS)) { + polity_line_num = READ_VPP_REG_BITS(VPU_VLOCK_RO_LINE_PIX_ADJ, + 29, 1); + line_num = READ_VPP_REG_BITS(VPU_VLOCK_RO_LINE_PIX_ADJ, 16, 14); + if (polity_line_num) { + line_num = (~(line_num - 1)) & 0x3fff; + enc_max_line = pre_enc_max_line - line_num; + } else { + enc_max_line = pre_enc_max_line + line_num; + } + if (enc_max_pixel > 0x1fff) + enc_max_line += 1; + WRITE_VPP_REG(enc_max_line_addr, enc_max_line); + } + + if (vlock_log_en && (vlock_log_cnt < vlock_log_size)) { + vlock_log[vlock_log_cnt]->enc_line_max = enc_max_line; + vlock_log[vlock_log_cnt]->line_num_adj = line_num; + vlock_log[vlock_log_cnt]->enc_pixel_max = enc_max_pixel; + vlock_log[vlock_log_cnt]->pixel_num_adj = pixel_num; + vlock_reg_get(); + vlock_log_cnt++; + } +} + +static void vlock_enable_step3_soft_enc(void) +{ + unsigned int ia, oa; + signed int margin; + signed int pixel_adj; + signed int err, vdif_err; + signed int nT0, tfrac; + signed int line_adj; + + signed int reg_errclip_rate = + READ_VPP_REG_BITS(VPU_VLOCK_LOOP0_CTRL0, 24, 8); + signed int reg_accum_lmt = READ_VPP_REG(VPU_VLOCK_LOOP0_ACCUM_LMT); + signed int reg_capt_gain = + READ_VPP_REG_BITS(VPU_VLOCK_LOOP0_CTRL0, 0, 8); + signed int reg_capt_rs = + READ_VPP_REG_BITS(VPU_VLOCK_LOOP0_CTRL0, 8, 4); + signed int reg_capt_lmt = READ_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT); + + if (last_i_vsync == 0) { + last_i_vsync = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + return; + } + ia = (READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST) + last_i_vsync + 1) / 2; + oa = READ_VPP_REG(VPU_VLOCK_RO_VS_O_DIST); + + if (ia < oa) + margin = ia >> 8; + else + margin = oa >> 8; + + margin *= reg_errclip_rate; + margin = (margin >> 26) ? 0x3ffffff : margin; + margin = margin << 5; + margin = (margin >> 28) ? 0xfffffff : margin; + + err = oa - ia; + + if ((err < margin) && (err > -margin)) + err = err; + else + err = 0; + + vdif_err = err_accum + err; + vdif_err = (vdif_err > (1<<30)) ? (1<<30) : + (vdif_err < -(1<<30)) ? -(1<<30) : vdif_err; + + err_accum = (vdif_err > reg_accum_lmt) ? reg_accum_lmt : + (vdif_err < -reg_accum_lmt) ? -reg_accum_lmt : vdif_err; + + nT0 = (err_accum * reg_capt_gain) >> reg_capt_rs; + + nT0 = -nT0; + + nT0 = (nT0 > reg_capt_lmt) ? reg_capt_lmt : + (nT0 < -reg_capt_lmt) ? -reg_capt_lmt : nT0; + + nT0 = (nT0 * pre_enc_max_line) >> 10; + + 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) { + line_adj = line_adj + 1; + pixel_adj = pixel_adj - pre_enc_max_pixel; + } + + 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); + + last_i_vsync = READ_VPP_REG(0x3011); + + if (vlock_log_en && (vlock_log_cnt < vlock_log_size)) { + vlock_log[vlock_log_cnt]->enc_line_max = pre_enc_max_line; + vlock_log[vlock_log_cnt]->line_num_adj = line_adj; + vlock_log[vlock_log_cnt]->enc_pixel_max = pre_enc_max_pixel; + vlock_log[vlock_log_cnt]->pixel_num_adj = pixel_adj; + vlock_log[vlock_log_cnt]->nT0 = nT0; + vlock_log[vlock_log_cnt]->vdif_err = err; + vlock_log[vlock_log_cnt]->err_sum = err_accum; + vlock_log[vlock_log_cnt]->margin = margin; + vlock_reg_get(); + vlock_log_cnt++; + } +} + +static void vlock_enable_step3_pll(void) +{ + unsigned int m_reg_value, tmp_value, abs_val, hiu_reg_addr; + + if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) + hiu_reg_addr = HHI_HDMI_PLL_CNTL1; + else + hiu_reg_addr = HHI_HDMI_PLL_CNTL2; + + /*vs_i*/ + tmp_value = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + abs_val = abs(vlock_log_last_ivcnt - tmp_value); + if ((abs_val > vlock_log_delta_ivcnt) && (vlock_log_delta_en&(1<<0))) + pr_info("%s: abs_ivcnt over 0x%x:0x%x(last:0x%x,cur:0x%x)\n", + __func__, vlock_log_delta_ivcnt, + abs_val, vlock_log_last_ivcnt, tmp_value); + vlock_log_last_ivcnt = tmp_value; + /*vs_o*/ + tmp_value = READ_VPP_REG(VPU_VLOCK_RO_VS_O_DIST); + abs_val = abs(vlock_log_last_ovcnt - tmp_value); + if ((abs_val > vlock_log_delta_ovcnt) && (vlock_log_delta_en&(1<<1))) + pr_info("%s: abs_ovcnt over 0x%x:0x%x(last:0x%x,cur:0x%x)\n", + __func__, vlock_log_delta_ovcnt, + abs_val, vlock_log_last_ivcnt, tmp_value); + vlock_log_last_ovcnt = tmp_value; + /*delta_vs*/ + abs_val = abs(vlock_log_last_ovcnt - vlock_log_last_ivcnt); + if ((abs_val > vlock_log_delta_vcnt) && (vlock_log_delta_en&(1<<2))) + pr_info("%s: abs_vcnt over 0x%x:0x%x(ivcnt:0x%x,ovcnt:0x%x)\n", + __func__, vlock_log_delta_vcnt, + abs_val, vlock_log_last_ivcnt, vlock_log_last_ovcnt); + + 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_reg_get(); + vlock_log_cnt++; + } + if (m_reg_value == 0) { + vlock_state = VLOCK_STATE_ENABLE_FORCE_RESET; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("%s:vlock work abnormal! force reset vlock\n", + __func__); + return; + } + /*vlsi suggest config:don't enable load signal, + *on gxtvbb this load signal will effect SSG, + *which may result in flashes black + */ + 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); + /*frac*/ + amvecm_hiu_reg_read(hiu_reg_addr, &tmp_value); + abs_val = abs(((m_reg_value & 0xfff) >> 2) - (tmp_value & 0xfff)); + if ((abs_val >= vlock_log_delta_frac) && (vlock_log_delta_en&(1<<3))) + 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) { + tmp_value = (tmp_value & 0xfffff000) | + ((m_reg_value & 0xfff) >> 2); + amvecm_hiu_reg_write(hiu_reg_addr, tmp_value); + } + /*m*/ + amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &tmp_value); + abs_val = abs(((m_reg_value >> 16) & 0x1ff) - (tmp_value & 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)) { + tmp_value = (tmp_value & 0xfffffe00) | + ((m_reg_value >> 16) & 0x1ff); + amvecm_hiu_reg_write(HHI_HDMI_PLL_CNTL, tmp_value); + } +} +/* won't change this function internal seqence, + * if really need change,please be carefull + */ +void amve_vlock_process(struct vframe_s *vf) +{ + struct vinfo_s *vinfo; + unsigned int input_hz, output_hz, input_vs_cnt; + + if (vecm_latch_flag & FLAG_VLOCK_DIS) { + vlock_disable_step1(); + vlock_en = 0; + vecm_latch_flag &= ~FLAG_VLOCK_DIS; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s]disable vlock module!!!\n", __func__); + return; + } + vinfo = get_current_vinfo(); + input_hz = vlock_check_input_hz(vf); + output_hz = vlock_check_output_hz(vinfo->sync_duration_num); + vlock_dis_cnt_no_vf = 0; + if (vecm_latch_flag & FLAG_VLOCK_EN) { + vlock_enable_step1(vf, vinfo, input_hz, output_hz); + vlock_en = 1; + vecm_latch_flag &= ~FLAG_VLOCK_EN; + } + if (vlock_state == VLOCK_STATE_DISABLE_STEP1_DONE) { + vlock_disable_step2(); + return; + } + if (vlock_en == 1) { + /*@20170728 new add work aound method: + **disable vlock for interlace input && hdmitx output + */ + if (((input_hz != output_hz) && (vlock_adapt == 0)) || + (input_hz == 0) || (output_hz == 0) || + (((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE) && + is_meson_txlx_package_962E())) { + if ((vlock_state != VLOCK_STATE_DISABLE_STEP2_DONE) && + (vlock_state != VLOCK_STATE_NULL)) + vlock_disable_step1(); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s]auto disable vlock module for no support case!!!\n", + __func__); + return; + } + vlock_vmode_check(); + if ((vinfo->mode != pre_vmode) || + (vf->source_type != pre_source_type) || + (vf->source_mode != pre_source_mode) || + (input_hz != pre_input_freq) || + (output_hz != pre_output_freq) || + vlock_vmode_changed || + (vlock_state == VLOCK_STATE_ENABLE_FORCE_RESET)) + vlock_enable_step1(vf, vinfo, input_hz, output_hz); + if ((vlock_sync_limit_flag < 10) && + (vlock_state >= VLOCK_STATE_ENABLE_STEP1_DONE)) { + vlock_sync_limit_flag++; + if ((vlock_sync_limit_flag <= 3) && + (vlock_mode == VLOCK_MODE_MANUAL_ENC)) { + 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)) { + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + } + } + if ((vlock_sync_limit_flag == 5) && + (vlock_state == VLOCK_STATE_ENABLE_STEP1_DONE)) { + /*input_vs_cnt =*/ + /*READ_VPP_REG_BITS(VPU_VLOCK_RO_VS_I_DIST,*/ + /* 0, 28);*/ + input_vs_cnt = XTAL_VLOCK_CLOCK/input_hz; + if (vf->type_original & VIDTYPE_TYPEMASK) + input_vs_cnt = input_vs_cnt << 1; + WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MAX, + input_vs_cnt*125/100); + WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MIN, + input_vs_cnt*70/100); + /*cal accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + /*cal accum0 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + vlock_state = VLOCK_STATE_ENABLE_STEP2_DONE; + } else if (vlock_dynamic_adjust && + (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_enable_step3_enc(); + else if (vlock_mode == VLOCK_MODE_MANUAL_PLL) + vlock_enable_step3_pll(); + else if (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC) + vlock_enable_step3_soft_enc(); + } + if (((vlock_mode == VLOCK_MODE_AUTO_PLL) || + (vlock_mode == VLOCK_MODE_AUTO_ENC)) && + vlock_log_en && (vlock_log_cnt < vlock_log_size) && + (vlock_debug & VLOCK_DEBUG_AUTO_MODE_LOG_EN)) { + vlock_reg_get(); + vlock_log_cnt++; + } + } +} + +void amve_vlock_resume(void) +{ + if ((vlock_en == 0) || (vlock_state == + VLOCK_STATE_DISABLE_STEP2_DONE) || + (vlock_state == VLOCK_STATE_NULL)) + return; + if (vlock_state == VLOCK_STATE_DISABLE_STEP1_DONE) { + vlock_disable_step2(); + return; + } + vlock_dis_cnt_no_vf++; + if ((vlock_state != VLOCK_STATE_DISABLE_STEP2_DONE) && + (vlock_dis_cnt_no_vf > vlock_dis_cnt_no_vf_limit)) { + vlock_disable_step1(); + vlock_dis_cnt_no_vf = 0; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s]auto disable vlock module for no vframe & run disable step1.!!!\n", + __func__); + } + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s]auto disable vlock module for no vframe!!!\n", + __func__); + if (vlock_dynamic_adjust && + (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_enable_step3_enc(); + else if (vlock_mode == VLOCK_MODE_MANUAL_PLL) + vlock_enable_step3_pll(); + else if (vlock_mode == VLOCK_MODE_MANUAL_SOFT_ENC) + vlock_enable_step3_soft_enc(); + } +} +void vlock_param_set(unsigned int val, enum vlock_param_e sel) +{ + switch (sel) { + case VLOCK_EN: + vlock_en = val; + break; + case VLOCK_ADAPT: + vlock_adapt = val; + break; + case VLOCK_MODE: + vlock_mode = val; + break; + case VLOCK_DIS_CNT_LIMIT: + vlock_dis_cnt_limit = val; + break; + case VLOCK_DELTA_LIMIT: + vlock_delta_limit = val; + break; + case VLOCK_DEBUG: + vlock_debug = val; + break; + case VLOCK_DYNAMIC_ADJUST: + vlock_dynamic_adjust = val; + break; + case VLOCK_DIS_CNT_NO_VF_LIMIT: + vlock_dis_cnt_no_vf_limit = val; + break; + case VLOCK_LINE_LIMIT: + vlock_line_limit = val; + break; + default: + pr_info("%s:unknown vlock param:%d\n", __func__, sel); + break; + } + +} +void vlock_status(void) +{ + pr_info("\n current vlock parameters status:\n"); + pr_info("vlock_mode:%d\n", vlock_mode); + pr_info("vlock_en:%d\n", vlock_en); + 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_debug:0x%x\n", vlock_debug); + pr_info("vlock_dynamic_adjust:%d\n", vlock_dynamic_adjust); + pr_info("vlock_state:%d\n", vlock_state); + pr_info("vlock_sync_limit_flag:%d\n", vlock_sync_limit_flag); + pr_info("pre_vmode:%d\n", pre_vmode); + pr_info("pre_hiu_reg_m:0x%x\n", pre_hiu_reg_m); + pr_info("pre_hiu_reg_frac:0x%x\n", pre_hiu_reg_frac); + pr_info("pre_enc_max_line:0x%x\n", pre_enc_max_line); + pr_info("pre_enc_max_pixel:0x%x\n", pre_enc_max_pixel); + pr_info("vlock_dis_cnt:%d\n", vlock_dis_cnt); + pr_info("pre_vout_mode:%s\n", pre_vout_mode); + pr_info("vlock_dis_cnt_no_vf:%d\n", vlock_dis_cnt_no_vf); + pr_info("vlock_dis_cnt_no_vf_limit:%d\n", vlock_dis_cnt_no_vf_limit); + pr_info("enc_max_line_addr:0x%x\n", enc_max_line_addr); + pr_info("enc_max_pixel_addr:0x%x\n", enc_max_pixel_addr); + pr_info("enc_video_mode_addr:0x%x\n", enc_video_mode_addr); + pr_info("enc_max_line_switch_addr:0x%x\n", enc_max_line_switch_addr); + pr_info("vlock_capture_limit:0x%x\n", vlock_capture_limit); + pr_info("vlock_line_limit:%d\n", vlock_line_limit); +} +void vlock_reg_dump(void) +{ + unsigned int addr; + + pr_info("----dump vlock reg----\n"); + for (addr = (0x3000); addr <= (0x3020); addr++) + pr_info("[0x%x]vcbus[0x%04x]=0x%08x\n", + (0xd0100000+(addr<<2)), addr, + READ_VPP_REG(addr)); +} +/*work around method for vlock process hdmirx input interlace source.@20170803 + **for interlace input,TOP and BOT have one line delta, + **Which may cause vlock output jitter. + **The work around method is that changing vlock input select. + **So input vsync cnt may be stable, + **However the input hz should be div 2 as vlock input setting + */ +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)) + return; + if (type == VIDTYPE_INTERLACE_TOP) { + if ((source_type == VFRAME_SOURCE_TYPE_TUNER) || + (source_type == VFRAME_SOURCE_TYPE_CVBS)) + /* Input Vsync source select from tv-decoder */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 2, 16, 3); + else if (source_type == VFRAME_SOURCE_TYPE_HDMI) + /* Input Vsync source select from hdmi-rx */ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 16, 3); + } else + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 7, 16, 3); +} +EXPORT_SYMBOL(vdin_vlock_input_sel); +/*video lock end*/ + diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.h b/drivers/amlogic/media/enhancement/amvecm/vlock.h new file mode 100644 index 000000000000..18b7a0919e76 --- /dev/null +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.h @@ -0,0 +1,101 @@ +/* + * drivers/amlogic/media/enhancement/amvecm/vlock.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef __AM_VLOCK_H +#define __AM_VLOCK_H + +#include +#include "linux/amlogic/media/amvecm/ve.h" + +#define VLOCK_REG_NUM 33 + +struct vlock_log_s { + unsigned int pll_m; + unsigned int pll_frac; + signed int line_num_adj; + unsigned int enc_line_max; + signed int pixel_num_adj; + unsigned int enc_pixel_max; + signed int nT0; + signed int vdif_err; + signed int err_sum; + signed int margin; + unsigned int vlock_regs[VLOCK_REG_NUM]; +}; + +enum vlock_param_e { + VLOCK_EN = 0x0, + VLOCK_ADAPT, + VLOCK_MODE, + VLOCK_DIS_CNT_LIMIT, + VLOCK_DELTA_LIMIT, + VLOCK_DEBUG, + VLOCK_DYNAMIC_ADJUST, + VLOCK_STATE, + VLOCK_SYNC_LIMIT_FLAG, + VLOCK_DIS_CNT_NO_VF_LIMIT, + VLOCK_LINE_LIMIT, + VLOCK_PARAM_MAX, +}; + +extern void amve_vlock_process(struct vframe_s *vf); +extern void amve_vlock_resume(void); +extern void vlock_param_set(unsigned int val, enum vlock_param_e sel); +extern void vlock_status(void); +extern void vlock_reg_dump(void); +extern void vlock_log_start(void); +extern void vlock_log_stop(void); +extern void vlock_log_print(void); + + +#define VLOCK_STATE_NULL 0 +#define VLOCK_STATE_ENABLE_STEP1_DONE 1 +#define VLOCK_STATE_ENABLE_STEP2_DONE 2 +#define VLOCK_STATE_DISABLE_STEP1_DONE 3 +#define VLOCK_STATE_DISABLE_STEP2_DONE 4 +#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 XTAL_VLOCK_CLOCK 24000000/*vlock use xtal clock*/ + +/*vlock_debug mask*/ +#define VLOCK_DEBUG_INFO (1 << 0) +#define VLOCK_DEBUG_FLUSH_REG_DIS (1 << 1) +#define VLOCK_DEBUG_ENC_LINE_ADJ_DIS (1 << 2) +#define VLOCK_DEBUG_ENC_PIXEL_ADJ_DIS (1 << 3) +#define VLOCK_DEBUG_AUTO_MODE_LOG_EN (1 << 4) + +/* 0:enc;1:pll;2:manual pll */ +extern unsigned int vlock_mode; +extern unsigned int vlock_en; +extern unsigned int vecm_latch_flag; +extern void __iomem *amvecm_hiu_reg_base; + +extern void lcd_ss_enable(bool flag); +extern unsigned int lcd_ss_status(void); +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); +#endif + diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h index 8110ff45de4e..a7b7a2114cb1 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h @@ -197,5 +197,8 @@ extern void vdin_source_bitdepth_reinit(struct vdin_dev_s *devp); extern void set_invert_top_bot(bool invert_flag); extern void vdin_clk_onoff(struct vdin_dev_s *devp, bool onoff); extern enum tvin_force_color_range_e color_range_force; + +extern void vdin_vlock_input_sel(unsigned int type, + enum vframe_source_type_e source_type); #endif diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 54bf28fe6f1a..3265b85ca334 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -1262,6 +1262,8 @@ irqreturn_t vdin_isr(int irq, void *dev_id) last_field_type = devp->curr_field_type; devp->curr_field_type = vdin_get_curr_field_type(devp); + vdin_vlock_input_sel(devp->curr_field_type, + devp->curr_wr_vfe->vf.source_type); /* ignore the unstable signal */ state = tvin_get_sm_status(devp->index);