Skip to content

Commit

Permalink
ALSA: Add a hook capability to vmaster controls
Browse files Browse the repository at this point in the history
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: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Takashi Iwai committed Mar 12, 2012
1 parent 18478e8 commit 2ad787e
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
5 changes: 5 additions & 0 deletions include/sound/control.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

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
*/
Expand Down
46 changes: 45 additions & 1 deletion sound/core/vmaster.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ struct link_master {
struct link_ctl_info info;
int val; /* the master value */
unsigned int tlv[4];
void (*hook)(void *private_data, int);
void *hook_private_data;
};

/*
Expand Down Expand Up @@ -126,7 +128,9 @@ static int master_init(struct link_master *master)
master->info.count = 1; /* always mono */
/* set full volume as default (= no attenuation) */
master->val = master->info.max_val;
return 0;
if (master->hook)
master->hook(master->hook_private_data, master->val);
return 1;
}
return -ENOENT;
}
Expand Down Expand Up @@ -329,6 +333,8 @@ static int master_put(struct snd_kcontrol *kcontrol,
slave_put_val(slave, uval);
}
kfree(uval);
if (master->hook && !err)
master->hook(master->hook_private_data, master->val);
return 1;
}

Expand Down Expand Up @@ -408,3 +414,41 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
return kctl;
}
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);

0 comments on commit 2ad787e

Please sign in to comment.