ASoC: WCD9304: Enable GPIO based headset detection

WCD9304 supports mechanical switch / GPIO based headset detection.
Enable mechanical detection of plug insertion / removal and plug type
determination to determine if the inserted accessory is a headphone
or headset.

Change-Id: Ib76d31f3c14fb91ed9bf1d39237d8910a0e2fc57
Signed-off-by: Bhalchandra Gajare <gajare@codeaurora.org>
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index 04b0fb0..a2c6f5f 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -55,7 +55,24 @@
 
 static struct snd_soc_jack hs_jack;
 static struct snd_soc_jack button_jack;
-static void *sitar_mbhc_cal;
+
+static int msm8930_enable_codec_ext_clk(
+		struct snd_soc_codec *codec, int enable,
+		bool dapm);
+
+static struct sitar_mbhc_config mbhc_cfg = {
+	.headset_jack = &hs_jack,
+	.button_jack = &button_jack,
+	.read_fw_bin = false,
+	.calibration = NULL,
+	.micbias = SITAR_MICBIAS2,
+	.mclk_cb_fn = msm8930_enable_codec_ext_clk,
+	.mclk_rate = SITAR_EXT_CLK_RATE,
+	.gpio = 0,
+	.gpio_irq = 0,
+	.gpio_level_insert = 1,
+};
+
 
 static void msm8930_ext_control(struct snd_soc_codec *codec)
 {
@@ -102,8 +119,9 @@
 	return 0;
 }
 
-int msm8930_enable_codec_ext_clk(
-		struct snd_soc_codec *codec, int enable)
+static int msm8930_enable_codec_ext_clk(
+		struct snd_soc_codec *codec, int enable,
+		bool dapm)
 {
 	pr_debug("%s: enable = %d\n", __func__, enable);
 	if (enable) {
@@ -115,7 +133,7 @@
 		if (codec_clk) {
 			clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
 			clk_prepare_enable(codec_clk);
-			sitar_mclk_enable(codec, 1);
+			sitar_mclk_enable(codec, 1, dapm);
 		} else {
 			pr_err("%s: Error setting Sitar MCLK\n", __func__);
 			clk_users--;
@@ -129,7 +147,7 @@
 		if (!clk_users) {
 			pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
-			sitar_mclk_enable(codec, 0);
+			sitar_mclk_enable(codec, 0, dapm);
 			clk_disable_unprepare(codec_clk);
 		}
 	}
@@ -143,9 +161,9 @@
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		return msm8930_enable_codec_ext_clk(w->codec, 1);
+		return msm8930_enable_codec_ext_clk(w->codec, 1, true);
 	case SND_SOC_DAPM_POST_PMD:
-		return msm8930_enable_codec_ext_clk(w->codec, 0);
+		return msm8930_enable_codec_ext_clk(w->codec, 0, true);
 	}
 	return 0;
 }
@@ -520,6 +538,10 @@
 	}
 	codec_clk = clk_get(cpu_dai->dev, "osr_clk");
 
+	mbhc_cfg.gpio = 37;
+	mbhc_cfg.gpio_irq = gpio_to_irq(mbhc_cfg.gpio);
+	sitar_hs_detect(codec, &mbhc_cfg);
+
 	return 0;
 }
 
@@ -978,8 +1000,8 @@
 		pr_err("%s: Not the right machine type\n", __func__);
 		return -ENODEV ;
 	}
-	sitar_mbhc_cal = def_sitar_mbhc_cal();
-	if (!sitar_mbhc_cal) {
+	mbhc_cfg.calibration = def_sitar_mbhc_cal();
+	if (!mbhc_cfg.calibration) {
 		pr_err("Calibration data allocation failed\n");
 		return -ENOMEM;
 	}
@@ -987,7 +1009,7 @@
 	msm8930_snd_device = platform_device_alloc("soc-audio", 0);
 	if (!msm8930_snd_device) {
 		pr_err("Platform device allocation failed\n");
-		kfree(sitar_mbhc_cal);
+		kfree(mbhc_cfg.calibration);
 		return -ENOMEM;
 	}
 
@@ -995,7 +1017,7 @@
 	ret = platform_device_add(msm8930_snd_device);
 	if (ret) {
 		platform_device_put(msm8930_snd_device);
-		kfree(sitar_mbhc_cal);
+		kfree(mbhc_cfg.calibration);
 		return ret;
 	}
 
@@ -1018,7 +1040,7 @@
 	}
 	msm8930_free_headset_mic_gpios();
 	platform_device_unregister(msm8930_snd_device);
-	kfree(sitar_mbhc_cal);
+	kfree(mbhc_cfg.calibration);
 }
 module_exit(msm8930_audio_exit);