Merge "ASoC: wcd937x-mbhc: Add support for headset moisture detection"

This commit is contained in:
Linux Build Service Account
2018-08-25 04:00:44 -07:00
committed by Gerrit - the friendly Code Review server
3 changed files with 114 additions and 1 deletions

View File

@@ -850,6 +850,36 @@ exit:
}
EXPORT_SYMBOL(wcd_mbhc_find_plug_and_report);
static bool wcd_mbhc_moisture_detect(struct wcd_mbhc *mbhc, bool detection_type)
{
bool ret = false;
if (!mbhc->mbhc_cfg->moisture_en ||
!mbhc->mbhc_cfg->moisture_duty_cycle_en)
return ret;
if (!mbhc->mbhc_cb->mbhc_get_moisture_status ||
!mbhc->mbhc_cb->mbhc_moisture_polling_ctrl ||
!mbhc->mbhc_cb->mbhc_moisture_detect_en)
return ret;
if (mbhc->mbhc_cb->mbhc_get_moisture_status(mbhc)) {
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 0);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_GND_DET_EN, 0);
mbhc->mbhc_cb->mbhc_moisture_polling_ctrl(mbhc, true);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MECH_DETECTION_TYPE,
detection_type);
ret = true;
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_GND_DET_EN, 1);
} else {
mbhc->mbhc_cb->mbhc_moisture_polling_ctrl(mbhc, false);
mbhc->mbhc_cb->mbhc_moisture_detect_en(mbhc, false);
}
return ret;
}
static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
{
bool detection_type = 0;
@@ -885,6 +915,13 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
if ((mbhc->current_plug == MBHC_PLUG_TYPE_NONE) &&
detection_type) {
/* If moisture is present, then enable polling, disable
* moisture detection and wait for interrupt
*/
if (wcd_mbhc_moisture_detect(mbhc, detection_type))
goto done;
/* Make sure MASTER_BIAS_CTL is enabled */
mbhc->mbhc_cb->mbhc_bias(codec, true);
@@ -970,6 +1007,16 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
mbhc->mbhc_cb->clk_setup(mbhc->codec, false);
}
if (mbhc->mbhc_cfg->moisture_en &&
mbhc->mbhc_cfg->moisture_duty_cycle_en) {
if (mbhc->mbhc_cb->mbhc_moisture_polling_ctrl)
mbhc->mbhc_cb->mbhc_moisture_polling_ctrl(mbhc,
false);
if (mbhc->mbhc_cb->mbhc_moisture_detect_en)
mbhc->mbhc_cb->mbhc_moisture_detect_en(mbhc,
false);
}
} else if (!detection_type) {
/* Disable external voltage source to micbias if present */
if (mbhc->mbhc_cb->enable_mb_source)
@@ -980,6 +1027,7 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
mbhc->extn_cable_hph_rem = false;
}
done:
mbhc->in_swch_irq_handler = false;
WCD_MBHC_RSC_UNLOCK(mbhc);
pr_debug("%s: leave\n", __func__);
@@ -1294,7 +1342,8 @@ static int wcd_mbhc_initialise(struct wcd_mbhc *mbhc)
else
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, 3);
if (mbhc->mbhc_cfg->moisture_en && mbhc->mbhc_cb->mbhc_moisture_config)
if (mbhc->mbhc_cfg->moisture_en && mbhc->mbhc_cb->mbhc_moisture_config
&& !mbhc->mbhc_cfg->moisture_duty_cycle_en)
mbhc->mbhc_cb->mbhc_moisture_config(mbhc);
/*

View File

@@ -437,6 +437,7 @@ struct wcd_mbhc_config {
int anc_micbias;
bool enable_anc_mic_detect;
u32 enable_usbc_analog;
bool moisture_duty_cycle_en;
};
struct wcd_mbhc_intr {
@@ -502,6 +503,9 @@ struct wcd_mbhc_cb {
bool enable, int anc_num);
bool (*is_anc_on)(struct wcd_mbhc *mbhc);
void (*hph_pull_up_control_v2)(struct snd_soc_codec *, int);
bool (*mbhc_get_moisture_status)(struct wcd_mbhc *);
void (*mbhc_moisture_polling_ctrl)(struct wcd_mbhc *, bool);
void (*mbhc_moisture_detect_en)(struct wcd_mbhc *, bool);
};
struct wcd_mbhc_fn {

View File

@@ -721,6 +721,63 @@ static void wcd937x_mbhc_moisture_config(struct wcd_mbhc *mbhc)
0x0C, mbhc->moist_rref << 2);
}
static void wcd937x_mbhc_moisture_detect_en(struct wcd_mbhc *mbhc, bool enable)
{
struct snd_soc_codec *codec = mbhc->codec;
if (enable)
snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2,
0x0C, mbhc->moist_rref << 2);
else
snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2,
0x0C, R_OFF << 2);
}
static bool wcd937x_mbhc_get_moisture_status(struct wcd_mbhc *mbhc)
{
struct snd_soc_codec *codec = mbhc->codec;
bool ret = false;
if ((mbhc->moist_rref == R_OFF) ||
(mbhc->mbhc_cfg->enable_usbc_analog)) {
snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2,
0x0C, R_OFF << 2);
goto done;
}
/* Do not enable moisture detection if jack type is NC */
if (!mbhc->hphl_swh) {
dev_dbg(codec->dev, "%s: disable moisture detection for NC\n",
__func__);
snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2,
0x0C, R_OFF << 2);
goto done;
}
/* If moisture_en is already enabled, then skip to plug type
* detection.
*/
if ((snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2) & 0x0C))
goto done;
wcd937x_mbhc_moisture_detect_en(mbhc, true);
/* Read moisture comparator status */
ret = ((snd_soc_read(codec, WCD937X_MBHC_NEW_FSM_STATUS)
& 0x20) ? 0 : 1);
done:
return ret;
}
static void wcd937x_mbhc_moisture_polling_ctrl(struct wcd_mbhc *mbhc,
bool enable)
{
snd_soc_update_bits(codec,
WCD937X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL,
0x04, (enable << 2));
}
static const struct wcd_mbhc_cb mbhc_cb = {
.request_irq = wcd937x_mbhc_request_irq,
.irq_control = wcd937x_mbhc_irq_control,
@@ -742,6 +799,9 @@ static const struct wcd_mbhc_cb mbhc_cb = {
.mbhc_gnd_det_ctrl = wcd937x_mbhc_gnd_det_ctrl,
.hph_pull_down_ctrl = wcd937x_mbhc_hph_pull_down_ctrl,
.mbhc_moisture_config = wcd937x_mbhc_moisture_config,
.mbhc_get_moisture_status = wcd937x_mbhc_get_moisture_status,
.mbhc_moisture_polling_ctrl = wcd937x_mbhc_moisture_polling_ctrl,
.mbhc_moisture_detect_en = wcd937x_mbhc_moisture_detect_en,
};
static int wcd937x_get_hph_type(struct snd_kcontrol *kcontrol,