1 /* 2 * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 and 6 * only version 2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * lpass-platform.c -- ALSA SoC platform driver for QTi LPASS 14 */ 15 16 #include <linux/dma-mapping.h> 17 #include <linux/export.h> 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <linux/platform_device.h> 21 #include <sound/pcm_params.h> 22 #include <linux/regmap.h> 23 #include <sound/soc.h> 24 #include "lpass-lpaif-reg.h" 25 #include "lpass.h" 26 27 struct lpass_pcm_data { 28 int dma_ch; 29 int i2s_port; 30 }; 31 32 #define LPASS_PLATFORM_BUFFER_SIZE (16 * 1024) 33 #define LPASS_PLATFORM_PERIODS 2 34 35 static struct snd_pcm_hardware lpass_platform_pcm_hardware = { 36 .info = SNDRV_PCM_INFO_MMAP | 37 SNDRV_PCM_INFO_MMAP_VALID | 38 SNDRV_PCM_INFO_INTERLEAVED | 39 SNDRV_PCM_INFO_PAUSE | 40 SNDRV_PCM_INFO_RESUME, 41 .formats = SNDRV_PCM_FMTBIT_S16 | 42 SNDRV_PCM_FMTBIT_S24 | 43 SNDRV_PCM_FMTBIT_S32, 44 .rates = SNDRV_PCM_RATE_8000_192000, 45 .rate_min = 8000, 46 .rate_max = 192000, 47 .channels_min = 1, 48 .channels_max = 8, 49 .buffer_bytes_max = LPASS_PLATFORM_BUFFER_SIZE, 50 .period_bytes_max = LPASS_PLATFORM_BUFFER_SIZE / 51 LPASS_PLATFORM_PERIODS, 52 .period_bytes_min = LPASS_PLATFORM_BUFFER_SIZE / 53 LPASS_PLATFORM_PERIODS, 54 .periods_min = LPASS_PLATFORM_PERIODS, 55 .periods_max = LPASS_PLATFORM_PERIODS, 56 .fifo_size = 0, 57 }; 58 59 static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) 60 { 61 struct snd_pcm_runtime *runtime = substream->runtime; 62 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 63 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; 64 struct lpass_data *drvdata = 65 snd_soc_platform_get_drvdata(soc_runtime->platform); 66 struct lpass_variant *v = drvdata->variant; 67 int ret, dma_ch, dir = substream->stream; 68 struct lpass_pcm_data *data; 69 70 data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL); 71 if (!data) 72 return -ENOMEM; 73 74 data->i2s_port = cpu_dai->driver->id; 75 runtime->private_data = data; 76 77 dma_ch = 0; 78 if (v->alloc_dma_channel) 79 dma_ch = v->alloc_dma_channel(drvdata, dir); 80 else 81 dma_ch = 0; 82 83 if (dma_ch < 0) 84 return dma_ch; 85 86 drvdata->substream[dma_ch] = substream; 87 88 ret = regmap_write(drvdata->lpaif_map, 89 LPAIF_DMACTL_REG(v, dma_ch, dir), 0); 90 if (ret) { 91 dev_err(soc_runtime->dev, 92 "error writing to rdmactl reg: %d\n", ret); 93 return ret; 94 } 95 96 data->dma_ch = dma_ch; 97 98 snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware); 99 100 runtime->dma_bytes = lpass_platform_pcm_hardware.buffer_bytes_max; 101 102 ret = snd_pcm_hw_constraint_integer(runtime, 103 SNDRV_PCM_HW_PARAM_PERIODS); 104 if (ret < 0) { 105 dev_err(soc_runtime->dev, "setting constraints failed: %d\n", 106 ret); 107 return -EINVAL; 108 } 109 110 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 111 112 return 0; 113 } 114 115 static int lpass_platform_pcmops_close(struct snd_pcm_substream *substream) 116 { 117 struct snd_pcm_runtime *runtime = substream->runtime; 118 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 119 struct lpass_data *drvdata = 120 snd_soc_platform_get_drvdata(soc_runtime->platform); 121 struct lpass_variant *v = drvdata->variant; 122 struct lpass_pcm_data *data; 123 124 data = runtime->private_data; 125 v = drvdata->variant; 126 drvdata->substream[data->dma_ch] = NULL; 127 if (v->free_dma_channel) 128 v->free_dma_channel(drvdata, data->dma_ch); 129 130 return 0; 131 } 132 133 static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, 134 struct snd_pcm_hw_params *params) 135 { 136 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 137 struct lpass_data *drvdata = 138 snd_soc_platform_get_drvdata(soc_runtime->platform); 139 struct snd_pcm_runtime *rt = substream->runtime; 140 struct lpass_pcm_data *pcm_data = rt->private_data; 141 struct lpass_variant *v = drvdata->variant; 142 snd_pcm_format_t format = params_format(params); 143 unsigned int channels = params_channels(params); 144 unsigned int regval; 145 int ch, dir = substream->stream; 146 int bitwidth; 147 int ret, dma_port = pcm_data->i2s_port + v->dmactl_audif_start; 148 149 ch = pcm_data->dma_ch; 150 151 bitwidth = snd_pcm_format_width(format); 152 if (bitwidth < 0) { 153 dev_err(soc_runtime->dev, "invalid bit width given: %d\n", 154 bitwidth); 155 return bitwidth; 156 } 157 158 regval = LPAIF_DMACTL_BURSTEN_INCR4 | 159 LPAIF_DMACTL_AUDINTF(dma_port) | 160 LPAIF_DMACTL_FIFOWM_8; 161 162 switch (bitwidth) { 163 case 16: 164 switch (channels) { 165 case 1: 166 case 2: 167 regval |= LPAIF_DMACTL_WPSCNT_ONE; 168 break; 169 case 4: 170 regval |= LPAIF_DMACTL_WPSCNT_TWO; 171 break; 172 case 6: 173 regval |= LPAIF_DMACTL_WPSCNT_THREE; 174 break; 175 case 8: 176 regval |= LPAIF_DMACTL_WPSCNT_FOUR; 177 break; 178 default: 179 dev_err(soc_runtime->dev, 180 "invalid PCM config given: bw=%d, ch=%u\n", 181 bitwidth, channels); 182 return -EINVAL; 183 } 184 break; 185 case 24: 186 case 32: 187 switch (channels) { 188 case 1: 189 regval |= LPAIF_DMACTL_WPSCNT_ONE; 190 break; 191 case 2: 192 regval |= LPAIF_DMACTL_WPSCNT_TWO; 193 break; 194 case 4: 195 regval |= LPAIF_DMACTL_WPSCNT_FOUR; 196 break; 197 case 6: 198 regval |= LPAIF_DMACTL_WPSCNT_SIX; 199 break; 200 case 8: 201 regval |= LPAIF_DMACTL_WPSCNT_EIGHT; 202 break; 203 default: 204 dev_err(soc_runtime->dev, 205 "invalid PCM config given: bw=%d, ch=%u\n", 206 bitwidth, channels); 207 return -EINVAL; 208 } 209 break; 210 default: 211 dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n", 212 bitwidth, channels); 213 return -EINVAL; 214 } 215 216 ret = regmap_write(drvdata->lpaif_map, 217 LPAIF_DMACTL_REG(v, ch, dir), regval); 218 if (ret) { 219 dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", 220 ret); 221 return ret; 222 } 223 224 return 0; 225 } 226 227 static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) 228 { 229 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 230 struct lpass_data *drvdata = 231 snd_soc_platform_get_drvdata(soc_runtime->platform); 232 struct snd_pcm_runtime *rt = substream->runtime; 233 struct lpass_pcm_data *pcm_data = rt->private_data; 234 struct lpass_variant *v = drvdata->variant; 235 unsigned int reg; 236 int ret; 237 238 reg = LPAIF_DMACTL_REG(v, pcm_data->dma_ch, substream->stream); 239 ret = regmap_write(drvdata->lpaif_map, reg, 0); 240 if (ret) 241 dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", 242 ret); 243 244 return ret; 245 } 246 247 static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) 248 { 249 struct snd_pcm_runtime *runtime = substream->runtime; 250 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 251 struct lpass_data *drvdata = 252 snd_soc_platform_get_drvdata(soc_runtime->platform); 253 struct snd_pcm_runtime *rt = substream->runtime; 254 struct lpass_pcm_data *pcm_data = rt->private_data; 255 struct lpass_variant *v = drvdata->variant; 256 int ret, ch, dir = substream->stream; 257 258 ch = pcm_data->dma_ch; 259 260 ret = regmap_write(drvdata->lpaif_map, 261 LPAIF_DMABASE_REG(v, ch, dir), 262 runtime->dma_addr); 263 if (ret) { 264 dev_err(soc_runtime->dev, "error writing to rdmabase reg: %d\n", 265 ret); 266 return ret; 267 } 268 269 ret = regmap_write(drvdata->lpaif_map, 270 LPAIF_DMABUFF_REG(v, ch, dir), 271 (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1); 272 if (ret) { 273 dev_err(soc_runtime->dev, "error writing to rdmabuff reg: %d\n", 274 ret); 275 return ret; 276 } 277 278 ret = regmap_write(drvdata->lpaif_map, 279 LPAIF_DMAPER_REG(v, ch, dir), 280 (snd_pcm_lib_period_bytes(substream) >> 2) - 1); 281 if (ret) { 282 dev_err(soc_runtime->dev, "error writing to rdmaper reg: %d\n", 283 ret); 284 return ret; 285 } 286 287 ret = regmap_update_bits(drvdata->lpaif_map, 288 LPAIF_DMACTL_REG(v, ch, dir), 289 LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON); 290 if (ret) { 291 dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", 292 ret); 293 return ret; 294 } 295 296 return 0; 297 } 298 299 static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, 300 int cmd) 301 { 302 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 303 struct lpass_data *drvdata = 304 snd_soc_platform_get_drvdata(soc_runtime->platform); 305 struct snd_pcm_runtime *rt = substream->runtime; 306 struct lpass_pcm_data *pcm_data = rt->private_data; 307 struct lpass_variant *v = drvdata->variant; 308 int ret, ch, dir = substream->stream; 309 310 ch = pcm_data->dma_ch; 311 312 switch (cmd) { 313 case SNDRV_PCM_TRIGGER_START: 314 case SNDRV_PCM_TRIGGER_RESUME: 315 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 316 /* clear status before enabling interrupts */ 317 ret = regmap_write(drvdata->lpaif_map, 318 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), 319 LPAIF_IRQ_ALL(ch)); 320 if (ret) { 321 dev_err(soc_runtime->dev, 322 "error writing to irqclear reg: %d\n", ret); 323 return ret; 324 } 325 326 ret = regmap_update_bits(drvdata->lpaif_map, 327 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 328 LPAIF_IRQ_ALL(ch), 329 LPAIF_IRQ_ALL(ch)); 330 if (ret) { 331 dev_err(soc_runtime->dev, 332 "error writing to irqen reg: %d\n", ret); 333 return ret; 334 } 335 336 ret = regmap_update_bits(drvdata->lpaif_map, 337 LPAIF_DMACTL_REG(v, ch, dir), 338 LPAIF_DMACTL_ENABLE_MASK, 339 LPAIF_DMACTL_ENABLE_ON); 340 if (ret) { 341 dev_err(soc_runtime->dev, 342 "error writing to rdmactl reg: %d\n", ret); 343 return ret; 344 } 345 break; 346 case SNDRV_PCM_TRIGGER_STOP: 347 case SNDRV_PCM_TRIGGER_SUSPEND: 348 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 349 ret = regmap_update_bits(drvdata->lpaif_map, 350 LPAIF_DMACTL_REG(v, ch, dir), 351 LPAIF_DMACTL_ENABLE_MASK, 352 LPAIF_DMACTL_ENABLE_OFF); 353 if (ret) { 354 dev_err(soc_runtime->dev, 355 "error writing to rdmactl reg: %d\n", ret); 356 return ret; 357 } 358 359 ret = regmap_update_bits(drvdata->lpaif_map, 360 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 361 LPAIF_IRQ_ALL(ch), 0); 362 if (ret) { 363 dev_err(soc_runtime->dev, 364 "error writing to irqen reg: %d\n", ret); 365 return ret; 366 } 367 break; 368 } 369 370 return 0; 371 } 372 373 static snd_pcm_uframes_t lpass_platform_pcmops_pointer( 374 struct snd_pcm_substream *substream) 375 { 376 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 377 struct lpass_data *drvdata = 378 snd_soc_platform_get_drvdata(soc_runtime->platform); 379 struct snd_pcm_runtime *rt = substream->runtime; 380 struct lpass_pcm_data *pcm_data = rt->private_data; 381 struct lpass_variant *v = drvdata->variant; 382 unsigned int base_addr, curr_addr; 383 int ret, ch, dir = substream->stream; 384 385 ch = pcm_data->dma_ch; 386 387 ret = regmap_read(drvdata->lpaif_map, 388 LPAIF_DMABASE_REG(v, ch, dir), &base_addr); 389 if (ret) { 390 dev_err(soc_runtime->dev, 391 "error reading from rdmabase reg: %d\n", ret); 392 return ret; 393 } 394 395 ret = regmap_read(drvdata->lpaif_map, 396 LPAIF_DMACURR_REG(v, ch, dir), &curr_addr); 397 if (ret) { 398 dev_err(soc_runtime->dev, 399 "error reading from rdmacurr reg: %d\n", ret); 400 return ret; 401 } 402 403 return bytes_to_frames(substream->runtime, curr_addr - base_addr); 404 } 405 406 static int lpass_platform_pcmops_mmap(struct snd_pcm_substream *substream, 407 struct vm_area_struct *vma) 408 { 409 struct snd_pcm_runtime *runtime = substream->runtime; 410 411 return dma_mmap_coherent(substream->pcm->card->dev, vma, 412 runtime->dma_area, runtime->dma_addr, 413 runtime->dma_bytes); 414 } 415 416 static const struct snd_pcm_ops lpass_platform_pcm_ops = { 417 .open = lpass_platform_pcmops_open, 418 .close = lpass_platform_pcmops_close, 419 .ioctl = snd_pcm_lib_ioctl, 420 .hw_params = lpass_platform_pcmops_hw_params, 421 .hw_free = lpass_platform_pcmops_hw_free, 422 .prepare = lpass_platform_pcmops_prepare, 423 .trigger = lpass_platform_pcmops_trigger, 424 .pointer = lpass_platform_pcmops_pointer, 425 .mmap = lpass_platform_pcmops_mmap, 426 }; 427 428 static irqreturn_t lpass_dma_interrupt_handler( 429 struct snd_pcm_substream *substream, 430 struct lpass_data *drvdata, 431 int chan, u32 interrupts) 432 { 433 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 434 struct lpass_variant *v = drvdata->variant; 435 irqreturn_t ret = IRQ_NONE; 436 int rv; 437 438 if (interrupts & LPAIF_IRQ_PER(chan)) { 439 rv = regmap_write(drvdata->lpaif_map, 440 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), 441 LPAIF_IRQ_PER(chan)); 442 if (rv) { 443 dev_err(soc_runtime->dev, 444 "error writing to irqclear reg: %d\n", rv); 445 return IRQ_NONE; 446 } 447 snd_pcm_period_elapsed(substream); 448 ret = IRQ_HANDLED; 449 } 450 451 if (interrupts & LPAIF_IRQ_XRUN(chan)) { 452 rv = regmap_write(drvdata->lpaif_map, 453 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), 454 LPAIF_IRQ_XRUN(chan)); 455 if (rv) { 456 dev_err(soc_runtime->dev, 457 "error writing to irqclear reg: %d\n", rv); 458 return IRQ_NONE; 459 } 460 dev_warn(soc_runtime->dev, "xrun warning\n"); 461 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); 462 ret = IRQ_HANDLED; 463 } 464 465 if (interrupts & LPAIF_IRQ_ERR(chan)) { 466 rv = regmap_write(drvdata->lpaif_map, 467 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), 468 LPAIF_IRQ_ERR(chan)); 469 if (rv) { 470 dev_err(soc_runtime->dev, 471 "error writing to irqclear reg: %d\n", rv); 472 return IRQ_NONE; 473 } 474 dev_err(soc_runtime->dev, "bus access error\n"); 475 snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); 476 ret = IRQ_HANDLED; 477 } 478 479 return ret; 480 } 481 482 static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) 483 { 484 struct lpass_data *drvdata = data; 485 struct lpass_variant *v = drvdata->variant; 486 unsigned int irqs; 487 int rv, chan; 488 489 rv = regmap_read(drvdata->lpaif_map, 490 LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs); 491 if (rv) { 492 pr_err("error reading from irqstat reg: %d\n", rv); 493 return IRQ_NONE; 494 } 495 496 /* Handle per channel interrupts */ 497 for (chan = 0; chan < LPASS_MAX_DMA_CHANNELS; chan++) { 498 if (irqs & LPAIF_IRQ_ALL(chan) && drvdata->substream[chan]) { 499 rv = lpass_dma_interrupt_handler( 500 drvdata->substream[chan], 501 drvdata, chan, irqs); 502 if (rv != IRQ_HANDLED) 503 return rv; 504 } 505 } 506 507 return IRQ_HANDLED; 508 } 509 510 static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) 511 { 512 struct snd_pcm *pcm = soc_runtime->pcm; 513 struct snd_pcm_substream *psubstream, *csubstream; 514 int ret = -EINVAL; 515 size_t size = lpass_platform_pcm_hardware.buffer_bytes_max; 516 517 psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 518 if (psubstream) { 519 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, 520 soc_runtime->platform->dev, 521 size, &psubstream->dma_buffer); 522 if (ret) { 523 dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n"); 524 return ret; 525 } 526 } 527 528 csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; 529 if (csubstream) { 530 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, 531 soc_runtime->platform->dev, 532 size, &csubstream->dma_buffer); 533 if (ret) { 534 dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n"); 535 if (psubstream) 536 snd_dma_free_pages(&psubstream->dma_buffer); 537 return ret; 538 } 539 540 } 541 542 return 0; 543 } 544 545 static void lpass_platform_pcm_free(struct snd_pcm *pcm) 546 { 547 struct snd_pcm_substream *substream; 548 int i; 549 550 for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) { 551 substream = pcm->streams[i].substream; 552 if (substream) { 553 snd_dma_free_pages(&substream->dma_buffer); 554 substream->dma_buffer.area = NULL; 555 substream->dma_buffer.addr = 0; 556 } 557 } 558 } 559 560 static struct snd_soc_platform_driver lpass_platform_driver = { 561 .pcm_new = lpass_platform_pcm_new, 562 .pcm_free = lpass_platform_pcm_free, 563 .ops = &lpass_platform_pcm_ops, 564 }; 565 566 int asoc_qcom_lpass_platform_register(struct platform_device *pdev) 567 { 568 struct lpass_data *drvdata = platform_get_drvdata(pdev); 569 struct lpass_variant *v = drvdata->variant; 570 int ret; 571 572 drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); 573 if (drvdata->lpaif_irq < 0) { 574 dev_err(&pdev->dev, "error getting irq handle: %d\n", 575 drvdata->lpaif_irq); 576 return -ENODEV; 577 } 578 579 /* ensure audio hardware is disabled */ 580 ret = regmap_write(drvdata->lpaif_map, 581 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0); 582 if (ret) { 583 dev_err(&pdev->dev, "error writing to irqen reg: %d\n", ret); 584 return ret; 585 } 586 587 ret = devm_request_irq(&pdev->dev, drvdata->lpaif_irq, 588 lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING, 589 "lpass-irq-lpaif", drvdata); 590 if (ret) { 591 dev_err(&pdev->dev, "irq request failed: %d\n", ret); 592 return ret; 593 } 594 595 596 return devm_snd_soc_register_platform(&pdev->dev, 597 &lpass_platform_driver); 598 } 599 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register); 600 601 MODULE_DESCRIPTION("QTi LPASS Platform Driver"); 602 MODULE_LICENSE("GPL v2"); 603