diff options
author | Codrin Ciubotariu <codrin.ciubotariu@microchip.com> | 2019-08-20 19:24:09 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-10-05 13:13:43 +0200 |
commit | cb00bdfdf4a1c160300ed3c9c897eb91e274f7e2 (patch) | |
tree | 7f7b441cf837d833545654847a5aa98fcad2b62a | |
parent | fd3a27888511038c7b1e99a6bd15e4b9f2eb2105 (diff) | |
download | linux-stable-cb00bdfdf4a1c160300ed3c9c897eb91e274f7e2.tar.gz linux-stable-cb00bdfdf4a1c160300ed3c9c897eb91e274f7e2.tar.bz2 linux-stable-cb00bdfdf4a1c160300ed3c9c897eb91e274f7e2.zip |
ASoC: mchp-i2s-mcc: Fix unprepare of GCLK
[ Upstream commit 988b59467b2b14523a266957affbe9eca3e99fc9 ]
If hw_free() gets called after hw_params(), GCLK remains prepared,
preventing further use of it. This patch fixes this by unpreparing the
clock in hw_free() or if hw_params() gets an error.
Fixes: 7e0cdf545a55 ("ASoC: mchp-i2s-mcc: add driver for I2SC Multi-Channel Controller")
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
Link: https://lore.kernel.org/r/20190820162411.24836-2-codrin.ciubotariu@microchip.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | sound/soc/atmel/mchp-i2s-mcc.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 8272915fa09b..ab7d5f98e759 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -670,8 +670,13 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, } ret = regmap_write(dev->regmap, MCHP_I2SMCC_MRA, mra); - if (ret < 0) + if (ret < 0) { + if (dev->gclk_use) { + clk_unprepare(dev->gclk); + dev->gclk_use = 0; + } return ret; + } return regmap_write(dev->regmap, MCHP_I2SMCC_MRB, mrb); } @@ -710,9 +715,13 @@ static int mchp_i2s_mcc_hw_free(struct snd_pcm_substream *substream, regmap_write(dev->regmap, MCHP_I2SMCC_CR, MCHP_I2SMCC_CR_CKDIS); if (dev->gclk_running) { - clk_disable_unprepare(dev->gclk); + clk_disable(dev->gclk); dev->gclk_running = 0; } + if (dev->gclk_use) { + clk_unprepare(dev->gclk); + dev->gclk_use = 0; + } } return 0; |