mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									e1a4dca671
								
							
						
					
					
						commit
						1ca2f2ec9e
					
				
					 2 changed files with 47 additions and 21 deletions
				
			
		| 
						 | 
					@ -233,7 +233,8 @@ snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
 | 
				
			||||||
int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl,
 | 
					int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl,
 | 
				
			||||||
			     void (*hook)(void *private_data, int),
 | 
								     void (*hook)(void *private_data, int),
 | 
				
			||||||
			     void *private_data);
 | 
								     void *private_data);
 | 
				
			||||||
void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kctl);
 | 
					void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only);
 | 
				
			||||||
 | 
					#define snd_ctl_sync_vmaster_hook(kctl)	snd_ctl_sync_vmaster(kctl, true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Helper functions for jack-detection controls
 | 
					 * Helper functions for jack-detection controls
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -310,20 +310,10 @@ static int master_get(struct snd_kcontrol *kcontrol,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int master_put(struct snd_kcontrol *kcontrol,
 | 
					static int sync_slaves(struct link_master *master, int old_val, int new_val)
 | 
				
			||||||
		      struct snd_ctl_elem_value *ucontrol)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct link_master *master = snd_kcontrol_chip(kcontrol);
 | 
					 | 
				
			||||||
	struct link_slave *slave;
 | 
						struct link_slave *slave;
 | 
				
			||||||
	struct snd_ctl_elem_value *uval;
 | 
						struct snd_ctl_elem_value *uval;
 | 
				
			||||||
	int err, old_val;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = master_init(master);
 | 
					 | 
				
			||||||
	if (err < 0)
 | 
					 | 
				
			||||||
		return err;
 | 
					 | 
				
			||||||
	old_val = master->val;
 | 
					 | 
				
			||||||
	if (ucontrol->value.integer.value[0] == old_val)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uval = kmalloc(sizeof(*uval), GFP_KERNEL);
 | 
						uval = kmalloc(sizeof(*uval), GFP_KERNEL);
 | 
				
			||||||
	if (!uval)
 | 
						if (!uval)
 | 
				
			||||||
| 
						 | 
					@ -332,11 +322,33 @@ static int master_put(struct snd_kcontrol *kcontrol,
 | 
				
			||||||
		master->val = old_val;
 | 
							master->val = old_val;
 | 
				
			||||||
		uval->id = slave->slave.id;
 | 
							uval->id = slave->slave.id;
 | 
				
			||||||
		slave_get_val(slave, uval);
 | 
							slave_get_val(slave, uval);
 | 
				
			||||||
		master->val = ucontrol->value.integer.value[0];
 | 
							master->val = new_val;
 | 
				
			||||||
		slave_put_val(slave, uval);
 | 
							slave_put_val(slave, uval);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	kfree(uval);
 | 
						kfree(uval);
 | 
				
			||||||
	if (master->hook && !err)
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int master_put(struct snd_kcontrol *kcontrol,
 | 
				
			||||||
 | 
							      struct snd_ctl_elem_value *ucontrol)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct link_master *master = snd_kcontrol_chip(kcontrol);
 | 
				
			||||||
 | 
						int err, new_val, old_val;
 | 
				
			||||||
 | 
						bool first_init;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = master_init(master);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
						first_init = err;
 | 
				
			||||||
 | 
						old_val = master->val;
 | 
				
			||||||
 | 
						new_val = ucontrol->value.integer.value[0];
 | 
				
			||||||
 | 
						if (new_val == old_val)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = sync_slaves(master, old_val, new_val);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
						if (master->hook && first_init)
 | 
				
			||||||
		master->hook(master->hook_private_data, master->val);
 | 
							master->hook(master->hook_private_data, master->val);
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -442,20 +454,33 @@ int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
 | 
				
			||||||
EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook);
 | 
					EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * snd_ctl_sync_vmaster_hook - Sync the vmaster hook
 | 
					 * snd_ctl_sync_vmaster - Sync the vmaster slaves and hook
 | 
				
			||||||
 * @kcontrol: vmaster kctl element
 | 
					 * @kcontrol: vmaster kctl element
 | 
				
			||||||
 | 
					 * @hook_only: sync only the hook
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Call the hook function to synchronize with the current value of the given
 | 
					 * Forcibly call the put callback of each slave and call the hook function
 | 
				
			||||||
 * vmaster element.  NOP when NULL is passed to @kcontrol or the hook doesn't
 | 
					 * to synchronize with the current value of the given vmaster element.
 | 
				
			||||||
 * exist.
 | 
					 * NOP when NULL is passed to @kcontrol.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol)
 | 
					void snd_ctl_sync_vmaster(struct snd_kcontrol *kcontrol, bool hook_only)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct link_master *master;
 | 
						struct link_master *master;
 | 
				
			||||||
 | 
						bool first_init = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!kcontrol)
 | 
						if (!kcontrol)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	master = snd_kcontrol_chip(kcontrol);
 | 
						master = snd_kcontrol_chip(kcontrol);
 | 
				
			||||||
	if (master->hook)
 | 
						if (!hook_only) {
 | 
				
			||||||
 | 
							int err = master_init(master);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							first_init = err;
 | 
				
			||||||
 | 
							err = sync_slaves(master, master->val, master->val);
 | 
				
			||||||
 | 
							if (err < 0)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (master->hook && !first_init)
 | 
				
			||||||
		master->hook(master->hook_private_data, master->val);
 | 
							master->hook(master->hook_private_data, master->val);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook);
 | 
					EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue