ASoC: SDCA: Add SDCA IRQ enable/disable helpers

Add helpers to enable and disable the SDCA IRQs by Function. These are
useful to sequence the powering down and up around system suspend.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Link: https://patch.msgid.link/20260109145206.3456151-2-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Charles Keepax
2026-01-09 14:52:03 +00:00
committed by Mark Brown
parent 8978da8e51
commit 9e3d4f794c
2 changed files with 83 additions and 0 deletions

View File

@@ -84,4 +84,11 @@ int sdca_irq_populate(struct sdca_function_data *function,
struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev,
struct regmap *regmap, int irq);
void sdca_irq_enable_early(struct sdca_function_data *function,
struct sdca_interrupt_info *info);
void sdca_irq_enable(struct sdca_function_data *function,
struct sdca_interrupt_info *info);
void sdca_irq_disable(struct sdca_function_data *function,
struct sdca_interrupt_info *info);
#endif

View File

@@ -541,3 +541,79 @@ struct sdca_interrupt_info *sdca_irq_allocate(struct device *sdev,
return info;
}
EXPORT_SYMBOL_NS_GPL(sdca_irq_allocate, "SND_SOC_SDCA");
static void irq_enable_flags(struct sdca_function_data *function,
struct sdca_interrupt_info *info, bool early)
{
struct sdca_interrupt *interrupt;
int i;
for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) {
interrupt = &info->irqs[i];
if (!interrupt || interrupt->function != function)
continue;
switch (SDCA_CTL_TYPE(interrupt->entity->type,
interrupt->control->sel)) {
case SDCA_CTL_TYPE_S(XU, FDL_CURRENTOWNER):
if (early)
enable_irq(interrupt->irq);
break;
default:
if (!early)
enable_irq(interrupt->irq);
break;
}
}
}
/**
* sdca_irq_enable_early - Re-enable early SDCA IRQs for a given function
* @function: Pointer to the SDCA Function.
* @info: Pointer to the SDCA interrupt info for this device.
*
* The early version of the IRQ enable allows enabling IRQs which may be
* necessary to bootstrap functionality for other IRQs, such as the FDL
* process.
*/
void sdca_irq_enable_early(struct sdca_function_data *function,
struct sdca_interrupt_info *info)
{
irq_enable_flags(function, info, true);
}
EXPORT_SYMBOL_NS_GPL(sdca_irq_enable_early, "SND_SOC_SDCA");
/**
* sdca_irq_enable - Re-enable SDCA IRQs for a given function
* @function: Pointer to the SDCA Function.
* @info: Pointer to the SDCA interrupt info for this device.
*/
void sdca_irq_enable(struct sdca_function_data *function,
struct sdca_interrupt_info *info)
{
irq_enable_flags(function, info, false);
}
EXPORT_SYMBOL_NS_GPL(sdca_irq_enable, "SND_SOC_SDCA");
/**
* sdca_irq_disable - Disable SDCA IRQs for a given function
* @function: Pointer to the SDCA Function.
* @info: Pointer to the SDCA interrupt info for this device.
*/
void sdca_irq_disable(struct sdca_function_data *function,
struct sdca_interrupt_info *info)
{
struct sdca_interrupt *interrupt;
int i;
for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) {
interrupt = &info->irqs[i];
if (!interrupt || interrupt->function != function)
continue;
disable_irq(interrupt->irq);
}
}
EXPORT_SYMBOL_NS_GPL(sdca_irq_disable, "SND_SOC_SDCA");