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