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); |
