|
@@ -143,6 +143,7 @@ struct fsl_ssi_private {
|
|
|
bool ssi_on_imx;
|
|
|
bool imx_ac97;
|
|
|
bool use_dma;
|
|
|
+ bool use_dual_fifo;
|
|
|
struct clk *clk;
|
|
|
struct snd_dmaengine_dai_dma_data dma_params_tx;
|
|
|
struct snd_dmaengine_dai_dma_data dma_params_rx;
|
|
@@ -413,6 +414,12 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
|
|
|
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;
|
|
|
}
|
|
|
|
|
@@ -480,6 +487,15 @@ static int fsl_ssi_startup(struct snd_pcm_substream *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;
|
|
|
}
|
|
|
|
|
@@ -947,7 +963,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
|
|
|
ssi_private->fifo_depth = 8;
|
|
|
|
|
|
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->clk = devm_clk_get(&pdev->dev, NULL);
|
|
@@ -1001,6 +1017,15 @@ static int fsl_ssi_probe(struct platform_device *pdev)
|
|
|
dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
|
|
|
imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
|
|
|
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) {
|
|
|
/* The 'name' should not have any slashes in it. */
|
|
|
ret = devm_request_irq(&pdev->dev, ssi_private->irq,
|