Merge branch 'asoc-4.18' into asoc-4.19 for amd dep
[muen/linux.git] / sound / soc / sh / rcar / ssi.c
index 3d9ea100a64f30108d066cf2d7a15f03d4fe1cec..8304e4ec9242c68eeabeca2516938990678aabc8 100644 (file)
@@ -33,6 +33,7 @@
 #define        CHNL_4          (1 << 22)       /* Channels */
 #define        CHNL_6          (2 << 22)       /* Channels */
 #define        CHNL_8          (3 << 22)       /* Channels */
+#define DWL_MASK       (7 << 19)       /* Data Word Length mask */
 #define        DWL_8           (0 << 19)       /* Data Word Length */
 #define        DWL_16          (1 << 19)       /* Data Word Length */
 #define        DWL_18          (2 << 19)       /* Data Word Length */
@@ -349,21 +350,18 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
        struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
        struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
        struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-       u32 cr_own;
-       u32 cr_mode;
-       u32 wsr;
+       u32 cr_own      = ssi->cr_own;
+       u32 cr_mode     = ssi->cr_mode;
+       u32 wsr         = ssi->wsr;
        int is_tdm;
 
-       if (rsnd_ssi_is_parent(mod, io))
-               return;
-
        is_tdm = rsnd_runtime_is_ssi_tdm(io);
 
        /*
         * always use 32bit system word.
         * see also rsnd_ssi_master_clk_enable()
         */
-       cr_own = FORCE | SWL_32;
+       cr_own |= FORCE | SWL_32;
 
        if (rdai->bit_clk_inv)
                cr_own |= SCKP;
@@ -373,9 +371,18 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
                cr_own |= SDTA;
        if (rdai->sys_delay)
                cr_own |= DEL;
+
+       /*
+        * We shouldn't exchange SWSP after running.
+        * This means, parent needs to care it.
+        */
+       if (rsnd_ssi_is_parent(mod, io))
+               goto init_end;
+
        if (rsnd_io_is_play(io))
                cr_own |= TRMD;
 
+       cr_own &= ~DWL_MASK;
        switch (snd_pcm_format_width(runtime->format)) {
        case 16:
                cr_own |= DWL_16;
@@ -402,7 +409,7 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
                wsr     |= WS_MODE;
                cr_own  |= CHNL_8;
        }
-
+init_end:
        ssi->cr_own     = cr_own;
        ssi->cr_mode    = cr_mode;
        ssi->wsr        = wsr;
@@ -466,15 +473,18 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod,
                return -EIO;
        }
 
-       if (!rsnd_ssi_is_parent(mod, io))
-               ssi->cr_own     = 0;
-
        rsnd_ssi_master_clk_stop(mod, io);
 
        rsnd_mod_power_off(mod);
 
        ssi->usrcnt--;
 
+       if (!ssi->usrcnt) {
+               ssi->cr_own     = 0;
+               ssi->cr_mode    = 0;
+               ssi->wsr        = 0;
+       }
+
        return 0;
 }
 
@@ -1051,9 +1061,10 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
 
 int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
 {
-       struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+       if (!mod)
+               return 0;
 
-       return !!(rsnd_flags_has(ssi, RSND_SSI_CLK_PIN_SHARE));
+       return !!(rsnd_flags_has(rsnd_mod_to_ssi(mod), RSND_SSI_CLK_PIN_SHARE));
 }
 
 static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io,