diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-11-26 06:40:21 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-11-26 09:07:14 -0500 |
commit | 657b1989dacf58e83e7a76bca6d4a91a9f294cf6 (patch) | |
tree | 8503f4609840da79c8438d8ae1f6e4fb3df62346 /sound/core | |
parent | 648f4e3e50c4793d9dbf9a09afa193631f76fa26 (diff) |
ALSA: pcm - Use dma_mmap_coherent() if available
Use dma_mmap_coherent() for mmapping the buffers allocated via
dma_alloc_coherent() if available. Currently, only ARM has this function,
so we do temporarily have an ifdef pcm_native.c. This should be handled
better globally in future.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/pcm_native.c | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index ab73edf2c89a..f067c5b906e4 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/time.h> | 26 | #include <linux/time.h> |
27 | #include <linux/pm_qos_params.h> | 27 | #include <linux/pm_qos_params.h> |
28 | #include <linux/uio.h> | 28 | #include <linux/uio.h> |
29 | #include <linux/dma-mapping.h> | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/control.h> | 31 | #include <sound/control.h> |
31 | #include <sound/info.h> | 32 | #include <sound/info.h> |
@@ -3094,23 +3095,42 @@ static int snd_pcm_mmap_data_fault(struct vm_area_struct *area, | |||
3094 | return 0; | 3095 | return 0; |
3095 | } | 3096 | } |
3096 | 3097 | ||
3097 | static const struct vm_operations_struct snd_pcm_vm_ops_data = | 3098 | static const struct vm_operations_struct snd_pcm_vm_ops_data = { |
3098 | { | 3099 | .open = snd_pcm_mmap_data_open, |
3100 | .close = snd_pcm_mmap_data_close, | ||
3101 | }; | ||
3102 | |||
3103 | static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = { | ||
3099 | .open = snd_pcm_mmap_data_open, | 3104 | .open = snd_pcm_mmap_data_open, |
3100 | .close = snd_pcm_mmap_data_close, | 3105 | .close = snd_pcm_mmap_data_close, |
3101 | .fault = snd_pcm_mmap_data_fault, | 3106 | .fault = snd_pcm_mmap_data_fault, |
3102 | }; | 3107 | }; |
3103 | 3108 | ||
3109 | #ifndef ARCH_HAS_DMA_MMAP_COHERENT | ||
3110 | /* This should be defined / handled globally! */ | ||
3111 | #ifdef CONFIG_ARM | ||
3112 | #define ARCH_HAS_DMA_MMAP_COHERENT | ||
3113 | #endif | ||
3114 | #endif | ||
3115 | |||
3104 | /* | 3116 | /* |
3105 | * mmap the DMA buffer on RAM | 3117 | * mmap the DMA buffer on RAM |
3106 | */ | 3118 | */ |
3107 | static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, | 3119 | static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, |
3108 | struct vm_area_struct *area) | 3120 | struct vm_area_struct *area) |
3109 | { | 3121 | { |
3110 | area->vm_ops = &snd_pcm_vm_ops_data; | ||
3111 | area->vm_private_data = substream; | ||
3112 | area->vm_flags |= VM_RESERVED; | 3122 | area->vm_flags |= VM_RESERVED; |
3113 | atomic_inc(&substream->mmap_count); | 3123 | #ifdef ARCH_HAS_DMA_MMAP_COHERENT |
3124 | if (!substream->ops->page && | ||
3125 | substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) | ||
3126 | return dma_mmap_coherent(substream->dma_buffer.dev.dev, | ||
3127 | area, | ||
3128 | substream->runtime->dma_area, | ||
3129 | substream->runtime->dma_addr, | ||
3130 | area->vm_end - area->vm_start); | ||
3131 | #endif /* ARCH_HAS_DMA_MMAP_COHERENT */ | ||
3132 | /* mmap with fault handler */ | ||
3133 | area->vm_ops = &snd_pcm_vm_ops_data_fault; | ||
3114 | return 0; | 3134 | return 0; |
3115 | } | 3135 | } |
3116 | 3136 | ||
@@ -3118,12 +3138,6 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, | |||
3118 | * mmap the DMA buffer on I/O memory area | 3138 | * mmap the DMA buffer on I/O memory area |
3119 | */ | 3139 | */ |
3120 | #if SNDRV_PCM_INFO_MMAP_IOMEM | 3140 | #if SNDRV_PCM_INFO_MMAP_IOMEM |
3121 | static const struct vm_operations_struct snd_pcm_vm_ops_data_mmio = | ||
3122 | { | ||
3123 | .open = snd_pcm_mmap_data_open, | ||
3124 | .close = snd_pcm_mmap_data_close, | ||
3125 | }; | ||
3126 | |||
3127 | int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, | 3141 | int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, |
3128 | struct vm_area_struct *area) | 3142 | struct vm_area_struct *area) |
3129 | { | 3143 | { |
@@ -3133,8 +3147,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, | |||
3133 | #ifdef pgprot_noncached | 3147 | #ifdef pgprot_noncached |
3134 | area->vm_page_prot = pgprot_noncached(area->vm_page_prot); | 3148 | area->vm_page_prot = pgprot_noncached(area->vm_page_prot); |
3135 | #endif | 3149 | #endif |
3136 | area->vm_ops = &snd_pcm_vm_ops_data_mmio; | ||
3137 | area->vm_private_data = substream; | ||
3138 | area->vm_flags |= VM_IO; | 3150 | area->vm_flags |= VM_IO; |
3139 | size = area->vm_end - area->vm_start; | 3151 | size = area->vm_end - area->vm_start; |
3140 | offset = area->vm_pgoff << PAGE_SHIFT; | 3152 | offset = area->vm_pgoff << PAGE_SHIFT; |
@@ -3142,7 +3154,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, | |||
3142 | (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, | 3154 | (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, |
3143 | size, area->vm_page_prot)) | 3155 | size, area->vm_page_prot)) |
3144 | return -EAGAIN; | 3156 | return -EAGAIN; |
3145 | atomic_inc(&substream->mmap_count); | ||
3146 | return 0; | 3157 | return 0; |
3147 | } | 3158 | } |
3148 | 3159 | ||
@@ -3159,6 +3170,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, | |||
3159 | long size; | 3170 | long size; |
3160 | unsigned long offset; | 3171 | unsigned long offset; |
3161 | size_t dma_bytes; | 3172 | size_t dma_bytes; |
3173 | int err; | ||
3162 | 3174 | ||
3163 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 3175 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
3164 | if (!(area->vm_flags & (VM_WRITE|VM_READ))) | 3176 | if (!(area->vm_flags & (VM_WRITE|VM_READ))) |
@@ -3183,10 +3195,15 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, | |||
3183 | if (offset > dma_bytes - size) | 3195 | if (offset > dma_bytes - size) |
3184 | return -EINVAL; | 3196 | return -EINVAL; |
3185 | 3197 | ||
3198 | area->vm_ops = &snd_pcm_vm_ops_data; | ||
3199 | area->vm_private_data = substream; | ||
3186 | if (substream->ops->mmap) | 3200 | if (substream->ops->mmap) |
3187 | return substream->ops->mmap(substream, area); | 3201 | err = substream->ops->mmap(substream, area); |
3188 | else | 3202 | else |
3189 | return snd_pcm_default_mmap(substream, area); | 3203 | err = snd_pcm_default_mmap(substream, area); |
3204 | if (!err) | ||
3205 | atomic_inc(&substream->mmap_count); | ||
3206 | return err; | ||
3190 | } | 3207 | } |
3191 | 3208 | ||
3192 | EXPORT_SYMBOL(snd_pcm_mmap_data); | 3209 | EXPORT_SYMBOL(snd_pcm_mmap_data); |