diff options
author | Misael Lopez Cruz <misael.lopez@ti.com> | 2011-12-19 22:03:08 -0600 |
---|---|---|
committer | Ziyann <jaraidaniel@gmail.com> | 2014-12-05 22:09:24 +0100 |
commit | 5fa74de61a8868801a342fb10b3eae70b94d2c79 (patch) | |
tree | 712a046531f8a92f63181ef33e7aaec2f75ea0d0 /sound | |
parent | ff8a9dbff9551fa8e9ef3ff44e27bbaff2423457 (diff) | |
download | kernel_samsung_tuna-5fa74de61a8868801a342fb10b3eae70b94d2c79.tar.gz kernel_samsung_tuna-5fa74de61a8868801a342fb10b3eae70b94d2c79.tar.bz2 kernel_samsung_tuna-5fa74de61a8868801a342fb10b3eae70b94d2c79.zip |
ASoC: twl6040: Handle handsfree overcurrent events
TWL6040 has a short circuit detection mechanism that report events
when the current exceeds 2.2A in its handsfree output stage. Upon
detection of handsfree overcurrent, the suggested action is to
disable handsfree drivers to prevent damage. Additionally, when
this event occurs it's reported to Android userspace layers through
an uEvent associated with the TWL6040 MFD.
Change-Id: Iea94c55286a9adb158caac10f7a15fae73827792
Signed-off-by: Misael Lopez Cruz <misael.lopez@ti.com>
Signed-off-by: Chris Kelly <c-kelly@ti.com>
Conflicts:
sound/soc/codecs/twl6040.c
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/twl6040.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 0112121f7bc..3cb4e1b38af 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -947,7 +947,7 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data) struct snd_soc_codec *codec = data; struct twl6040 *twl6040 = codec->control_data; struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - u8 intid; + u8 intid, val; intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID); @@ -957,6 +957,24 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data) msecs_to_jiffies(200)); } + if (intid & TWL6040_HFINT) { + val = twl6040_read_reg_volatile(codec, TWL6040_REG_STATUS); + if (val & TWL6040_HFLOCDET) + dev_err(codec->dev, "Left Handsfree overcurrent\n"); + if (val & TWL6040_HFROCDET) + dev_err(codec->dev, "Right Handsfree overcurrent\n"); + + val = twl6040_read_reg_cache(codec, TWL6040_REG_HFLCTL); + twl6040_write(codec, TWL6040_REG_HFLCTL, + val & ~TWL6040_HFDRVENAL); + + val = twl6040_read_reg_cache(codec, TWL6040_REG_HFRCTL); + twl6040_write(codec, TWL6040_REG_HFRCTL, + val & ~TWL6040_HFDRVENAR); + + twl6040_report_event(twl6040, TWL6040_HFOC_EVENT); + } + return IRQ_HANDLED; } @@ -1788,6 +1806,14 @@ static int twl6040_probe(struct snd_soc_codec *codec) goto irq_err; } + ret = twl6040_request_irq(codec->control_data, TWL6040_IRQ_HF, + twl6040_audio_handler, 0, + "twl6040_irq_hf", codec); + if (ret) { + dev_err(codec->dev, "HF IRQ request failed: %d\n", ret); + goto hfirq_err; + } + /* init vio registers */ twl6040_init_vio_regs(codec); @@ -1803,6 +1829,8 @@ static int twl6040_probe(struct snd_soc_codec *codec) return 0; bias_err: + twl6040_free_irq(codec->control_data, TWL6040_IRQ_HF, codec); +hfirq_err: twl6040_free_irq(codec->control_data, TWL6040_IRQ_PLUG, codec); irq_err: wake_lock_destroy(&priv->wake_lock); @@ -1824,6 +1852,7 @@ static int twl6040_remove(struct snd_soc_codec *codec) twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); twl6040_free_irq(codec->control_data, TWL6040_IRQ_PLUG, codec); + twl6040_free_irq(codec->control_data, TWL6040_IRQ_HF, codec); wake_lock_destroy(&priv->wake_lock); destroy_workqueue(priv->workqueue); destroy_workqueue(priv->hf_workqueue); |