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