Commit 2ad787e9 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: Add a hook capability to vmaster controls

This patch adds a hook to vmaster control to be called at each time
when the master value is changed.  It'd be handy for an additional
mute LED control following the Master switch, for example.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 18478e8b
...@@ -227,6 +227,11 @@ snd_ctl_add_slave_uncached(struct snd_kcontrol *master, ...@@ -227,6 +227,11 @@ snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
return _snd_ctl_add_slave(master, slave, SND_CTL_SLAVE_NEED_UPDATE); return _snd_ctl_add_slave(master, slave, SND_CTL_SLAVE_NEED_UPDATE);
} }
int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl,
void (*hook)(void *private_data, int),
void *private_data);
void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kctl);
/* /*
* Helper functions for jack-detection controls * Helper functions for jack-detection controls
*/ */
......
...@@ -37,6 +37,8 @@ struct link_master { ...@@ -37,6 +37,8 @@ struct link_master {
struct link_ctl_info info; struct link_ctl_info info;
int val; /* the master value */ int val; /* the master value */
unsigned int tlv[4]; unsigned int tlv[4];
void (*hook)(void *private_data, int);
void *hook_private_data;
}; };
/* /*
...@@ -126,7 +128,9 @@ static int master_init(struct link_master *master) ...@@ -126,7 +128,9 @@ static int master_init(struct link_master *master)
master->info.count = 1; /* always mono */ master->info.count = 1; /* always mono */
/* set full volume as default (= no attenuation) */ /* set full volume as default (= no attenuation) */
master->val = master->info.max_val; master->val = master->info.max_val;
return 0; if (master->hook)
master->hook(master->hook_private_data, master->val);
return 1;
} }
return -ENOENT; return -ENOENT;
} }
...@@ -329,6 +333,8 @@ static int master_put(struct snd_kcontrol *kcontrol, ...@@ -329,6 +333,8 @@ static int master_put(struct snd_kcontrol *kcontrol,
slave_put_val(slave, uval); slave_put_val(slave, uval);
} }
kfree(uval); kfree(uval);
if (master->hook && !err)
master->hook(master->hook_private_data, master->val);
return 1; return 1;
} }
...@@ -408,3 +414,41 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, ...@@ -408,3 +414,41 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
return kctl; return kctl;
} }
EXPORT_SYMBOL(snd_ctl_make_virtual_master); EXPORT_SYMBOL(snd_ctl_make_virtual_master);
/**
* snd_ctl_add_vmaster_hook - Add a hook to a vmaster control
* @kcontrol: vmaster kctl element
* @hook: the hook function
*
* Adds the given hook to the vmaster control element so that it's called
* at each time when the value is changed.
*/
int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
void (*hook)(void *private_data, int),
void *private_data)
{
struct link_master *master = snd_kcontrol_chip(kcontrol);
master->hook = hook;
master->hook_private_data = private_data;
return 0;
}
EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook);
/**
* snd_ctl_sync_vmaster_hook - Sync the vmaster hook
* @kcontrol: vmaster kctl element
*
* Call the hook function to synchronize with the current value of the given
* vmaster element. NOP when NULL is passed to @kcontrol or the hook doesn't
* exist.
*/
void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol)
{
struct link_master *master;
if (!kcontrol)
return;
master = snd_kcontrol_chip(kcontrol);
if (master->hook)
master->hook(master->hook_private_data, master->val);
}
EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook);
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