Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee9daad4 authored by Sascha Hauer's avatar Sascha Hauer Committed by Mark Brown
Browse files

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: default avatarSascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: default avatarMarkus Pargmann <mpa@pengutronix.de>
Tested-By: default avatarMichael Grzeschik <mgr@pengutronix.de>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 50489479
Loading
Loading
Loading
Loading
+96 −94
Original line number Diff line number Diff line
@@ -518,6 +518,102 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
	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
 *
@@ -720,100 +816,6 @@ static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
	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
 *