diff --git a/include/sound/sof/stream.h b/include/sound/sof/stream.h index 9377113f13e49e..35a59fe2d5f43b 100644 --- a/include/sound/sof/stream.h +++ b/include/sound/sof/stream.h @@ -148,4 +148,8 @@ struct sof_ipc_stream_posn { int32_t xrun_size; /**< XRUN size in bytes */ } __packed; +struct sof_ipc_stream_drain { + struct sof_ipc_reply rhdr; +} __packed; + #endif diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index 67139e15f862a1..fe517cd306e39e 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -287,6 +287,9 @@ static int sof_compr_trigger(struct snd_soc_component *component, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE; break; + case SNDRV_PCM_TRIGGER_DRAIN: + stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_DRAIN; + break; default: dev_err(component->dev, "error: unhandled trigger cmd %d\n", cmd); break; diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c index b28af3a48b7075..46d4e5184b506d 100644 --- a/sound/soc/sof/ipc3.c +++ b/sound/soc/sof/ipc3.c @@ -898,6 +898,35 @@ static void ipc3_xrun(struct snd_sof_dev *sdev, u32 msg_id) #endif } +static void ipc3_drain(struct snd_sof_dev *sdev, u32 msg_id) +{ + struct snd_soc_component *scomp = sdev->component; + struct snd_sof_pcm *spcm; + struct snd_sof_pcm_stream *stream; + struct sof_ipc_stream_drain drain; + int direction; + + spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction); + if (!spcm) { + dev_err(sdev->dev, + "error: drain for unknown stream, msg_id %d\n", + msg_id); + return; + } + + stream = &spcm->stream[direction]; + snd_sof_ipc_msg_data(sdev, stream->substream, &drain, sizeof(drain)); + + /* since struct sof_ipc_stream drain only contains the reply + * header there's no need for additional checks. + * + * we're assuming that since we're receiving the drain-related + * reply then the drain operation finished successfully. + */ + if (spcm->pcm.compress) + snd_compr_drain_notify(stream->cstream); +} + /* stream notifications from firmware */ static void ipc3_stream_message(struct snd_sof_dev *sdev, void *msg_buf) { @@ -912,6 +941,9 @@ static void ipc3_stream_message(struct snd_sof_dev *sdev, void *msg_buf) case SOF_IPC_STREAM_TRIG_XRUN: ipc3_xrun(sdev, msg_id); break; + case SOF_IPC_STREAM_TRIG_DRAIN: + ipc3_drain(sdev, msg_id); + break; default: dev_err(sdev->dev, "unhandled stream message %#x\n", msg_id);