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