diff mbox series

ASoC: pxa-ssp: make suspend call resilient against multiple invocations

Message ID 20181106112020.10901-1-daniel@zonque.org (mailing list archive)
State New, archived
Headers show
Series ASoC: pxa-ssp: make suspend call resilient against multiple invocations | expand

Commit Message

Daniel Mack Nov. 6, 2018, 11:20 a.m. UTC
The suspend callback is called twice when the machine is suspended, once
through the ASoC layer and once through the platform device layer. Make sure
not to confuse the clock layer with unbalanced calls, and bail out early if
we are already suspended.

Signed-off-by: Daniel Mack <daniel@zonque.org>
---
 sound/soc/pxa/pxa-ssp.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

Comments

Mark Brown Nov. 6, 2018, 4:31 p.m. UTC | #1
On Tue, Nov 06, 2018 at 12:20:20PM +0100, Daniel Mack wrote:
> The suspend callback is called twice when the machine is suspended, once
> through the ASoC layer and once through the platform device layer. Make sure
> not to confuse the clock layer with unbalanced calls, and bail out early if
> we are already suspended.

This feels like something we should be fixing at the core level - as far
as I can tell there's no PXA specific duplication going on here, it's
the core that's triggering the suspend operation twice so it's likely
that there's going to be problems on other platforms somehow.  Or is
there something PXA specific I'm missing here?
diff mbox series

Patch

diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index adcf8ba9d287..fd93706702a6 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -51,6 +51,7 @@  struct ssp_priv {
 	uint32_t	cr1;
 	uint32_t	to;
 	uint32_t	psp;
+	bool		suspended;
 #endif
 };
 
@@ -142,6 +143,9 @@  static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
 	struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
 	struct ssp_device *ssp = priv->ssp;
 
+	if (priv->suspended)
+		return 0;
+
 	if (!cpu_dai->active)
 		clk_prepare_enable(ssp->clk);
 
@@ -152,6 +156,8 @@  static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
 
 	pxa_ssp_disable(ssp);
 	clk_disable_unprepare(ssp->clk);
+	priv->suspended = true;
+
 	return 0;
 }
 
@@ -161,6 +167,9 @@  static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
 	struct ssp_device *ssp = priv->ssp;
 	uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE;
 
+	if (!priv->suspended)
+		return 0;
+
 	clk_prepare_enable(ssp->clk);
 
 	__raw_writel(sssr, ssp->mmio_base + SSSR);
@@ -174,6 +183,8 @@  static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
 	else
 		clk_disable_unprepare(ssp->clk);
 
+	priv->suspended = false;
+
 	return 0;
 }