asoc: codecs: Add comparator autozeroing support for rouleur

When current source mode is enabled, comparator auto
zeroing should be turned ON by HW. As rouleur codec HW
doesn't do this automatically, add this support
in SW to set the auto zero enable before FSM enable
and reset to auto once FSM is enabled.
Disable surge protection before ADC measurements
and change HPHL and HPHR thresholds while
identifying cross connection for proper
accessory identification.

Change-Id: Ib775de0f0bdb6c655a3c0eb4775276acfbca1e84
Signed-off-by: Aditya Bavanari <abavanar@codeaurora.org>
This commit is contained in:
Aditya Bavanari 2020-04-29 20:43:53 +05:30 committed by Akhil Karuturi
parent c3fd6cc305
commit 313aa17ac4
5 changed files with 112 additions and 56 deletions

View File

@ -37,6 +37,10 @@
#define ROULEUR_MBHC_ZDET_CONST (86 * 16384)
#define ROULEUR_MBHC_MOISTURE_RREF R_24_KOHM
/* Cross connection thresholds in mV */
#define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 200
#define ROULEUR_HPHR_CROSS_CONN_THRESHOLD 200
static struct wcd_mbhc_register
wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = {
WCD_MBHC_REGISTER("WCD_MBHC_L_DET_EN",
@ -320,11 +324,11 @@ static void rouleur_mbhc_micb_ramp_control(struct snd_soc_component *component,
0x1C, 0x0C);
snd_soc_component_update_bits(component,
ROULEUR_ANA_MBHC_MICB2_RAMP,
0xA0, 0x80);
0x80, 0x80);
} else {
snd_soc_component_update_bits(component,
ROULEUR_ANA_MBHC_MICB2_RAMP,
0xA0, 0x00);
0x80, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_ANA_MBHC_MICB2_RAMP,
0x1C, 0x00);
@ -820,15 +824,6 @@ 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;
@ -843,19 +838,40 @@ static void rouleur_mbhc_get_micbias_val(struct wcd_mbhc *mbhc, int *mb)
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)
static void rouleur_mbhc_comp_autozero_control(struct wcd_mbhc *mbhc,
bool az_enable)
{
if (pullup_enable)
rouleur_micbias_control(component, MIC_BIAS_2,
MICB_PULLUP_ENABLE, false);
if (az_enable)
snd_soc_component_update_bits(mbhc->component,
ROULEUR_ANA_MBHC_MCLK, 0x08, 0x08);
else
rouleur_micbias_control(component, MIC_BIAS_2,
MICB_PULLUP_DISABLE, false);
snd_soc_component_update_bits(mbhc->component,
ROULEUR_ANA_MBHC_MCLK, 0x08, 0x00);
}
static void rouleur_mbhc_surge_control(struct wcd_mbhc *mbhc,
bool surge_enable)
{
if (surge_enable)
snd_soc_component_update_bits(mbhc->component,
ROULEUR_ANA_SURGE_EN, 0xC0, 0xC0);
else
snd_soc_component_update_bits(mbhc->component,
ROULEUR_ANA_SURGE_EN, 0xC0, 0x00);
}
static void rouleur_mbhc_update_cross_conn_thr(struct wcd_mbhc *mbhc)
{
mbhc->hphl_cross_conn_thr = ROULEUR_HPHL_CROSS_CONN_THRESHOLD;
mbhc->hphr_cross_conn_thr = ROULEUR_HPHR_CROSS_CONN_THRESHOLD;
pr_debug("%s: Cross connection threshold for hphl: %d, hphr: %d\n",
__func__, mbhc->hphl_cross_conn_thr,
mbhc->hphr_cross_conn_thr);
}
static const struct wcd_mbhc_cb mbhc_cb = {
.request_irq = rouleur_mbhc_request_irq,
.irq_control = rouleur_mbhc_irq_control,
@ -880,9 +896,10 @@ 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,
.mbhc_comp_autozero_control = rouleur_mbhc_comp_autozero_control,
.mbhc_surge_ctl = rouleur_mbhc_surge_control,
.update_cross_conn_thr = rouleur_mbhc_update_cross_conn_thr,
};
static int rouleur_get_hph_type(struct snd_kcontrol *kcontrol,

View File

@ -107,6 +107,9 @@ static int rouleur_handle_post_irq(void *data)
static int rouleur_init_reg(struct snd_soc_component *component)
{
/* Disable HPH OCP */
snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_CNP_CTL_2,
0x03, 0x00);
/* Enable surge protection */
snd_soc_component_update_bits(component, ROULEUR_ANA_SURGE_EN,
0xC0, 0xC0);
@ -354,7 +357,7 @@ static int rouleur_rx_clk_enable(struct snd_soc_component *component)
usleep_range(5000, 5100);
rouleur_global_mbias_enable(component);
snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_FSM_CLK, 0x11, 0x11);
ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x11);
snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x80);
snd_soc_component_update_bits(component,
@ -382,14 +385,14 @@ static int rouleur_rx_clk_disable(struct snd_soc_component *component)
snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_ANA_HPHPA_FSM_CLK, 0x11, 0x00);
ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_ANA_NCP_EN, 0x01, 0x00);
rouleur_global_mbias_disable(component);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x20, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x10, 0x00);
rouleur_global_mbias_disable(component);
}
mutex_unlock(&rouleur->rx_clk_lock);
@ -478,8 +481,15 @@ static int rouleur_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
0x01, 0x00);
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
0x01, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
0x04, 0x00);
if (rouleur->comp1_enable)
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
0x02, 0x00);
break;
}
@ -544,6 +554,13 @@ static int rouleur_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x02, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
0x08, 0x00);
if (rouleur->comp2_enable)
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_COMP_CTL_0,
0x01, 0x00);
break;
}
@ -567,18 +584,21 @@ static int rouleur_codec_ear_lo_dac_event(struct snd_soc_dapm_widget *w,
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX0_CTL,
0x7C, 0x7C);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
0x01, 0x01);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
0x04, 0x04);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
0x01, 0x01);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
0x01, 0x00);
snd_soc_component_update_bits(component,
ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
0x04, 0x00);
break;
};

View File

@ -80,8 +80,22 @@ static int wcd_measure_adc_continuous(struct wcd_mbhc *mbhc)
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
/* Set the MUX selection to IN2P */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MUX_CTL, MUX_CTL_IN2P);
/*
* Current source mode requires Auto zeroing to be enabled
* automatically. If HW doesn't do it, SW has to take care of this
* for button interrupts to work fine and to avoid
* fake electrical removal interrupts by enabling autozero before FSM
* enable and disable it after FSM enable
*/
if (mbhc->mbhc_cb->mbhc_comp_autozero_control)
mbhc->mbhc_cb->mbhc_comp_autozero_control(mbhc,
true);
/* Enable MBHC FSM */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1);
if (mbhc->mbhc_cb->mbhc_comp_autozero_control)
mbhc->mbhc_cb->mbhc_comp_autozero_control(mbhc,
false);
/* Enable ADC_ENABLE bit */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 1);
@ -294,6 +308,10 @@ static int wcd_check_cross_conn(struct wcd_mbhc *mbhc)
WCD_MBHC_REG_READ(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl);
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0x00);
/* Disable surge detection before ADC measurement */
if (mbhc->mbhc_cb->mbhc_surge_ctl)
mbhc->mbhc_cb->mbhc_surge_ctl(mbhc, false);
/* Read and set ADC to single measurement */
WCD_MBHC_REG_READ(WCD_MBHC_ADC_MODE, adc_mode);
/* Read ADC Enable bit to restore after adc measurement */
@ -317,7 +335,12 @@ static int wcd_check_cross_conn(struct wcd_mbhc *mbhc)
goto done;
}
if (hphl_adc_res > 100 || hphr_adc_res > 100) {
/* Update cross connection threshold voltages if needed */
if (mbhc->mbhc_cb->update_cross_conn_thr)
mbhc->mbhc_cb->update_cross_conn_thr(mbhc);
if (hphl_adc_res > mbhc->hphl_cross_conn_thr ||
hphr_adc_res > mbhc->hphr_cross_conn_thr) {
plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP;
pr_debug("%s: Cross connection identified\n", __func__);
} else {
@ -339,6 +362,10 @@ done:
/* Restore FSM state */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, fsm_en);
/* Restore surge detection */
if (mbhc->mbhc_cb->mbhc_surge_ctl)
mbhc->mbhc_cb->mbhc_surge_ctl(mbhc, true);
/* Restore electrical detection */
WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl);

View File

@ -80,17 +80,13 @@ static void wcd_program_hs_vref(struct wcd_mbhc *mbhc)
struct snd_soc_component *component = mbhc->component;
u32 reg_val;
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);
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)
@ -999,14 +995,6 @@ 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)
@ -1084,10 +1072,6 @@ 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)
@ -1856,6 +1840,8 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_component *component,
mbhc->hph_type = WCD_MBHC_HPH_NONE;
mbhc->wcd_mbhc_regs = wcd_mbhc_regs;
mbhc->swap_thr = GND_MIC_SWAP_THRESHOLD;
mbhc->hphl_cross_conn_thr = HPHL_CROSS_CONN_THRESHOLD;
mbhc->hphr_cross_conn_thr = HPHR_CROSS_CONN_THRESHOLD;
if (mbhc->intr_ids == NULL) {
pr_err("%s: Interrupt mapping not provided\n", __func__);

View File

@ -145,6 +145,8 @@ do { \
#define FW_READ_ATTEMPTS 15
#define FW_READ_TIMEOUT 4000000
#define FAKE_REM_RETRY_ATTEMPTS 3
#define HPHL_CROSS_CONN_THRESHOLD 100
#define HPHR_CROSS_CONN_THRESHOLD 100
#define WCD_MBHC_BTN_PRESS_COMPL_TIMEOUT_MS 50
#define ANC_DETECT_RETRY_CNT 7
@ -456,12 +458,14 @@ struct wcd_mbhc_register {
};
struct wcd_mbhc_cb {
void (*mbhc_micb_pullup_control)
(struct snd_soc_component *component, bool enable);
void (*update_cross_conn_thr)
(struct wcd_mbhc *mbhc);
void (*mbhc_surge_ctl)
(struct wcd_mbhc *mbhc, bool surge_en);
void (*mbhc_comp_autozero_control)
(struct wcd_mbhc *mbhc, bool az_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);
@ -557,6 +561,8 @@ struct wcd_mbhc {
u32 moist_vref;
u32 moist_iref;
u32 moist_rref;
u32 hphl_cross_conn_thr;
u32 hphr_cross_conn_thr;
u8 micbias1_cap_mode; /* track ext cap setting */
u8 micbias2_cap_mode; /* track ext cap setting */
bool hs_detect_work_stop;