aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/wm8962.h2
-rw-r--r--sound/soc/codecs/wm8962.c60
2 files changed, 61 insertions, 1 deletions
diff --git a/include/sound/wm8962.h b/include/sound/wm8962.h
index f70258e3471c..cc32aff53222 100644
--- a/include/sound/wm8962.h
+++ b/include/sound/wm8962.h
@@ -17,6 +17,8 @@
17struct wm8962_pdata { 17struct wm8962_pdata {
18 u32 gpio_init[WM8962_MAX_GPIO]; 18 u32 gpio_init[WM8962_MAX_GPIO];
19 19
20 bool irq_active_low;
21
20 bool spk_mono; /* Speaker outputs tied together as mono */ 22 bool spk_mono; /* Speaker outputs tied together as mono */
21}; 23};
22 24
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
1464static 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
1465static int wm8962_resume(struct snd_soc_codec *codec) 1488static 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
1753err_enable: 1806err_enable:
@@ -1762,8 +1815,13 @@ err:
1762static int wm8962_remove(struct snd_soc_codec *codec) 1815static 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,