[alsa-devel] [PATCH 0/3] add support for jack detection in mid-x86
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(-)
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
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; }
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;
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
On Wed, Feb 09, 2011 at 09:51:48PM +0000, Liam Girdwood wrote:
All
Acked-by: Liam Girdwood lrg@slimlogic.co.uk
Applied, thanks.
participants (3)
-
Koul, Vinod
-
Liam Girdwood
-
Mark Brown