]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
ASoC: mchp-i2s-mcc: Fix unprepare of GCLK
authorCodrin Ciubotariu <codrin.ciubotariu@microchip.com>
Tue, 20 Aug 2019 16:24:09 +0000 (19:24 +0300)
committerKhalid Elmously <khalid.elmously@canonical.com>
Fri, 18 Oct 2019 08:25:53 +0000 (04:25 -0400)
BugLink: https://bugs.launchpad.net/bugs/1848046
[ 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>
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
sound/soc/atmel/mchp-i2s-mcc.c

index 8272915fa09b977c5aec83ae045d02c23d267526..ab7d5f98e759e4faf9cbd8f3595fda58f1bba9dd 100644 (file)
@@ -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;