diff options
Diffstat (limited to 'sound/soc/fsl/fsl_sai.c')
-rw-r--r-- | sound/soc/fsl/fsl_sai.c | 37 |
1 files changed, 36 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) { |