diff options
author | Nicolin Chen <b42378@freescale.com> | 2013-11-13 09:55:26 -0500 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2013-12-15 22:48:48 -0500 |
commit | 0da9e55e71bc239102d47ac422162c9915c99074 (patch) | |
tree | 34c135cf1b6cd84d768c32555e3260d1362a0ef4 /sound | |
parent | b1d27c79c8377df1880447375deffa3bb82c7bd3 (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.c | 27 |
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, |