return ret_hz;
}
-static unsigned int vlock_check_output_hz(unsigned int sync_duration_num)
+static unsigned int vlock_check_output_hz(unsigned int sync_duration_num,
+ unsigned int sync_duration_den)
{
unsigned int ret_hz = 0;
+ unsigned int tempHz;
- switch (sync_duration_num) {
- case 24:
+ tempHz = (sync_duration_num*100)/sync_duration_den;
+
+ switch (tempHz) {
+ case 2400:
ret_hz = 24;
break;
- case 30:
+ case 3000:
ret_hz = 30;
break;
- case 50:
+ case 5000:
ret_hz = 50;
break;
- case 60:
+ case 6000:
ret_hz = 60;
break;
- case 100:
+ case 10000:
ret_hz = 100;
break;
- case 120:
+ case 12000:
ret_hz = 120;
break;
default:
ret_hz = 0;
break;
}
+
+ if ((ret_hz == 0) && (vlock_debug & VLOCK_DEBUG_INFO))
+ pr_info("sync_duration_num:%d\n", sync_duration_num);
+
return ret_hz;
}
/*vlock is support eq_after gxbb,but which is useful only for tv chip
else
amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL5,
enable, 3, 1);
- } else if (is_meson_tl1_cpu()) {
+ } else if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) {
/*reset*/
- if (vlock_mode & VLOCK_MODE_MANUAL_PLL) {
- #if 0
- if (enable == 1) {
-
- if (vlock_debug & VLOCK_DEBUG_INFO)
- pr_info("tl1 vlock enable\n");
- amvecm_hiu_reg_write_bits(hhi_pll_reg_vlock_ctl,
- 1, 0, 1);
- } else {
- if (vlock_debug & VLOCK_DEBUG_INFO)
- pr_info("tl1 vlock disable\n");
- amvecm_hiu_reg_write_bits(hhi_pll_reg_vlock_ctl,
- 0, 0, 1);
- }
- #endif
- } else {
+ if (!(vlock_mode & VLOCK_MODE_MANUAL_PLL)) {
/*reset*/
WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1);
WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);
- if (!enable)
- amvecm_hiu_reg_write_bits(
- HHI_HDMI_PLL_VLOCK_CNTL, 0, 1, 2);
+ }
+
+ if (!enable) {
+ /*amvecm_hiu_reg_write_bits(*/
+ /* HHI_HDMI_PLL_VLOCK_CNTL, 0, 0, 3);*/
+
+ /*WRITE_VPP_REG(VPU_VLOCK_CTRL, 0);*/
}
}
amvecm_hiu_reg_read(hhi_pll_reg_m, &hiu_reg_value);
amvecm_hiu_reg_read(hhi_pll_reg_frac,
&hiu_reg_value_2);
+
+ if (vlock_debug & VLOCK_DEBUG_INFO) {
+ pr_info("hhi_pll_reg_m:0x%x\n", hiu_reg_value);
+ pr_info("hhi_pll_reg_frac:0x%x\n", hiu_reg_value_2);
+ }
+
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
hiu_m_val = hiu_reg_value & 0xff;
/*discard low 5 bits*/
/* enable to adjust pll */
WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 29, 1);
}
+
+ /*initial phase lock setting*/
+ if (vlock.dtdata->vlk_phlock_en) {
+ /*WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT, 0x06000000);*/
+ WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT, 0x06000000);
+ WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_PLL_LMT, 0x06000000);
+ WRITE_VPP_REG(VPU_VLOCK_OUTPUT1_CAPT_LMT, 0x06000000);
+ WRITE_VPP_REG(VPU_VLOCK_OUTPUT1_PLL_LMT, 0x06000000);
+
+ /*enable pll mode and enc mode phase lock*/
+ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 3, 0, 2);
+ }
+
/* vlock module output goes to which module */
switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, 0, 2)) {
case 0:/* ENCL */
if ((vlock_mode & (VLOCK_MODE_MANUAL_PLL |
VLOCK_MODE_AUTO_PLL |
VLOCK_MODE_MANUAL_SOFT_ENC))) {
- if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
+ if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) {
+ #if 0
amvecm_hiu_reg_read(hhi_pll_reg_frac,
&tmp_value);
m_reg_value = (tmp_value >> 5) & 0xfff;
(pre_hiu_reg_frac & 0xfff);
amvecm_hiu_reg_write(hhi_pll_reg_frac,
tmp_value);
+ pr_info("restore f value=0x%x\n", tmp_value);
}
amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);
m_reg_value = tmp_value & 0xff;
tmp_value = (tmp_value & 0xffffff00) |
(pre_hiu_reg_m & 0xff);
amvecm_hiu_reg_write(hhi_pll_reg_m, tmp_value);
+ pr_info("restore m value=0x%x\n", tmp_value);
}
+ #endif
+
+ #if 1
+ /*restore the orginal pll setting*/
+ amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);
+ m_reg_value = tmp_value & 0xff;
+ if (m_reg_value != (vlock.val_m & 0xff))
+ amvecm_hiu_reg_write(hhi_pll_reg_m,
+ vlock.val_m);
+
+ amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);
+ m_reg_value = tmp_value & 0x1ffff;
+ if (m_reg_value != (vlock.val_frac & 0xfff))
+ amvecm_hiu_reg_write(hhi_pll_reg_frac,
+ vlock.val_frac);
+ pr_info("restore orignal m,f value\n");
+ #endif
} else {
amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);
m_reg_value = tmp_value & 0xfff;
pr_info(">>>[%s]\n", __func__);
}
-static void vlock_disable_step2(void)
+static bool vlock_disable_step2(void)
{
unsigned int temp_val;
+ bool ret = false;
/* need delay to disable follow regs(vlsi suggest!!!) */
if (vlock_dis_cnt > 0)
vlock_dis_cnt--;
- if (vlock_dis_cnt == 0) {
+ else if (vlock_dis_cnt == 0) {
+ if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) {
+ amvecm_hiu_reg_write_bits(
+ HHI_HDMI_PLL_VLOCK_CNTL, 0x4, 0, 3);
+ amvecm_hiu_reg_write_bits(
+ HHI_HDMI_PLL_VLOCK_CNTL, 0x0, 0, 3);
+ }
+
/* disable to adjust pll */
WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 29, 1);
/* CFG_VID_LOCK_ADJ_EN disable */
amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6,
0, 21, 2);
}
+ ret = true;
+
+ if (vlock_debug & VLOCK_DEBUG_INFO)
+ pr_info(">>>[%s]\n", __func__);
}
- if (vlock_debug & VLOCK_DEBUG_INFO)
- pr_info(">>>[%s]\n", __func__);
+ return ret;
}
static void vlock_enable_step1(struct vframe_s *vf, struct vinfo_s *vinfo,
unsigned int input_hz, unsigned int output_hz)
else
vlock_pll_stable_cnt = 0;
} else {
- tmp_value = (tmp_value & 0xfff80000) |
- ((m_reg_value & 0xfff) << 5);
+ abs_val = abs((tmp_value & 0x1ffff) -
+ ((m_reg_value & 0xfff) << 5));
+
+ if (abs_val > (50 << 5))
+ tmp_value = ((tmp_value & 0xfffe0000) |
+ (((tmp_value & 0x1ffff) +
+ ((m_reg_value & 0xfff) << 5)) >> 1));
+ else
+ tmp_value = (tmp_value & 0xfffe0000) |
+ ((m_reg_value & 0xfff) << 5);
+
+ /*16:0*/
amvecm_hiu_reg_write(hhi_pll_reg_frac, tmp_value);
}
vlock_pll_val_last |= (m_reg_value & 0xffff0000);
}
} else {
- tmp_value = (tmp_value & 0xffffff00) |
- ((m_reg_value >> 16) & 0xff);
- amvecm_hiu_reg_write(hhi_pll_reg_m, tmp_value);
+ if ((tmp_value & 0xff) !=
+ ((m_reg_value >> 16) & 0xff)) {
+ if (vlock_debug & VLOCK_DEBUG_INFO)
+ pr_info("vlock err: m chg: org=0x%x, new=0x%x\n",
+ (tmp_value & 0xff), (m_reg_value >> 16) & 0xff);
+ #if 0
+ tmp_value = (tmp_value & 0xffffff00) |
+ ((m_reg_value >> 16) & 0xff);
+ amvecm_hiu_reg_write(hhi_pll_reg_m, tmp_value);
+ #endif
+ }
}
/*check stable by diff m*/
}
vinfo = get_current_vinfo();
input_hz = vlock_check_input_hz(vf);
- output_hz = vlock_check_output_hz(vinfo->sync_duration_num);
+ output_hz = vlock_check_output_hz(vinfo->sync_duration_num,
+ vinfo->sync_duration_den);
vlock_dis_cnt_no_vf = 0;
if (vecm_latch_flag & FLAG_VLOCK_EN) {
vlock_enable_step1(vf, vinfo, input_hz, output_hz);
//WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);
vlock_state = VLOCK_STATE_ENABLE_STEP2_DONE;
- /*tl1 auto pll,swich clk need after several frames*/
- if (is_meson_tl1_cpu() &&
- (vlock_mode & VLOCK_MODE_AUTO_PLL))
- amvecm_hiu_reg_write_bits(
- HHI_HDMI_PLL_VLOCK_CNTL, 0x3, 1, 2);
+ /*
+ * tl1 auto pll,swich clk need after
+ *several frames
+ */
+ if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) {
+ if (IS_AUTO_MODE(vlock_mode))
+ amvecm_hiu_reg_write_bits(
+ HHI_HDMI_PLL_VLOCK_CNTL, 0x7, 0, 3);
+ else if (IS_MANUAL_MODE(vlock_mode))
+ amvecm_hiu_reg_write_bits(
+ HHI_HDMI_PLL_VLOCK_CNTL, 0x6, 0, 3);
+ }
if (vlock_debug & VLOCK_DEBUG_INFO)
pr_info("amve_vlock_process-2\n");
void vlock_status_init(void)
{
+ unsigned int val;
+
/*config vlock mode*/
/*todo:txlx & g9tv support auto pll,*/
/*but support not good,need vlsi support optimize*/
hhi_pll_reg_frac = HHI_HDMI_PLL_CNTL2;
}
+ /*back up orignal pll value*/
+ amvecm_hiu_reg_read(hhi_pll_reg_m, &val);
+ vlock.val_m = val;
+ pr_info("HIU pll m[0x%x]=0x%x\n",
+ hhi_pll_reg_m, val);
+ amvecm_hiu_reg_read(hhi_pll_reg_frac, &val);
+ vlock.val_frac = val;
+ pr_info("HIU pll f[0x%x]=0x%x\n",
+ hhi_pll_reg_frac, val);
+
vlock.fsm_sts = VLOCK_STATE_NULL;
vlock.fsm_prests = VLOCK_STATE_NULL;
vlock.vf_sts = false;
vlock.vmd_chg = false;
vlock.md_support = false;
+ vlock.phlock_percent = 40;
vlock_clear_frame_counter();
pr_info("%s vlock_en:%d\n", __func__, vlock_en);
}
pr_info("vlock dt phlock_en: %d\n", vlock.dtdata->vlk_phlock_en);
}
+void vlock_set_phase(u32 percent)
+{
+ u32 vs_i_val = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST);
+ /*u32 vs_o_val = READ_VPP_REG(VPU_VLOCK_RO_VS_O_DIST);*/
+ u32 data = 0;
+
+ if (!vlock.dtdata->vlk_phlock_en)
+ return;
+
+ if (percent > 100) {
+ pr_info("percent val err:%d\n", percent);
+ return;
+ }
+
+ vlock.phlock_percent = percent;
+ data = (vs_i_val * (100 + vlock.phlock_percent))/200;
+ WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, data);
+ pr_info("LOOP1_PHSDIF_TGT:0x%x\n", data);
+
+ /*reset*/
+ data = READ_VPP_REG(VPU_VLOCK_CTRL);
+ data |= 1 << 2;
+ data |= 1 << 5;
+ WRITE_VPP_REG(VPU_VLOCK_CTRL, data);
+ data &= ~(1 << 2);
+ data &= ~(1 << 5);
+ WRITE_VPP_REG(VPU_VLOCK_CTRL, data);
+}
+
+void vlock_set_phase_en(u32 en)
+{
+ if (en)
+ vlock.dtdata->vlk_phlock_en = true;
+ else
+ vlock.dtdata->vlk_phlock_en = false;
+}
+
#if 1
u32 vlock_fsm_check_support(struct stvlock_sig_sts *pvlock,
!= VIDTYPE_PROGRESSIVE) &&
is_meson_txlx_package_962E())) {
- if (vlock_debug & VLOCK_DEBUG_INFO)
+ if (vlock_debug & VLOCK_DEBUG_INFO) {
pr_info("[%s] for no support case!!!\n",
__func__);
+ pr_info("input_hz:%d, output_hz:%d\n",
+ pvlock->input_hz, pvlock->output_hz);
+ pr_info("type_original:0x%x\n", vf->type_original);
+ }
ret = false;
}
else
vframe_sts = true;
+ vlock_vmode_check();
+
if (vf != NULL) {
vinfo = get_current_vinfo();
vlock->input_hz = vlock_check_input_hz(vf);
vlock->output_hz = vlock_check_output_hz(
- vinfo->sync_duration_num);
+ vinfo->sync_duration_num, vinfo->sync_duration_den);
}
/*check vf exist status*/
vlock_vmode_changed ||
(pvlock->fsm_sts ==
VLOCK_STATE_ENABLE_FORCE_RESET)) {
+
+ /*back up orignal pll value*/
+ amvecm_hiu_reg_read(hhi_pll_reg_m, &vlock.val_m);
+ amvecm_hiu_reg_read(hhi_pll_reg_frac, &vlock.val_frac);
+ if (vlock_debug & VLOCK_DEBUG_INFO) {
+ pr_info("HIU pll m[0x%x]=0x%x\n",
+ hhi_pll_reg_m, vlock.val_m);
+ pr_info("HIU pll f[0x%x]=0x%x\n",
+ hhi_pll_reg_frac, vlock.val_frac);
+ }
vinfo = get_current_vinfo();
vlock_enable_step1(vf, vinfo,
pvlock->input_hz, pvlock->output_hz);
* tl1 auto pll,swich clk need after
*several frames
*/
- if (is_meson_tl1_cpu() &&
- IS_AUTO_PLL_MODE(vlock_mode))
- amvecm_hiu_reg_write_bits(
- HHI_HDMI_PLL_VLOCK_CNTL, 0x3, 1, 2);
+ if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) {
+ if (IS_AUTO_MODE(vlock_mode))
+ amvecm_hiu_reg_write_bits(
+ HHI_HDMI_PLL_VLOCK_CNTL, 0x7, 0, 3);
+ else if (IS_MANUAL_MODE(vlock_mode))
+ amvecm_hiu_reg_write_bits(
+ HHI_HDMI_PLL_VLOCK_CNTL, 0x6, 0, 3);
+ }
ret = 1;
if (vlock_debug & VLOCK_DEBUG_INFO)
return ret;
}
+
+void vlock_phaselock_check(struct stvlock_sig_sts *pvlock,
+ struct vframe_s *vf)
+{
+ /*vs_i*/
+ u32 ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST);
+ u32 val;
+
+ if (vlock.dtdata->vlk_phlock_en) {
+ ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST);
+ val = (ia * (100 + vlock.phlock_percent))/200;
+ WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, val);
+
+ /*reset*/
+ /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1);*/
+ /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1);*/
+
+ /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1);*/
+ /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);*/
+ }
+}
+
u32 vlock_fsm_en_step2_func(struct stvlock_sig_sts *pvlock,
struct vframe_s *vf)
{
vlock_enable_step3_pll();
else if (IS_MANUAL_SOFTENC_MODE(vlock_mode))
vlock_enable_step3_soft_enc();
- /*check stable*/
- /*....*/
}
+ /*check phase*/
+ vlock_phaselock_check(pvlock, vf);
return ret;
}
u32 changed;
changed = vlock_fsm_input_check(&vlock, vf);
- vlock_vmode_check();
switch (vlock.fsm_sts) {
case VLOCK_STATE_NULL:
if (vlock.vf_sts) {
/*have frame in*/
- if (vlock.frame_cnt_in++ == 3) {
+ if (vlock.frame_cnt_in++ >= 20) {
/*vframe input valid*/
if (vlock.md_support) {
if (vlock_fsm_to_en_func(&vlock, vf)) {
/*go to disable state*/
vlock_clear_frame_counter();
vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE;
- } else {
- vlock_fsm_en_step2_func(&vlock, vf);
}
}
break;
case VLOCK_STATE_DISABLE_STEP1_DONE:
vlock_disable_step1();
- vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP2_DONE;
+ if (vlock_disable_step2())
+ vlock.fsm_sts = VLOCK_STATE_NULL;
+ else
+ vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP2_DONE;
break;
case VLOCK_STATE_DISABLE_STEP2_DONE:
- vlock_disable_step2();
- vlock.fsm_sts = VLOCK_STATE_NULL;
+ if (vlock_disable_step2())
+ vlock.fsm_sts = VLOCK_STATE_NULL;
break;
default:
if (probe_ok == 0 || !vlock_en)
return;
+ if (vlock_debug & VLOCK_DEBUG_FSM_DIS)
+ return;
+
/* todo:vlock processs only for tv chip */
if (vlock.dtdata->vlk_new_fsm)
vlock_fsm_monitor(vf);
}
void vlock_status(void)
{
+ struct vinfo_s *vinfo;
+
pr_info("\n current vlock parameters status:\n");
+ pr_info("vlock driver version : %s\n", VLOCK_VER);
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_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("vlk_support:%d\n", vlock.dtdata->vlk_support);
pr_info("vlk_new_fsm:%d\n", vlock.dtdata->vlk_new_fsm);
- pr_info("vlock driver version : %s\n", VLOCK_VER);
+ pr_info("vlk_phlock_en:%d\n", vlock.dtdata->vlk_phlock_en);
+ pr_info("vlk_hwver:%d\n", vlock.dtdata->vlk_hwver);
+ vinfo = get_current_vinfo();
+ pr_info("vinfo sync_duration_num:%d\n", vinfo->sync_duration_num);
+ pr_info("vinfo sync_duration_den:%d\n", vinfo->sync_duration_den);
+ pr_info("vinfo video_clk:%d\n", vinfo->video_clk);
+ pr_info("vframe input_hz:%d\n", vlock.input_hz);
+ pr_info("vframe output_hz:%d\n", vlock.output_hz);
}
+
void vlock_reg_dump(void)
{
unsigned int addr;
amvecm_hiu_reg_read(HHI_HDMI_PLL_VLOCK_CNTL, &val);
pr_info("HIU [0x%04x]=0x%08x\n", HHI_HDMI_PLL_VLOCK_CNTL, val);
}
+ amvecm_hiu_reg_read(hhi_pll_reg_m, &val);
+ pr_info("HIU pll m[0x%04x]=0x%08x\n", hhi_pll_reg_m, val);
+ amvecm_hiu_reg_read(hhi_pll_reg_frac, &val);
+ pr_info("HIU pll f[0x%04x]=0x%08x\n", hhi_pll_reg_frac, val);
+
+ /*back up orignal pll value*/
+ pr_info("HIU pll m[0x%x]=0x%x\n", hhi_pll_reg_m, vlock.val_m);
+ pr_info("HIU pll f[0x%x]=0x%x\n", hhi_pll_reg_frac, vlock.val_frac);
+
}
/*work around method for vlock process hdmirx input interlace source.@20170803
**for interlace input,TOP and BOT have one line delta,