1 /* 2 * tegra_pcm.c - Tegra PCM driver 3 * 4 * Author: Stephen Warren <swarren@nvidia.com> 5 * Copyright (C) 2010 - NVIDIA, Inc. 6 * 7 * Based on code copyright/by: 8 * 9 * Copyright (c) 2009-2010, NVIDIA Corporation. 10 * Scott Peterson <speterson@nvidia.com> 11 * Vijay Mali <vmali@nvidia.com> 12 * 13 * Copyright (C) 2010 Google, Inc. 14 * Iliyan Malchev <malchev@google.com> 15 * 16 * This program is free software; you can redistribute it and/or 17 * modify it under the terms of the GNU General Public License 18 * version 2 as published by the Free Software Foundation. 19 * 20 * This program is distributed in the hope that it will be useful, but 21 * WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 * General Public License for more details. 24 * 25 * You should have received a copy of the GNU General Public License 26 * along with this program; if not, write to the Free Software 27 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 28 * 02110-1301 USA 29 * 30 */ 31 32 #include <linux/module.h> 33 #include <linux/dma-mapping.h> 34 #include <linux/slab.h> 35 #include <sound/core.h> 36 #include <sound/pcm.h> 37 #include <sound/pcm_params.h> 38 #include <sound/soc.h> 39 40 #include "tegra_pcm.h" 41 42 #define DRV_NAME "tegra-pcm-audio" 43 44 static const struct snd_pcm_hardware tegra_pcm_hardware = { 45 .info = SNDRV_PCM_INFO_MMAP | 46 SNDRV_PCM_INFO_MMAP_VALID | 47 SNDRV_PCM_INFO_PAUSE | 48 SNDRV_PCM_INFO_RESUME | 49 SNDRV_PCM_INFO_INTERLEAVED, 50 .formats = SNDRV_PCM_FMTBIT_S16_LE, 51 .channels_min = 2, 52 .channels_max = 2, 53 .period_bytes_min = 1024, 54 .period_bytes_max = PAGE_SIZE, 55 .periods_min = 2, 56 .periods_max = 8, 57 .buffer_bytes_max = PAGE_SIZE * 8, 58 .fifo_size = 4, 59 }; 60 61 static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd) 62 { 63 struct snd_pcm_substream *substream = prtd->substream; 64 struct snd_dma_buffer *buf = &substream->dma_buffer; 65 struct tegra_dma_req *dma_req; 66 unsigned long addr; 67 68 dma_req = &prtd->dma_req[prtd->dma_req_idx]; 69 prtd->dma_req_idx = 1 - prtd->dma_req_idx; 70 71 addr = buf->addr + prtd->dma_pos; 72 prtd->dma_pos += dma_req->size; 73 if (prtd->dma_pos >= prtd->dma_pos_end) 74 prtd->dma_pos = 0; 75 76 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 77 dma_req->source_addr = addr; 78 else 79 dma_req->dest_addr = addr; 80 81 tegra_dma_enqueue_req(prtd->dma_chan, dma_req); 82 } 83 84 static void dma_complete_callback(struct tegra_dma_req *req) 85 { 86 struct tegra_runtime_data *prtd = (struct tegra_runtime_data *)req->dev; 87 struct snd_pcm_substream *substream = prtd->substream; 88 struct snd_pcm_runtime *runtime = substream->runtime; 89 90 spin_lock(&prtd->lock); 91 92 if (!prtd->running) { 93 spin_unlock(&prtd->lock); 94 return; 95 } 96 97 if (++prtd->period_index >= runtime->periods) 98 prtd->period_index = 0; 99 100 tegra_pcm_queue_dma(prtd); 101 102 spin_unlock(&prtd->lock); 103 104 snd_pcm_period_elapsed(substream); 105 } 106 107 static void setup_dma_tx_request(struct tegra_dma_req *req, 108 struct tegra_pcm_dma_params * dmap) 109 { 110 req->complete = dma_complete_callback; 111 req->to_memory = false; 112 req->dest_addr = dmap->addr; 113 req->dest_wrap = dmap->wrap; 114 req->source_bus_width = 32; 115 req->source_wrap = 0; 116 req->dest_bus_width = dmap->width; 117 req->req_sel = dmap->req_sel; 118 } 119 120 static void setup_dma_rx_request(struct tegra_dma_req *req, 121 struct tegra_pcm_dma_params * dmap) 122 { 123 req->complete = dma_complete_callback; 124 req->to_memory = true; 125 req->source_addr = dmap->addr; 126 req->dest_wrap = 0; 127 req->source_bus_width = dmap->width; 128 req->source_wrap = dmap->wrap; 129 req->dest_bus_width = 32; 130 req->req_sel = dmap->req_sel; 131 } 132 133 static int tegra_pcm_open(struct snd_pcm_substream *substream) 134 { 135 struct snd_pcm_runtime *runtime = substream->runtime; 136 struct tegra_runtime_data *prtd; 137 struct snd_soc_pcm_runtime *rtd = substream->private_data; 138 struct tegra_pcm_dma_params * dmap; 139 int ret = 0; 140 141 prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL); 142 if (prtd == NULL) 143 return -ENOMEM; 144 145 runtime->private_data = prtd; 146 prtd->substream = substream; 147 148 spin_lock_init(&prtd->lock); 149 150 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 151 dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 152 setup_dma_tx_request(&prtd->dma_req[0], dmap); 153 setup_dma_tx_request(&prtd->dma_req[1], dmap); 154 } else { 155 dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 156 setup_dma_rx_request(&prtd->dma_req[0], dmap); 157 setup_dma_rx_request(&prtd->dma_req[1], dmap); 158 } 159 160 prtd->dma_req[0].dev = prtd; 161 prtd->dma_req[1].dev = prtd; 162 163 prtd->dma_chan = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT); 164 if (prtd->dma_chan == NULL) { 165 ret = -ENOMEM; 166 goto err; 167 } 168 169 /* Set HW params now that initialization is complete */ 170 snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware); 171 172 /* Ensure that buffer size is a multiple of period size */ 173 ret = snd_pcm_hw_constraint_integer(runtime, 174 SNDRV_PCM_HW_PARAM_PERIODS); 175 if (ret < 0) 176 goto err; 177 178 return 0; 179 180 err: 181 if (prtd->dma_chan) { 182 tegra_dma_free_channel(prtd->dma_chan); 183 } 184 185 kfree(prtd); 186 187 return ret; 188 } 189 190 static int tegra_pcm_close(struct snd_pcm_substream *substream) 191 { 192 struct snd_pcm_runtime *runtime = substream->runtime; 193 struct tegra_runtime_data *prtd = runtime->private_data; 194 195 tegra_dma_free_channel(prtd->dma_chan); 196 197 kfree(prtd); 198 199 return 0; 200 } 201 202 static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, 203 struct snd_pcm_hw_params *params) 204 { 205 struct snd_pcm_runtime *runtime = substream->runtime; 206 struct tegra_runtime_data *prtd = runtime->private_data; 207 208 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 209 210 prtd->dma_req[0].size = params_period_bytes(params); 211 prtd->dma_req[1].size = prtd->dma_req[0].size; 212 213 return 0; 214 } 215 216 static int tegra_pcm_hw_free(struct snd_pcm_substream *substream) 217 { 218 snd_pcm_set_runtime_buffer(substream, NULL); 219 220 return 0; 221 } 222 223 static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 224 { 225 struct snd_pcm_runtime *runtime = substream->runtime; 226 struct tegra_runtime_data *prtd = runtime->private_data; 227 unsigned long flags; 228 229 switch (cmd) { 230 case SNDRV_PCM_TRIGGER_START: 231 prtd->dma_pos = 0; 232 prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size); 233 prtd->period_index = 0; 234 prtd->dma_req_idx = 0; 235 /* Fall-through */ 236 case SNDRV_PCM_TRIGGER_RESUME: 237 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 238 spin_lock_irqsave(&prtd->lock, flags); 239 prtd->running = 1; 240 spin_unlock_irqrestore(&prtd->lock, flags); 241 tegra_pcm_queue_dma(prtd); 242 tegra_pcm_queue_dma(prtd); 243 break; 244 case SNDRV_PCM_TRIGGER_STOP: 245 case SNDRV_PCM_TRIGGER_SUSPEND: 246 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 247 spin_lock_irqsave(&prtd->lock, flags); 248 prtd->running = 0; 249 spin_unlock_irqrestore(&prtd->lock, flags); 250 tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[0]); 251 tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[1]); 252 break; 253 default: 254 return -EINVAL; 255 } 256 257 return 0; 258 } 259 260 static snd_pcm_uframes_t tegra_pcm_pointer(struct snd_pcm_substream *substream) 261 { 262 struct snd_pcm_runtime *runtime = substream->runtime; 263 struct tegra_runtime_data *prtd = runtime->private_data; 264 265 return prtd->period_index * runtime->period_size; 266 } 267 268 269 static int tegra_pcm_mmap(struct snd_pcm_substream *substream, 270 struct vm_area_struct *vma) 271 { 272 struct snd_pcm_runtime *runtime = substream->runtime; 273 274 return dma_mmap_writecombine(substream->pcm->card->dev, vma, 275 runtime->dma_area, 276 runtime->dma_addr, 277 runtime->dma_bytes); 278 } 279 280 static struct snd_pcm_ops tegra_pcm_ops = { 281 .open = tegra_pcm_open, 282 .close = tegra_pcm_close, 283 .ioctl = snd_pcm_lib_ioctl, 284 .hw_params = tegra_pcm_hw_params, 285 .hw_free = tegra_pcm_hw_free, 286 .trigger = tegra_pcm_trigger, 287 .pointer = tegra_pcm_pointer, 288 .mmap = tegra_pcm_mmap, 289 }; 290 291 static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 292 { 293 struct snd_pcm_substream *substream = pcm->streams[stream].substream; 294 struct snd_dma_buffer *buf = &substream->dma_buffer; 295 size_t size = tegra_pcm_hardware.buffer_bytes_max; 296 297 buf->area = dma_alloc_writecombine(pcm->card->dev, size, 298 &buf->addr, GFP_KERNEL); 299 if (!buf->area) 300 return -ENOMEM; 301 302 buf->dev.type = SNDRV_DMA_TYPE_DEV; 303 buf->dev.dev = pcm->card->dev; 304 buf->private_data = NULL; 305 buf->bytes = size; 306 307 return 0; 308 } 309 310 static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream) 311 { 312 struct snd_pcm_substream *substream; 313 struct snd_dma_buffer *buf; 314 315 substream = pcm->streams[stream].substream; 316 if (!substream) 317 return; 318 319 buf = &substream->dma_buffer; 320 if (!buf->area) 321 return; 322 323 dma_free_writecombine(pcm->card->dev, buf->bytes, 324 buf->area, buf->addr); 325 buf->area = NULL; 326 } 327 328 static u64 tegra_dma_mask = DMA_BIT_MASK(32); 329 330 static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd) 331 { 332 struct snd_card *card = rtd->card->snd_card; 333 struct snd_soc_dai *dai = rtd->cpu_dai; 334 struct snd_pcm *pcm = rtd->pcm; 335 int ret = 0; 336 337 if (!card->dev->dma_mask) 338 card->dev->dma_mask = &tegra_dma_mask; 339 if (!card->dev->coherent_dma_mask) 340 card->dev->coherent_dma_mask = 0xffffffff; 341 342 if (dai->driver->playback.channels_min) { 343 ret = tegra_pcm_preallocate_dma_buffer(pcm, 344 SNDRV_PCM_STREAM_PLAYBACK); 345 if (ret) 346 goto err; 347 } 348 349 if (dai->driver->capture.channels_min) { 350 ret = tegra_pcm_preallocate_dma_buffer(pcm, 351 SNDRV_PCM_STREAM_CAPTURE); 352 if (ret) 353 goto err_free_play; 354 } 355 356 return 0; 357 358 err_free_play: 359 tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); 360 err: 361 return ret; 362 } 363 364 static void tegra_pcm_free(struct snd_pcm *pcm) 365 { 366 tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); 367 tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); 368 } 369 370 static struct snd_soc_platform_driver tegra_pcm_platform = { 371 .ops = &tegra_pcm_ops, 372 .pcm_new = tegra_pcm_new, 373 .pcm_free = tegra_pcm_free, 374 }; 375 376 static int __devinit tegra_pcm_platform_probe(struct platform_device *pdev) 377 { 378 return snd_soc_register_platform(&pdev->dev, &tegra_pcm_platform); 379 } 380 381 static int __devexit tegra_pcm_platform_remove(struct platform_device *pdev) 382 { 383 snd_soc_unregister_platform(&pdev->dev); 384 return 0; 385 } 386 387 static struct platform_driver tegra_pcm_driver = { 388 .driver = { 389 .name = DRV_NAME, 390 .owner = THIS_MODULE, 391 }, 392 .probe = tegra_pcm_platform_probe, 393 .remove = __devexit_p(tegra_pcm_platform_remove), 394 }; 395 396 static int __init snd_tegra_pcm_init(void) 397 { 398 return platform_driver_register(&tegra_pcm_driver); 399 } 400 module_init(snd_tegra_pcm_init); 401 402 static void __exit snd_tegra_pcm_exit(void) 403 { 404 platform_driver_unregister(&tegra_pcm_driver); 405 } 406 module_exit(snd_tegra_pcm_exit); 407 408 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); 409 MODULE_DESCRIPTION("Tegra PCM ASoC driver"); 410 MODULE_LICENSE("GPL"); 411 MODULE_ALIAS("platform:" DRV_NAME); 412