[PATCH] ASoC: SDCA: Write init table on function status IRQ

From: Cássio Gabriel

Date: Mon Mar 23 2026 - 23:04:14 EST


The function status IRQ handler currently acknowledges
SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION but does
not perform the function initialization writes. Since the
handler clears the function status register afterwards,
the request is lost.

Use sdca_regmap_write_init() when the initialization status
bit is reported and apply the writes through the device regmap
stored in the IRQ data, matching the existing class-function
boot and resume paths.

Fixes: b9ab3b618241 ("ASoC: SDCA: Add some initial IRQ handlers")
Signed-off-by: Cássio Gabriel <cassiogabrielcontato@xxxxxxxxx>
---
include/sound/sdca_interrupts.h | 5 ++++-
sound/soc/sdca/sdca_class.c | 1 +
sound/soc/sdca/sdca_interrupts.c | 20 +++++++++++++++++---
3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h
index 9bcb5d8fd592..a63ae9df26d6 100644
--- a/include/sound/sdca_interrupts.h
+++ b/include/sound/sdca_interrupts.h
@@ -30,6 +30,7 @@ struct sdca_function_data;
* @function: Pointer to the Function that the interrupt is associated with.
* @entity: Pointer to the Entity that the interrupt is associated with.
* @control: Pointer to the Control that the interrupt is associated with.
+ * @init_lock: Pointer to the lock serializing function initialization.
* @priv: Pointer to private data for use by the handler.
* @irq: IRQ number allocated to this interrupt, also used internally to track
* the IRQ being assigned.
@@ -44,6 +45,7 @@ struct sdca_interrupt {
struct sdca_function_data *function;
struct sdca_entity *entity;
struct sdca_control *control;
+ struct mutex *init_lock;

void *priv;

@@ -82,7 +84,8 @@ int sdca_irq_populate(struct sdca_function_data *function,
struct snd_soc_component *component,
struct sdca_interrupt_info *info);
struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev,
- struct regmap *regmap, int irq);
+ struct regmap *regmap,
+ struct mutex *init_lock, int irq);

void sdca_irq_enable_early(struct sdca_function_data *function,
struct sdca_interrupt_info *info);
diff --git a/sound/soc/sdca/sdca_class.c b/sound/soc/sdca/sdca_class.c
index 7af4e5d1b347..426c11c47557 100644
--- a/sound/soc/sdca/sdca_class.c
+++ b/sound/soc/sdca/sdca_class.c
@@ -149,6 +149,7 @@ static void class_boot_work(struct work_struct *work)
goto err;

drv->irq_info = sdca_irq_allocate(drv->dev, drv->dev_regmap,
+ &drv->init_lock,
drv->sdw->irq);
if (IS_ERR(drv->irq_info))
goto err;
diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c
index 95b1ab4ba1b0..caf5f6ace168 100644
--- a/sound/soc/sdca/sdca_interrupts.c
+++ b/sound/soc/sdca/sdca_interrupts.c
@@ -22,6 +22,7 @@
#include <sound/sdca_function.h>
#include <sound/sdca_hid.h>
#include <sound/sdca_interrupts.h>
+#include <sound/sdca_regmap.h>
#include <sound/sdca_jack.h>
#include <sound/sdca_ump.h>
#include <sound/soc-component.h>
@@ -121,7 +122,16 @@ static irqreturn_t function_status_handler(int irq, void *data)

switch (mask) {
case SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION:
- //FIXME: Add init writes
+ dev_dbg(dev, "write initialization\n");
+
+ guard(mutex)(interrupt->init_lock);
+
+ ret = sdca_regmap_write_init(dev, interrupt->device_regmap,
+ interrupt->function);
+ if (ret) {
+ dev_err(dev, "failed to write initialization: %d\n", ret);
+ goto error;
+ }
break;
case SDCA_CTL_ENTITY_0_FUNCTION_FAULT:
dev_err(dev, "function fault\n");
@@ -520,6 +530,7 @@ EXPORT_SYMBOL_NS_GPL(sdca_irq_populate, "SND_SOC_SDCA");
* sdca_irq_allocate - allocate an SDCA interrupt structure for a device
* @sdev: Device pointer against which things should be allocated.
* @regmap: regmap to be used for accessing the SDCA IRQ registers.
+ * @init_lock: Lock to serialize function initialization.
* @irq: The interrupt number.
*
* Typically this would be called from the top level driver for the whole
@@ -530,7 +541,8 @@ EXPORT_SYMBOL_NS_GPL(sdca_irq_populate, "SND_SOC_SDCA");
* error code.
*/
struct sdca_interrupt_info *sdca_irq_allocate(struct device *sdev,
- struct regmap *regmap, int irq)
+ struct regmap *regmap,
+ struct mutex *init_lock, int irq)
{
struct sdca_interrupt_info *info;
int ret, i;
@@ -541,8 +553,10 @@ struct sdca_interrupt_info *sdca_irq_allocate(struct device *sdev,

info->irq_chip = sdca_irq_chip;

- for (i = 0; i < ARRAY_SIZE(info->irqs); i++)
+ for (i = 0; i < ARRAY_SIZE(info->irqs); i++) {
info->irqs[i].device_regmap = regmap;
+ info->irqs[i].init_lock = init_lock;
+ }

ret = devm_mutex_init(sdev, &info->irq_lock);
if (ret)

---
base-commit: 834f16f74d88054df215eebef09ad864c7e5977c
change-id: 20260323-sdca-function-status-init-irq-f5f76e26ce19

Best regards,
--
Cássio Gabriel <cassiogabrielcontato@xxxxxxxxx>