summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDong Aisheng <aisheng.dong@nxp.com>2019-12-02 18:00:44 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-12-02 18:00:44 +0800
commit8d66f9b46183503dd052b2b9d8d851551c59aafb (patch)
treee31448903b46740c1fe6e35b36393b994c571dde
parent635de10e168f7b2417494248d54bbd94bec989b3 (diff)
parentf25a2423464bfb3e352c6a898f9e51e1e31895d1 (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.c47
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 = {