Merge "ASoC: wcd9xxx: Enable MBHC TxFE when micbias is enabled"
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 97bfaf6..93c18ba 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -1572,15 +1572,20 @@
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
+ struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
u16 micb_int_reg;
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 MSM8X10_WCD_A_MICB_1_CTL:
micb_int_reg = MSM8X10_WCD_A_MICB_1_INT_RBIAS;
+ 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;
default:
dev_err(codec->dev,
@@ -1591,6 +1596,9 @@
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ /* Let MBHC module know micbias is about to turn ON */
+ wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_pre_on);
+
if (strnstr(w->name, internal1_text, 30))
snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x80);
else if (strnstr(w->name, internal2_text, 30))
@@ -1600,8 +1608,13 @@
break;
case SND_SOC_DAPM_POST_PMU:
usleep_range(20000, 20100);
+ /* Let MBHC module know so micbias is on */
+ wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_on);
break;
case SND_SOC_DAPM_POST_PMD:
+ /* Let MBHC module know so micbias switch to be off */
+ wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_off);
+
if (strnstr(w->name, internal1_text, 30))
snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
else if (strnstr(w->name, internal2_text, 30))
@@ -2642,6 +2655,12 @@
snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_TOP_CLK_CTL, 0x10, 0x10);
}
+static void msm8x10_wcd_mbhc_txfe(struct snd_soc_codec *codec, bool on)
+{
+ snd_soc_update_bits(codec, MSM8X10_WCD_A_TX_7_MBHC_EN_ATEST_CTRL,
+ 0x80, on ? 0x80 : 0x00);
+}
+
static const struct wcd9xxx_mbhc_cb mbhc_cb = {
.enable_mux_bias_block = msm8x10_wcd_enable_mux_bias_block,
.cfilt_fast_mode = msm8x10_wcd_put_cfilt_fast_mode,
@@ -2652,6 +2671,7 @@
.free_irq = msm8x10_wcd_free_irq,
.get_cdc_type = msm8x10_wcd_get_cdc_type,
.enable_clock_gate = msm8x10_wcd_mbhc_clk_gate,
+ .enable_mbhc_txfe = msm8x10_wcd_mbhc_txfe,
};
static void delayed_hs_detect_fn(struct work_struct *work)
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index a9e0c43..c1e696d 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -4047,6 +4047,15 @@
return cfilt;
}
+static void wcd9xxx_enable_mbhc_txfe(struct wcd9xxx_mbhc *mbhc, bool on)
+{
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mbhc_txfe)
+ mbhc->mbhc_cb->enable_mbhc_txfe(mbhc->codec, on);
+ else
+ snd_soc_update_bits(mbhc->codec, WCD9XXX_A_TX_7_MBHC_TEST_CTL,
+ 0x40, on ? 0x40 : 0x00);
+}
+
static int wcd9xxx_event_notify(struct notifier_block *self, unsigned long val,
void *data)
{
@@ -4064,14 +4073,22 @@
case WCD9XXX_EVENT_PRE_MICBIAS_2_ON:
case WCD9XXX_EVENT_PRE_MICBIAS_3_ON:
case WCD9XXX_EVENT_PRE_MICBIAS_4_ON:
- if (mbhc->mbhc_cfg->micbias == wcd9xxx_event_to_micbias(event))
+ if (mbhc->mbhc_cfg && mbhc->mbhc_cfg->micbias ==
+ wcd9xxx_event_to_micbias(event)) {
wcd9xxx_switch_micbias(mbhc, 0);
+ /*
+ * Enable MBHC TxFE whenever micbias is
+ * turned ON and polling is active
+ */
+ if (mbhc->polling_active)
+ wcd9xxx_enable_mbhc_txfe(mbhc, true);
+ }
break;
case WCD9XXX_EVENT_POST_MICBIAS_1_ON:
case WCD9XXX_EVENT_POST_MICBIAS_2_ON:
case WCD9XXX_EVENT_POST_MICBIAS_3_ON:
case WCD9XXX_EVENT_POST_MICBIAS_4_ON:
- if (mbhc->mbhc_cfg->micbias ==
+ if (mbhc->mbhc_cfg && mbhc->mbhc_cfg->micbias ==
wcd9xxx_event_to_micbias(event) &&
wcd9xxx_mbhc_polling(mbhc)) {
/* if polling is on, restart it */
@@ -4083,11 +4100,17 @@
case WCD9XXX_EVENT_POST_MICBIAS_2_OFF:
case WCD9XXX_EVENT_POST_MICBIAS_3_OFF:
case WCD9XXX_EVENT_POST_MICBIAS_4_OFF:
- if (mbhc->mbhc_cfg->micbias ==
- wcd9xxx_event_to_micbias(event) &&
- (mbhc->event_state &
- (1 << MBHC_EVENT_PA_HPHL | 1 << MBHC_EVENT_PA_HPHR)))
- wcd9xxx_switch_micbias(mbhc, 1);
+ if (mbhc->mbhc_cfg && mbhc->mbhc_cfg->micbias ==
+ wcd9xxx_event_to_micbias(event)) {
+ if (mbhc->event_state &
+ (1 << MBHC_EVENT_PA_HPHL | 1 << MBHC_EVENT_PA_HPHR))
+ wcd9xxx_switch_micbias(mbhc, 1);
+ /*
+ * Disable MBHC TxFE, in case it was enabled
+ * earlier when micbias was enabled.
+ */
+ wcd9xxx_enable_mbhc_txfe(mbhc, false);
+ }
break;
/* PA usage change */
case WCD9XXX_EVENT_PRE_HPHL_PA_ON:
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index e5259c3..2e502cd 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.h
@@ -250,6 +250,7 @@
int (*setup_zdet) (struct wcd9xxx_mbhc *,
enum mbhc_impedance_detect_stages stage);
void (*compute_impedance) (s16 *, s16 *, uint32_t *, uint32_t *);
+ void (*enable_mbhc_txfe) (struct snd_soc_codec *, bool);
};
struct wcd9xxx_mbhc {