aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-03-12 07:18:37 -0400
committerTakashi Iwai <tiwai@suse.de>2012-03-12 08:58:54 -0400
commit2ad787e9aae8bfac14fa96748c0f2b034577be6a (patch)
treee11195d3f00e2a84c9bd322b0c5b7b334ea8cb36 /sound/core
parent18478e8b626edc2d181dcb1b93e1f99ad72095e9 (diff)
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: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/vmaster.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index 130cfe677d60..14a286a7bf2b 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -37,6 +37,8 @@ struct link_master {
37 struct link_ctl_info info; 37 struct link_ctl_info info;
38 int val; /* the master value */ 38 int val; /* the master value */
39 unsigned int tlv[4]; 39 unsigned int tlv[4];
40 void (*hook)(void *private_data, int);
41 void *hook_private_data;
40}; 42};
41 43
42/* 44/*
@@ -126,7 +128,9 @@ static int master_init(struct link_master *master)
126 master->info.count = 1; /* always mono */ 128 master->info.count = 1; /* always mono */
127 /* set full volume as default (= no attenuation) */ 129 /* set full volume as default (= no attenuation) */
128 master->val = master->info.max_val; 130 master->val = master->info.max_val;
129 return 0; 131 if (master->hook)
132 master->hook(master->hook_private_data, master->val);
133 return 1;
130 } 134 }
131 return -ENOENT; 135 return -ENOENT;
132} 136}
@@ -329,6 +333,8 @@ static int master_put(struct snd_kcontrol *kcontrol,
329 slave_put_val(slave, uval); 333 slave_put_val(slave, uval);
330 } 334 }
331 kfree(uval); 335 kfree(uval);
336 if (master->hook && !err)
337 master->hook(master->hook_private_data, master->val);
332 return 1; 338 return 1;
333} 339}
334 340
@@ -408,3 +414,41 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
408 return kctl; 414 return kctl;
409} 415}
410EXPORT_SYMBOL(snd_ctl_make_virtual_master); 416EXPORT_SYMBOL(snd_ctl_make_virtual_master);
417
418/**
419 * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control
420 * @kcontrol: vmaster kctl element
421 * @hook: the hook function
422 *
423 * Adds the given hook to the vmaster control element so that it's called
424 * at each time when the value is changed.
425 */
426int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
427 void (*hook)(void *private_data, int),
428 void *private_data)
429{
430 struct link_master *master = snd_kcontrol_chip(kcontrol);
431 master->hook = hook;
432 master->hook_private_data = private_data;
433 return 0;
434}
435EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook);
436
437/**
438 * snd_ctl_sync_vmaster_hook - Sync the vmaster hook
439 * @kcontrol: vmaster kctl element
440 *
441 * Call the hook function to synchronize with the current value of the given
442 * vmaster element. NOP when NULL is passed to @kcontrol or the hook doesn't
443 * exist.
444 */
445void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol)
446{
447 struct link_master *master;
448 if (!kcontrol)
449 return;
450 master = snd_kcontrol_chip(kcontrol);
451 if (master->hook)
452 master->hook(master->hook_private_data, master->val);
453}
454EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook);