Skip to content

Commit 0da9e55

Browse files
Nicolin ChenVinod Koul
authored andcommitted
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>
1 parent b1d27c7 commit 0da9e55

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

sound/soc/fsl/fsl_ssi.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ struct fsl_ssi_private {
143143
bool ssi_on_imx;
144144
bool imx_ac97;
145145
bool use_dma;
146+
bool use_dual_fifo;
146147
struct clk *clk;
147148
struct snd_dmaengine_dai_dma_data dma_params_tx;
148149
struct snd_dmaengine_dai_dma_data dma_params_rx;
@@ -413,6 +414,12 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
413414
write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
414415
}
415416

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+
416423
return 0;
417424
}
418425

@@ -480,6 +487,15 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
480487
ssi_private->second_stream = substream;
481488
}
482489

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+
483499
return 0;
484500
}
485501

@@ -947,7 +963,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
947963
ssi_private->fifo_depth = 8;
948964

949965
if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
950-
u32 dma_events[2];
966+
u32 dma_events[2], dmas[4];
951967
ssi_private->ssi_on_imx = true;
952968

953969
ssi_private->clk = devm_clk_get(&pdev->dev, NULL);
@@ -1001,6 +1017,15 @@ static int fsl_ssi_probe(struct platform_device *pdev)
10011017
dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
10021018
imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
10031019
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+
}
10041029
} else if (ssi_private->use_dma) {
10051030
/* The 'name' should not have any slashes in it. */
10061031
ret = devm_request_irq(&pdev->dev, ssi_private->irq,

0 commit comments

Comments
 (0)