[PATCH v2 2/2] ASoC: codecs: rt5631: Enable the optional MCLK
From: Romain TISSERAND
Date: Sun Nov 01 2026 - 09:32:00 EST
When the RT5631 master clock comes from a SoC clock output, nothing in
the codec driver keeps it running, and the clock framework turns it off
at boot as an unused clock.
Get an optional "mclk" clock in the I2C probe and enable it while the
codec is active, from the PREPARE bias level, as rt5616 does. The rate
is left to the CPU DAI.
On the GPD XD (RK3288) MCLK is i2s0_clkout, a mux between the I2S clock
and a 12 MHz oscillator. Handed to simple-audio-card instead, it is set
to the stream rate before the CPU DAI sets the I2S clock, so for
12.288 MHz the mux picks the oscillator and audio plays at the wrong
pitch. Held by the codec, it follows the I2S clock.
Signed-off-by: Romain TISSERAND <romain.tisserand@xxxxxxxxx>
---
sound/soc/codecs/rt5631.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index f97fd24e42..d523d6d3a2 100644
--- a/sound/soc/codecs/rt5631.c
+++ b/sound/soc/codecs/rt5631.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
@@ -27,6 +28,7 @@
struct rt5631_priv {
struct regmap *regmap;
+ struct clk *mclk;
int codec_version;
int master;
int sysclk;
@@ -1536,10 +1538,19 @@ static int rt5631_set_bias_level(struct snd_soc_component *component,
{
struct rt5631_priv *rt5631 = snd_soc_component_get_drvdata(component);
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
+ int ret;
switch (level) {
- case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
+ if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_ON) {
+ clk_disable_unprepare(rt5631->mclk);
+ } else {
+ ret = clk_prepare_enable(rt5631->mclk);
+ if (ret)
+ return ret;
+ }
+ fallthrough;
+ case SND_SOC_BIAS_ON:
snd_soc_component_update_bits(component, RT5631_PWR_MANAG_ADD2,
RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL,
RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL);
@@ -1726,6 +1737,11 @@ static int rt5631_i2c_probe(struct i2c_client *i2c)
if (IS_ERR(rt5631->regmap))
return PTR_ERR(rt5631->regmap);
+ rt5631->mclk = devm_clk_get_optional(&i2c->dev, "mclk");
+ if (IS_ERR(rt5631->mclk))
+ return dev_err_probe(&i2c->dev, PTR_ERR(rt5631->mclk),
+ "failed to get the mclk clock\n");
+
ret = devm_snd_soc_register_component(&i2c->dev,
&soc_component_dev_rt5631,
rt5631_dai, ARRAY_SIZE(rt5631_dai));
--
2.43.0