[PATCH 2/2] ASoC: codecs: rt5631: Enable the optional MCLK
From: Romain TISSERAND
Date: Sun Oct 25 2026 - 10:54:10 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 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 | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index f97fd24e42..82d5e8b9c8 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);
@@ -1579,6 +1590,10 @@ static int rt5631_probe(struct snd_soc_component *component)
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
unsigned int val;
+ rt5631->mclk = devm_clk_get_optional(component->dev, "mclk");
+ if (IS_ERR(rt5631->mclk))
+ return PTR_ERR(rt5631->mclk);
+
val = rt5631_read_index(component, RT5631_ADDA_MIXER_INTL_REG3);
if (val & 0x0002)
rt5631->codec_version = 1;
--
2.43.0