FILE
sdca_interrupts.c
File preview with syntax highlighting.
linux-6.19.14/sound/soc/sdca/sdca_interrupts.c
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 33static 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 67static 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 81static 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 91static 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 //FIXME: Add init writes 123 break; 124 case SDCA_CTL_ENTITY_0_FUNCTION_FAULT: 125 dev_err(dev, "function fault\n"); 126 break; 127 case SDCA_CTL_ENTITY_0_UMP_SEQUENCE_FAULT: 128 dev_err(dev, "ump sequence fault\n"); 129 break; 130 case SDCA_CTL_ENTITY_0_FUNCTION_BUSY: 131 dev_info(dev, "unexpected function busy\n"); 132 break; 133 case SDCA_CTL_ENTITY_0_DEVICE_NEWLY_ATTACHED: 134 case SDCA_CTL_ENTITY_0_INTS_DISABLED_ABNORMALLY: 135 case SDCA_CTL_ENTITY_0_STREAMING_STOPPED_ABNORMALLY: 136 case SDCA_CTL_ENTITY_0_FUNCTION_HAS_BEEN_RESET: 137 break; 138 } 139 } 140 141 ret = regmap_write(interrupt->function_regmap, reg, val); 142 if (ret < 0) { 143 dev_err(dev, "failed to clear function status: %d\n", ret); 144 goto error; 145 } 146 147 irqret = IRQ_HANDLED; 148error: 149 pm_runtime_put(dev); 150 return irqret; 151} 152 153static irqreturn_t detected_mode_handler(int irq, void *data) 154{ 155 struct sdca_interrupt *interrupt = data; 156 struct device *dev = interrupt->dev; 157 irqreturn_t irqret = IRQ_NONE; 158 int ret; 159 160 ret = pm_runtime_get_sync(dev); 161 if (ret < 0) { 162 dev_err(dev, "failed to resume for detected mode: %d\n", ret); 163 goto error; 164 } 165 166 ret = sdca_jack_process(interrupt); 167 if (ret) 168 goto error; 169 170 irqret = IRQ_HANDLED; 171error: 172 pm_runtime_put(dev); 173 return irqret; 174} 175 176static irqreturn_t hid_handler(int irq, void *data) 177{ 178 struct sdca_interrupt *interrupt = data; 179 struct device *dev = interrupt->dev; 180 irqreturn_t irqret = IRQ_NONE; 181 int ret; 182 183 ret = pm_runtime_get_sync(dev); 184 if (ret < 0) { 185 dev_err(dev, "failed to resume for hid: %d\n", ret); 186 goto error; 187 } 188 189 ret = sdca_hid_process_report(interrupt); 190 if (ret) 191 goto error; 192 193 irqret = IRQ_HANDLED; 194error: 195 pm_runtime_put(dev); 196 return irqret; 197} 198 199static irqreturn_t fdl_owner_handler(int irq, void *data) 200{ 201 struct sdca_interrupt *interrupt = data; 202 struct device *dev = interrupt->dev; 203 irqreturn_t irqret = IRQ_NONE; 204 int ret; 205 206 ret = pm_runtime_get_sync(dev); 207 if (ret < 0) { 208 dev_err(dev, "failed to resume for fdl: %d\n", ret); 209 goto error; 210 } 211 212 ret = sdca_fdl_process(interrupt); 213 if (ret) 214 goto error; 215 216 irqret = IRQ_HANDLED; 217error: 218 pm_runtime_put(dev); 219 return irqret; 220} 221 222static int sdca_irq_request_locked(struct device *dev, 223 struct sdca_interrupt_info *info, 224 int sdca_irq, const char *name, 225 irq_handler_t handler, void *data) 226{ 227 int irq; 228 int ret; 229 230 irq = regmap_irq_get_virq(info->irq_data, sdca_irq); 231 if (irq < 0) 232 return irq; 233 234 ret = request_threaded_irq(irq, NULL, handler, IRQF_ONESHOT, name, data); 235 if (ret) 236 return ret; 237 238 info->irqs[sdca_irq].irq = irq; 239 240 dev_dbg(dev, "requested irq %d for %s\n", irq, name); 241 242 return 0; 243} 244 245static void sdca_irq_free_locked(struct device *dev, struct sdca_interrupt_info *info, 246 int sdca_irq, const char *name, void *data) 247{ 248 int irq; 249 250 irq = regmap_irq_get_virq(info->irq_data, sdca_irq); 251 if (irq < 0) 252 return; 253 254 free_irq(irq, data); 255 256 info->irqs[sdca_irq].irq = 0; 257 258 dev_dbg(dev, "freed irq %d for %s\n", irq, name); 259} 260 261/** 262 * sdca_irq_request - request an individual SDCA interrupt 263 * @dev: Pointer to the struct device against which things should be allocated. 264 * @info: Pointer to the interrupt information structure. 265 * @sdca_irq: SDCA interrupt position. 266 * @name: Name to be given to the IRQ. 267 * @handler: A callback thread function to be called for the IRQ. 268 * @data: Private data pointer that will be passed to the handler. 269 * 270 * Typically this is handled internally by sdca_irq_populate, however if 271 * a device requires custom IRQ handling this can be called manually before 272 * calling sdca_irq_populate, which will then skip that IRQ whilst processing. 273 * 274 * Return: Zero on success, and a negative error code on failure. 275 */ 276int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *info, 277 int sdca_irq, const char *name, irq_handler_t handler, 278 void *data) 279{ 280 int ret; 281 282 if (sdca_irq < 0 || sdca_irq >= SDCA_MAX_INTERRUPTS) { 283 dev_err(dev, "bad irq request: %d\n", sdca_irq); 284 return -EINVAL; 285 } 286 287 guard(mutex)(&info->irq_lock); 288 289 ret = sdca_irq_request_locked(dev, info, sdca_irq, name, handler, data); 290 if (ret) { 291 dev_err(dev, "failed to request irq %s: %d\n", name, ret); 292 return ret; 293 } 294 295 return 0; 296} 297EXPORT_SYMBOL_NS_GPL(sdca_irq_request, "SND_SOC_SDCA"); 298 299/** 300 * sdca_irq_free - free an individual SDCA interrupt 301 * @dev: Pointer to the struct device. 302 * @info: Pointer to the interrupt information structure. 303 * @sdca_irq: SDCA interrupt position. 304 * @name: Name to be given to the IRQ. 305 * @data: Private data pointer that will be passed to the handler. 306 * 307 * Typically this is handled internally by sdca_irq_cleanup, however if 308 * a device requires custom IRQ handling this can be called manually before 309 * calling sdca_irq_cleanup, which will then skip that IRQ whilst processing. 310 */ 311void sdca_irq_free(struct device *dev, struct sdca_interrupt_info *info, 312 int sdca_irq, const char *name, void *data) 313{ 314 if (sdca_irq < 0 || sdca_irq >= SDCA_MAX_INTERRUPTS) 315 return; 316 317 guard(mutex)(&info->irq_lock); 318 319 sdca_irq_free_locked(dev, info, sdca_irq, name, data); 320} 321EXPORT_SYMBOL_NS_GPL(sdca_irq_free, "SND_SOC_SDCA"); 322 323/** 324 * sdca_irq_data_populate - Populate common interrupt data 325 * @dev: Pointer to the Function device. 326 * @regmap: Pointer to the Function regmap. 327 * @component: Pointer to the ASoC component for the Function. 328 * @function: Pointer to the SDCA Function. 329 * @entity: Pointer to the SDCA Entity. 330 * @control: Pointer to the SDCA Control. 331 * @interrupt: Pointer to the SDCA interrupt for this IRQ. 332 * 333 * Return: Zero on success, and a negative error code on failure. 334 */ 335int sdca_irq_data_populate(struct device *dev, struct regmap *regmap, 336 struct snd_soc_component *component, 337 struct sdca_function_data *function, 338 struct sdca_entity *entity, 339 struct sdca_control *control, 340 struct sdca_interrupt *interrupt) 341{ 342 const char *name; 343 344 if (!dev && component) 345 dev = component->dev; 346 if (!dev) 347 return -ENODEV; 348 349 name = kasprintf(GFP_KERNEL, "%s %s %s", function->desc->name, 350 entity->label, control->label); 351 if (!name) 352 return -ENOMEM; 353 354 interrupt->name = name; 355 interrupt->dev = dev; 356 if (!regmap && component) 357 interrupt->function_regmap = component->regmap; 358 else 359 interrupt->function_regmap = regmap; 360 interrupt->component = component; 361 interrupt->function = function; 362 interrupt->entity = entity; 363 interrupt->control = control; 364 365 return 0; 366} 367EXPORT_SYMBOL_NS_GPL(sdca_irq_data_populate, "SND_SOC_SDCA"); 368 369static struct sdca_interrupt *get_interrupt_data(struct device *dev, int irq, 370 struct sdca_interrupt_info *info) 371{ 372 if (irq == SDCA_NO_INTERRUPT) { 373 return NULL; 374 } else if (irq < 0 || irq >= SDCA_MAX_INTERRUPTS) { 375 dev_err(dev, "bad irq position: %d\n", irq); 376 return ERR_PTR(-EINVAL); 377 } 378 379 if (info->irqs[irq].irq) { 380 dev_dbg(dev, "skipping irq %d, already requested\n", irq); 381 return NULL; 382 } 383 384 return &info->irqs[irq]; 385} 386 387/** 388 * sdca_irq_populate_early - process pre-audio card IRQ registrations 389 * @dev: Device pointer for SDCA Function. 390 * @regmap: Regmap pointer for the SDCA Function. 391 * @function: Pointer to the SDCA Function. 392 * @info: Pointer to the SDCA interrupt info for this device. 393 * 394 * This is intended to be used as part of the Function boot process. It 395 * can be called before the soundcard is registered (ie. doesn't depend 396 * on component) and will register the FDL interrupts. 397 * 398 * Return: Zero on success, and a negative error code on failure. 399 */ 400int sdca_irq_populate_early(struct device *dev, struct regmap *regmap, 401 struct sdca_function_data *function, 402 struct sdca_interrupt_info *info) 403{ 404 int i, j; 405 406 guard(mutex)(&info->irq_lock); 407 408 for (i = 0; i < function->num_entities; i++) { 409 struct sdca_entity *entity = &function->entities[i]; 410 411 for (j = 0; j < entity->num_controls; j++) { 412 struct sdca_control *control = &entity->controls[j]; 413 int irq = control->interrupt_position; 414 struct sdca_interrupt *interrupt; 415 int ret; 416 417 interrupt = get_interrupt_data(dev, irq, info); 418 if (IS_ERR(interrupt)) 419 return PTR_ERR(interrupt); 420 else if (!interrupt) 421 continue; 422 423 switch (SDCA_CTL_TYPE(entity->type, control->sel)) { 424 case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER): 425 ret = sdca_irq_data_populate(dev, regmap, NULL, 426 function, entity, 427 control, interrupt); 428 if (ret) 429 return ret; 430 431 ret = sdca_fdl_alloc_state(interrupt); 432 if (ret) 433 return ret; 434 435 ret = sdca_irq_request_locked(dev, info, irq, 436 interrupt->name, 437 fdl_owner_handler, 438 interrupt); 439 if (ret) { 440 dev_err(dev, "failed to request irq %s: %d\n", 441 interrupt->name, ret); 442 return ret; 443 } 444 break; 445 default: 446 break; 447 } 448 } 449 } 450 451 return 0; 452} 453EXPORT_SYMBOL_NS_GPL(sdca_irq_populate_early, "SND_SOC_SDCA"); 454 455/** 456 * sdca_irq_populate - Request all the individual IRQs for an SDCA Function 457 * @function: Pointer to the SDCA Function. 458 * @component: Pointer to the ASoC component for the Function. 459 * @info: Pointer to the SDCA interrupt info for this device. 460 * 461 * Typically this would be called from the driver for a single SDCA Function. 462 * 463 * Return: Zero on success, and a negative error code on failure. 464 */ 465int sdca_irq_populate(struct sdca_function_data *function, 466 struct snd_soc_component *component, 467 struct sdca_interrupt_info *info) 468{ 469 struct device *dev = component->dev; 470 int i, j; 471 472 guard(mutex)(&info->irq_lock); 473 474 for (i = 0; i < function->num_entities; i++) { 475 struct sdca_entity *entity = &function->entities[i]; 476 477 for (j = 0; j < entity->num_controls; j++) { 478 struct sdca_control *control = &entity->controls[j]; 479 int irq = control->interrupt_position; 480 struct sdca_interrupt *interrupt; 481 irq_handler_t handler; 482 int ret; 483 484 interrupt = get_interrupt_data(dev, irq, info); 485 if (IS_ERR(interrupt)) 486 return PTR_ERR(interrupt); 487 else if (!interrupt) 488 continue; 489 490 ret = sdca_irq_data_populate(dev, NULL, component, 491 function, entity, control, 492 interrupt); 493 if (ret) 494 return ret; 495 496 handler = base_handler; 497 498 switch (SDCA_CTL_TYPE(entity->type, control->sel)) { 499 case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_STATUS): 500 handler = function_status_handler; 501 break; 502 case SDCA_CTL_TYPE_S(GE, DETECTED_MODE): 503 ret = sdca_jack_alloc_state(interrupt); 504 if (ret) 505 return ret; 506 507 handler = detected_mode_handler; 508 break; 509 case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER): 510 ret = sdca_fdl_alloc_state(interrupt); 511 if (ret) 512 return ret; 513 514 handler = fdl_owner_handler; 515 break; 516 case SDCA_CTL_TYPE_S(HIDE, HIDTX_CURRENTOWNER): 517 handler = hid_handler; 518 break; 519 default: 520 break; 521 } 522 523 ret = sdca_irq_request_locked(dev, info, irq, interrupt->name, 524 handler, interrupt); 525 if (ret) { 526 dev_err(dev, "failed to request irq %s: %d\n", 527 interrupt->name, ret); 528 return ret; 529 } 530 } 531 } 532 533 return 0; 534} 535EXPORT_SYMBOL_NS_GPL(sdca_irq_populate, "SND_SOC_SDCA"); 536 537/** 538 * sdca_irq_cleanup - Free all the individual IRQs for an SDCA Function 539 * @sdev: Device pointer against which the sdca_interrupt_info was allocated. 540 * @function: Pointer to the SDCA Function. 541 * @info: Pointer to the SDCA interrupt info for this device. 542 * 543 * Typically this would be called from the driver for a single SDCA Function. 544 */ 545void sdca_irq_cleanup(struct device *dev, 546 struct sdca_function_data *function, 547 struct sdca_interrupt_info *info) 548{ 549 int i; 550 551 guard(mutex)(&info->irq_lock); 552 553 for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) { 554 struct sdca_interrupt *interrupt = &info->irqs[i]; 555 556 if (interrupt->function != function || !interrupt->irq) 557 continue; 558 559 sdca_irq_free_locked(dev, info, i, interrupt->name, interrupt); 560 561 kfree(interrupt->name); 562 } 563} 564EXPORT_SYMBOL_NS_GPL(sdca_irq_cleanup, "SND_SOC_SDCA"); 565 566/** 567 * sdca_irq_allocate - allocate an SDCA interrupt structure for a device 568 * @sdev: Device pointer against which things should be allocated. 569 * @regmap: regmap to be used for accessing the SDCA IRQ registers. 570 * @irq: The interrupt number. 571 * 572 * Typically this would be called from the top level driver for the whole 573 * SDCA device, as only a single instance is required across all Functions 574 * on the device. 575 * 576 * Return: A pointer to the allocated sdca_interrupt_info struct, or an 577 * error code. 578 */ 579struct sdca_interrupt_info *sdca_irq_allocate(struct device *sdev, 580 struct regmap *regmap, int irq) 581{ 582 struct sdca_interrupt_info *info; 583 int ret, i; 584 585 info = devm_kzalloc(sdev, sizeof(*info), GFP_KERNEL); 586 if (!info) 587 return ERR_PTR(-ENOMEM); 588 589 info->irq_chip = sdca_irq_chip; 590 591 for (i = 0; i < ARRAY_SIZE(info->irqs); i++) 592 info->irqs[i].device_regmap = regmap; 593 594 ret = devm_mutex_init(sdev, &info->irq_lock); 595 if (ret) 596 return ERR_PTR(ret); 597 598 ret = devm_regmap_add_irq_chip(sdev, regmap, irq, IRQF_ONESHOT, 0, 599 &info->irq_chip, &info->irq_data); 600 if (ret) { 601 dev_err(sdev, "failed to register irq chip: %d\n", ret); 602 return ERR_PTR(ret); 603 } 604 605 dev_dbg(sdev, "registered on irq %d\n", irq); 606 607 return info; 608} 609EXPORT_SYMBOL_NS_GPL(sdca_irq_allocate, "SND_SOC_SDCA");
~/
Read-only file preview.