Skip to content

Commit 762eba7

Browse files
Stefan Bindingtiwai
authored andcommitted
ALSA: hda: cs35l41: Ignore errors when configuring IRQs
IRQs used for CS35L41 HDA are used to detect and attempt to recover from errors. Without these interrupts, the driver should behave as normal. For laptops which contain a bad configuration for the interrupt in the BIOS, the current behaviour of failing when trying to configure the interrupt means the probe fails, and audio is broken. It is better for the user experience if the driver instead warns that no interrupt is configured rather than simply failing. The drawback is that if an error occurs without the interrupt, we firstly would not be able to trace the issue, and secondly would not be able to attempt to recover from the issue, but this is better than failing immediately. Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://lore.kernel.org/r/20240429154853.9393-2-sbinding@opensource.cirrus.com
1 parent 6b844f0 commit 762eba7

1 file changed

Lines changed: 47 additions & 22 deletions

File tree

sound/pci/hda/cs35l41_hda.c

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,13 +1593,56 @@ static struct regmap_irq_chip cs35l41_regmap_irq_chip = {
15931593
.runtime_pm = true,
15941594
};
15951595

1596+
static void cs35l41_configure_interrupt(struct cs35l41_hda *cs35l41, int irq_pol)
1597+
{
1598+
int irq;
1599+
int ret;
1600+
int i;
1601+
1602+
if (!cs35l41->irq) {
1603+
dev_warn(cs35l41->dev, "No Interrupt Found");
1604+
goto err;
1605+
}
1606+
1607+
ret = devm_regmap_add_irq_chip(cs35l41->dev, cs35l41->regmap, cs35l41->irq,
1608+
IRQF_ONESHOT | IRQF_SHARED | irq_pol,
1609+
0, &cs35l41_regmap_irq_chip, &cs35l41->irq_data);
1610+
if (ret) {
1611+
dev_dbg(cs35l41->dev, "Unable to add IRQ Chip: %d.", ret);
1612+
goto err;
1613+
}
1614+
1615+
for (i = 0; i < ARRAY_SIZE(cs35l41_irqs); i++) {
1616+
irq = regmap_irq_get_virq(cs35l41->irq_data, cs35l41_irqs[i].irq);
1617+
if (irq < 0) {
1618+
ret = irq;
1619+
dev_dbg(cs35l41->dev, "Unable to map IRQ %s: %d.", cs35l41_irqs[i].name,
1620+
ret);
1621+
goto err;
1622+
}
1623+
1624+
ret = devm_request_threaded_irq(cs35l41->dev, irq, NULL,
1625+
cs35l41_irqs[i].handler,
1626+
IRQF_ONESHOT | IRQF_SHARED | irq_pol,
1627+
cs35l41_irqs[i].name, cs35l41);
1628+
if (ret) {
1629+
dev_dbg(cs35l41->dev, "Unable to allocate IRQ %s:: %d.",
1630+
cs35l41_irqs[i].name, ret);
1631+
goto err;
1632+
}
1633+
}
1634+
return;
1635+
err:
1636+
dev_warn(cs35l41->dev,
1637+
"IRQ Config Failed. Amp errors may not be recoverable without reboot.");
1638+
}
1639+
15961640
static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
15971641
{
15981642
struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
15991643
bool using_irq = false;
1600-
int irq, irq_pol;
1644+
int irq_pol;
16011645
int ret;
1602-
int i;
16031646

16041647
if (!cs35l41->hw_cfg.valid)
16051648
return -EINVAL;
@@ -1642,26 +1685,8 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
16421685

16431686
irq_pol = cs35l41_gpio_config(cs35l41->regmap, hw_cfg);
16441687

1645-
if (cs35l41->irq && using_irq) {
1646-
ret = devm_regmap_add_irq_chip(cs35l41->dev, cs35l41->regmap, cs35l41->irq,
1647-
IRQF_ONESHOT | IRQF_SHARED | irq_pol,
1648-
0, &cs35l41_regmap_irq_chip, &cs35l41->irq_data);
1649-
if (ret)
1650-
return ret;
1651-
1652-
for (i = 0; i < ARRAY_SIZE(cs35l41_irqs); i++) {
1653-
irq = regmap_irq_get_virq(cs35l41->irq_data, cs35l41_irqs[i].irq);
1654-
if (irq < 0)
1655-
return irq;
1656-
1657-
ret = devm_request_threaded_irq(cs35l41->dev, irq, NULL,
1658-
cs35l41_irqs[i].handler,
1659-
IRQF_ONESHOT | IRQF_SHARED | irq_pol,
1660-
cs35l41_irqs[i].name, cs35l41);
1661-
if (ret)
1662-
return ret;
1663-
}
1664-
}
1688+
if (using_irq)
1689+
cs35l41_configure_interrupt(cs35l41, irq_pol);
16651690

16661691
return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos);
16671692
}

0 commit comments

Comments
 (0)