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 x0052729@ti.com --- sound/soc/codecs/twl6030.c | 78 +++++++++++++++++++++++++++++++++++++++++++- sound/soc/codecs/twl6030.h | 10 ++++++ 2 files changed, 87 insertions(+), 1 deletions(-)
diff --git a/sound/soc/codecs/twl6030.c b/sound/soc/codecs/twl6030.c index 032619d..5cf2099 100644 --- a/sound/soc/codecs/twl6030.c +++ b/sound/soc/codecs/twl6030.c @@ -47,6 +47,7 @@ struct twl6030_data { struct snd_soc_codec codec; int codec_powered; unsigned int sysclk; + struct work_struct audint_work; };
/* @@ -329,6 +330,58 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf) return 0; }
+/* audio interrupt handler */ +irqreturn_t twl6030_naudint_handler(int irq, void *data) +{ + struct snd_soc_codec *codec = data; + struct twl6030_data *priv = codec->private_data; + + schedule_work(&priv->audint_work); + + /* disable audint irq to let workqueue to execute */ + disable_irq_nosync(irq); + + return IRQ_HANDLED; +} + +void twl6030_naudint_work(struct work_struct *work) +{ + struct twl_codec_data *twl_codec; + struct snd_soc_codec *codec; + struct twl6030_data *priv; + u8 intid; + + priv = container_of(work, struct twl6030_data, audint_work); + codec = &priv->codec; + twl_codec = codec->control_data; + + 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; + } + + enable_irq(twl_codec->naudint_irq); +} + /* * MICATT volume control: * from -6 to 0 dB in 6 dB steps @@ -610,6 +663,7 @@ static int twl6030_set_bias_level(struct snd_soc_codec *codec, priv->codec_powered = 0; break; } + codec->bias_level = level;
return 0; @@ -954,8 +1008,15 @@ static int __devinit twl6030_codec_probe(struct platform_device *pdev) struct twl6030_data *priv; struct snd_soc_codec *codec; int audpwron_gpio = twl_codec->audpwron_gpio; + int naudint_irq = twl_codec->naudint_irq; int ret = 0;
+ /* prerequisites */ + if (!naudint_irq) { + dev_err(&pdev->dev, "no audio interrupt irq supplied\n"); + return -EINVAL; + } + priv = kzalloc(sizeof(struct twl6030_data), GFP_KERNEL); if (priv == NULL) return -ENOMEM; @@ -998,6 +1059,17 @@ static int __devinit twl6030_codec_probe(struct platform_device *pdev) priv->codec_powered = 0; }
+ /* audio interrupt */ + INIT_WORK(&priv->audint_work, twl6030_naudint_work); + + ret = request_irq(naudint_irq, + twl6030_naudint_handler, + IRQF_TRIGGER_LOW | IRQF_DISABLED, + "twl6030-codec", + codec); + if (ret) + goto gpio2_err; + /* init vio registers */ twl6030_init_vio_regs(codec);
@@ -1006,7 +1078,7 @@ static int __devinit twl6030_codec_probe(struct platform_device *pdev)
ret = snd_soc_register_codec(codec); if (ret) - goto gpio2_err; + goto reg_err;
twl6030_codec = codec;
@@ -1019,6 +1091,8 @@ static int __devinit twl6030_codec_probe(struct platform_device *pdev) dai_err: snd_soc_unregister_codec(codec); twl6030_codec = NULL; +reg_err: + free_irq(naudint_irq, twl_codec); gpio2_err: if (gpio_is_valid(audpwron_gpio)) gpio_free(audpwron_gpio); @@ -1036,6 +1110,8 @@ static int __devexit twl6030_codec_remove(struct platform_device *pdev) if (gpio_is_valid(twl_codec->audpwron_gpio)) gpio_free(twl_codec->audpwron_gpio);
+ free_irq(twl_codec->naudint_irq, 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 15d3e1b..8a106f2 100644 --- a/sound/soc/codecs/twl6030.h +++ b/sound/soc/codecs/twl6030.h @@ -67,6 +67,16 @@ #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 + /* NCPCTL (0x05) fields */
#define TWL6030_NCPENA 0x01