All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] add support for jack detection in mid-x86
@ 2011-02-09 16:14 Koul, Vinod
  2011-02-09 16:14 ` [PATCH 1/3] ASoC: sn95031: Add jack support in the codec Koul, Vinod
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Koul, Vinod @ 2011-02-09 16:14 UTC (permalink / raw)
  To: alsa-devel; +Cc: Vinod Koul, broonie, lrg

From: Vinod Koul <vinod.koul@intel.com>

This patch set adds support for jack detection in mid-x6 machine and TI sn95031
codec drivers. This also adds support to read mic bias values thru ADC 

This version fixes namespace issue in patch1, and removes gpio bits in machine
driver pending gpiolib support, which will be added separately

Vinod Koul (3):
  ASoC: sn95031: Add jack support in the codec
  ASoC: mfld_machine: Add support for jack detection
  ASoC: sn95031: Add support for reading mic bias

 sound/soc/codecs/sn95031.c       |  183 +++++++++++++++++++++++++++++++++-
 sound/soc/codecs/sn95031.h       |   33 ++++++
 sound/soc/mid-x86/mfld_machine.c |  203 +++++++++++++++++++++++++++++++++-----
 3 files changed, 388 insertions(+), 31 deletions(-)

-- 
1.7.2.3

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] ASoC: sn95031: Add jack support in the codec
  2011-02-09 16:14 [PATCH 0/3] add support for jack detection in mid-x86 Koul, Vinod
@ 2011-02-09 16:14 ` Koul, Vinod
  2011-02-09 16:14 ` [PATCH 2/3] ASoC: mfld_machine: Add support for jack detection Koul, Vinod
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Koul, Vinod @ 2011-02-09 16:14 UTC (permalink / raw)
  To: alsa-devel; +Cc: Vinod Koul, broonie, Harsha Priya, lrg

From: Vinod Koul <vinod.koul@intel.com>

This patch adds support for jack detection and reporting in the codec
It however is not fully functional as it doesn't measure adc to figure
out what got inserted which will be added later

Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Harsha Priya <priya.harsha@intel.com>
---
 sound/soc/codecs/sn95031.c |   56 ++++++++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/sn95031.h |    9 +++++++
 2 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index 40e285d..b49d790 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -34,6 +34,7 @@
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
+#include <sound/jack.h>
 #include "sn95031.h"
 
 #define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100)
@@ -649,6 +650,61 @@ struct snd_soc_dai_driver sn95031_dais[] = {
 },
 };
 
+static inline void sn95031_disable_jack_btn(struct snd_soc_codec *codec)
+{
+	snd_soc_write(codec, SN95031_BTNCTRL2, 0x00);
+}
+
+static inline void sn95031_enable_jack_btn(struct snd_soc_codec *codec)
+{
+	snd_soc_write(codec, SN95031_BTNCTRL1, 0x77);
+	snd_soc_write(codec, SN95031_BTNCTRL2, 0x01);
+}
+
+static int sn95031_get_headset_state(struct snd_soc_jack *mfld_jack)
+{
+	/* Defaulting to HEADSET for now.
+	 * will change after adding soc-jack detection apis */
+	int jack_type = SND_JACK_HEADSET;
+
+	pr_debug("jack type detected = %d\n", jack_type);
+	if (jack_type == SND_JACK_HEADSET)
+		sn95031_enable_jack_btn(mfld_jack->codec);
+	return jack_type;
+}
+
+void sn95031_jack_detection(struct mfld_jack_data *jack_data)
+{
+	unsigned int status;
+	unsigned int mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_HEADSET;
+
+	pr_debug("interrupt id read in sram = 0x%x\n", jack_data->intr_id);
+	if (jack_data->intr_id & 0x1) {
+		pr_debug("short_push detected\n");
+		status = SND_JACK_HEADSET | SND_JACK_BTN_0;
+	} else if (jack_data->intr_id & 0x2) {
+		pr_debug("long_push detected\n");
+		status = SND_JACK_HEADSET | SND_JACK_BTN_1;
+	} else if (jack_data->intr_id & 0x4) {
+		pr_debug("headset or headphones inserted\n");
+		status = sn95031_get_headset_state(jack_data->mfld_jack);
+	} else if (jack_data->intr_id & 0x8) {
+		pr_debug("headset or headphones removed\n");
+		status = 0;
+		sn95031_disable_jack_btn(jack_data->mfld_jack->codec);
+	} else {
+		pr_err("unidentified interrupt\n");
+		return;
+	}
+
+	snd_soc_jack_report(jack_data->mfld_jack, status, mask);
+	/*button pressed and released so we send explicit button release */
+	if ((status & SND_JACK_BTN_0) | (status & SND_JACK_BTN_1))
+		snd_soc_jack_report(jack_data->mfld_jack,
+				SND_JACK_HEADSET, mask);
+}
+EXPORT_SYMBOL_GPL(sn95031_jack_detection);
+
 /* codec registration */
 static int sn95031_codec_probe(struct snd_soc_codec *codec)
 {
diff --git a/sound/soc/codecs/sn95031.h b/sound/soc/codecs/sn95031.h
index e2b17d9..2dbae61 100644
--- a/sound/soc/codecs/sn95031.h
+++ b/sound/soc/codecs/sn95031.h
@@ -96,4 +96,13 @@
 #define SN95031_SSR5			0x384
 #define SN95031_SSR6			0x385
 
+#define SN95031_AUDIO_GPIO_CTRL 0x070
+struct mfld_jack_data {
+	int intr_id;
+	int micbias_vol;
+	struct snd_soc_jack *mfld_jack;
+};
+
+extern void sn95031_jack_detection(struct mfld_jack_data *jack_data);
+
 #endif
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] ASoC: mfld_machine: Add support for jack detection
  2011-02-09 16:14 [PATCH 0/3] add support for jack detection in mid-x86 Koul, Vinod
  2011-02-09 16:14 ` [PATCH 1/3] ASoC: sn95031: Add jack support in the codec Koul, Vinod
@ 2011-02-09 16:14 ` Koul, Vinod
  2011-02-09 16:14 ` [PATCH 3/3] ASoC: sn95031: Add support for reading mic bias Koul, Vinod
  2011-02-09 21:51 ` [PATCH 0/3] add support for jack detection in mid-x86 Liam Girdwood
  3 siblings, 0 replies; 7+ messages in thread
From: Koul, Vinod @ 2011-02-09 16:14 UTC (permalink / raw)
  To: alsa-devel; +Cc: Vinod Koul, broonie, Harsha Priya, lrg

From: Vinod Koul <vinod.koul@intel.com>

This patch adds support for registering jack interupt
and registering jack with core

Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Harsha Priya <priya.harsha@intel.com>
---
 sound/soc/mid-x86/mfld_machine.c |  203 +++++++++++++++++++++++++++++++++-----
 1 files changed, 176 insertions(+), 27 deletions(-)

diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
index 7925851..45a0067 100644
--- a/sound/soc/mid-x86/mfld_machine.c
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -27,18 +27,53 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/jack.h>
 #include "../codecs/sn95031.h"
 
 #define MID_MONO 1
 #define MID_STEREO 2
 #define MID_MAX_CAP 5
+#define MFLD_JACK_INSERT 0x04
+
+enum soc_mic_bias_zones {
+	MFLD_MV_START = 0,
+	/* mic bias volutage range for Headphones*/
+	MFLD_MV_HP = 400,
+	/* mic bias volutage range for American Headset*/
+	MFLD_MV_AM_HS = 650,
+	/* mic bias volutage range for Headset*/
+	MFLD_MV_HS = 2000,
+	MFLD_MV_UNDEFINED,
+};
 
 static unsigned int	hs_switch;
 static unsigned int	lo_dac;
 
+struct mfld_mc_private {
+	struct platform_device *socdev;
+	void __iomem *int_base;
+	struct snd_soc_codec *codec;
+	u8 interrupt_status;
+};
+
+struct snd_soc_jack mfld_jack;
+
+/*Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin mfld_jack_pins[] = {
+	{
+		.pin = "Headphones",
+		.mask = SND_JACK_HEADPHONE,
+	},
+	{
+		.pin = "AMIC1",
+		.mask = SND_JACK_MICROPHONE,
+	},
+};
+
 /* sound card controls */
 static const char *headset_switch_text[] = {"Earpiece", "Headset"};
 
@@ -67,13 +102,11 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol,
 
 	if (ucontrol->value.integer.value[0]) {
 		pr_debug("hs_set HS path\n");
-		snd_soc_dapm_enable_pin(&codec->dapm, "HPOUTL");
-		snd_soc_dapm_enable_pin(&codec->dapm, "HPOUTR");
+		snd_soc_dapm_enable_pin(&codec->dapm, "Headphones");
 		snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
 	} else {
 		pr_debug("hs_set EP path\n");
-		snd_soc_dapm_disable_pin(&codec->dapm, "HPOUTL");
-		snd_soc_dapm_disable_pin(&codec->dapm, "HPOUTR");
+		snd_soc_dapm_disable_pin(&codec->dapm, "Headphones");
 		snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT");
 	}
 	snd_soc_dapm_sync(&codec->dapm);
@@ -91,12 +124,10 @@ static void lo_enable_out_pins(struct snd_soc_codec *codec)
 	snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT");
 	snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT");
 	if (hs_switch) {
-		snd_soc_dapm_enable_pin(&codec->dapm, "HPOUTL");
-		snd_soc_dapm_enable_pin(&codec->dapm, "HPOUTR");
+		snd_soc_dapm_enable_pin(&codec->dapm, "Headphones");
 		snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
 	} else {
-		snd_soc_dapm_disable_pin(&codec->dapm, "HPOUTL");
-		snd_soc_dapm_disable_pin(&codec->dapm, "HPOUTR");
+		snd_soc_dapm_disable_pin(&codec->dapm, "Headphones");
 		snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT");
 	}
 }
@@ -130,8 +161,7 @@ static int lo_set_switch(struct snd_kcontrol *kcontrol,
 
 	case 1:
 		pr_debug("set hs  path\n");
-		snd_soc_dapm_disable_pin(&codec->dapm, "HPOUTL");
-		snd_soc_dapm_disable_pin(&codec->dapm, "HPOUTR");
+		snd_soc_dapm_disable_pin(&codec->dapm, "Headphones");
 		snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
 		snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22);
 		break;
@@ -162,12 +192,45 @@ static const struct snd_kcontrol_new mfld_snd_controls[] = {
 			lo_get_switch, lo_set_switch),
 };
 
+static const struct snd_soc_dapm_widget mfld_widgets[] = {
+	SND_SOC_DAPM_HP("Headphones", NULL),
+	SND_SOC_DAPM_MIC("Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route mfld_map[] = {
+	{"Headphones", NULL, "HPOUTR"},
+	{"Headphones", NULL, "HPOUTL"},
+	{"Mic", NULL, "AMIC1"},
+};
+
+static void mfld_jack_check(unsigned int intr_status)
+{
+	struct mfld_jack_data jack_data;
+
+	jack_data.mfld_jack = &mfld_jack;
+	jack_data.intr_id = intr_status;
+
+	sn95031_jack_detection(&jack_data);
+	/* TODO: add american headset detection post gpiolib support */
+}
+
 static int mfld_init(struct snd_soc_pcm_runtime *runtime)
 {
 	struct snd_soc_codec *codec = runtime->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret_val;
 
+	/* Add jack sense widgets */
+	snd_soc_dapm_new_controls(dapm, mfld_widgets, ARRAY_SIZE(mfld_widgets));
+
+	/* Set up the map */
+	snd_soc_dapm_add_routes(dapm, mfld_map, ARRAY_SIZE(mfld_map));
+
+	/* always connected */
+	snd_soc_dapm_enable_pin(dapm, "Headphones");
+	snd_soc_dapm_enable_pin(dapm, "Mic");
+	snd_soc_dapm_sync(dapm);
+
 	ret_val = snd_soc_add_controls(codec, mfld_snd_controls,
 				ARRAY_SIZE(mfld_snd_controls));
 	if (ret_val) {
@@ -175,8 +238,7 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
 		return ret_val;
 	}
 	/* default is earpiece pin, userspace sets it explcitly */
-	snd_soc_dapm_disable_pin(dapm, "HPOUTL");
-	snd_soc_dapm_disable_pin(dapm, "HPOUTR");
+	snd_soc_dapm_disable_pin(dapm, "Headphones");
 	/* default is lineout NC, userspace sets it explcitly */
 	snd_soc_dapm_disable_pin(dapm, "LINEOUTL");
 	snd_soc_dapm_disable_pin(dapm, "LINEOUTR");
@@ -185,7 +247,29 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
 	/* we dont use linein in this so set to NC */
 	snd_soc_dapm_disable_pin(dapm, "LINEINL");
 	snd_soc_dapm_disable_pin(dapm, "LINEINR");
-	return snd_soc_dapm_sync(dapm);
+	snd_soc_dapm_sync(dapm);
+
+	/* Headset and button jack detection */
+	ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack",
+			SND_JACK_HEADSET | SND_JACK_BTN_0 |
+			SND_JACK_BTN_1, &mfld_jack);
+	if (ret_val) {
+		pr_err("jack creation failed\n");
+		return ret_val;
+	}
+
+	ret_val = snd_soc_jack_add_pins(&mfld_jack,
+			ARRAY_SIZE(mfld_jack_pins), mfld_jack_pins);
+	if (ret_val) {
+		pr_err("adding jack pins failed\n");
+		return ret_val;
+	}
+
+	/* we want to check if anything is inserted at boot,
+	 * so send a fake event to codec and it will read adc
+	 * to find if anything is there or not */
+	mfld_jack_check(MFLD_JACK_INSERT);
+	return ret_val;
 }
 
 struct snd_soc_dai_link mfld_msic_dailink[] = {
@@ -234,37 +318,102 @@ static struct snd_soc_card snd_soc_card_mfld = {
 	.num_links = ARRAY_SIZE(mfld_msic_dailink),
 };
 
+static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev)
+{
+	struct mfld_mc_private *mc_private = (struct mfld_mc_private *) dev;
+
+	memcpy_fromio(&mc_private->interrupt_status,
+			((void *)(mc_private->int_base)),
+			sizeof(u8));
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t snd_mfld_jack_detection(int irq, void *data)
+{
+	struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data;
+
+	if (mfld_jack.codec == NULL)
+		return IRQ_HANDLED;
+	mfld_jack_check(mc_drv_ctx->interrupt_status);
+
+	return IRQ_HANDLED;
+}
+
 static int __devinit snd_mfld_mc_probe(struct platform_device *pdev)
 {
-	struct platform_device *socdev;
-	int ret_val = 0;
+	int ret_val = 0, irq;
+	struct mfld_mc_private *mc_drv_ctx;
+	struct resource *irq_mem;
 
 	pr_debug("snd_mfld_mc_probe called\n");
 
-	socdev =  platform_device_alloc("soc-audio", -1);
-	if (!socdev) {
-		pr_err("soc-audio device allocation failed\n");
+	/* retrive the irq number */
+	irq = platform_get_irq(pdev, 0);
+
+	/* audio interrupt base of SRAM location where
+	 * interrupts are stored by System FW */
+	mc_drv_ctx = kzalloc(sizeof(*mc_drv_ctx), GFP_ATOMIC);
+	if (!mc_drv_ctx) {
+		pr_err("allocation failed\n");
 		return -ENOMEM;
 	}
-	platform_set_drvdata(socdev, &snd_soc_card_mfld);
-	ret_val = platform_device_add(socdev);
+
+	irq_mem = platform_get_resource_byname(
+				pdev, IORESOURCE_MEM, "IRQ_BASE");
+	if (!irq_mem) {
+		pr_err("no mem resource given\n");
+		ret_val = -ENODEV;
+		goto unalloc;
+	}
+	mc_drv_ctx->int_base = ioremap_nocache(irq_mem->start,
+					resource_size(irq_mem));
+	if (!mc_drv_ctx->int_base) {
+		pr_err("Mapping of cache failed\n");
+		ret_val = -ENOMEM;
+		goto unalloc;
+	}
+	/* register for interrupt */
+	ret_val = request_threaded_irq(irq, snd_mfld_jack_intr_handler,
+			snd_mfld_jack_detection,
+			IRQF_SHARED, pdev->dev.driver->name, mc_drv_ctx);
+	if (ret_val) {
+		pr_err("cannot register IRQ\n");
+		goto unalloc;
+	}
+	/* create soc device */
+	mc_drv_ctx->socdev = platform_device_alloc("soc-audio", -1);
+	if (!mc_drv_ctx->socdev) {
+		pr_err("soc-audio device allocation failed\n");
+		ret_val = -ENOMEM;
+		goto freeirq;
+	}
+	platform_set_drvdata(mc_drv_ctx->socdev, &snd_soc_card_mfld);
+	ret_val = platform_device_add(mc_drv_ctx->socdev);
 	if (ret_val) {
 		pr_err("Unable to add soc-audio device, err %d\n", ret_val);
-		platform_device_put(socdev);
+		goto unregister;
 	}
-
-	platform_set_drvdata(pdev, socdev);
-
+	platform_set_drvdata(pdev, mc_drv_ctx);
 	pr_debug("successfully exited probe\n");
 	return ret_val;
+
+unregister:
+	platform_device_put(mc_drv_ctx->socdev);
+freeirq:
+	free_irq(irq, mc_drv_ctx);
+unalloc:
+	kfree(mc_drv_ctx);
+	return ret_val;
 }
 
 static int __devexit snd_mfld_mc_remove(struct platform_device *pdev)
 {
-	struct platform_device *socdev =  platform_get_drvdata(pdev);
-	pr_debug("snd_mfld_mc_remove called\n");
+	struct mfld_mc_private *mc_drv_ctx = platform_get_drvdata(pdev);
 
-	platform_device_unregister(socdev);
+	pr_debug("snd_mfld_mc_remove called\n");
+	free_irq(platform_get_irq(pdev, 0), mc_drv_ctx);
+	platform_device_unregister(mc_drv_ctx->socdev);
+	kfree(mc_drv_ctx);
 	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] ASoC: sn95031: Add support for reading mic bias
  2011-02-09 16:14 [PATCH 0/3] add support for jack detection in mid-x86 Koul, Vinod
  2011-02-09 16:14 ` [PATCH 1/3] ASoC: sn95031: Add jack support in the codec Koul, Vinod
  2011-02-09 16:14 ` [PATCH 2/3] ASoC: mfld_machine: Add support for jack detection Koul, Vinod
@ 2011-02-09 16:14 ` Koul, Vinod
  2011-02-09 21:51 ` [PATCH 0/3] add support for jack detection in mid-x86 Liam Girdwood
  3 siblings, 0 replies; 7+ messages in thread
From: Koul, Vinod @ 2011-02-09 16:14 UTC (permalink / raw)
  To: alsa-devel; +Cc: Vinod Koul, broonie, Harsha Priya, lrg

From: Vinod Koul <vinod.koul@intel.com>

This patch adds support to read the mic bias voltage
when a jack is inserted. It uses ADC to measure.

Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Harsha Priya <priya.harsha@intel.com>
---
 sound/soc/codecs/sn95031.c |  127 ++++++++++++++++++++++++++++++++++++++++++--
 sound/soc/codecs/sn95031.h |   24 ++++++++
 2 files changed, 147 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index b49d790..4cc0017 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -40,12 +40,129 @@
 #define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100)
 #define SN95031_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
 
+/* adc helper functions */
+
+/* enables mic bias voltage */
+static void sn95031_enable_mic_bias(struct snd_soc_codec *codec)
+{
+	snd_soc_write(codec, SN95031_VAUD, BIT(2)|BIT(1)|BIT(0));
+	snd_soc_update_bits(codec, SN95031_MICBIAS, BIT(2), BIT(2));
+}
+
+/* Enable/Disable the ADC depending on the argument */
+static void configure_adc(struct snd_soc_codec *sn95031_codec, int val)
+{
+	int value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1);
+
+	if (val) {
+		/* Enable and start the ADC */
+		value |= (SN95031_ADC_ENBL | SN95031_ADC_START);
+		value &= (~SN95031_ADC_NO_LOOP);
+	} else {
+		/* Just stop the ADC */
+		value &= (~SN95031_ADC_START);
+	}
+	snd_soc_write(sn95031_codec, SN95031_ADC1CNTL1, value);
+}
+
 /*
- * todo:
- * capture paths
- * jack detection
- * PM functions
+ * finds an empty channel for conversion
+ * If the ADC is not enabled then start using 0th channel
+ * itself. Otherwise find an empty channel by looking for a
+ * channel in which the stopbit is set to 1. returns the index
+ * of the first free channel if succeeds or an error code.
+ *
+ * Context: can sleep
+ *
  */
+static int find_free_channel(struct snd_soc_codec *sn95031_codec)
+{
+	int ret = 0, i, value;
+
+	/* check whether ADC is enabled */
+	value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1);
+
+	if ((value & SN95031_ADC_ENBL) == 0)
+		return 0;
+
+	/* ADC is already enabled; Looking for an empty channel */
+	for (i = 0; i <	SN95031_ADC_CHANLS_MAX; i++) {
+		value = snd_soc_read(sn95031_codec,
+				SN95031_ADC_CHNL_START_ADDR + i);
+		if (value & SN95031_STOPBIT_MASK) {
+			ret = i;
+			break;
+		}
+	}
+	return (ret > SN95031_ADC_LOOP_MAX) ? (-EINVAL) : ret;
+}
+
+/* Initialize the ADC for reading micbias values. Can sleep. */
+static int sn95031_initialize_adc(struct snd_soc_codec *sn95031_codec)
+{
+	int base_addr, chnl_addr;
+	int value;
+	static int channel_index;
+
+	/* Index of the first channel in which the stop bit is set */
+	channel_index = find_free_channel(sn95031_codec);
+	if (channel_index < 0) {
+		pr_err("No free ADC channels");
+		return channel_index;
+	}
+
+	base_addr = SN95031_ADC_CHNL_START_ADDR + channel_index;
+
+	if (!(channel_index == 0 || channel_index ==  SN95031_ADC_LOOP_MAX)) {
+		/* Reset stop bit for channels other than 0 and 12 */
+		value = snd_soc_read(sn95031_codec, base_addr);
+		/* Set the stop bit to zero */
+		snd_soc_write(sn95031_codec, base_addr, value & 0xEF);
+		/* Index of the first free channel */
+		base_addr++;
+		channel_index++;
+	}
+
+	/* Since this is the last channel, set the stop bit
+	   to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
+	snd_soc_write(sn95031_codec, base_addr,
+				SN95031_AUDIO_DETECT_CODE | 0x10);
+
+	chnl_addr = SN95031_ADC_DATA_START_ADDR + 2 * channel_index;
+	pr_debug("mid_initialize : %x", chnl_addr);
+	configure_adc(sn95031_codec, 1);
+	return chnl_addr;
+}
+
+
+/* reads the ADC registers and gets the mic bias value in mV. */
+static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec)
+{
+	u16 adc_adr = sn95031_initialize_adc(codec);
+	u16 adc_val1, adc_val2;
+	unsigned int mic_bias;
+
+	sn95031_enable_mic_bias(codec);
+
+	/* Enable the sound card for conversion before reading */
+	snd_soc_write(codec, SN95031_ADC1CNTL3, 0x05);
+	/* Re-toggle the RRDATARD bit */
+	snd_soc_write(codec, SN95031_ADC1CNTL3, 0x04);
+
+	/* Read the higher bits of data */
+	msleep(1000);
+	adc_val1 = snd_soc_read(codec, adc_adr);
+	adc_adr++;
+	adc_val2 = snd_soc_read(codec, adc_adr);
+
+	/* Adding lower two bits to the higher bits */
+	mic_bias = (adc_val1 << 2) + (adc_val2 & 3);
+	mic_bias = (mic_bias * SN95031_ADC_ONE_LSB_MULTIPLIER) / 1000;
+	pr_debug("mic bias = %dmV\n", mic_bias);
+	return mic_bias;
+}
+EXPORT_SYMBOL_GPL(sn95031_get_mic_bias);
+/*end - adc helper functions */
 
 static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
 			unsigned int reg)
@@ -663,6 +780,8 @@ static inline void sn95031_enable_jack_btn(struct snd_soc_codec *codec)
 
 static int sn95031_get_headset_state(struct snd_soc_jack *mfld_jack)
 {
+	int micbias = sn95031_get_mic_bias(mfld_jack->codec);
+
 	/* Defaulting to HEADSET for now.
 	 * will change after adding soc-jack detection apis */
 	int jack_type = SND_JACK_HEADSET;
diff --git a/sound/soc/codecs/sn95031.h b/sound/soc/codecs/sn95031.h
index 2dbae61..20376d2 100644
--- a/sound/soc/codecs/sn95031.h
+++ b/sound/soc/codecs/sn95031.h
@@ -96,7 +96,31 @@
 #define SN95031_SSR5			0x384
 #define SN95031_SSR6			0x385
 
+/* ADC registers */
+
+#define SN95031_ADC1CNTL1 0x1C0
+#define SN95031_ADC_ENBL 0x10
+#define SN95031_ADC_START 0x08
+#define SN95031_ADC1CNTL3 0x1C2
+#define SN95031_ADCTHERM_ENBL 0x04
+#define SN95031_ADCRRDATA_ENBL 0x05
+#define SN95031_STOPBIT_MASK 16
+#define SN95031_ADCTHERM_MASK 4
+#define SN95031_ADC_CHANLS_MAX 15 /* Number of ADC channels */
+#define SN95031_ADC_LOOP_MAX (SN95031_ADC_CHANLS_MAX - 1)
+#define SN95031_ADC_NO_LOOP 0x07
 #define SN95031_AUDIO_GPIO_CTRL 0x070
+
+/* ADC channel code values */
+#define SN95031_AUDIO_DETECT_CODE 0x06
+
+/* ADC base addresses */
+#define SN95031_ADC_CHNL_START_ADDR 0x1C5 /* increments by 1 */
+#define SN95031_ADC_DATA_START_ADDR 0x1D4  /* increments by 2 */
+/* multipier to convert to mV */
+#define SN95031_ADC_ONE_LSB_MULTIPLIER 2346
+
+
 struct mfld_jack_data {
 	int intr_id;
 	int micbias_vol;
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/3] add support for jack detection in mid-x86
  2011-02-09 16:14 [PATCH 0/3] add support for jack detection in mid-x86 Koul, Vinod
                   ` (2 preceding siblings ...)
  2011-02-09 16:14 ` [PATCH 3/3] ASoC: sn95031: Add support for reading mic bias Koul, Vinod
@ 2011-02-09 21:51 ` Liam Girdwood
  2011-02-09 22:36   ` Mark Brown
  3 siblings, 1 reply; 7+ messages in thread
From: Liam Girdwood @ 2011-02-09 21:51 UTC (permalink / raw)
  To: Koul, Vinod; +Cc: alsa-devel, broonie

On Wed, 2011-02-09 at 21:44 +0530, Koul, Vinod wrote:
> From: Vinod Koul <vinod.koul@intel.com>
> 
> This patch set adds support for jack detection in mid-x6 machine and TI sn95031
> codec drivers. This also adds support to read mic bias values thru ADC 
> 
> This version fixes namespace issue in patch1, and removes gpio bits in machine
> driver pending gpiolib support, which will be added separately
> 
> Vinod Koul (3):
>   ASoC: sn95031: Add jack support in the codec
>   ASoC: mfld_machine: Add support for jack detection
>   ASoC: sn95031: Add support for reading mic bias
> 
>  sound/soc/codecs/sn95031.c       |  183 +++++++++++++++++++++++++++++++++-
>  sound/soc/codecs/sn95031.h       |   33 ++++++
>  sound/soc/mid-x86/mfld_machine.c |  203 +++++++++++++++++++++++++++++++++-----
>  3 files changed, 388 insertions(+), 31 deletions(-)
> 

All

Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
-- 
Freelance Developer, SlimLogic Ltd
ASoC and Voltage Regulator Maintainer.
http://www.slimlogic.co.uk

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/3] add support for jack detection in mid-x86
  2011-02-09 21:51 ` [PATCH 0/3] add support for jack detection in mid-x86 Liam Girdwood
@ 2011-02-09 22:36   ` Mark Brown
  0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2011-02-09 22:36 UTC (permalink / raw)
  To: Liam Girdwood; +Cc: Koul, Vinod, alsa-devel

On Wed, Feb 09, 2011 at 09:51:48PM +0000, Liam Girdwood wrote:

> All

> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>

Applied, thanks.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 0/3] add support for jack detection in mid-x86
@ 2011-02-09  9:12 Koul, Vinod
  0 siblings, 0 replies; 7+ messages in thread
From: Koul, Vinod @ 2011-02-09  9:12 UTC (permalink / raw)
  To: alsa-devel; +Cc: Vinod Koul, broonie, lrg

From: Vinod Koul <vinod.koul@intel.com>

This patch set adds support for jack detection in mid-x6 machine and TI sn95031
codec drivers. This also adds support to read mic bias values thru ADC 

The comments from previous submission are addressed and patches split
 
Vinod Koul (3):
  ASoC: sn95031: Add jack support in the codec
  ASoC: mfld_machine: Add support for jack detection
  ASoC: sn95031: Add support for reading mic bias

 sound/soc/codecs/sn95031.c       |  184 ++++++++++++++++++++++++++++++++-
 sound/soc/codecs/sn95031.h       |   35 ++++++
 sound/soc/mid-x86/mfld_machine.c |  211 +++++++++++++++++++++++++++++++++-----
 3 files changed, 399 insertions(+), 31 deletions(-)

-- 
1.7.2.3

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-02-09 22:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-09 16:14 [PATCH 0/3] add support for jack detection in mid-x86 Koul, Vinod
2011-02-09 16:14 ` [PATCH 1/3] ASoC: sn95031: Add jack support in the codec Koul, Vinod
2011-02-09 16:14 ` [PATCH 2/3] ASoC: mfld_machine: Add support for jack detection Koul, Vinod
2011-02-09 16:14 ` [PATCH 3/3] ASoC: sn95031: Add support for reading mic bias Koul, Vinod
2011-02-09 21:51 ` [PATCH 0/3] add support for jack detection in mid-x86 Liam Girdwood
2011-02-09 22:36   ` Mark Brown
  -- strict thread matches above, loose matches on Subject: below --
2011-02-09  9:12 Koul, Vinod

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.