]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ASoC: Intel: bytcht_es8316: Fix MCLK leak on init errors
authorCássio Gabriel <cassiogabrielcontato@gmail.com>
Tue, 19 May 2026 16:51:47 +0000 (13:51 -0300)
committerMark Brown <broonie@kernel.org>
Mon, 25 May 2026 12:33:23 +0000 (13:33 +0100)
byt_cht_es8316_init() enables MCLK before configuring the codec sysclk
and creating the headset jack. If either of those later steps fails, the
function returns without disabling MCLK, leaving the clock enabled after
card registration fails.

Track whether this driver enabled MCLK and disable it on the init error
paths. Add the matching DAI link exit callback so the same clock enable
is also balanced when ASoC cleans up a successfully initialized link.

Fixes: a03bdaa565cb ("ASoC: Intel: add machine driver for BYT/CHT + ES8316")
Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
Link: https://patch.msgid.link/20260519-asoc-bytcht-es8316-mclk-leak-v1-1-b4a11cdc2afd@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/boards/bytcht_es8316.c

index 192e2a394ff3d098f646e5def1e68246f954839d..ea387dc742738222484bbf0d0bd1d263a9155398 100644 (file)
@@ -40,6 +40,7 @@ struct byt_cht_es8316_private {
        struct gpio_desc *speaker_en_gpio;
        struct device *codec_dev;
        bool speaker_en;
+       bool mclk_enabled;
 };
 
 enum {
@@ -170,6 +171,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
        },
 };
 
+static void byt_cht_es8316_disable_mclk(struct byt_cht_es8316_private *priv)
+{
+       if (!priv->mclk_enabled)
+               return;
+
+       clk_disable_unprepare(priv->mclk);
+       priv->mclk_enabled = false;
+}
+
 static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
 {
        struct snd_soc_component *codec = snd_soc_rtd_to_codec(runtime, 0)->component;
@@ -227,12 +237,14 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
        ret = clk_prepare_enable(priv->mclk);
        if (ret)
                dev_err(card->dev, "unable to enable MCLK\n");
+       else
+               priv->mclk_enabled = true;
 
        ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(runtime, 0), 0, 19200000,
                                     SND_SOC_CLOCK_IN);
        if (ret < 0) {
                dev_err(card->dev, "can't set codec clock %d\n", ret);
-               return ret;
+               goto err_disable_mclk;
        }
 
        ret = snd_soc_card_jack_new_pins(card, "Headset",
@@ -241,13 +253,25 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
                                         ARRAY_SIZE(byt_cht_es8316_jack_pins));
        if (ret) {
                dev_err(card->dev, "jack creation failed %d\n", ret);
-               return ret;
+               goto err_disable_mclk;
        }
 
        snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
        snd_soc_component_set_jack(codec, &priv->jack, NULL);
 
        return 0;
+
+err_disable_mclk:
+       byt_cht_es8316_disable_mclk(priv);
+       return ret;
+}
+
+static void byt_cht_es8316_exit(struct snd_soc_pcm_runtime *runtime)
+{
+       struct snd_soc_card *card = runtime->card;
+       struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
+
+       byt_cht_es8316_disable_mclk(priv);
 }
 
 static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
@@ -353,6 +377,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
                                                | SND_SOC_DAIFMT_CBC_CFC,
                .be_hw_params_fixup = byt_cht_es8316_codec_fixup,
                .init = byt_cht_es8316_init,
+               .exit = byt_cht_es8316_exit,
                SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
        },
 };