From 850efe3d90d6f72f30a5dee10abe34c9abc26e6e Mon Sep 17 00:00:00 2001 From: KuldeepX Vyas Date: Tue, 5 Jun 2012 15:22:16 +0530 Subject: [PATCH] audio: add GPIO support for Lex jack detection BZ: 39875 In PR2.1 board, a GPIO is added to improve the jack detection logic. Add driver support GPIO jack detection. _JACK_DET line is connected to PNW GPIO line. In addition to existing MSIC jack detection interrupt, driver reads the GPIO line for making decision on type jack device connected. Change-Id: Ib4d8f0f4ecfa7b74f835d902ca8957845ef42261 Signed-off-by: KuldeepX Vyas Signed-off-by: Ramesh Babu K V Reviewed-on: http://android.intel.com:8080/51674 Reviewed-by: Koul, Vinod Tested-by: Gupta, ArvindX K Reviewed-by: buildbot Tested-by: buildbot --- sound/soc/mid-x86/mfld_common.h | 1 + sound/soc/mid-x86/mfld_machine_gi.c | 44 ++++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/sound/soc/mid-x86/mfld_common.h b/sound/soc/mid-x86/mfld_common.h index 2cd76ad..69066fb 100644 --- a/sound/soc/mid-x86/mfld_common.h +++ b/sound/soc/mid-x86/mfld_common.h @@ -68,6 +68,7 @@ struct mfld_mc_private { unsigned int hs_switch; unsigned int sn95031_lo_dac; struct msic_audio_platform_data *pdata; + int jack_gpio; #ifdef CONFIG_HAS_WAKELOCK struct wake_lock *jack_wake_lock; #endif diff --git a/sound/soc/mid-x86/mfld_machine_gi.c b/sound/soc/mid-x86/mfld_machine_gi.c index 9ab8c90..f107735 100644 --- a/sound/soc/mid-x86/mfld_machine_gi.c +++ b/sound/soc/mid-x86/mfld_machine_gi.c @@ -2,9 +2,8 @@ * mfld_machine_gi.c - ASoc Machine driver for Gilligan Island board * based on Intel Medfield MID platform * - * Copyright (C) 2010 Intel Corp + * Copyright (C) 2010-12 Intel Corp * Author: Vinod Koul - * Author: Harsha Priya * Author: Ramesh babu K V * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -33,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -93,9 +93,19 @@ static void mfld_jack_disable_mic_bias(struct snd_soc_codec *codec) } +static inline int mfld_get_gpio_value(struct mfld_mc_private *ctx) +{ + /* Return if there is no GPIO support */ + if (ctx->jack_gpio < 0) { + return -1; + } + return gpio_get_value(ctx->jack_gpio); +} static int mfld_get_headset_state(struct snd_soc_jack *jack) { - int micbias, jack_type; + int micbias, jack_type, gpio_state; + struct mfld_mc_private *ctx = + snd_soc_card_get_drvdata(jack->codec->card); mfld_jack_enable_mic_bias(jack->codec); micbias = mfld_jack_read_voltage(jack); @@ -103,6 +113,13 @@ static int mfld_get_headset_state(struct snd_soc_jack *jack) jack_type = snd_soc_jack_get_type(jack, micbias); pr_debug("jack type detected = %d, micbias = %d\n", jack_type, micbias); + if (jack_type != SND_JACK_HEADSET && jack_type != SND_JACK_HEADPHONE) { + gpio_state = mfld_get_gpio_value(ctx); + if (gpio_state == 0) { + jack_type = SND_JACK_HEADPHONE; + pr_debug("GPIO says there is a headphone, reporting it\n"); + } + } if (jack_type == SND_JACK_HEADSET) /* enable btn press detection */ snd_soc_update_bits(jack->codec, SN95031_BTNCTRL2, BIT(0), 1); @@ -147,6 +164,7 @@ void mfld_jack_wq(struct work_struct *work) struct mfld_jack_work *jack_work = &ctx->jack_work; struct snd_soc_jack *jack = jack_work->jack; unsigned int voltage, status = 0, intr_id = jack_work->intr_id; + int gpio_state; pr_debug("jack status in wq: 0x%x\n", intr_id); if (intr_id & SN95031_JACK_INSERTED) { @@ -156,6 +174,11 @@ void mfld_jack_wq(struct work_struct *work) snd_soc_update_bits(jack->codec, SN95031_ACCDETMASK, BIT(1)|BIT(0), 0); } else if (intr_id & SN95031_JACK_REMOVED) { + gpio_state = mfld_get_gpio_value(ctx); + if (gpio_state == 0) { + pr_debug("remove interrupt, but GPIO says inserted\n"); + return; + } pr_debug("reporting jack as removed\n"); snd_soc_update_bits(jack->codec, SN95031_BTNCTRL2, BIT(0), 0); snd_soc_update_bits(jack->codec, SN95031_ACCDETMASK, BIT(2), 0); @@ -685,6 +708,19 @@ static int __devinit snd_mfld_mc_probe(struct ipc_device *ipcdev) } INIT_DELAYED_WORK(&ctx->jack_work.work, mfld_jack_wq); + /* Store jack gpio pin number in ctx for future reference */ + ctx->jack_gpio = get_gpio_by_name("audio_jack_gpio"); + if (ctx->jack_gpio >= 0) { + pr_info("GPIO for jack det is %d\n", ctx->jack_gpio); + ret_val = gpio_request_one(ctx->jack_gpio, + GPIOF_DIR_IN, + "headset_detect_gpio"); + if (ret_val) { + pr_err("Headset detect GPIO alloc fail:%d\n", ret_val); + goto unalloc; + } + } + ctx->int_base = ioremap_nocache(irq_mem->start, resource_size(irq_mem)); if (!ctx->int_base) { pr_err("Mapping of cache failed\n"); @@ -735,6 +771,8 @@ static int __devexit snd_mfld_mc_remove(struct ipc_device *ipcdev) #endif cancel_delayed_work(&ctx->jack_work.work); intel_mid_gpadc_free(ctx->audio_adc_handle); + if (ctx->jack_gpio >= 0) + gpio_free(ctx->jack_gpio); kfree(ctx); snd_soc_card_set_drvdata(soc_card, NULL); snd_soc_unregister_card(soc_card); -- 2.7.4