Commit 8e097f9a authored by Amadeusz Sławiński's avatar Amadeusz Sławiński Committed by Mark Brown

ASoC: Intel: avs: Handle SUSPEND and RESUME triggers

With power management operations added, service SUSPEND and RESUME
trigger commands for running streams.
Signed-off-by: default avatarAmadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Signed-off-by: default avatarCezary Rojewski <cezary.rojewski@intel.com>
Link: https://lore.kernel.org/r/20221027124702.1761002-5-cezary.rojewski@intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent efffb014
...@@ -208,30 +208,43 @@ static int avs_dai_nonhda_be_prepare(struct snd_pcm_substream *substream, struct ...@@ -208,30 +208,43 @@ static int avs_dai_nonhda_be_prepare(struct snd_pcm_substream *substream, struct
static int avs_dai_nonhda_be_trigger(struct snd_pcm_substream *substream, int cmd, static int avs_dai_nonhda_be_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
struct avs_dma_data *data; struct avs_dma_data *data;
int ret = 0; int ret = 0;
data = snd_soc_dai_get_dma_data(dai, substream); data = snd_soc_dai_get_dma_data(dai, substream);
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_RESUME:
if (rtd->dai_link->ignore_suspend)
break;
fallthrough;
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
ret = avs_path_pause(data->path);
if (ret < 0) {
dev_err(dai->dev, "pause BE path failed: %d\n", ret);
break;
}
ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO); ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
if (ret < 0) if (ret < 0)
dev_err(dai->dev, "run BE path failed: %d\n", ret); dev_err(dai->dev, "run BE path failed: %d\n", ret);
break; break;
case SNDRV_PCM_TRIGGER_SUSPEND:
if (rtd->dai_link->ignore_suspend)
break;
fallthrough;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
ret = avs_path_pause(data->path); ret = avs_path_pause(data->path);
if (ret < 0) if (ret < 0)
dev_err(dai->dev, "pause BE path failed: %d\n", ret); dev_err(dai->dev, "pause BE path failed: %d\n", ret);
if (cmd == SNDRV_PCM_TRIGGER_STOP) { ret = avs_path_reset(data->path);
ret = avs_path_reset(data->path); if (ret < 0)
if (ret < 0) dev_err(dai->dev, "reset BE path failed: %d\n", ret);
dev_err(dai->dev, "reset BE path failed: %d\n", ret);
}
break; break;
default: default:
...@@ -351,6 +364,7 @@ static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct sn ...@@ -351,6 +364,7 @@ static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct sn
static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd, static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
struct hdac_ext_stream *link_stream; struct hdac_ext_stream *link_stream;
struct avs_dma_data *data; struct avs_dma_data *data;
int ret = 0; int ret = 0;
...@@ -361,15 +375,29 @@ static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -361,15 +375,29 @@ static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd,
link_stream = substream->runtime->private_data; link_stream = substream->runtime->private_data;
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_RESUME:
if (rtd->dai_link->ignore_suspend)
break;
fallthrough;
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
snd_hdac_ext_stream_start(link_stream); snd_hdac_ext_stream_start(link_stream);
ret = avs_path_pause(data->path);
if (ret < 0) {
dev_err(dai->dev, "pause BE path failed: %d\n", ret);
break;
}
ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO); ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
if (ret < 0) if (ret < 0)
dev_err(dai->dev, "run BE path failed: %d\n", ret); dev_err(dai->dev, "run BE path failed: %d\n", ret);
break; break;
case SNDRV_PCM_TRIGGER_SUSPEND:
if (rtd->dai_link->ignore_suspend)
break;
fallthrough;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
ret = avs_path_pause(data->path); ret = avs_path_pause(data->path);
...@@ -378,11 +406,9 @@ static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -378,11 +406,9 @@ static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd,
snd_hdac_ext_stream_clear(link_stream); snd_hdac_ext_stream_clear(link_stream);
if (cmd == SNDRV_PCM_TRIGGER_STOP) { ret = avs_path_reset(data->path);
ret = avs_path_reset(data->path); if (ret < 0)
if (ret < 0) dev_err(dai->dev, "reset BE path failed: %d\n", ret);
dev_err(dai->dev, "reset BE path failed: %d\n", ret);
}
break; break;
default: default:
...@@ -587,6 +613,7 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so ...@@ -587,6 +613,7 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so
static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
struct avs_dma_data *data; struct avs_dma_data *data;
struct hdac_ext_stream *host_stream; struct hdac_ext_stream *host_stream;
struct hdac_bus *bus; struct hdac_bus *bus;
...@@ -598,17 +625,36 @@ static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, stru ...@@ -598,17 +625,36 @@ static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, stru
bus = hdac_stream(host_stream)->bus; bus = hdac_stream(host_stream)->bus;
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_RESUME:
if (rtd->dai_link->ignore_suspend)
break;
fallthrough;
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
spin_lock_irqsave(&bus->reg_lock, flags); spin_lock_irqsave(&bus->reg_lock, flags);
snd_hdac_stream_start(hdac_stream(host_stream), true); snd_hdac_stream_start(hdac_stream(host_stream), true);
spin_unlock_irqrestore(&bus->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
/* Timeout on DRSM poll shall not stop the resume so ignore the result. */
if (cmd == SNDRV_PCM_TRIGGER_RESUME)
snd_hdac_stream_wait_drsm(hdac_stream(host_stream));
ret = avs_path_pause(data->path);
if (ret < 0) {
dev_err(dai->dev, "pause FE path failed: %d\n", ret);
break;
}
ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO); ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
if (ret < 0) if (ret < 0)
dev_err(dai->dev, "run FE path failed: %d\n", ret); dev_err(dai->dev, "run FE path failed: %d\n", ret);
break; break;
case SNDRV_PCM_TRIGGER_SUSPEND:
if (rtd->dai_link->ignore_suspend)
break;
fallthrough;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
ret = avs_path_pause(data->path); ret = avs_path_pause(data->path);
...@@ -619,11 +665,9 @@ static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, stru ...@@ -619,11 +665,9 @@ static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, stru
snd_hdac_stream_stop(hdac_stream(host_stream)); snd_hdac_stream_stop(hdac_stream(host_stream));
spin_unlock_irqrestore(&bus->reg_lock, flags); spin_unlock_irqrestore(&bus->reg_lock, flags);
if (cmd == SNDRV_PCM_TRIGGER_STOP) { ret = avs_path_reset(data->path);
ret = avs_path_reset(data->path); if (ret < 0)
if (ret < 0) dev_err(dai->dev, "reset FE path failed: %d\n", ret);
dev_err(dai->dev, "reset FE path failed: %d\n", ret);
}
break; break;
default: default:
...@@ -974,6 +1018,7 @@ static int avs_component_open(struct snd_soc_component *component, ...@@ -974,6 +1018,7 @@ static int avs_component_open(struct snd_soc_component *component,
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP; SNDRV_PCM_INFO_NO_PERIOD_WAKEUP;
hwparams.formats = SNDRV_PCM_FMTBIT_S16_LE | hwparams.formats = SNDRV_PCM_FMTBIT_S16_LE |
......
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