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;