aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_sai.c37
-rw-r--r--sound/soc/fsl/fsl_sai.h3
2 files changed, 39 insertions, 1 deletions
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index a7fa6f0bf83d..0f92906d7a29 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -527,6 +527,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
u32 slot_width = word_width;
int adir = tx ? RX : TX;
u32 pins, bclk;
+ u32 watermark;
int ret, i;
if (sai->slots)
@@ -619,7 +620,15 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
FSL_SAI_CR5_FBT_MASK, val_cr5);
}
- if (hweight8(dl_cfg[dl_cfg_idx].mask[tx]) <= 1)
+ /*
+ * Combine mode has limation:
+ * - Can't used for singel dataline/FIFO case except the FIFO0
+ * - Can't used for multi dataline/FIFO case except the enabled FIFOs
+ * are successive and start from FIFO0
+ *
+ * So for common usage, all multi fifo case disable the combine mode.
+ */
+ if (hweight8(dl_cfg[dl_cfg_idx].mask[tx]) <= 1 || sai->is_multi_fifo_dma)
regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
FSL_SAI_CR4_FCOMB_MASK, 0);
else
@@ -630,6 +639,26 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
dma_params->addr = sai->res->start + FSL_SAI_xDR0(tx) +
dl_cfg[dl_cfg_idx].start_off[tx] * 0x4;
+ if (sai->is_multi_fifo_dma) {
+ sai->audio_config[tx].words_per_fifo = min(slots, channels);
+ if (tx) {
+ sai->audio_config[tx].n_fifos_dst = pins;
+ sai->audio_config[tx].stride_fifos_dst = dl_cfg[dl_cfg_idx].next_off[tx];
+ } else {
+ sai->audio_config[tx].n_fifos_src = pins;
+ sai->audio_config[tx].stride_fifos_src = dl_cfg[dl_cfg_idx].next_off[tx];
+ }
+ dma_params->maxburst = sai->audio_config[tx].words_per_fifo * pins;
+ dma_params->peripheral_config = &sai->audio_config[tx];
+ dma_params->peripheral_size = sizeof(sai->audio_config[tx]);
+
+ watermark = tx ? (sai->soc_data->fifo_depth - dma_params->maxburst) :
+ (dma_params->maxburst - 1);
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR1(tx, ofs),
+ FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth),
+ watermark);
+ }
+
/* Find a proper tcre setting */
for (i = 0; i < sai->soc_data->pins; i++) {
trce_mask = (1 << (i + 1)) - 1;
@@ -1257,6 +1286,7 @@ static int fsl_sai_probe(struct platform_device *pdev)
char tmp[8];
int irq, ret, i;
int index;
+ u32 dmas[4];
sai = devm_kzalloc(dev, sizeof(*sai), GFP_KERNEL);
if (!sai)
@@ -1313,6 +1343,11 @@ static int fsl_sai_probe(struct platform_device *pdev)
fsl_asoc_get_pll_clocks(&pdev->dev, &sai->pll8k_clk,
&sai->pll11k_clk);
+ /* Use Multi FIFO mode depending on the support from SDMA script */
+ ret = of_property_read_u32_array(np, "dmas", dmas, 4);
+ if (!sai->soc_data->use_edma && !ret && dmas[2] == IMX_DMATYPE_MULTI_SAI)
+ sai->is_multi_fifo_dma = true;
+
/* read dataline mask for rx and tx*/
ret = fsl_sai_read_dlcfg(sai);
if (ret < 0) {
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index 17956b5731dc..697f6690068c 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -6,6 +6,7 @@
#ifndef __FSL_SAI_H
#define __FSL_SAI_H
+#include <linux/dma/imx-dma.h>
#include <sound/dmaengine_pcm.h>
#define FSL_SAI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
@@ -281,6 +282,7 @@ struct fsl_sai {
bool is_lsb_first;
bool is_dsp_mode;
bool is_pdm_mode;
+ bool is_multi_fifo_dma;
bool synchronous[2];
struct fsl_sai_dl_cfg *dl_cfg;
unsigned int dl_cfg_cnt;
@@ -300,6 +302,7 @@ struct fsl_sai {
struct pm_qos_request pm_qos_req;
struct pinctrl *pinctrl;
struct pinctrl_state *pins_state;
+ struct sdma_peripheral_config audio_config[2];
};
#define TX 1