]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: SDCA: Add early IRQ handling
authorCharles Keepax <ckeepax@opensource.cirrus.com>
Mon, 20 Oct 2025 15:55:11 +0000 (16:55 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 27 Oct 2025 15:31:28 +0000 (15:31 +0000)
Some IRQs (FDL) require processing before the primary soundcard is
brought up, as the downloaded files could be firmware required for
operation of the audio functions of the device. Add a new helper
function which registers the required IRQs.

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-19-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/sdca_interrupts.h
sound/soc/sdca/sdca_interrupts.c

index 3983f515349ad650ec12eccb8c6a00cd0309de0b..8f13417d129abac6d2ec52b0428e4ffc59f46a26 100644 (file)
@@ -75,6 +75,9 @@ int sdca_irq_data_populate(struct device *dev, struct regmap *function_regmap,
                           struct sdca_entity *entity,
                           struct sdca_control *control,
                           struct sdca_interrupt *interrupt);
+int sdca_irq_populate_early(struct device *dev, struct regmap *function_regmap,
+                           struct sdca_function_data *function,
+                           struct sdca_interrupt_info *info);
 int sdca_irq_populate(struct sdca_function_data *function,
                      struct snd_soc_component *component,
                      struct sdca_interrupt_info *info);
index 3a3b966b5782bdd03e1fb67d245678428557e5cf..51342b8aacae91e0158e92bd47827555d671bf25 100644 (file)
@@ -396,6 +396,77 @@ static struct sdca_interrupt *get_interrupt_data(struct device *dev, int irq,
        return &info->irqs[irq];
 }
 
+/**
+ * sdca_irq_populate_early - process pre-audio card IRQ registrations
+ * @dev: Device pointer for SDCA Function.
+ * @regmap: Regmap pointer for the SDCA Function.
+ * @function: Pointer to the SDCA Function.
+ * @info: Pointer to the SDCA interrupt info for this device.
+ *
+ * This is intended to be used as part of the Function boot process. It
+ * can be called before the soundcard is registered (ie. doesn't depend
+ * on component) and will register the FDL interrupts.
+ *
+ * Return: Zero on success, and a negative error code on failure.
+ */
+int sdca_irq_populate_early(struct device *dev, struct regmap *regmap,
+                           struct sdca_function_data *function,
+                           struct sdca_interrupt_info *info)
+{
+       int i, j;
+
+       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;
+                       int ret;
+
+                       interrupt = get_interrupt_data(dev, irq, info);
+                       if (IS_ERR(interrupt))
+                               return PTR_ERR(interrupt);
+                       else if (!interrupt)
+                               continue;
+
+                       switch (entity->type) {
+                       case SDCA_ENTITY_TYPE_XU:
+                               if (control->sel != SDCA_CTL_XU_FDL_CURRENTOWNER)
+                                       break;
+
+                               ret = sdca_irq_data_populate(dev, regmap, NULL,
+                                                            function, entity,
+                                                            control, interrupt);
+                               if (ret)
+                                       return ret;
+
+                               ret = sdca_fdl_alloc_state(interrupt);
+                               if (ret)
+                                       return ret;
+
+                               ret = sdca_irq_request_locked(dev, info, irq,
+                                                             interrupt->name,
+                                                             fdl_owner_handler,
+                                                             interrupt);
+                               if (ret) {
+                                       dev_err(dev, "failed to request irq %s: %d\n",
+                                               interrupt->name, ret);
+                                       return ret;
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_NS_GPL(sdca_irq_populate_early, "SND_SOC_SDCA");
+
 /**
  * sdca_irq_populate - Request all the individual IRQs for an SDCA Function
  * @function: Pointer to the SDCA Function.