[PATCH 3/5] ASoC: rsnd: adg: use more simple method for null_clk

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>

commit 965386c97616c ("ASoC: rsnd: call unregister for null_hw when
removed") tried unregister null_clk, but it has some issues.

1st issue is kernel will indicate below message when unregistering,
because of its timing. unregistering should be happen after clk_disable().

	clk_unregister: unregistering prepared clock: rsnd_adg_null

2nd issue is, it is using priv->null_clk, but it should be adg->null_clk.

3rd issue is it is using very complex clk registering method.
more simple clk_register/unregister_fixed_rate() should be OK.

This patch fixes these.

Fixes: 965386c97616c ("ASoC: rsnd: call unregister for null_hw when removed")
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>
---
 sound/soc/sh/rcar/adg.c  | 52 +++++++++++++++++++++-------------------
 sound/soc/sh/rcar/rsnd.h |  1 -
 2 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index af6132479593..3dfd07c8a7e3 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -28,6 +28,7 @@ static struct rsnd_mod_ops adg_ops = {
 struct rsnd_adg {
 	struct clk *clk[CLKMAX];
 	struct clk *clkout[CLKOUTMAX];
+	struct clk *null_clk;
 	struct clk_onecell_data onecell;
 	struct rsnd_mod mod;
 	int clk_rate[CLKMAX];
@@ -363,53 +364,52 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
 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;
 
 	for_each_rsnd_clk(clk, adg, i) {
 		if (enable) {
-			int ret = clk_prepare_enable(clk);
+			clk_prepare_enable(clk);
 
 			/*
 			 * We shouldn't use clk_get_rate() under
 			 * atomic context. Let's keep it when
 			 * rsnd_adg_clk_enable() was called
 			 */
-			adg->clk_rate[i] = 0;
-			if (ret < 0)
-				dev_warn(dev, "can't use clk %d\n", i);
-			else
-				adg->clk_rate[i] = clk_get_rate(clk);
+			adg->clk_rate[i] = clk_get_rate(clk);
 		} else {
-			if (adg->clk_rate[i])
-				clk_disable_unprepare(clk);
-			adg->clk_rate[i] = 0;
+			clk_disable_unprepare(clk);
 		}
 	}
 }
 
-#define NULL_CLK "rsnd_adg_null"
-static struct clk *rsnd_adg_null_clk_get(struct rsnd_priv *priv)
+static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv,
+					    const char * const name,
+					    const char *parent)
 {
 	struct device *dev = rsnd_priv_to_dev(priv);
+	struct clk *clk;
+
+	clk = clk_register_fixed_rate(dev, name, parent, 0, 0);
+	if (IS_ERR(clk)) {
+		dev_err(dev, "create null clk error\n");
+		return NULL;
+	}
 
-	if (!priv->null_hw) {
-		struct clk_hw *_hw;
-		int ret;
+	return clk;
+}
 
-		_hw = clk_hw_register_fixed_rate_with_accuracy(dev, NULL_CLK, NULL, 0, 0, 0);
-		if (IS_ERR(_hw))
-			return NULL;
+static struct clk *rsnd_adg_null_clk_get(struct rsnd_priv *priv)
+{
+	struct rsnd_adg *adg = priv->adg;
 
-		ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get, _hw);
-		if (ret < 0)
-			clk_hw_unregister_fixed_rate(_hw);
+	if (!adg->null_clk) {
+		static const char * const name = "rsnd_adg_null";
 
-		priv->null_hw = _hw;
+		adg->null_clk = rsnd_adg_create_null_clk(priv, name, NULL);
 	}
 
-	return clk_hw_get_clk(priv->null_hw, NULL_CLK);
+	return adg->null_clk;
 }
 
 static void rsnd_adg_get_clkin(struct rsnd_priv *priv)
@@ -666,10 +666,12 @@ void rsnd_adg_remove(struct rsnd_priv *priv)
 	for_each_rsnd_clkout(clk, adg, i)
 		if (adg->clkout[i])
 			clk_unregister_fixed_rate(adg->clkout[i]);
-	if (priv->null_hw)
-		clk_hw_unregister_fixed_rate(priv->null_hw);
 
 	of_clk_del_provider(np);
 
 	rsnd_adg_clk_disable(priv);
+
+	/* It should be called after rsnd_adg_clk_disable() */
+	if (adg->null_clk)
+		clk_unregister_fixed_rate(adg->null_clk);
 }
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index b2fbe3bbaabd..0182ea5b31d2 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -646,7 +646,6 @@ struct rsnd_priv {
 	 * below value will be filled on rsnd_adg_probe()
 	 */
 	void *adg;
-	struct clk_hw *null_hw;
 
 	/*
 	 * below value will be filled on rsnd_dma_probe()
-- 
2.25.1




[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux