[SRU][R][PATCH v4 7/7] ASoC: SDCA: Move kcontrol search out of IRQ
Chris Chiu
chris.chiu at canonical.com
Mon Sep 7 06:47:44 UTC 2026
From: Charles Keepax <ckeepax at opensource.cirrus.com>
BugLink: https://bugs.launchpad.net/bugs/2163215
Now that the IRQs are always registered after all the ALSA
controls are created it is possible to search for the control
at the point the IRQ is requested. Move the control search out
of the IRQ handler and do it at IRQ request time.
This also fixes a potential issue when the card was torn down
and reprobed without destroying the codec device, the kctl
pointer stored by the IRQ handler would not be updated to the
new control on the second probe.
Signed-off-by: Charles Keepax <ckeepax at opensource.cirrus.com>
Link: https://patch.msgid.link/20260721143636.361814-8-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie at kernel.org>
(cherry picked from commit bf1b7821f85383a8804441f8fd5165be148f3ec8)
Signed-off-by: Chris Chiu <chris.chiu at canonical.com>
---
include/sound/sdca_jack.h | 1 +
sound/soc/sdca/sdca_interrupts.c | 12 +++++++++
sound/soc/sdca/sdca_jack.c | 43 +++++++++++++++++++-------------
3 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/include/sound/sdca_jack.h b/include/sound/sdca_jack.h
index 8624c51eea26..bdde096141c3 100644
--- a/include/sound/sdca_jack.h
+++ b/include/sound/sdca_jack.h
@@ -25,6 +25,7 @@ struct jack_state {
};
int sdca_jack_alloc_state(struct sdca_interrupt *interrupt);
+int sdca_jack_init_state(struct sdca_interrupt *interrupt);
void sdca_jack_free_state(struct sdca_interrupt *interrupt);
int sdca_jack_process(struct sdca_interrupt *interrupt);
diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c
index 79a17d827f99..15da7c2aea50 100644
--- a/sound/soc/sdca/sdca_interrupts.c
+++ b/sound/soc/sdca/sdca_interrupts.c
@@ -512,6 +512,8 @@ int sdca_irq_populate(struct sdca_function_data *function,
for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) {
struct sdca_interrupt *interrupt = &info->irqs[i];
+ struct sdca_control *control = interrupt->control;
+ struct sdca_entity *entity = interrupt->entity;
int irq;
if (interrupt->function != function || interrupt->irq)
@@ -519,6 +521,16 @@ int sdca_irq_populate(struct sdca_function_data *function,
interrupt->component = component;
+ switch (SDCA_CTL_TYPE(entity->type, control->sel)) {
+ case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
+ ret = sdca_jack_init_state(interrupt);
+ if (ret)
+ return ret;
+ break;
+ default:
+ break;
+ }
+
irq = interrupt->control->interrupt_position;
ret = sdca_irq_request_locked(dev, info, irq, interrupt->name,
interrupt->handler, interrupt);
diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c
index 4497134cd32f..8d4f89dc416e 100644
--- a/sound/soc/sdca/sdca_jack.c
+++ b/sound/soc/sdca/sdca_jack.c
@@ -47,23 +47,6 @@ int sdca_jack_process(struct sdca_interrupt *interrupt)
guard(rwsem_write)(rwsem);
- if (!kctl) {
- const char *name __free(kfree) = kasprintf(GFP_KERNEL, "%s %s",
- interrupt->entity->label,
- SDCA_CTL_SELECTED_MODE_NAME);
-
- if (!name)
- return -ENOMEM;
-
- kctl = snd_soc_component_get_kcontrol(component, name);
- 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,
interrupt->control->sel, 0);
@@ -148,6 +131,32 @@ void sdca_jack_free_state(struct sdca_interrupt *interrupt)
}
EXPORT_SYMBOL_NS_GPL(sdca_jack_free_state, "SND_SOC_SDCA");
+/**
+ * sdca_jack_init_state - Initialise transient state for a jack interrupt
+ * @interrupt: SDCA interrupt structure.
+ *
+ * Return: Zero on success or a negative error code.
+ */
+int sdca_jack_init_state(struct sdca_interrupt *interrupt)
+{
+ struct jack_state *jack_state = interrupt->priv;
+ const char *name __free(kfree) = kasprintf(GFP_KERNEL, "%s %s",
+ interrupt->entity->label,
+ SDCA_CTL_SELECTED_MODE_NAME);
+
+ if (!name)
+ return -ENOMEM;
+
+ jack_state->kctl = snd_soc_component_get_kcontrol(interrupt->component, name);
+ if (!jack_state->kctl) {
+ dev_err(interrupt->dev, "control not found: %s\n", name);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(sdca_jack_init_state, "SND_SOC_SDCA");
+
static int type_get_mask(enum sdca_terminal_type type)
{
switch (type) {
--
2.43.0
More information about the kernel-team
mailing list