aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorShine Liu <shinel@foxmail.com>2009-08-25 08:05:50 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-08-25 08:09:05 -0400
commitfaf907c7ba3d7df6266366556817f2ef7314640a (patch)
tree5b89e22322e9fce532e4c78e80b52e791366bd0d /sound/soc
parentd09a2afc9359407114b7062519101f1ee2d05388 (diff)
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>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c10
-rw-r--r--sound/soc/s3c24xx/s3c2443-ac97.c10
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c5
-rw-r--r--sound/soc/s3c24xx/s3c24xx-pcm.c1
4 files changed, 25 insertions, 1 deletions
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
index ebfb2f631054..11d8717c9ea0 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c
@@ -387,6 +387,8 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
387 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); 387 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
388 unsigned long irqs; 388 unsigned long irqs;
389 int ret = 0; 389 int ret = 0;
390 int channel = ((struct s3c24xx_pcm_dma_params *)
391 rtd->dai->cpu_dai->dma_data)->channel;
390 392
391 pr_debug("Entered %s\n", __func__); 393 pr_debug("Entered %s\n", __func__);
392 394
@@ -416,6 +418,14 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
416 s3c2412_snd_txctrl(i2s, 1); 418 s3c2412_snd_txctrl(i2s, 1);
417 419
418 local_irq_restore(irqs); 420 local_irq_restore(irqs);
421
422 /*
423 * Load the next buffer to DMA to meet the reqirement
424 * of the auto reload mechanism of S3C24XX.
425 * This call won't bother S3C64XX.
426 */
427 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
428
419 break; 429 break;
420 430
421 case SNDRV_PCM_TRIGGER_STOP: 431 case SNDRV_PCM_TRIGGER_STOP:
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c
index bf16f20fcbb3..fc1beb0930b9 100644
--- a/sound/soc/s3c24xx/s3c2443-ac97.c
+++ b/sound/soc/s3c24xx/s3c2443-ac97.c
@@ -290,6 +290,9 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
290 struct snd_soc_dai *dai) 290 struct snd_soc_dai *dai)
291{ 291{
292 u32 ac_glbctrl; 292 u32 ac_glbctrl;
293 struct snd_soc_pcm_runtime *rtd = substream->private_data;
294 int channel = ((struct s3c24xx_pcm_dma_params *)
295 rtd->dai->cpu_dai->dma_data)->channel;
293 296
294 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); 297 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
295 switch (cmd) { 298 switch (cmd) {
@@ -312,6 +315,8 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
312 } 315 }
313 writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); 316 writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
314 317
318 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
319
315 return 0; 320 return 0;
316} 321}
317 322
@@ -334,6 +339,9 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
334 int cmd, struct snd_soc_dai *dai) 339 int cmd, struct snd_soc_dai *dai)
335{ 340{
336 u32 ac_glbctrl; 341 u32 ac_glbctrl;
342 struct snd_soc_pcm_runtime *rtd = substream->private_data;
343 int channel = ((struct s3c24xx_pcm_dma_params *)
344 rtd->dai->cpu_dai->dma_data)->channel;
337 345
338 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); 346 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
339 switch (cmd) { 347 switch (cmd) {
@@ -349,6 +357,8 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
349 } 357 }
350 writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); 358 writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
351 359
360 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
361
352 return 0; 362 return 0;
353} 363}
354 364
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 556e35f0ab73..40e2c4790f0d 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -279,6 +279,9 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
279 struct snd_soc_dai *dai) 279 struct snd_soc_dai *dai)
280{ 280{
281 int ret = 0; 281 int ret = 0;
282 struct snd_soc_pcm_runtime *rtd = substream->private_data;
283 int channel = ((struct s3c24xx_pcm_dma_params *)
284 rtd->dai->cpu_dai->dma_data)->channel;
282 285
283 pr_debug("Entered %s\n", __func__); 286 pr_debug("Entered %s\n", __func__);
284 287
@@ -296,6 +299,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
296 s3c24xx_snd_rxctrl(1); 299 s3c24xx_snd_rxctrl(1);
297 else 300 else
298 s3c24xx_snd_txctrl(1); 301 s3c24xx_snd_txctrl(1);
302
303 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
299 break; 304 break;
300 case SNDRV_PCM_TRIGGER_STOP: 305 case SNDRV_PCM_TRIGGER_STOP:
301 case SNDRV_PCM_TRIGGER_SUSPEND: 306 case SNDRV_PCM_TRIGGER_SUSPEND:
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index 8a931964ce46..5cbbdc80fde3 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -255,7 +255,6 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
255 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 255 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
256 prtd->state |= ST_RUNNING; 256 prtd->state |= ST_RUNNING;
257 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START); 257 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
258 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STARTED);
259 break; 258 break;
260 259
261 case SNDRV_PCM_TRIGGER_STOP: 260 case SNDRV_PCM_TRIGGER_STOP: