phy: freescale: fsl-samsung-hdmi: initialize default rate

The HDMI PHY clock reports 74.25 MHz when cur_cfg is unset, but does
not establish that rate in hardware. The common clock framework caches
the reported rate when registering the clock and skips a first
clk_set_rate(74250000) request because the rate appears unchanged.

Consequently, a display whose initial mode uses a 74.25 MHz pixel clock
can leave the PHY with its bootloader register state and receive no
TMDS signal. Requesting another rate first avoids the issue because the
set_rate callback configures the PHY.

Program the 74.25 MHz table entry with the reference clock enabled
before registering the clock provider. recalc_rate can then report the
configured rate, and a skipped first rate change is safe. Also enable
the reference clock when restoring that configuration on resume.

Fixes: 6ad082bee9 ("phy: freescale: add Samsung HDMI PHY")
Signed-off-by: Aristo Chen <aristo.chen@canonical.com>
Link: https://patch.msgid.link/20260903054811.9720-1-aristo.chen@canonical.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Aristo Chen 2026-09-03 05:47:58 +00:00 committed by Vinod Koul
parent 88498cfc3c
commit c01ccf91b2

View File

@ -44,6 +44,8 @@
#define MHZ (1000UL * 1000UL)
#endif
#define PHY_DEFAULT_RATE 74250000
#define PHY_PLL_DIV_REGS_NUM 7
struct phy_config {
@ -489,17 +491,6 @@ static int fsl_samsung_hdmi_phy_configure(struct fsl_samsung_hdmi_phy *phy,
return ret;
}
static unsigned long phy_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw);
if (!phy->cur_cfg)
return 74250000;
return phy->cur_cfg->pixclk;
}
/* Helper function to lookup the available fractional-divider rate */
static const struct phy_config *fsl_samsung_hdmi_phy_lookup_rate(unsigned long rate)
{
@ -520,6 +511,14 @@ static const struct phy_config *fsl_samsung_hdmi_phy_lookup_rate(unsigned long r
&phy_pll_cfg[i] : &phy_pll_cfg[i+1]);
}
static unsigned long phy_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw);
return phy->cur_cfg->pixclk;
}
static void fsl_samsung_hdmi_calculate_phy(struct phy_config *cal_phy, unsigned long rate,
u8 p, u16 m, u8 s)
{
@ -640,6 +639,7 @@ static int phy_clk_register(struct fsl_samsung_hdmi_phy *phy)
static int fsl_samsung_hdmi_phy_probe(struct platform_device *pdev)
{
const struct phy_config *default_cfg;
struct fsl_samsung_hdmi_phy *phy;
int ret;
@ -664,6 +664,23 @@ static int fsl_samsung_hdmi_phy_probe(struct platform_device *pdev)
return dev_err_probe(phy->dev, PTR_ERR(phy->refclk),
"failed to get ref clk\n");
/*
* Establish the rate reported by recalc_rate() before registering the
* clock. Otherwise CCF may skip the first set_rate() when it requests
* the assumed default rate, leaving the PHY unconfigured.
*/
ret = clk_prepare_enable(phy->refclk);
if (ret)
return dev_err_probe(phy->dev, ret,
"failed to enable ref clk\n");
default_cfg = fsl_samsung_hdmi_phy_lookup_rate(PHY_DEFAULT_RATE);
ret = fsl_samsung_hdmi_phy_configure(phy, default_cfg);
clk_disable_unprepare(phy->refclk);
if (ret)
return dev_err_probe(phy->dev, ret,
"failed to configure default rate\n");
pm_runtime_get_noresume(phy->dev);
pm_runtime_set_active(phy->dev);
pm_runtime_enable(phy->dev);
@ -702,7 +719,7 @@ static int __maybe_unused fsl_samsung_hdmi_phy_suspend(struct device *dev)
static int __maybe_unused fsl_samsung_hdmi_phy_resume(struct device *dev)
{
struct fsl_samsung_hdmi_phy *phy = dev_get_drvdata(dev);
int ret = 0;
int ret;
ret = clk_prepare_enable(phy->apbclk);
if (ret) {
@ -710,11 +727,23 @@ static int __maybe_unused fsl_samsung_hdmi_phy_resume(struct device *dev)
return ret;
}
if (phy->cur_cfg)
ret = fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
if (!phy->cur_cfg)
return 0;
ret = clk_prepare_enable(phy->refclk);
if (ret) {
dev_err(phy->dev, "failed to enable ref clk\n");
goto disable_apbclk;
}
ret = fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
clk_disable_unprepare(phy->refclk);
if (!ret)
return 0;
disable_apbclk:
clk_disable_unprepare(phy->apbclk);
return ret;
}
static DEFINE_RUNTIME_DEV_PM_OPS(fsl_samsung_hdmi_phy_pm_ops,