Linux Sound subsystem development
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Zhang Heng <zhangheng@kylinos.cn>
Cc: perex@perex.cz, tiwai@suse.com, linux-sound@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: Fwd: [PATCH] ALSA: hda/generic: Add mic autoswitch support for dyn_adc_switch mode
Date: Thu, 07 May 2026 17:05:46 +0200	[thread overview]
Message-ID: <87ecjnp8dx.wl-tiwai@suse.de> (raw)
In-Reply-To: <a7daf8a3-559b-4532-a2ee-a211a7e0e0b0@kylinos.cn>

On Wed, 06 May 2026 09:03:52 +0200,
Zhang Heng wrote:
> 
> 
> 
> 
> -------- 转发的消息 --------
> 主题: 	Re: [PATCH] ALSA: hda/generic: Add mic autoswitch support for
> dyn_adc_switch mode
> 日期: 	Wed, 6 May 2026 14:19:14 +0800
> 发件人: 	Zhang Heng <zhangheng@kylinos.cn>
> 收件人: 	Takashi Iwai <tiwai@suse.de>
> 
> 
> 
> 
> 在 2026/5/5 0:25, Takashi Iwai 写道:
> > On Sun, 03 May 2026 13:45:12 +0200,
> > Zhang Heng wrote:
> >> When auto_mic is not available but dyn_adc_switch mode is enabled
> >> (e.g., on laptops with both front and rear mic jacks), this patch
> >> enables automatic microphone switching based on jack detection.
> >> 
> >> The patch includes three changes:
> >> 
> >> 1. In check_dyn_adc_switch(): Register jack detect callbacks for
> >> all input pins when dyn_adc_switch is enabled and auto_mic is
> >> not available.
> >> 
> >> 2. In call_mic_autoswitch(): Add handling for dyn_adc_switch mode
> >> to check imux_pins[] for jack presence, searching from back to
> >> front (last inserted wins).
> >> 
> >> 3. In mux_select(): Notify Capture Source controls after switching
> >> to sync with user-space (PulseAudio/PipeWire).
> >> 
> >> Problem description:
> >> On Ubuntu 20.04 (with older PulseAudio/PipeWire):
> >> - Front mic is unplugged
> >> - Plug in rear mic
> >> - Jack event is reported correctly
> >> - Volume control (PulseAudio/PipeWire) recognizes the rear mic
> >> - But alsamixer does NOT switch to rear mic
> >> - Codec also does NOT perform the switch
> >> 
> >> The root cause is that in dyn_adc_switch mode without auto_mic,
> >> the jack detect callback was not properly set up to trigger the
> >> mic autoswitch. The call_mic_autoswitch() function only calls
> >> mic_autoswitch_hook or snd_hda_gen_mic_autoswitch(), which rely
> >> on auto_mic being enabled.
> >> 
> >> Additionally, after mux_select() performs the switch, user-space
> >> (PulseAudio/PipeWire) may not be aware of the path change,
> >> causing Capture Switch to show 'off'.
> >> 
> >> This patch fixes both issues by:
> >> 1. Registering jack detect callbacks for all input pins in
> >> dyn_adc_switch mode
> >> 2. Notifying Capture Source controls after switching
> >> 
> >> Tested on SN6186 codec with Ubuntu 20.04 and 25.10.
> >> 
> >> Question to the community: Is this approach correct? Should additional
> >> changes be made to handle mute state preservation, or is this purely
> >> a user-space issue that requires updating PulseAudio/PipeWire?
> >> 
> >> Testing and feedback are welcome.
> > I think the basic idea is OK. We can treat the auto-mic with dynamic
> > ADC switches, too.
> > 
> > But it's not clear what's the actual intent in your code changes:
> > 
> > 
> >> Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>
> >> ---
> >> sound/hda/codecs/generic.c | 82 ++++++++++++++++++++++++++++++++++++--
> >> 1 file changed, 79 insertions(+), 3 deletions(-)
> >> 
> >> diff --git a/sound/hda/codecs/generic.c b/sound/hda/codecs/generic.c
> >> index 660a9f2c0ded..c536de10d8b8 100644
> >> --- a/sound/hda/codecs/generic.c
> >> +++ b/sound/hda/codecs/generic.c
> >> @@ -27,6 +27,10 @@
> >> #include "hda_beep.h"
> >> #include "generic.h"
> >> +/* Forward declaration */
> >> +static void call_mic_autoswitch(struct hda_codec *codec,
> >> + struct hda_jack_callback *jack);
> >> +
> >> /**
> >> * snd_hda_gen_spec_init - initialize hda_gen_spec struct
> >> @@ -3238,6 +3242,19 @@ static int check_dyn_adc_switch(struct
> >> hda_codec *codec)
> >> if (!spec->dyn_adc_switch && spec->multi_cap_vol)
> >> spec->num_adc_nids = 1;
> >> + /* Enable mic autoswitch for dyn_adc_switch mode when auto_mic is
> >> not available */
> >> + if (!spec->auto_mic && imux->num_items > 1) {
> >> + int i;
> >> + for (i = 0; i < imux->num_items; i++) {
> >> + hda_nid_t pin = spec->imux_pins[i];
> >> + if (!is_jack_detectable(codec, pin))
> >> + continue;
> >> + snd_hda_jack_detect_enable_callback(codec, pin,
> >> + call_mic_autoswitch);
> >> + }
> >> + codec_dbg(codec, "Enable mic autoswitch for input sources\n");
> >> + }
> > IMO, this should be rather put at auto_mic_check_imux() instead,
> > something like:
> > 
> > @@ -4789,13 +4789,15 @@ static bool auto_mic_check_imux(struct
> > hda_codec *codec)
> > const struct hda_input_mux *imux;
> > int i;
> > - imux = &spec->input_mux;
> > - for (i = 0; i < spec->am_num_entries; i++) {
> > - spec->am_entry[i].idx =
> > - find_idx_in_nid_list(spec->am_entry[i].pin,
> > - spec->imux_pins, imux->num_items);
> > - if (spec->am_entry[i].idx < 0)
> > - return false; /* no corresponding imux */
> > + if (!spec->dyn_adc_switch) {
> > + imux = &spec->input_mux;
> > + for (i = 0; i < spec->am_num_entries; i++) {
> > + spec->am_entry[i].idx =
> > + find_idx_in_nid_list(spec->am_entry[i].pin,
> > + spec->imux_pins, imux->num_items);
> > + if (spec->am_entry[i].idx < 0)
> > + return false; /* no corresponding imux */
> > + }
> > }
> > /* we don't need the jack detection for the first pin */
> > 
> In fact, auto_ic_check_imux cannot be executed on desktop computers at
> all. You can take a look at the check_outo_ic_availability section
> for (int i = 0; i < cfg->num_inputs; i++) {
>     hda_nid_t nid = cfg->inputs[i].pin;
>     unsigned int attr;
>     attr = snd_hda_codec_get_pincfg(codec, nid);
>     attr = snd_hda_get_input_pin_attr(attr);
>     if (types & (1 << attr))        For desktop computers, the rear
> mic and line are an attr, which will be directly returned here.

Do you mean that the mic is no built-in mic?  If so, the auto-mic
isn't the way to go.

The driver can't judge which one has a higher priority between an mic
jack and a line jack.  OTOH, in the case of built-in mic vs mic jack,
it's clear who should win, and the driver provides the auto-mic
feature.  So, unless this condition is met, leaving the choice to
user-space is the designed behavior.


thanks,

Takashi

  reply	other threads:[~2026-05-07 15:05 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <5b215802-4c94-4f94-9cee-f8e497b31337@kylinos.cn>
2026-05-06  7:03 ` Fwd: [PATCH] ALSA: hda/generic: Add mic autoswitch support for dyn_adc_switch mode Zhang Heng
2026-05-07 15:05   ` Takashi Iwai [this message]
2026-05-08  2:21     ` Zhang Heng
2026-05-08  2:50       ` Zhang Heng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ecjnp8dx.wl-tiwai@suse.de \
    --to=tiwai@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.com \
    --cc=zhangheng@kylinos.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox