summaryrefslogtreecommitdiff
path: root/drivers/staging/line6/capture.c
diff options
context:
space:
mode:
authorMarkus Grabner <grabner@icg.tugraz.at>2011-12-10 01:12:32 (GMT)
committerGreg Kroah-Hartman <gregkh@suse.de>2011-12-10 03:26:09 (GMT)
commit6b02a17ee5cd5d200dbe4a285a4e750f70884967 (patch)
tree4f8a0f63d324ddbb284911a47303282ef0ef0c08 /drivers/staging/line6/capture.c
parent665f3f506b1c2684d6f78d6d03c038d1712e561d (diff)
downloadlinux-6b02a17ee5cd5d200dbe4a285a4e750f70884967.tar.xz
staging: line6: fixed ALSA/PCM interaction
The PCM subsystem in the Line6 driver is mainly used for PCM playback and capture by ALSA, but also has other tasks, most notably providing a low-latency software monitor for devices which don't support hardware monitoring (e.g., the TonePort series). This patch makes ALSA "play nicely" with the other components, i.e., prevents it from resetting the isochronous USB transfer while other PCM tasks (software monitoring) are running. Signed-off-by: Markus Grabner <grabner@icg.tugraz.at> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/line6/capture.c')
-rw-r--r--drivers/staging/line6/capture.c46
1 files changed, 34 insertions, 12 deletions
diff --git a/drivers/staging/line6/capture.c b/drivers/staging/line6/capture.c
index 8f59ff3..127f952 100644
--- a/drivers/staging/line6/capture.c
+++ b/drivers/staging/line6/capture.c
@@ -193,6 +193,31 @@ void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length)
}
}
+int line6_alloc_capture_buffer(struct snd_line6_pcm *line6pcm)
+{
+ /* We may be invoked multiple times in a row so allocate once only */
+ if (line6pcm->buffer_in)
+ return 0;
+
+ line6pcm->buffer_in =
+ kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
+ line6pcm->max_packet_size, GFP_KERNEL);
+
+ if (!line6pcm->buffer_in) {
+ dev_err(line6pcm->line6->ifcdev,
+ "cannot malloc capture buffer\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm)
+{
+ kfree(line6pcm->buffer_in);
+ line6pcm->buffer_in = NULL;
+}
+
/*
* Callback for completed capture URB.
*/
@@ -316,16 +341,11 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream,
}
/* -- [FD] end */
- /* We may be invoked multiple times in a row so allocate once only */
- if (!line6pcm->buffer_in)
- line6pcm->buffer_in =
- kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
- line6pcm->max_packet_size, GFP_KERNEL);
+ if ((line6pcm->flags & MASK_CAPTURE) == 0) {
+ ret = line6_alloc_capture_buffer(line6pcm);
- if (!line6pcm->buffer_in) {
- dev_err(line6pcm->line6->ifcdev,
- "cannot malloc capture buffer\n");
- return -ENOMEM;
+ if (ret < 0)
+ return ret;
}
ret = snd_pcm_lib_malloc_pages(substream,
@@ -342,9 +362,11 @@ static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream)
{
struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
- line6_unlink_wait_clear_audio_in_urbs(line6pcm);
- kfree(line6pcm->buffer_in);
- line6pcm->buffer_in = NULL;
+ if ((line6pcm->flags & MASK_CAPTURE) == 0) {
+ line6_unlink_wait_clear_audio_in_urbs(line6pcm);
+ line6_free_capture_buffer(line6pcm);
+ }
+
return snd_pcm_lib_free_pages(substream);
}