MLK-14316 ASoC: fsl_ssi: Fix playback and capture with mono stream
authorShengjiu Wang <shengjiu.wang@nxp.com>
Wed, 8 Mar 2017 17:44:47 +0000 (19:44 +0200)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:10:52 +0000 (15:10 -0500)
After starting playback with a single channel SSI runs in Normal mode
(SCR.net = 0b, SCR.i2s_mode = 00b). But, if starting also capture
in parallel with playback the SSI mode changes which breaks the playback.

This happens because, we can change SSI mode from two distinct places:
* _fsl_ssi_set_dai_fmt
* fsl_ssi_hw_params

When running playback and capture in parallel for a mono channel, changing
hw params for the second stream will have no effect.

This patch allows changing the mode only from fsl_ssi_hw_parms so that
we have an atomic view of SSI mode.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
sound/soc/fsl/fsl_ssi.c

index 124ceaf..fb90c27 100644 (file)
@@ -854,6 +854,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
        int ret;
        u32 scr_val;
        int enabled;
+       u8 i2smode = ssi_private->i2s_mode;
 
        regmap_read(regs, CCSR_SSI_SCR, &scr_val);
        enabled = scr_val & CCSR_SSI_SCR_SSIEN;
@@ -881,7 +882,6 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
        }
 
        if (!fsl_ssi_is_ac97(ssi_private)) {
-               u8 i2smode;
                /*
                 * Switch to normal net mode in order to have a frame sync
                 * signal every 32 bits instead of 16 bits
@@ -889,14 +889,14 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
                if (fsl_ssi_is_i2s_cbm_cfs(ssi_private) && sample_size == 16)
                        i2smode = CCSR_SSI_SCR_I2S_MODE_NORMAL |
                                CCSR_SSI_SCR_NET;
-               else
-                       i2smode = ssi_private->i2s_mode;
-
-               regmap_update_bits(regs, CCSR_SSI_SCR,
-                               CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
-                               channels == 1 ? 0 : i2smode);
+               if (channels == 1)
+                       i2smode = 0;
        }
 
+       regmap_update_bits(regs, CCSR_SSI_SCR,
+                          CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
+                          i2smode);
+
        /*
         * FIXME: The documentation says that SxCCR[WL] should not be
         * modified while the SSI is enabled.  The only time this can
@@ -1009,7 +1009,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
        default:
                return -EINVAL;
        }
-       scr |= ssi_private->i2s_mode;
 
        /* DAI clock inversion */
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {