ASoC: wcd-mbhc: update electrical removal detection logic

when moisture is in jack, removing of the plug result in
electrical removal interrupt. So, update electrical interrupt
handler to handle mechanical removal based on moisture status.

CRs-Fixed: 2058106
Change-Id: I9cfbfbaf04783f0edcadb14d7828759020745289
Signed-off-by: Meng Wang <mwang@codeaurora.org>
This commit is contained in:
Meng Wang
2017-09-19 10:21:57 +08:00
vanhempi 7cc0186011
commit 6f90162f22
6 muutettua tiedostoa jossa 148 lisäystä ja 29 poistoa

Näytä tiedosto

@@ -895,6 +895,8 @@ static irqreturn_t wcd_mbhc_adc_hs_rem_irq(int irq, void *data)
struct wcd_mbhc *mbhc = data;
unsigned long timeout;
int adc_threshold, output_mv, retry = 0;
bool hphpa_on = false;
u8 moisture_status = 0;
pr_debug("%s: enter\n", __func__);
WCD_MBHC_RSC_LOCK(mbhc);
@@ -928,10 +930,45 @@ static irqreturn_t wcd_mbhc_adc_hs_rem_irq(int irq, void *data)
goto exit;
}
if (mbhc->mbhc_cfg->moisture_en) {
if (mbhc->mbhc_cb->hph_pa_on_status)
if (mbhc->mbhc_cb->hph_pa_on_status(mbhc->codec)) {
hphpa_on = true;
WCD_MBHC_REG_UPDATE_BITS(
WCD_MBHC_HPHL_PA_EN, 0);
WCD_MBHC_REG_UPDATE_BITS(
WCD_MBHC_HPH_PA_EN, 0);
}
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHR_GND, 1);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHL_GND, 1);
/* wait for 50ms to get moisture status */
usleep_range(50000, 50100);
WCD_MBHC_REG_READ(WCD_MBHC_MOISTURE_STATUS, moisture_status);
}
if (mbhc->mbhc_cfg->moisture_en && !moisture_status) {
pr_debug("%s: moisture present in jack\n", __func__);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 0);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MECH_DETECTION_TYPE, 1);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
mbhc->btn_press_intr = false;
mbhc->is_btn_press = false;
if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET)
wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADSET);
else if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE)
wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADPHONE);
else if (mbhc->current_plug == MBHC_PLUG_TYPE_GND_MIC_SWAP)
wcd_mbhc_report_plug(mbhc, 0, SND_JACK_UNSUPPORTED);
else if (mbhc->current_plug == MBHC_PLUG_TYPE_HIGH_HPH)
wcd_mbhc_report_plug(mbhc, 0, SND_JACK_LINEOUT);
} else {
/*
* ADC COMPLETE and ELEC_REM interrupts are both enabled for HEADPHONE,
* need to reject the ADC COMPLETE interrupt which follows ELEC_REM one
* when HEADPHONE is removed.
* ADC COMPLETE and ELEC_REM interrupts are both enabled for
* HEADPHONE, need to reject the ADC COMPLETE interrupt which
* follows ELEC_REM one when HEADPHONE is removed.
*/
if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE)
mbhc->extn_cable_hph_rem = true;
@@ -939,6 +976,13 @@ static irqreturn_t wcd_mbhc_adc_hs_rem_irq(int irq, void *data)
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_MODE, 0);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 0);
wcd_mbhc_elec_hs_report_unplug(mbhc);
if (hphpa_on) {
hphpa_on = false;
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHL_PA_EN, 1);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPH_PA_EN, 1);
}
}
exit:
WCD_MBHC_RSC_UNLOCK(mbhc);
pr_debug("%s: leave\n", __func__);

Näytä tiedosto

@@ -794,6 +794,8 @@ static irqreturn_t wcd_mbhc_hs_rem_irq(int irq, void *data)
unsigned long timeout;
bool removed = true;
int retry = 0;
bool hphpa_on = false;
u8 moisture_status = 0;
pr_debug("%s: enter\n", __func__);
@@ -830,6 +832,52 @@ static irqreturn_t wcd_mbhc_hs_rem_irq(int irq, void *data)
WCD_MBHC_REG_READ(WCD_MBHC_HS_COMP_RESULT, hs_comp_result);
if (removed) {
if (mbhc->mbhc_cfg->moisture_en) {
if (mbhc->mbhc_cb->hph_pa_on_status)
if (
mbhc->mbhc_cb->hph_pa_on_status(mbhc->codec)) {
hphpa_on = true;
WCD_MBHC_REG_UPDATE_BITS(
WCD_MBHC_HPHL_PA_EN, 0);
WCD_MBHC_REG_UPDATE_BITS(
WCD_MBHC_HPH_PA_EN, 0);
}
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHR_GND, 1);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHL_GND, 1);
/* wait for 50ms to get moisture status */
usleep_range(50000, 50100);
WCD_MBHC_REG_READ(
WCD_MBHC_MOISTURE_STATUS, moisture_status);
}
if (mbhc->mbhc_cfg->moisture_en && !moisture_status) {
pr_debug("%s: moisture present in jack\n", __func__);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 0);
WCD_MBHC_REG_UPDATE_BITS(
WCD_MBHC_MECH_DETECTION_TYPE, 1);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
mbhc->btn_press_intr = false;
mbhc->is_btn_press = false;
if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET)
wcd_mbhc_report_plug(
mbhc, 0, SND_JACK_HEADSET);
else if (mbhc->current_plug ==
MBHC_PLUG_TYPE_HEADPHONE)
wcd_mbhc_report_plug(
mbhc, 0, SND_JACK_HEADPHONE);
else if (mbhc->current_plug ==
MBHC_PLUG_TYPE_GND_MIC_SWAP)
wcd_mbhc_report_plug(
mbhc, 0, SND_JACK_UNSUPPORTED);
else if (mbhc->current_plug ==
MBHC_PLUG_TYPE_HIGH_HPH)
wcd_mbhc_report_plug(
mbhc, 0, SND_JACK_LINEOUT);
} else {
if (!(hphl_sch && mic_sch && hs_comp_result)) {
/*
* extension cable is still plugged in
@@ -839,12 +887,14 @@ static irqreturn_t wcd_mbhc_hs_rem_irq(int irq, void *data)
} else {
if (!mic_sch) {
mic_trigerred++;
pr_debug("%s: Removal MIC trigerred %d\n",
pr_debug(
"%s: Removal MIC trigerred %d\n",
__func__, mic_trigerred);
}
if (!hphl_sch) {
hphl_trigerred++;
pr_debug("%s: Removal HPHL trigerred %d\n",
pr_debug(
"%s: Removal HPHL trigerred %d\n",
__func__, hphl_trigerred);
}
if (mic_trigerred && hphl_trigerred) {
@@ -856,6 +906,7 @@ static irqreturn_t wcd_mbhc_hs_rem_irq(int irq, void *data)
}
}
}
}
exit:
WCD_MBHC_RSC_UNLOCK(mbhc);
pr_debug("%s: leave\n", __func__);
@@ -863,6 +914,11 @@ exit:
report_unplug:
wcd_mbhc_elec_hs_report_unplug(mbhc);
if (hphpa_on) {
hphpa_on = false;
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHL_PA_EN, 1);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPH_PA_EN, 1);
}
hphl_trigerred = 0;
mic_trigerred = 0;
WCD_MBHC_RSC_UNLOCK(mbhc);

Näytä tiedosto

@@ -550,7 +550,7 @@ void wcd_mbhc_hs_elec_irq(struct wcd_mbhc *mbhc, int irq_type,
}
EXPORT_SYMBOL(wcd_mbhc_hs_elec_irq);
static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
enum snd_jack_types jack_type)
{
struct snd_soc_codec *codec = mbhc->codec;
@@ -725,6 +725,7 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
}
pr_debug("%s: leave hph_status %x\n", __func__, mbhc->hph_status);
}
EXPORT_SYMBOL(wcd_mbhc_report_plug);
void wcd_mbhc_elec_hs_report_unplug(struct wcd_mbhc *mbhc)
{

Näytä tiedosto

@@ -16,6 +16,7 @@
#include <linux/stringify.h>
#include <linux/power_supply.h>
#include "wcdcal-hwdep.h"
#include <sound/jack.h>
#define TOMBAK_MBHC_NC 0
#define TOMBAK_MBHC_NO 1
@@ -204,6 +205,9 @@ enum wcd_mbhc_register_function {
WCD_MBHC_ANC_DET_EN,
WCD_MBHC_FSM_STATUS,
WCD_MBHC_MUX_CTL,
WCD_MBHC_MOISTURE_STATUS,
WCD_MBHC_HPHR_GND,
WCD_MBHC_HPHL_GND,
WCD_MBHC_HPHL_OCP_DET_EN,
WCD_MBHC_HPHR_OCP_DET_EN,
WCD_MBHC_HPHL_OCP_STATUS,
@@ -594,5 +598,7 @@ void wcd_mbhc_jack_report(struct wcd_mbhc *mbhc,
struct snd_soc_jack *jack, int status, int mask);
int wcd_cancel_btn_work(struct wcd_mbhc *mbhc);
int wcd_mbhc_get_button_mask(struct wcd_mbhc *mbhc);
void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
enum snd_jack_types jack_type);
#endif /* __WCD_MBHC_V2_H__ */

Näytä tiedosto

@@ -650,6 +650,12 @@ static struct wcd_mbhc_register
0, 0, 0, 0),
WCD_MBHC_REGISTER("WCD_MBHC_MUX_CTL",
WCD9335_MBHC_CTL_2, 0x70, 4, 0),
WCD_MBHC_REGISTER("WCD_MBHC_MOISTURE_STATUS",
WCD9335_MBHC_FSM_STATUS, 0X20, 5, 0),
WCD_MBHC_REGISTER("WCD_MBHC_HPHR_GND",
WCD9335_HPH_PA_CTL2, 0x40, 6, 0),
WCD_MBHC_REGISTER("WCD_MBHC_HPHL_GND",
WCD9335_HPH_PA_CTL2, 0x10, 4, 0),
};
static const struct wcd_mbhc_intr intr_ids = {

Näytä tiedosto

@@ -120,6 +120,12 @@ static struct wcd_mbhc_register
WCD934X_MBHC_STATUS_SPARE_1, 0x01, 0, 0),
WCD_MBHC_REGISTER("WCD_MBHC_MUX_CTL",
WCD934X_MBHC_NEW_CTL_2, 0x70, 4, 0),
WCD_MBHC_REGISTER("WCD_MBHC_MOISTURE_STATUS",
WCD934X_MBHC_NEW_FSM_STATUS, 0x20, 5, 0),
WCD_MBHC_REGISTER("WCD_MBHC_HPHR_GND",
WCD934X_HPH_PA_CTL2, 0x40, 6, 0),
WCD_MBHC_REGISTER("WCD_MBHC_HPHL_GND",
WCD934X_HPH_PA_CTL2, 0x10, 4, 0),
WCD_MBHC_REGISTER("WCD_MBHC_HPHL_OCP_DET_EN",
WCD934X_HPH_L_TEST, 0x01, 0, 0),
WCD_MBHC_REGISTER("WCD_MBHC_HPHR_OCP_DET_EN",