ASoC: SOF: pcm: Modify the signature of a couple of PCM IPC ops

In order to reuse the pipeline triggering logic for compressed support
with IPC4, modify the signature of the trigger and hw_free PCM IPC ops
so that they can be reused.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Link: https://patch.msgid.link/20261007084955.1256-15-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Ranjani Sridharan 2026-10-07 11:49:41 +03:00 committed by Mark Brown
parent e1135ddec7
commit 9de51be869
4 changed files with 39 additions and 46 deletions

View File

@ -14,23 +14,18 @@
#include "sof-audio.h"
static int sof_ipc3_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
struct snd_pcm_substream *substream,
struct snd_sof_pcm *spcm, int dir)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sof_ipc_stream stream;
struct snd_sof_pcm *spcm;
spcm = snd_sof_find_spcm_dai(component, rtd);
if (!spcm)
return -EINVAL;
if (!spcm->prepared[substream->stream])
if (!spcm->prepared[dir])
return 0;
stream.hdr.size = sizeof(stream);
stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE;
stream.comp_id = spcm->stream[substream->stream].comp_id;
stream.comp_id = spcm->stream[dir].comp_id;
/* send IPC to the DSP */
return sof_ipc_tx_message_no_reply(sdev->ipc, &stream, sizeof(stream));
@ -141,20 +136,15 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component,
}
static int sof_ipc3_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
struct snd_pcm_substream *substream,
struct snd_sof_pcm *spcm, int cmd, int dir)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct sof_ipc_stream stream;
struct snd_sof_pcm *spcm;
spcm = snd_sof_find_spcm_dai(component, rtd);
if (!spcm)
return -EINVAL;
stream.hdr.size = sizeof(stream);
stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG;
stream.comp_id = spcm->stream[substream->stream].comp_id;
stream.comp_id = spcm->stream[dir].comp_id;
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@ -172,7 +162,7 @@ static int sof_ipc3_pcm_trigger(struct snd_soc_component *component,
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP;
break;
default:
spcm_err(spcm, substream->stream, "Unhandled trigger cmd %d\n", cmd);
spcm_err(spcm, dir, "Unhandled trigger cmd %d\n", cmd);
return -EINVAL;
}

View File

@ -412,28 +412,23 @@ static int sof_ipc4_chain_dma_trigger(struct snd_sof_dev *sdev,
}
static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int state, int cmd)
struct snd_pcm_substream *substream, int state, int cmd,
struct snd_sof_pcm *spcm, int dir)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_sof_pcm_stream_pipeline_list *pipeline_list;
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
struct ipc4_pipeline_set_state_data *trigger_list;
struct snd_sof_widget *pipe_widget;
struct sof_ipc4_pipeline *pipeline;
struct snd_sof_pipeline *spipe;
struct snd_sof_pcm *spcm;
u8 *pipe_priority;
int ret;
int i;
spcm = snd_sof_find_spcm_dai(component, rtd);
if (!spcm)
return -EINVAL;
spcm_dbg(spcm, dir, "cmd: %d, state: %d\n", cmd, state);
spcm_dbg(spcm, substream->stream, "cmd: %d, state: %d\n", cmd, state);
pipeline_list = &spcm->stream[substream->stream].pipeline_list;
pipeline_list = &spcm->stream[dir].pipeline_list;
guard(mutex)(&ipc4_data->pipeline_state_mutex);
/* nothing to trigger if the list is empty */
@ -451,9 +446,9 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
if (pipeline->use_chain_dma) {
struct sof_ipc4_timestamp_info *time_info;
time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
time_info = sof_ipc4_sps_to_time_info(&spcm->stream[dir]);
ret = sof_ipc4_chain_dma_trigger(sdev, spcm, substream->stream,
ret = sof_ipc4_chain_dma_trigger(sdev, spcm, dir,
pipeline_list, state, cmd);
if (ret || !time_info)
return ret;
@ -462,12 +457,16 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
/*
* Record the DAI position for delay reporting
* To handle multiple pause/resume/xrun we need to add
* the positions to simulate how the firmware behaves
* the positions to simulate how the firmware behaves.
* Chained DMA does not support compress streams. We should
* never get here with compress.
*/
u64 pos = snd_sof_pcm_get_dai_frame_counter(sdev, component,
substream);
if (substream) {
u64 pos = snd_sof_pcm_get_dai_frame_counter(sdev, component,
substream);
time_info->stream_end_offset += pos;
time_info->stream_end_offset += pos;
}
} else if (state == SOF_IPC4_PIPE_RESET) {
/* Reset the end offset as the stream is stopped */
time_info->stream_end_offset = 0;
@ -526,7 +525,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
*/
ret = sof_ipc4_set_multi_pipeline_state(sdev, SOF_IPC4_PIPE_PAUSED, trigger_list);
if (ret < 0) {
spcm_err(spcm, substream->stream, "failed to pause all pipelines\n");
spcm_err(spcm, dir, "failed to pause all pipelines\n");
/*
* workaround: if the firmware is crashed or the IPC timed out
* while setting the pipeline state we must ignore the error
@ -557,7 +556,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
* Invalidate the stream_start_offset to make sure that it is
* going to be updated if the stream resumes
*/
time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
time_info = sof_ipc4_sps_to_time_info(&spcm->stream[dir]);
if (time_info)
time_info->stream_start_offset = SOF_IPC4_INVALID_STREAM_POSITION;
@ -567,7 +566,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
/* else set the RUNNING/RESET state in the DSP */
ret = sof_ipc4_set_multi_pipeline_state(sdev, state, trigger_list);
if (ret < 0) {
spcm_err(spcm, substream->stream,
spcm_err(spcm, dir,
"failed to set final state %d for all pipelines\n",
state);
/*
@ -598,7 +597,8 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
}
static int sof_ipc4_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
struct snd_pcm_substream *substream,
struct snd_sof_pcm *spcm, int cmd, int dir)
{
int state;
@ -620,14 +620,15 @@ static int sof_ipc4_pcm_trigger(struct snd_soc_component *component,
}
/* set the pipeline state */
return sof_ipc4_trigger_pipelines(component, substream, state, cmd);
return sof_ipc4_trigger_pipelines(component, substream, state, cmd, spcm, dir);
}
static int sof_ipc4_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
struct snd_pcm_substream *substream,
struct snd_sof_pcm *spcm, int dir)
{
/* command is not relevant with RESET, so just pass 0 */
return sof_ipc4_trigger_pipelines(component, substream, SOF_IPC4_PIPE_RESET, 0);
return sof_ipc4_trigger_pipelines(component, substream, SOF_IPC4_PIPE_RESET, 0, spcm, dir);
}
static int ipc4_ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev,

View File

@ -152,7 +152,7 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
* between. At least ALSA OSS emulation depends on this.
*/
if (spcm->prepared[substream->stream] && pcm_ops && pcm_ops->hw_free) {
ret = pcm_ops->hw_free(component, substream);
ret = pcm_ops->hw_free(component, substream, spcm, substream->stream);
if (ret < 0)
return ret;
@ -223,7 +223,8 @@ static int sof_pcm_stream_free(struct snd_sof_dev *sdev,
/* free PCM in the DSP */
if (pcm_ops && pcm_ops->hw_free) {
ret = pcm_ops->hw_free(sdev->component, substream);
ret = pcm_ops->hw_free(sdev->component, substream, spcm,
substream->stream);
if (ret < 0) {
spcm_err(spcm, substream->stream,
"pcm_ops->hw_free failed %d\n", ret);
@ -458,7 +459,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
snd_sof_pcm_platform_trigger(sdev, substream, cmd);
if (pcm_ops && pcm_ops->trigger)
ret = pcm_ops->trigger(component, substream, cmd);
ret = pcm_ops->trigger(component, substream, spcm, cmd, substream->stream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:

View File

@ -125,9 +125,10 @@ struct sof_ipc_pcm_ops {
int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_sof_platform_stream_params *platform_params);
int (*hw_free)(struct snd_soc_component *component, struct snd_pcm_substream *substream);
int (*trigger)(struct snd_soc_component *component, struct snd_pcm_substream *substream,
int cmd);
int (*hw_free)(struct snd_soc_component *component, struct snd_pcm_substream *substream,
struct snd_sof_pcm *spcm, int dir);
int (*trigger)(struct snd_soc_component *component, struct snd_pcm_substream *substream,
struct snd_sof_pcm *spcm, int cmd, int dir);
int (*dai_link_fixup)(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params);
int (*pcm_setup)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm);
void (*pcm_free)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm);