ep93xx-pcm.c (12e04ffcd93b25dfd726d46338c2ee7d23de556e) | ep93xx-pcm.c (e27e8a60cb4ca8e3b047c5d6ee9afff9c4c5b61a) |
---|---|
1/* 2 * linux/sound/arm/ep93xx-pcm.c - EP93xx ALSA PCM interface 3 * 4 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> 5 * Copyright (C) 2006 Applied Data Systems 6 * 7 * Rewritten for the SoC audio subsystem (Based on PXA2xx code): 8 * Copyright (c) 2008 Ryan Mallon 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15#include <linux/module.h> 16#include <linux/init.h> | 1/* 2 * linux/sound/arm/ep93xx-pcm.c - EP93xx ALSA PCM interface 3 * 4 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> 5 * Copyright (C) 2006 Applied Data Systems 6 * 7 * Rewritten for the SoC audio subsystem (Based on PXA2xx code): 8 * Copyright (c) 2008 Ryan Mallon 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15#include <linux/module.h> 16#include <linux/init.h> |
17#include <linux/device.h> 18#include <linux/slab.h> | 17#include <linux/platform_device.h> |
19#include <linux/dmaengine.h> | 18#include <linux/dmaengine.h> |
20#include <linux/dma-mapping.h> | |
21 | 19 |
22#include <sound/core.h> | |
23#include <sound/pcm.h> | 20#include <sound/pcm.h> |
24#include <sound/pcm_params.h> | |
25#include <sound/soc.h> 26#include <sound/dmaengine_pcm.h> 27 28#include <linux/platform_data/dma-ep93xx.h> | 21#include <sound/soc.h> 22#include <sound/dmaengine_pcm.h> 23 24#include <linux/platform_data/dma-ep93xx.h> |
29#include <mach/hardware.h> 30#include <mach/ep93xx-regs.h> | |
31 32static const struct snd_pcm_hardware ep93xx_pcm_hardware = { 33 .info = (SNDRV_PCM_INFO_MMAP | 34 SNDRV_PCM_INFO_MMAP_VALID | 35 SNDRV_PCM_INFO_INTERLEAVED | 36 SNDRV_PCM_INFO_BLOCK_TRANSFER), 37 38 .rates = SNDRV_PCM_RATE_8000_192000, --- 19 unchanged lines hidden (view full) --- 58 if (data->direction == ep93xx_dma_chan_direction(chan)) { 59 chan->private = data; 60 return true; 61 } 62 63 return false; 64} 65 | 25 26static const struct snd_pcm_hardware ep93xx_pcm_hardware = { 27 .info = (SNDRV_PCM_INFO_MMAP | 28 SNDRV_PCM_INFO_MMAP_VALID | 29 SNDRV_PCM_INFO_INTERLEAVED | 30 SNDRV_PCM_INFO_BLOCK_TRANSFER), 31 32 .rates = SNDRV_PCM_RATE_8000_192000, --- 19 unchanged lines hidden (view full) --- 52 if (data->direction == ep93xx_dma_chan_direction(chan)) { 53 chan->private = data; 54 return true; 55 } 56 57 return false; 58} 59 |
66static int ep93xx_pcm_open(struct snd_pcm_substream *substream) 67{ 68 struct snd_soc_pcm_runtime *rtd = substream->private_data; 69 70 snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); 71 72 return snd_dmaengine_pcm_open_request_chan(substream, 73 ep93xx_pcm_dma_filter, 74 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream)); 75} 76 77static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, 78 struct snd_pcm_hw_params *params) 79{ 80 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 81 82 return 0; 83} 84 85static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream) 86{ 87 snd_pcm_set_runtime_buffer(substream, NULL); 88 return 0; 89} 90 91static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream, 92 struct vm_area_struct *vma) 93{ 94 struct snd_pcm_runtime *runtime = substream->runtime; 95 96 return dma_mmap_writecombine(substream->pcm->card->dev, vma, 97 runtime->dma_area, 98 runtime->dma_addr, 99 runtime->dma_bytes); 100} 101 102static struct snd_pcm_ops ep93xx_pcm_ops = { 103 .open = ep93xx_pcm_open, 104 .close = snd_dmaengine_pcm_close_release_chan, 105 .ioctl = snd_pcm_lib_ioctl, 106 .hw_params = ep93xx_pcm_hw_params, 107 .hw_free = ep93xx_pcm_hw_free, 108 .trigger = snd_dmaengine_pcm_trigger, 109 .pointer = snd_dmaengine_pcm_pointer_no_residue, 110 .mmap = ep93xx_pcm_mmap, | 60static const struct snd_dmaengine_pcm_config ep93xx_dmaengine_pcm_config = { 61 .pcm_hardware = &ep93xx_pcm_hardware, 62 .compat_filter_fn = ep93xx_pcm_dma_filter, 63 .prealloc_buffer_size = 131072, |
111}; 112 | 64}; 65 |
113static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 114{ 115 struct snd_pcm_substream *substream = pcm->streams[stream].substream; 116 struct snd_dma_buffer *buf = &substream->dma_buffer; 117 size_t size = ep93xx_pcm_hardware.buffer_bytes_max; 118 119 buf->dev.type = SNDRV_DMA_TYPE_DEV; 120 buf->dev.dev = pcm->card->dev; 121 buf->private_data = NULL; 122 buf->area = dma_alloc_writecombine(pcm->card->dev, size, 123 &buf->addr, GFP_KERNEL); 124 buf->bytes = size; 125 126 return (buf->area == NULL) ? -ENOMEM : 0; 127} 128 129static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm) 130{ 131 struct snd_pcm_substream *substream; 132 struct snd_dma_buffer *buf; 133 int stream; 134 135 for (stream = 0; stream < 2; stream++) { 136 substream = pcm->streams[stream].substream; 137 if (!substream) 138 continue; 139 140 buf = &substream->dma_buffer; 141 if (!buf->area) 142 continue; 143 144 dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area, 145 buf->addr); 146 buf->area = NULL; 147 } 148} 149 150static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32); 151 152static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd) 153{ 154 struct snd_card *card = rtd->card->snd_card; 155 struct snd_pcm *pcm = rtd->pcm; 156 int ret = 0; 157 158 if (!card->dev->dma_mask) 159 card->dev->dma_mask = &ep93xx_pcm_dmamask; 160 if (!card->dev->coherent_dma_mask) 161 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 162 163 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { 164 ret = ep93xx_pcm_preallocate_dma_buffer(pcm, 165 SNDRV_PCM_STREAM_PLAYBACK); 166 if (ret) 167 return ret; 168 } 169 170 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { 171 ret = ep93xx_pcm_preallocate_dma_buffer(pcm, 172 SNDRV_PCM_STREAM_CAPTURE); 173 if (ret) 174 return ret; 175 } 176 177 return 0; 178} 179 180static struct snd_soc_platform_driver ep93xx_soc_platform = { 181 .ops = &ep93xx_pcm_ops, 182 .pcm_new = &ep93xx_pcm_new, 183 .pcm_free = &ep93xx_pcm_free_dma_buffers, 184}; 185 | |
186static int ep93xx_soc_platform_probe(struct platform_device *pdev) 187{ | 66static int ep93xx_soc_platform_probe(struct platform_device *pdev) 67{ |
188 return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform); | 68 return snd_dmaengine_pcm_register(&pdev->dev, 69 &ep93xx_dmaengine_pcm_config, 70 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | 71 SND_DMAENGINE_PCM_FLAG_NO_DT | 72 SND_DMAENGINE_PCM_FLAG_COMPAT); |
189} 190 191static int ep93xx_soc_platform_remove(struct platform_device *pdev) 192{ | 73} 74 75static int ep93xx_soc_platform_remove(struct platform_device *pdev) 76{ |
193 snd_soc_unregister_platform(&pdev->dev); | 77 snd_dmaengine_pcm_unregister(&pdev->dev); |
194 return 0; 195} 196 197static struct platform_driver ep93xx_pcm_driver = { 198 .driver = { 199 .name = "ep93xx-pcm-audio", 200 .owner = THIS_MODULE, 201 }, 202 203 .probe = ep93xx_soc_platform_probe, 204 .remove = ep93xx_soc_platform_remove, 205}; 206 207module_platform_driver(ep93xx_pcm_driver); 208 209MODULE_AUTHOR("Ryan Mallon"); 210MODULE_DESCRIPTION("EP93xx ALSA PCM interface"); 211MODULE_LICENSE("GPL"); 212MODULE_ALIAS("platform:ep93xx-pcm-audio"); | 78 return 0; 79} 80 81static struct platform_driver ep93xx_pcm_driver = { 82 .driver = { 83 .name = "ep93xx-pcm-audio", 84 .owner = THIS_MODULE, 85 }, 86 87 .probe = ep93xx_soc_platform_probe, 88 .remove = ep93xx_soc_platform_remove, 89}; 90 91module_platform_driver(ep93xx_pcm_driver); 92 93MODULE_AUTHOR("Ryan Mallon"); 94MODULE_DESCRIPTION("EP93xx ALSA PCM interface"); 95MODULE_LICENSE("GPL"); 96MODULE_ALIAS("platform:ep93xx-pcm-audio"); |