diff options
Diffstat (limited to 'sound/soc/codecs/wm8962.c')
| -rw-r--r-- | sound/soc/codecs/wm8962.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 8e5f46691379..4fa5de873c8b 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
| @@ -1461,6 +1461,29 @@ static struct snd_soc_dai_driver wm8962_dai = { | |||
| 1461 | .symmetric_rates = 1, | 1461 | .symmetric_rates = 1, |
| 1462 | }; | 1462 | }; |
| 1463 | 1463 | ||
| 1464 | static irqreturn_t wm8962_irq(int irq, void *data) | ||
| 1465 | { | ||
| 1466 | struct snd_soc_codec *codec = data; | ||
| 1467 | int mask; | ||
| 1468 | int active; | ||
| 1469 | |||
| 1470 | mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); | ||
| 1471 | |||
| 1472 | active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); | ||
| 1473 | active &= ~mask; | ||
| 1474 | |||
| 1475 | if (active & WM8962_FIFOS_ERR_EINT) | ||
| 1476 | dev_err(codec->dev, "FIFO error\n"); | ||
| 1477 | |||
| 1478 | if (active & WM8962_TEMP_SHUT_EINT) | ||
| 1479 | dev_crit(codec->dev, "Thermal shutdown\n"); | ||
| 1480 | |||
| 1481 | /* Acknowledge the interrupts */ | ||
| 1482 | snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active); | ||
| 1483 | |||
| 1484 | return IRQ_HANDLED; | ||
| 1485 | } | ||
| 1486 | |||
| 1464 | #ifdef CONFIG_PM | 1487 | #ifdef CONFIG_PM |
| 1465 | static int wm8962_resume(struct snd_soc_codec *codec) | 1488 | static int wm8962_resume(struct snd_soc_codec *codec) |
| 1466 | { | 1489 | { |
| @@ -1632,7 +1655,9 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
| 1632 | int ret; | 1655 | int ret; |
| 1633 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 1656 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
| 1634 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); | 1657 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); |
| 1635 | int i; | 1658 | struct i2c_client *i2c = container_of(codec->dev, struct i2c_client, |
| 1659 | dev); | ||
| 1660 | int i, trigger, irq_pol; | ||
| 1636 | 1661 | ||
| 1637 | wm8962->codec = codec; | 1662 | wm8962->codec = codec; |
| 1638 | 1663 | ||
| @@ -1748,6 +1773,34 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
| 1748 | 1773 | ||
| 1749 | wm8962_init_beep(codec); | 1774 | wm8962_init_beep(codec); |
| 1750 | 1775 | ||
| 1776 | if (i2c->irq) { | ||
| 1777 | if (pdata && pdata->irq_active_low) { | ||
| 1778 | trigger = IRQF_TRIGGER_LOW; | ||
| 1779 | irq_pol = WM8962_IRQ_POL; | ||
| 1780 | } else { | ||
| 1781 | trigger = IRQF_TRIGGER_HIGH; | ||
| 1782 | irq_pol = 0; | ||
| 1783 | } | ||
| 1784 | |||
| 1785 | snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL, | ||
| 1786 | WM8962_IRQ_POL, irq_pol); | ||
| 1787 | |||
| 1788 | ret = request_threaded_irq(i2c->irq, NULL, wm8962_irq, | ||
| 1789 | trigger | IRQF_ONESHOT, | ||
| 1790 | "wm8962", codec); | ||
| 1791 | if (ret != 0) { | ||
| 1792 | dev_err(codec->dev, "Failed to request IRQ %d: %d\n", | ||
| 1793 | i2c->irq, ret); | ||
| 1794 | /* Non-fatal */ | ||
| 1795 | } else { | ||
| 1796 | /* Enable error reporting IRQs by default */ | ||
| 1797 | snd_soc_update_bits(codec, | ||
| 1798 | WM8962_INTERRUPT_STATUS_2_MASK, | ||
| 1799 | WM8962_TEMP_SHUT_EINT | | ||
| 1800 | WM8962_FIFOS_ERR_EINT, 0); | ||
| 1801 | } | ||
| 1802 | } | ||
| 1803 | |||
| 1751 | return 0; | 1804 | return 0; |
| 1752 | 1805 | ||
| 1753 | err_enable: | 1806 | err_enable: |
| @@ -1762,8 +1815,13 @@ err: | |||
| 1762 | static int wm8962_remove(struct snd_soc_codec *codec) | 1815 | static int wm8962_remove(struct snd_soc_codec *codec) |
| 1763 | { | 1816 | { |
| 1764 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 1817 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
| 1818 | struct i2c_client *i2c = container_of(codec->dev, struct i2c_client, | ||
| 1819 | dev); | ||
| 1765 | int i; | 1820 | int i; |
| 1766 | 1821 | ||
| 1822 | if (i2c->irq) | ||
| 1823 | free_irq(i2c->irq, codec); | ||
| 1824 | |||
| 1767 | wm8962_free_beep(codec); | 1825 | wm8962_free_beep(codec); |
| 1768 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) | 1826 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) |
| 1769 | regulator_unregister_notifier(wm8962->supplies[i].consumer, | 1827 | regulator_unregister_notifier(wm8962->supplies[i].consumer, |
