Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ca2f2ec authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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: default avatarTakashi Iwai <tiwai@suse.de>
parent e1a4dca6
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -233,7 +233,8 @@ snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl,
			     void (*hook)(void *private_data, int),
			     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
+45 −20
Original line number Diff line number Diff line
@@ -310,20 +310,10 @@ static int master_get(struct snd_kcontrol *kcontrol,
	return 0;
}

static int master_put(struct snd_kcontrol *kcontrol,
		      struct snd_ctl_elem_value *ucontrol)
static int sync_slaves(struct link_master *master, int old_val, int new_val)
{
	struct link_master *master = snd_kcontrol_chip(kcontrol);
	struct link_slave *slave;
	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);
	if (!uval)
@@ -332,11 +322,33 @@ static int master_put(struct snd_kcontrol *kcontrol,
		master->val = old_val;
		uval->id = slave->slave.id;
		slave_get_val(slave, uval);
		master->val = ucontrol->value.integer.value[0];
		master->val = new_val;
		slave_put_val(slave, 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);
	return 1;
}
@@ -442,20 +454,33 @@ int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
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
 * @hook_only: sync only the hook
 *
 * Call the hook function to synchronize with the current value of the given
 * vmaster element.  NOP when NULL is passed to @kcontrol or the hook doesn't
 * exist.
 * Forcibly call the put callback of each slave and call the hook function
 * to synchronize with the current value of the given vmaster element.
 * 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;
	bool first_init = false;

	if (!kcontrol)
		return;
	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);
}
EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook);
EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster);