提交 0da9e55e 编写于 作者: N Nicolin Chen 提交者: Vinod Koul

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: NNicolin Chen <b42378@freescale.com>
Acked-by: NTimur Tabi <timur@tabi.org>
Acked-by: NMark Brown <broonie@linaro.org>
Signed-off-by: NVinod Koul <vinod.koul@intel.com>
上级 b1d27c79
...@@ -143,6 +143,7 @@ struct fsl_ssi_private { ...@@ -143,6 +143,7 @@ struct fsl_ssi_private {
bool ssi_on_imx; bool ssi_on_imx;
bool imx_ac97; bool imx_ac97;
bool use_dma; bool use_dma;
bool use_dual_fifo;
struct clk *clk; struct clk *clk;
struct snd_dmaengine_dai_dma_data dma_params_tx; struct snd_dmaengine_dai_dma_data dma_params_tx;
struct snd_dmaengine_dai_dma_data dma_params_rx; 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,6 +414,12 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor); write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
} }
if (ssi_private->use_dual_fifo) {
write_ssi_mask(&ssi->srcr, 0, CCSR_SSI_SRCR_RFEN1);
write_ssi_mask(&ssi->stcr, 0, CCSR_SSI_STCR_TFEN1);
write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_TCH_EN);
}
return 0; return 0;
} }
...@@ -480,6 +487,15 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, ...@@ -480,6 +487,15 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
ssi_private->second_stream = substream; ssi_private->second_stream = substream;
} }
/* When using dual fifo mode, it is safer to ensure an even period
* size. If appearing to an odd number while DMA always starts its
* task from fifo0, fifo1 would be neglected at the end of each
* period. But SSI would still access fifo1 with an invalid data.
*/
if (ssi_private->use_dual_fifo)
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
return 0; return 0;
} }
...@@ -947,7 +963,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) ...@@ -947,7 +963,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
ssi_private->fifo_depth = 8; ssi_private->fifo_depth = 8;
if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) { if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
u32 dma_events[2]; u32 dma_events[2], dmas[4];
ssi_private->ssi_on_imx = true; ssi_private->ssi_on_imx = true;
ssi_private->clk = devm_clk_get(&pdev->dev, NULL); ssi_private->clk = devm_clk_get(&pdev->dev, NULL);
...@@ -1001,6 +1017,15 @@ static int fsl_ssi_probe(struct platform_device *pdev) ...@@ -1001,6 +1017,15 @@ static int fsl_ssi_probe(struct platform_device *pdev)
dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx, imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI); dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
if (!of_property_read_u32_array(pdev->dev.of_node, "dmas", dmas, 4)
&& dmas[2] == IMX_DMATYPE_SSI_DUAL) {
ssi_private->use_dual_fifo = true;
/* When using dual fifo mode, we need to keep watermark
* as even numbers due to dma script limitation.
*/
ssi_private->dma_params_tx.maxburst &= ~0x1;
ssi_private->dma_params_rx.maxburst &= ~0x1;
}
} else if (ssi_private->use_dma) { } else if (ssi_private->use_dma) {
/* The 'name' should not have any slashes in it. */ /* The 'name' should not have any slashes in it. */
ret = devm_request_irq(&pdev->dev, ssi_private->irq, ret = devm_request_irq(&pdev->dev, ssi_private->irq,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册