From: Chancel Liu <chancel.liu@oss.nxp.com>
To: Mark Brown <broonie@kernel.org>,
Liam Girdwood <lgirdwood@gmail.com>,
Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>,
Charles Keepax <ckeepax@opensource.cirrus.com>,
Oder Chiou <oder_chiou@realtek.com>,
Cezary Rojewski <cezary.rojewski@intel.com>
Cc: Support Opensource <support.opensource@diasemi.com>,
linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org,
patches@opensource.cirrus.com
Subject: [PATCH v2 03/21] ASoC: codecs: tlv320aic32x4: Fix clock leak from runtime callbacks
Date: Wed, 23 Sep 2026 15:12:47 +0900 [thread overview]
Message-ID: <20260923061305.4041197-4-chancel.liu@oss.nxp.com> (raw)
In-Reply-To: <20260923061305.4041197-1-chancel.liu@oss.nxp.com>
From: Chancel Liu <chancel.liu@nxp.com>
component->dev is the underlying I2C/SPI device. The driver acquired
its codec clocks with devm_clk_get()/devm_clk_bulk_get(component->dev,
...) from the DAI set_sysclk runtime callback, from set_bias_level and
from the component .probe. Because devres on component->dev is only
released when the platform device is removed, each card bind/unbind
(and, for set_sysclk, each runtime invocation) leaked a fresh clock
reference.
Acquire all codec clocks once in the bus probe with a single
devm_clk_bulk_get() into the private struct, and have the runtime
callbacks and both component probes reuse those stored references.
Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
---
sound/soc/codecs/tlv320aic32x4.c | 94 +++++++++++++++-----------------
1 file changed, 44 insertions(+), 50 deletions(-)
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index af4be5bee723..7fec94768afb 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -48,8 +48,18 @@ struct aic32x4_priv {
enum aic32x4_type type;
unsigned int fmt;
+
+ struct clk_bulk_data clocks[7];
};
+#define AIC32X4_CLK_CODEC_CLKIN 0
+#define AIC32X4_CLK_PLL 1
+#define AIC32X4_CLK_NADC 2
+#define AIC32X4_CLK_MADC 3
+#define AIC32X4_CLK_NDAC 4
+#define AIC32X4_CLK_MDAC 5
+#define AIC32X4_CLK_BDIV 6
+
static int aic32x4_reset_adc(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -591,14 +601,10 @@ static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_component *component = codec_dai->component;
+ struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
struct clk *mclk;
- struct clk *pll;
-
- pll = devm_clk_get(component->dev, "pll");
- if (IS_ERR(pll))
- return PTR_ERR(pll);
- mclk = clk_get_parent(pll);
+ mclk = clk_get_parent(aic32x4->clocks[AIC32X4_CLK_PLL].clk);
return clk_set_rate(mclk, freq);
}
@@ -750,17 +756,7 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component,
unsigned long adc_clock_rate, dac_clock_rate;
int ret;
- struct clk_bulk_data clocks[] = {
- { .id = "pll" },
- { .id = "nadc" },
- { .id = "madc" },
- { .id = "ndac" },
- { .id = "mdac" },
- { .id = "bdiv" },
- };
- ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
- if (ret)
- return ret;
+ struct clk_bulk_data *clocks = &aic32x4->clocks[AIC32X4_CLK_PLL];
ret = aic32x4_configure_rate(component, sample_rate, &aosr,
&adc_resource_class, &dac_resource_class,
@@ -876,18 +872,15 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
+ struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
int ret;
struct clk_bulk_data clocks[] = {
- { .id = "madc" },
- { .id = "mdac" },
- { .id = "bdiv" },
+ aic32x4->clocks[AIC32X4_CLK_MADC],
+ aic32x4->clocks[AIC32X4_CLK_MDAC],
+ aic32x4->clocks[AIC32X4_CLK_BDIV],
};
- ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
- if (ret)
- return ret;
-
switch (level) {
case SND_SOC_BIAS_ON:
ret = clk_bulk_prepare_enable(ARRAY_SIZE(clocks), clocks);
@@ -970,23 +963,16 @@ static int aic32x4_component_probe(struct snd_soc_component *component)
{
struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
u32 tmp_reg;
- int ret;
- struct clk_bulk_data clocks[] = {
- { .id = "codec_clkin" },
- { .id = "pll" },
- { .id = "bdiv" },
- { .id = "mdac" },
- };
-
- ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
- if (ret)
- return ret;
+ struct clk *codec_clkin = aic32x4->clocks[AIC32X4_CLK_CODEC_CLKIN].clk;
+ struct clk *pll = aic32x4->clocks[AIC32X4_CLK_PLL].clk;
+ struct clk *bdiv = aic32x4->clocks[AIC32X4_CLK_BDIV].clk;
+ struct clk *mdac = aic32x4->clocks[AIC32X4_CLK_MDAC].clk;
aic32x4_setup_gpios(component);
- clk_set_parent(clocks[0].clk, clocks[1].clk);
- clk_set_parent(clocks[2].clk, clocks[3].clk);
+ clk_set_parent(codec_clkin, pll);
+ clk_set_parent(bdiv, mdac);
/* Power platform configuration */
if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
@@ -1127,23 +1113,16 @@ static int aic32x4_tas2505_component_probe(struct snd_soc_component *component)
{
struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
u32 tmp_reg;
- int ret;
-
- struct clk_bulk_data clocks[] = {
- { .id = "codec_clkin" },
- { .id = "pll" },
- { .id = "bdiv" },
- { .id = "mdac" },
- };
- ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
- if (ret)
- return ret;
+ struct clk *codec_clkin = aic32x4->clocks[AIC32X4_CLK_CODEC_CLKIN].clk;
+ struct clk *pll = aic32x4->clocks[AIC32X4_CLK_PLL].clk;
+ struct clk *bdiv = aic32x4->clocks[AIC32X4_CLK_BDIV].clk;
+ struct clk *mdac = aic32x4->clocks[AIC32X4_CLK_MDAC].clk;
aic32x4_setup_gpios(component);
- clk_set_parent(clocks[0].clk, clocks[1].clk);
- clk_set_parent(clocks[2].clk, clocks[3].clk);
+ clk_set_parent(codec_clkin, pll);
+ clk_set_parent(bdiv, mdac);
/* Power platform configuration */
if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE)
@@ -1362,6 +1341,21 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap,
if (ret)
goto err_disable_regulators;
+ aic32x4->clocks[AIC32X4_CLK_CODEC_CLKIN].id = "codec_clkin";
+ aic32x4->clocks[AIC32X4_CLK_PLL].id = "pll";
+ aic32x4->clocks[AIC32X4_CLK_NADC].id = "nadc";
+ aic32x4->clocks[AIC32X4_CLK_MADC].id = "madc";
+ aic32x4->clocks[AIC32X4_CLK_NDAC].id = "ndac";
+ aic32x4->clocks[AIC32X4_CLK_MDAC].id = "mdac";
+ aic32x4->clocks[AIC32X4_CLK_BDIV].id = "bdiv";
+
+ ret = devm_clk_bulk_get(dev, ARRAY_SIZE(aic32x4->clocks),
+ aic32x4->clocks);
+ if (ret) {
+ dev_err(dev, "Failed to get clocks\n");
+ goto err_disable_regulators;
+ }
+
switch (aic32x4->type) {
case AIC32X4_TYPE_TAS2505:
ret = devm_snd_soc_register_component(dev,
--
2.50.1
next prev parent reply other threads:[~2026-09-23 6:13 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-23 6:12 [PATCH v2 00/21] ASoC: codecs: Fix resource leaks across card bind/unbind Chancel Liu
2026-09-23 6:12 ` [PATCH v2 01/21] ASoC: codecs: cpcap: Fix devm " Chancel Liu
2026-09-23 6:12 ` [PATCH v2 02/21] ASoC: codecs: da7218: " Chancel Liu
2026-09-23 6:12 ` Chancel Liu [this message]
2026-09-23 6:12 ` [PATCH v2 04/21] ASoC: codecs: twl4030: Acquire board params and hs_extmute GPIO in the platform probe Chancel Liu
2026-09-23 6:12 ` [PATCH v2 05/21] ASoC: codecs: es8316: Move mclk acquisition to the i2c probe Chancel Liu
2026-09-23 8:19 ` Cezary Rojewski
2026-09-23 6:12 ` [PATCH v2 06/21] ASoC: codecs: es8323: " Chancel Liu
2026-09-23 6:12 ` [PATCH v2 07/21] ASoC: codecs: es8311: " Chancel Liu
2026-09-23 6:12 ` [PATCH v2 08/21] ASoC: codecs: es8328: Move clk acquisition to the bus probe Chancel Liu
2026-09-23 6:12 ` [PATCH v2 09/21] ASoC: codecs: rt5640: Move mclk acquisition to the i2c probe Chancel Liu
2026-09-23 8:16 ` Cezary Rojewski
2026-09-23 8:22 ` Chancel Liu
2026-09-23 6:12 ` [PATCH v2 10/21] ASoC: codecs: rt5616: " Chancel Liu
2026-09-23 6:12 ` [PATCH v2 11/21] ASoC: codecs: rt5514: Move clk " Chancel Liu
2026-09-23 8:19 ` Cezary Rojewski
2026-09-23 6:12 ` [PATCH v2 12/21] ASoC: codecs: rt5682s: Move mclk " Chancel Liu
2026-09-23 6:12 ` [PATCH v2 13/21] ASoC: codecs: max98090: " Chancel Liu
2026-09-23 6:12 ` [PATCH v2 14/21] ASoC: codecs: max98095: " Chancel Liu
2026-09-23 6:12 ` [PATCH v2 15/21] ASoC: codecs: wm8985: Move regulator acquisition to the bus probe Chancel Liu
2026-09-23 8:56 ` Charles Keepax
2026-09-23 6:13 ` [PATCH v2 16/21] ASoC: codecs: wm8955: Move regulator acquisition to the i2c probe Chancel Liu
2026-09-23 6:13 ` [PATCH v2 17/21] ASoC: codecs: es8389: Move regulator and mclk " Chancel Liu
2026-09-23 6:13 ` [PATCH v2 18/21] ASoC: codecs: rt5677-spi: Free the DSP context on component remove Chancel Liu
2026-09-23 6:13 ` [PATCH v2 19/21] ASoC: codecs: rt1011: Free the bq/drc coefficient arrays " Chancel Liu
2026-09-23 6:13 ` [PATCH v2 20/21] ASoC: codecs: rt5645: Free the hardware EQ parameters " Chancel Liu
2026-09-23 6:13 ` [PATCH v2 21/21] ASoC: codecs: rt5514-spi: Free the DSP context " Chancel Liu
2026-09-23 12:27 ` [PATCH v2 00/21] ASoC: codecs: Fix resource leaks across card bind/unbind Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260923061305.4041197-4-chancel.liu@oss.nxp.com \
--to=chancel.liu@oss.nxp.com \
--cc=broonie@kernel.org \
--cc=cezary.rojewski@intel.com \
--cc=ckeepax@opensource.cirrus.com \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=oder_chiou@realtek.com \
--cc=patches@opensource.cirrus.com \
--cc=perex@perex.cz \
--cc=support.opensource@diasemi.com \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®