| /* | |
| * linux/sound/arm/devdma.c | |
| * | |
| * Copyright (C) 2003-2004 Russell King, All rights reserved. | |
| * | |
| * This program is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU General Public License version 2 as | |
| * published by the Free Software Foundation. | |
| * | |
| * ARM DMA shim for ALSA. | |
| */ | |
| #include <linux/device.h> | |
| #include <linux/dma-mapping.h> | |
| #include <sound/driver.h> | |
| #include <sound/core.h> | |
| #include <sound/pcm.h> | |
| #include "devdma.h" | |
| void devdma_hw_free(struct device *dev, struct snd_pcm_substream *substream) | |
| { | |
| struct snd_pcm_runtime *runtime = substream->runtime; | |
| struct snd_dma_buffer *buf = runtime->dma_buffer_p; | |
| if (runtime->dma_area == NULL) | |
| return; | |
| if (buf != &substream->dma_buffer) { | |
| dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, buf->addr); | |
| kfree(runtime->dma_buffer_p); | |
| } | |
| snd_pcm_set_runtime_buffer(substream, NULL); | |
| } | |
| int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream *substream, size_t size) | |
| { | |
| struct snd_pcm_runtime *runtime = substream->runtime; | |
| struct snd_dma_buffer *buf = runtime->dma_buffer_p; | |
| int ret = 0; | |
| if (buf) { | |
| if (buf->bytes >= size) | |
| goto out; | |
| devdma_hw_free(dev, substream); | |
| } | |
| if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) { | |
| buf = &substream->dma_buffer; | |
| } else { | |
| buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); | |
| if (!buf) | |
| goto nomem; | |
| buf->dev.type = SNDRV_DMA_TYPE_DEV; | |
| buf->dev.dev = dev; | |
| buf->area = dma_alloc_coherent(dev, size, &buf->addr, GFP_KERNEL); | |
| buf->bytes = size; | |
| buf->private_data = NULL; | |
| if (!buf->area) | |
| goto free; | |
| } | |
| snd_pcm_set_runtime_buffer(substream, buf); | |
| ret = 1; | |
| out: | |
| runtime->dma_bytes = size; | |
| return ret; | |
| free: | |
| kfree(buf); | |
| nomem: | |
| return -ENOMEM; | |
| } | |
| int devdma_mmap(struct device *dev, struct snd_pcm_substream *substream, struct vm_area_struct *vma) | |
| { | |
| struct snd_pcm_runtime *runtime = substream->runtime; | |
| return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); | |
| } |