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 | |
| 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>
| -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); |
