aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8962.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-09-28 19:01:20 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-09-29 03:32:36 -0400
commit45e655047fd64ba7eb52d14ef5acc41763c8ea34 (patch)
tree7c1c32a3574a6473036c2701bb3be5ff3f83e51e /sound/soc/codecs/wm8962.c
parentea738bade2111568a4e6b4b454e2dcd028bc17f6 (diff)
ASoC: Initial WM8962 IRQ support
Provide an initial hookup for interrupts on the WM8962. Currently we simply report error status via log messages if an IRQ is provided for the device. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/codecs/wm8962.c')
-rw-r--r--sound/soc/codecs/wm8962.c60
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
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,