From ed36cde37c7d2a14a655f3d251bc16014346336e Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Tue, 13 Jun 2023 22:35:38 +0800 Subject: [PATCH] ASoC: rockchip: rk817-codec: Fix a large number of mclk counts being enabled If it is not controlled, when the path is configured after resume, the clock will be continuously turn on to increase the clock count. Therefore, we can count and control the switch of clock separately according to the current status of playback and capture, so as to avoid that mclk is accidentally turned off when playback and capture exist at the same time, causing the other stream to fail to work. For example: - before: mclk_sai0 2 2 0 11289600 0 0 50000 mclk_sai0_out2io 1 1 0 11289600 0 0 50000 mclk_sai0_to_io 16 16 0 11289600 0 0 50000 - after: mclk_sai0 2 2 0 11289600 0 0 50000 mclk_sai0_out2io 1 1 0 11289600 0 0 50000 mclk_sai0_to_io 2 2 0 11289600 0 0 50000 Change-Id: I78ec18c7ffc42f548e82357bcf20701aa057f15d Signed-off-by: Xing Zheng --- sound/soc/codecs/rk817_codec.c | 41 +++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index f662ba54c99a..91e573255c19 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -67,7 +67,10 @@ struct rk817_codec_priv { struct regmap *regmap; struct rk808 *rk817; struct clk *mclk; + struct mutex clk_lock; + unsigned int clk_capture; + unsigned int clk_playback; unsigned int stereo_sysclk; unsigned int rate; @@ -539,10 +542,19 @@ static int rk817_playback_path_config(struct snd_soc_component *component, DBG("%s : set playback_path %ld, pre_path %ld\n", __func__, rk817->playback_path, pre_path); - if (rk817->playback_path != OFF) - clk_prepare_enable(rk817->mclk); - else - clk_disable_unprepare(rk817->mclk); + mutex_lock(&rk817->clk_lock); + if (rk817->playback_path != OFF) { + if (rk817->clk_playback == 0) { + clk_prepare_enable(rk817->mclk); + rk817->clk_playback++; + } + } else { + if (rk817->clk_playback > 0) { + clk_disable_unprepare(rk817->mclk); + rk817->clk_playback--; + } + } + mutex_unlock(&rk817->clk_lock); switch (rk817->playback_path) { case OFF: @@ -726,10 +738,19 @@ static int rk817_capture_path_config(struct snd_soc_component *component, DBG("%s : set capture_path %ld, pre_path %ld\n", __func__, rk817->capture_path, pre_path); - if (rk817->capture_path != MIC_OFF) - clk_prepare_enable(rk817->mclk); - else - clk_disable_unprepare(rk817->mclk); + mutex_lock(&rk817->clk_lock); + if (rk817->capture_path != MIC_OFF) { + if (rk817->clk_capture == 0) { + clk_prepare_enable(rk817->mclk); + rk817->clk_capture++; + } + } else { + if (rk817->clk_capture > 0) { + clk_disable_unprepare(rk817->mclk); + rk817->clk_capture--; + } + } + mutex_unlock(&rk817->clk_lock); switch (rk817->capture_path) { case MIC_OFF: @@ -1223,6 +1244,9 @@ static int rk817_probe(struct snd_soc_component *component) clk_prepare_enable(rk817->mclk); rk817_reset(component); clk_disable_unprepare(rk817->mclk); + mutex_init(&rk817->clk_lock); + rk817->clk_capture = 0; + rk817->clk_playback = 0; snd_soc_add_component_controls(component, rk817_snd_path_controls, ARRAY_SIZE(rk817_snd_path_controls)); @@ -1243,6 +1267,7 @@ static void rk817_remove(struct snd_soc_component *component) rk817_codec_power_down(component, RK817_CODEC_ALL); snd_soc_component_exit_regmap(component); + mutex_destroy(&rk817->clk_lock); mdelay(10); }