ASoC: WCD9310: Read microphone voltage twice for button interrupts

Doing two voltage readings when receiving a button press interrupt
ensures that a button was actually pressed.  Sometimes a headset
insertion or removal can trigger a button press detection, and this
patch makes sure that only true button presses cause button events
to be passed up to user space.

Signed-off-by: Brad Rubin <brubin@codeaurora.org>
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 56de124..f8a00c3 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -1925,11 +1925,12 @@
 }
 EXPORT_SYMBOL_GPL(tabla_hs_detect);
 
+#define TABLA_BUTTON_MARGIN_ERROR 4
 static irqreturn_t tabla_dce_handler(int irq, void *data)
 {
 	struct tabla_priv *priv = data;
 	struct snd_soc_codec *codec = priv->codec;
-	short bias_value;
+	short bias_value, bias_value2;
 
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
 	tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
@@ -1937,14 +1938,19 @@
 	bias_value = tabla_codec_read_dce_result(codec);
 	pr_debug("button press interrupt, bias value is %d\n", bias_value);
 
-	if (priv->button_jack)
-		snd_soc_jack_report(priv->button_jack, SND_JACK_BTN_0,
-			SND_JACK_BTN_0);
+	/* Do another DCE to make sure button voltage is the same */
+	bias_value2 = tabla_codec_measure_micbias_voltage(codec, 1);
+	pr_debug("button press part 2, bias value is %d\n", bias_value2);
 
-	priv->buttons_pressed |= SND_JACK_BTN_0;
-	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL,
-		0x09);
-	usleep_range(100000, 100000);
+	if (abs(bias_value - bias_value2) < TABLA_BUTTON_MARGIN_ERROR) {
+		if (priv->button_jack)
+			snd_soc_jack_report(priv->button_jack, SND_JACK_BTN_0,
+				SND_JACK_BTN_0);
+
+		priv->buttons_pressed |= SND_JACK_BTN_0;
+	}
+	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x09);
+	msleep(100);
 
 	return IRQ_HANDLED;
 }
@@ -1960,11 +1966,11 @@
 				SND_JACK_BTN_0);
 
 		priv->buttons_pressed &= ~SND_JACK_BTN_0;
-		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL,
-			0x08);
-		tabla_codec_start_hs_polling(codec);
 	}
 
+	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x08);
+	tabla_codec_start_hs_polling(codec);
+
 	return IRQ_HANDLED;
 }