Merge branch 'fix/rcar' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
authorMark Brown <broonie@kernel.org>
Thu, 10 Aug 2017 14:51:05 +0000 (15:51 +0100)
committerMark Brown <broonie@kernel.org>
Thu, 10 Aug 2017 14:51:05 +0000 (15:51 +0100)
sound/soc/sh/rcar/adg.c
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/ssi.c

index 197cb3ec075f3de5905d4ccf002b0700311154e0..5b5389e5b92b3e5da3dbaa66bea9b6b5bbfce894 100644 (file)
@@ -610,6 +610,13 @@ void rsnd_adg_remove(struct rsnd_priv *priv)
 {
        struct device *dev = rsnd_priv_to_dev(priv);
        struct device_node *np = dev->of_node;
+       struct rsnd_adg *adg = priv->adg;
+       struct clk *clk;
+       int i;
+
+       for_each_rsnd_clkout(clk, adg, i)
+               if (adg->clkout[i])
+                       clk_unregister_fixed_rate(adg->clkout[i]);
 
        of_clk_del_provider(np);
 
index c34562388cfaf1169e9aa4c7195dcb03f202dd49..2c12ad2b2b3484c973766745238d3ba9dc0b1458 100644 (file)
@@ -726,7 +726,6 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
        case 2:
        case 6:
        case 8:
-       case 16:
                /* TDM Extend Mode */
                rsnd_rdai_channels_set(rdai, slots);
                rsnd_rdai_ssi_lane_set(rdai, 1);
@@ -740,7 +739,7 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
 }
 
 static unsigned int rsnd_soc_hw_channels_list[] = {
-       2, 6, 8, 16,
+       2, 6, 8,
 };
 
 static unsigned int rsnd_soc_hw_rate_list[] = {
@@ -1025,7 +1024,7 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
        drv->playback.rates             = RSND_RATES;
        drv->playback.formats           = RSND_FMTS;
        drv->playback.channels_min      = 2;
-       drv->playback.channels_max      = 16;
+       drv->playback.channels_max      = 8;
        drv->playback.stream_name       = rdai->playback.name;
 
        snprintf(rdai->capture.name, RSND_DAI_NAME_SIZE,
@@ -1033,7 +1032,7 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
        drv->capture.rates              = RSND_RATES;
        drv->capture.formats            = RSND_FMTS;
        drv->capture.channels_min       = 2;
-       drv->capture.channels_max       = 16;
+       drv->capture.channels_max       = 8;
        drv->capture.stream_name        = rdai->capture.name;
 
        rdai->playback.rdai             = rdai;
index 434996d4054a5b4521f870ce80abe25f5fc80ed3..0309de58bf18f41975cc98a33d9be155a42e634e 100644 (file)
@@ -72,6 +72,7 @@ struct rsnd_ssi {
        u32 cr_own;
        u32 cr_clk;
        u32 cr_mode;
+       u32 cr_en;
        u32 wsr;
        int chan;
        int rate;
@@ -291,6 +292,16 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
        if (ret < 0)
                return ret;
 
+       /*
+        * SSI clock will be output contiguously
+        * by below settings.
+        * This means, rsnd_ssi_master_clk_start()
+        * and rsnd_ssi_register_setup() are necessary
+        * for SSI parent
+        *
+        * SSICR  : FORCE, SCKD, SWSD
+        * SSIWSR : CONT
+        */
        ssi->cr_clk = FORCE | SWL_32 | SCKD | SWSD | CKDV(idx);
        ssi->wsr = CONT;
        ssi->rate = rate;
@@ -395,7 +406,8 @@ static void rsnd_ssi_register_setup(struct rsnd_mod *mod)
        rsnd_mod_write(mod, SSIWSR,     ssi->wsr);
        rsnd_mod_write(mod, SSICR,      ssi->cr_own     |
                                        ssi->cr_clk     |
-                                       ssi->cr_mode); /* without EN */
+                                       ssi->cr_mode    |
+                                       ssi->cr_en);
 }
 
 static void rsnd_ssi_pointer_init(struct rsnd_mod *mod,
@@ -545,6 +557,8 @@ static int rsnd_ssi_start(struct rsnd_mod *mod,
                          struct rsnd_dai_stream *io,
                          struct rsnd_priv *priv)
 {
+       struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+
        if (!rsnd_ssi_is_run_mods(mod, io))
                return 0;
 
@@ -555,7 +569,19 @@ static int rsnd_ssi_start(struct rsnd_mod *mod,
        if (rsnd_ssi_multi_slaves_runtime(io))
                return 0;
 
-       rsnd_mod_bset(mod, SSICR, EN, EN);
+       /*
+        * EN is for data output.
+        * SSI parent EN is not needed.
+        */
+       if (rsnd_ssi_is_parent(mod, io))
+               return 0;
+
+       ssi->cr_en = EN;
+
+       rsnd_mod_write(mod, SSICR,      ssi->cr_own     |
+                                       ssi->cr_clk     |
+                                       ssi->cr_mode    |
+                                       ssi->cr_en);
 
        return 0;
 }
@@ -570,13 +596,7 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
        if (!rsnd_ssi_is_run_mods(mod, io))
                return 0;
 
-       /*
-        * don't stop if not last user
-        * see also
-        *      rsnd_ssi_start
-        *      rsnd_ssi_interrupt
-        */
-       if (ssi->usrcnt > 1)
+       if (rsnd_ssi_is_parent(mod, io))
                return 0;
 
        /*
@@ -596,6 +616,8 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
        rsnd_mod_write(mod, SSICR, cr); /* disabled all */
        rsnd_ssi_status_check(mod, IIRQ);
 
+       ssi->cr_en = 0;
+
        return 0;
 }
 
@@ -824,10 +846,10 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
                               struct rsnd_priv *priv)
 {
        struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-       struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
+       struct rsnd_mod *pure_ssi_mod = rsnd_io_to_mod_ssi(io);
 
-       /* Do nothing for SSI parent mod */
-       if (ssi_parent_mod == mod)
+       /* Do nothing if non SSI (= SSI parent, multi SSI) mod */
+       if (pure_ssi_mod != mod)
                return 0;
 
        /* PIO will request IRQ again */