]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: SDCA: Rely less on the ASoC component in IRQ handling
authorCharles Keepax <ckeepax@opensource.cirrus.com>
Mon, 20 Oct 2025 15:55:01 +0000 (16:55 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 27 Oct 2025 15:31:18 +0000 (15:31 +0000)
In the future some IRQs (mostly the UMPs used during File
DownLoad) will need to run after the device has enumerated on the
bus but before the soundcard is actually constructed. As such
refactor more of the IRQ handling to use raw device and regmap
pointers, rather than accessing things through the component.

Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Link: https://patch.msgid.link/20251020155512.353774-9-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/sdca_interrupts.h
sound/soc/sdca/sdca_interrupts.c

index e4bf123936bbd430e28dd8ded42394ad948fe4df..3983f515349ad650ec12eccb8c6a00cd0309de0b 100644 (file)
@@ -23,7 +23,9 @@ struct sdca_function_data;
 /**
  * struct sdca_interrupt - contains information about a single SDCA interrupt
  * @name: The name of the interrupt.
+ * @dev: Pointer to the Function device.
  * @device_regmap: Pointer to the IRQ regmap.
+ * @function_regmap: Pointer to the SDCA Function regmap.
  * @component: Pointer to the ASoC component owns the interrupt.
  * @function: Pointer to the Function that the interrupt is associated with.
  * @entity: Pointer to the Entity that the interrupt is associated with.
@@ -35,7 +37,9 @@ struct sdca_function_data;
 struct sdca_interrupt {
        const char *name;
 
+       struct device *dev;
        struct regmap *device_regmap;
+       struct regmap *function_regmap;
        struct snd_soc_component *component;
        struct sdca_function_data *function;
        struct sdca_entity *entity;
@@ -65,7 +69,8 @@ struct sdca_interrupt_info {
 int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *interrupt_info,
                     int sdca_irq, const char *name, irq_handler_t handler,
                     void *data);
-int sdca_irq_data_populate(struct snd_soc_component *component,
+int sdca_irq_data_populate(struct device *dev, struct regmap *function_regmap,
+                          struct snd_soc_component *component,
                           struct sdca_function_data *function,
                           struct sdca_entity *entity,
                           struct sdca_control *control,
index 2b3bb7d0cb4439f6b3c4645e13d6d3cfc5811117..d0894c8e0552c1303152249e6fe41f20583e266a 100644 (file)
@@ -77,7 +77,7 @@ static const struct regmap_irq_chip sdca_irq_chip = {
 static irqreturn_t base_handler(int irq, void *data)
 {
        struct sdca_interrupt *interrupt = data;
-       struct device *dev = interrupt->component->dev;
+       struct device *dev = interrupt->dev;
 
        dev_info(dev, "%s irq without full handling\n", interrupt->name);
 
@@ -87,7 +87,7 @@ static irqreturn_t base_handler(int irq, void *data)
 static irqreturn_t function_status_handler(int irq, void *data)
 {
        struct sdca_interrupt *interrupt = data;
-       struct device *dev = interrupt->component->dev;
+       struct device *dev = interrupt->dev;
        irqreturn_t irqret = IRQ_NONE;
        unsigned int reg, val;
        unsigned long status;
@@ -103,7 +103,7 @@ static irqreturn_t function_status_handler(int irq, void *data)
        reg = SDW_SDCA_CTL(interrupt->function->desc->adr, interrupt->entity->id,
                           interrupt->control->sel, 0);
 
-       ret = regmap_read(interrupt->component->regmap, reg, &val);
+       ret = regmap_read(interrupt->function_regmap, reg, &val);
        if (ret < 0) {
                dev_err(dev, "failed to read function status: %d\n", ret);
                goto error;
@@ -136,7 +136,7 @@ static irqreturn_t function_status_handler(int irq, void *data)
                }
        }
 
-       ret = regmap_write(interrupt->component->regmap, reg, val);
+       ret = regmap_write(interrupt->function_regmap, reg, val);
        if (ret < 0) {
                dev_err(dev, "failed to clear function status: %d\n", ret);
                goto error;
@@ -151,8 +151,8 @@ error:
 static irqreturn_t detected_mode_handler(int irq, void *data)
 {
        struct sdca_interrupt *interrupt = data;
+       struct device *dev = interrupt->dev;
        struct snd_soc_component *component = interrupt->component;
-       struct device *dev = component->dev;
        struct snd_soc_card *card = component->card;
        struct rw_semaphore *rwsem = &card->snd_card->controls_rwsem;
        struct snd_kcontrol *kctl = interrupt->priv;
@@ -190,7 +190,7 @@ static irqreturn_t detected_mode_handler(int irq, void *data)
        reg = SDW_SDCA_CTL(interrupt->function->desc->adr, interrupt->entity->id,
                           interrupt->control->sel, 0);
 
-       ret = regmap_read(component->regmap, reg, &val);
+       ret = regmap_read(interrupt->function_regmap, reg, &val);
        if (ret < 0) {
                dev_err(dev, "failed to read detected mode: %d\n", ret);
                goto error;
@@ -209,9 +209,9 @@ static irqreturn_t detected_mode_handler(int irq, void *data)
                 * detected mode is unknown we need to see what the device
                 * selected as a "safe" option.
                 */
-               regcache_drop_region(component->regmap, reg, reg);
+               regcache_drop_region(interrupt->function_regmap, reg, reg);
 
-               ret = regmap_read(component->regmap, reg, &val);
+               ret = regmap_read(interrupt->function_regmap, reg, &val);
                if (ret) {
                        dev_err(dev, "failed to re-check selected mode: %d\n", ret);
                        goto error;
@@ -309,6 +309,8 @@ EXPORT_SYMBOL_NS_GPL(sdca_irq_request, "SND_SOC_SDCA");
 
 /**
  * sdca_irq_data_populate - Populate common interrupt data
+ * @dev: Pointer to the Function device.
+ * @regmap: Pointer to the Function regmap.
  * @component: Pointer to the ASoC component for the Function.
  * @function: Pointer to the SDCA Function.
  * @entity: Pointer to the SDCA Entity.
@@ -317,21 +319,31 @@ EXPORT_SYMBOL_NS_GPL(sdca_irq_request, "SND_SOC_SDCA");
  *
  * Return: Zero on success, and a negative error code on failure.
  */
-int sdca_irq_data_populate(struct snd_soc_component *component,
+int sdca_irq_data_populate(struct device *dev, struct regmap *regmap,
+                          struct snd_soc_component *component,
                           struct sdca_function_data *function,
                           struct sdca_entity *entity,
                           struct sdca_control *control,
                           struct sdca_interrupt *interrupt)
 {
-       struct device *dev = component->dev;
        const char *name;
 
+       if (!dev && component)
+               dev = component->dev;
+       if (!dev)
+               return -ENODEV;
+
        name = devm_kasprintf(dev, GFP_KERNEL, "%s %s %s", function->desc->name,
                              entity->label, control->label);
        if (!name)
                return -ENOMEM;
 
        interrupt->name = name;
+       interrupt->dev = dev;
+       if (!regmap && component)
+               interrupt->function_regmap = component->regmap;
+       else
+               interrupt->function_regmap = regmap;
        interrupt->component = component;
        interrupt->function = function;
        interrupt->entity = entity;
@@ -394,8 +406,9 @@ int sdca_irq_populate(struct sdca_function_data *function,
                        else if (!interrupt)
                                continue;
 
-                       ret = sdca_irq_data_populate(component, function, entity,
-                                                    control, interrupt);
+                       ret = sdca_irq_data_populate(dev, NULL, component,
+                                                    function, entity, control,
+                                                    interrupt);
                        if (ret)
                                return ret;