mirror of
https://github.com/torvalds/linux
synced 2024-10-22 11:19:17 +00:00
ASoC: fsl-ssi: Move fsl_ssi_set_dai_sysclk above fsl_ssi_hw_params
fsl_ssi_set_dai_sysclk will be called from fsl_ssi_hw_params in the next patch. Move up to avoid forward declaration and to keep the next patch more readable. No functional change. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Markus Pargmann <mpa@pengutronix.de> Tested-By: Michael Grzeschik <mgr@pengutronix.de> Signed-off-by: Mark Brown <broonie@linaro.org>
This commit is contained in:
parent
504894799f
commit
ee9daad495
|
@ -518,6 +518,102 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fsl_ssi_set_dai_sysclk - configure Digital Audio Interface bit clock
|
||||||
|
*
|
||||||
|
* Note: This function can be only called when using SSI as DAI master
|
||||||
|
*
|
||||||
|
* Quick instruction for parameters:
|
||||||
|
* freq: Output BCLK frequency = samplerate * 32 (fixed) * channels
|
||||||
|
* dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK.
|
||||||
|
*/
|
||||||
|
static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
|
||||||
|
int clk_id, unsigned int freq, int dir)
|
||||||
|
{
|
||||||
|
struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
|
||||||
|
struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
|
||||||
|
int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
|
||||||
|
u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
|
||||||
|
unsigned long flags, clkrate, baudrate, tmprate;
|
||||||
|
u64 sub, savesub = 100000;
|
||||||
|
|
||||||
|
/* Don't apply it to any non-baudclk circumstance */
|
||||||
|
if (IS_ERR(ssi_private->baudclk))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* It should be already enough to divide clock by setting pm alone */
|
||||||
|
psr = 0;
|
||||||
|
div2 = 0;
|
||||||
|
|
||||||
|
factor = (div2 + 1) * (7 * psr + 1) * 2;
|
||||||
|
|
||||||
|
for (i = 0; i < 255; i++) {
|
||||||
|
/* The bclk rate must be smaller than 1/5 sysclk rate */
|
||||||
|
if (factor * (i + 1) < 5)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tmprate = freq * factor * (i + 2);
|
||||||
|
clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
|
||||||
|
|
||||||
|
do_div(clkrate, factor);
|
||||||
|
afreq = (u32)clkrate / (i + 1);
|
||||||
|
|
||||||
|
if (freq == afreq)
|
||||||
|
sub = 0;
|
||||||
|
else if (freq / afreq == 1)
|
||||||
|
sub = freq - afreq;
|
||||||
|
else if (afreq / freq == 1)
|
||||||
|
sub = afreq - freq;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Calculate the fraction */
|
||||||
|
sub *= 100000;
|
||||||
|
do_div(sub, freq);
|
||||||
|
|
||||||
|
if (sub < savesub) {
|
||||||
|
baudrate = tmprate;
|
||||||
|
savesub = sub;
|
||||||
|
pm = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We are lucky */
|
||||||
|
if (savesub == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No proper pm found if it is still remaining the initial value */
|
||||||
|
if (pm == 999) {
|
||||||
|
dev_err(cpu_dai->dev, "failed to handle the required sysclk\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stccr = CCSR_SSI_SxCCR_PM(pm + 1) | (div2 ? CCSR_SSI_SxCCR_DIV2 : 0) |
|
||||||
|
(psr ? CCSR_SSI_SxCCR_PSR : 0);
|
||||||
|
mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 |
|
||||||
|
CCSR_SSI_SxCCR_PSR;
|
||||||
|
|
||||||
|
if (dir == SND_SOC_CLOCK_OUT || synchronous)
|
||||||
|
write_ssi_mask(&ssi->stccr, mask, stccr);
|
||||||
|
else
|
||||||
|
write_ssi_mask(&ssi->srccr, mask, stccr);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
|
||||||
|
if (!ssi_private->baudclk_locked) {
|
||||||
|
ret = clk_set_rate(ssi_private->baudclk, baudrate);
|
||||||
|
if (ret) {
|
||||||
|
spin_unlock_irqrestore(&ssi_private->baudclk_lock,
|
||||||
|
flags);
|
||||||
|
dev_err(cpu_dai->dev, "failed to set baudclk rate\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
ssi_private->baudclk_locked = true;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fsl_ssi_hw_params - program the sample size
|
* fsl_ssi_hw_params - program the sample size
|
||||||
*
|
*
|
||||||
|
@ -720,100 +816,6 @@ static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* fsl_ssi_set_dai_sysclk - configure Digital Audio Interface bit clock
|
|
||||||
*
|
|
||||||
* Note: This function can be only called when using SSI as DAI master
|
|
||||||
*
|
|
||||||
* Quick instruction for parameters:
|
|
||||||
* freq: Output BCLK frequency = samplerate * 32 (fixed) * channels
|
|
||||||
* dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK.
|
|
||||||
*/
|
|
||||||
static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
|
|
||||||
int clk_id, unsigned int freq, int dir)
|
|
||||||
{
|
|
||||||
struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
|
|
||||||
struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
|
|
||||||
int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
|
|
||||||
u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
|
|
||||||
unsigned long flags, clkrate, baudrate, tmprate;
|
|
||||||
u64 sub, savesub = 100000;
|
|
||||||
|
|
||||||
/* Don't apply it to any non-baudclk circumstance */
|
|
||||||
if (IS_ERR(ssi_private->baudclk))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* It should be already enough to divide clock by setting pm alone */
|
|
||||||
psr = 0;
|
|
||||||
div2 = 0;
|
|
||||||
|
|
||||||
factor = (div2 + 1) * (7 * psr + 1) * 2;
|
|
||||||
|
|
||||||
for (i = 0; i < 255; i++) {
|
|
||||||
/* The bclk rate must be smaller than 1/5 sysclk rate */
|
|
||||||
if (factor * (i + 1) < 5)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
tmprate = freq * factor * (i + 2);
|
|
||||||
clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
|
|
||||||
|
|
||||||
do_div(clkrate, factor);
|
|
||||||
afreq = (u32)clkrate / (i + 1);
|
|
||||||
|
|
||||||
if (freq == afreq)
|
|
||||||
sub = 0;
|
|
||||||
else if (freq / afreq == 1)
|
|
||||||
sub = freq - afreq;
|
|
||||||
else if (afreq / freq == 1)
|
|
||||||
sub = afreq - freq;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Calculate the fraction */
|
|
||||||
sub *= 100000;
|
|
||||||
do_div(sub, freq);
|
|
||||||
|
|
||||||
if (sub < savesub) {
|
|
||||||
baudrate = tmprate;
|
|
||||||
savesub = sub;
|
|
||||||
pm = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We are lucky */
|
|
||||||
if (savesub == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No proper pm found if it is still remaining the initial value */
|
|
||||||
if (pm == 999) {
|
|
||||||
dev_err(cpu_dai->dev, "failed to handle the required sysclk\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
stccr = CCSR_SSI_SxCCR_PM(pm + 1) | (div2 ? CCSR_SSI_SxCCR_DIV2 : 0) |
|
|
||||||
(psr ? CCSR_SSI_SxCCR_PSR : 0);
|
|
||||||
mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 | CCSR_SSI_SxCCR_PSR;
|
|
||||||
|
|
||||||
if (dir == SND_SOC_CLOCK_OUT || synchronous)
|
|
||||||
write_ssi_mask(&ssi->stccr, mask, stccr);
|
|
||||||
else
|
|
||||||
write_ssi_mask(&ssi->srccr, mask, stccr);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
|
|
||||||
if (!ssi_private->baudclk_locked) {
|
|
||||||
ret = clk_set_rate(ssi_private->baudclk, baudrate);
|
|
||||||
if (ret) {
|
|
||||||
spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
|
|
||||||
dev_err(cpu_dai->dev, "failed to set baudclk rate\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
ssi_private->baudclk_locked = true;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fsl_ssi_set_dai_tdm_slot - set TDM slot number
|
* fsl_ssi_set_dai_tdm_slot - set TDM slot number
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue