aboutsummaryrefslogtreecommitdiffstats
path: root/core.c
diff options
context:
space:
mode:
authorMark Farrugia <mark.farrugia@fiberdyne.com.au>2019-04-03 17:41:32 +1100
committerMark Farrugia <mark.farrugia@fiberdyne.com.au>2019-04-03 17:41:32 +1100
commitde95b5d9cb985acf9e28ea4e1a8592d335e601b1 (patch)
treeaf02bdc00e2c2dd0242e97fe1dc8002ca6df24ae /core.c
parente152900bc73f1f7d3b33aa5369c36da762b0b042 (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.c51
1 files changed, 51 insertions, 0 deletions
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;