mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
ODROID-COMMON: hdmitx: Fix unstable HDMI modes
Change-Id: Ibac9840a0a97d195918592059b62f6024b4047be
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user