Commit 911761c2 authored by Takashi Iwai's avatar Takashi Iwai

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: default avatarTakashi Iwai <tiwai@suse.de>
parent e6ce180f
...@@ -339,9 +339,15 @@ void snd_hda_jack_report_sync(struct hda_codec *codec) ...@@ -339,9 +339,15 @@ void snd_hda_jack_report_sync(struct hda_codec *codec)
if (jack->nid) { if (jack->nid) {
if (!jack->jack || jack->block_report) if (!jack->jack || jack->block_report)
continue; continue;
state = get_jack_plug_state(jack->pin_sense); state = jack->button_state;
snd_jack_report(jack->jack, if (get_jack_plug_state(jack->pin_sense))
state ? jack->type : 0); 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); EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync);
...@@ -379,15 +385,19 @@ static void hda_free_jack_priv(struct snd_jack *jack) ...@@ -379,15 +385,19 @@ static void hda_free_jack_priv(struct snd_jack *jack)
* @nid: pin NID to assign * @nid: pin NID to assign
* @name: string name for the jack * @name: string name for the jack
* @phantom_jack: flag to deal as a phantom 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 * This assigns a jack-detection kctl to the given pin. The kcontrol
* will have the given name and index. * will have the given name and index.
*/ */
int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, 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; 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); jack = snd_hda_jack_tbl_new(codec, nid);
if (!jack) if (!jack)
...@@ -395,16 +405,30 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, ...@@ -395,16 +405,30 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
if (jack->jack) if (jack->jack)
return 0; /* already created */ return 0; /* already created */
type = get_input_jack_type(codec, nid); if (!type)
err = snd_jack_new(codec->card, name, 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); &jack->jack, true, phantom_jack);
if (err < 0) if (err < 0)
return err; return err;
jack->phantom_jack = !!phantom_jack; jack->phantom_jack = !!phantom_jack;
jack->type = type; jack->type = type;
jack->button_state = 0;
jack->jack->private_data = jack; jack->jack->private_data = jack;
jack->jack->private_free = hda_free_jack_priv; 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); state = snd_hda_jack_detect(codec, nid);
snd_jack_report(jack->jack, state ? jack->type : 0); 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, ...@@ -437,7 +461,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
if (phantom_jack) if (phantom_jack)
/* Example final name: "Internal Mic Phantom Jack" */ /* Example final name: "Internal Mic Phantom Jack" */
strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); 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) if (err < 0)
return err; return err;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#define __SOUND_HDA_JACK_H #define __SOUND_HDA_JACK_H
#include <linux/err.h> #include <linux/err.h>
#include <sound/jack.h>
struct auto_pin_cfg; struct auto_pin_cfg;
struct hda_jack_tbl; struct hda_jack_tbl;
...@@ -42,9 +43,15 @@ struct hda_jack_tbl { ...@@ -42,9 +43,15 @@ struct hda_jack_tbl {
hda_nid_t gating_jack; /* valid when gating jack plugged */ hda_nid_t gating_jack; /* valid when gating jack plugged */
hda_nid_t gated_jack; /* gated is dependent on this jack */ hda_nid_t gated_jack; /* gated is dependent on this jack */
int type; int type;
int button_state;
struct snd_jack *jack; struct snd_jack *jack;
}; };
struct hda_jack_keymap {
enum snd_jack_types type;
int key;
};
struct hda_jack_tbl * struct hda_jack_tbl *
snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid); snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid);
struct hda_jack_tbl * struct hda_jack_tbl *
...@@ -84,7 +91,8 @@ static inline bool snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) ...@@ -84,7 +91,8 @@ static inline bool snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid); bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, 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);
int snd_hda_jack_add_kctls(struct hda_codec *codec, int snd_hda_jack_add_kctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg); const struct auto_pin_cfg *cfg);
......
...@@ -2142,7 +2142,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx) ...@@ -2142,7 +2142,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx)
strncat(hdmi_str, " Phantom", strncat(hdmi_str, " Phantom",
sizeof(hdmi_str) - strlen(hdmi_str) - 1); sizeof(hdmi_str) - strlen(hdmi_str) - 1);
ret = snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, ret = snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str,
phantom_jack); phantom_jack, 0, NULL);
if (ret < 0) if (ret < 0)
return ret; return ret;
jack = snd_hda_jack_tbl_get(codec, per_pin->pin_nid); jack = snd_hda_jack_tbl_get(codec, per_pin->pin_nid);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment