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@xxxxxxxxxxxxx> > --- > 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