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_stream_lock(substream); 204 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); 205 snd_pcm_stream_unlock(substream); 206 } 207 } 208 EXPORT_SYMBOL(pxa2xx_pcm_dma_irq); 209 210 int __pxa2xx_pcm_open(struct snd_pcm_substream *substream) 211 { 212 struct snd_pcm_runtime *runtime = substream->runtime; 213 struct pxa2xx_runtime_data *rtd; 214 int ret; 215 216 runtime->hw = pxa2xx_pcm_hardware; 217 218 /* 219 * For mysterious reasons (and despite what the manual says) 220 * playback samples are lost if the DMA count is not a multiple 221 * of the DMA burst size. Let's add a rule to enforce that. 222 */ 223 ret = snd_pcm_hw_constraint_step(runtime, 0, 224 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); 225 if (ret) 226 goto out; 227 228 ret = snd_pcm_hw_constraint_step(runtime, 0, 229 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); 230 if (ret) 231 goto out; 232 233 ret = snd_pcm_hw_constraint_integer(runtime, 234 SNDRV_PCM_HW_PARAM_PERIODS); 235 if (ret < 0) 236 goto out; 237 238 ret = -ENOMEM; 239 rtd = kzalloc(sizeof(*rtd), GFP_KERNEL); 240 if (!rtd) 241 goto out; 242 rtd->dma_desc_array = 243 dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE, 244 &rtd->dma_desc_array_phys, GFP_KERNEL); 245 if (!rtd->dma_desc_array) 246 goto err1; 247 248 rtd->dma_ch = -1; 249 runtime->private_data = rtd; 250 return 0; 251 252 err1: 253 kfree(rtd); 254 out: 255 return ret; 256 } 257 EXPORT_SYMBOL(__pxa2xx_pcm_open); 258 259 int __pxa2xx_pcm_close(struct snd_pcm_substream *substream) 260 { 261 struct snd_pcm_runtime *runtime = substream->runtime; 262 struct pxa2xx_runtime_data *rtd = runtime->private_data; 263 264 dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE, 265 rtd->dma_desc_array, rtd->dma_desc_array_phys); 266 kfree(rtd); 267 return 0; 268 } 269 EXPORT_SYMBOL(__pxa2xx_pcm_close); 270 271 int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream, 272 struct vm_area_struct *vma) 273 { 274 struct snd_pcm_runtime *runtime = substream->runtime; 275 return dma_mmap_writecombine(substream->pcm->card->dev, vma, 276 runtime->dma_area, 277 runtime->dma_addr, 278 runtime->dma_bytes); 279 } 280 EXPORT_SYMBOL(pxa2xx_pcm_mmap); 281 282 int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 283 { 284 struct snd_pcm_substream *substream = pcm->streams[stream].substream; 285 struct snd_dma_buffer *buf = &substream->dma_buffer; 286 size_t size = pxa2xx_pcm_hardware.buffer_bytes_max; 287 buf->dev.type = SNDRV_DMA_TYPE_DEV; 288 buf->dev.dev = pcm->card->dev; 289 buf->private_data = NULL; 290 buf->area = dma_alloc_writecombine(pcm->card->dev, size, 291 &buf->addr, GFP_KERNEL); 292 if (!buf->area) 293 return -ENOMEM; 294 buf->bytes = size; 295 return 0; 296 } 297 EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer); 298 299 void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm) 300 { 301 struct snd_pcm_substream *substream; 302 struct snd_dma_buffer *buf; 303 int stream; 304 305 for (stream = 0; stream < 2; stream++) { 306 substream = pcm->streams[stream].substream; 307 if (!substream) 308 continue; 309 buf = &substream->dma_buffer; 310 if (!buf->area) 311 continue; 312 dma_free_writecombine(pcm->card->dev, buf->bytes, 313 buf->area, buf->addr); 314 buf->area = NULL; 315 } 316 } 317 EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers); 318 319 MODULE_AUTHOR("Nicolas Pitre"); 320 MODULE_DESCRIPTION("Intel PXA2xx sound library"); 321 MODULE_LICENSE("GPL"); 322