[PATCH] ALSA: hda - bind headset buttons to the headphone jack
Takashi Iwai
tiwai at suse.de
Wed Mar 3 09:46:35 CET 2021
On Wed, 03 Mar 2021 02:23:46 +0100,
Hui Wang wrote:
>
> With the HDA driver, if the headset buttons are supported, an audio
> Jack will be created for them. This audio Jack is a bit confusing to
> users since it can't report headphone/mic insertion events but it
> claims to support these events.
>
> And in addition, the driver already builds a headphone Jack and a mic
> Jack, and most of those buttons are used for headphone playback, so
> do some change to bind those buttons to the headphone Jack. After this
> change, the key events are generated from NID 0x55, and are reported
> to the input layer via headphone jack (NID 0x21).
>
> If there is no headphone Jack, then build an audio jack to support
> those buttons same as previously.
>
> Signed-off-by: Hui Wang <hui.wang at canonical.com>
> ---
> sound/pci/hda/hda_jack.c | 43 ++++++++++++++++++++++++++++++++++-
> sound/pci/hda/hda_jack.h | 5 ++++
> sound/pci/hda/patch_realtek.c | 23 ++++++++++++++++---
> 3 files changed, 67 insertions(+), 4 deletions(-)
>
> diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
> index b8b568046592..640b72b598e8 100644
> --- a/sound/pci/hda/hda_jack.c
> +++ b/sound/pci/hda/hda_jack.c
> @@ -388,6 +388,39 @@ int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
> }
> EXPORT_SYMBOL_GPL(snd_hda_jack_set_gating_jack);
>
> +/**
> + * snd_hda_jack_bind_keymap - bind keys generated from one NID to another jack.
> + * @codec: the HDA codec
> + * @key_nid: key event is generated by this pin NID
> + * @keymap: map of key type and key code
> + * @jack_nid: key reports to the jack of this pin NID
> + *
> + * This function is used in the case of key is generated from one NID while is
> + * reported to the jack of another NID.
> + */
> +int snd_hda_jack_bind_keymap(struct hda_codec *codec, hda_nid_t key_nid,
> + const struct hda_jack_keymap *keymap,
> + hda_nid_t jack_nid)
> +{
> + const struct hda_jack_keymap *map;
> + struct hda_jack_tbl *key_gen = snd_hda_jack_tbl_get(codec, key_nid);
> + struct hda_jack_tbl *report_to = snd_hda_jack_tbl_get(codec, jack_nid);
> +
> + WARN_ON(codec->dp_mst);
> +
> + if (!key_gen || !report_to || !report_to->jack)
> + return -EINVAL;
> +
> + key_gen->key_report_jack = jack_nid;
> +
> + if (keymap)
> + for (map = keymap; map->type; map++)
> + snd_jack_set_key(report_to->jack, map->type, map->key);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(snd_hda_jack_bind_keymap);
> +
> /**
> * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
> * @codec: the HDA codec
> @@ -651,7 +684,15 @@ void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
> }
> if (!event)
> return;
> - event->jack_dirty = 1;
> +
> + if (event->key_report_jack) {
> + struct hda_jack_tbl *report_to =
> + snd_hda_jack_tbl_get_mst(codec, event->key_report_jack,
> + event->dev_id);
> + if (report_to)
> + report_to->jack_dirty = 1;
> + } else
> + event->jack_dirty = 1;
>
> call_jack_callback(codec, res, event);
> snd_hda_jack_report_sync(codec);
> diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
> index 8ceaf0ef5df1..339746dd9578 100644
> --- a/sound/pci/hda/hda_jack.h
> +++ b/sound/pci/hda/hda_jack.h
> @@ -40,6 +40,7 @@ struct hda_jack_tbl {
> unsigned int block_report:1; /* in a transitional state - do not report to userspace */
> hda_nid_t gating_jack; /* valid when gating jack plugged */
> hda_nid_t gated_jack; /* gated is dependent on this jack */
> + hda_nid_t key_report_jack; /* key reports to this jack */
> int type;
> int button_state;
> struct snd_jack *jack;
> @@ -99,6 +100,10 @@ snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
> int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
> hda_nid_t gating_nid);
>
> +int snd_hda_jack_bind_keymap(struct hda_codec *codec, hda_nid_t key_nid,
> + const struct hda_jack_keymap *keymap,
> + hda_nid_t jack_nid);
> +
> u32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id);
>
> /* the jack state returned from snd_hda_jack_detect_state() */
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index 52907506e16e..f381474f9403 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -3102,6 +3102,16 @@ static void alc_headset_btn_callback(struct hda_codec *codec,
> if (jack->unsol_res & (7 << 10))
> report |= SND_JACK_BTN_3;
>
> + if (jack->jack->key_report_jack) {
> + struct hda_jack_tbl *report_to =
> + snd_hda_jack_tbl_get(codec, jack->jack->key_report_jack);
> +
> + if (report_to) {
> + report_to->button_state = report;
> + return;
> + }
> + }
> +
> jack->jack->button_state = report;
> }
I think this part should be rather in hda_jack.c, e.g. create a function
snd_hda_jack_set_button_state() and handle the redirection there.
It's not good to change the content in jack->jack externally.
thanks,
Takashi
More information about the Alsa-devel
mailing list