[PATCH] ASoC: fsl_spdif: keep all TxClk sources by txclk array
From: Viorel Suman viorel.suman@nxp.com
Use txclk array to keep all TxClk sources instead of keeping clocks per rate - need to do this in order to avoid multiple prepare_enable/disable_unprepare of the same clock during suspend/resume.
Signed-off-by: Viorel Suman viorel.suman@nxp.com Signed-off-by: Shengjiu Wang shengjiu.wang@nxp.com --- sound/soc/fsl/fsl_spdif.c | 41 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 21 deletions(-)
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 57c41b2f7d17..e0acce6b2213 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -125,7 +125,7 @@ struct fsl_spdif_priv { u16 sysclk_df[SPDIF_TXRATE_MAX]; u8 txclk_src[SPDIF_TXRATE_MAX]; u8 rxclk_src; - struct clk *txclk[SPDIF_TXRATE_MAX]; + struct clk *txclk[STC_TXCLK_SRC_MAX]; struct clk *rxclk; struct clk *coreclk; struct clk *sysclk; @@ -526,7 +526,7 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream, goto clk_set_bypass;
/* The S/PDIF block needs a clock of 64 * fs * txclk_df */ - ret = clk_set_rate(spdif_priv->txclk[rate], + ret = clk_set_rate(spdif_priv->txclk[clk], 64 * sample_rate * txclk_df); if (ret) { dev_err(&pdev->dev, "failed to set tx clock rate\n"); @@ -537,7 +537,7 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream, dev_dbg(&pdev->dev, "expected clock rate = %d\n", (64 * sample_rate * txclk_df * sysclk_df)); dev_dbg(&pdev->dev, "actual clock rate = %ld\n", - clk_get_rate(spdif_priv->txclk[rate])); + clk_get_rate(spdif_priv->txclk[clk]));
/* set fs field in consumer channel status */ spdif_set_cstatus(ctrl, IEC958_AES3_CON_FS, csfs); @@ -1376,12 +1376,10 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, struct device *dev = &pdev->dev; u64 savesub = 100000, ret; struct clk *clk; - char tmp[16]; int i;
for (i = 0; i < STC_TXCLK_SRC_MAX; i++) { - sprintf(tmp, "rxtx%d", i); - clk = devm_clk_get(dev, tmp); + clk = spdif_priv->txclk[i]; if (IS_ERR(clk)) { dev_err(dev, "no rxtx%d clock in devicetree\n", i); return PTR_ERR(clk); @@ -1395,7 +1393,6 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, continue;
savesub = ret; - spdif_priv->txclk[index] = clk; spdif_priv->txclk_src[index] = i;
/* To quick catch a divisor, we allow a 0.1% deviation */ @@ -1407,7 +1404,7 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, spdif_priv->txclk_src[index], rate[index]); dev_dbg(dev, "use txclk df %d for %dHz sample rate\n", spdif_priv->txclk_df[index], rate[index]); - if (clk_is_match(spdif_priv->txclk[index], spdif_priv->sysclk)) + if (clk_is_match(spdif_priv->txclk[spdif_priv->txclk_src[index]], spdif_priv->sysclk)) dev_dbg(dev, "use sysclk df %d for %dHz sample rate\n", spdif_priv->sysclk_df[index], rate[index]); dev_dbg(dev, "the best rate for %dHz sample rate is %dHz\n", @@ -1423,6 +1420,7 @@ static int fsl_spdif_probe(struct platform_device *pdev) struct resource *res; void __iomem *regs; int irq, ret, i; + char tmp[16];
spdif_priv = devm_kzalloc(&pdev->dev, sizeof(*spdif_priv), GFP_KERNEL); if (!spdif_priv) @@ -1462,8 +1460,17 @@ static int fsl_spdif_probe(struct platform_device *pdev) } }
+ for (i = 0; i < STC_TXCLK_SRC_MAX; i++) { + sprintf(tmp, "rxtx%d", i); + spdif_priv->txclk[i] = devm_clk_get(&pdev->dev, tmp); + if (IS_ERR(spdif_priv->txclk[i])) { + dev_err(&pdev->dev, "no rxtx%d clock in devicetree\n", i); + return PTR_ERR(spdif_priv->txclk[i]); + } + } + /* Get system clock for rx clock rate calculation */ - spdif_priv->sysclk = devm_clk_get(&pdev->dev, "rxtx5"); + spdif_priv->sysclk = spdif_priv->txclk[5]; if (IS_ERR(spdif_priv->sysclk)) { dev_err(&pdev->dev, "no sys clock (rxtx5) in devicetree\n"); return PTR_ERR(spdif_priv->sysclk); @@ -1481,7 +1488,7 @@ static int fsl_spdif_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "no spba clock in devicetree\n");
/* Select clock source for rx/tx clock */ - spdif_priv->rxclk = devm_clk_get(&pdev->dev, "rxtx1"); + spdif_priv->rxclk = spdif_priv->txclk[1]; if (IS_ERR(spdif_priv->rxclk)) { dev_err(&pdev->dev, "no rxtx1 clock in devicetree\n"); return PTR_ERR(spdif_priv->rxclk); @@ -1562,9 +1569,7 @@ static int fsl_spdif_runtime_suspend(struct device *dev) &spdif_priv->regcache_srpc); regcache_cache_only(spdif_priv->regmap, true);
- clk_disable_unprepare(spdif_priv->rxclk); - - for (i = 0; i < SPDIF_TXRATE_MAX; i++) + for (i = 0; i < STC_TXCLK_SRC_MAX; i++) clk_disable_unprepare(spdif_priv->txclk[i]);
if (!IS_ERR(spdif_priv->spbaclk)) @@ -1594,16 +1599,12 @@ static int fsl_spdif_runtime_resume(struct device *dev) } }
- for (i = 0; i < SPDIF_TXRATE_MAX; i++) { + for (i = 0; i < STC_TXCLK_SRC_MAX; i++) { ret = clk_prepare_enable(spdif_priv->txclk[i]); if (ret) goto disable_tx_clk; }
- ret = clk_prepare_enable(spdif_priv->rxclk); - if (ret) - goto disable_tx_clk; - regcache_cache_only(spdif_priv->regmap, false); regcache_mark_dirty(spdif_priv->regmap);
@@ -1613,12 +1614,10 @@ static int fsl_spdif_runtime_resume(struct device *dev)
ret = regcache_sync(spdif_priv->regmap); if (ret) - goto disable_rx_clk; + goto disable_tx_clk;
return 0;
-disable_rx_clk: - clk_disable_unprepare(spdif_priv->rxclk); disable_tx_clk: for (i--; i >= 0; i--) clk_disable_unprepare(spdif_priv->txclk[i]);
On Wed, 9 Mar 2022 17:18:43 +0800, Shengjiu Wang wrote:
From: Viorel Suman viorel.suman@nxp.com
Use txclk array to keep all TxClk sources instead of keeping clocks per rate - need to do this in order to avoid multiple prepare_enable/disable_unprepare of the same clock during suspend/resume.
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/1] ASoC: fsl_spdif: keep all TxClk sources by txclk array commit: 5bd998af5b69cf21fd4db5eaf7e9db85a4a35295
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (2)
-
Mark Brown
-
Shengjiu Wang