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