1 /* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License version 2 as 4 * published by the Free Software Foundation. 5 */ 6 7 #include <linux/slab.h> 8 #include <linux/module.h> 9 #include <linux/dma-mapping.h> 10 #include <linux/dmaengine.h> 11 12 #include <sound/core.h> 13 #include <sound/pcm.h> 14 #include <sound/pcm_params.h> 15 #include <sound/pxa2xx-lib.h> 16 #include <sound/dmaengine_pcm.h> 17 18 #include <mach/dma.h> 19 20 #include "pxa2xx-pcm.h" 21 22 static const struct snd_pcm_hardware pxa2xx_pcm_hardware = { 23 .info = SNDRV_PCM_INFO_MMAP | 24 SNDRV_PCM_INFO_MMAP_VALID | 25 SNDRV_PCM_INFO_INTERLEAVED | 26 SNDRV_PCM_INFO_PAUSE | 27 SNDRV_PCM_INFO_RESUME, 28 .formats = SNDRV_PCM_FMTBIT_S16_LE | 29 SNDRV_PCM_FMTBIT_S24_LE | 30 SNDRV_PCM_FMTBIT_S32_LE, 31 .period_bytes_min = 32, 32 .period_bytes_max = 8192 - 32, 33 .periods_min = 1, 34 .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc), 35 .buffer_bytes_max = 128 * 1024, 36 .fifo_size = 32, 37 }; 38 39 int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, 40 struct snd_pcm_hw_params *params) 41 { 42 struct snd_pcm_runtime *runtime = substream->runtime; 43 struct pxa2xx_runtime_data *rtd = runtime->private_data; 44 size_t totsize = params_buffer_bytes(params); 45 size_t period = params_period_bytes(params); 46 pxa_dma_desc *dma_desc; 47 dma_addr_t dma_buff_phys, next_desc_phys; 48 u32 dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG; 49 50 /* temporary transition hack */ 51 switch (rtd->params->addr_width) { 52 case DMA_SLAVE_BUSWIDTH_1_BYTE: 53 dcmd |= DCMD_WIDTH1; 54 break; 55 case DMA_SLAVE_BUSWIDTH_2_BYTES: 56 dcmd |= DCMD_WIDTH2; 57 break; 58 case DMA_SLAVE_BUSWIDTH_4_BYTES: 59 dcmd |= DCMD_WIDTH4; 60 break; 61 default: 62 /* can't happen */ 63 break; 64 } 65 66 switch (rtd->params->maxburst) { 67 case 8: 68 dcmd |= DCMD_BURST8; 69 break; 70 case 16: 71 dcmd |= DCMD_BURST16; 72 break; 73 case 32: 74 dcmd |= DCMD_BURST32; 75 break; 76 } 77 78 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 79 runtime->dma_bytes = totsize; 80 81 dma_desc = rtd->dma_desc_array; 82 next_desc_phys = rtd->dma_desc_array_phys; 83 dma_buff_phys = runtime->dma_addr; 84 do { 85 next_desc_phys += sizeof(pxa_dma_desc); 86 dma_desc->ddadr = next_desc_phys; 87 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 88 dma_desc->dsadr = dma_buff_phys; 89 dma_desc->dtadr = rtd->params->addr; 90 } else { 91 dma_desc->dsadr = rtd->params->addr; 92 dma_desc->dtadr = dma_buff_phys; 93 } 94 if (period > totsize) 95 period = totsize; 96 dma_desc->dcmd = dcmd | period | DCMD_ENDIRQEN; 97 dma_desc++; 98 dma_buff_phys += period; 99 } while (totsize -= period); 100 dma_desc[-1].ddadr = rtd->dma_desc_array_phys; 101 102 return 0; 103 } 104 EXPORT_SYMBOL(__pxa2xx_pcm_hw_params); 105 106 int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) 107 { 108 struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; 109 110 if (rtd && rtd->params && rtd->params->filter_data) { 111 unsigned long req = *(unsigned long *) rtd->params->filter_data; 112 DRCMR(req) = 0; 113 } 114 115 snd_pcm_set_runtime_buffer(substream, NULL); 116 return 0; 117 } 118 EXPORT_SYMBOL(__pxa2xx_pcm_hw_free); 119 120 int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 121 { 122 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; 123 int ret = 0; 124 125 switch (cmd) { 126 case SNDRV_PCM_TRIGGER_START: 127 DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys; 128 DCSR(prtd->dma_ch) = DCSR_RUN; 129 break; 130 131 case SNDRV_PCM_TRIGGER_STOP: 132 case SNDRV_PCM_TRIGGER_SUSPEND: 133 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 134 DCSR(prtd->dma_ch) &= ~DCSR_RUN; 135 break; 136 137 case SNDRV_PCM_TRIGGER_RESUME: 138 DCSR(prtd->dma_ch) |= DCSR_RUN; 139 break; 140 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 141 DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys; 142 DCSR(prtd->dma_ch) |= DCSR_RUN; 143 break; 144 145 default: 146 ret = -EINVAL; 147 } 148 149 return ret; 150 } 151 EXPORT_SYMBOL(pxa2xx_pcm_trigger); 152 153 snd_pcm_uframes_t 154 pxa2xx_pcm_pointer(struct snd_pcm_substream *substream) 155 { 156 struct snd_pcm_runtime *runtime = substream->runtime; 157 struct pxa2xx_runtime_data *prtd = runtime->private_data; 158 159 dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 160 DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch); 161 snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr); 162 163 if (x == runtime->buffer_size) 164 x = 0; 165 return x; 166 } 167 EXPORT_SYMBOL(pxa2xx_pcm_pointer); 168 169 int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) 170 { 171 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; 172 unsigned long req; 173 174 if (!prtd || !prtd->params) 175 return 0; 176 177 if (prtd->dma_ch == -1) 178 return -EINVAL; 179 180 DCSR(prtd->dma_ch) &= ~DCSR_RUN; 181 DCSR(prtd->dma_ch) = 0; 182 DCMD(prtd->dma_ch) = 0; 183 req = *(unsigned long *) prtd->params->filter_data; 184 DRCMR(req) = prtd->dma_ch | DRCMR_MAPVLD; 185 186 return 0; 187 } 188 EXPORT_SYMBOL(__pxa2xx_pcm_prepare); 189 190 void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id) 191 { 192 struct snd_pcm_substream *substream = dev_id; 193 int dcsr; 194 195 dcsr = DCSR(dma_ch); 196 DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN; 197 198 if (dcsr & DCSR_ENDINTR) { 199 snd_pcm_period_elapsed(substream); 200 } else { 201 printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n", 202 dma_ch, dcsr); 203 snd_pcm_stop_xrun(substream); 204 } 205 } 206 EXPORT_SYMBOL(pxa2xx_pcm_dma_irq); 207 208 int __pxa2xx_pcm_open(struct snd_pcm_substream *substream) 209 { 210 struct snd_pcm_runtime *runtime = substream->runtime; 211 struct pxa2xx_runtime_data *rtd; 212 int ret; 213 214 runtime->hw = pxa2xx_pcm_hardware; 215 216 /* 217 * For mysterious reasons (and despite what the manual says) 218 * playback samples are lost if the DMA count is not a multiple 219 * of the DMA burst size. Let's add a rule to enforce that. 220 */ 221 ret = snd_pcm_hw_constraint_step(runtime, 0, 222 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); 223 if (ret) 224 goto out; 225 226 ret = snd_pcm_hw_constraint_step(runtime, 0, 227 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); 228 if (ret) 229 goto out; 230 231 ret = snd_pcm_hw_constraint_integer(runtime, 232 SNDRV_PCM_HW_PARAM_PERIODS); 233 if (ret < 0) 234 goto out; 235 236 ret = -ENOMEM; 237 rtd = kzalloc(sizeof(*rtd), GFP_KERNEL); 238 if (!rtd) 239 goto out; 240 rtd->dma_desc_array = 241 dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE, 242 &rtd->dma_desc_array_phys, GFP_KERNEL); 243 if (!rtd->dma_desc_array) 244 goto err1; 245 246 rtd->dma_ch = -1; 247 runtime->private_data = rtd; 248 return 0; 249 250 err1: 251 kfree(rtd); 252 out: 253 return ret; 254 } 255 EXPORT_SYMBOL(__pxa2xx_pcm_open); 256 257 int __pxa2xx_pcm_close(struct snd_pcm_substream *substream) 258 { 259 struct snd_pcm_runtime *runtime = substream->runtime; 260 struct pxa2xx_runtime_data *rtd = runtime->private_data; 261 262 dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE, 263 rtd->dma_desc_array, rtd->dma_desc_array_phys); 264 kfree(rtd); 265 return 0; 266 } 267 EXPORT_SYMBOL(__pxa2xx_pcm_close); 268 269 int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream, 270 struct vm_area_struct *vma) 271 { 272 struct snd_pcm_runtime *runtime = substream->runtime; 273 return dma_mmap_writecombine(substream->pcm->card->dev, vma, 274 runtime->dma_area, 275 runtime->dma_addr, 276 runtime->dma_bytes); 277 } 278 EXPORT_SYMBOL(pxa2xx_pcm_mmap); 279 280 int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 281 { 282 struct snd_pcm_substream *substream = pcm->streams[stream].substream; 283 struct snd_dma_buffer *buf = &substream->dma_buffer; 284 size_t size = pxa2xx_pcm_hardware.buffer_bytes_max; 285 buf->dev.type = SNDRV_DMA_TYPE_DEV; 286 buf->dev.dev = pcm->card->dev; 287 buf->private_data = NULL; 288 buf->area = dma_alloc_writecombine(pcm->card->dev, size, 289 &buf->addr, GFP_KERNEL); 290 if (!buf->area) 291 return -ENOMEM; 292 buf->bytes = size; 293 return 0; 294 } 295 EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer); 296 297 void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm) 298 { 299 struct snd_pcm_substream *substream; 300 struct snd_dma_buffer *buf; 301 int stream; 302 303 for (stream = 0; stream < 2; stream++) { 304 substream = pcm->streams[stream].substream; 305 if (!substream) 306 continue; 307 buf = &substream->dma_buffer; 308 if (!buf->area) 309 continue; 310 dma_free_writecombine(pcm->card->dev, buf->bytes, 311 buf->area, buf->addr); 312 buf->area = NULL; 313 } 314 } 315 EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers); 316 317 MODULE_AUTHOR("Nicolas Pitre"); 318 MODULE_DESCRIPTION("Intel PXA2xx sound library"); 319 MODULE_LICENSE("GPL"); 320