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

Commit fb0ef645 authored by Naresh Medisetty's avatar Naresh Medisetty Committed by Mark Brown
Browse files

ASoC: DaVinci: Audio: Fix swapping of channels at start of stereo playback



Fixes swapping of channels at start of stereo playback.

Channel swap can be observed while playing left-only or right-only audio data. The channel
swap is fixed by handling the XSYNCERR condition.

Signed-off-by: default avatarNaresh Medisetty <naresh@ti.com>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent b402dff8
Loading
Loading
Loading
Loading
+46 −3
Original line number Diff line number Diff line
@@ -111,16 +111,59 @@ static void davinci_mcbsp_start(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
	struct snd_soc_device *socdev = rtd->socdev;
	struct snd_soc_platform *platform = socdev->platform;
	u32 w;
	int ret;

	/* Start the sample generator and enable transmitter/receiver */
	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
	MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1);
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		/* Stop the DMA to avoid data loss */
		/* while the transmitter is out of reset to handle XSYNCERR */
		if (platform->pcm_ops->trigger) {
			ret = platform->pcm_ops->trigger(substream,
				SNDRV_PCM_TRIGGER_STOP);
			if (ret < 0)
				printk(KERN_DEBUG "Playback DMA stop failed\n");
		}

		/* Enable the transmitter */
		w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
		MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
	else
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);

		/* wait for any unexpected frame sync error to occur */
		udelay(100);

		/* Disable the transmitter to clear any outstanding XSYNCERR */
		w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
		MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);

		/* Restart the DMA */
		if (platform->pcm_ops->trigger) {
			ret = platform->pcm_ops->trigger(substream,
				SNDRV_PCM_TRIGGER_START);
			if (ret < 0)
				printk(KERN_DEBUG "Playback DMA start failed\n");
		}
		/* Enable the transmitter */
		w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
		MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);

	} else {

		/* Enable the reciever */
		w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
		MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
	}


	/* Start frame sync */
	w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);