From 6f3ce5a9b97500e7e5435c44e130136f7402c1b9 Mon Sep 17 00:00:00 2001 From: "Dharageswari.R" Date: Thu, 6 Oct 2011 16:18:27 +0100 Subject: [PATCH] ASoC: sn95031: inte_sst: Fix for spurious long press event report bug headset long press button, trigger too many long-press interrupts and fault short-press interrupt. This issue was found to be a hardware bug, and the workaround is implemented in audio driver.when the button in the headset is pressed(long press i.e for more than 2 seconds) and released, rain of long press interrupts followed by a short press/long press event is observed after the button release. This patch fixes the issue of spurious long press event report, followed by a short press event, for every single long press, as a result of this patch only one long press event will be reported for every long press. Change-Id: I56812c9891729aae134559835a10126541e2dabd Signed-off-by: Dharageswari.R --- drivers/staging/intel_sst/intel_sst_common.h | 4 +- sound/soc/codecs/sn95031.c | 55 ++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/drivers/staging/intel_sst/intel_sst_common.h b/drivers/staging/intel_sst/intel_sst_common.h index 3fe9cb1..293060e 100644 --- a/drivers/staging/intel_sst/intel_sst_common.h +++ b/drivers/staging/intel_sst/intel_sst_common.h @@ -28,8 +28,8 @@ * Common private declarations for SST */ -#define SST_DRIVER_VERSION "2.0.03" -#define SST_VERSION_NUM 0x2003 +#define SST_DRIVER_VERSION "2.0.04" +#define SST_VERSION_NUM 0x2004 /* driver names */ #define SST_DRV_NAME "intel_sst_driver" diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 8151559..6697fbb 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c @@ -49,6 +49,26 @@ struct sn95031_priv { uint8_t pcmclk; }; void *audio_adc_handle; +unsigned int sn95031_lp_flag; + +/* This Function reads the voltage level from the ADC Driver*/ +static unsigned int sn95031_read_voltage() +{ + unsigned int mic_bias; + + /* Reads the mic bias value */ + if (!sn95031_lp_flag) + /* GPADC MIC BIAS takes around a 1000ms to settle down and + * get sampled porperly, reading earlier than this causes to + * read incorrect values */ + msleep(1000); + intel_mid_gpadc_sample(audio_adc_handle, SN95031_ADC_SAMPLE_COUNT, + &mic_bias); + mic_bias = (mic_bias * SN95031_ADC_ONE_LSB_MULTIPLIER) / 1000; + pr_debug("mic bias = %dmV\n", mic_bias); + return mic_bias; +} + /* enables mic bias voltage */ static void sn95031_enable_mic_bias(struct snd_soc_codec *codec) { @@ -62,17 +82,11 @@ static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec) unsigned int mic_bias; sn95031_enable_mic_bias(codec); - /*Reads the mic bias value*/ - msleep(1000); - intel_mid_gpadc_sample(audio_adc_handle, SN95031_ADC_SAMPLE_COUNT, - &mic_bias); - - mic_bias = (mic_bias * SN95031_ADC_ONE_LSB_MULTIPLIER) / 1000; - pr_debug("mic bias = %dmV\n", mic_bias); + mic_bias = sn95031_read_voltage(); return mic_bias; } EXPORT_SYMBOL_GPL(sn95031_get_mic_bias); -/*end - adc helper functions */ +/* end - adc helper functions */ static inline unsigned int sn95031_read(struct snd_soc_codec *codec, unsigned int reg) @@ -972,16 +986,35 @@ static int sn95031_get_headset_state(struct snd_soc_jack *mfld_jack) void sn95031_jack_detection(struct mfld_jack_data *jack_data) { - unsigned int status; + unsigned int status, voltage; 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; + if (sn95031_lp_flag) { + snd_soc_jack_report(jack_data->mfld_jack, + SND_JACK_HEADSET, mask); + sn95031_lp_flag = 0; + return; + } else + status = SND_JACK_HEADSET | SND_JACK_BTN_0; } else if (jack_data->intr_id & 0x2) { pr_debug("long_push detected\n"); + /* we get spurious intterupts if jack key is held down + * so we ignore them untill key is released by + * checking the voltage level */ + if (sn95031_lp_flag) { + voltage = sn95031_read_voltage(); + if (voltage > 400) { + snd_soc_jack_report(jack_data->mfld_jack, + SND_JACK_HEADSET, mask); + sn95031_lp_flag = 0; /* button released */ + } + return; + } status = SND_JACK_HEADSET | SND_JACK_BTN_1; + sn95031_lp_flag = 1; } else if (jack_data->intr_id & 0x4) { pr_debug("headset or headphones inserted\n"); status = sn95031_get_headset_state(jack_data->mfld_jack); @@ -1021,7 +1054,7 @@ void sn95031_jack_detection(struct mfld_jack_data *jack_data) } #endif /*button pressed and released so we send explicit button release */ - if ((status & SND_JACK_BTN_0) | (status & SND_JACK_BTN_1)) + if (status & SND_JACK_BTN_0) snd_soc_jack_report(jack_data->mfld_jack, SND_JACK_HEADSET, mask); } -- 2.7.4