From c76157d9286ed598c241c212aa5a3c6e5107bd82 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 2 Jun 2009 15:26:19 +0200 Subject: [PATCH] ALSA: ctxfi - Support SG-buffers Use SG-buffers instead of contiguous pages. Signed-off-by: Takashi Iwai --- sound/pci/ctxfi/ctatc.c | 2 +- sound/pci/ctxfi/ctpcm.c | 4 ++- sound/pci/ctxfi/ctvmem.c | 56 ++++++++++++++++------------------------ 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 268ecc4c2856..684947546d81 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 26d86dc35e52..52ddf19d83bb 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 74a03623d047..b7f8e58ae07d 100644 --- a/sound/pci/ctxfi/ctvmem.c +++ b/sound/pci/ctxfi/ctvmem.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #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 17d2d37a9ea7..01e4fd0386a3 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); -- 2.34.1