From a83cba6338dc1a40eaff3acf45fadfff71e6da6b Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Sun, 16 Apr 2023 18:53:40 +0900 Subject: [PATCH] ASoC: apple: mca: Move clock shutdown to be shutdown Codecs are set to mute after hw_free, so yanking the clock out from under them in hw_free leads to breakage. Move the clock shutdown to the shutdown op, which is late enough. Signed-off-by: Hector Martin --- sound/soc/apple/mca.c | 48 ++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c index 409b3a716ccbcb..8ca40d8e87fed2 100644 --- a/sound/soc/apple/mca.c +++ b/sound/soc/apple/mca.c @@ -355,33 +355,6 @@ static int mca_be_prepare(struct snd_pcm_substream *substream, return 0; } -static int mca_be_hw_free(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; - - if (cl->port_driver < 0) - return -EINVAL; - - /* - * We are operating on a foreign cluster here, but since we - * belong to the same PCM, accesses should have been - * synchronized at ASoC level. - */ - fe_cl = &mca->clusters[cl->port_driver]; - if (!mca_fe_clocks_in_use(fe_cl)) - return 0; /* Nothing to do */ - - cl->clocks_in_use[substream->stream] = false; - - if (!mca_fe_clocks_in_use(fe_cl)) - mca_fe_disable_clocks(fe_cl); - - return 0; -} - static unsigned int mca_crop_mask(unsigned int mask, int nchans) { while (hweight32(mask) > nchans) @@ -779,6 +752,26 @@ static void mca_be_shutdown(struct snd_pcm_substream *substream, struct mca_cluster *cl = mca_dai_to_cluster(dai); struct mca_data *mca = cl->host; + if (cl->clocks_in_use[substream->stream] && + !WARN_ON(cl->port_driver < 0)) { + struct mca_cluster *fe_cl = &mca->clusters[cl->port_driver]; + + /* + * Typically the CODECs we are paired with will require clocks + * to be present at time of mute with the 'mute_stream' op. + * We need to disable the clocks here at the earliest (hw_free + * would be too early). + * + * We are operating on a foreign cluster here, but since we + * belong to the same PCM, accesses should have been + * synchronized at ASoC level. + */ + cl->clocks_in_use[substream->stream] = false; + + if (!mca_fe_clocks_in_use(fe_cl)) + mca_fe_disable_clocks(fe_cl); + } + cl->port_started[substream->stream] = false; if (!mca_be_started(cl)) { @@ -796,7 +789,6 @@ static void mca_be_shutdown(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops mca_be_ops = { .prepare = mca_be_prepare, - .hw_free = mca_be_hw_free, .startup = mca_be_startup, .shutdown = mca_be_shutdown, };