aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorNicolin Chen <b42378@freescale.com>2013-11-13 09:55:26 -0500
committerVinod Koul <vinod.koul@intel.com>2013-12-15 22:48:48 -0500
commit0da9e55e71bc239102d47ac422162c9915c99074 (patch)
tree34c135cf1b6cd84d768c32555e3260d1362a0ef4 /sound
parentb1d27c79c8377df1880447375deffa3bb82c7bd3 (diff)
ASoC: fsl_ssi: Add dual fifo mode support
By enabling dual fifo mode, it would allow SSI enter a better performance to transimit/receive data without occasional hardware underrun/overrun. Signed-off-by: Nicolin Chen <b42378@freescale.com> Acked-by: Timur Tabi <timur@tabi.org> Acked-by: Mark Brown <broonie@linaro.org> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/fsl/fsl_ssi.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 35e277379b86..f43be6d4c549 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -143,6 +143,7 @@ struct fsl_ssi_private {
143 bool ssi_on_imx; 143 bool ssi_on_imx;
144 bool imx_ac97; 144 bool imx_ac97;
145 bool use_dma; 145 bool use_dma;
146 bool use_dual_fifo;
146 struct clk *clk; 147 struct clk *clk;
147 struct snd_dmaengine_dai_dma_data dma_params_tx; 148 struct snd_dmaengine_dai_dma_data dma_params_tx;
148 struct snd_dmaengine_dai_dma_data dma_params_rx; 149 struct snd_dmaengine_dai_dma_data dma_params_rx;
@@ -413,6 +414,12 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
413 write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor); 414 write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
414 } 415 }
415 416
417 if (ssi_private->use_dual_fifo) {
418 write_ssi_mask(&ssi->srcr, 0, CCSR_SSI_SRCR_RFEN1);
419 write_ssi_mask(&ssi->stcr, 0, CCSR_SSI_STCR_TFEN1);
420 write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_TCH_EN);
421 }
422
416 return 0; 423 return 0;
417} 424}
418 425
@@ -480,6 +487,15 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
480 ssi_private->second_stream = substream; 487 ssi_private->second_stream = substream;
481 } 488 }
482 489
490 /* When using dual fifo mode, it is safer to ensure an even period
491 * size. If appearing to an odd number while DMA always starts its
492 * task from fifo0, fifo1 would be neglected at the end of each
493 * period. But SSI would still access fifo1 with an invalid data.
494 */
495 if (ssi_private->use_dual_fifo)
496 snd_pcm_hw_constraint_step(substream->runtime, 0,
497 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
498
483 return 0; 499 return 0;
484} 500}
485 501
@@ -947,7 +963,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
947 ssi_private->fifo_depth = 8; 963 ssi_private->fifo_depth = 8;
948 964
949 if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) { 965 if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
950 u32 dma_events[2]; 966 u32 dma_events[2], dmas[4];
951 ssi_private->ssi_on_imx = true; 967 ssi_private->ssi_on_imx = true;
952 968
953 ssi_private->clk = devm_clk_get(&pdev->dev, NULL); 969 ssi_private->clk = devm_clk_get(&pdev->dev, NULL);
@@ -1001,6 +1017,15 @@ static int fsl_ssi_probe(struct platform_device *pdev)
1001 dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); 1017 dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
1002 imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, 1018 imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
1003 dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); 1019 dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
1020 if (!of_property_read_u32_array(pdev->dev.of_node, "dmas", dmas, 4)
1021 && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
1022 ssi_private->use_dual_fifo = true;
1023 /* When using dual fifo mode, we need to keep watermark
1024 * as even numbers due to dma script limitation.
1025 */
1026 ssi_private->dma_params_tx.maxburst &= ~0x1;
1027 ssi_private->dma_params_rx.maxburst &= ~0x1;
1028 }
1004 } else if (ssi_private->use_dma) { 1029 } else if (ssi_private->use_dma) {
1005 /* The 'name' should not have any slashes in it. */ 1030 /* The 'name' should not have any slashes in it. */
1006 ret = devm_request_irq(&pdev->dev, ssi_private->irq, 1031 ret = devm_request_irq(&pdev->dev, ssi_private->irq,