diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-06-24 09:51:54 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-06-24 09:51:54 -0400 |
commit | 1ca2f2ec9e74e9d6e398e09b6468b4462c6d6b6e (patch) | |
tree | 45abf24c4c67b427d1f0d5ed33c0279db29d3ca3 | |
parent | e1a4dca6711c68b6fcc4a236b3475f25dbf227ae (diff) |
ALSA: vmaster: Add snd_ctl_sync_vmaster() helper function
Introduce a new helper function, snd_ctl_sync_vmaster(), which updates
the slave put callbacks forcibly as well as calling the hook. This
will be used in the upcoming patch in HD-audio codec driver for
toggling the mute in vmaster slaves.
Along with the new function, the old snd_ctl_sync_vmaster_hook() is
replaced as a macro calling with the argument hook_only=true.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | include/sound/control.h | 3 | ||||
-rw-r--r-- | sound/core/vmaster.c | 65 |
2 files changed, 47 insertions, 21 deletions
diff --git a/include/sound/control.h b/include/sound/control.h index 34bc93d80d55..5358892b1b39 100644 --- a/include/sound/control.h +++ b/include/sound/control.h | |||
@@ -233,7 +233,8 @@ snd_ctl_add_slave_uncached(struct snd_kcontrol *master, | |||
233 | int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl, | 233 | int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl, |
234 | void (*hook)(void *private_data, int), | 234 | void (*hook)(void *private_data, int), |
235 | void *private_data); | 235 | void *private_data); |
236 | void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kctl); | 236 | void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only); |
237 | #define snd_ctl_sync_vmaster_hook(kctl) snd_ctl_sync_vmaster(kctl, true) | ||
237 | 238 | ||
238 | /* | 239 | /* |
239 | * Helper functions for jack-detection controls | 240 | * Helper functions for jack-detection controls |
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 02f90b4f8b86..5df8dc25ad80 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c | |||
@@ -310,20 +310,10 @@ static int master_get(struct snd_kcontrol *kcontrol, | |||
310 | return 0; | 310 | return 0; |
311 | } | 311 | } |
312 | 312 | ||
313 | static int master_put(struct snd_kcontrol *kcontrol, | 313 | static int sync_slaves(struct link_master *master, int old_val, int new_val) |
314 | struct snd_ctl_elem_value *ucontrol) | ||
315 | { | 314 | { |
316 | struct link_master *master = snd_kcontrol_chip(kcontrol); | ||
317 | struct link_slave *slave; | 315 | struct link_slave *slave; |
318 | struct snd_ctl_elem_value *uval; | 316 | struct snd_ctl_elem_value *uval; |
319 | int err, old_val; | ||
320 | |||
321 | err = master_init(master); | ||
322 | if (err < 0) | ||
323 | return err; | ||
324 | old_val = master->val; | ||
325 | if (ucontrol->value.integer.value[0] == old_val) | ||
326 | return 0; | ||
327 | 317 | ||
328 | uval = kmalloc(sizeof(*uval), GFP_KERNEL); | 318 | uval = kmalloc(sizeof(*uval), GFP_KERNEL); |
329 | if (!uval) | 319 | if (!uval) |
@@ -332,11 +322,33 @@ static int master_put(struct snd_kcontrol *kcontrol, | |||
332 | master->val = old_val; | 322 | master->val = old_val; |
333 | uval->id = slave->slave.id; | 323 | uval->id = slave->slave.id; |
334 | slave_get_val(slave, uval); | 324 | slave_get_val(slave, uval); |
335 | master->val = ucontrol->value.integer.value[0]; | 325 | master->val = new_val; |
336 | slave_put_val(slave, uval); | 326 | slave_put_val(slave, uval); |
337 | } | 327 | } |
338 | kfree(uval); | 328 | kfree(uval); |
339 | if (master->hook && !err) | 329 | return 0; |
330 | } | ||
331 | |||
332 | static int master_put(struct snd_kcontrol *kcontrol, | ||
333 | struct snd_ctl_elem_value *ucontrol) | ||
334 | { | ||
335 | struct link_master *master = snd_kcontrol_chip(kcontrol); | ||
336 | int err, new_val, old_val; | ||
337 | bool first_init; | ||
338 | |||
339 | err = master_init(master); | ||
340 | if (err < 0) | ||
341 | return err; | ||
342 | first_init = err; | ||
343 | old_val = master->val; | ||
344 | new_val = ucontrol->value.integer.value[0]; | ||
345 | if (new_val == old_val) | ||
346 | return 0; | ||
347 | |||
348 | err = sync_slaves(master, old_val, new_val); | ||
349 | if (err < 0) | ||
350 | return err; | ||
351 | if (master->hook && first_init) | ||
340 | master->hook(master->hook_private_data, master->val); | 352 | master->hook(master->hook_private_data, master->val); |
341 | return 1; | 353 | return 1; |
342 | } | 354 | } |
@@ -442,20 +454,33 @@ int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol, | |||
442 | EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook); | 454 | EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook); |
443 | 455 | ||
444 | /** | 456 | /** |
445 | * snd_ctl_sync_vmaster_hook - Sync the vmaster hook | 457 | * snd_ctl_sync_vmaster - Sync the vmaster slaves and hook |
446 | * @kcontrol: vmaster kctl element | 458 | * @kcontrol: vmaster kctl element |
459 | * @hook_only: sync only the hook | ||
447 | * | 460 | * |
448 | * Call the hook function to synchronize with the current value of the given | 461 | * Forcibly call the put callback of each slave and call the hook function |
449 | * vmaster element. NOP when NULL is passed to @kcontrol or the hook doesn't | 462 | * to synchronize with the current value of the given vmaster element. |
450 | * exist. | 463 | * NOP when NULL is passed to @kcontrol. |
451 | */ | 464 | */ |
452 | void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol) | 465 | void snd_ctl_sync_vmaster(struct snd_kcontrol *kcontrol, bool hook_only) |
453 | { | 466 | { |
454 | struct link_master *master; | 467 | struct link_master *master; |
468 | bool first_init = false; | ||
469 | |||
455 | if (!kcontrol) | 470 | if (!kcontrol) |
456 | return; | 471 | return; |
457 | master = snd_kcontrol_chip(kcontrol); | 472 | master = snd_kcontrol_chip(kcontrol); |
458 | if (master->hook) | 473 | if (!hook_only) { |
474 | int err = master_init(master); | ||
475 | if (err < 0) | ||
476 | return; | ||
477 | first_init = err; | ||
478 | err = sync_slaves(master, master->val, master->val); | ||
479 | if (err < 0) | ||
480 | return; | ||
481 | } | ||
482 | |||
483 | if (master->hook && !first_init) | ||
459 | master->hook(master->hook_private_data, master->val); | 484 | master->hook(master->hook_private_data, master->val); |
460 | } | 485 | } |
461 | EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook); | 486 | EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster); |