Add support for runtime pm ops for soundwire dma driver.
Signed-off-by: Vijendar Mukunda Vijendar.Mukunda@amd.com --- sound/soc/amd/ps/ps-sdw-dma.c | 66 +++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+)
diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index e94f76053c66..960c0bc5e848 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -12,6 +12,7 @@ #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/soc-dai.h> +#include <linux/pm_runtime.h> #include <linux/soundwire/sdw_amd.h> #include "acp63.h"
@@ -56,6 +57,30 @@ static const struct snd_pcm_hardware acp63_sdw_hardware_capture = { .periods_max = SDW_CAPTURE_MAX_NUM_PERIODS, };
+static void acp63_enable_disable_sdw_dma_interrupts(void __iomem *acp_base, bool enable) +{ + u32 ext_intr_cntl, ext_intr_cntl1, irq_mask, irq_mask1; + + irq_mask = ACP_SDW_DMA_IRQ_MASK; + irq_mask1 = ACP_P1_SDW_DMA_IRQ_MASK; + + if (enable) { + ext_intr_cntl = acp63_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_intr_cntl |= irq_mask; + acp63_writel(ext_intr_cntl, acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_intr_cntl1 = acp63_readl(acp_base + ACP_EXTERNAL_INTR_CNTL1); + ext_intr_cntl1 |= irq_mask1; + acp63_writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1); + } else { + ext_intr_cntl = acp63_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_intr_cntl &= ~irq_mask; + acp63_writel(ext_intr_cntl, acp_base + ACP_EXTERNAL_INTR_CNTL); + ext_intr_cntl1 = acp63_readl(acp_base + ACP_EXTERNAL_INTR_CNTL1); + ext_intr_cntl1 &= ~irq_mask1; + acp63_writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1); + } +} + static void acp63_config_dma(struct sdw_stream_instance *sdw_ins, u32 stream_id) { u16 page_idx; @@ -585,13 +610,54 @@ static int acp63_sdw_platform_probe(struct platform_device *pdev)
return -ENODEV; } + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); + pm_runtime_allow(&pdev->dev); + return 0; +} + +static int acp63_sdw_platform_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + return 0; +} + +static int __maybe_unused acp63_sdw_pcm_runtime_suspend(struct device *dev) +{ + struct sdw_dma_dev_data *sdw_dma_data; + + sdw_dma_data = dev_get_drvdata(dev); + mutex_lock(sdw_dma_data->acp_lock); + acp63_enable_disable_sdw_dma_interrupts(sdw_dma_data->acp_base, false); + mutex_unlock(sdw_dma_data->acp_lock); + + return 0; +} + +static int __maybe_unused acp63_sdw_pcm_runtime_resume(struct device *dev) +{ + struct sdw_dma_dev_data *sdw_dma_data; + + sdw_dma_data = dev_get_drvdata(dev); + mutex_lock(sdw_dma_data->acp_lock); + acp63_enable_disable_sdw_dma_interrupts(sdw_dma_data->acp_base, true); + mutex_unlock(sdw_dma_data->acp_lock); + return 0; }
+static const struct dev_pm_ops acp63_pm_ops = { + SET_RUNTIME_PM_OPS(acp63_sdw_pcm_runtime_suspend, + acp63_sdw_pcm_runtime_resume, NULL) +}; + static struct platform_driver acp63_sdw_dma_driver = { .probe = acp63_sdw_platform_probe, + .remove = acp63_sdw_platform_remove, .driver = { .name = "amd_ps_sdw_dma", + .pm = &acp63_pm_ops, }, };