diff options
author | Mark Farrugia <mark.farrugia@fiberdyne.com.au> | 2019-04-03 17:41:32 +1100 |
---|---|---|
committer | Mark Farrugia <mark.farrugia@fiberdyne.com.au> | 2019-04-08 13:57:54 +1000 |
commit | 8e151019a32b733420e2eb3006a5edaac5bc9589 (patch) | |
tree | 0117c22646a7d880b71b1908957a00a347fdf020 /core.c | |
parent | 16912fcce2802752ba11b884d920c71cae5eb1c9 (diff) |
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 <mark.farrugia@fiberdyne.com.au>
Diffstat (limited to 'core.c')
-rw-r--r-- | core.c | 51 |
1 files changed, 51 insertions, 0 deletions
@@ -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; |