1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2025 Cirrus Logic, Inc. and 3 // Cirrus Logic International Semiconductor Ltd. 4 5 /* 6 * The MIPI SDCA specification is available for public downloads at 7 * https://www.mipi.org/mipi-sdca-v1-0-download 8 */ 9 10 #include <linux/bitmap.h> 11 #include <linux/bits.h> 12 #include <linux/cleanup.h> 13 #include <linux/device.h> 14 #include <linux/dev_printk.h> 15 #include <linux/interrupt.h> 16 #include <linux/pm_runtime.h> 17 #include <linux/regmap.h> 18 #include <linux/soundwire/sdw.h> 19 #include <linux/soundwire/sdw_registers.h> 20 #include <sound/sdca.h> 21 #include <sound/sdca_fdl.h> 22 #include <sound/sdca_function.h> 23 #include <sound/sdca_hid.h> 24 #include <sound/sdca_interrupts.h> 25 #include <sound/sdca_jack.h> 26 #include <sound/sdca_ump.h> 27 #include <sound/soc-component.h> 28 #include <sound/soc.h> 29 30 #define IRQ_SDCA(number) REGMAP_IRQ_REG(number, ((number) / BITS_PER_BYTE), \ 31 SDW_SCP_SDCA_INTMASK_SDCA_##number) 32 33 static const struct regmap_irq regmap_irqs[SDCA_MAX_INTERRUPTS] = { 34 IRQ_SDCA(0), 35 IRQ_SDCA(1), 36 IRQ_SDCA(2), 37 IRQ_SDCA(3), 38 IRQ_SDCA(4), 39 IRQ_SDCA(5), 40 IRQ_SDCA(6), 41 IRQ_SDCA(7), 42 IRQ_SDCA(8), 43 IRQ_SDCA(9), 44 IRQ_SDCA(10), 45 IRQ_SDCA(11), 46 IRQ_SDCA(12), 47 IRQ_SDCA(13), 48 IRQ_SDCA(14), 49 IRQ_SDCA(15), 50 IRQ_SDCA(16), 51 IRQ_SDCA(17), 52 IRQ_SDCA(18), 53 IRQ_SDCA(19), 54 IRQ_SDCA(20), 55 IRQ_SDCA(21), 56 IRQ_SDCA(22), 57 IRQ_SDCA(23), 58 IRQ_SDCA(24), 59 IRQ_SDCA(25), 60 IRQ_SDCA(26), 61 IRQ_SDCA(27), 62 IRQ_SDCA(28), 63 IRQ_SDCA(29), 64 IRQ_SDCA(30), 65 }; 66 67 static const struct regmap_irq_chip sdca_irq_chip = { 68 .name = "sdca_irq", 69 70 .status_base = SDW_SCP_SDCA_INT1, 71 .unmask_base = SDW_SCP_SDCA_INTMASK1, 72 .ack_base = SDW_SCP_SDCA_INT1, 73 .num_regs = 4, 74 75 .irqs = regmap_irqs, 76 .num_irqs = SDCA_MAX_INTERRUPTS, 77 78 .runtime_pm = true, 79 }; 80 81 static irqreturn_t base_handler(int irq, void *data) 82 { 83 struct sdca_interrupt *interrupt = data; 84 struct device *dev = interrupt->dev; 85 86 dev_info(dev, "%s irq without full handling\n", interrupt->name); 87 88 return IRQ_HANDLED; 89 } 90 91 static irqreturn_t function_status_handler(int irq, void *data) 92 { 93 struct sdca_interrupt *interrupt = data; 94 struct device *dev = interrupt->dev; 95 irqreturn_t irqret = IRQ_NONE; 96 unsigned int reg, val; 97 unsigned long status; 98 unsigned int mask; 99 int ret; 100 101 ret = pm_runtime_get_sync(dev); 102 if (ret < 0) { 103 dev_err(dev, "failed to resume for function status: %d\n", ret); 104 goto error; 105 } 106 107 reg = SDW_SDCA_CTL(interrupt->function->desc->adr, interrupt->entity->id, 108 interrupt->control->sel, 0); 109 110 ret = regmap_read(interrupt->function_regmap, reg, &val); 111 if (ret < 0) { 112 dev_err(dev, "failed to read function status: %d\n", ret); 113 goto error; 114 } 115 116 dev_dbg(dev, "function status: %#x\n", val); 117 118 status = val; 119 for_each_set_bit(mask, &status, BITS_PER_BYTE) { 120 switch (BIT(mask)) { 121 case SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION: 122 /* 123 * FIXME: Should this do init writes? 124 * 125 * Currently init writes/cache sync are done from the suspend/resume 126 * infrastructure. It is unclear in what situations one would receive this 127 * IRQ outside of that flow. Presumably it would be something like the chip 128 * crashing. In that case however doing the init writes and a cache sync might 129 * not be sufficient, for example if the failure was during audio playback 130 * there could be ordering constraints on the register writes to restore the 131 * state that are not handled by a simple cache sync. 132 */ 133 break; 134 case SDCA_CTL_ENTITY_0_FUNCTION_FAULT: 135 dev_err(dev, "function fault\n"); 136 break; 137 case SDCA_CTL_ENTITY_0_UMP_SEQUENCE_FAULT: 138 dev_err(dev, "ump sequence fault\n"); 139 break; 140 case SDCA_CTL_ENTITY_0_FUNCTION_BUSY: 141 dev_info(dev, "unexpected function busy\n"); 142 break; 143 case SDCA_CTL_ENTITY_0_DEVICE_NEWLY_ATTACHED: 144 case SDCA_CTL_ENTITY_0_INTS_DISABLED_ABNORMALLY: 145 case SDCA_CTL_ENTITY_0_STREAMING_STOPPED_ABNORMALLY: 146 case SDCA_CTL_ENTITY_0_FUNCTION_HAS_BEEN_RESET: 147 break; 148 } 149 } 150 151 ret = regmap_write(interrupt->function_regmap, reg, val & 0x7F); 152 if (ret < 0) { 153 dev_err(dev, "failed to clear function status: %d\n", ret); 154 goto error; 155 } 156 157 irqret = IRQ_HANDLED; 158 error: 159 pm_runtime_put(dev); 160 return irqret; 161 } 162 163 static irqreturn_t detected_mode_handler(int irq, void *data) 164 { 165 struct sdca_interrupt *interrupt = data; 166 struct device *dev = interrupt->dev; 167 irqreturn_t irqret = IRQ_NONE; 168 int ret; 169 170 ret = pm_runtime_get_sync(dev); 171 if (ret < 0) { 172 dev_err(dev, "failed to resume for detected mode: %d\n", ret); 173 goto error; 174 } 175 176 ret = sdca_jack_process(interrupt); 177 if (ret) 178 goto error; 179 180 irqret = IRQ_HANDLED; 181 error: 182 pm_runtime_put(dev); 183 return irqret; 184 } 185 186 static irqreturn_t hid_handler(int irq, void *data) 187 { 188 struct sdca_interrupt *interrupt = data; 189 struct device *dev = interrupt->dev; 190 irqreturn_t irqret = IRQ_NONE; 191 int ret; 192 193 ret = pm_runtime_get_sync(dev); 194 if (ret < 0) { 195 dev_err(dev, "failed to resume for hid: %d\n", ret); 196 goto error; 197 } 198 199 ret = sdca_hid_process_report(interrupt); 200 if (ret) 201 goto error; 202 203 irqret = IRQ_HANDLED; 204 error: 205 pm_runtime_put(dev); 206 return irqret; 207 } 208 209 #ifdef CONFIG_PM_SLEEP 210 static bool no_pm_in_progress(struct device *dev) 211 { 212 return completion_done(&dev->power.completion); 213 } 214 #else 215 static bool no_pm_in_progress(struct device *dev) 216 { 217 return true; 218 } 219 #endif 220 221 static irqreturn_t fdl_owner_handler(int irq, void *data) 222 { 223 struct sdca_interrupt *interrupt = data; 224 struct device *dev = interrupt->dev; 225 irqreturn_t irqret = IRQ_NONE; 226 int ret; 227 228 /* 229 * FDL has to run from the system resume handler, at which point 230 * we can't wait for the pm runtime. 231 */ 232 if (no_pm_in_progress(dev)) { 233 ret = pm_runtime_get_sync(dev); 234 if (ret < 0) { 235 dev_err(dev, "failed to resume for fdl: %d\n", ret); 236 goto error; 237 } 238 } 239 240 ret = sdca_fdl_process(interrupt); 241 if (ret) 242 goto error; 243 244 irqret = IRQ_HANDLED; 245 error: 246 if (no_pm_in_progress(dev)) 247 pm_runtime_put(dev); 248 return irqret; 249 } 250 251 static int sdca_irq_request_locked(struct device *dev, 252 struct sdca_interrupt_info *info, 253 int sdca_irq, const char *name, 254 irq_handler_t handler, void *data) 255 { 256 int irq; 257 int ret; 258 259 irq = regmap_irq_get_virq(info->irq_data, sdca_irq); 260 if (irq < 0) 261 return irq; 262 263 ret = request_threaded_irq(irq, NULL, handler, IRQF_ONESHOT, name, data); 264 if (ret) 265 return ret; 266 267 info->irqs[sdca_irq].irq = irq; 268 269 dev_dbg(dev, "requested irq %d for %s\n", irq, name); 270 271 return 0; 272 } 273 274 static void sdca_irq_free_locked(struct device *dev, struct sdca_interrupt_info *info, 275 int sdca_irq, const char *name, void *data) 276 { 277 int irq; 278 279 irq = regmap_irq_get_virq(info->irq_data, sdca_irq); 280 if (irq < 0) 281 return; 282 283 free_irq(irq, data); 284 285 info->irqs[sdca_irq].irq = 0; 286 287 dev_dbg(dev, "freed irq %d for %s\n", irq, name); 288 } 289 290 /** 291 * sdca_irq_request - request an individual SDCA interrupt 292 * @dev: Pointer to the struct device against which things should be allocated. 293 * @info: Pointer to the interrupt information structure. 294 * @sdca_irq: SDCA interrupt position. 295 * @name: Name to be given to the IRQ. 296 * @handler: A callback thread function to be called for the IRQ. 297 * @data: Private data pointer that will be passed to the handler. 298 * 299 * Typically this is handled internally by sdca_irq_populate, however if 300 * a device requires custom IRQ handling this can be called manually before 301 * calling sdca_irq_populate, which will then skip that IRQ whilst processing. 302 * 303 * Return: Zero on success, and a negative error code on failure. 304 */ 305 int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *info, 306 int sdca_irq, const char *name, irq_handler_t handler, 307 void *data) 308 { 309 int ret; 310 311 if (sdca_irq < 0 || sdca_irq >= SDCA_MAX_INTERRUPTS) { 312 dev_err(dev, "bad irq request: %d\n", sdca_irq); 313 return -EINVAL; 314 } 315 316 guard(mutex)(&info->irq_lock); 317 318 ret = sdca_irq_request_locked(dev, info, sdca_irq, name, handler, data); 319 if (ret) { 320 dev_err(dev, "failed to request irq %s: %d\n", name, ret); 321 return ret; 322 } 323 324 return 0; 325 } 326 EXPORT_SYMBOL_NS_GPL(sdca_irq_request, "SND_SOC_SDCA"); 327 328 /** 329 * sdca_irq_free - free an individual SDCA interrupt 330 * @dev: Pointer to the struct device. 331 * @info: Pointer to the interrupt information structure. 332 * @sdca_irq: SDCA interrupt position. 333 * @name: Name to be given to the IRQ. 334 * @data: Private data pointer that will be passed to the handler. 335 * 336 * Typically this is handled internally by sdca_irq_cleanup, however if 337 * a device requires custom IRQ handling this can be called manually before 338 * calling sdca_irq_cleanup, which will then skip that IRQ whilst processing. 339 */ 340 void sdca_irq_free(struct device *dev, struct sdca_interrupt_info *info, 341 int sdca_irq, const char *name, void *data) 342 { 343 if (sdca_irq < 0 || sdca_irq >= SDCA_MAX_INTERRUPTS) 344 return; 345 346 guard(mutex)(&info->irq_lock); 347 348 sdca_irq_free_locked(dev, info, sdca_irq, name, data); 349 } 350 EXPORT_SYMBOL_NS_GPL(sdca_irq_free, "SND_SOC_SDCA"); 351 352 /** 353 * sdca_irq_data_populate - Populate common interrupt data 354 * @dev: Pointer to the Function device. 355 * @regmap: Pointer to the Function regmap. 356 * @component: Pointer to the ASoC component for the Function. 357 * @function: Pointer to the SDCA Function. 358 * @entity: Pointer to the SDCA Entity. 359 * @control: Pointer to the SDCA Control. 360 * @interrupt: Pointer to the SDCA interrupt for this IRQ. 361 * 362 * Return: Zero on success, and a negative error code on failure. 363 */ 364 int sdca_irq_data_populate(struct device *dev, struct regmap *regmap, 365 struct snd_soc_component *component, 366 struct sdca_function_data *function, 367 struct sdca_entity *entity, 368 struct sdca_control *control, 369 struct sdca_interrupt *interrupt) 370 { 371 const char *name; 372 373 if (!dev && component) 374 dev = component->dev; 375 if (!dev) 376 return -ENODEV; 377 378 name = kasprintf(GFP_KERNEL, "%s %s", entity->label, control->label); 379 if (!name) 380 return -ENOMEM; 381 382 interrupt->name = name; 383 interrupt->dev = dev; 384 if (!regmap && component) 385 interrupt->function_regmap = component->regmap; 386 else 387 interrupt->function_regmap = regmap; 388 interrupt->component = component; 389 interrupt->function = function; 390 interrupt->entity = entity; 391 interrupt->control = control; 392 393 return 0; 394 } 395 EXPORT_SYMBOL_NS_GPL(sdca_irq_data_populate, "SND_SOC_SDCA"); 396 397 static struct sdca_interrupt *get_interrupt_data(struct device *dev, int irq, 398 struct sdca_interrupt_info *info) 399 { 400 if (irq == SDCA_NO_INTERRUPT) { 401 return NULL; 402 } else if (irq < 0 || irq >= SDCA_MAX_INTERRUPTS) { 403 dev_err(dev, "bad irq position: %d\n", irq); 404 return ERR_PTR(-EINVAL); 405 } 406 407 if (info->irqs[irq].irq) { 408 dev_dbg(dev, "skipping irq %d, already requested\n", irq); 409 return NULL; 410 } 411 412 return &info->irqs[irq]; 413 } 414 415 /** 416 * sdca_irq_populate_early - process pre-audio card IRQ registrations 417 * @dev: Device pointer for SDCA Function. 418 * @regmap: Regmap pointer for the SDCA Function. 419 * @function: Pointer to the SDCA Function. 420 * @info: Pointer to the SDCA interrupt info for this device. 421 * 422 * This is intended to be used as part of the Function boot process. It 423 * can be called before the soundcard is registered (ie. doesn't depend 424 * on component) and will populate all the required IRQ data, as well as 425 * registering the FDL interrupts to start booting the device. 426 * 427 * Return: Zero on success, and a negative error code on failure. 428 */ 429 int sdca_irq_populate_early(struct device *dev, struct regmap *regmap, 430 struct sdca_function_data *function, 431 struct sdca_interrupt_info *info) 432 { 433 int i, j; 434 435 guard(mutex)(&info->irq_lock); 436 437 for (i = 0; i < function->num_entities; i++) { 438 struct sdca_entity *entity = &function->entities[i]; 439 440 for (j = 0; j < entity->num_controls; j++) { 441 struct sdca_control *control = &entity->controls[j]; 442 int irq = control->interrupt_position; 443 struct sdca_interrupt *interrupt; 444 int ret; 445 446 interrupt = get_interrupt_data(dev, irq, info); 447 if (IS_ERR(interrupt)) 448 return PTR_ERR(interrupt); 449 else if (!interrupt) 450 continue; 451 452 ret = sdca_irq_data_populate(dev, regmap, NULL, function, 453 entity, control, interrupt); 454 if (ret) 455 return ret; 456 457 switch (SDCA_CTL_TYPE(entity->type, control->sel)) { 458 case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_STATUS): 459 interrupt->handler = function_status_handler; 460 break; 461 case SDCA_CTL_TYPE_S(GE, DETECTED_MODE): 462 interrupt->handler = detected_mode_handler; 463 interrupt->free_priv = sdca_jack_free_state; 464 465 ret = sdca_jack_alloc_state(interrupt); 466 if (ret) 467 return ret; 468 break; 469 case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER): 470 interrupt->handler = fdl_owner_handler; 471 interrupt->free_priv = sdca_fdl_free_state; 472 473 ret = sdca_fdl_alloc_state(interrupt); 474 if (ret) 475 return ret; 476 477 interrupt->early_request = true; 478 479 ret = sdca_irq_request_locked(dev, info, irq, 480 interrupt->name, 481 interrupt->handler, 482 interrupt); 483 if (ret) { 484 dev_err(dev, "failed to request irq %s: %d\n", 485 interrupt->name, ret); 486 return ret; 487 } 488 break; 489 case SDCA_CTL_TYPE_S(HIDE, HIDTX_CURRENTOWNER): 490 interrupt->handler = hid_handler; 491 break; 492 default: 493 interrupt->handler = base_handler; 494 break; 495 } 496 } 497 } 498 499 return 0; 500 } 501 EXPORT_SYMBOL_NS_GPL(sdca_irq_populate_early, "SND_SOC_SDCA"); 502 503 /** 504 * sdca_irq_populate - Request all the individual IRQs for an SDCA Function 505 * @function: Pointer to the SDCA Function. 506 * @component: Pointer to the ASoC component for the Function. 507 * @info: Pointer to the SDCA interrupt info for this device. 508 * 509 * Typically this would be called from the driver for a single SDCA Function. 510 * 511 * Return: Zero on success, and a negative error code on failure. 512 */ 513 int sdca_irq_populate(struct sdca_function_data *function, 514 struct snd_soc_component *component, 515 struct sdca_interrupt_info *info) 516 { 517 struct device *dev = component->dev; 518 int i, ret; 519 520 guard(mutex)(&info->irq_lock); 521 522 for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) { 523 struct sdca_interrupt *interrupt = &info->irqs[i]; 524 struct sdca_control *control = interrupt->control; 525 struct sdca_entity *entity = interrupt->entity; 526 int irq; 527 528 if (interrupt->function != function || interrupt->irq) 529 continue; 530 531 interrupt->component = component; 532 533 switch (SDCA_CTL_TYPE(entity->type, control->sel)) { 534 case SDCA_CTL_TYPE_S(GE, DETECTED_MODE): 535 ret = sdca_jack_init_state(interrupt); 536 if (ret) 537 return ret; 538 break; 539 default: 540 break; 541 } 542 543 irq = interrupt->control->interrupt_position; 544 ret = sdca_irq_request_locked(dev, info, irq, interrupt->name, 545 interrupt->handler, interrupt); 546 if (ret) { 547 dev_err(dev, "failed to request irq %s: %d\n", 548 interrupt->name, ret); 549 return ret; 550 } 551 } 552 553 return 0; 554 } 555 EXPORT_SYMBOL_NS_GPL(sdca_irq_populate, "SND_SOC_SDCA"); 556 557 static void sdca_irq_cleanup_flags(struct device *dev, 558 struct sdca_function_data *function, 559 struct sdca_interrupt_info *info, 560 bool late_cleanup) 561 { 562 int i; 563 564 guard(mutex)(&info->irq_lock); 565 566 for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) { 567 struct sdca_interrupt *interrupt = &info->irqs[i]; 568 569 if (interrupt->function != function || 570 (interrupt->early_request && !late_cleanup)) 571 continue; 572 573 if (interrupt->irq) 574 sdca_irq_free_locked(dev, info, i, interrupt->name, interrupt); 575 576 if (!late_cleanup) 577 continue; 578 579 if (interrupt->free_priv) 580 interrupt->free_priv(interrupt); 581 582 kfree(interrupt->name); 583 } 584 } 585 586 /** 587 * sdca_irq_cleanup - Free the regular IRQs for an SDCA Function 588 * @dev: Device pointer against which the sdca_interrupt_info was allocated. 589 * @function: Pointer to the SDCA Function. 590 * @info: Pointer to the SDCA interrupt info for this device. 591 * 592 * Typically this would be called from the driver for a single SDCA Function 593 * from component remove. 594 */ 595 void sdca_irq_cleanup(struct device *dev, 596 struct sdca_function_data *function, 597 struct sdca_interrupt_info *info) 598 { 599 sdca_irq_cleanup_flags(dev, function, info, false); 600 } 601 EXPORT_SYMBOL_NS_GPL(sdca_irq_cleanup, "SND_SOC_SDCA"); 602 603 /** 604 * sdca_irq_cleanup_late - Free the early IRQs for an SDCA Function 605 * @dev: Device pointer against which the sdca_interrupt_info was allocated. 606 * @function: Pointer to the SDCA Function. 607 * @info: Pointer to the SDCA interrupt info for this device. 608 * 609 * Typically this would be called from the driver for a single SDCA Function 610 * from bus remove. 611 */ 612 void sdca_irq_cleanup_late(struct device *dev, 613 struct sdca_function_data *function, 614 struct sdca_interrupt_info *info) 615 { 616 sdca_irq_cleanup_flags(dev, function, info, true); 617 } 618 EXPORT_SYMBOL_NS_GPL(sdca_irq_cleanup_late, "SND_SOC_SDCA"); 619 620 /** 621 * devm_sdca_irq_allocate - allocate an SDCA interrupt structure for a device 622 * @sdev: Device pointer against which things should be allocated. 623 * @regmap: regmap to be used for accessing the SDCA IRQ registers. 624 * @irq: The interrupt number. 625 * 626 * Typically this would be called from the top level driver for the whole 627 * SDCA device, as only a single instance is required across all Functions 628 * on the device. 629 * 630 * Return: A pointer to the allocated sdca_interrupt_info struct, or an 631 * error code. 632 */ 633 struct sdca_interrupt_info *devm_sdca_irq_allocate(struct device *sdev, 634 struct regmap *regmap, int irq) 635 { 636 struct sdca_interrupt_info *info; 637 int ret, i; 638 639 info = devm_kzalloc(sdev, sizeof(*info), GFP_KERNEL); 640 if (!info) 641 return ERR_PTR(-ENOMEM); 642 643 info->irq_chip = sdca_irq_chip; 644 645 for (i = 0; i < ARRAY_SIZE(info->irqs); i++) 646 info->irqs[i].device_regmap = regmap; 647 648 ret = devm_mutex_init(sdev, &info->irq_lock); 649 if (ret) 650 return ERR_PTR(ret); 651 652 ret = devm_regmap_add_irq_chip(sdev, regmap, irq, IRQF_ONESHOT, 0, 653 &info->irq_chip, &info->irq_data); 654 if (ret) { 655 dev_err(sdev, "failed to register irq chip: %d\n", ret); 656 return ERR_PTR(ret); 657 } 658 659 dev_dbg(sdev, "registered on irq %d\n", irq); 660 661 return info; 662 } 663 EXPORT_SYMBOL_NS_GPL(devm_sdca_irq_allocate, "SND_SOC_SDCA"); 664 665 static void irq_enable_flags(struct sdca_function_data *function, 666 struct sdca_interrupt_info *info, bool early) 667 { 668 int i; 669 670 for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) { 671 struct sdca_interrupt *interrupt = &info->irqs[i]; 672 673 if (!interrupt->irq || interrupt->function != function) 674 continue; 675 676 switch (SDCA_CTL_TYPE(interrupt->entity->type, 677 interrupt->control->sel)) { 678 case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER): 679 if (early) 680 enable_irq(interrupt->irq); 681 break; 682 default: 683 if (!early) 684 enable_irq(interrupt->irq); 685 break; 686 } 687 } 688 } 689 690 /** 691 * sdca_irq_enable_early - Re-enable early SDCA IRQs for a given function 692 * @function: Pointer to the SDCA Function. 693 * @info: Pointer to the SDCA interrupt info for this device. 694 * 695 * The early version of the IRQ enable allows enabling IRQs which may be 696 * necessary to bootstrap functionality for other IRQs, such as the FDL 697 * process. 698 */ 699 void sdca_irq_enable_early(struct sdca_function_data *function, 700 struct sdca_interrupt_info *info) 701 { 702 irq_enable_flags(function, info, true); 703 } 704 EXPORT_SYMBOL_NS_GPL(sdca_irq_enable_early, "SND_SOC_SDCA"); 705 706 /** 707 * sdca_irq_enable - Re-enable SDCA IRQs for a given function 708 * @function: Pointer to the SDCA Function. 709 * @info: Pointer to the SDCA interrupt info for this device. 710 */ 711 void sdca_irq_enable(struct sdca_function_data *function, 712 struct sdca_interrupt_info *info) 713 { 714 irq_enable_flags(function, info, false); 715 } 716 EXPORT_SYMBOL_NS_GPL(sdca_irq_enable, "SND_SOC_SDCA"); 717 718 /** 719 * sdca_irq_disable - Disable SDCA IRQs for a given function 720 * @function: Pointer to the SDCA Function. 721 * @info: Pointer to the SDCA interrupt info for this device. 722 */ 723 void sdca_irq_disable(struct sdca_function_data *function, 724 struct sdca_interrupt_info *info) 725 { 726 int i; 727 728 for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) { 729 struct sdca_interrupt *interrupt = &info->irqs[i]; 730 731 if (!interrupt->irq || interrupt->function != function) 732 continue; 733 734 disable_irq(interrupt->irq); 735 } 736 } 737 EXPORT_SYMBOL_NS_GPL(sdca_irq_disable, "SND_SOC_SDCA"); 738