]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00295423-3 ASoC: fsl_ssi: Don't disable SSIEN if SSI is already enabled
authorNicolin Chen <Guangyu.Chen@freescale.com>
Mon, 6 Jan 2014 08:55:07 +0000 (16:55 +0800)
committerNicolin Chen <Guangyu.Chen@freescale.com>
Thu, 16 Jan 2014 11:27:49 +0000 (19:27 +0800)
If disabling SSI when SSI is already in the working state, the whole running
substream would be broken. Thus we here replace it to a safer way -- saving
the current SSIEN value and restore it afterward.

This patch also adds a slot number checking code before setting slot number.

Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com>
(cherry picked from commit 2f71335a5b39afec4cf976b45683e5de1baed31d)

sound/soc/fsl/fsl_ssi.c

index 46f574895f7397a460e62e6c5861a3e755f3168e..0d711544c0231d42836d30fb51d9476610f741ca 100644 (file)
@@ -756,6 +756,14 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
 {
        struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
        struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+       u32 val;
+
+       /* The slot number should be >= 2 if using Network mode or I2S mode */
+       val = read_ssi(&ssi->scr) & (CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_NET);
+       if (val && slots < 2) {
+               dev_err(cpu_dai->dev, "slot number should be >= 2 in I2S or NET\n");
+               return -EINVAL;
+       }
 
        write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_DC_MASK,
                        CCSR_SSI_SxCCR_DC(slots));
@@ -765,10 +773,11 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
        /* The register SxMSKs need SSI to provide essential clock due to
         * hardware design. So we here temporarily enable SSI to set them.
         */
+       val = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
        write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN);
        write_ssi(tx_mask, &ssi->stmsk);
        write_ssi(rx_mask, &ssi->srmsk);
-       write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, 0);
+       write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_SSIEN, val);
 
        return 0;
 }