ASoC: S3C platform: Fix s3c2410_dma_started() called at improper time
s3c24xx dma has the auto reload feature, when the the trnasfer is done, CURR_TC(DSTAT[19:0], current value of transfer count) reaches 0, and DMA ACK becomes 1, and then, TC(DCON[19:0]) will be loaded into CURR_TC. So the transmission is repeated. IRQ is issued while auto reload occurs. We change the DISRC and DCON[19:0] in the ISR, but at this time, the auto reload has been performed already. The first block is being re-transmitted by the DMA. So we need rewrite the DISRC and DCON[19:0] for the next block immediatly after the this block has been started to be transported. The function s3c2410_dma_started() is for this perpose, which is called in the form of "s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STARTED);" in s3c24xx_pcm_trigger(). But it is not correct. DMA transmission won't start until DMA REQ signal arrived, it is the time s3c24xx_snd_txctrl(1) or s3c24xx_snd_rxctrl(1) is called in s3c24xx_i2s_trigger(). In the current framework, s3c24xx_pcm_trigger() is always called before s3c24xx_pcm_trigger(). So the s3c2410_dma_started() should be called in s3c24xx_pcm_trigger() after s3c24xx_snd_txctrl(1) or s3c24xx_snd_rxctrl(1) is called in this function. However, s3c2410_dma_started() is dma related, to call this function we should provide the channel number, which is given by substream->runtime->private_data->params->channel. The private_data points to a struct s3c24xx_runtime_data object, which is define in s3c24xx_pcm.c, so s3c2410_dma_started() can't be called in s3c24xx_i2s.c Fix this by moving the call to signal the DMA started to the DAI drivers. Signed-off-by: Shine Liu <liuxian@redflag-linux.com> Signed-off-by: Shine Liu <shinel@foxmail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
parent
d09a2afc93
commit
faf907c7ba
4 changed files with 25 additions and 1 deletions
|
@ -387,6 +387,8 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||
int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
|
||||
unsigned long irqs;
|
||||
int ret = 0;
|
||||
int channel = ((struct s3c24xx_pcm_dma_params *)
|
||||
rtd->dai->cpu_dai->dma_data)->channel;
|
||||
|
||||
pr_debug("Entered %s\n", __func__);
|
||||
|
||||
|
@ -416,6 +418,14 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||
s3c2412_snd_txctrl(i2s, 1);
|
||||
|
||||
local_irq_restore(irqs);
|
||||
|
||||
/*
|
||||
* Load the next buffer to DMA to meet the reqirement
|
||||
* of the auto reload mechanism of S3C24XX.
|
||||
* This call won't bother S3C64XX.
|
||||
*/
|
||||
s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
|
||||
|
||||
break;
|
||||
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
|
|
|
@ -290,6 +290,9 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||
struct snd_soc_dai *dai)
|
||||
{
|
||||
u32 ac_glbctrl;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
int channel = ((struct s3c24xx_pcm_dma_params *)
|
||||
rtd->dai->cpu_dai->dma_data)->channel;
|
||||
|
||||
ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
|
||||
switch (cmd) {
|
||||
|
@ -312,6 +315,8 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||
}
|
||||
writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
|
||||
|
||||
s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -334,6 +339,9 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
|
|||
int cmd, struct snd_soc_dai *dai)
|
||||
{
|
||||
u32 ac_glbctrl;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
int channel = ((struct s3c24xx_pcm_dma_params *)
|
||||
rtd->dai->cpu_dai->dma_data)->channel;
|
||||
|
||||
ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
|
||||
switch (cmd) {
|
||||
|
@ -349,6 +357,8 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
|
|||
}
|
||||
writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
|
||||
|
||||
s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -279,6 +279,9 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int ret = 0;
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
int channel = ((struct s3c24xx_pcm_dma_params *)
|
||||
rtd->dai->cpu_dai->dma_data)->channel;
|
||||
|
||||
pr_debug("Entered %s\n", __func__);
|
||||
|
||||
|
@ -296,6 +299,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||
s3c24xx_snd_rxctrl(1);
|
||||
else
|
||||
s3c24xx_snd_txctrl(1);
|
||||
|
||||
s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
|
|
|
@ -255,7 +255,6 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
|||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
prtd->state |= ST_RUNNING;
|
||||
s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
|
||||
s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STARTED);
|
||||
break;
|
||||
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
|
|
Reference in a new issue