summaryrefslogtreecommitdiff
path: root/sound/pci/hda/hda_jack.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2018-11-28 14:25:37 +0100
committerTakashi Iwai <tiwai@suse.de>2018-12-07 11:42:36 +0100
commit911761c2304327a39ec9372be812a9648bd35c09 (patch)
tree5d34e83238f7a829c787ce84921c5739cb69f04e /sound/pci/hda/hda_jack.c
parente6ce180fa6df519b1e24dab9d1fcbe32ce618a5e (diff)
ALSA: hda - Add jack button support
Extend some structs to add the support for jack button changes. Now snd_hda_jack_add_kctl() receives two more arguments: the jack type and the jack keymaps. Both are optional, and when zero are passed, the function behaves just like before. For reporting button state changes, you'd need to update jack->button_state bits accordingly, typically in the jack callback. Then the value OR'ed with button_state and the jack plug state is passed to snd_jack_report(). Note that currently the code assumes only the one-shot button events, i.e. it tries to send the button release soon after sending the button event. If a driver really supports the button release handling by itself, we may need to introduce some flag to control this behavior in future. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_jack.c')
-rw-r--r--sound/pci/hda/hda_jack.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 87498235787a..74b46952fc98 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -339,9 +339,15 @@ void snd_hda_jack_report_sync(struct hda_codec *codec)
if (jack->nid) {
if (!jack->jack || jack->block_report)
continue;
- state = get_jack_plug_state(jack->pin_sense);
- snd_jack_report(jack->jack,
- state ? jack->type : 0);
+ state = jack->button_state;
+ if (get_jack_plug_state(jack->pin_sense))
+ state |= jack->type;
+ snd_jack_report(jack->jack, state);
+ if (jack->button_state) {
+ snd_jack_report(jack->jack,
+ state & ~jack->button_state);
+ jack->button_state = 0; /* button released */
+ }
}
}
EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync);
@@ -379,15 +385,19 @@ static void hda_free_jack_priv(struct snd_jack *jack)
* @nid: pin NID to assign
* @name: string name for the jack
* @phantom_jack: flag to deal as a phantom jack
+ * @type: jack type bits to be reported, 0 for guessing from pincfg
+ * @keymap: optional jack / key mapping
*
* This assigns a jack-detection kctl to the given pin. The kcontrol
* will have the given name and index.
*/
int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
- const char *name, bool phantom_jack)
+ const char *name, bool phantom_jack,
+ int type, const struct hda_jack_keymap *keymap)
{
struct hda_jack_tbl *jack;
- int err, state, type;
+ const struct hda_jack_keymap *map;
+ int err, state, buttons;
jack = snd_hda_jack_tbl_new(codec, nid);
if (!jack)
@@ -395,16 +405,30 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
if (jack->jack)
return 0; /* already created */
- type = get_input_jack_type(codec, nid);
- err = snd_jack_new(codec->card, name, type,
+ if (!type)
+ type = get_input_jack_type(codec, nid);
+
+ buttons = 0;
+ if (keymap) {
+ for (map = keymap; map->type; map++)
+ buttons |= map->type;
+ }
+
+ err = snd_jack_new(codec->card, name, type | buttons,
&jack->jack, true, phantom_jack);
if (err < 0)
return err;
jack->phantom_jack = !!phantom_jack;
jack->type = type;
+ jack->button_state = 0;
jack->jack->private_data = jack;
jack->jack->private_free = hda_free_jack_priv;
+ if (keymap) {
+ for (map = keymap; map->type; map++)
+ snd_jack_set_key(jack->jack, map->type, map->key);
+ }
+
state = snd_hda_jack_detect(codec, nid);
snd_jack_report(jack->jack, state ? jack->type : 0);
@@ -437,7 +461,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
if (phantom_jack)
/* Example final name: "Internal Mic Phantom Jack" */
strncat(name, " Phantom", sizeof(name) - strlen(name) - 1);
- err = snd_hda_jack_add_kctl(codec, nid, name, phantom_jack);
+ err = snd_hda_jack_add_kctl(codec, nid, name, phantom_jack, 0, NULL);
if (err < 0)
return err;