ALSA: hda - Allow multiple callbacks for jack
So far, hda_jack infrastructure allows only one callback per jack, and this makes things slightly complicated when a driver wants to assign multiple tasks to a jack, e.g. the standard auto-mute with a power up/down sequence. This can be simplified if the hda_jack accepts multiple callbacks. This patch is such an extension: the callback-specific part (the function and private_data) is split to another struct from hda_jack_tbl, and multiple such objects can be assigned to a single hda_jack_tbl entry. The new struct hda_jack_callback is passed to each callback function now, thus the patch became bigger than expected. But these changes are mostly trivial. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user