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 "%s() error writing to rdmactl reg: %d\n", 93 __func__, 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, "%s() setting constraints failed: %d\n", 107 __func__, 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 lpass_data *drvdata = 121 snd_soc_platform_get_drvdata(soc_runtime->platform); 122 struct lpass_variant *v = drvdata->variant; 123 struct lpass_pcm_data *data; 124 125 data = runtime->private_data; 126 v = drvdata->variant; 127 drvdata->substream[data->dma_ch] = NULL; 128 if (v->free_dma_channel) 129 v->free_dma_channel(drvdata, data->dma_ch); 130 131 return 0; 132 } 133 134 static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, 135 struct snd_pcm_hw_params *params) 136 { 137 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 138 struct lpass_data *drvdata = 139 snd_soc_platform_get_drvdata(soc_runtime->platform); 140 struct snd_pcm_runtime *rt = substream->runtime; 141 struct lpass_pcm_data *pcm_data = rt->private_data; 142 struct lpass_variant *v = drvdata->variant; 143 snd_pcm_format_t format = params_format(params); 144 unsigned int channels = params_channels(params); 145 unsigned int regval; 146 int ch, dir = substream->stream; 147 int bitwidth; 148 int ret, dma_port = pcm_data->i2s_port + v->dmactl_audif_start; 149 150 ch = pcm_data->dma_ch; 151 152 bitwidth = snd_pcm_format_width(format); 153 if (bitwidth < 0) { 154 dev_err(soc_runtime->dev, "%s() invalid bit width given: %d\n", 155 __func__, bitwidth); 156 return bitwidth; 157 } 158 159 regval = LPAIF_DMACTL_BURSTEN_INCR4 | 160 LPAIF_DMACTL_AUDINTF(dma_port) | 161 LPAIF_DMACTL_FIFOWM_8; 162 163 switch (bitwidth) { 164 case 16: 165 switch (channels) { 166 case 1: 167 case 2: 168 regval |= LPAIF_DMACTL_WPSCNT_ONE; 169 break; 170 case 4: 171 regval |= LPAIF_DMACTL_WPSCNT_TWO; 172 break; 173 case 6: 174 regval |= LPAIF_DMACTL_WPSCNT_THREE; 175 break; 176 case 8: 177 regval |= LPAIF_DMACTL_WPSCNT_FOUR; 178 break; 179 default: 180 dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n", 181 __func__, 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, "%s() invalid PCM config given: bw=%d, ch=%u\n", 205 __func__, bitwidth, channels); 206 return -EINVAL; 207 } 208 break; 209 default: 210 dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n", 211 __func__, bitwidth, channels); 212 return -EINVAL; 213 } 214 215 ret = regmap_write(drvdata->lpaif_map, 216 LPAIF_DMACTL_REG(v, ch, dir), regval); 217 if (ret) { 218 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 219 __func__, ret); 220 return ret; 221 } 222 223 return 0; 224 } 225 226 static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) 227 { 228 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 229 struct lpass_data *drvdata = 230 snd_soc_platform_get_drvdata(soc_runtime->platform); 231 struct snd_pcm_runtime *rt = substream->runtime; 232 struct lpass_pcm_data *pcm_data = rt->private_data; 233 struct lpass_variant *v = drvdata->variant; 234 unsigned int reg; 235 int ret; 236 237 reg = LPAIF_DMACTL_REG(v, pcm_data->dma_ch, substream->stream); 238 ret = regmap_write(drvdata->lpaif_map, reg, 0); 239 if (ret) 240 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 241 __func__, ret); 242 243 return ret; 244 } 245 246 static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) 247 { 248 struct snd_pcm_runtime *runtime = substream->runtime; 249 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 250 struct lpass_data *drvdata = 251 snd_soc_platform_get_drvdata(soc_runtime->platform); 252 struct snd_pcm_runtime *rt = substream->runtime; 253 struct lpass_pcm_data *pcm_data = rt->private_data; 254 struct lpass_variant *v = drvdata->variant; 255 int ret, ch, dir = substream->stream; 256 257 ch = pcm_data->dma_ch; 258 259 ret = regmap_write(drvdata->lpaif_map, 260 LPAIF_DMABASE_REG(v, ch, dir), 261 runtime->dma_addr); 262 if (ret) { 263 dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n", 264 __func__, ret); 265 return ret; 266 } 267 268 ret = regmap_write(drvdata->lpaif_map, 269 LPAIF_DMABUFF_REG(v, ch, dir), 270 (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1); 271 if (ret) { 272 dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n", 273 __func__, ret); 274 return ret; 275 } 276 277 ret = regmap_write(drvdata->lpaif_map, 278 LPAIF_DMAPER_REG(v, ch, dir), 279 (snd_pcm_lib_period_bytes(substream) >> 2) - 1); 280 if (ret) { 281 dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n", 282 __func__, ret); 283 return ret; 284 } 285 286 ret = regmap_update_bits(drvdata->lpaif_map, 287 LPAIF_DMACTL_REG(v, ch, dir), 288 LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON); 289 if (ret) { 290 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 291 __func__, ret); 292 return ret; 293 } 294 295 return 0; 296 } 297 298 static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, 299 int cmd) 300 { 301 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 302 struct lpass_data *drvdata = 303 snd_soc_platform_get_drvdata(soc_runtime->platform); 304 struct snd_pcm_runtime *rt = substream->runtime; 305 struct lpass_pcm_data *pcm_data = rt->private_data; 306 struct lpass_variant *v = drvdata->variant; 307 int ret, ch, dir = substream->stream; 308 309 ch = pcm_data->dma_ch; 310 311 switch (cmd) { 312 case SNDRV_PCM_TRIGGER_START: 313 case SNDRV_PCM_TRIGGER_RESUME: 314 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 315 /* clear status before enabling interrupts */ 316 ret = regmap_write(drvdata->lpaif_map, 317 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), 318 LPAIF_IRQ_ALL(ch)); 319 if (ret) { 320 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", 321 __func__, ret); 322 return ret; 323 } 324 325 ret = regmap_update_bits(drvdata->lpaif_map, 326 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 327 LPAIF_IRQ_ALL(ch), 328 LPAIF_IRQ_ALL(ch)); 329 if (ret) { 330 dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", 331 __func__, ret); 332 return ret; 333 } 334 335 ret = regmap_update_bits(drvdata->lpaif_map, 336 LPAIF_DMACTL_REG(v, ch, dir), 337 LPAIF_DMACTL_ENABLE_MASK, 338 LPAIF_DMACTL_ENABLE_ON); 339 if (ret) { 340 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 341 __func__, ret); 342 return ret; 343 } 344 break; 345 case SNDRV_PCM_TRIGGER_STOP: 346 case SNDRV_PCM_TRIGGER_SUSPEND: 347 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 348 ret = regmap_update_bits(drvdata->lpaif_map, 349 LPAIF_DMACTL_REG(v, ch, dir), 350 LPAIF_DMACTL_ENABLE_MASK, 351 LPAIF_DMACTL_ENABLE_OFF); 352 if (ret) { 353 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 354 __func__, ret); 355 return ret; 356 } 357 358 ret = regmap_update_bits(drvdata->lpaif_map, 359 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 360 LPAIF_IRQ_ALL(ch), 0); 361 if (ret) { 362 dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", 363 __func__, ret); 364 return ret; 365 } 366 break; 367 } 368 369 return 0; 370 } 371 372 static snd_pcm_uframes_t lpass_platform_pcmops_pointer( 373 struct snd_pcm_substream *substream) 374 { 375 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 376 struct lpass_data *drvdata = 377 snd_soc_platform_get_drvdata(soc_runtime->platform); 378 struct snd_pcm_runtime *rt = substream->runtime; 379 struct lpass_pcm_data *pcm_data = rt->private_data; 380 struct lpass_variant *v = drvdata->variant; 381 unsigned int base_addr, curr_addr; 382 int ret, ch, dir = substream->stream; 383 384 ch = pcm_data->dma_ch; 385 386 ret = regmap_read(drvdata->lpaif_map, 387 LPAIF_DMABASE_REG(v, ch, dir), &base_addr); 388 if (ret) { 389 dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n", 390 __func__, ret); 391 return ret; 392 } 393 394 ret = regmap_read(drvdata->lpaif_map, 395 LPAIF_DMACURR_REG(v, ch, dir), &curr_addr); 396 if (ret) { 397 dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n", 398 __func__, ret); 399 return ret; 400 } 401 402 return bytes_to_frames(substream->runtime, curr_addr - base_addr); 403 } 404 405 static int lpass_platform_pcmops_mmap(struct snd_pcm_substream *substream, 406 struct vm_area_struct *vma) 407 { 408 struct snd_pcm_runtime *runtime = substream->runtime; 409 410 return dma_mmap_coherent(substream->pcm->card->dev, vma, 411 runtime->dma_area, runtime->dma_addr, 412 runtime->dma_bytes); 413 } 414 415 static const struct snd_pcm_ops lpass_platform_pcm_ops = { 416 .open = lpass_platform_pcmops_open, 417 .close = lpass_platform_pcmops_close, 418 .ioctl = snd_pcm_lib_ioctl, 419 .hw_params = lpass_platform_pcmops_hw_params, 420 .hw_free = lpass_platform_pcmops_hw_free, 421 .prepare = lpass_platform_pcmops_prepare, 422 .trigger = lpass_platform_pcmops_trigger, 423 .pointer = lpass_platform_pcmops_pointer, 424 .mmap = lpass_platform_pcmops_mmap, 425 }; 426 427 static irqreturn_t lpass_dma_interrupt_handler( 428 struct snd_pcm_substream *substream, 429 struct lpass_data *drvdata, 430 int chan, u32 interrupts) 431 { 432 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 433 struct lpass_variant *v = drvdata->variant; 434 irqreturn_t ret = IRQ_NONE; 435 int rv; 436 437 if (interrupts & LPAIF_IRQ_PER(chan)) { 438 rv = regmap_write(drvdata->lpaif_map, 439 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), 440 LPAIF_IRQ_PER(chan)); 441 if (rv) { 442 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", 443 __func__, rv); 444 return IRQ_NONE; 445 } 446 snd_pcm_period_elapsed(substream); 447 ret = IRQ_HANDLED; 448 } 449 450 if (interrupts & LPAIF_IRQ_XRUN(chan)) { 451 rv = regmap_write(drvdata->lpaif_map, 452 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), 453 LPAIF_IRQ_XRUN(chan)); 454 if (rv) { 455 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", 456 __func__, rv); 457 return IRQ_NONE; 458 } 459 dev_warn(soc_runtime->dev, "%s() xrun warning\n", __func__); 460 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); 461 ret = IRQ_HANDLED; 462 } 463 464 if (interrupts & LPAIF_IRQ_ERR(chan)) { 465 rv = regmap_write(drvdata->lpaif_map, 466 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), 467 LPAIF_IRQ_ERR(chan)); 468 if (rv) { 469 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", 470 __func__, rv); 471 return IRQ_NONE; 472 } 473 dev_err(soc_runtime->dev, "%s() bus access error\n", __func__); 474 snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); 475 ret = IRQ_HANDLED; 476 } 477 478 return ret; 479 } 480 481 static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) 482 { 483 struct lpass_data *drvdata = data; 484 struct lpass_variant *v = drvdata->variant; 485 unsigned int irqs; 486 int rv, chan; 487 488 rv = regmap_read(drvdata->lpaif_map, 489 LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs); 490 if (rv) { 491 pr_err("%s() error reading from irqstat reg: %d\n", 492 __func__, 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, "%s() error getting irq handle: %d\n", 575 __func__, 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, "%s() error writing to irqen reg: %d\n", 584 __func__, ret); 585 return ret; 586 } 587 588 ret = devm_request_irq(&pdev->dev, drvdata->lpaif_irq, 589 lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING, 590 "lpass-irq-lpaif", drvdata); 591 if (ret) { 592 dev_err(&pdev->dev, "%s() irq request failed: %d\n", 593 __func__, ret); 594 return ret; 595 } 596 597 598 return devm_snd_soc_register_platform(&pdev->dev, 599 &lpass_platform_driver); 600 } 601 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register); 602 603 MODULE_DESCRIPTION("QTi LPASS Platform Driver"); 604 MODULE_LICENSE("GPL v2"); 605