aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2005-08-15 02:35:25 -0400
committerJaroslav Kysela <perex@suse.cz>2005-08-30 02:45:57 -0400
commit6207e51b79f89352a8623f806df5bfafb012e489 (patch)
tree9fcf8208991a35a6bff0361858c94702bf5b4e76 /sound
parent55851f734d7af7e5362d43b60331c95c32a3b027 (diff)
[ALSA] usb-audio: use vmalloc for the PCM buffer
USB generic driver With the double buffering, we no longer need contiguous memory for the PCM buffer, so we can use vmalloc() instead of the preallocation functions, and increase the maximum size to 256 KB. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/usbaudio.c53
1 files changed, 44 insertions, 9 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 13ff66b0a532..5aa5fe651a8a 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -46,6 +46,7 @@
46#include <linux/slab.h> 46#include <linux/slab.h>
47#include <linux/string.h> 47#include <linux/string.h>
48#include <linux/usb.h> 48#include <linux/usb.h>
49#include <linux/vmalloc.h>
49#include <linux/moduleparam.h> 50#include <linux/moduleparam.h>
50#include <sound/core.h> 51#include <sound/core.h>
51#include <sound/info.h> 52#include <sound/info.h>
@@ -676,6 +677,42 @@ static void snd_complete_sync_urb(struct urb *urb, struct pt_regs *regs)
676} 677}
677 678
678 679
680/* get the physical page pointer at the given offset */
681static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t *subs,
682 unsigned long offset)
683{
684 void *pageptr = subs->runtime->dma_area + offset;
685 return vmalloc_to_page(pageptr);
686}
687
688/* allocate virtual buffer; may be called more than once */
689static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size)
690{
691 snd_pcm_runtime_t *runtime = subs->runtime;
692 if (runtime->dma_area) {
693 if (runtime->dma_bytes >= size)
694 return 0; /* already large enough */
695 vfree_nocheck(runtime->dma_area);
696 }
697 runtime->dma_area = vmalloc_nocheck(size);
698 if (! runtime->dma_area)
699 return -ENOMEM;
700 runtime->dma_bytes = size;
701 return 0;
702}
703
704/* free virtual buffer; may be called more than once */
705static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs)
706{
707 snd_pcm_runtime_t *runtime = subs->runtime;
708 if (runtime->dma_area) {
709 vfree_nocheck(runtime->dma_area);
710 runtime->dma_area = NULL;
711 }
712 return 0;
713}
714
715
679/* 716/*
680 * unlink active urbs. 717 * unlink active urbs.
681 */ 718 */
@@ -1311,7 +1348,8 @@ static int snd_usb_hw_params(snd_pcm_substream_t *substream,
1311 unsigned int channels, rate, format; 1348 unsigned int channels, rate, format;
1312 int ret, changed; 1349 int ret, changed;
1313 1350
1314 ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); 1351 ret = snd_pcm_alloc_vmalloc_buffer(substream,
1352 params_buffer_bytes(hw_params));
1315 if (ret < 0) 1353 if (ret < 0)
1316 return ret; 1354 return ret;
1317 1355
@@ -1367,7 +1405,7 @@ static int snd_usb_hw_free(snd_pcm_substream_t *substream)
1367 subs->cur_rate = 0; 1405 subs->cur_rate = 0;
1368 subs->period_bytes = 0; 1406 subs->period_bytes = 0;
1369 release_substream_urbs(subs, 0); 1407 release_substream_urbs(subs, 0);
1370 return snd_pcm_lib_free_pages(substream); 1408 return snd_pcm_free_vmalloc_buffer(substream);
1371} 1409}
1372 1410
1373/* 1411/*
@@ -1406,7 +1444,7 @@ static snd_pcm_hardware_t snd_usb_playback =
1406 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 1444 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1407 SNDRV_PCM_INFO_BLOCK_TRANSFER | 1445 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1408 SNDRV_PCM_INFO_MMAP_VALID), 1446 SNDRV_PCM_INFO_MMAP_VALID),
1409 .buffer_bytes_max = (128*1024), 1447 .buffer_bytes_max = (256*1024),
1410 .period_bytes_min = 64, 1448 .period_bytes_min = 64,
1411 .period_bytes_max = (128*1024), 1449 .period_bytes_max = (128*1024),
1412 .periods_min = 2, 1450 .periods_min = 2,
@@ -1418,7 +1456,7 @@ static snd_pcm_hardware_t snd_usb_capture =
1418 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 1456 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1419 SNDRV_PCM_INFO_BLOCK_TRANSFER | 1457 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1420 SNDRV_PCM_INFO_MMAP_VALID), 1458 SNDRV_PCM_INFO_MMAP_VALID),
1421 .buffer_bytes_max = (128*1024), 1459 .buffer_bytes_max = (256*1024),
1422 .period_bytes_min = 64, 1460 .period_bytes_min = 64,
1423 .period_bytes_max = (128*1024), 1461 .period_bytes_max = (128*1024),
1424 .periods_min = 2, 1462 .periods_min = 2,
@@ -1810,6 +1848,7 @@ static snd_pcm_ops_t snd_usb_playback_ops = {
1810 .prepare = snd_usb_pcm_prepare, 1848 .prepare = snd_usb_pcm_prepare,
1811 .trigger = snd_usb_pcm_trigger, 1849 .trigger = snd_usb_pcm_trigger,
1812 .pointer = snd_usb_pcm_pointer, 1850 .pointer = snd_usb_pcm_pointer,
1851 .page = snd_pcm_get_vmalloc_page,
1813}; 1852};
1814 1853
1815static snd_pcm_ops_t snd_usb_capture_ops = { 1854static snd_pcm_ops_t snd_usb_capture_ops = {
@@ -1821,6 +1860,7 @@ static snd_pcm_ops_t snd_usb_capture_ops = {
1821 .prepare = snd_usb_pcm_prepare, 1860 .prepare = snd_usb_pcm_prepare,
1822 .trigger = snd_usb_pcm_trigger, 1861 .trigger = snd_usb_pcm_trigger,
1823 .pointer = snd_usb_pcm_pointer, 1862 .pointer = snd_usb_pcm_pointer,
1863 .page = snd_pcm_get_vmalloc_page,
1824}; 1864};
1825 1865
1826 1866
@@ -2048,10 +2088,6 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat
2048 subs->ops = audio_urb_ops[stream]; 2088 subs->ops = audio_urb_ops[stream];
2049 else 2089 else
2050 subs->ops = audio_urb_ops_high_speed[stream]; 2090 subs->ops = audio_urb_ops_high_speed[stream];
2051 snd_pcm_lib_preallocate_pages(as->pcm->streams[stream].substream,
2052 SNDRV_DMA_TYPE_CONTINUOUS,
2053 snd_dma_continuous_data(GFP_NOIO),
2054 64 * 1024, 128 * 1024);
2055 snd_pcm_set_ops(as->pcm, stream, 2091 snd_pcm_set_ops(as->pcm, stream,
2056 stream == SNDRV_PCM_STREAM_PLAYBACK ? 2092 stream == SNDRV_PCM_STREAM_PLAYBACK ?
2057 &snd_usb_playback_ops : &snd_usb_capture_ops); 2093 &snd_usb_playback_ops : &snd_usb_capture_ops);
@@ -2097,7 +2133,6 @@ static void snd_usb_audio_pcm_free(snd_pcm_t *pcm)
2097 snd_usb_stream_t *stream = pcm->private_data; 2133 snd_usb_stream_t *stream = pcm->private_data;
2098 if (stream) { 2134 if (stream) {
2099 stream->pcm = NULL; 2135 stream->pcm = NULL;
2100 snd_pcm_lib_preallocate_free_for_all(pcm);
2101 snd_usb_audio_stream_free(stream); 2136 snd_usb_audio_stream_free(stream);
2102 } 2137 }
2103} 2138}