1/* 2 * linux/sound/arm/devdma.c 3 * 4 * Copyright (C) 2003-2004 Russell King, All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * ARM DMA shim for ALSA. 11 */ 12#include <linux/device.h> 13#include <linux/dma-mapping.h> 14 15#include <sound/driver.h> 16#include <sound/core.h> 17#include <sound/pcm.h> 18 19#include "devdma.h" 20 21void devdma_hw_free(struct device *dev, struct snd_pcm_substream *substream) 22{ 23 struct snd_pcm_runtime *runtime = substream->runtime; 24 struct snd_dma_buffer *buf = runtime->dma_buffer_p; 25 26 if (runtime->dma_area == NULL) 27 return; 28 29 if (buf != &substream->dma_buffer) { 30 dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, buf->addr); 31 kfree(runtime->dma_buffer_p); 32 } 33 34 snd_pcm_set_runtime_buffer(substream, NULL); 35} 36 37int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream *substream, size_t size) 38{ 39 struct snd_pcm_runtime *runtime = substream->runtime; 40 struct snd_dma_buffer *buf = runtime->dma_buffer_p; 41 int ret = 0; 42 43 if (buf) { 44 if (buf->bytes >= size) 45 goto out; 46 devdma_hw_free(dev, substream); 47 } 48 49 if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) { 50 buf = &substream->dma_buffer; 51 } else { 52 buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); 53 if (!buf) 54 goto nomem; 55 56 buf->dev.type = SNDRV_DMA_TYPE_DEV; 57 buf->dev.dev = dev; 58 buf->area = dma_alloc_coherent(dev, size, &buf->addr, GFP_KERNEL); 59 buf->bytes = size; 60 buf->private_data = NULL; 61 62 if (!buf->area) 63 goto free; 64 } 65 snd_pcm_set_runtime_buffer(substream, buf); 66 ret = 1; 67 out: 68 runtime->dma_bytes = size; 69 return ret; 70 71 free: 72 kfree(buf); 73 nomem: 74 return -ENOMEM; 75} 76 77int devdma_mmap(struct device *dev, struct snd_pcm_substream *substream, struct vm_area_struct *vma) 78{ 79 struct snd_pcm_runtime *runtime = substream->runtime; 80 return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); 81} 82