[PATCH] ALSA: hda/realtek - a fake key event is triggered by running shutup
Hui Wang
hui.wang at canonical.com
Sun Mar 29 10:17:01 CEST 2020
Please ignore this patch, I put a wrong Fixes: ...
On 2020/3/29 下午4:06, Hui Wang wrote:
> On the Lenovo X1C7 machines, after we plug the headset, the rt_resume()
> and rt_suspend() of the codec driver will be called periodically, the
> driver can't stay in the rt_suspend state even users doen't use the
> sound card.
>
> Through debugging, I found when running rt_suspend(), it will call
> alc225_shutup(), in this function, it will change 3k pull down control
> by alc_update_coef_idx(codec, 0x4a, 0, 3 << 10), this will trigger a
> fake key event and that event will resume the codec, when codec
> suspend agin, it will trigger the fake key event one more time, this
> process will repeat.
>
> If disable the key event before changing the pull down control, it
> will not trigger fake key event. It also needs to restore the pull
> down control and re-enable the key event, otherwise the system can't
> get key event when codec is in rt_suspend state.
>
> Also move some functions ahead of alc225_shutup(), this can save the
> function declaration.
>
> Fixes: 78def224f59c (ALSA: hda/realtek - Add Headset Mic supported)
> Cc: Kailang Yang <kailang at realtek.com>
> Cc: <stable at vger.kernel.org>
> Signed-off-by: Hui Wang <hui.wang at canonical.com>
> ---
> sound/pci/hda/patch_realtek.c | 170 +++++++++++++++++++++-------------
> 1 file changed, 107 insertions(+), 63 deletions(-)
>
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index 1ad8c2e2d1af..0af33f00617a 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -107,6 +107,7 @@ struct alc_spec {
> unsigned int done_hp_init:1;
> unsigned int no_shutup_pins:1;
> unsigned int ultra_low_power:1;
> + unsigned int has_hs_key:1;
>
> /* for PLL fix */
> hda_nid_t pll_nid;
> @@ -2982,6 +2983,107 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
> return alc_parse_auto_config(codec, alc269_ignore, ssids);
> }
>
> +static const struct hda_jack_keymap alc_headset_btn_keymap[] = {
> + { SND_JACK_BTN_0, KEY_PLAYPAUSE },
> + { SND_JACK_BTN_1, KEY_VOICECOMMAND },
> + { SND_JACK_BTN_2, KEY_VOLUMEUP },
> + { SND_JACK_BTN_3, KEY_VOLUMEDOWN },
> + {}
> +};
> +
> +static void alc_headset_btn_callback(struct hda_codec *codec,
> + struct hda_jack_callback *jack)
> +{
> + int report = 0;
> +
> + if (jack->unsol_res & (7 << 13))
> + report |= SND_JACK_BTN_0;
> +
> + if (jack->unsol_res & (1 << 16 | 3 << 8))
> + report |= SND_JACK_BTN_1;
> +
> + /* Volume up key */
> + if (jack->unsol_res & (7 << 23))
> + report |= SND_JACK_BTN_2;
> +
> + /* Volume down key */
> + if (jack->unsol_res & (7 << 10))
> + report |= SND_JACK_BTN_3;
> +
> + jack->jack->button_state = report;
> +}
> +
> +static void alc_disable_headset_jack_key(struct hda_codec *codec)
> +{
> + struct alc_spec *spec = codec->spec;
> +
> + if (!spec->has_hs_key)
> + return;
> +
> + switch (codec->core.vendor_id) {
> + case 0x10ec0215:
> + case 0x10ec0225:
> + case 0x10ec0285:
> + case 0x10ec0295:
> + case 0x10ec0289:
> + case 0x10ec0299:
> + alc_write_coef_idx(codec, 0x48, 0x0);
> + alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
> + alc_update_coef_idx(codec, 0x44, 0x0045 << 8, 0x0);
> + break;
> + case 0x10ec0236:
> + case 0x10ec0256:
> + alc_write_coef_idx(codec, 0x48, 0x0);
> + alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
> + break;
> + }
> +}
> +
> +static void alc_enable_headset_jack_key(struct hda_codec *codec)
> +{
> + struct alc_spec *spec = codec->spec;
> +
> + if (!spec->has_hs_key)
> + return;
> +
> + switch (codec->core.vendor_id) {
> + case 0x10ec0215:
> + case 0x10ec0225:
> + case 0x10ec0285:
> + case 0x10ec0295:
> + case 0x10ec0289:
> + case 0x10ec0299:
> + alc_write_coef_idx(codec, 0x48, 0xd011);
> + alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
> + alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8);
> + break;
> + case 0x10ec0236:
> + case 0x10ec0256:
> + alc_write_coef_idx(codec, 0x48, 0xd011);
> + alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
> + break;
> + }
> +}
> +
> +static void alc_fixup_headset_jack(struct hda_codec *codec,
> + const struct hda_fixup *fix, int action)
> +{
> + struct alc_spec *spec = codec->spec;
> +
> + switch (action) {
> + case HDA_FIXUP_ACT_PRE_PROBE:
> + spec->has_hs_key = 1;
> + snd_hda_jack_detect_enable_callback(codec, 0x55,
> + alc_headset_btn_callback);
> + snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false,
> + SND_JACK_HEADSET, alc_headset_btn_keymap);
> + break;
> + case HDA_FIXUP_ACT_INIT:
> + alc_enable_headset_jack_key(codec);
> + break;
> + }
> +}
> +
> static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)
> {
> alc_update_coef_idx(codec, 0x04, 1 << 11, power_up ? (1 << 11) : 0);
> @@ -3372,6 +3474,8 @@ static void alc225_shutup(struct hda_codec *codec)
>
> if (!hp_pin)
> hp_pin = 0x21;
> +
> + alc_disable_headset_jack_key(codec);
> /* 3k pull low control for Headset jack. */
> alc_update_coef_idx(codec, 0x4a, 0, 3 << 10);
>
> @@ -3411,6 +3515,9 @@ static void alc225_shutup(struct hda_codec *codec)
> alc_update_coef_idx(codec, 0x4a, 3<<4, 2<<4);
> msleep(30);
> }
> +
> + alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
> + alc_enable_headset_jack_key(codec);
> }
>
> static void alc_default_init(struct hda_codec *codec)
> @@ -5668,69 +5775,6 @@ static void alc285_fixup_invalidate_dacs(struct hda_codec *codec,
> snd_hda_override_wcaps(codec, 0x03, 0);
> }
>
> -static const struct hda_jack_keymap alc_headset_btn_keymap[] = {
> - { SND_JACK_BTN_0, KEY_PLAYPAUSE },
> - { SND_JACK_BTN_1, KEY_VOICECOMMAND },
> - { SND_JACK_BTN_2, KEY_VOLUMEUP },
> - { SND_JACK_BTN_3, KEY_VOLUMEDOWN },
> - {}
> -};
> -
> -static void alc_headset_btn_callback(struct hda_codec *codec,
> - struct hda_jack_callback *jack)
> -{
> - int report = 0;
> -
> - if (jack->unsol_res & (7 << 13))
> - report |= SND_JACK_BTN_0;
> -
> - if (jack->unsol_res & (1 << 16 | 3 << 8))
> - report |= SND_JACK_BTN_1;
> -
> - /* Volume up key */
> - if (jack->unsol_res & (7 << 23))
> - report |= SND_JACK_BTN_2;
> -
> - /* Volume down key */
> - if (jack->unsol_res & (7 << 10))
> - report |= SND_JACK_BTN_3;
> -
> - jack->jack->button_state = report;
> -}
> -
> -static void alc_fixup_headset_jack(struct hda_codec *codec,
> - const struct hda_fixup *fix, int action)
> -{
> -
> - switch (action) {
> - case HDA_FIXUP_ACT_PRE_PROBE:
> - snd_hda_jack_detect_enable_callback(codec, 0x55,
> - alc_headset_btn_callback);
> - snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false,
> - SND_JACK_HEADSET, alc_headset_btn_keymap);
> - break;
> - case HDA_FIXUP_ACT_INIT:
> - switch (codec->core.vendor_id) {
> - case 0x10ec0215:
> - case 0x10ec0225:
> - case 0x10ec0285:
> - case 0x10ec0295:
> - case 0x10ec0289:
> - case 0x10ec0299:
> - alc_write_coef_idx(codec, 0x48, 0xd011);
> - alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
> - alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8);
> - break;
> - case 0x10ec0236:
> - case 0x10ec0256:
> - alc_write_coef_idx(codec, 0x48, 0xd011);
> - alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
> - break;
> - }
> - break;
> - }
> -}
> -
> static void alc295_fixup_chromebook(struct hda_codec *codec,
> const struct hda_fixup *fix, int action)
> {
More information about the Alsa-devel
mailing list