Linux Sound subsystem development
 help / color / mirror / Atom feed
* [PATCH v2 0/3] Fix races on creation of SDCA jack detection
@ 2026-07-15 16:29 Charles Keepax
  2026-07-15 16:29 ` [PATCH v2 1/3] ASoC: Add a component fixup_controls callback Charles Keepax
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Charles Keepax @ 2026-07-15 16:29 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, linux-sound,
	linux-kernel, patches

Currently there exists a couple races that can result in the DAPM graph
coming up in a state that doesn't match the hardware with respect to
SDCA jack detection. This series fixes these up by adding a component
level fixup_controls helper into the asoc core and shuffling around the
IRQ requests from the SDCA side.

Thanks,
Charles

Changes since v1:
 - Clean up freeing of the interrupt name, Sashiko astutely pointed out
   there was a memory leak there.

Charles Keepax (3):
  ASoC: Add a component fixup_controls callback
  ASoC: SDCA: Populate IRQ data earlier
  ASoC: SDCA: Switch to fixup_controls callback for IRQ registration

 include/sound/sdca_interrupts.h      |  2 +
 include/sound/soc-component.h        |  2 +
 sound/soc/sdca/sdca_class_function.c | 12 +---
 sound/soc/sdca/sdca_interrupts.c     | 98 ++++++++++------------------
 sound/soc/sdca/sdca_jack.c           | 44 ++++++-------
 sound/soc/soc-component.c            | 10 +++
 sound/soc/soc-core.c                 |  5 ++
 7 files changed, 76 insertions(+), 97 deletions(-)

-- 
2.47.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/3] ASoC: Add a component fixup_controls callback
  2026-07-15 16:29 [PATCH v2 0/3] Fix races on creation of SDCA jack detection Charles Keepax
@ 2026-07-15 16:29 ` Charles Keepax
  2026-07-15 16:29 ` [PATCH v2 2/3] ASoC: SDCA: Populate IRQ data earlier Charles Keepax
  2026-07-15 16:29 ` [PATCH v2 3/3] ASoC: SDCA: Switch to fixup_controls callback for IRQ registration Charles Keepax
  2 siblings, 0 replies; 5+ messages in thread
From: Charles Keepax @ 2026-07-15 16:29 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, linux-sound,
	linux-kernel, patches

A card level fixup_controls callback was added in:

commit df4d27b19b89 ("ASoC: Introduce 'fixup_controls' card method")

This allowed the machine driver to take actions after all the
card controls have been added. However, there are times when a
codec driver would also want to do things like obtain references
to controls for later use, which require all the controls to be
present. Add a component level fixup_controls callback, echoing
the card level option.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

No changes since v1.

 include/sound/soc-component.h |  2 ++
 sound/soc/soc-component.c     | 10 ++++++++++
 sound/soc/soc-core.c          |  5 +++++
 3 files changed, 17 insertions(+)

diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index aa423865dbe7c..4b7d7954953db 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -78,6 +78,7 @@ struct snd_soc_component_driver {
 	unsigned int num_dapm_routes;
 
 	int (*probe)(struct snd_soc_component *component);
+	int (*fixup_controls)(struct snd_soc_component *component);
 	void (*remove)(struct snd_soc_component *component);
 	int (*suspend)(struct snd_soc_component *component);
 	int (*resume)(struct snd_soc_component *component);
@@ -380,6 +381,7 @@ void snd_soc_component_suspend(struct snd_soc_component *component);
 void snd_soc_component_resume(struct snd_soc_component *component);
 int snd_soc_component_is_suspended(struct snd_soc_component *component);
 int snd_soc_component_probe(struct snd_soc_component *component);
+int snd_soc_component_fixup_controls(struct snd_soc_component *component);
 void snd_soc_component_remove(struct snd_soc_component *component);
 int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component,
 				      struct device_node *ep);
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index 21492d15833f7..2ce24513fac5d 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -310,6 +310,16 @@ int snd_soc_component_probe(struct snd_soc_component *component)
 	return soc_component_ret(component, ret);
 }
 
+int snd_soc_component_fixup_controls(struct snd_soc_component *component)
+{
+	int ret = 0;
+
+	if (component->driver->fixup_controls)
+		ret = component->driver->fixup_controls(component);
+
+	return soc_component_ret(component, ret);
+}
+
 void snd_soc_component_remove(struct snd_soc_component *component)
 {
 	if (component->driver->remove)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 7817beea5b3bc..44f9bb4473f55 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2162,6 +2162,11 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
 		goto probe_end;
 
 	snd_soc_dapm_new_widgets(card);
+	for_each_card_components(card, component) {
+		ret = snd_soc_component_fixup_controls(component);
+		if (ret < 0)
+			goto probe_end;
+	}
 	snd_soc_card_fixup_controls(card);
 
 	ret = snd_card_register(card->snd_card);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/3] ASoC: SDCA: Populate IRQ data earlier
  2026-07-15 16:29 [PATCH v2 0/3] Fix races on creation of SDCA jack detection Charles Keepax
  2026-07-15 16:29 ` [PATCH v2 1/3] ASoC: Add a component fixup_controls callback Charles Keepax
@ 2026-07-15 16:29 ` Charles Keepax
  2026-07-15 16:29 ` [PATCH v2 3/3] ASoC: SDCA: Switch to fixup_controls callback for IRQ registration Charles Keepax
  2 siblings, 0 replies; 5+ messages in thread
From: Charles Keepax @ 2026-07-15 16:29 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, linux-sound,
	linux-kernel, patches

Currently, the IRQ data (attached Entity/Control/etc) is populated
as the IRQ is requested. However, this can cause issues as
occasionally the setup process wants to access specifics of
an IRQ before the IRQ is actually enabled. To facilitate this
cache all the IRQ data during sdca_irq_populate_early() and make
sdca_irq_populate() simply request the outstanding IRQs. This
also has the advantage that sdca_irq_populate() can now just
iterate through the IRQ array which is much smaller/faster than
going through every Entity in the Function for Controls.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

Changes since v1:
 - devm_ allocate the interrupt name now that it will always be
   called from irq_populate_early which happens at probe time. This
   also avoids a memory leak Sashiko spotted.

 include/sound/sdca_interrupts.h  |  2 +
 sound/soc/sdca/sdca_interrupts.c | 98 ++++++++++++--------------------
 2 files changed, 38 insertions(+), 62 deletions(-)

diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h
index a515cc3df0971..20ff5eac34eaa 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.
+ * @handler: Handler function to be called for the IRQ.
  * @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;
+	irq_handler_t handler;
 
 	void *priv;
 
diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c
index 4539a52a8e32b..6bbe65ac3d2f0 100644
--- a/sound/soc/sdca/sdca_interrupts.c
+++ b/sound/soc/sdca/sdca_interrupts.c
@@ -375,7 +375,7 @@ int sdca_irq_data_populate(struct device *dev, struct regmap *regmap,
 	if (!dev)
 		return -ENODEV;
 
-	name = kasprintf(GFP_KERNEL, "%s %s", entity->label, control->label);
+	name = devm_kasprintf(dev, GFP_KERNEL, "%s %s", entity->label, control->label);
 	if (!name)
 		return -ENOMEM;
 
@@ -448,21 +448,34 @@ int sdca_irq_populate_early(struct device *dev, struct regmap *regmap,
 			else if (!interrupt)
 				continue;
 
+			ret = sdca_irq_data_populate(dev, regmap, NULL, function,
+						     entity, control, interrupt);
+			if (ret)
+				return ret;
+
+			interrupt->handler = base_handler;
+
 			switch (SDCA_CTL_TYPE(entity->type, control->sel)) {
-			case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER):
-				ret = sdca_irq_data_populate(dev, regmap, NULL,
-							     function, entity,
-							     control, interrupt);
+			case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_STATUS):
+				interrupt->handler = function_status_handler;
+				break;
+			case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
+				ret = sdca_jack_alloc_state(interrupt);
 				if (ret)
 					return ret;
 
+				interrupt->handler = detected_mode_handler;
+				break;
+			case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER):
 				ret = sdca_fdl_alloc_state(interrupt);
 				if (ret)
 					return ret;
 
+				interrupt->handler = fdl_owner_handler;
+
 				ret = sdca_irq_request_locked(dev, info, irq,
 							      interrupt->name,
-							      fdl_owner_handler,
+							      interrupt->handler,
 							      interrupt);
 				if (ret) {
 					dev_err(dev, "failed to request irq %s: %d\n",
@@ -470,6 +483,9 @@ int sdca_irq_populate_early(struct device *dev, struct regmap *regmap,
 					return ret;
 				}
 				break;
+			case SDCA_CTL_TYPE_S(HIDE, HIDTX_CURRENTOWNER):
+				interrupt->handler = hid_handler;
+				break;
 			default:
 				break;
 			}
@@ -495,66 +511,26 @@ int sdca_irq_populate(struct sdca_function_data *function,
 		      struct sdca_interrupt_info *info)
 {
 	struct device *dev = component->dev;
-	int i, j;
+	int i, ret;
 
 	guard(mutex)(&info->irq_lock);
 
-	for (i = 0; i < function->num_entities; i++) {
-		struct sdca_entity *entity = &function->entities[i];
-
-		for (j = 0; j < entity->num_controls; j++) {
-			struct sdca_control *control = &entity->controls[j];
-			int irq = control->interrupt_position;
-			struct sdca_interrupt *interrupt;
-			irq_handler_t handler;
-			int ret;
-
-			interrupt = get_interrupt_data(dev, irq, info);
-			if (IS_ERR(interrupt))
-				return PTR_ERR(interrupt);
-			else if (!interrupt)
-				continue;
-
-			ret = sdca_irq_data_populate(dev, NULL, component,
-						     function, entity, control,
-						     interrupt);
-			if (ret)
-				return ret;
-
-			handler = base_handler;
-
-			switch (SDCA_CTL_TYPE(entity->type, control->sel)) {
-			case SDCA_CTL_TYPE_S(ENTITY_0, FUNCTION_STATUS):
-				handler = function_status_handler;
-				break;
-			case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
-				ret = sdca_jack_alloc_state(interrupt);
-				if (ret)
-					return ret;
+	for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) {
+		struct sdca_interrupt *interrupt = &info->irqs[i];
+		int irq;
 
-				handler = detected_mode_handler;
-				break;
-			case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER):
-				ret = sdca_fdl_alloc_state(interrupt);
-				if (ret)
-					return ret;
+		if (interrupt->function != function || interrupt->irq)
+			continue;
 
-				handler = fdl_owner_handler;
-				break;
-			case SDCA_CTL_TYPE_S(HIDE, HIDTX_CURRENTOWNER):
-				handler = hid_handler;
-				break;
-			default:
-				break;
-			}
+		interrupt->component = component;
 
-			ret = sdca_irq_request_locked(dev, info, irq, interrupt->name,
-						      handler, interrupt);
-			if (ret) {
-				dev_err(dev, "failed to request irq %s: %d\n",
-					interrupt->name, ret);
-				return ret;
-			}
+		irq = interrupt->control->interrupt_position;
+		ret = sdca_irq_request_locked(dev, info, irq, interrupt->name,
+					      interrupt->handler, interrupt);
+		if (ret) {
+			dev_err(dev, "failed to request irq %s: %d\n",
+				interrupt->name, ret);
+			return ret;
 		}
 	}
 
@@ -585,8 +561,6 @@ void sdca_irq_cleanup(struct device *dev,
 			continue;
 
 		sdca_irq_free_locked(dev, info, i, interrupt->name, interrupt);
-
-		kfree(interrupt->name);
 	}
 }
 EXPORT_SYMBOL_NS_GPL(sdca_irq_cleanup, "SND_SOC_SDCA");
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 3/3] ASoC: SDCA: Switch to fixup_controls callback for IRQ registration
  2026-07-15 16:29 [PATCH v2 0/3] Fix races on creation of SDCA jack detection Charles Keepax
  2026-07-15 16:29 ` [PATCH v2 1/3] ASoC: Add a component fixup_controls callback Charles Keepax
  2026-07-15 16:29 ` [PATCH v2 2/3] ASoC: SDCA: Populate IRQ data earlier Charles Keepax
@ 2026-07-15 16:29 ` Charles Keepax
  2026-07-16  9:32   ` Charles Keepax
  2 siblings, 1 reply; 5+ messages in thread
From: Charles Keepax @ 2026-07-15 16:29 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, linux-sound,
	linux-kernel, patches

Currently there are some race conditions around the boot of SDCA
jack detection. The core creates DAPM widgets/routes quite a
long time before it creates the associated ALSA control, and
the jack detection IRQ is currently registered in component
probe. At the time of component probe, the DAPM widgets exist,
shortly after this the DAPM routes are added. At the time the DAPM
routes are added the register value for the control is checked
and the appropriate path is connected. The existing handling
in the SDCA jack IRQ handles the case the control doesn't exist
and updates the registers directly, which works until the DAPM
routes are added.  After the routes are added the DAPM graph has
already set connected on a particular DAPM path, which will not
be updated until an IRQ is received when the control is present.
Thus those updated are usually not reflected in the resulting
DAPM graph which can lead to the audio path being erroneously
powered on/off.

Switch to the new fixup_controls callback to register the
IRQs, this is guaranteed to run after all the controls have
been created. Which means we can avoid the aforementioned race
condition and as a bonus no longer need to concern ourselves
with a case where the IRQ handler runs and the ALSA control
is unavailable.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

Changes since v1:
 - Remove the bus remove callback since all the IRQs are freed in
   component remove and the memory is devm managed.

 sound/soc/sdca/sdca_class_function.c | 12 ++------
 sound/soc/sdca/sdca_jack.c           | 44 ++++++++++++----------------
 2 files changed, 21 insertions(+), 35 deletions(-)

diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c
index 1496a15f7d2ac..32cada9e369cb 100644
--- a/sound/soc/sdca/sdca_class_function.c
+++ b/sound/soc/sdca/sdca_class_function.c
@@ -191,7 +191,7 @@ static const struct snd_soc_dai_ops class_function_sdw_ops = {
 	.hw_free	= class_function_sdw_remove_peripheral,
 };
 
-static int class_function_component_probe(struct snd_soc_component *component)
+static int class_function_component_fixup_controls(struct snd_soc_component *component)
 {
 	struct class_function_drv *drv = snd_soc_component_get_drvdata(component);
 	struct sdca_class_drv *core = drv->core;
@@ -217,7 +217,7 @@ static int class_function_set_jack(struct snd_soc_component *component,
 }
 
 static const struct snd_soc_component_driver class_function_component_drv = {
-	.probe			= class_function_component_probe,
+	.fixup_controls		= class_function_component_fixup_controls,
 	.remove			= class_function_component_remove,
 	.endianness		= 1,
 };
@@ -404,13 +404,6 @@ static int class_function_probe(struct auxiliary_device *auxdev,
 	return 0;
 }
 
-static void class_function_remove(struct auxiliary_device *auxdev)
-{
-	struct class_function_drv *drv = auxiliary_get_drvdata(auxdev);
-
-	sdca_irq_cleanup(drv->dev, drv->function, drv->core->irq_info);
-}
-
 static int class_function_runtime_suspend(struct device *dev)
 {
 	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
@@ -563,7 +556,6 @@ static struct auxiliary_driver class_function_drv = {
 	},
 
 	.probe		= class_function_probe,
-	.remove		= class_function_remove,
 	.id_table	= class_function_id_table
 };
 module_auxiliary_driver(class_function_drv);
diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c
index ae9636622a840..2ac74b9826736 100644
--- a/sound/soc/sdca/sdca_jack.c
+++ b/sound/soc/sdca/sdca_jack.c
@@ -41,6 +41,7 @@ int sdca_jack_process(struct sdca_interrupt *interrupt)
 	struct jack_state *state = interrupt->priv;
 	struct snd_kcontrol *kctl = state->kctl;
 	struct snd_ctl_elem_value *ucontrol __free(kfree) = NULL;
+	struct soc_enum *soc_enum;
 	unsigned int reg, val;
 	int ret;
 
@@ -55,10 +56,12 @@ int sdca_jack_process(struct sdca_interrupt *interrupt)
 			return -ENOMEM;
 
 		kctl = snd_soc_component_get_kcontrol(component, name);
-		if (!kctl)
-			dev_dbg(dev, "control not found: %s\n", name);
-		else
-			state->kctl = kctl;
+		if (!kctl) {
+			dev_err(dev, "control not found: %s\n", name);
+			return -ENODEV;
+		}
+
+		state->kctl = kctl;
 	}
 
 	reg = SDW_SDCA_CTL(interrupt->function->desc->adr, interrupt->entity->id,
@@ -96,30 +99,21 @@ int sdca_jack_process(struct sdca_interrupt *interrupt)
 
 	dev_dbg(dev, "%s: %#x\n", interrupt->name, val);
 
-	if (kctl) {
-		struct soc_enum *soc_enum = (struct soc_enum *)kctl->private_value;
-
-		ucontrol = kzalloc_obj(*ucontrol);
-		if (!ucontrol)
-			return -ENOMEM;
-
-		ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(soc_enum, val);
+	ucontrol = kzalloc_obj(*ucontrol);
+	if (!ucontrol)
+		return -ENOMEM;
 
-		ret = snd_soc_dapm_put_enum_double(kctl, ucontrol);
-		if (ret < 0) {
-			dev_err(dev, "failed to update selected mode: %d\n", ret);
-			return ret;
-		}
+	soc_enum = (struct soc_enum *)kctl->private_value;
+	ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(soc_enum, val);
 
-		snd_ctl_notify(card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
-	} else {
-		ret = regmap_write(interrupt->function_regmap, reg, val);
-		if (ret) {
-			dev_err(dev, "failed to write selected mode: %d\n", ret);
-			return ret;
-		}
+	ret = snd_soc_dapm_put_enum_double(kctl, ucontrol);
+	if (ret < 0) {
+		dev_err(dev, "failed to update selected mode: %d\n", ret);
+		return ret;
 	}
 
+	snd_ctl_notify(card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
+
 	return sdca_jack_report(interrupt);
 }
 EXPORT_SYMBOL_NS_GPL(sdca_jack_process, "SND_SOC_SDCA");
@@ -192,7 +186,7 @@ int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *ja
 		struct sdca_control_range *range;
 		struct jack_state *jack_state;
 
-		if (!interrupt->irq)
+		if (!interrupt->dev)
 			continue;
 
 		switch (SDCA_CTL_TYPE(entity->type, control->sel)) {
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 3/3] ASoC: SDCA: Switch to fixup_controls callback for IRQ registration
  2026-07-15 16:29 ` [PATCH v2 3/3] ASoC: SDCA: Switch to fixup_controls callback for IRQ registration Charles Keepax
@ 2026-07-16  9:32   ` Charles Keepax
  0 siblings, 0 replies; 5+ messages in thread
From: Charles Keepax @ 2026-07-16  9:32 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, linux-sound,
	linux-kernel, patches

On Wed, Jul 15, 2026 at 05:29:18PM +0100, Charles Keepax wrote:
> Currently there are some race conditions around the boot of SDCA
> jack detection. The core creates DAPM widgets/routes quite a
> long time before it creates the associated ALSA control, and
> the jack detection IRQ is currently registered in component
> probe. At the time of component probe, the DAPM widgets exist,
> shortly after this the DAPM routes are added. At the time the DAPM
> routes are added the register value for the control is checked
> and the appropriate path is connected. The existing handling
> in the SDCA jack IRQ handles the case the control doesn't exist
> and updates the registers directly, which works until the DAPM
> routes are added.  After the routes are added the DAPM graph has
> already set connected on a particular DAPM path, which will not
> be updated until an IRQ is received when the control is present.
> Thus those updated are usually not reflected in the resulting
> DAPM graph which can lead to the audio path being erroneously
> powered on/off.
> 
> Switch to the new fixup_controls callback to register the
> IRQs, this is guaranteed to run after all the controls have
> been created. Which means we can avoid the aforementioned race
> condition and as a bonus no longer need to concern ourselves
> with a case where the IRQ handler runs and the ALSA control
> is unavailable.
> 
> Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
> ---
> 
> Changes since v1:
>  - Remove the bus remove callback since all the IRQs are freed in
>    component remove and the memory is devm managed.

Sigh... very sorry I shouldn't have removed that. It is needed to
free the FDL IRQ if component remove never ran. Will do a little
more thinking and send a v3.

Thanks,
Charles

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-07-16  9:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-15 16:29 [PATCH v2 0/3] Fix races on creation of SDCA jack detection Charles Keepax
2026-07-15 16:29 ` [PATCH v2 1/3] ASoC: Add a component fixup_controls callback Charles Keepax
2026-07-15 16:29 ` [PATCH v2 2/3] ASoC: SDCA: Populate IRQ data earlier Charles Keepax
2026-07-15 16:29 ` [PATCH v2 3/3] ASoC: SDCA: Switch to fixup_controls callback for IRQ registration Charles Keepax
2026-07-16  9:32   ` Charles Keepax

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox