diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-06-02 09:26:19 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-06-02 09:54:47 -0400 |
commit | c76157d9286ed598c241c212aa5a3c6e5107bd82 (patch) | |
tree | a08d4b06184bf37ee55a20e30f9c66a43cee37c2 /sound | |
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')
-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 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) | |||
128 | runtime = apcm->substream->runtime; | 128 | runtime = apcm->substream->runtime; |
129 | vm = atc->vm; | 129 | vm = atc->vm; |
130 | 130 | ||
131 | apcm->vm_block = vm->map(vm, runtime->dma_area, runtime->dma_bytes); | 131 | apcm->vm_block = vm->map(vm, apcm->substream, runtime->dma_bytes); |
132 | 132 | ||
133 | if (NULL == apcm->vm_block) | 133 | if (NULL == apcm->vm_block) |
134 | return -ENOENT; | 134 | 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 = { | |||
442 | .prepare = ct_pcm_playback_prepare, | 442 | .prepare = ct_pcm_playback_prepare, |
443 | .trigger = ct_pcm_playback_trigger, | 443 | .trigger = ct_pcm_playback_trigger, |
444 | .pointer = ct_pcm_playback_pointer, | 444 | .pointer = ct_pcm_playback_pointer, |
445 | .page = snd_pcm_sgbuf_ops_page, | ||
445 | }; | 446 | }; |
446 | 447 | ||
447 | /* PCM operators for capture */ | 448 | /* PCM operators for capture */ |
@@ -454,6 +455,7 @@ static struct snd_pcm_ops ct_pcm_capture_ops = { | |||
454 | .prepare = ct_pcm_capture_prepare, | 455 | .prepare = ct_pcm_capture_prepare, |
455 | .trigger = ct_pcm_capture_trigger, | 456 | .trigger = ct_pcm_capture_trigger, |
456 | .pointer = ct_pcm_capture_pointer, | 457 | .pointer = ct_pcm_capture_pointer, |
458 | .page = snd_pcm_sgbuf_ops_page, | ||
457 | }; | 459 | }; |
458 | 460 | ||
459 | /* Create ALSA pcm device */ | 461 | /* Create ALSA pcm device */ |
@@ -485,7 +487,7 @@ int ct_alsa_pcm_create(struct ct_atc *atc, | |||
485 | snd_pcm_set_ops(pcm, | 487 | snd_pcm_set_ops(pcm, |
486 | SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops); | 488 | SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops); |
487 | 489 | ||
488 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 490 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
489 | snd_dma_pci_data(atc->pci), 128*1024, 128*1024); | 491 | snd_dma_pci_data(atc->pci), 128*1024, 128*1024); |
490 | 492 | ||
491 | return 0; | 493 | 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 @@ | |||
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <asm/pgtable.h> | 22 | #include <sound/pcm.h> |
23 | 23 | ||
24 | #define CT_PTES_PER_PAGE (CT_PAGE_SIZE / sizeof(void *)) | 24 | #define CT_PTES_PER_PAGE (CT_PAGE_SIZE / sizeof(void *)) |
25 | #define CT_ADDRS_PER_PAGE (CT_PTES_PER_PAGE * CT_PAGE_SIZE) | 25 | #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) | |||
34 | struct ct_vm_block *block = NULL, *entry = NULL; | 34 | struct ct_vm_block *block = NULL, *entry = NULL; |
35 | struct list_head *pos = NULL; | 35 | struct list_head *pos = NULL; |
36 | 36 | ||
37 | size = CT_PAGE_ALIGN(size); | ||
38 | if (size > vm->size) { | ||
39 | printk(KERN_ERR "ctxfi: Fail! No sufficient device virtural " | ||
40 | "memory space available!\n"); | ||
41 | return NULL; | ||
42 | } | ||
43 | |||
37 | mutex_lock(&vm->lock); | 44 | mutex_lock(&vm->lock); |
38 | list_for_each(pos, &vm->unused) { | 45 | list_for_each(pos, &vm->unused) { |
39 | entry = list_entry(pos, struct ct_vm_block, list); | 46 | 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) | |||
73 | struct ct_vm_block *entry = NULL, *pre_ent = NULL; | 80 | struct ct_vm_block *entry = NULL, *pre_ent = NULL; |
74 | struct list_head *pos = NULL, *pre = NULL; | 81 | struct list_head *pos = NULL, *pre = NULL; |
75 | 82 | ||
83 | block->size = CT_PAGE_ALIGN(block->size); | ||
84 | |||
76 | mutex_lock(&vm->lock); | 85 | mutex_lock(&vm->lock); |
77 | list_del(&block->list); | 86 | list_del(&block->list); |
78 | vm->size += block->size; | 87 | vm->size += block->size; |
@@ -115,57 +124,36 @@ static void put_vm_block(struct ct_vm *vm, struct ct_vm_block *block) | |||
115 | 124 | ||
116 | /* Map host addr (kmalloced/vmalloced) to device logical addr. */ | 125 | /* Map host addr (kmalloced/vmalloced) to device logical addr. */ |
117 | static struct ct_vm_block * | 126 | static struct ct_vm_block * |
118 | ct_vm_map(struct ct_vm *vm, void *host_addr, int size) | 127 | ct_vm_map(struct ct_vm *vm, struct snd_pcm_substream *substream, int size) |
119 | { | 128 | { |
120 | struct ct_vm_block *block = NULL; | 129 | struct ct_vm_block *block; |
121 | unsigned long pte_start; | 130 | unsigned int pte_start; |
122 | unsigned long i; | 131 | unsigned i, pages; |
123 | unsigned long pages; | ||
124 | unsigned long start_phys; | ||
125 | unsigned long *ptp; | 132 | unsigned long *ptp; |
126 | 133 | ||
127 | /* do mapping */ | 134 | block = get_vm_block(vm, size); |
128 | if ((unsigned long)host_addr >= VMALLOC_START) { | ||
129 | printk(KERN_ERR "ctxfi: " | ||
130 | "Fail! Not support vmalloced addr now!\n"); | ||
131 | return NULL; | ||
132 | } | ||
133 | |||
134 | if (size > vm->size) { | ||
135 | printk(KERN_ERR "ctxfi: Fail! No sufficient device virtural " | ||
136 | "memory space available!\n"); | ||
137 | return NULL; | ||
138 | } | ||
139 | |||
140 | start_phys = (virt_to_phys(host_addr) & CT_PAGE_MASK); | ||
141 | pages = (CT_PAGE_ALIGN(virt_to_phys(host_addr) + size) | ||
142 | - start_phys) >> CT_PAGE_SHIFT; | ||
143 | |||
144 | ptp = vm->ptp[0]; | ||
145 | |||
146 | block = get_vm_block(vm, (pages << CT_PAGE_SHIFT)); | ||
147 | if (block == NULL) { | 135 | if (block == NULL) { |
148 | printk(KERN_ERR "ctxfi: No virtual memory block that is big " | 136 | printk(KERN_ERR "ctxfi: No virtual memory block that is big " |
149 | "enough to allocate!\n"); | 137 | "enough to allocate!\n"); |
150 | return NULL; | 138 | return NULL; |
151 | } | 139 | } |
152 | 140 | ||
141 | ptp = vm->ptp[0]; | ||
153 | pte_start = (block->addr >> CT_PAGE_SHIFT); | 142 | pte_start = (block->addr >> CT_PAGE_SHIFT); |
154 | for (i = 0; i < pages; i++) | 143 | pages = block->size >> CT_PAGE_SHIFT; |
155 | ptp[pte_start+i] = start_phys + (i << CT_PAGE_SHIFT); | 144 | for (i = 0; i < pages; i++) { |
145 | unsigned long addr; | ||
146 | addr = snd_pcm_sgbuf_get_addr(substream, i << CT_PAGE_SHIFT); | ||
147 | ptp[pte_start + i] = addr; | ||
148 | } | ||
156 | 149 | ||
157 | block->addr += (virt_to_phys(host_addr) & (~CT_PAGE_MASK)); | ||
158 | block->size = size; | 150 | block->size = size; |
159 | |||
160 | return block; | 151 | return block; |
161 | } | 152 | } |
162 | 153 | ||
163 | static void ct_vm_unmap(struct ct_vm *vm, struct ct_vm_block *block) | 154 | static void ct_vm_unmap(struct ct_vm *vm, struct ct_vm_block *block) |
164 | { | 155 | { |
165 | /* do unmapping */ | 156 | /* do unmapping */ |
166 | block->size = ((block->addr + block->size + CT_PAGE_SIZE - 1) | ||
167 | & CT_PAGE_MASK) - (block->addr & CT_PAGE_MASK); | ||
168 | block->addr &= CT_PAGE_MASK; | ||
169 | put_vm_block(vm, block); | 157 | put_vm_block(vm, block); |
170 | } | 158 | } |
171 | 159 | ||
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 { | |||
37 | struct list_head list; | 37 | struct list_head list; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | struct snd_pcm_substream; | ||
41 | |||
40 | /* Virtual memory management object for card device */ | 42 | /* Virtual memory management object for card device */ |
41 | struct ct_vm { | 43 | struct ct_vm { |
42 | void *ptp[CT_PTP_NUM]; /* Device page table pages */ | 44 | void *ptp[CT_PTP_NUM]; /* Device page table pages */ |
@@ -46,7 +48,8 @@ struct ct_vm { | |||
46 | struct mutex lock; | 48 | struct mutex lock; |
47 | 49 | ||
48 | /* Map host addr (kmalloced/vmalloced) to device logical addr. */ | 50 | /* Map host addr (kmalloced/vmalloced) to device logical addr. */ |
49 | struct ct_vm_block *(*map)(struct ct_vm *, void *host_addr, int size); | 51 | struct ct_vm_block *(*map)(struct ct_vm *, struct snd_pcm_substream *, |
52 | int size); | ||
50 | /* Unmap device logical addr area. */ | 53 | /* Unmap device logical addr area. */ |
51 | void (*unmap)(struct ct_vm *, struct ct_vm_block *block); | 54 | void (*unmap)(struct ct_vm *, struct ct_vm_block *block); |
52 | void *(*get_ptp_virt)(struct ct_vm *vm, int index); | 55 | void *(*get_ptp_virt)(struct ct_vm *vm, int index); |