diff options
Diffstat (limited to 'sound/pci/hda/hda_jack.c')
-rw-r--r-- | sound/pci/hda/hda_jack.c | 58 |
1 files changed, 38 insertions, 20 deletions
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index a5fe1b428015..f56765ae73a7 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -111,17 +111,21 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) void snd_hda_jack_tbl_clear(struct hda_codec *codec) { + struct hda_jack_tbl *jack = codec->jacktbl.list; + int i; + + for (i = 0; i < codec->jacktbl.used; i++, jack++) { + struct hda_jack_callback *cb, *next; #ifdef CONFIG_SND_HDA_INPUT_JACK - /* free jack instances manually when clearing/reconfiguring */ - if (!codec->bus->shutdown && codec->jacktbl.list) { - struct hda_jack_tbl *jack = codec->jacktbl.list; - int i; - for (i = 0; i < codec->jacktbl.used; i++, jack++) { - if (jack->jack) - snd_device_free(codec->bus->card, jack->jack); + /* free jack instances manually when clearing/reconfiguring */ + if (!codec->bus->shutdown && jack->jack) + snd_device_free(codec->bus->card, jack->jack); +#endif + for (cb = jack->callback; cb; cb = next) { + next = cb->next; + kfree(cb); } } -#endif snd_array_free(&codec->jacktbl); } @@ -219,28 +223,38 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state); * errno. Check and handle the return value appropriately with standard * macros such as @IS_ERR() and @PTR_ERR(). */ -struct hda_jack_tbl * +struct hda_jack_callback * snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, - hda_jack_callback cb) + hda_jack_callback_fn func) { - struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); + struct hda_jack_tbl *jack; + struct hda_jack_callback *callback = NULL; int err; + jack = snd_hda_jack_tbl_new(codec, nid); if (!jack) return ERR_PTR(-ENOMEM); + if (func) { + callback = kzalloc(sizeof(*callback), GFP_KERNEL); + if (!callback) + return ERR_PTR(-ENOMEM); + callback->func = func; + callback->tbl = jack; + callback->next = jack->callback; + jack->callback = callback; + } + if (jack->jack_detect) - return jack; /* already registered */ + return callback; /* already registered */ jack->jack_detect = 1; - if (cb) - jack->callback = cb; if (codec->jackpoll_interval > 0) - return jack; /* No unsol if we're polling instead */ + return callback; /* No unsol if we're polling instead */ err = snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | jack->tag); if (err < 0) return ERR_PTR(err); - return jack; + return callback; } EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback); @@ -503,13 +517,17 @@ EXPORT_SYMBOL_GPL(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); + struct hda_jack_callback *cb; + + for (cb = jack->callback; cb; cb = cb->next) + cb->func(codec, cb); 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); + if (gated) { + for (cb = gated->callback; cb; cb = cb->next) + cb->func(codec, cb); + } } } |