OSDN Git Service

ASoC: SOF: Make sof_suspend/resume IPC agnostic
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Thu, 17 Mar 2022 17:50:28 +0000 (10:50 -0700)
committerMark Brown <broonie@kernel.org>
Fri, 18 Mar 2022 16:04:36 +0000 (16:04 +0000)
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>
sound/soc/sof/Makefile
sound/soc/sof/ipc.c
sound/soc/sof/ipc3-ops.h [new file with mode: 0644]
sound/soc/sof/ipc3-topology.c
sound/soc/sof/ipc3.c [new file with mode: 0644]
sound/soc/sof/pm.c
sound/soc/sof/sof-priv.h

index e13dab5..5948290 100644 (file)
@@ -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
index 19a294c..46a989b 100644 (file)
@@ -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 (file)
index 0000000..5d8cab9
--- /dev/null
@@ -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
index 8d08ffb..bf0cf38 100644 (file)
@@ -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 (file)
index 0000000..e71cf30
--- /dev/null
@@ -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,
+};
index 7300eca..10adbbd 100644 (file)
@@ -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;
 }
index 0b89c3e..3e88304 100644 (file)
@@ -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;