From 02d90cd42dafc401b2da437fedbef233a7bd5aeb Mon Sep 17 00:00:00 2001 From: Bhalchandra Gajare Date: Fri, 30 Sep 2011 16:14:00 -0700 Subject: [PATCH] ASoC: WCD9310: Include the MBHC mic bias registers in private data The microphone bias that MBHC uses will be board specific and will not change once it is decided for the board. Add common function to compute the commonly used mbhc mic bias registers and save them in private data so that these do not have to be computed each time. Change-Id: Ibd0f1029cd8ca663d32e3e2eac0cc76c1e110abe Signed-off-by: Bhalchandra Gajare --- sound/soc/codecs/wcd9310.c | 221 +++++++++++++++---------------------- 1 file changed, 89 insertions(+), 132 deletions(-) diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c index ec31c0fdf49..09f694ae5a5 100644 --- a/sound/soc/codecs/wcd9310.c +++ b/sound/soc/codecs/wcd9310.c @@ -47,6 +47,14 @@ enum tabla_bandgap_type { TABLA_BANDGAP_MBHC_MODE, }; +struct mbhc_micbias_regs { + u16 cfilt_val; + u16 cfilt_ctl; + u16 mbhc_reg; + u16 int_rbias; + u16 ctl_reg; +}; + struct tabla_priv { struct snd_soc_codec *codec; u32 adc_count; @@ -72,6 +80,8 @@ struct tabla_priv { bool no_mic_headset_override; /* Delayed work to report long button press */ struct delayed_work btn0_dwork; + + struct mbhc_micbias_regs mbhc_bias_regs; }; #ifdef CONFIG_DEBUG_FS @@ -1091,6 +1101,59 @@ static int tabla_hph_pa_event(struct snd_soc_dapm_widget *w, return 0; } +static void tabla_get_mbhc_micbias_regs(struct snd_soc_codec *codec, + struct mbhc_micbias_regs *micbias_regs) +{ + struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec); + struct tabla_mbhc_calibration *calibration = tabla->calibration; + unsigned int cfilt; + + switch (calibration->bias) { + case TABLA_MICBIAS1: + cfilt = tabla->pdata->micbias.bias1_cfilt_sel; + micbias_regs->mbhc_reg = TABLA_A_MICB_1_MBHC; + micbias_regs->int_rbias = TABLA_A_MICB_1_INT_RBIAS; + micbias_regs->ctl_reg = TABLA_A_MICB_1_CTL; + break; + case TABLA_MICBIAS2: + cfilt = tabla->pdata->micbias.bias2_cfilt_sel; + micbias_regs->mbhc_reg = TABLA_A_MICB_2_MBHC; + micbias_regs->int_rbias = TABLA_A_MICB_2_INT_RBIAS; + micbias_regs->ctl_reg = TABLA_A_MICB_2_CTL; + break; + case TABLA_MICBIAS3: + cfilt = tabla->pdata->micbias.bias3_cfilt_sel; + micbias_regs->mbhc_reg = TABLA_A_MICB_3_MBHC; + micbias_regs->int_rbias = TABLA_A_MICB_3_INT_RBIAS; + micbias_regs->ctl_reg = TABLA_A_MICB_3_CTL; + break; + case TABLA_MICBIAS4: + cfilt = tabla->pdata->micbias.bias4_cfilt_sel; + micbias_regs->mbhc_reg = TABLA_A_MICB_4_MBHC; + micbias_regs->int_rbias = TABLA_A_MICB_4_INT_RBIAS; + micbias_regs->ctl_reg = TABLA_A_MICB_4_CTL; + break; + default: + /* Should never reach here */ + pr_err("%s: Invalid MIC BIAS for MBHC\n", __func__); + } + + switch (cfilt) { + case TABLA_CFILT1_SEL: + micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_1_VAL; + micbias_regs->cfilt_ctl = TABLA_A_MICB_CFILT_1_CTL; + break; + case TABLA_CFILT2_SEL: + micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_2_VAL; + micbias_regs->cfilt_ctl = TABLA_A_MICB_CFILT_2_CTL; + break; + case TABLA_CFILT3_SEL: + micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_3_VAL; + micbias_regs->cfilt_ctl = TABLA_A_MICB_CFILT_3_CTL; + break; + } +} + static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = { /*RX stuff */ SND_SOC_DAPM_OUTPUT("EAR"), @@ -2035,10 +2098,7 @@ static short tabla_codec_setup_hs_polling(struct snd_soc_codec *codec) { struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec); struct tabla_mbhc_calibration *calibration = tabla->calibration; - int micbias_ctl_reg, micbias_cfilt_ctl_reg, - micbias_mbhc_reg; short bias_value; - unsigned int cfilt_sel; if (!calibration) { pr_err("Error, no tabla calibration\n"); @@ -2057,49 +2117,12 @@ static short tabla_codec_setup_hs_polling(struct snd_soc_codec *codec) snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0xE0); - /* select cfilt separately from the micbias line in the platform data */ - switch (calibration->bias) { - case TABLA_MICBIAS1: - micbias_ctl_reg = TABLA_A_MICB_1_CTL; - cfilt_sel = tabla->pdata->micbias.bias1_cfilt_sel; - micbias_mbhc_reg = TABLA_A_MICB_1_MBHC; - break; - case TABLA_MICBIAS2: - micbias_ctl_reg = TABLA_A_MICB_2_CTL; - cfilt_sel = tabla->pdata->micbias.bias2_cfilt_sel; - micbias_mbhc_reg = TABLA_A_MICB_2_MBHC; - break; - case TABLA_MICBIAS3: - micbias_ctl_reg = TABLA_A_MICB_3_CTL; - cfilt_sel = tabla->pdata->micbias.bias3_cfilt_sel; - micbias_mbhc_reg = TABLA_A_MICB_3_MBHC; - break; - case TABLA_MICBIAS4: - pr_err("%s: Error, microphone bias 4 not supported\n", - __func__); - return -EINVAL; - default: - pr_err("Error, invalid mic bias line\n"); - return -EINVAL; - } - switch (cfilt_sel) { - case TABLA_CFILT1_SEL: - micbias_cfilt_ctl_reg = TABLA_A_MICB_CFILT_1_CTL; - break; - case TABLA_CFILT2_SEL: - micbias_cfilt_ctl_reg = TABLA_A_MICB_CFILT_2_CTL; - break; - case TABLA_CFILT3_SEL: - micbias_cfilt_ctl_reg = TABLA_A_MICB_CFILT_3_CTL; - break; - default: /* default should not happen as check should have been done */ - return -EINVAL; - } + snd_soc_update_bits(codec, + tabla->mbhc_bias_regs.cfilt_ctl, 0x70, 0x00); - snd_soc_update_bits(codec, micbias_cfilt_ctl_reg, 0x70, 0x00); - - snd_soc_update_bits(codec, micbias_ctl_reg, 0x1F, 0x16); + snd_soc_update_bits(codec, + tabla->mbhc_bias_regs.ctl_reg, 0x1F, 0x16); snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x2, 0x2); snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84); @@ -2115,13 +2138,15 @@ static short tabla_codec_setup_hs_polling(struct snd_soc_codec *codec) snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x6, 0x6); snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8); - snd_soc_update_bits(codec, micbias_mbhc_reg, 0x10, 0x10); + snd_soc_update_bits(codec, + tabla->mbhc_bias_regs.mbhc_reg, 0x10, 0x10); snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x01); tabla_codec_calibrate_hs_polling(codec); bias_value = tabla_codec_measure_micbias_voltage(codec, 0); - snd_soc_update_bits(codec, micbias_cfilt_ctl_reg, 0x40, 0x40); + snd_soc_update_bits(codec, + tabla->mbhc_bias_regs.cfilt_ctl, 0x40, 0x40); snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x00); return bias_value; @@ -2133,7 +2158,6 @@ static int tabla_codec_enable_hs_detect(struct snd_soc_codec *codec, struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec); struct tabla_mbhc_calibration *calibration = tabla->calibration; int central_bias_enabled = 0; - int micbias_int_reg, micbias_ctl_reg, micbias_mbhc_reg; if (!calibration) { pr_err("Error, no tabla calibration\n"); @@ -2169,33 +2193,8 @@ static int tabla_codec_enable_hs_detect(struct snd_soc_codec *codec, snd_soc_update_bits(codec, TABLA_A_RX_HPH_CNP_EN, 0x30, 0x00); snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x13); - switch (calibration->bias) { - case TABLA_MICBIAS1: - micbias_mbhc_reg = TABLA_A_MICB_1_MBHC; - micbias_int_reg = TABLA_A_MICB_1_INT_RBIAS; - micbias_ctl_reg = TABLA_A_MICB_1_CTL; - break; - case TABLA_MICBIAS2: - micbias_mbhc_reg = TABLA_A_MICB_2_MBHC; - micbias_int_reg = TABLA_A_MICB_2_INT_RBIAS; - micbias_ctl_reg = TABLA_A_MICB_2_CTL; - break; - case TABLA_MICBIAS3: - micbias_mbhc_reg = TABLA_A_MICB_3_MBHC; - micbias_int_reg = TABLA_A_MICB_3_INT_RBIAS; - micbias_ctl_reg = TABLA_A_MICB_3_CTL; - break; - case TABLA_MICBIAS4: - micbias_mbhc_reg = TABLA_A_MICB_4_MBHC; - micbias_int_reg = TABLA_A_MICB_4_INT_RBIAS; - micbias_ctl_reg = TABLA_A_MICB_4_CTL; - break; - default: - pr_err("Error, invalid mic bias line\n"); - return -EINVAL; - } - snd_soc_update_bits(codec, micbias_int_reg, 0x80, 0); - snd_soc_update_bits(codec, micbias_ctl_reg, 0x1, 0); + snd_soc_update_bits(codec, tabla->mbhc_bias_regs.int_rbias, 0x80, 0); + snd_soc_update_bits(codec, tabla->mbhc_bias_regs.ctl_reg, 0x1, 0); /* If central bandgap disabled */ if (!(snd_soc_read(codec, TABLA_A_PIN_CTL_OE1) & 1)) { @@ -2215,12 +2214,12 @@ static int tabla_codec_enable_hs_detect(struct snd_soc_codec *codec, if (central_bias_enabled) snd_soc_update_bits(codec, TABLA_A_PIN_CTL_OE1, 0x1, 0); } - snd_soc_update_bits(codec, micbias_mbhc_reg, 0x60, + snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg, 0x60, calibration->mic_current << 5); - snd_soc_update_bits(codec, micbias_mbhc_reg, 0x80, 0x80); + snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg, 0x80, 0x80); usleep_range(calibration->mic_pid, calibration->mic_pid); - snd_soc_update_bits(codec, micbias_mbhc_reg, 0x10, 0x10); + snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg, 0x10, 0x10); snd_soc_update_bits(codec, TABLA_A_MICB_4_MBHC, 0x3, calibration->bias); @@ -2264,6 +2263,7 @@ int tabla_hs_detect(struct snd_soc_codec *codec, tabla->headset_jack = headset_jack; tabla->button_jack = button_jack; tabla->calibration = calibration; + tabla_get_mbhc_micbias_regs(codec, &tabla->mbhc_bias_regs); INIT_DELAYED_WORK(&tabla->btn0_dwork, btn0_lpress_fn); return tabla_codec_enable_hs_detect(codec, 1); @@ -2355,7 +2355,6 @@ static void tabla_codec_shutdown_hs_removal_detect(struct snd_soc_codec *codec) { struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec); struct tabla_mbhc_calibration *calibration = tabla->calibration; - int micbias_mbhc_reg; if (!tabla->mclk_enabled && !tabla->mbhc_polling_active) tabla_codec_enable_config_mode(codec, 1); @@ -2363,24 +2362,8 @@ static void tabla_codec_shutdown_hs_removal_detect(struct snd_soc_codec *codec) snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x2, 0x2); snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x6, 0x0); - switch (calibration->bias) { - case TABLA_MICBIAS1: - micbias_mbhc_reg = TABLA_A_MICB_1_MBHC; - break; - case TABLA_MICBIAS2: - micbias_mbhc_reg = TABLA_A_MICB_2_MBHC; - break; - case TABLA_MICBIAS3: - micbias_mbhc_reg = TABLA_A_MICB_3_MBHC; - break; - case TABLA_MICBIAS4: - micbias_mbhc_reg = TABLA_A_MICB_4_MBHC; - break; - default: - pr_err("Error, invalid mic bias line\n"); - return; - } - snd_soc_update_bits(codec, micbias_mbhc_reg, 0x80, 0x00); + snd_soc_update_bits(codec, + tabla->mbhc_bias_regs.mbhc_reg, 0x80, 0x00); usleep_range(calibration->shutdown_plug_removal, calibration->shutdown_plug_removal); @@ -2411,7 +2394,6 @@ static irqreturn_t tabla_hs_insert_irq(int irq, void *data) struct tabla_priv *priv = data; struct snd_soc_codec *codec = priv->codec; int ldo_h_on, micb_cfilt_on; - int micbias_cfilt_ctl_reg, cfilt_sel; short mic_voltage; short threshold_no_mic = 0xF7F6; short threshold_fake_insert = 0xFD30; @@ -2420,45 +2402,15 @@ static irqreturn_t tabla_hs_insert_irq(int irq, void *data) pr_debug("%s\n", __func__); tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION); - switch (priv->calibration->bias) { - case TABLA_MICBIAS1: - cfilt_sel = priv->pdata->micbias.bias1_cfilt_sel; - break; - case TABLA_MICBIAS2: - cfilt_sel = priv->pdata->micbias.bias2_cfilt_sel; - break; - case TABLA_MICBIAS3: - cfilt_sel = priv->pdata->micbias.bias3_cfilt_sel; - break; - default: - pr_err("%s: Error, invalid mic bias line, bias value = %d\n", - __func__, priv->calibration->bias); - return IRQ_HANDLED; - } - - switch (cfilt_sel) { - case TABLA_CFILT1_SEL: - micbias_cfilt_ctl_reg = TABLA_A_MICB_CFILT_1_CTL; - break; - case TABLA_CFILT2_SEL: - micbias_cfilt_ctl_reg = TABLA_A_MICB_CFILT_2_CTL; - break; - case TABLA_CFILT3_SEL: - micbias_cfilt_ctl_reg = TABLA_A_MICB_CFILT_3_CTL; - break; - default: /* default should not happen as check should have been done */ - pr_err("%s: Invalid cfilt select, cfilt_sel = %d\n", - __func__, cfilt_sel); - return IRQ_HANDLED; - } - ldo_h_on = snd_soc_read(codec, TABLA_A_LDO_H_MODE_1) & 0x80; - micb_cfilt_on = snd_soc_read(codec, micbias_cfilt_ctl_reg) & 0x80; + micb_cfilt_on = snd_soc_read(codec, + priv->mbhc_bias_regs.cfilt_ctl) & 0x80; if (!ldo_h_on) snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x80, 0x80); if (!micb_cfilt_on) - snd_soc_update_bits(codec, micbias_cfilt_ctl_reg, 0x80, 0x80); + snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl, + 0x80, 0x80); usleep_range(priv->calibration->setup_plug_removal_delay, priv->calibration->setup_plug_removal_delay); @@ -2477,7 +2429,8 @@ static irqreturn_t tabla_hs_insert_irq(int irq, void *data) if (!ldo_h_on) snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, 0x80, 0x0); if (!micb_cfilt_on) - snd_soc_update_bits(codec, micbias_cfilt_ctl_reg, 0x80, 0x0); + snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl, + 0x80, 0x0); mic_voltage = tabla_codec_setup_hs_polling(codec); @@ -2811,6 +2764,10 @@ static int tabla_codec_probe(struct snd_soc_codec *codec) return -ENOMEM; } + /* Make sure mbhc micbias register addresses are zeroed out */ + memset(&tabla->mbhc_bias_regs, 0, + sizeof(struct mbhc_micbias_regs)); + snd_soc_codec_set_drvdata(codec, tabla); tabla->mclk_enabled = false;