From 727394f2d9fe5d4a89f5dc7ea78863670a869513 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Wed, 15 May 2024 17:53:32 +0800 Subject: [PATCH] phy: rockchip-samsung-hdptx-hdmi: Fix get phy pll freq failed in frl mode Get phy pll freq failed in frl mode should read lcpll regs. Fixes: fff8ec3ee904 ("phy: rockchip-samsung-hdptx-hdmi: Fix phy pll is incorrectly configured when logo is enabled.") Change-Id: I64e973f85acd74ee251b4ab6c0a141394c116d92 Signed-off-by: Algea Cao --- .../phy-rockchip-samsung-hdptx-hdmi.c | 97 ++++++++++++------- 1 file changed, 62 insertions(+), 35 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx-hdmi.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx-hdmi.c index 319a601410d4..4f3b9f075426 100644 --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx-hdmi.c +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx-hdmi.c @@ -729,7 +729,7 @@ struct rockchip_hdptx_phy { int count; }; -struct lcpll_config lcpll_cfg[] = { +static struct lcpll_config lcpll_cfg[] = { { 48000000, 1, 0, 0, 0x7d, 0x7d, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2, 0, 0x13, 0x18, 1, 0, 0x20, 0x0c, 1, 0, }, @@ -745,27 +745,9 @@ struct lcpll_config lcpll_cfg[] = { { 9000000, 1, 0, 0, 0x7d, 0x7d, 1, 1, 3, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2, 0, 0x13, 0x18, 1, 0, 0x20, 0x0c, 1, 0, }, - { ~0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - }, }; -struct ropll_config ropll_frl_cfg[] = { - { 24000000, 0x19, 0x19, 1, 1, 0, 1, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, - 0, 0x20, 0x0c, 1, 0x0e, 0, 0, - }, - { 18000000, 0x7d, 0x7d, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, - 0, 0x20, 0x0c, 1, 0x0e, 0, 0, - }, - { 9000000, 0x7d, 0x7d, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, - 0, 0x20, 0x0c, 1, 0x0e, 0, 0, - }, - { ~0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }, -}; - -struct ropll_config ropll_tmds_cfg[] = { +static struct ropll_config ropll_tmds_cfg[] = { { 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, @@ -826,9 +808,6 @@ struct ropll_config ropll_tmds_cfg[] = { { 251750, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, - { ~0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }, }; static bool rockchip_hdptx_phy_is_accissible_reg(struct device *dev, @@ -1166,8 +1145,9 @@ static int hdptx_ropll_cmn_config(struct rockchip_hdptx_phy *hdptx, unsigned lon { int bus_width = phy_get_bus_width(hdptx->phy); u8 color_depth = (bus_width & COLOR_DEPTH_MASK) ? 1 : 0; - struct ropll_config *cfg = ropll_tmds_cfg; + struct ropll_config *cfg; struct ropll_config rc = {0}; + u8 i; dev_info(hdptx->dev, "%s bus_width:%x rate:%lu\n", __func__, bus_width, bit_rate); hdptx->rate = bit_rate * 100; @@ -1175,17 +1155,19 @@ static int hdptx_ropll_cmn_config(struct rockchip_hdptx_phy *hdptx, unsigned lon if (color_depth) bit_rate = bit_rate * 10 / 8; - for (; cfg->bit_rate != ~0; cfg++) - if (bit_rate == cfg->bit_rate) + for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++) + if (bit_rate == ropll_tmds_cfg[i].bit_rate) break; - if (cfg->bit_rate == ~0) { + if (i == ARRAY_SIZE(ropll_tmds_cfg)) { if (hdptx_phy_clk_pll_calc(bit_rate, &rc)) { cfg = &rc; } else { dev_err(hdptx->dev, "%s can't find pll cfg\n", __func__); return -EINVAL; } + } else { + cfg = &ropll_tmds_cfg[i]; } dev_dbg(hdptx->dev, "mdiv=%u, sdiv=%u\n", @@ -1610,21 +1592,24 @@ static int hdptx_lcpll_cmn_config(struct rockchip_hdptx_phy *hdptx, unsigned lon { u32 bit_rate = rate & DATA_RATE_MASK; u8 color_depth = (rate & COLOR_DEPTH_MASK) ? 1 : 0; - struct lcpll_config *cfg = lcpll_cfg; + struct lcpll_config *cfg; + u8 i; dev_info(hdptx->dev, "%s rate:%lu\n", __func__, rate); hdptx->rate = bit_rate * 100; - for (; cfg->bit_rate != ~0; cfg++) - if (bit_rate == cfg->bit_rate) + for (i = 0; i < ARRAY_SIZE(lcpll_cfg); i++) + if (bit_rate == lcpll_cfg[i].bit_rate) break; - if (cfg->bit_rate == ~0) { + if (i == ARRAY_SIZE(lcpll_cfg)) { dev_err(hdptx->dev, "can't find frl rate, phy pll init failed\n"); return -EINVAL; } + cfg = &lcpll_cfg[i]; + hdptx_pre_power_up(hdptx); hdptx_grf_write(hdptx, GRF_HDPTX_CON0, LC_REF_CLK_SEL << 16); @@ -2029,11 +2014,53 @@ static void rockchip_hdptx_phy_runtime_disable(void *data) #define PLL_REF_CLK 24000000ULL +/* + * pll frequency in frl mode is calculated differently from that in tmds + * mode and is different from the actual frl frequency. So use register + * configuration to confirm the current frl frequency. + */ +static bool hdptx_frl_pll_cfg_equal(struct rockchip_hdptx_phy *hdptx, struct lcpll_config *cfg) +{ + u8 mdiv, sdiv, sdm_num, sdm_deno, sdc_n; + bool sdm_num_sign; + + mdiv = hdptx_read(hdptx, CMN_REG0020); + sdiv = hdptx_read(hdptx, CMN_REG0023) & 0xf; + sdm_num_sign = hdptx_read(hdptx, CMN_REG002B); + sdm_num = hdptx_read(hdptx, CMN_REG002C); + sdm_deno = hdptx_read(hdptx, CMN_REG002A); + sdc_n = (hdptx_read(hdptx, CMN_REG002D) & LCPLL_SDC_N_MASK) >> 1; + + if (cfg->pms_mdiv == mdiv && cfg->pms_sdiv == sdiv && cfg->sdm_num_sign == sdm_num_sign && + cfg->sdm_num == sdm_num && cfg->sdm_deno == sdm_deno && cfg->sdc_n == sdc_n) + return true; + + return false; +} + static unsigned long hdptx_cal_current_rate(struct rockchip_hdptx_phy *hdptx) { u8 mdiv, sdiv, sdm_num, sdm_deno, sdc_n, sdc_num, sdc_deno; u64 fout, sdm; bool sdm_en, sdm_num_sign; + struct lcpll_config *cfg; + u8 i; + + /* frl mode phy pll clk will not be used */ + if (hdptx_read(hdptx, CMN_REG0008) & LCPLL_LCVCO_MODE_EN_MASK) { + for (i = 0; i < ARRAY_SIZE(lcpll_cfg); i++) { + cfg = &lcpll_cfg[i]; + if (hdptx_frl_pll_cfg_equal(hdptx, cfg)) + break; + } + + if (i == ARRAY_SIZE(lcpll_cfg)) { + dev_err(hdptx->dev, "can't find frl rate, phy pll init failed\n"); + return -EINVAL; + } + + return cfg->bit_rate * 100; + } mdiv = hdptx_read(hdptx, CMN_REG0051); sdm_en = hdptx_read(hdptx, CMN_REG005E) & ROPLL_SDM_EN_MASK; @@ -2080,17 +2107,17 @@ static unsigned long hdptx_phy_clk_recalc_rate(struct clk_hw *hw, static long hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { - struct ropll_config *cfg = ropll_tmds_cfg; u32 bit_rate = rate / 100; + u8 i; if (rate > HDMI20_MAX_RATE) return rate; - for (; cfg->bit_rate != ~0; cfg++) - if (bit_rate == cfg->bit_rate) + for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++) + if (bit_rate == ropll_tmds_cfg[i].bit_rate) break; - if (cfg->bit_rate == ~0 && !hdptx_phy_clk_pll_calc(bit_rate, NULL)) + if (i == ARRAY_SIZE(ropll_tmds_cfg) && !hdptx_phy_clk_pll_calc(bit_rate, NULL)) return -EINVAL; return rate;