summaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_jack.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/hda_jack.c')
-rw-r--r--sound/pci/hda/hda_jack.c83
1 files changed, 53 insertions, 30 deletions
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 9746d73cec52..f56765ae73a7 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -94,7 +94,7 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_from_tag);
/**
* snd_hda_jack_tbl_new - create a jack-table entry for the given NID
*/
-struct hda_jack_tbl *
+static struct hda_jack_tbl *
snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
{
struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
@@ -108,21 +108,24 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
jack->tag = codec->jacktbl.used;
return jack;
}
-EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_new);
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);
}
@@ -215,33 +218,49 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state);
/**
* snd_hda_jack_detect_enable - enable the jack-detection
+ *
+ * In the case of error, the return value will be a pointer embedded with
+ * errno. Check and handle the return value appropriately with standard
+ * macros such as @IS_ERR() and @PTR_ERR().
*/
-int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
- unsigned char action,
- hda_jack_callback cb)
+struct hda_jack_callback *
+snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
+ 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 -ENOMEM;
+ 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 0; /* already registered */
+ return callback; /* already registered */
jack->jack_detect = 1;
- if (action)
- jack->action = action;
- if (cb)
- jack->callback = cb;
if (codec->jackpoll_interval > 0)
- return 0; /* No unsol if we're polling instead */
- return snd_hda_codec_write_cache(codec, nid, 0,
+ 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 callback;
}
EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback);
-int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
- unsigned char action)
+int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid)
{
- return snd_hda_jack_detect_enable_callback(codec, nid, action, NULL);
+ return PTR_ERR_OR_ZERO(snd_hda_jack_detect_enable_callback(codec, nid, NULL));
}
EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable);
@@ -431,7 +450,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
return err;
if (!phantom_jack)
- return snd_hda_jack_detect_enable(codec, nid, 0);
+ return snd_hda_jack_detect_enable(codec, nid);
return 0;
}
@@ -498,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);
+ }
}
}