Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

authored by

Stefan Binding and committed by
Takashi Iwai
762eba70 6b844f06

+47 -22
+47 -22
sound/pci/hda/cs35l41_hda.c
··· 1593 1593 .runtime_pm = true, 1594 1594 }; 1595 1595 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 + 1596 1640 static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41) 1597 1641 { 1598 1642 struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; 1599 1643 bool using_irq = false; 1600 - int irq, irq_pol; 1644 + int irq_pol; 1601 1645 int ret; 1602 - int i; 1603 1646 1604 1647 if (!cs35l41->hw_cfg.valid) 1605 1648 return -EINVAL; ··· 1685 1642 1686 1643 irq_pol = cs35l41_gpio_config(cs35l41->regmap, hw_cfg); 1687 1644 1688 - if (cs35l41->irq && using_irq) { 1689 - ret = devm_regmap_add_irq_chip(cs35l41->dev, cs35l41->regmap, cs35l41->irq, 1690 - IRQF_ONESHOT | IRQF_SHARED | irq_pol, 1691 - 0, &cs35l41_regmap_irq_chip, &cs35l41->irq_data); 1692 - if (ret) 1693 - return ret; 1694 - 1695 - for (i = 0; i < ARRAY_SIZE(cs35l41_irqs); i++) { 1696 - irq = regmap_irq_get_virq(cs35l41->irq_data, cs35l41_irqs[i].irq); 1697 - if (irq < 0) 1698 - return irq; 1699 - 1700 - ret = devm_request_threaded_irq(cs35l41->dev, irq, NULL, 1701 - cs35l41_irqs[i].handler, 1702 - IRQF_ONESHOT | IRQF_SHARED | irq_pol, 1703 - cs35l41_irqs[i].name, cs35l41); 1704 - if (ret) 1705 - return ret; 1706 - } 1707 - } 1645 + if (using_irq) 1646 + cs35l41_configure_interrupt(cs35l41, irq_pol); 1708 1647 1709 1648 return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos); 1710 1649 }