MLK-16130-1: ASoC: fsl_sai: enable TCE/RCE according to input channels
authorShengjiu Wang <shengjiu.wang@freescale.com>
Tue, 1 Aug 2017 08:10:38 +0000 (16:10 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:36:16 +0000 (15:36 -0500)
If there is only two channels input and slots is 2, then enable one
port is enough for data transfer. so enable the TCE/RCE according to
the input channels and slots configuration.

Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
sound/soc/fsl/fsl_sai.c

index 6aa5af9..4139c10 100644 (file)
@@ -491,11 +491,14 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
        u32 val_cr4 = 0, val_cr5 = 0;
        u32 slots = (channels == 1) ? 2 : channels;
        u32 slot_width = word_width;
+       u32 pins;
        int ret;
 
        if (sai->slots)
                slots = sai->slots;
 
+       pins = DIV_ROUND_UP(channels, slots);
+
        if (sai->slot_width)
                slot_width = sai->slot_width;
 
@@ -562,6 +565,10 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
                                FSL_SAI_CR4_FCOMB_MASK, FSL_SAI_CR4_FCOMB_SOFT);
        }
 
+       regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, offset),
+                          FSL_SAI_CR3_TRCE_MASK,
+                          FSL_SAI_CR3_TRCE((sai->dataline[tx] & ((1 << pins) - 1))));
+
        regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, offset),
                           FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
                           val_cr4);
@@ -577,8 +584,12 @@ static int fsl_sai_hw_free(struct snd_pcm_substream *substream,
                struct snd_soc_dai *cpu_dai)
 {
        struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+       unsigned char offset = sai->soc->reg_offset;
        bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
+       regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, offset),
+                                  FSL_SAI_CR3_TRCE_MASK, 0);
+
        if (!sai->slave_mode[tx] &&
                        sai->mclk_streams & BIT(substream->stream)) {
                clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]);
@@ -698,7 +709,6 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
                struct snd_soc_dai *cpu_dai)
 {
        struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
-       unsigned char offset = sai->soc->reg_offset;
        bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
        struct device *dev = &sai->pdev->dev;
        int ret;
@@ -714,10 +724,6 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
                return ret;
        }
 
-       regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, offset),
-                          FSL_SAI_CR3_TRCE_MASK,
-                          FSL_SAI_CR3_TRCE(sai->dataline[tx]));
-
        /* EDMA engine needs periods of size multiple of tx/rx maxburst */
        if (sai->soc->constrain_period_size)
                snd_pcm_hw_constraint_step(substream->runtime, 0,
@@ -735,12 +741,9 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
                struct snd_soc_dai *cpu_dai)
 {
        struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
-       unsigned char offset = sai->soc->reg_offset;
        bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
        if (sai->is_stream_opened[tx]) {
-               regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, offset),
-                                  FSL_SAI_CR3_TRCE_MASK, 0);
                clk_disable_unprepare(sai->bus_clk);
                sai->is_stream_opened[tx] = false;
        }