1/* 2 * Virtual master and slave controls 3 * 4 * Copyright (c) 2008 by Takashi Iwai <tiwai@suse.de> 5 * 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. 9 * 10 */ 11 12#include <linux/slab.h> 13#include <sound/core.h> 14#include <sound/control.h> 15#include <sound/tlv.h> 16 17/* 18 * a subset of information returned via ctl info callback 19 */ 20struct link_ctl_info { 21 int type; /* value type */ 22 int count; /* item count */ 23 int min_val, max_val; /* min, max values */ 24}; 25 26/* 27 * link master - this contains a list of slave controls that are 28 * identical types, i.e. info returns the same value type and value 29 * ranges, but may have different number of counts. 30 * 31 * The master control is so far only mono volume/switch for simplicity. 32 * The same value will be applied to all slaves. 33 */ 34struct link_master { 35 struct list_head slaves; 36 struct link_ctl_info info; 37 int val; /* the master value */ 38 unsigned int tlv[4]; 39}; 40 41/* 42 * link slave - this contains a slave control element 43 * 44 * It fakes the control callbacsk with additional attenuation by the 45 * master control. A slave may have either one or two channels. 46 */ 47 48struct link_slave { 49 struct list_head list; 50 struct link_master *master; 51 struct link_ctl_info info; 52 int vals[2]; /* current values */ 53 unsigned int flags; 54 struct snd_kcontrol slave; /* the copy of original control entry */ 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 73/* get the slave ctl info and save the initial values */ 74static int slave_init(struct link_slave *slave) 75{ 76 struct snd_ctl_elem_info *uinfo; 77 int err; 78 79 if (slave->info.count) { 80 /* already initialized */ 81 if (slave->flags & SND_CTL_SLAVE_NEED_UPDATE) 82 return slave_update(slave); 83 return 0; 84 } 85 86 uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL); 87 if (!uinfo) 88 return -ENOMEM; 89 uinfo->id = slave->slave.id; 90 err = slave->slave.info(&slave->slave, uinfo); 91 if (err < 0) { 92 kfree(uinfo); 93 return err; 94 } 95 slave->info.type = uinfo->type; 96 slave->info.count = uinfo->count; 97 if (slave->info.count > 2 || 98 (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER && 99 slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) { 100 snd_printk(KERN_ERR "invalid slave element\n"); 101 kfree(uinfo); 102 return -EINVAL; 103 } 104 slave->info.min_val = uinfo->value.integer.min; 105 slave->info.max_val = uinfo->value.integer.max; 106 kfree(uinfo); 107 108 return slave_update(slave); 109} 110 111/* initialize master volume */ 112static int master_init(struct link_master *master) 113{ 114 struct link_slave *slave; 115 116 if (master->info.count) 117 return 0; /* already initialized */ 118 119 list_for_each_entry(slave, &master->slaves, list) { 120 int err = slave_init(slave); 121 if (err < 0) 122 return err; 123 master->info = slave->info; 124 master->info.count = 1; /* always mono */ 125 /* set full volume as default (= no attenuation) */ 126 master->val = master->info.max_val; 127 return 0; 128 } 129 return -ENOENT; 130} 131 132static int slave_get_val(struct link_slave *slave, 133 struct snd_ctl_elem_value *ucontrol) 134{ 135 int err, ch; 136 137 err = slave_init(slave); 138 if (err < 0) 139 return err; 140 for (ch = 0; ch < slave->info.count; ch++) 141 ucontrol->value.integer.value[ch] = slave->vals[ch]; 142 return 0; 143} 144 145static int slave_put_val(struct link_slave *slave, 146 struct snd_ctl_elem_value *ucontrol) 147{ 148 int err, ch, vol; 149 150 err = master_init(slave->master); 151 if (err < 0) 152 return err; 153 154 switch (slave->info.type) { 155 case SNDRV_CTL_ELEM_TYPE_BOOLEAN: 156 for (ch = 0; ch < slave->info.count; ch++) 157 ucontrol->value.integer.value[ch] &= 158 !!slave->master->val; 159 break; 160 case SNDRV_CTL_ELEM_TYPE_INTEGER: 161 for (ch = 0; ch < slave->info.count; ch++) { 162 /* max master volume is supposed to be 0 dB */ 163 vol = ucontrol->value.integer.value[ch]; 164 vol += slave->master->val - slave->master->info.max_val; 165 if (vol < slave->info.min_val) 166 vol = slave->info.min_val; 167 else if (vol > slave->info.max_val) 168 vol = slave->info.max_val; 169 ucontrol->value.integer.value[ch] = vol; 170 } 171 break; 172 } 173 return slave->slave.put(&slave->slave, ucontrol); 174} 175 176/* 177 * ctl callbacks for slaves 178 */ 179static int slave_info(struct snd_kcontrol *kcontrol, 180 struct snd_ctl_elem_info *uinfo) 181{ 182 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 183 return slave->slave.info(&slave->slave, uinfo); 184} 185 186static int slave_get(struct snd_kcontrol *kcontrol, 187 struct snd_ctl_elem_value *ucontrol) 188{ 189 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 190 return slave_get_val(slave, ucontrol); 191} 192 193static int slave_put(struct snd_kcontrol *kcontrol, 194 struct snd_ctl_elem_value *ucontrol) 195{ 196 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 197 int err, ch, changed = 0; 198 199 err = slave_init(slave); 200 if (err < 0) 201 return err; 202 for (ch = 0; ch < slave->info.count; ch++) { 203 if (slave->vals[ch] != ucontrol->value.integer.value[ch]) { 204 changed = 1; 205 slave->vals[ch] = ucontrol->value.integer.value[ch]; 206 } 207 } 208 if (!changed) 209 return 0; 210 return slave_put_val(slave, ucontrol); 211} 212 213static int slave_tlv_cmd(struct snd_kcontrol *kcontrol, 214 int op_flag, unsigned int size, 215 unsigned int __user *tlv) 216{ 217 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 218 return slave->slave.tlv.c(&slave->slave, op_flag, size, tlv); 219} 220 221static void slave_free(struct snd_kcontrol *kcontrol) 222{ 223 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 224 if (slave->slave.private_free) 225 slave->slave.private_free(&slave->slave); 226 if (slave->master) 227 list_del(&slave->list); 228 kfree(slave); 229} 230 231/* 232 * Add a slave control to the group with the given master control 233 * 234 * All slaves must be the same type (returning the same information 235 * via info callback). The fucntion doesn't check it, so it's your 236 * responsibility. 237 * 238 * Also, some additional limitations: 239 * - at most two channels 240 * - logarithmic volume control (dB level), no linear volume 241 * - master can only attenuate the volume, no gain 242 */ 243int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, 244 unsigned int flags) 245{ 246 struct link_master *master_link = snd_kcontrol_chip(master); 247 struct link_slave *srec; 248 249 srec = kzalloc(sizeof(*srec) + 250 slave->count * sizeof(*slave->vd), GFP_KERNEL); 251 if (!srec) 252 return -ENOMEM; 253 srec->slave = *slave; 254 memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); 255 srec->master = master_link; 256 srec->flags = flags; 257 258 /* override callbacks */ 259 slave->info = slave_info; 260 slave->get = slave_get; 261 slave->put = slave_put; 262 if (slave->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) 263 slave->tlv.c = slave_tlv_cmd; 264 slave->private_data = srec; 265 slave->private_free = slave_free; 266 267 list_add_tail(&srec->list, &master_link->slaves); 268 return 0; 269} 270EXPORT_SYMBOL(_snd_ctl_add_slave); 271 272/* 273 * ctl callbacks for master controls 274 */ 275static int master_info(struct snd_kcontrol *kcontrol, 276 struct snd_ctl_elem_info *uinfo) 277{ 278 struct link_master *master = snd_kcontrol_chip(kcontrol); 279 int ret; 280 281 ret = master_init(master); 282 if (ret < 0) 283 return ret; 284 uinfo->type = master->info.type; 285 uinfo->count = master->info.count; 286 uinfo->value.integer.min = master->info.min_val; 287 uinfo->value.integer.max = master->info.max_val; 288 return 0; 289} 290 291static int master_get(struct snd_kcontrol *kcontrol, 292 struct snd_ctl_elem_value *ucontrol) 293{ 294 struct link_master *master = snd_kcontrol_chip(kcontrol); 295 int err = master_init(master); 296 if (err < 0) 297 return err; 298 ucontrol->value.integer.value[0] = master->val; 299 return 0; 300} 301 302static int master_put(struct snd_kcontrol *kcontrol, 303 struct snd_ctl_elem_value *ucontrol) 304{ 305 struct link_master *master = snd_kcontrol_chip(kcontrol); 306 struct link_slave *slave; 307 struct snd_ctl_elem_value *uval; 308 int err, old_val; 309 310 err = master_init(master); 311 if (err < 0) 312 return err; 313 old_val = master->val; 314 if (ucontrol->value.integer.value[0] == old_val) 315 return 0; 316 317 uval = kmalloc(sizeof(*uval), GFP_KERNEL); 318 if (!uval) 319 return -ENOMEM; 320 list_for_each_entry(slave, &master->slaves, list) { 321 master->val = old_val; 322 uval->id = slave->slave.id; 323 slave_get_val(slave, uval); 324 master->val = ucontrol->value.integer.value[0]; 325 slave_put_val(slave, uval); 326 } 327 kfree(uval); 328 return 1; 329} 330 331static void master_free(struct snd_kcontrol *kcontrol) 332{ 333 struct link_master *master = snd_kcontrol_chip(kcontrol); 334 struct link_slave *slave; 335 336 list_for_each_entry(slave, &master->slaves, list) 337 slave->master = NULL; 338 kfree(master); 339} 340 341 342/** 343 * snd_ctl_make_virtual_master - Create a virtual master control 344 * @name: name string of the control element to create 345 * @tlv: optional TLV int array for dB information 346 * 347 * Creates a virtual matster control with the given name string. 348 * Returns the created control element, or NULL for errors (ENOMEM). 349 * 350 * After creating a vmaster element, you can add the slave controls 351 * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached(). 352 * 353 * The optional argument @tlv can be used to specify the TLV information 354 * for dB scale of the master control. It should be a single element 355 * with #SNDRV_CTL_TLVT_DB_SCALE, #SNDRV_CTL_TLV_DB_MINMAX or 356 * #SNDRV_CTL_TLVT_DB_MINMAX_MUTE type, and should be the max 0dB. 357 */ 358struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, 359 const unsigned int *tlv) 360{ 361 struct link_master *master; 362 struct snd_kcontrol *kctl; 363 struct snd_kcontrol_new knew; 364 365 memset(&knew, 0, sizeof(knew)); 366 knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 367 knew.name = name; 368 knew.info = master_info; 369 370 master = kzalloc(sizeof(*master), GFP_KERNEL); 371 if (!master) 372 return NULL; 373 INIT_LIST_HEAD(&master->slaves); 374 375 kctl = snd_ctl_new1(&knew, master); 376 if (!kctl) { 377 kfree(master); 378 return NULL; 379 } 380 /* override some callbacks */ 381 kctl->info = master_info; 382 kctl->get = master_get; 383 kctl->put = master_put; 384 kctl->private_free = master_free; 385 386 /* additional (constant) TLV read */ 387 if (tlv && 388 (tlv[0] == SNDRV_CTL_TLVT_DB_SCALE || 389 tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX || 390 tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) { 391 kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; 392 memcpy(master->tlv, tlv, sizeof(master->tlv)); 393 kctl->tlv.p = master->tlv; 394 } 395 396 return kctl; 397} 398EXPORT_SYMBOL(snd_ctl_make_virtual_master); 399