asoc: codecs: Fix button interrupts issue in rouleur

Current source mode in rouleur does not work
properly leading to issues in button interrupts
and fake electrical removal interrupts.
Enable pull up mode instead of current source
mode to fix these issues. Modify the headset
max vref voltage to 1.7 volts and micbias
calculation logic.

Change-Id: If3e4a2fdcf080b07fe3c363b6eb6115f101b91f4
Signed-off-by: Aditya Bavanari <abavanar@codeaurora.org>
This commit is contained in:
Aditya Bavanari 2020-04-23 18:57:27 +05:30 committed by Gerrit - the friendly Code Review server
parent 1db5a7d432
commit c3fd6cc305
6 changed files with 118 additions and 19 deletions

View File

@ -82,6 +82,7 @@ struct rouleur_priv {
int mbias_cnt;
struct mutex rx_clk_lock;
struct mutex main_bias_lock;
bool dev_up;
};
struct rouleur_micbias_setting {

View File

@ -820,6 +820,42 @@ static void rouleur_mbhc_bcs_enable(struct wcd_mbhc *mbhc,
rouleur_disable_bcs_before_slow_insert(mbhc->component, true);
}
static void rouleur_mbhc_hs_vref_max_update(struct wcd_mbhc *mbhc)
{
struct snd_soc_component *component = mbhc->component;
/* Update the HS Vref max voltage to 1.7V */
snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_2,
0x03, 0x03);
}
static void rouleur_mbhc_get_micbias_val(struct wcd_mbhc *mbhc, int *mb)
{
u8 vout_ctl = 0;
/* Read MBHC Micbias (Mic Bias2) voltage */
WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl);
/* Formula for getting micbias from vout
* micbias = 1.6V + VOUT_CTL * 50mV
*/
*mb = 1600 + (vout_ctl * 50);
pr_debug("%s: vout_ctl: %d, micbias: %d\n", __func__, vout_ctl, *mb);
}
static void rouleur_mbhc_micb_pullup_control(
struct snd_soc_component *component,
bool pullup_enable)
{
if (pullup_enable)
rouleur_micbias_control(component, MIC_BIAS_2,
MICB_PULLUP_ENABLE, false);
else
rouleur_micbias_control(component, MIC_BIAS_2,
MICB_PULLUP_DISABLE, false);
}
static const struct wcd_mbhc_cb mbhc_cb = {
.request_irq = rouleur_mbhc_request_irq,
.irq_control = rouleur_mbhc_irq_control,
@ -844,6 +880,9 @@ static const struct wcd_mbhc_cb mbhc_cb = {
.mbhc_get_moisture_status = rouleur_mbhc_get_moisture_status,
.mbhc_moisture_detect_en = rouleur_mbhc_moisture_detect_en,
.bcs_enable = rouleur_mbhc_bcs_enable,
.hs_vref_max_update = rouleur_mbhc_hs_vref_max_update,
.get_micbias_val = rouleur_mbhc_get_micbias_val,
.mbhc_micb_pullup_control = rouleur_mbhc_micb_pullup_control,
};
static int rouleur_get_hph_type(struct snd_kcontrol *kcontrol,

View File

@ -1146,6 +1146,7 @@ int rouleur_micbias_control(struct snd_soc_component *component,
int post_on_event = 0, post_dapm_off = 0;
int post_dapm_on = 0;
u8 pullup_mask = 0, enable_mask = 0;
int ret = 0;
if ((micb_index < 0) || (micb_index > ROULEUR_MAX_MICBIAS - 1)) {
dev_err(component->dev, "%s: Invalid micbias index, micb_ind:%d\n",
@ -1181,6 +1182,12 @@ int rouleur_micbias_control(struct snd_soc_component *component,
switch (req) {
case MICB_PULLUP_ENABLE:
if (!rouleur->dev_up) {
dev_dbg(component->dev, "%s: enable req %d wcd device down\n",
__func__, req);
ret = -ENODEV;
goto done;
}
rouleur->pullup_ref[micb_index]++;
if ((rouleur->pullup_ref[micb_index] == 1) &&
(rouleur->micb_ref[micb_index] == 0))
@ -1188,6 +1195,12 @@ int rouleur_micbias_control(struct snd_soc_component *component,
pullup_mask, pullup_mask);
break;
case MICB_PULLUP_DISABLE:
if (!rouleur->dev_up) {
dev_dbg(component->dev, "%s: enable req %d wcd device down\n",
__func__, req);
ret = -ENODEV;
goto done;
}
if (rouleur->pullup_ref[micb_index] > 0)
rouleur->pullup_ref[micb_index]--;
if ((rouleur->pullup_ref[micb_index] == 0) &&
@ -1196,11 +1209,15 @@ int rouleur_micbias_control(struct snd_soc_component *component,
pullup_mask, 0x00);
break;
case MICB_ENABLE:
if (!rouleur->dev_up) {
dev_dbg(component->dev, "%s: enable req %d wcd device down\n",
__func__, req);
ret = -ENODEV;
goto done;
}
rouleur->micb_ref[micb_index]++;
if (rouleur->micb_ref[micb_index] == 1) {
rouleur_global_mbias_enable(component);
snd_soc_component_update_bits(component, micb_reg,
0x80, 0x80);
snd_soc_component_update_bits(component,
micb_reg, enable_mask, enable_mask);
if (post_on_event)
@ -1216,16 +1233,27 @@ int rouleur_micbias_control(struct snd_soc_component *component,
case MICB_DISABLE:
if (rouleur->micb_ref[micb_index] > 0)
rouleur->micb_ref[micb_index]--;
if (!rouleur->dev_up) {
dev_dbg(component->dev, "%s: enable req %d wcd device down\n",
__func__, req);
ret = -ENODEV;
goto done;
}
if ((rouleur->micb_ref[micb_index] == 0) &&
(rouleur->pullup_ref[micb_index] == 0)) {
(rouleur->pullup_ref[micb_index] > 0)) {
snd_soc_component_update_bits(component, micb_reg,
pullup_mask, pullup_mask);
snd_soc_component_update_bits(component, micb_reg,
enable_mask, 0x00);
rouleur_global_mbias_disable(component);
} else if ((rouleur->micb_ref[micb_index] == 0) &&
(rouleur->pullup_ref[micb_index] == 0)) {
if (pre_off_event && rouleur->mbhc)
blocking_notifier_call_chain(
&rouleur->mbhc->notifier, pre_off_event,
&rouleur->mbhc->wcd_mbhc);
snd_soc_component_update_bits(component, micb_reg,
enable_mask, 0x00);
snd_soc_component_update_bits(component, micb_reg,
0x80, 0x00);
rouleur_global_mbias_disable(component);
if (post_off_event && rouleur->mbhc)
blocking_notifier_call_chain(
@ -1243,8 +1271,8 @@ int rouleur_micbias_control(struct snd_soc_component *component,
dev_dbg(component->dev, "%s: micb_num:%d, micb_ref: %d, pullup_ref: %d\n",
__func__, micb_num, rouleur->micb_ref[micb_index],
rouleur->pullup_ref[micb_index]);
done:
mutex_unlock(&rouleur->micb_lock);
return 0;
}
EXPORT_SYMBOL(rouleur_micbias_control);
@ -1313,6 +1341,7 @@ static int rouleur_event_notify(struct notifier_block *block,
0x80, 0x00);
break;
case BOLERO_WCD_EVT_SSR_DOWN:
rouleur->dev_up = false;
rouleur->mbhc->wcd_mbhc.deinit_in_progress = true;
mbhc = &rouleur->mbhc->wcd_mbhc;
rouleur_mbhc_ssr_down(rouleur->mbhc, component);
@ -1338,6 +1367,7 @@ static int rouleur_event_notify(struct notifier_block *block,
rouleur_mbhc_hs_detect(component, mbhc->mbhc_cfg);
}
rouleur->mbhc->wcd_mbhc.deinit_in_progress = false;
rouleur->dev_up = true;
break;
default:
dev_err(component->dev, "%s: invalid event %d\n", __func__,
@ -1969,6 +1999,7 @@ static int rouleur_soc_codec_probe(struct snd_soc_component *component)
return ret;
}
}
rouleur->dev_up = true;
done:
return ret;
}

View File

@ -33,16 +33,20 @@ static int wcd_mbhc_get_micbias(struct wcd_mbhc *mbhc)
int micbias = 0;
u8 vout_ctl = 0;
/* Read MBHC Micbias (Mic Bias2) voltage */
WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl);
/* Formula for getting micbias from vout
* micbias = 1.0V + VOUT_CTL * 50mV
*/
micbias = 1000 + (vout_ctl * 50);
pr_debug("%s: vout_ctl: %d, micbias: %d\n",
__func__, vout_ctl, micbias);
if (mbhc->mbhc_cb->get_micbias_val) {
mbhc->mbhc_cb->get_micbias_val(mbhc, &micbias);
pr_debug("%s: micbias: %d\n", __func__, micbias);
} else {
/* Read MBHC Micbias (Mic Bias2) voltage */
WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl);
/* Formula for getting micbias from vout
* micbias = 1.0V + VOUT_CTL * 50mV
*/
micbias = 1000 + (vout_ctl * 50);
pr_debug("%s: vout_ctl: %d, micbias: %d\n",
__func__, vout_ctl, micbias);
}
return micbias;
}

View File

@ -80,11 +80,17 @@ static void wcd_program_hs_vref(struct wcd_mbhc *mbhc)
struct snd_soc_component *component = mbhc->component;
u32 reg_val;
plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100);
if (mbhc->mbhc_cb->hs_vref_max_update) {
mbhc->mbhc_cb->hs_vref_max_update(mbhc);
} else {
plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR(
mbhc->mbhc_cfg->calibration);
reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100);
dev_dbg(component->dev, "%s: reg_val = %x\n", __func__, reg_val);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val);
dev_dbg(component->dev, "%s: reg_val = %x\n",
__func__, reg_val);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val);
}
}
static void wcd_program_btn_threshold(const struct wcd_mbhc *mbhc, bool micbias)
@ -993,6 +999,14 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
mbhc->mbhc_cb->enable_mb_source(mbhc, true);
mbhc->btn_press_intr = false;
mbhc->is_btn_press = false;
/*
* When current source mode doesn't work properly
* use mic bias pull up mode for button interrupts
* to function properly
*/
if (mbhc->mbhc_cb->mbhc_micb_pullup_control)
mbhc->mbhc_cb->mbhc_micb_pullup_control(component,
true);
if (mbhc->mbhc_fn)
mbhc->mbhc_fn->wcd_mbhc_detect_plug_type(mbhc);
} else if ((mbhc->current_plug != MBHC_PLUG_TYPE_NONE)
@ -1070,6 +1084,10 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
false);
}
if (mbhc->mbhc_cb->mbhc_micb_pullup_control)
mbhc->mbhc_cb->mbhc_micb_pullup_control(component,
false);
} else if (!detection_type) {
/* Disable external voltage source to micbias if present */
if (mbhc->mbhc_cb->enable_mb_source)

View File

@ -456,6 +456,12 @@ struct wcd_mbhc_register {
};
struct wcd_mbhc_cb {
void (*mbhc_micb_pullup_control)
(struct snd_soc_component *component, bool enable);
void (*get_micbias_val)
(struct wcd_mbhc *mbhc, int *mb);
void (*hs_vref_max_update)
(struct wcd_mbhc *mbhc);
void (*bcs_enable)
(struct wcd_mbhc *mbhc, bool bcs_enable);
int (*enable_mb_source)(struct wcd_mbhc *mbhc, bool turn_on);