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