mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
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:
parent
88498cfc3c
commit
c01ccf91b2
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user