Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions drivers/soundwire/intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,9 @@ static int intel_component_dais_suspend(struct snd_soc_component *component)
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
struct sdw_cdns_dai_runtime *dai_runtime;

if (sdw_bus_ignore_suspend(&cdns->bus))
continue;

dai_runtime = cdns->dai_runtime_array[dai->id];

if (dai_runtime)
Expand Down
3 changes: 3 additions & 0 deletions drivers/soundwire/intel_ace2x.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,9 @@ static int intel_component_dais_suspend(struct snd_soc_component *component)
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
struct sdw_cdns_dai_runtime *dai_runtime;

if (sdw_bus_ignore_suspend(&cdns->bus))
continue;

dai_runtime = cdns->dai_runtime_array[dai->id];

if (dai_runtime)
Expand Down
9 changes: 9 additions & 0 deletions drivers/soundwire/intel_auxdevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,9 @@ static int __maybe_unused intel_suspend(struct device *dev)
return 0;
}

if (sdw_bus_ignore_suspend(bus))
return 0;

/* Prevent runtime PM from racing with the code below. */
pm_runtime_disable(dev);

Expand Down Expand Up @@ -734,6 +737,12 @@ static int __maybe_unused intel_resume(struct device *dev)
return 0;
}

if (sdw_bus_ignore_suspend(bus)) {
dev_dbg(dev, "SoundWire master %d remained active during system suspend\n",
bus->link_id);
return 0;
}

ret = sdw_intel_link_power_up(sdw);
if (ret) {
dev_err(dev, "%s failed: %d\n", __func__, ret);
Expand Down
18 changes: 18 additions & 0 deletions drivers/soundwire/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -1679,6 +1679,24 @@ int sdw_enable_stream(struct sdw_stream_runtime *stream)
}
EXPORT_SYMBOL(sdw_enable_stream);

bool sdw_bus_ignore_suspend(struct sdw_bus *bus)
{
struct sdw_master_runtime *m_rt;
bool ret = false;

mutex_lock(&bus->bus_lock);
list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) {
if (m_rt->stream->ignore_suspend) {
ret = true;
break;
}
}
mutex_unlock(&bus->bus_lock);

return ret;
}
EXPORT_SYMBOL(sdw_bus_ignore_suspend);

static int _sdw_disable_stream(struct sdw_stream_runtime *stream)
{
struct sdw_master_runtime *m_rt;
Expand Down
3 changes: 3 additions & 0 deletions include/linux/soundwire/sdw.h
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,7 @@ struct sdw_stream_params {
* @master_list: List of Master runtime(s) in this stream.
* master_list can contain only one m_rt per Master instance
* for a stream
* @ignore_suspend: stream keeps running during system suspend
*/
struct sdw_stream_runtime {
const char *name;
Expand All @@ -984,6 +985,7 @@ struct sdw_stream_runtime {
enum sdw_stream_type type;
int m_rt_count;
struct list_head master_list;
bool ignore_suspend;
};

/**
Expand Down Expand Up @@ -1086,6 +1088,7 @@ int sdw_stream_remove_master(struct sdw_bus *bus,
int sdw_startup_stream(void *sdw_substream);
int sdw_prepare_stream(struct sdw_stream_runtime *stream);
int sdw_enable_stream(struct sdw_stream_runtime *stream);
bool sdw_bus_ignore_suspend(struct sdw_bus *bus);
int sdw_disable_stream(struct sdw_stream_runtime *stream);
int sdw_deprepare_stream(struct sdw_stream_runtime *stream);
void sdw_shutdown_stream(void *sdw_substream);
Expand Down
8 changes: 7 additions & 1 deletion sound/soc/sdw_utils/soc_sdw_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1902,6 +1902,10 @@ int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd)

switch (cmd) {
case SNDRV_PCM_TRIGGER_RESUME:
if (sdw_stream->state == SDW_STREAM_ENABLED) {
ret = 0;
break;
}
/*
* The peripherals lose their port configuration when the
* controller is power-gated during system suspend, and an
Expand All @@ -1923,10 +1927,12 @@ int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd)
break;

case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
ret = sdw_disable_stream(sdw_stream);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
ret = sdw_stream->ignore_suspend ? 0 : sdw_disable_stream(sdw_stream);
break;
default:
ret = -EINVAL;
break;
Expand Down
56 changes: 56 additions & 0 deletions sound/soc/sof/intel/hda.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,51 @@ static int sdw_clock_stop_quirks = SDW_INTEL_CLK_STOP_BUS_RESET;
module_param(sdw_clock_stop_quirks, int, 0444);
MODULE_PARM_DESC(sdw_clock_stop_quirks, "SOF SoundWire clock stop quirks");

static bool sdw_be_ignore_suspend(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *be = snd_soc_substream_to_rtd(substream);
struct snd_soc_dpcm *dpcm;
int dir = substream->stream;

if (dir != SNDRV_PCM_STREAM_CAPTURE)
return false;

for_each_dpcm_fe(be, dir, dpcm) {
struct snd_soc_pcm_runtime *fe = dpcm->fe;
struct snd_pcm_substream *fe_substream;
struct snd_sof_pcm *spcm;

if (dpcm->state == SND_SOC_DPCM_LINK_STATE_FREE)
continue;

fe_substream = snd_soc_dpcm_get_substream(fe, dir);
if (!fe_substream || !fe_substream->runtime)
continue;

list_for_each_entry(spcm, &sdev->pcm_list, list) {
if (!strcmp(spcm->pcm.pcm_name, fe->dai_link->name))
break;
}

if (!list_entry_is_head(spcm, &sdev->pcm_list, list) &&
spcm->stream[dir].d0i3_compatible &&
spcm->stream[dir].dsp_max_burst_size_in_ms <= 1)
return true;
}

return false;
}

static void sdw_set_stream_ignore_suspend(struct snd_sof_dev *sdev, struct snd_soc_dai *dai,
struct snd_pcm_substream *substream)
{
struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);

if (!IS_ERR_OR_NULL(sdw_stream))
sdw_stream->ignore_suspend = sdw_be_ignore_suspend(sdev, substream);
Comment thread
bardliao marked this conversation as resolved.
}

static int sdw_params_stream(struct device *dev,
struct sdw_intel_stream_params_data *params_data)
{
Expand All @@ -70,6 +115,9 @@ static int sdw_params_stream(struct device *dev,
d->name);
return -EINVAL;
}

sdw_set_stream_ignore_suspend(widget_to_sdev(w), d, params_data->substream);

data.dai_index = (params_data->link_id << 8) | d->id;
data.dai_data = params_data->alh_stream_id;
data.dai_node_id = data.dai_data;
Expand Down Expand Up @@ -108,6 +156,14 @@ struct sdw_intel_ops sdw_callback = {
static int sdw_ace2x_params_stream(struct device *dev,
struct sdw_intel_stream_params_data *params_data)
{
struct snd_soc_dai *d = params_data->dai;
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(d, params_data->substream->stream);

if (!w)
return -EINVAL;

sdw_set_stream_ignore_suspend(widget_to_sdev(w), d, params_data->substream);

return sdw_hda_dai_hw_params(params_data->substream,
params_data->hw_params,
params_data->dai,
Expand Down
38 changes: 38 additions & 0 deletions sound/soc/sof/pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,41 @@ void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream)
}
EXPORT_SYMBOL(snd_sof_pcm_period_elapsed);

static void sof_pcm_set_widget_ignore_suspend(struct snd_sof_dev *sdev,
struct snd_soc_pcm_runtime *rtd,
struct snd_sof_pcm *spcm, int dir,
bool ignore_suspend)
{
struct snd_soc_dai *dai;
int j;

for_each_rtd_cpu_dais(rtd, j, dai) {
struct snd_soc_dapm_widget_list *connected_widgets;
struct snd_soc_dapm_widget *widget;
int connected, i;

connected = snd_soc_dapm_dai_get_connected_widgets(dai, dir,
&connected_widgets,
NULL);
if (connected >= 0) {
for_each_dapm_widgets(connected_widgets, i, widget) {
if (!widget->is_ep)
continue;

dev_dbg(sdev->dev,
"WoV PCM %s ignore suspend for widget %s\n",
spcm->pcm.caps[dir].name, widget->name);
widget->ignore_suspend = ignore_suspend;
}
snd_soc_dapm_dai_free_widgets(&connected_widgets);
} else {
dev_dbg(sdev->dev,
"failed to enumerate D0i3-compatible PCM %s widgets: %d\n",
spcm->pcm.caps[dir].name, connected);
}
}
}

int
sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd,
struct snd_sof_pcm *spcm, struct snd_pcm_hw_params *params,
Expand Down Expand Up @@ -422,6 +457,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
* remained enabled in D0ix.
*/
spcm->stream[substream->stream].suspend_ignored = false;
sof_pcm_set_widget_ignore_suspend(sdev, rtd, spcm, substream->stream, false);
return 0;
}

Expand All @@ -437,6 +473,8 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
spcm->stream[substream->stream].d0i3_compatible) {
spcm->stream[substream->stream].suspend_ignored = true;
/* Set ignore_suspend to the DAPM widgets */
sof_pcm_set_widget_ignore_suspend(sdev, rtd, spcm, substream->stream, true);
return 0;
}

Expand Down
Loading