From 8e151019a32b733420e2eb3006a5edaac5bc9589 Mon Sep 17 00:00:00 2001 From: Mark Farrugia Date: Wed, 3 Apr 2019 17:41:32 +1100 Subject: Introduce 'unconfigure' callback The 'unconfigure' callback can be used to clean up the 'configured' state of an Audio Path, for when it is desired to reset the streams, and/or reload a different stream configuration. To destroy the streams, we must attempt to force their PCMs closed. Take note though, that if a PCM is being written to when an unconfigure command is issued, system instability may occur. Signed-off-by: Mark Farrugia --- core.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'core.c') diff --git a/core.c b/core.c index d9e264c..c2e32c5 100644 --- a/core.c +++ b/core.c @@ -112,6 +112,30 @@ static struct snd_pcm *snd_avirt_pcm_create(struct snd_avirt_stream *stream) return pcm; } +void snd_avirt_stream_try_destroy(struct snd_avirt_stream *stream) +{ + unsigned long _flags; + struct snd_pcm_substream *substream = + stream->pcm->streams[stream->direction].substream; + + snd_pcm_stream_lock_irqsave(substream, _flags); + if (substream->runtime) { + if (snd_pcm_running(substream)) { + if (0 != + snd_pcm_stop(substream, SNDRV_PCM_STATE_SUSPENDED)) + D_ERRORK("Could not stop PCM '%s'", + stream->name); + } + } + snd_pcm_stream_unlock_irqrestore(substream, _flags); + + snd_device_free(core.card, stream->pcm); + kfree(stream->pcm_ops); + kfree(stream); + + core.stream_count--; +} + static struct snd_avirt_route *snd_avirt_route_get(const char *uid) { struct list_head *entry; @@ -620,6 +644,33 @@ int snd_avirt_streams_configure(void) return err; } +int snd_avirt_streams_unconfigure(void) +{ + int i = 0, err = 0; + struct snd_avirt_audiopath_obj *ap_obj; + struct snd_avirt_stream_array stream_array; + + if (!core.streams_configured) { + D_ERRORK("streams are already unconfigured!"); + return -1; + } + + list_for_each_entry (ap_obj, &audiopath_list, list) { + if (!ap_obj->path->unconfigure) { + D_ERRORK("Cannot do 'unconfigure' for AP: %s", + ap_obj->path->uid); + return -EFAULT; + } + + D_INFOK("Do 'unconfigure' for AP: %s", ap_obj->path->uid); + ap_obj->path->unconfigure(); + } + + core.streams_configured = false; + + return 0; +} + bool snd_avirt_streams_configured(void) { return core.streams_configured; -- cgit 1.2.3-korg