2 * Virtual master and slave controls
4 * Copyright (c) 2008 by Takashi Iwai <tiwai@suse.de>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
12 #include <linux/slab.h>
13 #include <linux/export.h>
14 #include <sound/core.h>
15 #include <sound/control.h>
16 #include <sound/tlv.h>
19 * a subset of information returned via ctl info callback
21 struct link_ctl_info
{
22 snd_ctl_elem_type_t type
; /* value type */
23 int count
; /* item count */
24 int min_val
, max_val
; /* min, max values */
28 * link master - this contains a list of slave controls that are
29 * identical types, i.e. info returns the same value type and value
30 * ranges, but may have different number of counts.
32 * The master control is so far only mono volume/switch for simplicity.
33 * The same value will be applied to all slaves.
36 struct list_head slaves
;
37 struct link_ctl_info info
;
38 int val
; /* the master value */
40 void (*hook
)(void *private_data
, int);
41 void *hook_private_data
;
45 * link slave - this contains a slave control element
47 * It fakes the control callbacsk with additional attenuation by the
48 * master control. A slave may have either one or two channels.
52 struct list_head list
;
53 struct link_master
*master
;
54 struct link_ctl_info info
;
55 int vals
[2]; /* current values */
57 struct snd_kcontrol
*kctl
; /* original kcontrol pointer */
58 struct snd_kcontrol slave
; /* the copy of original control entry */
61 static int slave_update(struct link_slave
*slave
)
63 struct snd_ctl_elem_value
*uctl
;
66 uctl
= kmalloc(sizeof(*uctl
), GFP_KERNEL
);
69 uctl
->id
= slave
->slave
.id
;
70 err
= slave
->slave
.get(&slave
->slave
, uctl
);
73 for (ch
= 0; ch
< slave
->info
.count
; ch
++)
74 slave
->vals
[ch
] = uctl
->value
.integer
.value
[ch
];
77 return err
< 0 ? err
: 0;
80 /* get the slave ctl info and save the initial values */
81 static int slave_init(struct link_slave
*slave
)
83 struct snd_ctl_elem_info
*uinfo
;
86 if (slave
->info
.count
) {
87 /* already initialized */
88 if (slave
->flags
& SND_CTL_SLAVE_NEED_UPDATE
)
89 return slave_update(slave
);
93 uinfo
= kmalloc(sizeof(*uinfo
), GFP_KERNEL
);
96 uinfo
->id
= slave
->slave
.id
;
97 err
= slave
->slave
.info(&slave
->slave
, uinfo
);
102 slave
->info
.type
= uinfo
->type
;
103 slave
->info
.count
= uinfo
->count
;
104 if (slave
->info
.count
> 2 ||
105 (slave
->info
.type
!= SNDRV_CTL_ELEM_TYPE_INTEGER
&&
106 slave
->info
.type
!= SNDRV_CTL_ELEM_TYPE_BOOLEAN
)) {
107 pr_err("ALSA: vmaster: invalid slave element\n");
111 slave
->info
.min_val
= uinfo
->value
.integer
.min
;
112 slave
->info
.max_val
= uinfo
->value
.integer
.max
;
115 return slave_update(slave
);
118 /* initialize master volume */
119 static int master_init(struct link_master
*master
)
121 struct link_slave
*slave
;
123 if (master
->info
.count
)
124 return 0; /* already initialized */
126 list_for_each_entry(slave
, &master
->slaves
, list
) {
127 int err
= slave_init(slave
);
130 master
->info
= slave
->info
;
131 master
->info
.count
= 1; /* always mono */
132 /* set full volume as default (= no attenuation) */
133 master
->val
= master
->info
.max_val
;
135 master
->hook(master
->hook_private_data
, master
->val
);
141 static int slave_get_val(struct link_slave
*slave
,
142 struct snd_ctl_elem_value
*ucontrol
)
146 err
= slave_init(slave
);
149 for (ch
= 0; ch
< slave
->info
.count
; ch
++)
150 ucontrol
->value
.integer
.value
[ch
] = slave
->vals
[ch
];
154 static int slave_put_val(struct link_slave
*slave
,
155 struct snd_ctl_elem_value
*ucontrol
)
159 err
= master_init(slave
->master
);
163 switch (slave
->info
.type
) {
164 case SNDRV_CTL_ELEM_TYPE_BOOLEAN
:
165 for (ch
= 0; ch
< slave
->info
.count
; ch
++)
166 ucontrol
->value
.integer
.value
[ch
] &=
167 !!slave
->master
->val
;
169 case SNDRV_CTL_ELEM_TYPE_INTEGER
:
170 for (ch
= 0; ch
< slave
->info
.count
; ch
++) {
171 /* max master volume is supposed to be 0 dB */
172 vol
= ucontrol
->value
.integer
.value
[ch
];
173 vol
+= slave
->master
->val
- slave
->master
->info
.max_val
;
174 if (vol
< slave
->info
.min_val
)
175 vol
= slave
->info
.min_val
;
176 else if (vol
> slave
->info
.max_val
)
177 vol
= slave
->info
.max_val
;
178 ucontrol
->value
.integer
.value
[ch
] = vol
;
182 return slave
->slave
.put(&slave
->slave
, ucontrol
);
186 * ctl callbacks for slaves
188 static int slave_info(struct snd_kcontrol
*kcontrol
,
189 struct snd_ctl_elem_info
*uinfo
)
191 struct link_slave
*slave
= snd_kcontrol_chip(kcontrol
);
192 return slave
->slave
.info(&slave
->slave
, uinfo
);
195 static int slave_get(struct snd_kcontrol
*kcontrol
,
196 struct snd_ctl_elem_value
*ucontrol
)
198 struct link_slave
*slave
= snd_kcontrol_chip(kcontrol
);
199 return slave_get_val(slave
, ucontrol
);
202 static int slave_put(struct snd_kcontrol
*kcontrol
,
203 struct snd_ctl_elem_value
*ucontrol
)
205 struct link_slave
*slave
= snd_kcontrol_chip(kcontrol
);
206 int err
, ch
, changed
= 0;
208 err
= slave_init(slave
);
211 for (ch
= 0; ch
< slave
->info
.count
; ch
++) {
212 if (slave
->vals
[ch
] != ucontrol
->value
.integer
.value
[ch
]) {
214 slave
->vals
[ch
] = ucontrol
->value
.integer
.value
[ch
];
219 err
= slave_put_val(slave
, ucontrol
);
225 static int slave_tlv_cmd(struct snd_kcontrol
*kcontrol
,
226 int op_flag
, unsigned int size
,
227 unsigned int __user
*tlv
)
229 struct link_slave
*slave
= snd_kcontrol_chip(kcontrol
);
230 /* FIXME: this assumes that the max volume is 0 dB */
231 return slave
->slave
.tlv
.c(&slave
->slave
, op_flag
, size
, tlv
);
234 static void slave_free(struct snd_kcontrol
*kcontrol
)
236 struct link_slave
*slave
= snd_kcontrol_chip(kcontrol
);
237 if (slave
->slave
.private_free
)
238 slave
->slave
.private_free(&slave
->slave
);
240 list_del(&slave
->list
);
245 * Add a slave control to the group with the given master control
247 * All slaves must be the same type (returning the same information
248 * via info callback). The function doesn't check it, so it's your
251 * Also, some additional limitations:
252 * - at most two channels
253 * - logarithmic volume control (dB level), no linear volume
254 * - master can only attenuate the volume, no gain
256 int _snd_ctl_add_slave(struct snd_kcontrol
*master
, struct snd_kcontrol
*slave
,
259 struct link_master
*master_link
= snd_kcontrol_chip(master
);
260 struct link_slave
*srec
;
262 srec
= kzalloc(sizeof(*srec
) +
263 slave
->count
* sizeof(*slave
->vd
), GFP_KERNEL
);
267 srec
->slave
= *slave
;
268 memcpy(srec
->slave
.vd
, slave
->vd
, slave
->count
* sizeof(*slave
->vd
));
269 srec
->master
= master_link
;
272 /* override callbacks */
273 slave
->info
= slave_info
;
274 slave
->get
= slave_get
;
275 slave
->put
= slave_put
;
276 if (slave
->vd
[0].access
& SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK
)
277 slave
->tlv
.c
= slave_tlv_cmd
;
278 slave
->private_data
= srec
;
279 slave
->private_free
= slave_free
;
281 list_add_tail(&srec
->list
, &master_link
->slaves
);
284 EXPORT_SYMBOL(_snd_ctl_add_slave
);
287 * ctl callbacks for master controls
289 static int master_info(struct snd_kcontrol
*kcontrol
,
290 struct snd_ctl_elem_info
*uinfo
)
292 struct link_master
*master
= snd_kcontrol_chip(kcontrol
);
295 ret
= master_init(master
);
298 uinfo
->type
= master
->info
.type
;
299 uinfo
->count
= master
->info
.count
;
300 uinfo
->value
.integer
.min
= master
->info
.min_val
;
301 uinfo
->value
.integer
.max
= master
->info
.max_val
;
305 static int master_get(struct snd_kcontrol
*kcontrol
,
306 struct snd_ctl_elem_value
*ucontrol
)
308 struct link_master
*master
= snd_kcontrol_chip(kcontrol
);
309 int err
= master_init(master
);
312 ucontrol
->value
.integer
.value
[0] = master
->val
;
316 static int sync_slaves(struct link_master
*master
, int old_val
, int new_val
)
318 struct link_slave
*slave
;
319 struct snd_ctl_elem_value
*uval
;
321 uval
= kmalloc(sizeof(*uval
), GFP_KERNEL
);
324 list_for_each_entry(slave
, &master
->slaves
, list
) {
325 master
->val
= old_val
;
326 uval
->id
= slave
->slave
.id
;
327 slave_get_val(slave
, uval
);
328 master
->val
= new_val
;
329 slave_put_val(slave
, uval
);
335 static int master_put(struct snd_kcontrol
*kcontrol
,
336 struct snd_ctl_elem_value
*ucontrol
)
338 struct link_master
*master
= snd_kcontrol_chip(kcontrol
);
339 int err
, new_val
, old_val
;
342 err
= master_init(master
);
346 old_val
= master
->val
;
347 new_val
= ucontrol
->value
.integer
.value
[0];
348 if (new_val
== old_val
)
351 err
= sync_slaves(master
, old_val
, new_val
);
354 if (master
->hook
&& !first_init
)
355 master
->hook(master
->hook_private_data
, master
->val
);
359 static void master_free(struct snd_kcontrol
*kcontrol
)
361 struct link_master
*master
= snd_kcontrol_chip(kcontrol
);
362 struct link_slave
*slave
, *n
;
364 /* free all slave links and retore the original slave kctls */
365 list_for_each_entry_safe(slave
, n
, &master
->slaves
, list
) {
366 struct snd_kcontrol
*sctl
= slave
->kctl
;
367 struct list_head olist
= sctl
->list
;
368 memcpy(sctl
, &slave
->slave
, sizeof(*sctl
));
369 memcpy(sctl
->vd
, slave
->slave
.vd
,
370 sctl
->count
* sizeof(*sctl
->vd
));
371 sctl
->list
= olist
; /* keep the current linked-list */
379 * snd_ctl_make_virtual_master - Create a virtual master control
380 * @name: name string of the control element to create
381 * @tlv: optional TLV int array for dB information
383 * Creates a virtual master control with the given name string.
385 * After creating a vmaster element, you can add the slave controls
386 * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached().
388 * The optional argument @tlv can be used to specify the TLV information
389 * for dB scale of the master control. It should be a single element
390 * with #SNDRV_CTL_TLVT_DB_SCALE, #SNDRV_CTL_TLV_DB_MINMAX or
391 * #SNDRV_CTL_TLVT_DB_MINMAX_MUTE type, and should be the max 0dB.
393 * Return: The created control element, or %NULL for errors (ENOMEM).
395 struct snd_kcontrol
*snd_ctl_make_virtual_master(char *name
,
396 const unsigned int *tlv
)
398 struct link_master
*master
;
399 struct snd_kcontrol
*kctl
;
400 struct snd_kcontrol_new knew
;
402 memset(&knew
, 0, sizeof(knew
));
403 knew
.iface
= SNDRV_CTL_ELEM_IFACE_MIXER
;
405 knew
.info
= master_info
;
407 master
= kzalloc(sizeof(*master
), GFP_KERNEL
);
410 INIT_LIST_HEAD(&master
->slaves
);
412 kctl
= snd_ctl_new1(&knew
, master
);
417 /* override some callbacks */
418 kctl
->info
= master_info
;
419 kctl
->get
= master_get
;
420 kctl
->put
= master_put
;
421 kctl
->private_free
= master_free
;
423 /* additional (constant) TLV read */
425 (tlv
[0] == SNDRV_CTL_TLVT_DB_SCALE
||
426 tlv
[0] == SNDRV_CTL_TLVT_DB_MINMAX
||
427 tlv
[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE
)) {
428 kctl
->vd
[0].access
|= SNDRV_CTL_ELEM_ACCESS_TLV_READ
;
429 memcpy(master
->tlv
, tlv
, sizeof(master
->tlv
));
430 kctl
->tlv
.p
= master
->tlv
;
435 EXPORT_SYMBOL(snd_ctl_make_virtual_master
);
438 * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control
439 * @kcontrol: vmaster kctl element
440 * @hook: the hook function
441 * @private_data: the private_data pointer to be saved
443 * Adds the given hook to the vmaster control element so that it's called
444 * at each time when the value is changed.
448 int snd_ctl_add_vmaster_hook(struct snd_kcontrol
*kcontrol
,
449 void (*hook
)(void *private_data
, int),
452 struct link_master
*master
= snd_kcontrol_chip(kcontrol
);
454 master
->hook_private_data
= private_data
;
457 EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook
);
460 * snd_ctl_sync_vmaster - Sync the vmaster slaves and hook
461 * @kcontrol: vmaster kctl element
462 * @hook_only: sync only the hook
464 * Forcibly call the put callback of each slave and call the hook function
465 * to synchronize with the current value of the given vmaster element.
466 * NOP when NULL is passed to @kcontrol.
468 void snd_ctl_sync_vmaster(struct snd_kcontrol
*kcontrol
, bool hook_only
)
470 struct link_master
*master
;
471 bool first_init
= false;
475 master
= snd_kcontrol_chip(kcontrol
);
477 int err
= master_init(master
);
481 err
= sync_slaves(master
, master
->val
, master
->val
);
486 if (master
->hook
&& !first_init
)
487 master
->hook(master
->hook_private_data
, master
->val
);
489 EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster
);