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>
This commit is contained in:
parent
051744b1bf
commit
657774acd0
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue