summaryrefslogtreecommitdiffstats
path: root/sound/soc/sof/ipc.c
diff options
context:
space:
mode:
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>2020-01-29 16:07:25 -0600
committerMark Brown <broonie@kernel.org>2020-02-11 11:48:07 +0000
commit63e51fd33fef04b634a0c32ae491ab16a19cb17c (patch)
tree5996a950867d6a946d4404100ff2950e34d17563 /sound/soc/sof/ipc.c
parent207bf12f642f39e749ca65d3efca9d48311e629f (diff)
downloadlinux-63e51fd33fef04b634a0c32ae491ab16a19cb17c.tar.bz2
ASoC: SOF: Intel: cnl: Implement feature to support DSP D0i3 in S0
This patch implements support for DSP D0i3 when the system is in S0. The basic idea is to schedule a delayed work after every successful IPC TX that checks if there are only D0I3-compatible streams active and if so transition the DSP to D0I3. With the introduction of DSP D0I3 in S0, we need to ensure that the DSP is in D0I0 before sending any new IPCs. The exception for this would be the compact IPCs that are used to set the DSP in D0I3/D0I0 states. Signed-off-by: Keyon Jie <yang.jie@linux.intel.com> Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20200129220726.31792-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/sof/ipc.c')
-rw-r--r--sound/soc/sof/ipc.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index b63fc529b456..22d296f95761 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -268,7 +268,6 @@ static int sof_ipc_tx_message_unlocked(struct snd_sof_ipc *ipc, u32 header,
spin_unlock_irq(&sdev->ipc_lock);
if (ret < 0) {
- /* So far IPC TX never fails, consider making the above void */
dev_err_ratelimited(sdev->dev,
"error: ipc tx failed with error %d\n",
ret);
@@ -289,6 +288,32 @@ int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header,
void *msg_data, size_t msg_bytes, void *reply_data,
size_t reply_bytes)
{
+ const struct sof_dsp_power_state target_state = {
+ .state = SOF_DSP_PM_D0,
+ };
+ int ret;
+
+ /* ensure the DSP is in D0 before sending a new IPC */
+ ret = snd_sof_dsp_set_power_state(ipc->sdev, &target_state);
+ if (ret < 0) {
+ dev_err(ipc->sdev->dev, "error: resuming DSP %d\n", ret);
+ return ret;
+ }
+
+ return sof_ipc_tx_message_no_pm(ipc, header, msg_data, msg_bytes,
+ reply_data, reply_bytes);
+}
+EXPORT_SYMBOL(sof_ipc_tx_message);
+
+/*
+ * send IPC message from host to DSP without modifying the DSP state.
+ * This will be used for IPC's that can be handled by the DSP
+ * even in a low-power D0 substate.
+ */
+int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, u32 header,
+ void *msg_data, size_t msg_bytes,
+ void *reply_data, size_t reply_bytes)
+{
int ret;
if (msg_bytes > SOF_IPC_MSG_MAX_SIZE ||
@@ -305,7 +330,7 @@ int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header,
return ret;
}
-EXPORT_SYMBOL(sof_ipc_tx_message);
+EXPORT_SYMBOL(sof_ipc_tx_message_no_pm);
/* handle reply message from DSP */
int snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id)