Commit 34dcdebe authored by Shengjiu Wang's avatar Shengjiu Wang Committed by Mark Brown

ASoC: fsl_spdif: Add support for PLL switch at runtime.

i.MX8MQ/MN/MM/MP platforms typically have 2 AUDIO PLLs being
configured to handle 8kHz and 11kHz series audio rates.

The patch implements the functionality to select at runtime
the appropriate AUDIO PLL as function of audio file rate.
As the clock parent may be changed, need to probe txclk
according to sample rate again.
Signed-off-by: default avatarViorel Suman <viorel.suman@nxp.com>
Signed-off-by: default avatarShengjiu Wang <shengjiu.wang@nxp.com>
Link: https://lore.kernel.org/r/1656667961-1799-3-git-send-email-shengjiu.wang@nxp.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 7bad8125
...@@ -59,6 +59,7 @@ config SND_SOC_FSL_SPDIF ...@@ -59,6 +59,7 @@ config SND_SOC_FSL_SPDIF
select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n
select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && (MXC_TZIC || MXC_AVIC) select SND_SOC_IMX_PCM_FIQ if SND_IMX_SOC != n && (MXC_TZIC || MXC_AVIC)
select BITREVERSE select BITREVERSE
select SND_SOC_FSL_UTILS
help help
Say Y if you want to add Sony/Philips Digital Interface (SPDIF) Say Y if you want to add Sony/Philips Digital Interface (SPDIF)
support for the Freescale CPUs. support for the Freescale CPUs.
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <sound/soc.h> #include <sound/soc.h>
#include "fsl_spdif.h" #include "fsl_spdif.h"
#include "fsl_utils.h"
#include "imx-pcm.h" #include "imx-pcm.h"
#define FSL_SPDIF_TXFIFO_WML 0x8 #define FSL_SPDIF_TXFIFO_WML 0x8
...@@ -114,6 +115,8 @@ struct spdif_mixer_control { ...@@ -114,6 +115,8 @@ struct spdif_mixer_control {
* @dma_params_rx: DMA parameters for receive channel * @dma_params_rx: DMA parameters for receive channel
* @regcache_srpc: regcache for SRPC * @regcache_srpc: regcache for SRPC
* @bypass: status of bypass input to output * @bypass: status of bypass input to output
* @pll8k_clk: PLL clock for the rate of multiply of 8kHz
* @pll11k_clk: PLL clock for the rate of multiply of 11kHz
*/ */
struct fsl_spdif_priv { struct fsl_spdif_priv {
const struct fsl_spdif_soc_data *soc; const struct fsl_spdif_soc_data *soc;
...@@ -137,6 +140,8 @@ struct fsl_spdif_priv { ...@@ -137,6 +140,8 @@ struct fsl_spdif_priv {
/* regcache for SRPC */ /* regcache for SRPC */
u32 regcache_srpc; u32 regcache_srpc;
bool bypass; bool bypass;
struct clk *pll8k_clk;
struct clk *pll11k_clk;
}; };
static struct fsl_spdif_soc_data fsl_spdif_vf610 = { static struct fsl_spdif_soc_data fsl_spdif_vf610 = {
...@@ -480,6 +485,8 @@ static int spdif_set_rx_clksrc(struct fsl_spdif_priv *spdif_priv, ...@@ -480,6 +485,8 @@ static int spdif_set_rx_clksrc(struct fsl_spdif_priv *spdif_priv,
return 0; return 0;
} }
static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, enum spdif_txrate index);
static int spdif_set_sample_rate(struct snd_pcm_substream *substream, static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
int sample_rate) int sample_rate)
{ {
...@@ -528,6 +535,10 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream, ...@@ -528,6 +535,10 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
ret = fsl_spdif_probe_txclk(spdif_priv, rate);
if (ret)
return ret;
clk = spdif_priv->txclk_src[rate]; clk = spdif_priv->txclk_src[rate];
if (clk >= STC_TXCLK_SRC_MAX) { if (clk >= STC_TXCLK_SRC_MAX) {
dev_err(&pdev->dev, "tx clock source is out of range\n"); dev_err(&pdev->dev, "tx clock source is out of range\n");
...@@ -647,6 +658,29 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream *substream, ...@@ -647,6 +658,29 @@ static void fsl_spdif_shutdown(struct snd_pcm_substream *substream,
} }
} }
static int spdif_reparent_rootclk(struct fsl_spdif_priv *spdif_priv, unsigned int sample_rate)
{
struct platform_device *pdev = spdif_priv->pdev;
struct clk *clk;
int ret;
/* Reparent clock if required condition is true */
if (!fsl_spdif_can_set_clk_rate(spdif_priv, STC_TXCLK_SPDIF_ROOT))
return 0;
/* Get root clock */
clk = spdif_priv->txclk[STC_TXCLK_SPDIF_ROOT];
/* Disable clock first, for it was enabled by pm_runtime */
clk_disable_unprepare(clk);
fsl_asoc_reparent_pll_clocks(&pdev->dev, clk, spdif_priv->pll8k_clk,
spdif_priv->pll11k_clk, sample_rate);
ret = clk_prepare_enable(clk);
if (ret)
return ret;
return 0;
}
static int fsl_spdif_hw_params(struct snd_pcm_substream *substream, static int fsl_spdif_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
...@@ -659,6 +693,13 @@ static int fsl_spdif_hw_params(struct snd_pcm_substream *substream, ...@@ -659,6 +693,13 @@ static int fsl_spdif_hw_params(struct snd_pcm_substream *substream,
int ret = 0; int ret = 0;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ret = spdif_reparent_rootclk(spdif_priv, sample_rate);
if (ret) {
dev_err(&pdev->dev, "%s: reparent root clk failed: %d\n",
__func__, sample_rate);
return ret;
}
ret = spdif_set_sample_rate(substream, sample_rate); ret = spdif_set_sample_rate(substream, sample_rate);
if (ret) { if (ret) {
dev_err(&pdev->dev, "%s: set sample rate failed: %d\n", dev_err(&pdev->dev, "%s: set sample rate failed: %d\n",
...@@ -1548,11 +1589,8 @@ static int fsl_spdif_probe(struct platform_device *pdev) ...@@ -1548,11 +1589,8 @@ static int fsl_spdif_probe(struct platform_device *pdev)
} }
spdif_priv->rxclk_src = DEFAULT_RXCLK_SRC; spdif_priv->rxclk_src = DEFAULT_RXCLK_SRC;
for (i = 0; i < SPDIF_TXRATE_MAX; i++) { fsl_asoc_get_pll_clocks(&pdev->dev, &spdif_priv->pll8k_clk,
ret = fsl_spdif_probe_txclk(spdif_priv, i); &spdif_priv->pll11k_clk);
if (ret)
return ret;
}
/* Initial spinlock for control data */ /* Initial spinlock for control data */
ctrl = &spdif_priv->fsl_spdif_control; ctrl = &spdif_priv->fsl_spdif_control;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment