[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250518-mca-fixes-v1-8-ee1015a695f6@gmail.com>
Date: Sun, 18 May 2025 20:50:53 +1000
From: James Calligeros <jcalligeros99@...il.com>
To: Martin PoviĊĦer <povik+lin@...ebit.org>,
Liam Girdwood <lgirdwood@...il.com>, Mark Brown <broonie@...nel.org>,
Jaroslav Kysela <perex@...ex.cz>, Takashi Iwai <tiwai@...e.com>
Cc: asahi@...ts.linux.dev, linux-sound@...r.kernel.org,
linux-kernel@...r.kernel.org, Hector Martin <marcan@...can.st>,
James Calligeros <jcalligeros99@...il.com>
Subject: [PATCH 8/9] ASoC: apple: mca: Do not mark clocks in use for
non-providers
From: Hector Martin <marcan@...can.st>
On the speakers PCM, this sequence:
1. Open playback
2. Open sense
3. Close playback
4. Close sense
would result in the sense FE being marked as clocks in use at (2), since
there is a clock provider (playback FE). Then at (4) this would WARN since
there is no driver any more when closing the in use clocks.
If (1) and (2) are reversed this does not happen, since the sense PCM is
not marked as using the clocks when there is no provider yet. So, check
explicitly whether the substream FE is a clock provider in be_prepare,
and skip everything if it isn't.
Signed-off-by: Hector Martin <marcan@...can.st>
Signed-off-by: James Calligeros <jcalligeros99@...il.com>
---
sound/soc/apple/mca.c | 67 ++++++++++++++-----------
1 file changed, 37 insertions(+), 30 deletions(-)
diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c
index 441da5ef3de1c0be1dc607ff2490046206660e59..25d04b3d8a57a8551f2ac1c0cd2dbf2997d907e8 100644
--- a/sound/soc/apple/mca.c
+++ b/sound/soc/apple/mca.c
@@ -354,36 +354,6 @@ static bool mca_fe_clocks_in_use(struct mca_cluster *cl)
return false;
}
-static int mca_be_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct mca_cluster *cl = mca_dai_to_cluster(dai);
- struct mca_data *mca = cl->host;
- struct mca_cluster *fe_cl;
- int ret;
-
- if (cl->port_clk_driver < 0)
- return 0;
-
- fe_cl = &mca->clusters[cl->port_clk_driver];
-
- /*
- * Typically the CODECs we are paired with will require clocks
- * to be present at time of unmute with the 'mute_stream' op
- * or at time of DAPM widget power-up. We need to enable clocks
- * here at the latest (frontend prepare would be too late).
- */
- if (!mca_fe_clocks_in_use(fe_cl)) {
- ret = mca_fe_enable_clocks(fe_cl);
- if (ret < 0)
- return ret;
- }
-
- cl->clocks_in_use[substream->stream] = true;
-
- return 0;
-}
-
static int mca_fe_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -787,6 +757,43 @@ static struct snd_soc_pcm_runtime *mca_be_get_fe(struct snd_soc_pcm_runtime *be,
return fe;
}
+static int mca_be_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *be = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_pcm_runtime *fe = mca_be_get_fe(be, substream->stream);
+ struct mca_cluster *cl = mca_dai_to_cluster(dai);
+ struct mca_data *mca = cl->host;
+ struct mca_cluster *fe_cl, *fe_clk_cl;
+ int ret;
+
+ fe_cl = mca_dai_to_cluster(snd_soc_rtd_to_cpu(fe, 0));
+
+ if (!fe_cl->clk_provider)
+ return 0;
+
+ if (cl->port_clk_driver < 0)
+ return 0;
+
+ fe_clk_cl = &mca->clusters[cl->port_clk_driver];
+
+ /*
+ * Typically the CODECs we are paired with will require clocks
+ * to be present at time of unmute with the 'mute_stream' op
+ * or at time of DAPM widget power-up. We need to enable clocks
+ * here at the latest (frontend prepare would be too late).
+ */
+ if (!mca_fe_clocks_in_use(fe_clk_cl)) {
+ ret = mca_fe_enable_clocks(fe_clk_cl);
+ if (ret < 0)
+ return ret;
+ }
+
+ cl->clocks_in_use[substream->stream] = true;
+
+ return 0;
+}
+
static int mca_be_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
--
2.49.0
Powered by blists - more mailing lists