aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorNicolin Chen <Guangyu.Chen@freescale.com>2014-03-31 23:17:06 -0400
committerMark Brown <broonie@linaro.org>2014-04-14 12:26:05 -0400
commite6b398465821fb8e08d208bd4ef2b5b73ce87b58 (patch)
tree1fca8b6e236ff2fb13869df4ac3b060dea446794 /sound/soc/fsl
parent413312aa17ceefe7003ad690778ab72f023128f0 (diff)
ASoC: fsl_sai: Fix buggy configurations in trigger()
The current trigger() has two crucial problems: 1) The DMA request enabling operations (FSL_SAI_CSR_FRDE) for Tx and Rx are now totally exclusive: It would fail to run simultaneous Tx-Rx cases. 2) The TERE disabling operation depends on an incorrect condition -- active reference count that only gets increased in snd_pcm_open() and decreased in snd_pcm_close(): The TERE would never get cleared. So this patch overwrites the trigger function by following these rules: A) We continue to support tx-async-while-rx-sync-to-tx case alone, which's originally limited by this fsl_sai driver, but we make the code easy to modify for the further support of the opposite case. B) We enable both TE and RE for PLAYBACK stream or CAPTURE stream but only enabling the DMA request bit (FSL_SAI_CSR_FRDE) of the current direction due to the requirement of SAI -- For tx-async-while-rx-sync-to-tx case, the receiver is enabled only when both the transmitter and receiver are enabled. Tested cases: a) aplay test.wav -d5 b) arecord -r44100 -c2 -fS16_LE test.wav -d5 c) arecord -r44100 -c2 -fS16_LE -d5 | aplay d) (aplay test2.wav &); sleep 1; arecord -r44100 -c2 -fS16_LE test.wav -d1 e) (arecord -r44100 -c2 -fS16_LE test.wav -d5 &); sleep 1; aplay test.wav -d1 Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com> Acked-by: Xiubo Li <Li.Xiubo@freescale.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_sai.c35
-rw-r--r--sound/soc/fsl/fsl_sai.h10
2 files changed, 27 insertions, 18 deletions
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 7194d9280020..80cca7bb2a11 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -365,6 +365,7 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
365 struct snd_soc_dai *cpu_dai) 365 struct snd_soc_dai *cpu_dai)
366{ 366{
367 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); 367 struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
368 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
368 u32 tcsr, rcsr; 369 u32 tcsr, rcsr;
369 370
370 /* 371 /*
@@ -379,14 +380,6 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
379 regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr); 380 regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr);
380 regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr); 381 regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr);
381 382
382 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
383 tcsr |= FSL_SAI_CSR_FRDE;
384 rcsr &= ~FSL_SAI_CSR_FRDE;
385 } else {
386 rcsr |= FSL_SAI_CSR_FRDE;
387 tcsr &= ~FSL_SAI_CSR_FRDE;
388 }
389
390 /* 383 /*
391 * It is recommended that the transmitter is the last enabled 384 * It is recommended that the transmitter is the last enabled
392 * and the first disabled. 385 * and the first disabled.
@@ -395,22 +388,28 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
395 case SNDRV_PCM_TRIGGER_START: 388 case SNDRV_PCM_TRIGGER_START:
396 case SNDRV_PCM_TRIGGER_RESUME: 389 case SNDRV_PCM_TRIGGER_RESUME:
397 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 390 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
398 tcsr |= FSL_SAI_CSR_TERE; 391 if (!(tcsr & FSL_SAI_CSR_FRDE || rcsr & FSL_SAI_CSR_FRDE)) {
399 rcsr |= FSL_SAI_CSR_TERE; 392 regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
393 FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
394 regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
395 FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
396 }
400 397
401 regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr); 398 regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
402 regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr); 399 FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
403 break; 400 break;
404 case SNDRV_PCM_TRIGGER_STOP: 401 case SNDRV_PCM_TRIGGER_STOP:
405 case SNDRV_PCM_TRIGGER_SUSPEND: 402 case SNDRV_PCM_TRIGGER_SUSPEND:
406 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 403 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
407 if (!(cpu_dai->playback_active || cpu_dai->capture_active)) { 404 regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
408 tcsr &= ~FSL_SAI_CSR_TERE; 405 FSL_SAI_CSR_FRDE, 0);
409 rcsr &= ~FSL_SAI_CSR_TERE; 406
407 if (!(tcsr & FSL_SAI_CSR_FRDE || rcsr & FSL_SAI_CSR_FRDE)) {
408 regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
409 FSL_SAI_CSR_TERE, 0);
410 regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
411 FSL_SAI_CSR_TERE, 0);
410 } 412 }
411
412 regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr);
413 regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr);
414 break; 413 break;
415 default: 414 default:
416 return -EINVAL; 415 return -EINVAL;
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index a264185c7138..64b6fe72cd08 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -35,6 +35,16 @@
35#define FSL_SAI_RFR 0xc0 /* SAI Receive FIFO */ 35#define FSL_SAI_RFR 0xc0 /* SAI Receive FIFO */
36#define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */ 36#define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */
37 37
38#define FSL_SAI_xCSR(tx) (tx ? FSL_SAI_TCSR : FSL_SAI_RCSR)
39#define FSL_SAI_xCR1(tx) (tx ? FSL_SAI_TCR1 : FSL_SAI_RCR1)
40#define FSL_SAI_xCR2(tx) (tx ? FSL_SAI_TCR2 : FSL_SAI_RCR2)
41#define FSL_SAI_xCR3(tx) (tx ? FSL_SAI_TCR3 : FSL_SAI_RCR3)
42#define FSL_SAI_xCR4(tx) (tx ? FSL_SAI_TCR4 : FSL_SAI_RCR4)
43#define FSL_SAI_xCR5(tx) (tx ? FSL_SAI_TCR5 : FSL_SAI_RCR5)
44#define FSL_SAI_xDR(tx) (tx ? FSL_SAI_TDR : FSL_SAI_RDR)
45#define FSL_SAI_xFR(tx) (tx ? FSL_SAI_TFR : FSL_SAI_RFR)
46#define FSL_SAI_xMR(tx) (tx ? FSL_SAI_TMR : FSL_SAI_RMR)
47
38/* SAI Transmit/Recieve Control Register */ 48/* SAI Transmit/Recieve Control Register */
39#define FSL_SAI_CSR_TERE BIT(31) 49#define FSL_SAI_CSR_TERE BIT(31)
40#define FSL_SAI_CSR_FR BIT(25) 50#define FSL_SAI_CSR_FR BIT(25)