diff mbox series

[07/11] usb: gadget: u_audio: Stopping PCM substream at capture/playback stop

Message ID 20211220082542.13750-8-pavel.hofman@ivitera.com
State New
Headers show
Series usb: gadget: audio: Multiple rates, dyn. bInterval | expand

Commit Message

Pavel Hofman Dec. 20, 2021, 8:25 a.m. UTC
When the USB host stops capture/playback, the corresponding PCM
substream (if activated and running) is stopped and drained.

Signed-off-by: Pavel Hofman <pavel.hofman@ivitera.com>
---
 drivers/usb/gadget/function/u_audio.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
diff mbox series

Patch

diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c
index a6293415c071..9dbce51c2eb7 100644
--- a/drivers/usb/gadget/function/u_audio.c
+++ b/drivers/usb/gadget/function/u_audio.c
@@ -544,6 +544,20 @@  static void set_reported_srate(struct uac_rtd_params *prm, int srate)
 	}
 }
 
+static void stop_substream(struct uac_rtd_params *prm)
+{
+	unsigned long _flags;
+	struct snd_pcm_substream *substream;
+
+	substream = prm->ss;
+	if (substream) {
+		snd_pcm_stream_lock_irqsave(substream, _flags);
+		if (snd_pcm_running(substream))
+			snd_pcm_stop(substream, SNDRV_PCM_STATE_DRAINING);
+		snd_pcm_stream_unlock_irqrestore(substream, _flags);
+	}
+}
+
 int u_audio_start_capture(struct g_audio *audio_dev)
 {
 	struct snd_uac_chip *uac = audio_dev->uac;
@@ -630,6 +644,7 @@  void u_audio_stop_capture(struct g_audio *audio_dev)
 {
 	struct snd_uac_chip *uac = audio_dev->uac;
 
+	stop_substream(&uac->c_prm);
 	set_reported_srate(&uac->c_prm, 0);
 	if (audio_dev->in_ep_fback)
 		free_ep_fback(&uac->c_prm, audio_dev->in_ep_fback);
@@ -713,6 +728,7 @@  void u_audio_stop_playback(struct g_audio *audio_dev)
 {
 	struct snd_uac_chip *uac = audio_dev->uac;
 
+	stop_substream(&uac->p_prm);
 	set_reported_srate(&uac->p_prm, 0);
 	free_ep(&uac->p_prm, audio_dev->in_ep);
 }