diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c index dfaa87dac6de..af92d2e25563 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_clk.c @@ -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); diff --git a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c index b71e268f6b33..cbdef1469bee 100644 --- a/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c +++ b/drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hw/hw_g12a.c @@ -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; } }