diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-06-02 15:26:19 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-06-02 15:54:47 +0200 |
commit | c76157d9286ed598c241c212aa5a3c6e5107bd82 (patch) | |
tree | a08d4b06184bf37ee55a20e30f9c66a43cee37c2 /sound/pci/ctxfi | |
parent | cd391e206f486955e216a61bd9ebcb0e142122e9 (diff) |
ALSA: ctxfi - Support SG-buffers
Use SG-buffers instead of contiguous pages.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/ctxfi')
-rw-r--r-- | sound/pci/ctxfi/ctatc.c | 2 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctpcm.c | 4 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctvmem.c | 56 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctvmem.h | 5 |
4 files changed, 30 insertions, 37 deletions
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 268ecc4c285..684947546d8 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -128,7 +128,7 @@ static int ct_map_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm) runtime = apcm->substream->runtime; vm = atc->vm; - apcm->vm_block = vm->map(vm, runtime->dma_area, runtime->dma_bytes); + apcm->vm_block = vm->map(vm, apcm->substream, runtime->dma_bytes); if (NULL == apcm->vm_block) return -ENOENT; diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index 26d86dc35e5..52ddf19d83b 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c @@ -442,6 +442,7 @@ static struct snd_pcm_ops ct_pcm_playback_ops = { .prepare = ct_pcm_playback_prepare, .trigger = ct_pcm_playback_trigger, .pointer = ct_pcm_playback_pointer, + .page = snd_pcm_sgbuf_ops_page, }; /* PCM operators for capture */ @@ -454,6 +455,7 @@ static struct snd_pcm_ops ct_pcm_capture_ops = { .prepare = ct_pcm_capture_prepare, .trigger = ct_pcm_capture_trigger, .pointer = ct_pcm_capture_pointer, + .page = snd_pcm_sgbuf_ops_page, }; /* Create ALSA pcm device */ @@ -485,7 +487,7 @@ int ct_alsa_pcm_create(struct ct_atc *atc, snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops); - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(atc->pci), 128*1024, 128*1024); return 0; diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c index 74a03623d04..b7f8e58ae07 100644 --- a/sound/pci/ctxfi/ctvmem.c +++ b/sound/pci/ctxfi/ctvmem.c @@ -19,7 +19,7 @@ #include <linux/slab.h> #include <linux/mm.h> #include <linux/io.h> -#include <asm/pgtable.h> +#include <sound/pcm.h> #define CT_PTES_PER_PAGE (CT_PAGE_SIZE / sizeof(void *)) #define CT_ADDRS_PER_PAGE (CT_PTES_PER_PAGE * CT_PAGE_SIZE) @@ -34,6 +34,13 @@ get_vm_block(struct ct_vm *vm, unsigned int size) struct ct_vm_block *block = NULL, *entry = NULL; struct list_head *pos = NULL; + size = CT_PAGE_ALIGN(size); + if (size > vm->size) { + printk(KERN_ERR "ctxfi: Fail! No sufficient device virtural " + "memory space available!\n"); + return NULL; + } + mutex_lock(&vm->lock); list_for_each(pos, &vm->unused) { entry = list_entry(pos, struct ct_vm_block, list); @@ -73,6 +80,8 @@ static void put_vm_block(struct ct_vm *vm, struct ct_vm_block *block) struct ct_vm_block *entry = NULL, *pre_ent = NULL; struct list_head *pos = NULL, *pre = NULL; + block->size = CT_PAGE_ALIGN(block->size); + mutex_lock(&vm->lock); list_del(&block->list); vm->size += block->size; @@ -115,57 +124,36 @@ static void put_vm_block(struct ct_vm *vm, struct ct_vm_block *block) /* Map host addr (kmalloced/vmalloced) to device logical addr. */ static struct ct_vm_block * -ct_vm_map(struct ct_vm *vm, void *host_addr, int size) +ct_vm_map(struct ct_vm *vm, struct snd_pcm_substream *substream, int size) { - struct ct_vm_block *block = NULL; - unsigned long pte_start; - unsigned long i; - unsigned long pages; - unsigned long start_phys; + struct ct_vm_block *block; + unsigned int pte_start; + unsigned i, pages; unsigned long *ptp; - /* do mapping */ - if ((unsigned long)host_addr >= VMALLOC_START) { - printk(KERN_ERR "ctxfi: " - "Fail! Not support vmalloced addr now!\n"); - return NULL; - } - - if (size > vm->size) { - printk(KERN_ERR "ctxfi: Fail! No sufficient device virtural " - "memory space available!\n"); - return NULL; - } - - start_phys = (virt_to_phys(host_addr) & CT_PAGE_MASK); - pages = (CT_PAGE_ALIGN(virt_to_phys(host_addr) + size) - - start_phys) >> CT_PAGE_SHIFT; - - ptp = vm->ptp[0]; - - block = get_vm_block(vm, (pages << CT_PAGE_SHIFT)); + block = get_vm_block(vm, size); if (block == NULL) { printk(KERN_ERR "ctxfi: No virtual memory block that is big " "enough to allocate!\n"); return NULL; } + ptp = vm->ptp[0]; pte_start = (block->addr >> CT_PAGE_SHIFT); - for (i = 0; i < pages; i++) - ptp[pte_start+i] = start_phys + (i << CT_PAGE_SHIFT); + pages = block->size >> CT_PAGE_SHIFT; + for (i = 0; i < pages; i++) { + unsigned long addr; + addr = snd_pcm_sgbuf_get_addr(substream, i << CT_PAGE_SHIFT); + ptp[pte_start + i] = addr; + } - block->addr += (virt_to_phys(host_addr) & (~CT_PAGE_MASK)); block->size = size; - return block; } static void ct_vm_unmap(struct ct_vm *vm, struct ct_vm_block *block) { /* do unmapping */ - block->size = ((block->addr + block->size + CT_PAGE_SIZE - 1) - & CT_PAGE_MASK) - (block->addr & CT_PAGE_MASK); - block->addr &= CT_PAGE_MASK; put_vm_block(vm, block); } diff --git a/sound/pci/ctxfi/ctvmem.h b/sound/pci/ctxfi/ctvmem.h index 17d2d37a9ea..01e4fd0386a 100644 --- a/sound/pci/ctxfi/ctvmem.h +++ b/sound/pci/ctxfi/ctvmem.h @@ -37,6 +37,8 @@ struct ct_vm_block { struct list_head list; }; +struct snd_pcm_substream; + /* Virtual memory management object for card device */ struct ct_vm { void *ptp[CT_PTP_NUM]; /* Device page table pages */ @@ -46,7 +48,8 @@ struct ct_vm { struct mutex lock; /* Map host addr (kmalloced/vmalloced) to device logical addr. */ - struct ct_vm_block *(*map)(struct ct_vm *, void *host_addr, int size); + struct ct_vm_block *(*map)(struct ct_vm *, struct snd_pcm_substream *, + int size); /* Unmap device logical addr area. */ void (*unmap)(struct ct_vm *, struct ct_vm_block *block); void *(*get_ptp_virt)(struct ct_vm *vm, int index); |