aboutsummaryrefslogtreecommitdiffstats
path: root/pcm.c
diff options
context:
space:
mode:
authorMark Farrugia <mark.farrugia@fiberdyne.com.au>2019-03-05 12:35:47 +1100
committerMark Farrugia <mark.farrugia@fiberdyne.com.au>2019-03-05 12:36:02 +1100
commit6a2f694005d8e31c74043b9b90c715bcdf394294 (patch)
tree9cd08c4772c2e13d5cff4e3ad49c6cce3f68be77 /pcm.c
parentea9a8ede7f343d589c8d9fac945f7b3d9dca9c3f (diff)
parent9f68614f664506535c873699dcfbca6e2515a24c (diff)
Merge remote-tracking branch 'agl/master' into backport_4.12
Signed-off-by: Mark Farrugia <mark.farrugia@fiberdyne.com.au>
Diffstat (limited to 'pcm.c')
-rw-r--r--pcm.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/pcm.c b/pcm.c
index 411db40..e91b121 100644
--- a/pcm.c
+++ b/pcm.c
@@ -67,6 +67,11 @@ static int pcm_open(struct snd_pcm_substream *substream)
struct snd_pcm_hardware *hw;
unsigned int chans = 0;
+ if (!snd_avirt_streams_sealed()) {
+ D_ERRORK("Cannot open PCM. Card is not sealed");
+ return -EPERM;
+ }
+
// Find the Audio Path mapped to this device
stream = snd_avirt_stream_find_by_device(substream->pcm->device);
if (IS_ERR_VALUE(stream) || !stream)
@@ -84,6 +89,10 @@ static int pcm_open(struct snd_pcm_substream *substream)
// Setup remaining hw properties
chans = stream->channels;
+ if (chans == 0) {
+ D_ERRORK("Channels cannot be 0");
+ return -EINVAL;
+ }
hw->channels_min = chans;
hw->channels_max = chans;
@@ -92,6 +101,22 @@ static int pcm_open(struct snd_pcm_substream *substream)
}
/**
+ * pcm_close - Implements 'close' callback for PCM middle layer
+ * @substream: pointer to ALSA PCM substream
+ *
+ * This is called when a PCM substream is closed.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_close(struct snd_pcm_substream *substream)
+{
+ // Do additional Audio Path 'close' callback
+ return DO_AUDIOPATH_CB(
+ (struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath,
+ close, substream);
+}
+
+/**
* pcm_hw_params - Implements 'hw_params' callback for PCM middle layer
* @substream: pointer to ALSA PCM substream
* @hw_params: contains the hardware parameters for the PCM
@@ -105,7 +130,6 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
int retval;
- size_t bufsz;
/* Check supported channels */
if ((params_channels(hw_params) <
@@ -117,10 +141,8 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- bufsz = params_buffer_bytes(hw_params) *
- substream->runtime->hw.periods_max;
-
- retval = snd_pcm_lib_alloc_vmalloc_buffer(substream, bufsz);
+ retval = snd_pcm_lib_alloc_vmalloc_buffer(
+ substream, params_buffer_bytes(hw_params));
if (retval < 0)
D_ERRORK("pcm: buffer allocation failed: %d", retval);
@@ -144,6 +166,8 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
err = DO_AUDIOPATH_CB(
(struct snd_avirt_audiopath *)PRIVATE_DATA(substream)->audiopath,
hw_free, substream);
+ if (err < 0)
+ return err;
return snd_pcm_lib_free_vmalloc_buffer(substream);
}
@@ -154,6 +178,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
*/
struct snd_pcm_ops pcm_ops_avirt = {
.open = pcm_open,
+ .close = pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pcm_hw_params,
.hw_free = pcm_hw_free,