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 #define DRV_NAME "lpass-platform" 28 29 struct lpass_pcm_data { 30 int dma_ch; 31 int i2s_port; 32 }; 33 34 #define LPASS_PLATFORM_BUFFER_SIZE (16 * 1024) 35 #define LPASS_PLATFORM_PERIODS 2 36 37 static const struct snd_pcm_hardware lpass_platform_pcm_hardware = { 38 .info = SNDRV_PCM_INFO_MMAP | 39 SNDRV_PCM_INFO_MMAP_VALID | 40 SNDRV_PCM_INFO_INTERLEAVED | 41 SNDRV_PCM_INFO_PAUSE | 42 SNDRV_PCM_INFO_RESUME, 43 .formats = SNDRV_PCM_FMTBIT_S16 | 44 SNDRV_PCM_FMTBIT_S24 | 45 SNDRV_PCM_FMTBIT_S32, 46 .rates = SNDRV_PCM_RATE_8000_192000, 47 .rate_min = 8000, 48 .rate_max = 192000, 49 .channels_min = 1, 50 .channels_max = 8, 51 .buffer_bytes_max = LPASS_PLATFORM_BUFFER_SIZE, 52 .period_bytes_max = LPASS_PLATFORM_BUFFER_SIZE / 53 LPASS_PLATFORM_PERIODS, 54 .period_bytes_min = LPASS_PLATFORM_BUFFER_SIZE / 55 LPASS_PLATFORM_PERIODS, 56 .periods_min = LPASS_PLATFORM_PERIODS, 57 .periods_max = LPASS_PLATFORM_PERIODS, 58 .fifo_size = 0, 59 }; 60 61 static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) 62 { 63 struct snd_pcm_runtime *runtime = substream->runtime; 64 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 65 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; 66 struct snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME); 67 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 68 struct lpass_variant *v = drvdata->variant; 69 int ret, dma_ch, dir = substream->stream; 70 struct lpass_pcm_data *data; 71 72 data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL); 73 if (!data) 74 return -ENOMEM; 75 76 data->i2s_port = cpu_dai->driver->id; 77 runtime->private_data = data; 78 79 if (v->alloc_dma_channel) 80 dma_ch = v->alloc_dma_channel(drvdata, dir); 81 else 82 dma_ch = 0; 83 84 if (dma_ch < 0) 85 return dma_ch; 86 87 drvdata->substream[dma_ch] = substream; 88 89 ret = regmap_write(drvdata->lpaif_map, 90 LPAIF_DMACTL_REG(v, dma_ch, dir), 0); 91 if (ret) { 92 dev_err(soc_runtime->dev, 93 "error writing to rdmactl reg: %d\n", ret); 94 return ret; 95 } 96 97 data->dma_ch = dma_ch; 98 99 snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware); 100 101 runtime->dma_bytes = lpass_platform_pcm_hardware.buffer_bytes_max; 102 103 ret = snd_pcm_hw_constraint_integer(runtime, 104 SNDRV_PCM_HW_PARAM_PERIODS); 105 if (ret < 0) { 106 dev_err(soc_runtime->dev, "setting constraints failed: %d\n", 107 ret); 108 return -EINVAL; 109 } 110 111 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 112 113 return 0; 114 } 115 116 static int lpass_platform_pcmops_close(struct snd_pcm_substream *substream) 117 { 118 struct snd_pcm_runtime *runtime = substream->runtime; 119 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 120 struct snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME); 121 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 122 struct lpass_variant *v = drvdata->variant; 123 struct lpass_pcm_data *data; 124 125 data = runtime->private_data; 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 snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME); 138 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 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 snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME); 231 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 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 snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME); 252 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 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 snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME); 304 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 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 snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME); 378 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 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 struct snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME); 515 int ret = -EINVAL; 516 size_t size = lpass_platform_pcm_hardware.buffer_bytes_max; 517 518 psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 519 if (psubstream) { 520 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, 521 component->dev, 522 size, &psubstream->dma_buffer); 523 if (ret) { 524 dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n"); 525 return ret; 526 } 527 } 528 529 csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; 530 if (csubstream) { 531 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, 532 component->dev, 533 size, &csubstream->dma_buffer); 534 if (ret) { 535 dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n"); 536 if (psubstream) 537 snd_dma_free_pages(&psubstream->dma_buffer); 538 return ret; 539 } 540 541 } 542 543 return 0; 544 } 545 546 static void lpass_platform_pcm_free(struct snd_pcm *pcm) 547 { 548 struct snd_pcm_substream *substream; 549 int i; 550 551 for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) { 552 substream = pcm->streams[i].substream; 553 if (substream) { 554 snd_dma_free_pages(&substream->dma_buffer); 555 substream->dma_buffer.area = NULL; 556 substream->dma_buffer.addr = 0; 557 } 558 } 559 } 560 561 static const struct snd_soc_component_driver lpass_component_driver = { 562 .name = DRV_NAME, 563 .pcm_new = lpass_platform_pcm_new, 564 .pcm_free = lpass_platform_pcm_free, 565 .ops = &lpass_platform_pcm_ops, 566 }; 567 568 int asoc_qcom_lpass_platform_register(struct platform_device *pdev) 569 { 570 struct lpass_data *drvdata = platform_get_drvdata(pdev); 571 struct lpass_variant *v = drvdata->variant; 572 int ret; 573 574 drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); 575 if (drvdata->lpaif_irq < 0) { 576 dev_err(&pdev->dev, "error getting irq handle: %d\n", 577 drvdata->lpaif_irq); 578 return -ENODEV; 579 } 580 581 /* ensure audio hardware is disabled */ 582 ret = regmap_write(drvdata->lpaif_map, 583 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0); 584 if (ret) { 585 dev_err(&pdev->dev, "error writing to irqen reg: %d\n", ret); 586 return ret; 587 } 588 589 ret = devm_request_irq(&pdev->dev, drvdata->lpaif_irq, 590 lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING, 591 "lpass-irq-lpaif", drvdata); 592 if (ret) { 593 dev_err(&pdev->dev, "irq request failed: %d\n", ret); 594 return ret; 595 } 596 597 598 return devm_snd_soc_register_component(&pdev->dev, 599 &lpass_component_driver, NULL, 0); 600 } 601 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register); 602 603 MODULE_DESCRIPTION("QTi LPASS Platform Driver"); 604 MODULE_LICENSE("GPL v2"); 605