ASoC: rsnd: enable/disable ADG when suspend/resume timing
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Wed, 7 Dec 2016 00:29:02 +0000 (00:29 +0000)
committerMark Brown <broonie@kernel.org>
Wed, 7 Dec 2016 15:47:45 +0000 (15:47 +0000)
Current rsnd driver enables ADG clock when .probe timing,
but it breaks sound after Suspend/Resume. These should be setups
every suspend/resume timing too.
This patch is tested on R-Car Gen3 Salvator-X board

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sh/rcar/adg.c
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/rsnd.h

index 545377dc15edc75526ff7352f2d865d34e602ec4..54b28fd502ef7078e5a579cab876214b181cc75a 100644 (file)
@@ -376,6 +376,25 @@ found_clock:
        return 0;
 }
 
+void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
+{
+       struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
+       struct device *dev = rsnd_priv_to_dev(priv);
+       struct clk *clk;
+       int i, ret;
+
+       for_each_rsnd_clk(clk, adg, i) {
+               ret = 0;
+               if (enable)
+                       ret = clk_prepare_enable(clk);
+               else
+                       clk_disable_unprepare(clk);
+
+               if (ret < 0)
+                       dev_warn(dev, "can't use clk %d\n", i);
+       }
+}
+
 static void rsnd_adg_get_clkin(struct rsnd_priv *priv,
                               struct rsnd_adg *adg)
 {
@@ -387,20 +406,15 @@ static void rsnd_adg_get_clkin(struct rsnd_priv *priv,
                [CLKC]  = "clk_c",
                [CLKI]  = "clk_i",
        };
-       int i, ret;
+       int i;
 
        for (i = 0; i < CLKMAX; i++) {
                clk = devm_clk_get(dev, clk_name[i]);
                adg->clk[i] = IS_ERR(clk) ? NULL : clk;
        }
 
-       for_each_rsnd_clk(clk, adg, i) {
-               ret = clk_prepare_enable(clk);
-               if (ret < 0)
-                       dev_warn(dev, "can't use clk %d\n", i);
-
+       for_each_rsnd_clk(clk, adg, i)
                dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk));
-       }
 }
 
 static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
@@ -565,16 +579,12 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
 
        priv->adg = adg;
 
+       rsnd_adg_clk_enable(priv);
+
        return 0;
 }
 
 void rsnd_adg_remove(struct rsnd_priv *priv)
 {
-       struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
-       struct clk *clk;
-       int i;
-
-       for_each_rsnd_clk(clk, adg, i) {
-               clk_disable_unprepare(clk);
-       }
+       rsnd_adg_clk_disable(priv);
 }
index 825635aaf30e1de59e5560b938f10bb12f0831ac..4bd68de761309b57285bf203aa2ee46cabc440cc 100644 (file)
@@ -1308,9 +1308,33 @@ static int rsnd_remove(struct platform_device *pdev)
        return ret;
 }
 
+static int rsnd_suspend(struct device *dev)
+{
+       struct rsnd_priv *priv = dev_get_drvdata(dev);
+
+       rsnd_adg_clk_disable(priv);
+
+       return 0;
+}
+
+static int rsnd_resume(struct device *dev)
+{
+       struct rsnd_priv *priv = dev_get_drvdata(dev);
+
+       rsnd_adg_clk_enable(priv);
+
+       return 0;
+}
+
+static struct dev_pm_ops rsnd_pm_ops = {
+       .suspend                = rsnd_suspend,
+       .resume                 = rsnd_resume,
+};
+
 static struct platform_driver rsnd_driver = {
        .driver = {
                .name   = "rcar_sound",
+               .pm     = &rsnd_pm_ops,
                .of_match_table = rsnd_of_match,
        },
        .probe          = rsnd_probe,
index 71158c8bc254027fdf01eeadb2d57c011b2c0546..b90df77662dfa337e5ff50bb44ef59efa1eef6e6 100644 (file)
@@ -499,6 +499,9 @@ int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod,
                                  unsigned int out_rate);
 int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod,
                                 struct rsnd_dai_stream *io);
+#define rsnd_adg_clk_enable(priv)      rsnd_adg_clk_control(priv, 1)
+#define rsnd_adg_clk_disable(priv)     rsnd_adg_clk_control(priv, 0)
+void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable);
 
 /*
  *     R-Car sound priv