NAUDINT interrupt line is provided by the TWL6030 codec to signal
externally events like headset plug/unplug, hook, power-up sequence
completion, etc.

Signed-off-by: Misael Lopez Cruz <x0052...@ti.com>
---
 sound/soc/codecs/twl6030.c |   70 ++++++++++++++++++++++++++++++++++++++++---
 sound/soc/codecs/twl6030.h |   14 +++++++++
 2 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/twl6030.c b/sound/soc/codecs/twl6030.c
index 8548442..56fe136 100644
--- a/sound/soc/codecs/twl6030.c
+++ b/sound/soc/codecs/twl6030.c
@@ -46,6 +46,7 @@
 struct twl6030_data {
        struct snd_soc_codec codec;
        int audpwron;
+       int naudint;
        int codec_powered;
        int pll;
        int non_lp;
@@ -61,7 +62,7 @@ static const u8 twl6030_reg[TWL6030_CACHEREGNUM] = {
        0x4B, /* TWL6030_ASICID (ro)    0x01    */
        0x00, /* TWL6030_ASICREV (ro)   0x02    */
        0x00, /* TWL6030_INTID          0x03    */
-       0x7B, /* TWL6030_INTMR          0x04    */
+       0x00, /* TWL6030_INTMR          0x04    */
        0x00, /* TWL6030_NCPCTRL        0x05    */
        0x00, /* TWL6030_LDOCTL         0x06    */
        0x00, /* TWL6030_HPPLLCTL       0x07    */
@@ -367,6 +368,39 @@ static int twl6030_power_mode_event(struct 
snd_soc_dapm_widget *w,
        return 0;
 }
 
+/* audio interrupt handler */
+static irqreturn_t twl6030_naudint_handler(int irq, void *data)
+{
+       struct snd_soc_codec *codec = data;
+       u8 intid;
+
+       twl_i2c_read_u8(TWL6030_MODULE_AUDIO, &intid, TWL6030_REG_INTID);
+
+       switch (intid) {
+       case TWL6030_THINT:
+               dev_alert(codec->dev, "die temp over-limit detection\n");
+               break;
+       case TWL6030_PLUGINT:
+       case TWL6030_UNPLUGINT:
+       case TWL6030_HOOKINT:
+               break;
+       case TWL6030_HFINT:
+               dev_alert(codec->dev, "hf drivers over current detection\n");
+               break;
+       case TWL6030_VIBINT:
+               dev_alert(codec->dev, "vib drivers over current detection\n");
+               break;
+       case TWL6030_READYINT:
+               dev_alert(codec->dev, "codec is ready\n");
+               break;
+       default:
+               dev_err(codec->dev, "unknown audio interrupt %d\n", intid);
+               break;
+       }
+
+       return IRQ_HANDLED;
+}
+
 /*
  * MICATT volume control:
  * from -6 to 0 dB in 6 dB steps
@@ -993,19 +1027,23 @@ static int __devinit twl6030_codec_probe(struct 
platform_device *pdev)
        struct twl_codec_data *twl_codec = pdev->dev.platform_data;
        struct snd_soc_codec *codec;
        struct twl6030_data *priv;
-       int audpwron;
+       int audpwron, naudint;
        int ret = 0;
 
        priv = kzalloc(sizeof(struct twl6030_data), GFP_KERNEL);
        if (priv == NULL)
                return -ENOMEM;
 
-       if (twl_codec)
+       if (twl_codec) {
                audpwron = twl_codec->audpwron_gpio;
-       else
+               naudint = twl_codec->naudint_irq;
+       } else {
                audpwron = -EINVAL;
+               naudint = 0;
+       }
 
        priv->audpwron = audpwron;
+       priv->naudint = naudint;
 
        codec = &priv->codec;
        codec->dev = &pdev->dev;
@@ -1043,13 +1081,28 @@ static int __devinit twl6030_codec_probe(struct 
platform_device *pdev)
                priv->codec_powered = 0;
        }
 
+       if (naudint) {
+               /* audio interrupt */
+               ret = request_threaded_irq(naudint, NULL,
+                               twl6030_naudint_handler,
+                               IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+                               "twl6030_codec", codec);
+               if (ret)
+                       goto gpio2_err;
+       } else {
+               dev_warn(codec->dev,
+                       "no naudint irq, audio interrupts disabled\n");
+               twl6030_write_reg_cache(codec, TWL6030_REG_INTMR,
+                                       TWL6030_ALLINT_MSK);
+       }
+
        /* init vio registers */
        twl6030_init_vio_regs(codec);
 
        /* power on device */
        ret = twl6030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        if (ret)
-               goto gpio2_err;
+               goto irq_err;
 
        ret = snd_soc_register_codec(codec);
        if (ret)
@@ -1068,6 +1121,9 @@ dai_err:
        twl6030_codec = NULL;
 reg_err:
        twl6030_set_bias_level(codec, SND_SOC_BIAS_OFF);
+irq_err:
+       if (naudint)
+               free_irq(naudint, codec);
 gpio2_err:
        if (gpio_is_valid(audpwron))
                gpio_free(audpwron);
@@ -1082,10 +1138,14 @@ static int __devexit twl6030_codec_remove(struct 
platform_device *pdev)
 {
        struct twl6030_data *priv = twl6030_codec->private_data;
        int audpwron = priv->audpwron;
+       int naudint = priv->naudint;
 
        if (gpio_is_valid(audpwron))
                gpio_free(audpwron);
 
+       if (naudint)
+               free_irq(naudint, twl6030_codec);
+
        snd_soc_unregister_dai(&twl6030_dai);
        snd_soc_unregister_codec(twl6030_codec);
 
diff --git a/sound/soc/codecs/twl6030.h b/sound/soc/codecs/twl6030.h
index 87f1e1e..786fd80 100644
--- a/sound/soc/codecs/twl6030.h
+++ b/sound/soc/codecs/twl6030.h
@@ -67,6 +67,20 @@
 #define TWL6030_VIOREGNUM              18
 #define TWL6030_VDDREGNUM              21
 
+/* INTID (0x03) fields */
+
+#define TWL6030_THINT                  0x01
+#define TWL6030_PLUGINT                        0x02
+#define TWL6030_UNPLUGINT              0x04
+#define TWL6030_HOOKINT                        0x08
+#define TWL6030_HFINT                  0x10
+#define TWL6030_VIBINT                 0x20
+#define TWL6030_READYINT               0x40
+
+/* INTMR (0x04) fields */
+
+#define TWL6030_ALLINT_MSK             0x7B
+
 /* NCPCTL (0x05) fields */
 
 #define TWL6030_NCPENA                 0x01
-- 
1.5.4.3
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to