summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2018-09-28 15:16:57 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:54:27 +0800
commit24a3bee2e17b29cbeb0517a86e8822c5e1ac0884 (patch)
tree355ece428caf87dda087b8153c2c5b4223be998e
parent219d54332a09e8d8741c1e1982f5eae56099de85 (diff)
MLK-15975-1: ASoC: fsl_ssi: support multi fifo script
With dual fifo enabled, the case recording mono sound in the background, playback sound twice in parallal, the second time playback sound may distort, the possible reason is using dual fifo to playback mono sound is not recommended. This patch is to provide a option to use multi fifo script, which can be dynamically configured as one fifo or two fifo mode. Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> (cherry picked from commit 9d71068cf7d1fc1ec36e5fb34a321c1bdbaad324)
-rw-r--r--sound/soc/fsl/fsl_ssi.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 537dc69256f0..88baaf3f7a45 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -266,6 +266,7 @@ struct fsl_ssi {
bool synchronous;
bool use_dma;
bool use_dual_fifo;
+ bool use_dyna_fifo;
bool has_ipg_clk_name;
unsigned int fifo_depth;
unsigned int slot_width;
@@ -644,7 +645,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
* 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->use_dual_fifo)
+ if (ssi->use_dual_fifo || ssi->use_dyna_fifo)
snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
@@ -798,6 +799,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
unsigned int sample_size = params_width(hw_params);
u32 wl = SSI_SxCCR_WL(sample_size);
int ret;
+ struct fsl_ssi_regvals *vals = ssi->regvals;
if (fsl_ssi_is_i2s_master(ssi)) {
ret = fsl_ssi_set_bclk(substream, dai, hw_params);
@@ -847,6 +849,24 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
tx2 = tx || ssi->synchronous;
regmap_update_bits(regs, REG_SSI_SxCCR(tx2), SSI_SxCCR_WL_MASK, wl);
+ if (ssi->use_dyna_fifo) {
+ if (channels == 1) {
+ ssi->dma_params_tx.fifo_num = 1;
+ ssi->dma_params_rx.fifo_num = 1;
+ vals[RX].srcr &= ~SSI_SRCR_RFEN1;
+ vals[TX].stcr &= ~SSI_STCR_TFEN1;
+ vals[RX].scr &= ~SSI_SCR_TCH_EN;
+ vals[TX].scr &= ~SSI_SCR_TCH_EN;
+ } else {
+ ssi->dma_params_tx.fifo_num = 2;
+ ssi->dma_params_rx.fifo_num = 2;
+ vals[RX].srcr |= SSI_SRCR_RFEN1;
+ vals[TX].stcr |= SSI_STCR_TFEN1;
+ vals[RX].scr |= SSI_SCR_TCH_EN;
+ vals[TX].scr |= SSI_SCR_TCH_EN;
+ }
+ }
+
return 0;
}
@@ -1324,6 +1344,8 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
dev_dbg(dev, "failed to get baud clock: %ld\n",
PTR_ERR(ssi->baudclk));
+ ssi->dma_params_rx.chan_name = "rx";
+ ssi->dma_params_tx.chan_name = "tx";
ssi->dma_params_tx.maxburst = ssi->dma_maxburst;
ssi->dma_params_rx.maxburst = ssi->dma_maxburst;
ssi->dma_params_tx.addr = ssi->ssi_phys + REG_SSI_STX0;
@@ -1349,7 +1371,7 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
if (ret)
goto error_pcm;
} else {
- ret = imx_pcm_dma_init(pdev, IMX_SSI_DMABUF_SIZE);
+ ret = imx_pcm_platform_register(&pdev->dev);
if (ret)
goto error_pcm;
}
@@ -1430,6 +1452,8 @@ static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi)
if (ssi->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL)
ssi->use_dual_fifo = true;
+ if (ssi->use_dma && !ret && dmas[2] == IMX_DMATYPE_MULTI_SAI)
+ ssi->use_dyna_fifo = true;
/*
* Backward compatible for older bindings by manually triggering the
* machine driver's probe(). Use /compatible property, including the