aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-06-24 09:51:54 -0400
committerTakashi Iwai <tiwai@suse.de>2013-06-24 09:51:54 -0400
commit1ca2f2ec9e74e9d6e398e09b6468b4462c6d6b6e (patch)
tree45abf24c4c67b427d1f0d5ed33c0279db29d3ca3
parente1a4dca6711c68b6fcc4a236b3475f25dbf227ae (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.h3
-rw-r--r--sound/core/vmaster.c65
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,
233int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl, 233int 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);
236void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kctl); 236void 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
313static int master_put(struct snd_kcontrol *kcontrol, 313static 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
332static 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,
442EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook); 454EXPORT_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 */
452void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol) 465void 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}
461EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook); 486EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster);