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