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 b3e4c6059db6..4e78d7c5e8fd 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 @@ -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); } 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 c41047e2c0f6..36dce824cc89 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,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;