aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMisael Lopez Cruz <misael.lopez@ti.com>2011-12-19 22:03:08 -0600
committerZiyann <jaraidaniel@gmail.com>2014-12-05 22:09:24 +0100
commit5fa74de61a8868801a342fb10b3eae70b94d2c79 (patch)
tree712a046531f8a92f63181ef33e7aaec2f75ea0d0 /sound
parentff8a9dbff9551fa8e9ef3ff44e27bbaff2423457 (diff)
downloadkernel_samsung_tuna-5fa74de61a8868801a342fb10b3eae70b94d2c79.zip
kernel_samsung_tuna-5fa74de61a8868801a342fb10b3eae70b94d2c79.tar.gz
kernel_samsung_tuna-5fa74de61a8868801a342fb10b3eae70b94d2c79.tar.bz2
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.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 0112121..3cb4e1b 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);