ODROID-COMMON: hdmitx: Fix unstable HDMI modes

Change-Id: Ibac9840a0a97d195918592059b62f6024b4047be
This commit is contained in:
Joy Cho
2020-09-14 23:27:37 +09:00
committed by Chris
parent ce5ab3c466
commit cbfd2f0cdd
2 changed files with 84 additions and 23 deletions

View File

@@ -1110,26 +1110,39 @@ static void hdmitx_set_clk_(struct hdmitx_dev *hdev)
return;
}
next:
/* FIXME : consider pixel clocks over 200MHz */
#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON)
if (vic == HDMI_CUSTOMBUILT) {
custom_timing = get_custom_timing();
p_enc[j].hpll_clk_out = (custom_timing->frac_freq * 10);
pr_info("[N2][%s] vic == HDMI_CUSTOMBUILT, frac_freq %d\n",
pr_info("[%s] vic == HDMI_CUSTOMBUILT, frac_freq %d\n",
__func__, custom_timing->frac_freq);
/* check if hpll clk output is under (100*10)MHz */
if (p_enc[j].hpll_clk_out < 1000000) {
if (p_enc[j].hpll_clk_out > 2800000) {
p_enc[j].od1 = 1;
p_enc[j].od2 = 1;
p_enc[j].od3 = 2;
} else if (p_enc[j].hpll_clk_out <= 2800000
&& p_enc[j].hpll_clk_out > 1400000) {
p_enc[j].hpll_clk_out *= 2;
p_enc[j].od1 = 2;
p_enc[j].od2 = 1;
p_enc[j].od3 = 2;
} else if (p_enc[j].hpll_clk_out <= 1400000
&& p_enc[j].hpll_clk_out > 700000) {
p_enc[j].hpll_clk_out *= 4;
/* control od dividers */
p_enc[j].od1 = 4;
p_enc[j].od2 = 1;
p_enc[j].od3 = 2;
} else {
/* control od dividers */
p_enc[j].od1 = 1;
p_enc[j].od2 = 1;
p_enc[j].hpll_clk_out *= 8;
p_enc[j].od1 = 4;
p_enc[j].od2 = 2;
p_enc[j].od3 = 2;
}
pr_info("hpll_clk_out %d, od1 %d, od2 %d, od3 %d\n",
p_enc[j].hpll_clk_out,
p_enc[j].od1, p_enc[j].od2, p_enc[j].od3);
}
#endif
hdmitx_set_cts_sys_clk(hdev);
set_hpll_clk_out(p_enc[j].hpll_clk_out);

View File

@@ -192,10 +192,39 @@ static void set_hpll_hclk_dongle_5940m(void)
pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL0));
}
#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON)
#define XTAL_FREQ 24000
#define HDMI_FRAC_MAX_G12A 131072
unsigned int get_g12a_pll_get_frac(unsigned int m, unsigned int pll_freq)
{
unsigned int parent_freq = XTAL_FREQ;
unsigned int frac_max = HDMI_FRAC_MAX_G12A;
unsigned int frac_m;
unsigned int frac;
if (pll_freq / m == parent_freq &&
pll_freq % m == 0)
return 0;
frac = div_u64((u64)pll_freq * (u64)frac_max, parent_freq);
frac_m = m * frac_max;
if (frac_m > frac)
return frac_max;
frac -= frac_m;
return min((u16)frac, (u16)(frac_max - 1));
}
#endif
void set_g12a_hpll_clk_out(unsigned int frac_rate, unsigned int clk)
{
struct hdmitx_dev *hdev = get_hdmitx_device();
#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON)
unsigned int m, m1, m2;
unsigned int ret;
unsigned int frac;
#endif
switch (clk) {
case 5940000:
@@ -338,29 +367,48 @@ void set_g12a_hpll_clk_out(unsigned int frac_rate, unsigned int clk)
pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL0));
break;
default:
pr_info("error hpll clk: %d\n", clk);
pr_info("NO HPLL candidate - clk: %d, calculate HPLL\n", clk);
/* FIXME : consider pixel clocks over 200MHz */
/* calculate "m" */
m1 = (clk * 0x3A) / 1422000;
m2 = (clk * 0xE1) / 5405400;
m = (m1 + m2)/2;
#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON)
/* calculate m */
m = clk / XTAL_FREQ;
m &= 0xff;
m |= 0x3b000400;
hd_write_reg(P_HHI_HDMI_PLL_CNTL0, m);
hd_write_reg(P_HHI_HDMI_PLL_CNTL0, (m | 0x3b000400));
pr_info("m1 0x%x, m2 0x%x, m 0x%x\n", m1, m2, m);
/* check pll LOCK time */
hd_write_reg(P_HHI_HDMI_PLL_CNTL1, 0x00018000);
/* calculate frac */
frac = get_g12a_pll_get_frac(m, clk);
pr_info("m 0x%x, frac 0x%x\n", m, frac);
hd_write_reg(P_HHI_HDMI_PLL_CNTL1, frac);
hd_write_reg(P_HHI_HDMI_PLL_CNTL2, 0x00000000);
hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0a691c00);
hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x33771290);
hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x39270000);
hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x50540000);
if (m >= 0xf7) {
if (frac < 0x10000) {
hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x6a685c00);
hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x11551293);
} else {
hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0xea68dc00);
hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x65771290);
}
hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x39270000);
hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x55540000);
} else {
hd_write_reg(P_HHI_HDMI_PLL_CNTL3, 0x0a691c00);
hd_write_reg(P_HHI_HDMI_PLL_CNTL4, 0x33771290);
hd_write_reg(P_HHI_HDMI_PLL_CNTL5, 0x39270000);
hd_write_reg(P_HHI_HDMI_PLL_CNTL6, 0x50540000);
}
hd_set_reg_bits(P_HHI_HDMI_PLL_CNTL0, 0x0, 29, 1);
WAIT_FOR_PLL_LOCKED(P_HHI_HDMI_PLL_CNTL0);
pr_info("HPLL: 0x%x\n", hd_read_reg(P_HHI_HDMI_PLL_CNTL0));
ret = (((hd_read_reg(P_HHI_HDMI_PLL_CNTL0) >> 30) & 0x3) == 0x3);
if (ret)
pr_info("[%s] HPLL set OK!\n", __func__);
else
pr_info("[%s] Error! Check HPLL track!\n", __func__);
#endif
break;
}
}