Commit 7077a07a authored by Ranjani Sridharan's avatar Ranjani Sridharan Committed by Mark Brown

ASoC: SOF: Intel: hda: release link DMA for paused streams during suspend

Paused streams do not get suspended when the system enters S3.
So, clear and release link DMA channel for such streams in the
hda_dsp_set_hw_params_upon_resume() callback. Also, invalidate
the link DMA channel in the DAI config before restoring the
dai config upon resume. Also, modify the signature for the
set_hw_params_upon_resume() op to return an int.
Signed-off-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 6b2239e3
...@@ -454,18 +454,45 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, int state) ...@@ -454,18 +454,45 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, int state)
return 0; return 0;
} }
void hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
{ {
struct hdac_bus *bus = sof_to_bus(sdev); struct hdac_bus *bus = sof_to_bus(sdev);
struct sof_intel_hda_stream *hda_stream; struct sof_intel_hda_stream *hda_stream;
struct hdac_ext_stream *stream; struct hdac_ext_stream *stream;
struct hdac_stream *s; struct hdac_stream *s;
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
struct snd_soc_pcm_runtime *rtd;
struct hdac_ext_link *link;
const char *name;
int stream_tag;
#endif
/* set internal flag for BE */ /* set internal flag for BE */
list_for_each_entry(s, &bus->stream_list, list) { list_for_each_entry(s, &bus->stream_list, list) {
stream = stream_to_hdac_ext_stream(s); stream = stream_to_hdac_ext_stream(s);
hda_stream = container_of(stream, struct sof_intel_hda_stream, hda_stream = container_of(stream, struct sof_intel_hda_stream,
hda_stream); hda_stream);
hda_stream->hw_params_upon_resume = 1; hda_stream->hw_params_upon_resume = 1;
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
/*
* clear and release stream. This should already be taken care
* for running streams when the SUSPEND trigger is called.
* But paused streams do not get suspended, so this needs to be
* done explicitly during suspend.
*/
if (stream->link_substream) {
rtd = snd_pcm_substream_chip(stream->link_substream);
name = rtd->codec_dai->component->name;
link = snd_hdac_ext_bus_get_link(bus, name);
if (!link)
return -EINVAL;
stream_tag = hdac_stream(stream)->stream_tag;
snd_hdac_ext_link_clear_stream_id(link, stream_tag);
snd_hdac_ext_stream_release(stream,
HDAC_EXT_STREAM_TYPE_LINK);
}
#endif
} }
return 0;
} }
...@@ -451,7 +451,7 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, int state); ...@@ -451,7 +451,7 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, int state);
int hda_dsp_resume(struct snd_sof_dev *sdev); int hda_dsp_resume(struct snd_sof_dev *sdev);
int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state); int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev, int state);
int hda_dsp_runtime_resume(struct snd_sof_dev *sdev); int hda_dsp_runtime_resume(struct snd_sof_dev *sdev);
void hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev);
void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags); void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags);
void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags); void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags);
void hda_ipc_dump(struct snd_sof_dev *sdev); void hda_ipc_dump(struct snd_sof_dev *sdev);
......
...@@ -134,10 +134,11 @@ static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev, ...@@ -134,10 +134,11 @@ static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev,
return 0; return 0;
} }
static inline void snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev) static inline int snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev)
{ {
if (sof_ops(sdev)->set_hw_params_upon_resume) if (sof_ops(sdev)->set_hw_params_upon_resume)
sof_ops(sdev)->set_hw_params_upon_resume(sdev); return sof_ops(sdev)->set_hw_params_upon_resume(sdev);
return 0;
} }
static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq) static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq)
......
...@@ -153,6 +153,15 @@ static int sof_restore_pipelines(struct snd_sof_dev *sdev) ...@@ -153,6 +153,15 @@ static int sof_restore_pipelines(struct snd_sof_dev *sdev)
continue; continue;
} }
/*
* The link DMA channel would be invalidated for running
* streams but not for streams that were in the PAUSED
* state during suspend. So invalidate it here before setting
* the dai config in the DSP.
*/
if (config->type == SOF_DAI_INTEL_HDA)
config->hda.link_dma_ch = DMA_CHAN_INVALID;
ret = sof_ipc_tx_message(sdev->ipc, ret = sof_ipc_tx_message(sdev->ipc,
config->hdr.cmd, config, config->hdr.cmd, config,
config->hdr.size, config->hdr.size,
...@@ -204,7 +213,7 @@ static int sof_send_pm_ipc(struct snd_sof_dev *sdev, int cmd) ...@@ -204,7 +213,7 @@ static int sof_send_pm_ipc(struct snd_sof_dev *sdev, int cmd)
sizeof(pm_ctx), &reply, sizeof(reply)); sizeof(pm_ctx), &reply, sizeof(reply));
} }
static void sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev) static int sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
{ {
struct snd_pcm_substream *substream; struct snd_pcm_substream *substream;
struct snd_sof_pcm *spcm; struct snd_sof_pcm *spcm;
...@@ -229,7 +238,7 @@ static void sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev) ...@@ -229,7 +238,7 @@ static void sof_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
} }
/* set internal flag for BE */ /* set internal flag for BE */
snd_sof_dsp_hw_params_upon_resume(sdev); return snd_sof_dsp_hw_params_upon_resume(sdev);
} }
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
...@@ -333,8 +342,15 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) ...@@ -333,8 +342,15 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
snd_sof_release_trace(sdev); snd_sof_release_trace(sdev);
/* set restore_stream for all streams during system suspend */ /* set restore_stream for all streams during system suspend */
if (!runtime_suspend) if (!runtime_suspend) {
sof_set_hw_params_upon_resume(sdev); ret = sof_set_hw_params_upon_resume(sdev);
if (ret < 0) {
dev_err(sdev->dev,
"error: setting hw_params flag during suspend %d\n",
ret);
return ret;
}
}
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
/* cache debugfs contents during runtime suspend */ /* cache debugfs contents during runtime suspend */
......
...@@ -172,7 +172,7 @@ struct snd_sof_dsp_ops { ...@@ -172,7 +172,7 @@ struct snd_sof_dsp_ops {
int (*runtime_suspend)(struct snd_sof_dev *sof_dev, int (*runtime_suspend)(struct snd_sof_dev *sof_dev,
int state); /* optional */ int state); /* optional */
int (*runtime_resume)(struct snd_sof_dev *sof_dev); /* optional */ int (*runtime_resume)(struct snd_sof_dev *sof_dev); /* optional */
void (*set_hw_params_upon_resume)(struct snd_sof_dev *sdev); /* optional */ int (*set_hw_params_upon_resume)(struct snd_sof_dev *sdev); /* optional */
/* DSP clocking */ /* DSP clocking */
int (*set_clk)(struct snd_sof_dev *sof_dev, u32 freq); /* optional */ int (*set_clk)(struct snd_sof_dev *sof_dev, u32 freq); /* optional */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment