All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hui Wang <hui.wang@canonical.com>
To: alsa-devel@alsa-project.org, tiwai@suse.de, kailang@realtek.com
Subject: [PATCH] ALSA: hda/realtek: add more delay time before determine_headset_type
Date: Tue, 16 Mar 2021 19:55:49 +0800	[thread overview]
Message-ID: <20210316115549.240014-1-hui.wang@canonical.com> (raw)

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.

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;
+		schedule_delayed_work(&spec->headset_set_work, msecs_to_jiffies(2000));
 		break;
 	case ALC_HEADSET_MODE_MIC:
 		alc_headset_mode_mic_in(codec, hp_pin, spec->headphone_mic_pin);
@@ -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:
+		INIT_DELAYED_WORK(&spec->headset_set_work, alc_headset_check_and_set);
 		alc_probe_headset_mode(codec);
 		break;
 	case HDA_FIXUP_ACT_INIT:
@@ -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


             reply	other threads:[~2021-03-16 11:57 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-16 11:55 Hui Wang [this message]
2021-03-16 14:17 ` [PATCH] ALSA: hda/realtek: add more delay time before determine_headset_type Takashi Iwai
2021-03-17  2:15   ` Hui Wang
2021-03-19  7:54     ` Hui Wang

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=20210316115549.240014-1-hui.wang@canonical.com \
    --to=hui.wang@canonical.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=kailang@realtek.com \
    --cc=tiwai@suse.de \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.