Merge "ASoC: wcd-mbhc: Disconnect ANC from RX chain during plug removal"

This commit is contained in:
Linux Build Service Account 2017-07-04 01:21:02 -07:00 committed by Gerrit - the friendly Code Review server
commit 48b492e8e1
4 changed files with 100 additions and 0 deletions

View file

@ -361,6 +361,7 @@ out_micb_en:
/* Disable micbias, pullup & enable cs */ /* Disable micbias, pullup & enable cs */
wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS); wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS);
mutex_unlock(&mbhc->hphl_pa_lock); mutex_unlock(&mbhc->hphl_pa_lock);
clear_bit(WCD_MBHC_ANC0_OFF_ACK, &mbhc->hph_anc_state);
break; break;
case WCD_EVENT_PRE_HPHR_PA_OFF: case WCD_EVENT_PRE_HPHR_PA_OFF:
mutex_lock(&mbhc->hphr_pa_lock); mutex_lock(&mbhc->hphr_pa_lock);
@ -378,6 +379,7 @@ out_micb_en:
/* Disable micbias, pullup & enable cs */ /* Disable micbias, pullup & enable cs */
wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS); wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS);
mutex_unlock(&mbhc->hphr_pa_lock); mutex_unlock(&mbhc->hphr_pa_lock);
clear_bit(WCD_MBHC_ANC1_OFF_ACK, &mbhc->hph_anc_state);
break; break;
case WCD_EVENT_PRE_HPHL_PA_ON: case WCD_EVENT_PRE_HPHL_PA_ON:
set_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state); set_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state);
@ -495,6 +497,25 @@ static void wcd_mbhc_clr_and_turnon_hph_padac(struct wcd_mbhc *mbhc)
__func__); __func__);
usleep_range(wg_time * 1000, wg_time * 1000 + 50); usleep_range(wg_time * 1000, wg_time * 1000 + 50);
} }
if (test_and_clear_bit(WCD_MBHC_ANC0_OFF_ACK,
&mbhc->hph_anc_state)) {
usleep_range(20000, 20100);
pr_debug("%s: HPHL ANC clear flag and enable ANC_EN\n",
__func__);
if (mbhc->mbhc_cb->update_anc_state)
mbhc->mbhc_cb->update_anc_state(mbhc->codec, true, 0);
}
if (test_and_clear_bit(WCD_MBHC_ANC1_OFF_ACK,
&mbhc->hph_anc_state)) {
usleep_range(20000, 20100);
pr_debug("%s: HPHR ANC clear flag and enable ANC_EN\n",
__func__);
if (mbhc->mbhc_cb->update_anc_state)
mbhc->mbhc_cb->update_anc_state(mbhc->codec, true, 1);
}
} }
static bool wcd_mbhc_is_hph_pa_on(struct wcd_mbhc *mbhc) static bool wcd_mbhc_is_hph_pa_on(struct wcd_mbhc *mbhc)
@ -526,6 +547,20 @@ static void wcd_mbhc_set_and_turnoff_hph_padac(struct wcd_mbhc *mbhc)
} }
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPH_PA_EN, 0); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPH_PA_EN, 0);
usleep_range(wg_time * 1000, wg_time * 1000 + 50); usleep_range(wg_time * 1000, wg_time * 1000 + 50);
if (mbhc->mbhc_cb->is_anc_on && mbhc->mbhc_cb->is_anc_on(mbhc)) {
usleep_range(20000, 20100);
pr_debug("%s ANC is on, setting ANC_OFF_ACK\n", __func__);
set_bit(WCD_MBHC_ANC0_OFF_ACK, &mbhc->hph_anc_state);
set_bit(WCD_MBHC_ANC1_OFF_ACK, &mbhc->hph_anc_state);
if (mbhc->mbhc_cb->update_anc_state) {
mbhc->mbhc_cb->update_anc_state(mbhc->codec, false, 0);
mbhc->mbhc_cb->update_anc_state(mbhc->codec, false, 1);
} else {
pr_debug("%s ANC is off\n", __func__);
}
}
} }
int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl, int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,

View file

@ -89,6 +89,11 @@ enum pa_dac_ack_flags {
WCD_MBHC_HPHR_PA_OFF_ACK, WCD_MBHC_HPHR_PA_OFF_ACK,
}; };
enum anc_ack_flags {
WCD_MBHC_ANC0_OFF_ACK = 0,
WCD_MBHC_ANC1_OFF_ACK,
};
enum wcd_mbhc_btn_det_mem { enum wcd_mbhc_btn_det_mem {
WCD_MBHC_BTN_DET_V_BTN_LOW, WCD_MBHC_BTN_DET_V_BTN_LOW,
WCD_MBHC_BTN_DET_V_BTN_HIGH WCD_MBHC_BTN_DET_V_BTN_HIGH
@ -386,6 +391,9 @@ struct wcd_mbhc_cb {
void (*hph_pull_down_ctrl)(struct snd_soc_codec *, bool); void (*hph_pull_down_ctrl)(struct snd_soc_codec *, bool);
void (*mbhc_moisture_config)(struct wcd_mbhc *); void (*mbhc_moisture_config)(struct wcd_mbhc *);
bool (*hph_register_recovery)(struct wcd_mbhc *); bool (*hph_register_recovery)(struct wcd_mbhc *);
void (*update_anc_state)(struct snd_soc_codec *codec,
bool enable, int anc_num);
bool (*is_anc_on)(struct wcd_mbhc *mbhc);
}; };
struct wcd_mbhc { struct wcd_mbhc {
@ -426,6 +434,7 @@ struct wcd_mbhc {
/* track PA/DAC state to sync with userspace */ /* track PA/DAC state to sync with userspace */
unsigned long hph_pa_dac_state; unsigned long hph_pa_dac_state;
unsigned long hph_anc_state;
unsigned long event_state; unsigned long event_state;
unsigned long jiffies_atreport; unsigned long jiffies_atreport;

View file

@ -2219,6 +2219,32 @@ static void tasha_mbhc_moisture_config(struct wcd_mbhc *mbhc)
tasha_mbhc_hph_l_pull_up_control(codec, mbhc->moist_iref); tasha_mbhc_hph_l_pull_up_control(codec, mbhc->moist_iref);
} }
static void tasha_update_anc_state(struct snd_soc_codec *codec, bool enable,
int anc_num)
{
if (enable)
snd_soc_update_bits(codec, WCD9335_CDC_RX1_RX_PATH_CFG0 +
(20 * anc_num), 0x10, 0x10);
else
snd_soc_update_bits(codec, WCD9335_CDC_RX1_RX_PATH_CFG0 +
(20 * anc_num), 0x10, 0x00);
}
static bool tasha_is_anc_on(struct wcd_mbhc *mbhc)
{
bool anc_on = false;
u16 ancl, ancr;
ancl =
(snd_soc_read(mbhc->codec, WCD9335_CDC_RX1_RX_PATH_CFG0)) & 0x10;
ancr =
(snd_soc_read(mbhc->codec, WCD9335_CDC_RX2_RX_PATH_CFG0)) & 0x10;
anc_on = !!(ancl | ancr);
return anc_on;
}
static const struct wcd_mbhc_cb mbhc_cb = { static const struct wcd_mbhc_cb mbhc_cb = {
.request_irq = tasha_mbhc_request_irq, .request_irq = tasha_mbhc_request_irq,
.irq_control = tasha_mbhc_irq_control, .irq_control = tasha_mbhc_irq_control,
@ -2241,6 +2267,8 @@ static const struct wcd_mbhc_cb mbhc_cb = {
.mbhc_gnd_det_ctrl = tasha_mbhc_gnd_det_ctrl, .mbhc_gnd_det_ctrl = tasha_mbhc_gnd_det_ctrl,
.hph_pull_down_ctrl = tasha_mbhc_hph_pull_down_ctrl, .hph_pull_down_ctrl = tasha_mbhc_hph_pull_down_ctrl,
.mbhc_moisture_config = tasha_mbhc_moisture_config, .mbhc_moisture_config = tasha_mbhc_moisture_config,
.update_anc_state = tasha_update_anc_state,
.is_anc_on = tasha_is_anc_on,
}; };
static int tasha_get_anc_slot(struct snd_kcontrol *kcontrol, static int tasha_get_anc_slot(struct snd_kcontrol *kcontrol,

View file

@ -812,6 +812,32 @@ static bool tavil_hph_register_recovery(struct wcd_mbhc *mbhc)
return wcd934x_mbhc->is_hph_recover; return wcd934x_mbhc->is_hph_recover;
} }
static void tavil_update_anc_state(struct snd_soc_codec *codec, bool enable,
int anc_num)
{
if (enable)
snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CFG0 +
(20 * anc_num), 0x10, 0x10);
else
snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CFG0 +
(20 * anc_num), 0x10, 0x00);
}
static bool tavil_is_anc_on(struct wcd_mbhc *mbhc)
{
bool anc_on = false;
u16 ancl, ancr;
ancl =
(snd_soc_read(mbhc->codec, WCD934X_CDC_RX1_RX_PATH_CFG0)) & 0x10;
ancr =
(snd_soc_read(mbhc->codec, WCD934X_CDC_RX2_RX_PATH_CFG0)) & 0x10;
anc_on = !!(ancl | ancr);
return anc_on;
}
static const struct wcd_mbhc_cb mbhc_cb = { static const struct wcd_mbhc_cb mbhc_cb = {
.request_irq = tavil_mbhc_request_irq, .request_irq = tavil_mbhc_request_irq,
.irq_control = tavil_mbhc_irq_control, .irq_control = tavil_mbhc_irq_control,
@ -835,6 +861,8 @@ static const struct wcd_mbhc_cb mbhc_cb = {
.hph_pull_down_ctrl = tavil_mbhc_hph_pull_down_ctrl, .hph_pull_down_ctrl = tavil_mbhc_hph_pull_down_ctrl,
.mbhc_moisture_config = tavil_mbhc_moisture_config, .mbhc_moisture_config = tavil_mbhc_moisture_config,
.hph_register_recovery = tavil_hph_register_recovery, .hph_register_recovery = tavil_hph_register_recovery,
.update_anc_state = tavil_update_anc_state,
.is_anc_on = tavil_is_anc_on,
}; };
static struct regulator *tavil_codec_find_ondemand_regulator( static struct regulator *tavil_codec_find_ondemand_regulator(