From 0e95e089821bdc833ecbf8d2d1bf0e170a621c38 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Wed, 13 Jul 2022 20:49:30 +0800 Subject: [PATCH] phy: rockchip-samsung-hdptx-hdmi: Add function of enabling PLL independently in FRL mode The phy pll must be enabled before access hdmi controller registers. To support config hdmi controller registers before phy output is enabled, pll must be enabled separately in both TMDS and FRL mode. Signed-off-by: Algea Cao Change-Id: I1860c8a333e37db0c3406a0487ec916d5fd94976 --- .../phy-rockchip-samsung-hdptx-hdmi.c | 60 ++++++++----------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx-hdmi.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx-hdmi.c index 7ae0510124de..7f39af64397f 100644 --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx-hdmi.c +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx-hdmi.c @@ -917,6 +917,8 @@ static int hdptx_post_enable_lane(struct rockchip_hdptx_phy *hdptx) HDPTX_I_BGR_EN; hdptx_grf_write(hdptx, GRF_HDPTX_CON0, val); + hdptx_write(hdptx, LNTOP_REG0207, 0x0f); + for (i = 0; i < 50; i++) { val = hdptx_grf_read(hdptx, GRF_HDPTX_STATUS); @@ -1395,14 +1397,6 @@ static int hdptx_ropll_tmds_mode_config(struct rockchip_hdptx_phy *hdptx, u32 ra { u32 bit_rate = rate & DATA_RATE_MASK; - if (!(hdptx_grf_read(hdptx, GRF_HDPTX_STATUS) & HDPTX_O_PLL_LOCK_DONE)) { - int ret; - - ret = hdptx_ropll_cmn_config(hdptx, bit_rate); - if (ret) - return ret; - } - hdptx_write(hdptx, SB_REG0114, 0x00); hdptx_write(hdptx, SB_REG0115, 0x00); hdptx_write(hdptx, SB_REG0116, 0x00); @@ -1426,7 +1420,6 @@ static int hdptx_ropll_tmds_mode_config(struct rockchip_hdptx_phy *hdptx, u32 ra } hdptx_write(hdptx, LNTOP_REG0206, 0x07); - hdptx_write(hdptx, LNTOP_REG0207, 0x0f); hdptx_write(hdptx, LANE_REG0303, 0x0c); hdptx_write(hdptx, LANE_REG0307, 0x20); hdptx_write(hdptx, LANE_REG030A, 0x17); @@ -1733,19 +1726,24 @@ static int hdptx_ropll_frl_mode_config(struct rockchip_hdptx_phy *hdptx, u32 rat return hdptx_post_power_up(hdptx); } -static int hdptx_lcpll_frl_mode_config(struct rockchip_hdptx_phy *hdptx, u32 rate) +static int hdptx_lcpll_cmn_config(struct rockchip_hdptx_phy *hdptx, unsigned long rate) { u32 bit_rate = rate & DATA_RATE_MASK; u8 color_depth = (rate & COLOR_DEPTH_MASK) ? 1 : 0; struct lcpll_config *cfg = lcpll_cfg; + 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) break; - if (cfg->bit_rate == ~0) + if (cfg->bit_rate == ~0) { + dev_err(hdptx->dev, "can't find frl rate, phy pll init failed\n"); return -EINVAL; + } hdptx_pre_power_up(hdptx); @@ -1880,6 +1878,12 @@ static int hdptx_lcpll_frl_mode_config(struct rockchip_hdptx_phy *hdptx, u32 rat hdptx_write(hdptx, CMN_REG0099, 0x00); hdptx_write(hdptx, CMN_REG009A, 0x11); hdptx_write(hdptx, CMN_REG009B, 0x10); + + return hdptx_post_enable_pll(hdptx); +} + +static int hdptx_lcpll_frl_mode_config(struct rockchip_hdptx_phy *hdptx, u32 rate) +{ hdptx_write(hdptx, SB_REG0114, 0x00); hdptx_write(hdptx, SB_REG0115, 0x00); hdptx_write(hdptx, SB_REG0116, 0x00); @@ -1891,7 +1895,6 @@ static int hdptx_lcpll_frl_mode_config(struct rockchip_hdptx_phy *hdptx, u32 rat hdptx_write(hdptx, LNTOP_REG0204, 0xff); hdptx_write(hdptx, LNTOP_REG0205, 0xff); hdptx_write(hdptx, LNTOP_REG0206, 0x05); - hdptx_write(hdptx, LNTOP_REG0207, 0x0f); hdptx_write(hdptx, LANE_REG0303, 0x0c); hdptx_write(hdptx, LANE_REG0307, 0x20); hdptx_write(hdptx, LANE_REG030A, 0x17); @@ -1974,7 +1977,7 @@ static int hdptx_lcpll_frl_mode_config(struct rockchip_hdptx_phy *hdptx, u32 rat if (hdptx->earc_en) hdptx_earc_config(hdptx); - return hdptx_post_power_up(hdptx); + return hdptx_post_enable_lane(hdptx); } static int rockchip_hdptx_phy_power_on(struct phy *phy) @@ -1982,15 +1985,6 @@ static int rockchip_hdptx_phy_power_on(struct phy *phy) struct rockchip_hdptx_phy *hdptx = phy_get_drvdata(phy); int bus_width = phy_get_bus_width(hdptx->phy); int bit_rate = bus_width & DATA_RATE_MASK; - int ret; - - if (!hdptx->count) { - ret = clk_bulk_enable(hdptx->nr_clks, hdptx->clks); - if (ret) { - dev_err(hdptx->dev, "failed to enable clocks\n"); - return ret; - } - } dev_info(hdptx->dev, "bus_width:0x%x,bit_rate:%d\n", bus_width, bit_rate); if (bus_width & HDMI_EARC_MASK) @@ -2011,14 +2005,8 @@ static int rockchip_hdptx_phy_power_off(struct phy *phy) { struct rockchip_hdptx_phy *hdptx = phy_get_drvdata(phy); - if (hdptx->count) - return 0; - - if (!(hdptx_grf_read(hdptx, GRF_HDPTX_STATUS) & HDPTX_O_PLL_LOCK_DONE)) - return 0; - - hdptx_phy_disable(hdptx); - clk_bulk_disable(hdptx->nr_clks, hdptx->clks); + /* disable phy lane output */ + hdptx_write(hdptx, LNTOP_REG0207, 0); return 0; } @@ -2079,9 +2067,10 @@ static int hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate, if (hdptx_grf_read(hdptx, GRF_HDPTX_STATUS) & HDPTX_O_PLL_LOCK_DONE) hdptx_phy_disable(hdptx); - rate = rate / 100; - - return hdptx_ropll_cmn_config(hdptx, rate); + if (rate > HDMI20_MAX_RATE) + return hdptx_lcpll_cmn_config(hdptx, rate / 100); + else + return hdptx_ropll_cmn_config(hdptx, rate / 100); } static int hdptx_phy_clk_enable(struct clk_hw *hw) @@ -2101,7 +2090,10 @@ static int hdptx_phy_clk_enable(struct clk_hw *hw) } if (hdptx->rate) { - ret = hdptx_ropll_cmn_config(hdptx, hdptx->rate / 100); + if (hdptx->rate > HDMI20_MAX_RATE) + ret = hdptx_lcpll_cmn_config(hdptx, hdptx->rate / 100); + else + ret = hdptx_ropll_cmn_config(hdptx, hdptx->rate / 100); if (ret < 0) { dev_err(hdptx->dev, "hdmi phy pll init failed\n"); return ret;