diff options
author | Dong Aisheng <aisheng.dong@nxp.com> | 2019-12-02 18:00:44 +0800 |
---|---|---|
committer | Dong Aisheng <aisheng.dong@nxp.com> | 2019-12-02 18:00:44 +0800 |
commit | 8d66f9b46183503dd052b2b9d8d851551c59aafb (patch) | |
tree | e31448903b46740c1fe6e35b36393b994c571dde | |
parent | 635de10e168f7b2417494248d54bbd94bec989b3 (diff) | |
parent | f25a2423464bfb3e352c6a898f9e51e1e31895d1 (diff) |
Merge remote-tracking branch 'origin/audio/ssi' into audio/next
* origin/audio/ssi:
LF-106: ASoC: fsl_ssi: request BUS_FREQ_AUDIO
MLK-15975-1: ASoC: fsl_ssi: support multi fifo script
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 085855f9b08d..e4a38ebd4fc4 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -40,6 +40,8 @@ #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/of_platform.h> +#include <linux/pm_runtime.h> +#include <linux/busfreq-imx.h> #include <sound/core.h> #include <sound/pcm.h> @@ -266,6 +268,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 +647,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 +801,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 +851,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 +1346,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 +1373,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 +1454,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 @@ -1550,6 +1576,7 @@ static int fsl_ssi_probe(struct platform_device *pdev) } dev_set_drvdata(dev, ssi); + pm_runtime_enable(&pdev->dev); if (ssi->soc->imx) { ret = fsl_ssi_imx_probe(pdev, ssi, iomem); @@ -1649,6 +1676,20 @@ static int fsl_ssi_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM +static int fsl_ssi_runtime_resume(struct device *dev) +{ + request_bus_freq(BUS_FREQ_AUDIO); + return 0; +} + +static int fsl_ssi_runtime_suspend(struct device *dev) +{ + release_bus_freq(BUS_FREQ_AUDIO); + return 0; +} +#endif + #ifdef CONFIG_PM_SLEEP static int fsl_ssi_suspend(struct device *dev) { @@ -1683,6 +1724,8 @@ static int fsl_ssi_resume(struct device *dev) static const struct dev_pm_ops fsl_ssi_pm = { SET_SYSTEM_SLEEP_PM_OPS(fsl_ssi_suspend, fsl_ssi_resume) + SET_RUNTIME_PM_OPS(fsl_ssi_runtime_suspend, fsl_ssi_runtime_resume, + NULL) }; static struct platform_driver fsl_ssi_driver = { |