aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/control.h20
-rw-r--r--sound/core/vmaster.c46
2 files changed, 47 insertions, 19 deletions
diff --git a/include/sound/control.h b/include/sound/control.h
index 4721b4bba053..4cf8f7aaa13f 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -171,6 +171,22 @@ int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
171 */ 171 */
172struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, 172struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
173 const unsigned int *tlv); 173 const unsigned int *tlv);
174int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave); 174int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
175 175 unsigned int flags);
176/* optional flags for slave */
177#define SND_CTL_SLAVE_NEED_UPDATE (1 << 0)
178
179static inline int
180snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
181{
182 return _snd_ctl_add_slave(master, slave, 0);
183}
184
185static inline int
186snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
187 struct snd_kcontrol *slave)
188{
189 return _snd_ctl_add_slave(master, slave, SND_CTL_SLAVE_NEED_UPDATE);
190}
191
176#endif /* __SOUND_CONTROL_H */ 192#endif /* __SOUND_CONTROL_H */
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index 4cc57f902e2c..d51b198d06d9 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -50,18 +50,38 @@ struct link_slave {
50 struct link_master *master; 50 struct link_master *master;
51 struct link_ctl_info info; 51 struct link_ctl_info info;
52 int vals[2]; /* current values */ 52 int vals[2]; /* current values */
53 unsigned int flags;
53 struct snd_kcontrol slave; /* the copy of original control entry */ 54 struct snd_kcontrol slave; /* the copy of original control entry */
54}; 55};
55 56
57static int slave_update(struct link_slave *slave)
58{
59 struct snd_ctl_elem_value *uctl;
60 int err, ch;
61
62 uctl = kmalloc(sizeof(*uctl), GFP_KERNEL);
63 if (!uctl)
64 return -ENOMEM;
65 uctl->id = slave->slave.id;
66 err = slave->slave.get(&slave->slave, uctl);
67 for (ch = 0; ch < slave->info.count; ch++)
68 slave->vals[ch] = uctl->value.integer.value[ch];
69 kfree(uctl);
70 return 0;
71}
72
56/* get the slave ctl info and save the initial values */ 73/* get the slave ctl info and save the initial values */
57static int slave_init(struct link_slave *slave) 74static int slave_init(struct link_slave *slave)
58{ 75{
59 struct snd_ctl_elem_info *uinfo; 76 struct snd_ctl_elem_info *uinfo;
60 struct snd_ctl_elem_value *uctl; 77 int err;
61 int err, ch;
62 78
63 if (slave->info.count) 79 if (slave->info.count) {
64 return 0; /* already initialized */ 80 /* already initialized */
81 if (slave->flags & SND_CTL_SLAVE_NEED_UPDATE)
82 return slave_update(slave);
83 return 0;
84 }
65 85
66 uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL); 86 uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
67 if (!uinfo) 87 if (!uinfo)
@@ -85,15 +105,7 @@ static int slave_init(struct link_slave *slave)
85 slave->info.max_val = uinfo->value.integer.max; 105 slave->info.max_val = uinfo->value.integer.max;
86 kfree(uinfo); 106 kfree(uinfo);
87 107
88 uctl = kmalloc(sizeof(*uctl), GFP_KERNEL); 108 return slave_update(slave);
89 if (!uctl)
90 return -ENOMEM;
91 uctl->id = slave->slave.id;
92 err = slave->slave.get(&slave->slave, uctl);
93 for (ch = 0; ch < slave->info.count; ch++)
94 slave->vals[ch] = uctl->value.integer.value[ch];
95 kfree(uctl);
96 return 0;
97} 109}
98 110
99/* initialize master volume */ 111/* initialize master volume */
@@ -229,7 +241,8 @@ static void slave_free(struct snd_kcontrol *kcontrol)
229 * - logarithmic volume control (dB level), no linear volume 241 * - logarithmic volume control (dB level), no linear volume
230 * - master can only attenuate the volume, no gain 242 * - master can only attenuate the volume, no gain
231 */ 243 */
232int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave) 244int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
245 unsigned int flags)
233{ 246{
234 struct link_master *master_link = snd_kcontrol_chip(master); 247 struct link_master *master_link = snd_kcontrol_chip(master);
235 struct link_slave *srec; 248 struct link_slave *srec;
@@ -241,6 +254,7 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
241 srec->slave = *slave; 254 srec->slave = *slave;
242 memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); 255 memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
243 srec->master = master_link; 256 srec->master = master_link;
257 srec->flags = flags;
244 258
245 /* override callbacks */ 259 /* override callbacks */
246 slave->info = slave_info; 260 slave->info = slave_info;
@@ -254,8 +268,7 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
254 list_add_tail(&srec->list, &master_link->slaves); 268 list_add_tail(&srec->list, &master_link->slaves);
255 return 0; 269 return 0;
256} 270}
257 271EXPORT_SYMBOL(_snd_ctl_add_slave);
258EXPORT_SYMBOL(snd_ctl_add_slave);
259 272
260/* 273/*
261 * ctl callbacks for master controls 274 * ctl callbacks for master controls
@@ -367,5 +380,4 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
367 380
368 return kctl; 381 return kctl;
369} 382}
370
371EXPORT_SYMBOL(snd_ctl_make_virtual_master); 383EXPORT_SYMBOL(snd_ctl_make_virtual_master);