From f8e8c6179b28037ac3380a836b1e79993b63350e Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 13 Aug 2026 22:29:06 +0300 Subject: [PATCH] ASoC: SOF: ipc4: add D0I3 stream compatibility support for S0ix IPC4 topologies can mark PCM streams as D0I3-compatible using the SOF_TKN_STREAM_PLAYBACK_COMPATIBLE_D0I3 (1200) and SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3 (1201) tokens on host copier widgets. However, the IPC4 topology path did not parse these tokens, so the d0i3_compatible flag was never set and the DSP always went to D3 during S0ix. Add token definitions and parsing in sof_ipc4_widget_setup_pcm() to read the D0I3 compatibility flag from the host copier widget tuples into spcm->stream[dir].d0i3_compatible. Also set d0i3_supported_in_s0ix = true in ipc4_pcm_ops so the existing suspend_ignored logic in pcm.c applies to IPC4 streams, allowing the DSP to remain in D0i3 during S0ix when D0I3-compatible streams are active (e.g. wake-on-voice keyword detection). Signed-off-by: Jyri Sarha --- sound/soc/sof/ipc4-pcm.c | 1 + sound/soc/sof/ipc4-topology.c | 26 ++++++++++++++++++++++++++ sound/soc/sof/sof-audio.h | 2 ++ 3 files changed, 29 insertions(+) diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 5d8fc9b25bcc82..d73646b375705a 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -1336,6 +1336,7 @@ const struct sof_ipc_pcm_ops ipc4_pcm_ops = { .delay = sof_ipc4_pcm_delay, .ipc_first_on_start = true, .platform_stop_during_hw_free = true, + .d0i3_supported_in_s0ix = true, #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS) .compress_ops = &sof_ipc4_compressed_ops, #endif diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 09246e4c378097..122c893536284a 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -136,6 +136,14 @@ static const struct sof_topology_token ipc4_copier_deep_buffer_tokens[] = { {SOF_TKN_INTEL_COPIER_DEEP_BUFFER_DMA_MS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 0}, }; +static const struct sof_topology_token ipc4_stream_playback_d0i3_tokens[] = { + {SOF_TKN_STREAM_PLAYBACK_COMPATIBLE_D0I3, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u32, 0}, +}; + +static const struct sof_topology_token ipc4_stream_capture_d0i3_tokens[] = { + {SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u32, 0}, +}; + static const struct sof_topology_token ipc4_copier_tokens[] = { {SOF_TKN_INTEL_COPIER_NODE_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32, 0}, }; @@ -211,6 +219,12 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = { ipc4_copier_deep_buffer_tokens, ARRAY_SIZE(ipc4_copier_deep_buffer_tokens)}, [SOF_COPIER_TOKENS] = {"IPC4 Copier tokens", ipc4_copier_tokens, ARRAY_SIZE(ipc4_copier_tokens)}, + [SOF_STREAM_PLAYBACK_D0I3_TOKENS] = {"IPC4 Stream playback D0I3 tokens", + ipc4_stream_playback_d0i3_tokens, + ARRAY_SIZE(ipc4_stream_playback_d0i3_tokens)}, + [SOF_STREAM_CAPTURE_D0I3_TOKENS] = {"IPC4 Stream capture D0I3 tokens", + ipc4_stream_capture_d0i3_tokens, + ARRAY_SIZE(ipc4_stream_capture_d0i3_tokens)}, [SOF_AUDIO_FMT_NUM_TOKENS] = {"IPC4 Audio format number tokens", ipc4_audio_fmt_num_tokens, ARRAY_SIZE(ipc4_audio_fmt_num_tokens)}, [SOF_GAIN_TOKENS] = {"Gain tokens", gain_tokens, ARRAY_SIZE(gain_tokens)}, @@ -680,6 +694,7 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) struct snd_sof_pcm_stream *sps; struct snd_sof_pcm *spcm; int node_type = 0; + u32 d0i3 = 0; int ret, dir; ipc4_copier = kzalloc_obj(*ipc4_copier); @@ -731,6 +746,15 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) swidget->tuples, swidget->num_tuples, sizeof(u32), 1); + /* Parse D0I3 compatibility token for this stream direction */ + sof_update_ipc_object(scomp, &d0i3, + dir == SNDRV_PCM_STREAM_PLAYBACK ? + SOF_STREAM_PLAYBACK_D0I3_TOKENS : + SOF_STREAM_CAPTURE_D0I3_TOKENS, + swidget->tuples, + swidget->num_tuples, sizeof(d0i3), 1); + sps->d0i3_compatible = !!d0i3; + /* Set default DMA buffer size if it is not specified in topology */ if (!sps->dsp_max_burst_size_in_ms) { struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; @@ -4265,6 +4289,8 @@ static enum sof_tokens copier_token_list[] = { SOF_COMP_EXT_TOKENS, SOF_COPIER_DEEP_BUFFER_TOKENS, /* for AIF copier */ + SOF_STREAM_PLAYBACK_D0I3_TOKENS, /* for AIF copier */ + SOF_STREAM_CAPTURE_D0I3_TOKENS, /* for AIF copier */ SOF_DAI_TOKENS, /* for DAI copier */ }; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index b60246fd5869b1..edb79ddfee54e0 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -289,6 +289,8 @@ enum sof_tokens { SOF_OUT_AUDIO_FORMAT_TOKENS, SOF_COPIER_DEEP_BUFFER_TOKENS, SOF_COPIER_TOKENS, + SOF_STREAM_PLAYBACK_D0I3_TOKENS, + SOF_STREAM_CAPTURE_D0I3_TOKENS, SOF_AUDIO_FMT_NUM_TOKENS, SOF_COPIER_FORMAT_TOKENS, SOF_GAIN_TOKENS,