diff options
author | Takashi Iwai <tiwai@suse.de> | 2019-12-10 09:34:54 +0300 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2019-12-11 09:26:01 +0300 |
commit | dc5eafe7787c6c4ffab6c6b8a5f78859a249880e (patch) | |
tree | 68a6c25f7cb7da9d34d141be8dd38c99f88e0972 | |
parent | 0ca4cefad185da4b1a5ebf1f03a2ec92b7825551 (diff) | |
download | linux-dc5eafe7787c6c4ffab6c6b8a5f78859a249880e.tar.xz |
ALSA: usb-audio: Support PCM sync_stop
USB-audio driver had some implementation of its own sync-stop
mechanism. This patch moved a part of it to the common PCM sync_stop
ops.
Link: https://lore.kernel.org/r/20191210063454.31603-56-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/usb/pcm.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 33c1e971e61e..8a52996041e9 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -260,18 +260,31 @@ static int start_endpoints(struct snd_usb_substream *subs) return 0; } -static void stop_endpoints(struct snd_usb_substream *subs, bool wait) +static void sync_pending_stops(struct snd_usb_substream *subs) +{ + snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); + snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); +} + +static void stop_endpoints(struct snd_usb_substream *subs) { if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) snd_usb_endpoint_stop(subs->sync_endpoint); if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) snd_usb_endpoint_stop(subs->data_endpoint); +} - if (wait) { - snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); - snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); +/* PCM sync_stop callback */ +static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream) +{ + struct snd_usb_substream *subs = substream->runtime->private_data; + + if (!snd_usb_lock_shutdown(subs->stream->chip)) { + sync_pending_stops(subs); + snd_usb_unlock_shutdown(subs->stream->chip); } + return 0; } static int search_roland_implicit_fb(struct usb_device *dev, int ifnum, @@ -697,7 +710,8 @@ static int configure_endpoint(struct snd_usb_substream *subs) int ret; /* format changed */ - stop_endpoints(subs, true); + stop_endpoints(subs); + sync_pending_stops(subs); ret = snd_usb_endpoint_set_params(subs->data_endpoint, subs->pcm_format, subs->channels, @@ -842,7 +856,8 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->cur_rate = 0; subs->period_bytes = 0; if (!snd_usb_lock_shutdown(subs->stream->chip)) { - stop_endpoints(subs, true); + stop_endpoints(subs); + sync_pending_stops(subs); snd_usb_endpoint_deactivate(subs->sync_endpoint); snd_usb_endpoint_deactivate(subs->data_endpoint); snd_usb_unlock_shutdown(subs->stream->chip); @@ -877,9 +892,6 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) goto unlock; } - snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); - snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); - ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0); if (ret < 0) goto unlock; @@ -1337,7 +1349,6 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream) struct snd_usb_substream *subs = &as->substream[direction]; int ret; - stop_endpoints(subs, true); snd_media_stop_pipeline(subs); if (!as->chip->keep_iface && @@ -1714,7 +1725,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea subs->running = 1; return 0; case SNDRV_PCM_TRIGGER_STOP: - stop_endpoints(subs, false); + stop_endpoints(subs); subs->running = 0; return 0; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: @@ -1744,7 +1755,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream subs->running = 1; return 0; case SNDRV_PCM_TRIGGER_STOP: - stop_endpoints(subs, false); + stop_endpoints(subs); subs->running = 0; return 0; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: @@ -1767,6 +1778,7 @@ static const struct snd_pcm_ops snd_usb_playback_ops = { .hw_free = snd_usb_hw_free, .prepare = snd_usb_pcm_prepare, .trigger = snd_usb_substream_playback_trigger, + .sync_stop = snd_usb_pcm_sync_stop, .pointer = snd_usb_pcm_pointer, }; @@ -1777,6 +1789,7 @@ static const struct snd_pcm_ops snd_usb_capture_ops = { .hw_free = snd_usb_hw_free, .prepare = snd_usb_pcm_prepare, .trigger = snd_usb_substream_capture_trigger, + .sync_stop = snd_usb_pcm_sync_stop, .pointer = snd_usb_pcm_pointer, }; |