[12/12] ASoC: AMD: add ACP PCM driver runtime PM
diff mbox

Message ID 1438871112-25946-12-git-send-email-alexander.deucher@amd.com
State New
Headers show

Commit Message

Alex Deucher Aug. 6, 2015, 2:25 p.m. UTC
From: Maruthi Srinivas Bayyavarapu <Maruthi.Bayyavarapu@amd.com>

Added runtime PM functionality to AMD I2S driver. This uses
functionality from ACP IP methods.

Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Murali Krishna Vemuri <murali-krishna.vemuri@amd.com>
---
 sound/soc/amd/acp-pcm-dma.c | 87 +++++++++++++++++++++++++++++++++++++++------
 1 file changed, 77 insertions(+), 10 deletions(-)

Comments

Mark Brown Aug. 6, 2015, 7:26 p.m. UTC | #1
On Thu, Aug 06, 2015 at 10:25:12AM -0400, Alex Deucher wrote:
> From: Maruthi Srinivas Bayyavarapu <Maruthi.Bayyavarapu@amd.com>
> 
> Added runtime PM functionality to AMD I2S driver. This uses
> functionality from ACP IP methods.

Just add this (and the previous patch) in the driver.  The patches are
so tiny it's not adding much to split them out like this and it's
actually harder to review this one when it's split from the system
suspend code.
Maruthi Srinivas Bayyavarapu Aug. 7, 2015, 9:41 a.m. UTC | #2
Hi Mark,

I will send a another patch-set, with patches  combined, as suggested.

Regards,
Maruthi

-----Original Message-----
From: Mark Brown [mailto:broonie@kernel.org] 
Sent: 07 August 2015 00:57
To: Alex Deucher
Cc: airlied@gmail.com; dri-devel@lists.freedesktop.org; alsa-devel@alsa-project.org; tiwai@suse.de; perex@perex.cz; lgirdwood@gmail.com; Bayyavarapu, Maruthi
Subject: Re: [PATCH 12/12] ASoC: AMD: add ACP PCM driver runtime PM

On Thu, Aug 06, 2015 at 10:25:12AM -0400, Alex Deucher wrote:
> From: Maruthi Srinivas Bayyavarapu <Maruthi.Bayyavarapu@amd.com>
> 
> Added runtime PM functionality to AMD I2S driver. This uses 
> functionality from ACP IP methods.

Just add this (and the previous patch) in the driver.  The patches are so tiny it's not adding much to split them out like this and it's actually harder to review this one when it's split from the system suspend code.

Patch
diff mbox

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index db09b77..7e0e5cb 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -32,6 +32,7 @@ 
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/pci.h>
+#include <linux/pm_runtime.h>
 
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -379,10 +380,12 @@  static int acp_dma_close(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct audio_substream_data *rtd = runtime->private_data;
 
+	struct snd_soc_pcm_runtime *prtd = substream->private_data;
 	kfree(rtd->dma_config);
 	kfree(rtd->i2s_config);
 	kfree(rtd);
 
+	pm_runtime_mark_last_busy(prtd->platform->dev);
 	return 0;
 }
 
@@ -610,6 +613,10 @@  static int acp_amdsoc_probe(struct amd_gnb_bus_dev *adev)
 	else
 		pr_err("ACP initialization Failed\n");
 
+	pm_runtime_set_autosuspend_delay(&adev->dev, 10000);
+	pm_runtime_use_autosuspend(&adev->dev);
+	pm_runtime_enable(&adev->dev);
+
 	return status;
 }
 
@@ -621,36 +628,96 @@  static int acp_amdsoc_remove(struct amd_gnb_bus_dev *adev)
 	snd_soc_unregister_platform(&adev->dev);
 
 	acp_dev->fini(acp_dev);
-
+	pm_runtime_disable(&adev->dev);
 	return 0;
 }
 
 static int acp_pcm_suspend(struct device *dev)
 {
+	bool pm_rts;
+	struct audio_drv_data *adata =
+	    (struct audio_drv_data *)dev_get_drvdata(dev);
+
+	pm_rts = pm_runtime_status_suspended(dev);
+	if (pm_rts == false)
+		adata->acp_dev->fini(adata->acp_dev);
+
 	return 0;
 }
 
 static int acp_pcm_resume(struct device *dev)
 {
-	struct snd_pcm_substream *substream;
-	struct snd_pcm_runtime *runtime;
+	bool pm_rts;
+	struct snd_pcm_substream *pstream, *cstream;
+	struct snd_pcm_runtime *prtd, *crtd;
 	struct audio_substream_data *rtd;
 
-	struct audio_drv_data *irq_data =
+	struct audio_drv_data *adata =
 	    (struct audio_drv_data *)dev_get_drvdata(dev);
 
-	substream = irq_data->play_stream;
-	runtime = substream->runtime;
-	rtd = runtime->private_data;
+	pm_rts = pm_runtime_status_suspended(dev);
+	if (pm_rts == true) {
+		/* Resumed from system wide suspend and there is
+		 * no pending audio activity to resume. */
+		pm_runtime_disable(dev);
+		pm_runtime_set_active(dev);
+		pm_runtime_enable(dev);
+
+		goto out;
+	}
 
-	irq_data->acp_dev->config_i2s(irq_data->acp_dev, rtd->i2s_config);
-	irq_data->acp_dev->config_dma(irq_data->acp_dev, rtd->dma_config);
+	pstream = adata->play_stream;
+	prtd = pstream ? pstream->runtime : NULL;
+	if (prtd != NULL) {
+		/* Resume playback stream from a suspended state */
+		rtd = prtd->private_data;
 
+		adata->acp_dev->config_dma(adata->acp_dev, rtd->dma_config);
+		adata->acp_dev->config_i2s(adata->acp_dev, rtd->i2s_config);
+	}
+
+	cstream = adata->capture_stream;
+	crtd =  cstream ? cstream->runtime : NULL;
+	if (crtd != NULL) {
+		/* Resume capture stream from a suspended state */
+		rtd = crtd->private_data;
+
+		adata->acp_dev->config_dma(adata->acp_dev, rtd->dma_config);
+		adata->acp_dev->config_i2s(adata->acp_dev, rtd->i2s_config);
+	}
+out:
+	return 0;
+}
+
+int acp_pcm_runtime_suspend(struct device *dev)
+{
+	struct audio_drv_data *adata =
+	    (struct audio_drv_data *)dev_get_drvdata(dev);
+
+	adata->acp_dev->acp_suspend(adata->acp_dev);
+	return 0;
+}
+
+int acp_pcm_runtime_resume(struct device *dev)
+{
+	struct audio_drv_data *adata =
+	    (struct audio_drv_data *)dev_get_drvdata(dev);
+
+	adata->acp_dev->acp_resume(adata->acp_dev);
+	return 0;
+}
+
+int acp_pcm_runtime_idle(struct device *dev)
+{
 	return 0;
 }
 
 static const struct dev_pm_ops acp_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(acp_pcm_suspend, acp_pcm_resume)
+	.suspend = acp_pcm_suspend,
+	.resume = acp_pcm_resume,
+	.runtime_suspend = acp_pcm_runtime_suspend,
+	.runtime_resume = acp_pcm_runtime_resume,
+	.runtime_idle = acp_pcm_runtime_idle
 };
 
 static struct amd_gnb_bus_driver acp_dma_driver = {