[PATCH v1 3/4] ASoC: codecs: pm4125: Keep the micbias reference count balanced
From: Mohammad Rafi Shaik
Date: Thu Oct 15 2026 - 10:48:12 EST
The analog master bias is shared between the microphone bias supplies
and the playback and capture paths, so pm4125_global_mbias_enable() and
pm4125_global_mbias_disable() reference count it and only touch
PM4125_ANA_MBIAS_EN for the first user and the last one.
MICB_DISABLE clamps the per-supply reference count at zero but then
evaluates the enable and pull-up counts regardless, so a release that
has no matching request still reaches pm4125_global_mbias_disable() and
drops a reference it never took. The MBHC framework issues exactly such
a release: it takes MIC_BIAS_2 once when it starts detecting a plug
type and releases it both at the end of the correction work and again
from wcd_micbias_disable(). Inserting a jack while a stream is running
therefore switches the analog master bias off underneath it, leaving
the path up but silent, and it stays silent until another stream takes
the first reference again.
Return early when there is nothing to release, so the hardware is only
touched for a request that was actually made.
While at it, use atomic_dec_if_positive() for the global count.
atomic_dec_and_test() lets it go negative, and once it is negative the
next enable increments it to zero instead of one and never re-arms the
bias at all.
Assisted-by: Claude Opus 5
Signed-off-by: Mohammad Rafi Shaik <mohammad.rafi.shaik@xxxxxxxxxxxxxxxx>
---
sound/soc/codecs/pm4125.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/pm4125.c b/sound/soc/codecs/pm4125.c
index 923318c78..2100f4e36 100644
--- a/sound/soc/codecs/pm4125.c
+++ b/sound/soc/codecs/pm4125.c
@@ -229,7 +229,7 @@ static int pm4125_global_mbias_disable(struct snd_soc_component *component)
{
struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
- if (atomic_dec_and_test(&pm4125->gloal_mbias_cnt)) {
+ if (atomic_dec_if_positive(&pm4125->gloal_mbias_cnt) == 0) {
snd_soc_component_write_field(component, PM4125_ANA_MBIAS_EN,
PM4125_ANA_MBIAS_EN_V2I_MASK,
@@ -772,8 +772,18 @@ static int pm4125_micbias_control(struct snd_soc_component *component, int micb_
}
break;
case MICB_DISABLE:
- if (pm4125->micb_ref[micb_index] > 0)
- pm4125->micb_ref[micb_index]--;
+ /*
+ * Ignore a release that has no matching request. The MBHC
+ * framework releases MIC_BIAS_2 once when the plug type
+ * correction work ends and again when it turns the bias off,
+ * and honouring the second one would drop a reference on the
+ * shared global mbias that was never taken, switching the
+ * analog master bias off under an active stream.
+ */
+ if (!pm4125->micb_ref[micb_index])
+ break;
+
+ pm4125->micb_ref[micb_index]--;
if ((pm4125->micb_ref[micb_index] == 0) &&
(pm4125->pullup_ref[micb_index] > 0)) {
snd_soc_component_update_bits(component, micb_reg,
--
2.34.1