ASoC: SDCA: Add early IRQ handling

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>
This commit is contained in:
Charles Keepax 2025-10-20 16:55:11 +01:00 committed by Mark Brown
parent e92e25f777
commit 12aa3160c1
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
2 changed files with 74 additions and 0 deletions

View 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);

View 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.