Loading sound/soc/codecs/wcd9306.c +149 −29 Original line number Diff line number Diff line Loading @@ -42,6 +42,8 @@ #define TAPAN_HPH_PA_SETTLE_COMP_ON 3000 #define TAPAN_HPH_PA_SETTLE_COMP_OFF 13000 #define DAPM_MICBIAS2_EXTERNAL_STANDALONE "MIC BIAS2 External Standalone" #define TAPAN_VDD_CX_OPTIMAL_UA 10000 #define TAPAN_VDD_CX_SLEEP_UA 2000 Loading Loading @@ -281,6 +283,8 @@ struct tapan_priv { s32 dmic_1_2_clk_cnt; s32 dmic_3_4_clk_cnt; s32 dmic_5_6_clk_cnt; s32 ldo_h_users; s32 micb_2_users; u32 anc_slot; bool anc_func; Loading Loading @@ -2180,38 +2184,37 @@ static int tapan_codec_enable_micbias(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec); u16 micb_int_reg; u16 micb_int_reg = 0, micb_ctl_reg = 0; u8 cfilt_sel_val = 0; char *internal1_text = "Internal1"; char *internal2_text = "Internal2"; char *internal3_text = "Internal3"; enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on; dev_dbg(codec->dev, "%s %d\n", __func__, event); switch (w->reg) { case TAPAN_A_MICB_1_CTL: pr_debug("%s: w->name %s event %d\n", __func__, w->name, event); if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1"))) { micb_ctl_reg = TAPAN_A_MICB_1_CTL; micb_int_reg = TAPAN_A_MICB_1_INT_RBIAS; cfilt_sel_val = tapan->resmgr.pdata->micbias.bias1_cfilt_sel; e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON; e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON; e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF; break; case TAPAN_A_MICB_2_CTL: } else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2"))) { micb_ctl_reg = TAPAN_A_MICB_2_CTL; micb_int_reg = TAPAN_A_MICB_2_INT_RBIAS; cfilt_sel_val = tapan->resmgr.pdata->micbias.bias2_cfilt_sel; e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_2_ON; e_post_on = WCD9XXX_EVENT_POST_MICBIAS_2_ON; e_post_off = WCD9XXX_EVENT_POST_MICBIAS_2_OFF; break; case TAPAN_A_MICB_3_CTL: } else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3"))) { micb_ctl_reg = TAPAN_A_MICB_3_CTL; micb_int_reg = TAPAN_A_MICB_3_INT_RBIAS; cfilt_sel_val = tapan->resmgr.pdata->micbias.bias3_cfilt_sel; e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_3_ON; e_post_on = WCD9XXX_EVENT_POST_MICBIAS_3_ON; e_post_off = WCD9XXX_EVENT_POST_MICBIAS_3_OFF; break; default: pr_err("%s: Error, invalid micbias register\n", __func__); } else { pr_err("%s: Error, invalid micbias %s\n", __func__, w->name); return -EINVAL; } Loading @@ -2230,6 +2233,20 @@ static int tapan_codec_enable_micbias(struct snd_soc_dapm_widget *w, else if (strnstr(w->name, internal3_text, 30)) snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3); if (micb_ctl_reg == TAPAN_A_MICB_2_CTL) { if (++tapan->micb_2_users == 1) wcd9xxx_resmgr_add_cond_update_bits( &tapan->resmgr, WCD9XXX_COND_HPH_MIC, micb_ctl_reg, w->shift, false); pr_debug("%s: micb_2_users %d\n", __func__, tapan->micb_2_users); } else snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift, 1 << w->shift); break; case SND_SOC_DAPM_POST_PMU: usleep_range(20000, 20000); Loading @@ -2237,6 +2254,22 @@ static int tapan_codec_enable_micbias(struct snd_soc_dapm_widget *w, wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_on); break; case SND_SOC_DAPM_POST_PMD: if (micb_ctl_reg == TAPAN_A_MICB_2_CTL) { if (--tapan->micb_2_users == 0) wcd9xxx_resmgr_rm_cond_update_bits( &tapan->resmgr, WCD9XXX_COND_HPH_MIC, micb_ctl_reg, 7, false); pr_debug("%s: micb_2_users %d\n", __func__, tapan->micb_2_users); WARN(tapan->micb_2_users < 0, "Unexpected micbias users %d\n", tapan->micb_2_users); } else snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift, 0); /* Let MBHC module know so micbias switch to be off */ wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_off); Loading @@ -2255,6 +2288,23 @@ static int tapan_codec_enable_micbias(struct snd_soc_dapm_widget *w, return 0; } /* called under codec_resource_lock acquisition */ static int tapan_enable_mbhc_micbias(struct snd_soc_codec *codec, bool enable) { int rc; if (enable) rc = snd_soc_dapm_force_enable_pin(&codec->dapm, DAPM_MICBIAS2_EXTERNAL_STANDALONE); else rc = snd_soc_dapm_disable_pin(&codec->dapm, DAPM_MICBIAS2_EXTERNAL_STANDALONE); if (!rc) snd_soc_dapm_sync(&codec->dapm); pr_debug("%s: leave ret %d\n", __func__, rc); return rc; } static void tx_hpf_corner_freq_callback(struct work_struct *work) { struct delayed_work *hpf_delayed_work; Loading Loading @@ -2486,18 +2536,68 @@ static int tapan_codec_enable_interpolator(struct snd_soc_dapm_widget *w, return 0; } static int tapan_codec_enable_ldo_h(struct snd_soc_dapm_widget *w, /* called under codec_resource_lock acquisition */ static int __tapan_codec_enable_ldo_h(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct tapan_priv *priv = snd_soc_codec_get_drvdata(codec); pr_debug("%s: enter\n", __func__); switch (event) { case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_PRE_PMU: /* * ldo_h_users is protected by codec->mutex, don't need * additional mutex */ if (++priv->ldo_h_users == 1) { WCD9XXX_BG_CLK_LOCK(&priv->resmgr); wcd9xxx_resmgr_get_bandgap(&priv->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE); wcd9xxx_resmgr_get_clk_block(&priv->resmgr, WCD9XXX_CLK_RCO); snd_soc_update_bits(codec, TAPAN_A_LDO_H_MODE_1, 1 << 7, 1 << 7); wcd9xxx_resmgr_put_clk_block(&priv->resmgr, WCD9XXX_CLK_RCO); WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr); pr_debug("%s: ldo_h_users %d\n", __func__, priv->ldo_h_users); /* LDO enable requires 1ms to settle down */ usleep_range(1000, 1010); } break; case SND_SOC_DAPM_POST_PMD: usleep_range(1000, 1000); if (--priv->ldo_h_users == 0) { WCD9XXX_BG_CLK_LOCK(&priv->resmgr); wcd9xxx_resmgr_get_clk_block(&priv->resmgr, WCD9XXX_CLK_RCO); snd_soc_update_bits(codec, TAPAN_A_LDO_H_MODE_1, 1 << 7, 0); wcd9xxx_resmgr_put_clk_block(&priv->resmgr, WCD9XXX_CLK_RCO); wcd9xxx_resmgr_put_bandgap(&priv->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE); WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr); pr_debug("%s: ldo_h_users %d\n", __func__, priv->ldo_h_users); } WARN(priv->ldo_h_users < 0, "Unexpected ldo_h users %d\n", priv->ldo_h_users); break; } pr_debug("%s: leave\n", __func__); return 0; } static int tapan_codec_enable_ldo_h(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { int rc; rc = __tapan_codec_enable_ldo_h(w, kcontrol, event); return rc; } static int tapan_codec_enable_rx_bias(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { Loading Loading @@ -3068,6 +3168,7 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MIC BIAS2 Internal2", NULL, "LDO_H"}, {"MIC BIAS2 Internal3", NULL, "LDO_H"}, {"MIC BIAS2 External", NULL, "LDO_H"}, {DAPM_MICBIAS2_EXTERNAL_STANDALONE, NULL, "LDO_H Standalone"}, }; static const struct snd_soc_dapm_route wcd9302_map[] = { Loading Loading @@ -4284,13 +4385,13 @@ static const struct snd_soc_dapm_widget tapan_9306_dapm_widgets[] = { SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux), SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TAPAN_A_MICB_3_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TAPAN_A_MICB_3_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TAPAN_A_MICB_3_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), Loading Loading @@ -4513,17 +4614,27 @@ static const struct snd_soc_dapm_widget tapan_common_dapm_widgets[] = { SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("LDO_H", TAPAN_A_LDO_H_MODE_1, 7, 0, tapan_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_SUPPLY("LDO_H", SND_SOC_NOPM, 7, 0, tapan_codec_enable_ldo_h, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), /* * DAPM 'LDO_H Standalone' is to be powered by mbhc driver after * acquring codec_resource lock. * So call __tapan_codec_enable_ldo_h instead and avoid deadlock. */ SND_SOC_DAPM_SUPPLY("LDO_H Standalone", SND_SOC_NOPM, 7, 0, __tapan_codec_enable_ldo_h, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_INPUT("AMIC1"), SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAPAN_A_MICB_1_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TAPAN_A_MICB_1_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TAPAN_A_MICB_1_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), Loading @@ -4545,19 +4656,24 @@ static const struct snd_soc_dapm_widget tapan_common_dapm_widgets[] = { SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_INPUT("AMIC2"), SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TAPAN_A_MICB_2_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TAPAN_A_MICB_2_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TAPAN_A_MICB_2_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TAPAN_A_MICB_2_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS2_EXTERNAL_STANDALONE, SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM, AIF1_CAP, 0, tapan_codec_enable_slimtx, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), Loading Loading @@ -5555,7 +5671,8 @@ static int tapan_post_reset_cb(struct wcd9xxx *wcd9xxx) else rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ; ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL, ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, tapan_enable_mbhc_micbias, &mbhc_cb, &cdc_intr_ids, rco_clk_rate, TAPAN_CDC_ZDET_SUPPORTED); if (ret) Loading Loading @@ -5779,7 +5896,8 @@ static int tapan_codec_probe(struct snd_soc_codec *codec) else rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ; ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL, ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, tapan_enable_mbhc_micbias, &mbhc_cb, &cdc_intr_ids, rco_clk_rate, TAPAN_CDC_ZDET_SUPPORTED); Loading @@ -5797,6 +5915,8 @@ static int tapan_codec_probe(struct snd_soc_codec *codec) tapan->aux_pga_cnt = 0; tapan->aux_l_gain = 0x1F; tapan->aux_r_gain = 0x1F; tapan->ldo_h_users = 0; tapan->micb_2_users = 0; tapan_update_reg_defaults(codec); tapan_update_reg_mclk_rate(wcd9xxx); tapan_codec_init_reg(codec); Loading Loading
sound/soc/codecs/wcd9306.c +149 −29 Original line number Diff line number Diff line Loading @@ -42,6 +42,8 @@ #define TAPAN_HPH_PA_SETTLE_COMP_ON 3000 #define TAPAN_HPH_PA_SETTLE_COMP_OFF 13000 #define DAPM_MICBIAS2_EXTERNAL_STANDALONE "MIC BIAS2 External Standalone" #define TAPAN_VDD_CX_OPTIMAL_UA 10000 #define TAPAN_VDD_CX_SLEEP_UA 2000 Loading Loading @@ -281,6 +283,8 @@ struct tapan_priv { s32 dmic_1_2_clk_cnt; s32 dmic_3_4_clk_cnt; s32 dmic_5_6_clk_cnt; s32 ldo_h_users; s32 micb_2_users; u32 anc_slot; bool anc_func; Loading Loading @@ -2180,38 +2184,37 @@ static int tapan_codec_enable_micbias(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec); u16 micb_int_reg; u16 micb_int_reg = 0, micb_ctl_reg = 0; u8 cfilt_sel_val = 0; char *internal1_text = "Internal1"; char *internal2_text = "Internal2"; char *internal3_text = "Internal3"; enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on; dev_dbg(codec->dev, "%s %d\n", __func__, event); switch (w->reg) { case TAPAN_A_MICB_1_CTL: pr_debug("%s: w->name %s event %d\n", __func__, w->name, event); if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1"))) { micb_ctl_reg = TAPAN_A_MICB_1_CTL; micb_int_reg = TAPAN_A_MICB_1_INT_RBIAS; cfilt_sel_val = tapan->resmgr.pdata->micbias.bias1_cfilt_sel; e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON; e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON; e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF; break; case TAPAN_A_MICB_2_CTL: } else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2"))) { micb_ctl_reg = TAPAN_A_MICB_2_CTL; micb_int_reg = TAPAN_A_MICB_2_INT_RBIAS; cfilt_sel_val = tapan->resmgr.pdata->micbias.bias2_cfilt_sel; e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_2_ON; e_post_on = WCD9XXX_EVENT_POST_MICBIAS_2_ON; e_post_off = WCD9XXX_EVENT_POST_MICBIAS_2_OFF; break; case TAPAN_A_MICB_3_CTL: } else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3"))) { micb_ctl_reg = TAPAN_A_MICB_3_CTL; micb_int_reg = TAPAN_A_MICB_3_INT_RBIAS; cfilt_sel_val = tapan->resmgr.pdata->micbias.bias3_cfilt_sel; e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_3_ON; e_post_on = WCD9XXX_EVENT_POST_MICBIAS_3_ON; e_post_off = WCD9XXX_EVENT_POST_MICBIAS_3_OFF; break; default: pr_err("%s: Error, invalid micbias register\n", __func__); } else { pr_err("%s: Error, invalid micbias %s\n", __func__, w->name); return -EINVAL; } Loading @@ -2230,6 +2233,20 @@ static int tapan_codec_enable_micbias(struct snd_soc_dapm_widget *w, else if (strnstr(w->name, internal3_text, 30)) snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3); if (micb_ctl_reg == TAPAN_A_MICB_2_CTL) { if (++tapan->micb_2_users == 1) wcd9xxx_resmgr_add_cond_update_bits( &tapan->resmgr, WCD9XXX_COND_HPH_MIC, micb_ctl_reg, w->shift, false); pr_debug("%s: micb_2_users %d\n", __func__, tapan->micb_2_users); } else snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift, 1 << w->shift); break; case SND_SOC_DAPM_POST_PMU: usleep_range(20000, 20000); Loading @@ -2237,6 +2254,22 @@ static int tapan_codec_enable_micbias(struct snd_soc_dapm_widget *w, wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_on); break; case SND_SOC_DAPM_POST_PMD: if (micb_ctl_reg == TAPAN_A_MICB_2_CTL) { if (--tapan->micb_2_users == 0) wcd9xxx_resmgr_rm_cond_update_bits( &tapan->resmgr, WCD9XXX_COND_HPH_MIC, micb_ctl_reg, 7, false); pr_debug("%s: micb_2_users %d\n", __func__, tapan->micb_2_users); WARN(tapan->micb_2_users < 0, "Unexpected micbias users %d\n", tapan->micb_2_users); } else snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift, 0); /* Let MBHC module know so micbias switch to be off */ wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_off); Loading @@ -2255,6 +2288,23 @@ static int tapan_codec_enable_micbias(struct snd_soc_dapm_widget *w, return 0; } /* called under codec_resource_lock acquisition */ static int tapan_enable_mbhc_micbias(struct snd_soc_codec *codec, bool enable) { int rc; if (enable) rc = snd_soc_dapm_force_enable_pin(&codec->dapm, DAPM_MICBIAS2_EXTERNAL_STANDALONE); else rc = snd_soc_dapm_disable_pin(&codec->dapm, DAPM_MICBIAS2_EXTERNAL_STANDALONE); if (!rc) snd_soc_dapm_sync(&codec->dapm); pr_debug("%s: leave ret %d\n", __func__, rc); return rc; } static void tx_hpf_corner_freq_callback(struct work_struct *work) { struct delayed_work *hpf_delayed_work; Loading Loading @@ -2486,18 +2536,68 @@ static int tapan_codec_enable_interpolator(struct snd_soc_dapm_widget *w, return 0; } static int tapan_codec_enable_ldo_h(struct snd_soc_dapm_widget *w, /* called under codec_resource_lock acquisition */ static int __tapan_codec_enable_ldo_h(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct tapan_priv *priv = snd_soc_codec_get_drvdata(codec); pr_debug("%s: enter\n", __func__); switch (event) { case SND_SOC_DAPM_POST_PMU: case SND_SOC_DAPM_PRE_PMU: /* * ldo_h_users is protected by codec->mutex, don't need * additional mutex */ if (++priv->ldo_h_users == 1) { WCD9XXX_BG_CLK_LOCK(&priv->resmgr); wcd9xxx_resmgr_get_bandgap(&priv->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE); wcd9xxx_resmgr_get_clk_block(&priv->resmgr, WCD9XXX_CLK_RCO); snd_soc_update_bits(codec, TAPAN_A_LDO_H_MODE_1, 1 << 7, 1 << 7); wcd9xxx_resmgr_put_clk_block(&priv->resmgr, WCD9XXX_CLK_RCO); WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr); pr_debug("%s: ldo_h_users %d\n", __func__, priv->ldo_h_users); /* LDO enable requires 1ms to settle down */ usleep_range(1000, 1010); } break; case SND_SOC_DAPM_POST_PMD: usleep_range(1000, 1000); if (--priv->ldo_h_users == 0) { WCD9XXX_BG_CLK_LOCK(&priv->resmgr); wcd9xxx_resmgr_get_clk_block(&priv->resmgr, WCD9XXX_CLK_RCO); snd_soc_update_bits(codec, TAPAN_A_LDO_H_MODE_1, 1 << 7, 0); wcd9xxx_resmgr_put_clk_block(&priv->resmgr, WCD9XXX_CLK_RCO); wcd9xxx_resmgr_put_bandgap(&priv->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE); WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr); pr_debug("%s: ldo_h_users %d\n", __func__, priv->ldo_h_users); } WARN(priv->ldo_h_users < 0, "Unexpected ldo_h users %d\n", priv->ldo_h_users); break; } pr_debug("%s: leave\n", __func__); return 0; } static int tapan_codec_enable_ldo_h(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { int rc; rc = __tapan_codec_enable_ldo_h(w, kcontrol, event); return rc; } static int tapan_codec_enable_rx_bias(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { Loading Loading @@ -3068,6 +3168,7 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MIC BIAS2 Internal2", NULL, "LDO_H"}, {"MIC BIAS2 Internal3", NULL, "LDO_H"}, {"MIC BIAS2 External", NULL, "LDO_H"}, {DAPM_MICBIAS2_EXTERNAL_STANDALONE, NULL, "LDO_H Standalone"}, }; static const struct snd_soc_dapm_route wcd9302_map[] = { Loading Loading @@ -4284,13 +4385,13 @@ static const struct snd_soc_dapm_widget tapan_9306_dapm_widgets[] = { SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux), SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TAPAN_A_MICB_3_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TAPAN_A_MICB_3_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TAPAN_A_MICB_3_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), Loading Loading @@ -4513,17 +4614,27 @@ static const struct snd_soc_dapm_widget tapan_common_dapm_widgets[] = { SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("LDO_H", TAPAN_A_LDO_H_MODE_1, 7, 0, tapan_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_SUPPLY("LDO_H", SND_SOC_NOPM, 7, 0, tapan_codec_enable_ldo_h, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), /* * DAPM 'LDO_H Standalone' is to be powered by mbhc driver after * acquring codec_resource lock. * So call __tapan_codec_enable_ldo_h instead and avoid deadlock. */ SND_SOC_DAPM_SUPPLY("LDO_H Standalone", SND_SOC_NOPM, 7, 0, __tapan_codec_enable_ldo_h, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_INPUT("AMIC1"), SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAPAN_A_MICB_1_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TAPAN_A_MICB_1_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TAPAN_A_MICB_1_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), Loading @@ -4545,19 +4656,24 @@ static const struct snd_soc_dapm_widget tapan_common_dapm_widgets[] = { SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_INPUT("AMIC2"), SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TAPAN_A_MICB_2_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TAPAN_A_MICB_2_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TAPAN_A_MICB_2_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TAPAN_A_MICB_2_CTL, 7, 0, SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS2_EXTERNAL_STANDALONE, SND_SOC_NOPM, 7, 0, tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM, AIF1_CAP, 0, tapan_codec_enable_slimtx, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), Loading Loading @@ -5555,7 +5671,8 @@ static int tapan_post_reset_cb(struct wcd9xxx *wcd9xxx) else rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ; ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL, ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, tapan_enable_mbhc_micbias, &mbhc_cb, &cdc_intr_ids, rco_clk_rate, TAPAN_CDC_ZDET_SUPPORTED); if (ret) Loading Loading @@ -5779,7 +5896,8 @@ static int tapan_codec_probe(struct snd_soc_codec *codec) else rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ; ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL, ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, tapan_enable_mbhc_micbias, &mbhc_cb, &cdc_intr_ids, rco_clk_rate, TAPAN_CDC_ZDET_SUPPORTED); Loading @@ -5797,6 +5915,8 @@ static int tapan_codec_probe(struct snd_soc_codec *codec) tapan->aux_pga_cnt = 0; tapan->aux_l_gain = 0x1F; tapan->aux_r_gain = 0x1F; tapan->ldo_h_users = 0; tapan->micb_2_users = 0; tapan_update_reg_defaults(codec); tapan_update_reg_mclk_rate(wcd9xxx); tapan_codec_init_reg(codec); Loading