summaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>2022-03-17 10:50:28 -0700
committerMark Brown <broonie@kernel.org>2022-03-18 16:04:36 +0000
commit657774acd00f3d63ebae06e5d15a74e013cee0ed (patch)
treed0128ddef30c6043ad2d8f992dd45bd93831c928 /sound/soc
parent051744b1bf0b13f63af5de3c296d04ab0cc6117c (diff)
downloadlinux-stable-657774acd00f3d63ebae06e5d15a74e013cee0ed.tar.gz
linux-stable-657774acd00f3d63ebae06e5d15a74e013cee0ed.tar.bz2
linux-stable-657774acd00f3d63ebae06e5d15a74e013cee0ed.zip
ASoC: SOF: Make sof_suspend/resume IPC agnostic
Add a new set of IPC ops for PM with the ctx_save and ctx_restore ops for suspend/resume and implement the ops for IPC3. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20220317175044.1752400-4-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/sof/Makefile2
-rw-r--r--sound/soc/sof/ipc.c1
-rw-r--r--sound/soc/sof/ipc3-ops.h19
-rw-r--r--sound/soc/sof/ipc3-topology.c7
-rw-r--r--sound/soc/sof/ipc3.c44
-rw-r--r--sound/soc/sof/pm.c63
-rw-r--r--sound/soc/sof/sof-priv.h14
7 files changed, 104 insertions, 46 deletions
diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile
index e13dab59764c..59482903a243 100644
--- a/sound/soc/sof/Makefile
+++ b/sound/soc/sof/Makefile
@@ -2,7 +2,7 @@
snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
control.o trace.o iomem-utils.o sof-audio.o stream-ipc.o\
- ipc3-topology.o
+ ipc3-topology.o ipc3.o
ifneq ($(CONFIG_SND_SOC_SOF_CLIENT),)
snd-sof-objs += sof-client.o
endif
diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index 19a294cbbb8d..46a989be9a82 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -17,6 +17,7 @@
#include "sof-priv.h"
#include "sof-audio.h"
#include "ops.h"
+#include "ipc3-ops.h"
typedef void (*ipc_rx_callback)(struct snd_sof_dev *sdev, void *msg_buf);
diff --git a/sound/soc/sof/ipc3-ops.h b/sound/soc/sof/ipc3-ops.h
new file mode 100644
index 000000000000..5d8cab92c1a4
--- /dev/null
+++ b/sound/soc/sof/ipc3-ops.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Copyright(c) 2021 Intel Corporation. All rights reserved.
+ *
+ * Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+ */
+
+#ifndef __SOUND_SOC_SOF_IPC3_OPS_H
+#define __SOUND_SOC_SOF_IPC3_OPS_H
+
+#include "sof-priv.h"
+
+extern const struct sof_ipc_tplg_ops ipc3_tplg_ops;
+extern const struct sof_ipc_ops ipc3_ops;
+
+#endif
diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c
index 8d08ffb37008..bf0cf38f4524 100644
--- a/sound/soc/sof/ipc3-topology.c
+++ b/sound/soc/sof/ipc3-topology.c
@@ -11,6 +11,7 @@
#include <sound/pcm_params.h>
#include "sof-priv.h"
#include "sof-audio.h"
+#include "ipc3-ops.h"
#include "ops.h"
/* Full volume for default values */
@@ -2152,7 +2153,7 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops[SND_SOC_DAPM_TY
sof_ipc3_widget_bind_event},
};
-static const struct sof_ipc_tplg_ops ipc3_tplg_ops = {
+const struct sof_ipc_tplg_ops ipc3_tplg_ops = {
.widget = tplg_ipc3_widget_ops,
.route_setup = sof_ipc3_route_setup,
.control_setup = sof_ipc3_control_setup,
@@ -2163,7 +2164,3 @@ static const struct sof_ipc_tplg_ops ipc3_tplg_ops = {
.widget_setup = sof_ipc3_widget_setup,
.dai_config = sof_ipc3_dai_config,
};
-
-const struct sof_ipc_ops ipc3_ops = {
- .tplg = &ipc3_tplg_ops,
-};
diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c
new file mode 100644
index 000000000000..e71cf30908c6
--- /dev/null
+++ b/sound/soc/sof/ipc3.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+//
+// This file is provided under a dual BSD/GPLv2 license. When using or
+// redistributing this file, you may do so under either license.
+//
+// Copyright(c) 2021 Intel Corporation. All rights reserved.
+//
+//
+
+#include "sof-priv.h"
+#include "ipc3-ops.h"
+
+static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd)
+{
+ struct sof_ipc_pm_ctx pm_ctx = {
+ .hdr.size = sizeof(pm_ctx),
+ .hdr.cmd = SOF_IPC_GLB_PM_MSG | cmd,
+ };
+ struct sof_ipc_reply reply;
+
+ /* send ctx save ipc to dsp */
+ return sof_ipc_tx_message(sdev->ipc, pm_ctx.hdr.cmd, &pm_ctx,
+ sizeof(pm_ctx), &reply, sizeof(reply));
+}
+
+static int sof_ipc3_ctx_save(struct snd_sof_dev *sdev)
+{
+ return sof_ipc3_ctx_ipc(sdev, SOF_IPC_PM_CTX_SAVE);
+}
+
+static int sof_ipc3_ctx_restore(struct snd_sof_dev *sdev)
+{
+ return sof_ipc3_ctx_ipc(sdev, SOF_IPC_PM_CTX_RESTORE);
+}
+
+static const struct sof_ipc_pm_ops ipc3_pm_ops = {
+ .ctx_save = sof_ipc3_ctx_save,
+ .ctx_restore = sof_ipc3_ctx_restore,
+};
+
+const struct sof_ipc_ops ipc3_ops = {
+ .tplg = &ipc3_tplg_ops,
+ .pm = &ipc3_pm_ops,
+};
diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c
index 7300ecadabd9..10adbbd0a9cd 100644
--- a/sound/soc/sof/pm.c
+++ b/sound/soc/sof/pm.c
@@ -48,22 +48,6 @@ static u32 snd_sof_dsp_power_target(struct snd_sof_dev *sdev)
return target_dsp_state;
}
-static int sof_send_pm_ctx_ipc(struct snd_sof_dev *sdev, int cmd)
-{
- struct sof_ipc_pm_ctx pm_ctx;
- struct sof_ipc_reply reply;
-
- memset(&pm_ctx, 0, sizeof(pm_ctx));
-
- /* configure ctx save ipc message */
- pm_ctx.hdr.size = sizeof(pm_ctx);
- pm_ctx.hdr.cmd = SOF_IPC_GLB_PM_MSG | cmd;
-
- /* send ctx save ipc to dsp */
- return sof_ipc_tx_message(sdev->ipc, pm_ctx.hdr.cmd, &pm_ctx,
- sizeof(pm_ctx), &reply, sizeof(reply));
-}
-
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
static void sof_cache_debugfs(struct snd_sof_dev *sdev)
{
@@ -86,6 +70,7 @@ static void sof_cache_debugfs(struct snd_sof_dev *sdev)
static int sof_resume(struct device *dev, bool runtime_resume)
{
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
+ const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm;
u32 old_state = sdev->dsp_power_state.state;
int ret;
@@ -171,11 +156,11 @@ static int sof_resume(struct device *dev, bool runtime_resume)
sof_resume_clients(sdev);
/* notify DSP of system resume */
- ret = sof_send_pm_ctx_ipc(sdev, SOF_IPC_PM_CTX_RESTORE);
- if (ret < 0)
- dev_err(sdev->dev,
- "error: ctx_restore ipc error during resume %d\n",
- ret);
+ if (pm_ops && pm_ops->ctx_restore) {
+ ret = pm_ops->ctx_restore(sdev);
+ if (ret < 0)
+ dev_err(sdev->dev, "ctx_restore IPC error during resume: %d\n", ret);
+ }
return ret;
}
@@ -183,6 +168,7 @@ static int sof_resume(struct device *dev, bool runtime_resume)
static int sof_suspend(struct device *dev, bool runtime_suspend)
{
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
+ const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm;
pm_message_t pm_state;
u32 target_state = 0;
int ret;
@@ -232,21 +218,20 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
sof_cache_debugfs(sdev);
#endif
/* notify DSP of upcoming power down */
- ret = sof_send_pm_ctx_ipc(sdev, SOF_IPC_PM_CTX_SAVE);
- if (ret == -EBUSY || ret == -EAGAIN) {
- /*
- * runtime PM has logic to handle -EBUSY/-EAGAIN so
- * pass these errors up
- */
- dev_err(sdev->dev,
- "error: ctx_save ipc error during suspend %d\n",
- ret);
- return ret;
- } else if (ret < 0) {
- /* FW in unexpected state, continue to power down */
- dev_warn(sdev->dev,
- "ctx_save ipc error %d, proceeding with suspend\n",
- ret);
+ if (pm_ops && pm_ops->ctx_save) {
+ ret = pm_ops->ctx_save(sdev);
+ if (ret == -EBUSY || ret == -EAGAIN) {
+ /*
+ * runtime PM has logic to handle -EBUSY/-EAGAIN so
+ * pass these errors up
+ */
+ dev_err(sdev->dev, "ctx_save IPC error during suspend: %d\n", ret);
+ return ret;
+ } else if (ret < 0) {
+ /* FW in unexpected state, continue to power down */
+ dev_warn(sdev->dev, "ctx_save IPC error: %d, proceeding with suspend\n",
+ ret);
+ }
}
suspend:
@@ -278,9 +263,11 @@ suspend:
int snd_sof_dsp_power_down_notify(struct snd_sof_dev *sdev)
{
+ const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm;
+
/* Notify DSP of upcoming power down */
- if (sof_ops(sdev)->remove)
- return sof_send_pm_ctx_ipc(sdev, SOF_IPC_PM_CTX_SAVE);
+ if (sof_ops(sdev)->remove && pm_ops && pm_ops->ctx_save)
+ return pm_ops->ctx_save(sdev);
return 0;
}
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index 0b89c3e6ef21..3e883044dd0f 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -360,18 +360,28 @@ struct snd_sof_ipc_msg {
bool ipc_complete;
};
+/**
+ * struct sof_ipc_pm_ops - IPC-specific PM ops
+ * @ctx_save: Function pointer for context save
+ * @ctx_restore: Function pointer for context restore
+ */
+struct sof_ipc_pm_ops {
+ int (*ctx_save)(struct snd_sof_dev *sdev);
+ int (*ctx_restore)(struct snd_sof_dev *sdev);
+};
+
struct sof_ipc_tplg_ops;
/**
* struct sof_ipc_ops - IPC-specific ops
* @tplg: Pointer to IPC-specific topology ops
+ * @pm: Pointer to PM ops
*/
struct sof_ipc_ops {
const struct sof_ipc_tplg_ops *tplg;
+ const struct sof_ipc_pm_ops *pm;
};
-extern const struct sof_ipc_ops ipc3_ops;
-
/* SOF generic IPC data */
struct snd_sof_ipc {
struct snd_sof_dev *sdev;