ODROID-COMMON: hdmitx: Fix unstable HDMI modes

Change-Id: I19f4ca3059d89c9a3eb651e4feaf7f0447f8a3e3
This commit is contained in:
Joy Cho
2020-08-26 15:52:16 +09:00
parent 65e5cc6e2b
commit 031c39436f
2 changed files with 77 additions and 25 deletions

View File

@@ -823,7 +823,7 @@ static struct hw_enc_clk_val_group setting_enc_clk_val_24[] = {
#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON)
{{HDMIV_2560x1440p60hz,
HDMI_VIC_END},
2415000, 1, 1, 2, VID_PLL_DIV_5, 1, 1, 1, -1},
4830000, 2, 1, 2, VID_PLL_DIV_5, 1, 1, 1, -1},
{{HDMI_480x320p60_4x3,
HDMI_480x272p60_4x3,
HDMI_VIC_END},
@@ -1154,26 +1154,34 @@ static void hdmitx_set_clk_(struct hdmitx_dev *hdev)
}
next:
#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON)
/* FIXME : consider pixel clocks over 200MHz */
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 (140*10)MHz */
if (p_enc[j].hpll_clk_out < 1400000) {
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("[N2] hpll_clk_out %d, od1 %d, od2 %d, od3 %d\n",
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);
}

View File

@@ -192,6 +192,31 @@ 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();
@@ -563,33 +588,52 @@ void set_g12a_hpll_clk_out(unsigned int frac_rate, unsigned int clk)
break;
#endif
default:
pr_info("error hpll clk: %d\n", clk);
pr_info("NO HPLL candidate - clk: %d, calculate HPLL\n", clk);
#if defined(CONFIG_ARCH_MESON64_ODROID_COMMON)
{
unsigned int m, m1, m2;
unsigned int ret;
unsigned int frac;
/* FIXME : consider pixel clocks over 200MHz */
/* calculate "m" */
m1 = (clk * 0x3A) / 1422000;
m2 = (clk * 0xE1) / 5405400;
m = ((m1 + m2) / 2) + 1;
/* 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;