Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0da9e55e authored by Nicolin Chen's avatar Nicolin Chen Committed by Vinod Koul
Browse files

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: default avatarNicolin Chen <b42378@freescale.com>
Acked-by: default avatarTimur Tabi <timur@tabi.org>
Acked-by: default avatarMark Brown <broonie@linaro.org>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
parent b1d27c79
Loading
Loading
Loading
Loading
+26 −1
Original line number Diff line number Diff line
@@ -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,