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 <gajare@codeaurora.org>
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index ec31c0f..09f694a 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -47,6 +47,14 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
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;