diff options
author | Kuninori Morimoto | 2021-06-02 08:43:50 +0900 |
---|---|---|
committer | Mark Brown | 2021-06-03 13:56:40 +0100 |
commit | cb2f97d89f383dafa822bce66f0c3514dfb135b8 (patch) | |
tree | 774108822b3935f999cd026013a3c2b4a5972fa0 /sound/soc/sh/rcar/adg.c | |
parent | b48e4aa48931030382d26c624cf4ae1c68d15666 (diff) |
ASoC: rsnd: adg: use more simple method for null_clk
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@renesas.com>
Link: https://lore.kernel.org/r/87r1hli215.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/sh/rcar/adg.c')
-rw-r--r-- | sound/soc/sh/rcar/adg.c | 52 |
1 files changed, 27 insertions, 25 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); } |