This driver unconditionally set the rate of DSP system clock to 250MHz, that on A1 SoC family causes reconfiguring of 'hifi_pll' clock to some rate, that is multiple to 250MHz.
Further, when playback is activating 'hifi_pll' would be reconfigured to another rate to produce audio clock like 12288000Hz. Both these rates can't coexist on same parent.
To avoid the fight for 'hifi_pll' clock allow PDM controller to configure its maximum sysrate through device tree. It will allow to inherit 'sysclk' from another clock (i.e. 'fclk_div2') and isolate 'hifi_pll' from PDM influence.
Signed-off-by: Jan Dakinevich jan.dakinevich@salutedevices.com --- sound/soc/meson/axg-pdm.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/sound/soc/meson/axg-pdm.c b/sound/soc/meson/axg-pdm.c index d59050914d3c..a132444a51fb 100644 --- a/sound/soc/meson/axg-pdm.c +++ b/sound/soc/meson/axg-pdm.c @@ -94,6 +94,7 @@ struct axg_pdm { struct clk *dclk; struct clk *sysclk; struct clk *pclk; + u32 sys_rate; };
static void axg_pdm_enable(struct regmap *map) @@ -172,10 +173,10 @@ static int axg_pdm_set_sysclk(struct axg_pdm *priv, unsigned int os, * the requested sample rate. In this case, the sample pointer * counter could overflow so set a lower system clock rate */ - if (sys_rate < priv->cfg->sys_rate) + if (sys_rate < priv->sys_rate) return clk_set_rate(priv->sysclk, sys_rate);
- return clk_set_rate(priv->sysclk, priv->cfg->sys_rate); + return clk_set_rate(priv->sysclk, priv->sys_rate); }
static int axg_pdm_set_sample_pointer(struct axg_pdm *priv) @@ -386,7 +387,7 @@ static int axg_pdm_dai_probe(struct snd_soc_dai *dai) * sysclk must be set and enabled as well to access the pdm registers * Accessing the register w/o it will give a bus error. */ - ret = clk_set_rate(priv->sysclk, priv->cfg->sys_rate); + ret = clk_set_rate(priv->sysclk, priv->sys_rate); if (ret) { dev_err(dai->dev, "setting sysclk failed\n"); goto err_pclk; @@ -623,6 +624,9 @@ static int axg_pdm_probe(struct platform_device *pdev) if (IS_ERR(priv->sysclk)) return dev_err_probe(dev, PTR_ERR(priv->sysclk), "failed to get dclk\n");
+ if (device_property_read_u32(dev, "sysrate", &priv->sys_rate)) + priv->sys_rate = priv->cfg->sys_rate; + return devm_snd_soc_register_component(dev, &axg_pdm_component_drv, &axg_pdm_dai_drv, 1); }