diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h index e4bf123936bb..3983f515349a 100644 --- a/include/sound/sdca_interrupts.h +++ b/include/sound/sdca_interrupts.h @@ -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, diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c index 2b3bb7d0cb44..d0894c8e0552 100644 --- a/sound/soc/sdca/sdca_interrupts.c +++ b/sound/soc/sdca/sdca_interrupts.c @@ -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 @@ static irqreturn_t function_status_handler(int irq, void *data) 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;