From b0720d7ba3d97a51c988526db121278382adec2e Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Mon, 19 Nov 2012 19:48:07 +0100 Subject: [PATCH] --- yaml --- r: 342591 b: refs/heads/master c: 0619ba8c17b121ef0273be181198659b17d84247 h: refs/heads/master i: 342589: 1a37c1c6837b5a8502bc5cea10fd5756b562633e 342587: 3c74561d831b7d89a3bab0f887f50e767021b549 342583: 2206a778461fb6783b04be770e9be5fa80341a79 342575: 5d33b1f39705c183a7b76785c30c54dd8ca898ca 342559: a14ec5f74aa7e1963eb3a69b7a2b970b6c7fae05 342527: 90b738781ef04affef4f62306d8f998d72cd3cca v: v3 --- [refs] | 2 +- trunk/sound/pci/hda/hda_jack.c | 72 +++++++++++++++++++++++++++++----- trunk/sound/pci/hda/hda_jack.h | 4 ++ 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/[refs] b/[refs] index 95a55673b98f..a7962c45fc36 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 379170a42c84cee5f95fac536a4b5b76843baf90 +refs/heads/master: 0619ba8c17b121ef0273be181198659b17d84247 diff --git a/trunk/sound/pci/hda/hda_jack.c b/trunk/sound/pci/hda/hda_jack.c index 5bdbadaa20fe..4e1948001338 100644 --- a/trunk/sound/pci/hda/hda_jack.c +++ b/trunk/sound/pci/hda/hda_jack.c @@ -122,6 +122,8 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec) snd_array_free(&codec->jacktbl); } +#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE) + /* update the cached value and notification flag if needed */ static void jack_detect_update(struct hda_codec *codec, struct hda_jack_tbl *jack) @@ -134,7 +136,21 @@ static void jack_detect_update(struct hda_codec *codec, else jack->pin_sense = read_pin_sense(codec, jack->nid); + /* A gating jack indicates the jack is invalid if gating is unplugged */ + if (jack->gating_jack && !snd_hda_jack_detect(codec, jack->gating_jack)) + jack->pin_sense &= ~AC_PINSENSE_PRESENCE; + jack->jack_dirty = 0; + + /* If a jack is gated by this one update it. */ + if (jack->gated_jack) { + struct hda_jack_tbl *gated = + snd_hda_jack_tbl_get(codec, jack->gated_jack); + if (gated) { + gated->jack_dirty = 1; + jack_detect_update(codec, gated); + } + } } /** @@ -173,8 +189,6 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) } EXPORT_SYMBOL_HDA(snd_hda_pin_sense); -#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE) - /** * snd_hda_jack_detect - query pin Presence Detect status * @codec: the CODEC to sense @@ -221,17 +235,47 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, } EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); +/** + * snd_hda_jack_set_gating_jack - Set gating jack. + * + * Indicates the gated jack is only valid when the gating jack is plugged. + */ +int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, + hda_nid_t gating_nid) +{ + struct hda_jack_tbl *gated = snd_hda_jack_tbl_get(codec, gated_nid); + struct hda_jack_tbl *gating = snd_hda_jack_tbl_get(codec, gating_nid); + + if (!gated || !gating) + return -EINVAL; + + gated->gating_jack = gating_nid; + gating->gated_jack = gated_nid; + + return 0; +} +EXPORT_SYMBOL_HDA(snd_hda_jack_set_gating_jack); + /** * snd_hda_jack_report_sync - sync the states of all jacks and report if changed */ void snd_hda_jack_report_sync(struct hda_codec *codec) { - struct hda_jack_tbl *jack = codec->jacktbl.list; + struct hda_jack_tbl *jack; int i, state; + /* update all jacks at first */ + jack = codec->jacktbl.list; for (i = 0; i < codec->jacktbl.used; i++, jack++) - if (jack->nid) { + if (jack->nid) jack_detect_update(codec, jack); + + /* report the updated jacks; it's done after updating all jacks + * to make sure that all gating jacks properly have been set + */ + jack = codec->jacktbl.list; + for (i = 0; i < codec->jacktbl.used; i++, jack++) + if (jack->nid) { if (!jack->kctl) continue; state = get_jack_plug_state(jack->pin_sense); @@ -424,6 +468,19 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, } EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls); +static void call_jack_callback(struct hda_codec *codec, + struct hda_jack_tbl *jack) +{ + if (jack->callback) + jack->callback(codec, jack); + if (jack->gated_jack) { + struct hda_jack_tbl *gated = + snd_hda_jack_tbl_get(codec, jack->gated_jack); + if (gated && gated->callback) + gated->callback(codec, gated); + } +} + void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res) { struct hda_jack_tbl *event; @@ -434,9 +491,7 @@ void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res) return; event->jack_dirty = 1; - if (event->callback) - event->callback(codec, event); - + call_jack_callback(codec, event); snd_hda_jack_report_sync(codec); } EXPORT_SYMBOL_HDA(snd_hda_jack_unsol_event); @@ -455,8 +510,7 @@ void snd_hda_jack_poll_all(struct hda_codec *codec) if (old_sense == get_jack_plug_state(jack->pin_sense)) continue; changes = 1; - if (jack->callback) - jack->callback(codec, jack); + call_jack_callback(codec, jack); } if (changes) snd_hda_jack_report_sync(codec); diff --git a/trunk/sound/pci/hda/hda_jack.h b/trunk/sound/pci/hda/hda_jack.h index 4487785adf34..ec12abd45263 100644 --- a/trunk/sound/pci/hda/hda_jack.h +++ b/trunk/sound/pci/hda/hda_jack.h @@ -28,6 +28,8 @@ struct hda_jack_tbl { unsigned int jack_detect:1; /* capable of jack-detection? */ unsigned int jack_dirty:1; /* needs to update? */ unsigned int phantom_jack:1; /* a fixed, always present port? */ + hda_nid_t gating_jack; /* valid when gating jack plugged */ + hda_nid_t gated_jack; /* gated is dependent on this jack */ struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ #ifdef CONFIG_SND_HDA_INPUT_JACK int type; @@ -69,6 +71,8 @@ int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, unsigned char action, hda_jack_callback cb); +int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, + hda_nid_t gating_nid); u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);