From df3e952b008526d213832d806a4254d63d84c3eb Mon Sep 17 00:00:00 2001 From: Zhibin Huang Date: Fri, 19 Jul 2024 17:54:44 +0800 Subject: [PATCH] misc: rk628: fix first edid get failure Type: Fix Redmine ID: N/A Associated modifications: N/A Test: N/A Signed-off-by: Zhibin Huang Change-Id: I799efc76a444f33c4206f2d6e3610a8768088c81 (cherry picked from commit 11e329fa9405c61c01e6f7630b1482f4f82b6b5f) --- drivers/misc/rk628/rk628_cru.c | 102 ++++++++++++++++-------------- drivers/misc/rk628/rk628_hdmitx.c | 9 ++- 2 files changed, 62 insertions(+), 49 deletions(-) diff --git a/drivers/misc/rk628/rk628_cru.c b/drivers/misc/rk628/rk628_cru.c index 6afdae90e5f7..753bfa6a728f 100644 --- a/drivers/misc/rk628/rk628_cru.c +++ b/drivers/misc/rk628/rk628_cru.c @@ -722,57 +722,65 @@ void rk628_cru_init(struct rk628 *rk628) * rk628f pclk use gpll by default, and frequency is 98.304MHz */ if (rk628_input_is_bt1120(rk628)) { - /* set pclk use gpll, and set pclk 98.304Hz */ + /* set pclk use gpll, and set pclk 98.304MHz */ rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0089); } - return; + } else { + /* clock switch and first set gpll almost 99MHz */ + rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff701d); + mdelay(1); + /* set clk_gpll_mux from gpll */ + rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0004); + mdelay(1); + rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0080); + /* set pclk use gpll, now div is 4 */ + rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0083); + /* set cpll almost 400MHz */ + rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff3063); + mdelay(1); + /* set clk_cpll_mux from clk_cpll */ + rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0005); + mdelay(1); + if (rk628_input_is_bt1120(rk628)) { + /* set pclk use cpll, now div is 4 */ + rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0003); + /* set pclk use cpll, now div is 10 */ + rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0009); + /* set gpll 983.04MHz */ + rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff1028); + mdelay(1); + /* set pclk use gpll, now div is 10 */ + rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0089); + /* set cpll 1188MHz */ + rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff1063); + /* final: cpll 1188MHz, gpll 983.04MHz, pclk (use gpll) 98.304MHz */ + } else { + /* set pclk use cpll, now div is 4 */ + rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0003); + /* set pclk use cpll, now div is 12 */ + rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b); + /* set gpll 983.04MHz */ + rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff1028); + mdelay(1); + /* set pclk use gpll, now div is 12 */ + rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff008b); + /* set cpll 1188MHz */ + rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff1063); + mdelay(1); + /* set pclk use cpll, now div is 12 */ + rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b); + /* final: cpll 1188MHz, gpll 983.04MHz, pclk (use cpll) 99MHz */ + } } - /* clock switch and first set gpll almost 99MHz */ - rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff701d); - mdelay(1); - /* set clk_gpll_mux from gpll */ - rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0004); - mdelay(1); - rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0080); - /* set pclk use gpll, now div is 4 */ - rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0083); - /* set cpll almost 400MHz */ - rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff3063); - mdelay(1); - /* set clk_cpll_mux from clk_cpll */ - rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0005); - mdelay(1); - if (rk628_input_is_bt1120(rk628)) { - /* set pclk use cpll, now div is 4 */ - rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0003); - /* set pclk use cpll, now div is 10 */ - rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0009); - /* set gpll 983.04Hz */ - rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff1028); - mdelay(1); - /* set pclk use gpll, now div is 10 */ - rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0089); - /* set cpll 1188MHz */ - rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff1063); - /* final: cpll 1188MHz, gpll 983.04Hz, pclk (use gpll) 98.304Hz */ - } else { - /* set pclk use cpll, now div is 4 */ - rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0003); - /* set pclk use cpll, now div is 12 */ - rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b); - /* set gpll 983.04Hz */ - rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff1028); - mdelay(1); - /* set pclk use gpll, now div is 12 */ - rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff008b); - /* set cpll 1188MHz */ - rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff1063); - mdelay(1); - /* set pclk use cpll, now div is 12 */ - rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b); - /* final: cpll 1188MHz, gpll 983.04Hz, pclk (use cpll) 99Hz */ - } + /* + * The sclk_vop frequency default is 594M, which exceeds the reference + * clock frequency acceptable by hdmitx phy. Therefore, in the hdmitx + * scenario, we need to set the initial frequency of the sclk_vop to a + * lower frequency, which is set to 148.5M. + */ + if (rk628_output_is_hdmi(rk628)) + rk628_cru_clk_set_rate(rk628, CGU_SCLK_VOP, 148500000); } void rk628_cru_clk_adjust(struct rk628 *rk628) diff --git a/drivers/misc/rk628/rk628_hdmitx.c b/drivers/misc/rk628/rk628_hdmitx.c index a5444501455d..f28b78a6b525 100644 --- a/drivers/misc/rk628/rk628_hdmitx.c +++ b/drivers/misc/rk628/rk628_hdmitx.c @@ -31,6 +31,7 @@ #include "rk628_config.h" #include "rk628_hdmitx.h" #include "rk628_post_process.h" +#include "rk628_cru.h" #include #include @@ -1231,7 +1232,7 @@ void rk628_hdmitx_disable(struct rk628 *rk628) int rk628_hdmitx_enable(struct rk628 *rk628) { struct device *dev = rk628->dev; - struct rk628_hdmi *hdmi; + struct rk628_hdmi *hdmi = NULL; u32 mask = SW_OUTPUT_MODE_MASK; u32 val = SW_OUTPUT_MODE(OUTPUT_MODE_HDMI); int irq; @@ -1299,7 +1300,11 @@ int rk628_hdmitx_enable(struct rk628 *rk628) * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate, * and reconfigure the DDC clock. */ - hdmi->tmds_rate = 24000 * 1000; + rk628_i2c_read(rk628, GRF_POST_PROC_CON, &val); + if (val & SW_HDMITX_VCLK_PLLREF_SEL(1)) + hdmi->tmds_rate = rk628_cru_clk_get_rate(rk628, CGU_SCLK_VOP); + else + hdmi->tmds_rate = 24000000; rk628_hdmi_i2c_init(hdmi); rk628_hdmi_audio_codec_init(hdmi, dev);