Commit 3481fc04 authored by Cristian Ciocaltea's avatar Cristian Ciocaltea Committed by Vinod Koul
Browse files

phy: rockchip: samsung-hdptx: Compute clk rate from PLL config



Improve ->recalc_rate() callback of hdptx_phy_clk_ops to calculate the
initial clock rate based on the actual PHY PLL configuration as
retrieved from the related hardware registers.

Signed-off-by: default avatarCristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://patch.msgid.link/20260113-phy-hdptx-frl-v6-7-8d5f97419c0b@collabora.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent df74a964
Loading
Loading
Loading
Loading
+90 −1
Original line number Diff line number Diff line
@@ -1818,12 +1818,101 @@ static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
	rk_hdptx_phy_consumer_put(hdptx, true);
}

#define PLL_REF_CLK 24000000ULL

static u64 rk_hdptx_phy_clk_calc_rate_from_pll_cfg(struct rk_hdptx_phy *hdptx)
{
	struct ropll_config ropll_hw;
	u64 fout, sdm;
	u32 mode, val;
	int ret;

	ret = regmap_read(hdptx->regmap, CMN_REG(0008), &mode);
	if (ret)
		return 0;

	if (mode & LCPLL_LCVCO_MODE_EN_MASK)
		return 0;

	ret = regmap_read(hdptx->regmap, CMN_REG(0051), &val);
	if (ret)
		return 0;
	ropll_hw.pms_mdiv = val;

	ret = regmap_read(hdptx->regmap, CMN_REG(005E), &val);
	if (ret)
		return 0;
	ropll_hw.sdm_en = val & ROPLL_SDM_EN_MASK;

	ret = regmap_read(hdptx->regmap, CMN_REG(0064), &val);
	if (ret)
		return 0;
	ropll_hw.sdm_num_sign = val & ROPLL_SDM_NUM_SIGN_RBR_MASK;

	ret = regmap_read(hdptx->regmap, CMN_REG(0065), &val);
	if (ret)
		return 0;
	ropll_hw.sdm_num = val;

	ret = regmap_read(hdptx->regmap, CMN_REG(0060), &val);
	if (ret)
		return 0;
	ropll_hw.sdm_deno = val;

	ret = regmap_read(hdptx->regmap, CMN_REG(0069), &val);
	if (ret)
		return 0;
	ropll_hw.sdc_n = (val & ROPLL_SDC_N_RBR_MASK) + 3;

	ret = regmap_read(hdptx->regmap, CMN_REG(006c), &val);
	if (ret)
		return 0;
	ropll_hw.sdc_num = val;

	ret = regmap_read(hdptx->regmap, CMN_REG(0070), &val);
	if (ret)
		return 0;
	ropll_hw.sdc_deno = val;

	ret = regmap_read(hdptx->regmap, CMN_REG(0086), &val);
	if (ret)
		return 0;
	ropll_hw.pms_sdiv = ((val & PLL_PCG_POSTDIV_SEL_MASK) >> 4) + 1;

	fout = PLL_REF_CLK * ropll_hw.pms_mdiv;
	if (ropll_hw.sdm_en) {
		sdm = div_u64(PLL_REF_CLK * ropll_hw.sdc_deno *
			      ropll_hw.pms_mdiv * ropll_hw.sdm_num,
			      16 * ropll_hw.sdm_deno *
			      (ropll_hw.sdc_deno * ropll_hw.sdc_n - ropll_hw.sdc_num));

		if (ropll_hw.sdm_num_sign)
			fout = fout - sdm;
		else
			fout = fout + sdm;
	}

	return div_u64(fout * 2, ropll_hw.pms_sdiv * 10);
}

static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
						  unsigned long parent_rate)
{
	struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
	u32 status;
	u64 rate;
	int ret;

	if (hdptx->hw_rate)
		return hdptx->hw_rate;

	ret = regmap_read(hdptx->grf, GRF_HDPTX_CON0, &status);
	if (ret || !(status & HDPTX_I_PLL_EN))
		return 0;

	rate = rk_hdptx_phy_clk_calc_rate_from_pll_cfg(hdptx);

	return DIV_ROUND_CLOSEST_ULL(rate * 8, hdptx->hdmi_cfg.bpc);
}

static int rk_hdptx_phy_clk_determine_rate(struct clk_hw *hw,