diff options
Diffstat (limited to 'drivers/staging/line6/capture.c')
-rw-r--r-- | drivers/staging/line6/capture.c | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/drivers/staging/line6/capture.c b/drivers/staging/line6/capture.c index 9647154a4923..127f95247749 100644 --- a/drivers/staging/line6/capture.c +++ b/drivers/staging/line6/capture.c @@ -9,6 +9,7 @@ * */ +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -192,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. */ @@ -243,11 +269,7 @@ static void audio_in_callback(struct urb *urb) length += fsize; /* the following assumes LINE6_ISO_PACKETS == 1: */ -#if LINE6_BACKUP_MONITOR_SIGNAL - memcpy(line6pcm->prev_fbuf, fbuf, fsize); -#else line6pcm->prev_fbuf = fbuf; -#endif line6pcm->prev_fsize = fsize; #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE @@ -319,6 +341,13 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream, } /* -- [FD] end */ + if ((line6pcm->flags & MASK_CAPTURE) == 0) { + ret = line6_alloc_capture_buffer(line6pcm); + + if (ret < 0) + return ret; + } + ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); if (ret < 0) @@ -331,6 +360,13 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream, /* hw_free capture callback */ static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream) { + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + + 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); } |