On Tue, 16 Mar 2021 12:55:49 +0100, Hui Wang wrote:
We found a recording issue on the headset-mic recently, sometimes users plug a headset and select headset-mic from UI, but can't record any sound from headset-mic. The root cause is the determine_headset_type() returns a wrong type, e.g. users plug a ctia type headset, but that function returns omtp type.
In the past, determine_headset_type() worked well because the internal mic is connected to the codec, so the "Input Source" or "Capture Source" is internal mic by default when users plug a headset, the determine_headset_type() will not be called unless users select headset-mic from UI, when users select headset-mic, the plugging action already finished and the headset is completely plugged into the jack, so determine_headset_type() could return a correct type.
But more and more machines connect the internal mic to the PCH now, and the "Input Source" is headset mic by default, when users plug a headset, the determine_headset_type() will be called immediately, if the headset is not completely plugged in, it will return a wrong type.
Here add 2s delay before calling determine_headset_type(), and since there is a pop-up dialogue when users do plugging action, to avoid freezing the UI, use the deleyed_work to call that function.
Hm, two seconds are quite long, IMHO. How is this delay determined?
Takashi
Signed-off-by: Hui Wang hui.wang@canonical.com
sound/pci/hda/patch_realtek.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b47504fa8dfd..1f6fc8addf3e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -127,6 +127,8 @@ struct alc_spec { unsigned int coef0; struct input_dev *kb_dev; u8 alc_mute_keycode_map[1];
- struct hda_codec *codec;
- struct delayed_work headset_set_work;
};
/* @@ -1160,6 +1162,7 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid) kfree(spec); return err; }
- spec->codec = codec; return 0;
}
@@ -5363,6 +5366,21 @@ static void alc_determine_headset_type(struct hda_codec *codec) spec->current_headset_type = is_ctia ? ALC_HEADSET_TYPE_CTIA : ALC_HEADSET_TYPE_OMTP; }
+static void alc_headset_check_and_set(struct work_struct *work) +{
- struct alc_spec *spec = container_of(work, struct alc_spec,
headset_set_work.work);
- struct hda_codec *codec = spec->codec;
- if (spec->current_headset_type == ALC_HEADSET_TYPE_UNKNOWN)
alc_determine_headset_type(codec);
- if (spec->current_headset_type == ALC_HEADSET_TYPE_CTIA)
alc_headset_mode_ctia(codec);
- else if (spec->current_headset_type == ALC_HEADSET_TYPE_OMTP)
alc_headset_mode_omtp(codec);
- spec->gen.hp_jack_present = true;
+}
static void alc_update_headset_mode(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -5386,6 +5404,7 @@ static void alc_update_headset_mode(struct hda_codec *codec) return; }
- cancel_delayed_work_sync(&spec->headset_set_work); switch (new_headset_mode) { case ALC_HEADSET_MODE_UNPLUGGED: alc_headset_mode_unplugged(codec);
@@ -5394,13 +5413,7 @@ static void alc_update_headset_mode(struct hda_codec *codec) spec->gen.hp_jack_present = false; break; case ALC_HEADSET_MODE_HEADSET:
if (spec->current_headset_type == ALC_HEADSET_TYPE_UNKNOWN)
alc_determine_headset_type(codec);
if (spec->current_headset_type == ALC_HEADSET_TYPE_CTIA)
alc_headset_mode_ctia(codec);
else if (spec->current_headset_type == ALC_HEADSET_TYPE_OMTP)
alc_headset_mode_omtp(codec);
spec->gen.hp_jack_present = true;
break; case ALC_HEADSET_MODE_MIC: alc_headset_mode_mic_in(codec, hp_pin, spec->headphone_mic_pin);schedule_delayed_work(&spec->headset_set_work, msecs_to_jiffies(2000));
@@ -5466,6 +5479,7 @@ static void alc_fixup_headset_mode(struct hda_codec *codec, spec->parse_flags |= HDA_PINCFG_HEADSET_MIC | HDA_PINCFG_HEADPHONE_MIC; break; case HDA_FIXUP_ACT_PROBE:
alc_probe_headset_mode(codec); break; case HDA_FIXUP_ACT_INIT:INIT_DELAYED_WORK(&spec->headset_set_work, alc_headset_check_and_set);
@@ -5475,6 +5489,9 @@ static void alc_fixup_headset_mode(struct hda_codec *codec, } alc_update_headset_mode(codec); break;
- case HDA_FIXUP_ACT_FREE:
cancel_delayed_work_sync(&spec->headset_set_work);
}break;
}
-- 2.25.1