提交 faf907c7 编写于 作者: S Shine Liu 提交者: Mark Brown

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: NShine Liu <liuxian@redflag-linux.com>
Signed-off-by: NShine Liu <shinel@foxmail.com>
Signed-off-by: NMark Brown <broonie@opensource.wolfsonmicro.com>
上级 d09a2afc
...@@ -387,6 +387,8 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -387,6 +387,8 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
unsigned long irqs; unsigned long irqs;
int ret = 0; int ret = 0;
int channel = ((struct s3c24xx_pcm_dma_params *)
rtd->dai->cpu_dai->dma_data)->channel;
pr_debug("Entered %s\n", __func__); pr_debug("Entered %s\n", __func__);
...@@ -416,6 +418,14 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -416,6 +418,14 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
s3c2412_snd_txctrl(i2s, 1); s3c2412_snd_txctrl(i2s, 1);
local_irq_restore(irqs); 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; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
......
...@@ -290,6 +290,9 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -290,6 +290,9 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
u32 ac_glbctrl; 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); ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
switch (cmd) { switch (cmd) {
...@@ -312,6 +315,8 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int 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); writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
return 0; return 0;
} }
...@@ -334,6 +339,9 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream, ...@@ -334,6 +339,9 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai) int cmd, struct snd_soc_dai *dai)
{ {
u32 ac_glbctrl; 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); ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
switch (cmd) { switch (cmd) {
...@@ -349,6 +357,8 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream, ...@@ -349,6 +357,8 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
} }
writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
return 0; return 0;
} }
......
...@@ -279,6 +279,9 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -279,6 +279,9 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
int ret = 0; 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__); pr_debug("Entered %s\n", __func__);
...@@ -296,6 +299,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -296,6 +299,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
s3c24xx_snd_rxctrl(1); s3c24xx_snd_rxctrl(1);
else else
s3c24xx_snd_txctrl(1); s3c24xx_snd_txctrl(1);
s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
......
...@@ -255,7 +255,6 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ...@@ -255,7 +255,6 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
prtd->state |= ST_RUNNING; prtd->state |= ST_RUNNING;
s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START); s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STARTED);
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册