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 <sound/core.h>
14 #include <sound/control.h>
17 * a subset of information returned via ctl info callback
19 struct link_ctl_info
{
20 int type
; /* value type */
21 int count
; /* item count */
22 int min_val
, max_val
; /* min, max values */
26 * link master - this contains a list of slave controls that are
27 * identical types, i.e. info returns the same value type and value
28 * ranges, but may have different number of counts.
30 * The master control is so far only mono volume/switch for simplicity.
31 * The same value will be applied to all slaves.
34 struct list_head slaves
;
35 struct link_ctl_info info
;
36 int val
; /* the master value */
40 * link slave - this contains a slave control element
42 * It fakes the control callbacsk with additional attenuation by the
43 * master control. A slave may have either one or two channels.
47 struct list_head list
;
48 struct link_master
*master
;
49 struct link_ctl_info info
;
50 int vals
[2]; /* current values */
51 struct snd_kcontrol slave
; /* the copy of original control entry */
54 /* get the slave ctl info and save the initial values */
55 static int slave_init(struct link_slave
*slave
)
57 struct snd_ctl_elem_info
*uinfo
;
58 struct snd_ctl_elem_value
*uctl
;
61 if (slave
->info
.count
)
62 return 0; /* already initialized */
64 uinfo
= kmalloc(sizeof(*uinfo
), GFP_KERNEL
);
67 uinfo
->id
= slave
->slave
.id
;
68 err
= slave
->slave
.info(&slave
->slave
, uinfo
);
73 slave
->info
.type
= uinfo
->type
;
74 slave
->info
.count
= uinfo
->count
;
75 if (slave
->info
.count
> 2 ||
76 (slave
->info
.type
!= SNDRV_CTL_ELEM_TYPE_INTEGER
&&
77 slave
->info
.type
!= SNDRV_CTL_ELEM_TYPE_BOOLEAN
)) {
78 snd_printk(KERN_ERR
"invalid slave element\n");
82 slave
->info
.min_val
= uinfo
->value
.integer
.min
;
83 slave
->info
.max_val
= uinfo
->value
.integer
.max
;
86 uctl
= kmalloc(sizeof(*uctl
), GFP_KERNEL
);
89 uctl
->id
= slave
->slave
.id
;
90 err
= slave
->slave
.get(&slave
->slave
, uctl
);
91 for (ch
= 0; ch
< slave
->info
.count
; ch
++)
92 slave
->vals
[ch
] = uctl
->value
.integer
.value
[ch
];
97 /* initialize master volume */
98 static int master_init(struct link_master
*master
)
100 struct link_slave
*slave
;
102 if (master
->info
.count
)
103 return 0; /* already initialized */
105 list_for_each_entry(slave
, &master
->slaves
, list
) {
106 int err
= slave_init(slave
);
109 master
->info
= slave
->info
;
110 master
->info
.count
= 1; /* always mono */
111 /* set full volume as default (= no attenuation) */
112 master
->val
= master
->info
.max_val
;
118 static int slave_get_val(struct link_slave
*slave
,
119 struct snd_ctl_elem_value
*ucontrol
)
123 err
= slave_init(slave
);
126 for (ch
= 0; ch
< slave
->info
.count
; ch
++)
127 ucontrol
->value
.integer
.value
[ch
] = slave
->vals
[ch
];
131 static int slave_put_val(struct link_slave
*slave
,
132 struct snd_ctl_elem_value
*ucontrol
)
136 err
= master_init(slave
->master
);
140 switch (slave
->info
.type
) {
141 case SNDRV_CTL_ELEM_TYPE_BOOLEAN
:
142 for (ch
= 0; ch
< slave
->info
.count
; ch
++)
143 ucontrol
->value
.integer
.value
[ch
] &=
144 !!slave
->master
->val
;
146 case SNDRV_CTL_ELEM_TYPE_INTEGER
:
147 for (ch
= 0; ch
< slave
->info
.count
; ch
++) {
148 /* max master volume is supposed to be 0 dB */
149 vol
= ucontrol
->value
.integer
.value
[ch
];
150 vol
+= slave
->master
->val
- slave
->master
->info
.max_val
;
151 if (vol
< slave
->info
.min_val
)
152 vol
= slave
->info
.min_val
;
153 else if (vol
> slave
->info
.max_val
)
154 vol
= slave
->info
.max_val
;
155 ucontrol
->value
.integer
.value
[ch
] = vol
;
159 return slave
->slave
.put(&slave
->slave
, ucontrol
);
163 * ctl callbacks for slaves
165 static int slave_info(struct snd_kcontrol
*kcontrol
,
166 struct snd_ctl_elem_info
*uinfo
)
168 struct link_slave
*slave
= snd_kcontrol_chip(kcontrol
);
169 return slave
->slave
.info(&slave
->slave
, uinfo
);
172 static int slave_get(struct snd_kcontrol
*kcontrol
,
173 struct snd_ctl_elem_value
*ucontrol
)
175 struct link_slave
*slave
= snd_kcontrol_chip(kcontrol
);
176 return slave_get_val(slave
, ucontrol
);
179 static int slave_put(struct snd_kcontrol
*kcontrol
,
180 struct snd_ctl_elem_value
*ucontrol
)
182 struct link_slave
*slave
= snd_kcontrol_chip(kcontrol
);
183 int err
, ch
, changed
= 0;
185 err
= slave_init(slave
);
188 for (ch
= 0; ch
< slave
->info
.count
; ch
++) {
189 if (slave
->vals
[ch
] != ucontrol
->value
.integer
.value
[ch
]) {
191 slave
->vals
[ch
] = ucontrol
->value
.integer
.value
[ch
];
196 return slave_put_val(slave
, ucontrol
);
199 static int slave_tlv_cmd(struct snd_kcontrol
*kcontrol
,
200 int op_flag
, unsigned int size
,
201 unsigned int __user
*tlv
)
203 struct link_slave
*slave
= snd_kcontrol_chip(kcontrol
);
204 /* FIXME: this assumes that the max volume is 0 dB */
205 return slave
->slave
.tlv
.c(&slave
->slave
, op_flag
, size
, tlv
);
208 static void slave_free(struct snd_kcontrol
*kcontrol
)
210 struct link_slave
*slave
= snd_kcontrol_chip(kcontrol
);
211 if (slave
->slave
.private_free
)
212 slave
->slave
.private_free(&slave
->slave
);
214 list_del(&slave
->list
);
219 * Add a slave control to the group with the given master control
221 * All slaves must be the same type (returning the same information
222 * via info callback). The fucntion doesn't check it, so it's your
225 * Also, some additional limitations:
226 * - at most two channels
227 * - logarithmic volume control (dB level), no linear volume
228 * - master can only attenuate the volume, no gain
230 int snd_ctl_add_slave(struct snd_kcontrol
*master
, struct snd_kcontrol
*slave
)
232 struct link_master
*master_link
= snd_kcontrol_chip(master
);
233 struct link_slave
*srec
;
235 srec
= kzalloc(sizeof(*srec
) +
236 slave
->count
* sizeof(*slave
->vd
), GFP_KERNEL
);
239 srec
->slave
= *slave
;
240 memcpy(srec
->slave
.vd
, slave
->vd
, slave
->count
* sizeof(*slave
->vd
));
241 srec
->master
= master_link
;
243 /* override callbacks */
244 slave
->info
= slave_info
;
245 slave
->get
= slave_get
;
246 slave
->put
= slave_put
;
247 if (slave
->vd
[0].access
& SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK
)
248 slave
->tlv
.c
= slave_tlv_cmd
;
249 slave
->private_data
= srec
;
250 slave
->private_free
= slave_free
;
252 list_add_tail(&srec
->list
, &master_link
->slaves
);
257 * ctl callbacks for master controls
259 static int master_info(struct snd_kcontrol
*kcontrol
,
260 struct snd_ctl_elem_info
*uinfo
)
262 struct link_master
*master
= snd_kcontrol_chip(kcontrol
);
265 ret
= master_init(master
);
268 uinfo
->type
= master
->info
.type
;
269 uinfo
->count
= master
->info
.count
;
270 uinfo
->value
.integer
.min
= master
->info
.min_val
;
271 uinfo
->value
.integer
.max
= master
->info
.max_val
;
275 static int master_get(struct snd_kcontrol
*kcontrol
,
276 struct snd_ctl_elem_value
*ucontrol
)
278 struct link_master
*master
= snd_kcontrol_chip(kcontrol
);
279 int err
= master_init(master
);
282 ucontrol
->value
.integer
.value
[0] = master
->val
;
286 static int master_put(struct snd_kcontrol
*kcontrol
,
287 struct snd_ctl_elem_value
*ucontrol
)
289 struct link_master
*master
= snd_kcontrol_chip(kcontrol
);
290 struct link_slave
*slave
;
291 struct snd_ctl_elem_value
*uval
;
294 err
= master_init(master
);
297 old_val
= master
->val
;
298 if (ucontrol
->value
.integer
.value
[0] == old_val
)
301 uval
= kmalloc(sizeof(*uval
), GFP_KERNEL
);
304 list_for_each_entry(slave
, &master
->slaves
, list
) {
305 master
->val
= old_val
;
306 uval
->id
= slave
->slave
.id
;
307 slave_get_val(slave
, uval
);
308 master
->val
= ucontrol
->value
.integer
.value
[0];
309 slave_put_val(slave
, uval
);
315 static void master_free(struct snd_kcontrol
*kcontrol
)
317 struct link_master
*master
= snd_kcontrol_chip(kcontrol
);
318 struct link_slave
*slave
;
320 list_for_each_entry(slave
, &master
->slaves
, list
)
321 slave
->master
= NULL
;
327 * Create a virtual master control with the given name
329 struct snd_kcontrol
*snd_ctl_make_virtual_master(char *name
,
330 const unsigned int *tlv
)
332 struct link_master
*master
;
333 struct snd_kcontrol
*kctl
;
334 struct snd_kcontrol_new knew
;
336 memset(&knew
, 0, sizeof(knew
));
337 knew
.iface
= SNDRV_CTL_ELEM_IFACE_MIXER
;
339 knew
.info
= master_info
;
341 master
= kzalloc(sizeof(*master
), GFP_KERNEL
);
344 INIT_LIST_HEAD(&master
->slaves
);
346 kctl
= snd_ctl_new1(&knew
, master
);
351 /* override some callbacks */
352 kctl
->info
= master_info
;
353 kctl
->get
= master_get
;
354 kctl
->put
= master_put
;
355 kctl
->private_free
= master_free
;
357 /* additional (constant) TLV read */
359 /* FIXME: this assumes that the max volume is 0 dB */
360 kctl
->vd
[0].access
|= SNDRV_CTL_ELEM_ACCESS_TLV_READ
;