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 <linux/export.h> 14#include <sound/core.h> 15#include <sound/control.h> 16#include <sound/tlv.h> 17 18/* 19 * a subset of information returned via ctl info callback 20 */ 21struct 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 */ 25}; 26 27/* 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. 31 * 32 * The master control is so far only mono volume/switch for simplicity. 33 * The same value will be applied to all slaves. 34 */ 35struct link_master { 36 struct list_head slaves; 37 struct link_ctl_info info; 38 int val; /* the master value */ 39 unsigned int tlv[4]; 40 void (*hook)(void *private_data, int); 41 void *hook_private_data; 42}; 43 44/* 45 * link slave - this contains a slave control element 46 * 47 * It fakes the control callbacsk with additional attenuation by the 48 * master control. A slave may have either one or two channels. 49 */ 50 51struct link_slave { 52 struct list_head list; 53 struct link_master *master; 54 struct link_ctl_info info; 55 int vals[2]; /* current values */ 56 unsigned int flags; 57 struct snd_kcontrol *kctl; /* original kcontrol pointer */ 58 struct snd_kcontrol slave; /* the copy of original control entry */ 59}; 60 61static int slave_update(struct link_slave *slave) 62{ 63 struct snd_ctl_elem_value *uctl; 64 int err, ch; 65 66 uctl = kmalloc(sizeof(*uctl), GFP_KERNEL); 67 if (!uctl) 68 return -ENOMEM; 69 uctl->id = slave->slave.id; 70 err = slave->slave.get(&slave->slave, uctl); 71 for (ch = 0; ch < slave->info.count; ch++) 72 slave->vals[ch] = uctl->value.integer.value[ch]; 73 kfree(uctl); 74 return 0; 75} 76 77/* get the slave ctl info and save the initial values */ 78static int slave_init(struct link_slave *slave) 79{ 80 struct snd_ctl_elem_info *uinfo; 81 int err; 82 83 if (slave->info.count) { 84 /* already initialized */ 85 if (slave->flags & SND_CTL_SLAVE_NEED_UPDATE) 86 return slave_update(slave); 87 return 0; 88 } 89 90 uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL); 91 if (!uinfo) 92 return -ENOMEM; 93 uinfo->id = slave->slave.id; 94 err = slave->slave.info(&slave->slave, uinfo); 95 if (err < 0) { 96 kfree(uinfo); 97 return err; 98 } 99 slave->info.type = uinfo->type; 100 slave->info.count = uinfo->count; 101 if (slave->info.count > 2 || 102 (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER && 103 slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) { 104 pr_err("ALSA: vmaster: invalid slave element\n"); 105 kfree(uinfo); 106 return -EINVAL; 107 } 108 slave->info.min_val = uinfo->value.integer.min; 109 slave->info.max_val = uinfo->value.integer.max; 110 kfree(uinfo); 111 112 return slave_update(slave); 113} 114 115/* initialize master volume */ 116static int master_init(struct link_master *master) 117{ 118 struct link_slave *slave; 119 120 if (master->info.count) 121 return 0; /* already initialized */ 122 123 list_for_each_entry(slave, &master->slaves, list) { 124 int err = slave_init(slave); 125 if (err < 0) 126 return err; 127 master->info = slave->info; 128 master->info.count = 1; /* always mono */ 129 /* set full volume as default (= no attenuation) */ 130 master->val = master->info.max_val; 131 if (master->hook) 132 master->hook(master->hook_private_data, master->val); 133 return 1; 134 } 135 return -ENOENT; 136} 137 138static int slave_get_val(struct link_slave *slave, 139 struct snd_ctl_elem_value *ucontrol) 140{ 141 int err, ch; 142 143 err = slave_init(slave); 144 if (err < 0) 145 return err; 146 for (ch = 0; ch < slave->info.count; ch++) 147 ucontrol->value.integer.value[ch] = slave->vals[ch]; 148 return 0; 149} 150 151static int slave_put_val(struct link_slave *slave, 152 struct snd_ctl_elem_value *ucontrol) 153{ 154 int err, ch, vol; 155 156 err = master_init(slave->master); 157 if (err < 0) 158 return err; 159 160 switch (slave->info.type) { 161 case SNDRV_CTL_ELEM_TYPE_BOOLEAN: 162 for (ch = 0; ch < slave->info.count; ch++) 163 ucontrol->value.integer.value[ch] &= 164 !!slave->master->val; 165 break; 166 case SNDRV_CTL_ELEM_TYPE_INTEGER: 167 for (ch = 0; ch < slave->info.count; ch++) { 168 /* max master volume is supposed to be 0 dB */ 169 vol = ucontrol->value.integer.value[ch]; 170 vol += slave->master->val - slave->master->info.max_val; 171 if (vol < slave->info.min_val) 172 vol = slave->info.min_val; 173 else if (vol > slave->info.max_val) 174 vol = slave->info.max_val; 175 ucontrol->value.integer.value[ch] = vol; 176 } 177 break; 178 } 179 return slave->slave.put(&slave->slave, ucontrol); 180} 181 182/* 183 * ctl callbacks for slaves 184 */ 185static int slave_info(struct snd_kcontrol *kcontrol, 186 struct snd_ctl_elem_info *uinfo) 187{ 188 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 189 return slave->slave.info(&slave->slave, uinfo); 190} 191 192static int slave_get(struct snd_kcontrol *kcontrol, 193 struct snd_ctl_elem_value *ucontrol) 194{ 195 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 196 return slave_get_val(slave, ucontrol); 197} 198 199static int slave_put(struct snd_kcontrol *kcontrol, 200 struct snd_ctl_elem_value *ucontrol) 201{ 202 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 203 int err, ch, changed = 0; 204 205 err = slave_init(slave); 206 if (err < 0) 207 return err; 208 for (ch = 0; ch < slave->info.count; ch++) { 209 if (slave->vals[ch] != ucontrol->value.integer.value[ch]) { 210 changed = 1; 211 slave->vals[ch] = ucontrol->value.integer.value[ch]; 212 } 213 } 214 if (!changed) 215 return 0; 216 err = slave_put_val(slave, ucontrol); 217 if (err < 0) 218 return err; 219 return 1; 220} 221 222static int slave_tlv_cmd(struct snd_kcontrol *kcontrol, 223 int op_flag, unsigned int size, 224 unsigned int __user *tlv) 225{ 226 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 227 /* FIXME: this assumes that the max volume is 0 dB */ 228 return slave->slave.tlv.c(&slave->slave, op_flag, size, tlv); 229} 230 231static void slave_free(struct snd_kcontrol *kcontrol) 232{ 233 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 234 if (slave->slave.private_free) 235 slave->slave.private_free(&slave->slave); 236 if (slave->master) 237 list_del(&slave->list); 238 kfree(slave); 239} 240 241/* 242 * Add a slave control to the group with the given master control 243 * 244 * All slaves must be the same type (returning the same information 245 * via info callback). The function doesn't check it, so it's your 246 * responsibility. 247 * 248 * Also, some additional limitations: 249 * - at most two channels 250 * - logarithmic volume control (dB level), no linear volume 251 * - master can only attenuate the volume, no gain 252 */ 253int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, 254 unsigned int flags) 255{ 256 struct link_master *master_link = snd_kcontrol_chip(master); 257 struct link_slave *srec; 258 259 srec = kzalloc(sizeof(*srec) + 260 slave->count * sizeof(*slave->vd), GFP_KERNEL); 261 if (!srec) 262 return -ENOMEM; 263 srec->kctl = slave; 264 srec->slave = *slave; 265 memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); 266 srec->master = master_link; 267 srec->flags = flags; 268 269 /* override callbacks */ 270 slave->info = slave_info; 271 slave->get = slave_get; 272 slave->put = slave_put; 273 if (slave->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) 274 slave->tlv.c = slave_tlv_cmd; 275 slave->private_data = srec; 276 slave->private_free = slave_free; 277 278 list_add_tail(&srec->list, &master_link->slaves); 279 return 0; 280} 281EXPORT_SYMBOL(_snd_ctl_add_slave); 282 283/* 284 * ctl callbacks for master controls 285 */ 286static int master_info(struct snd_kcontrol *kcontrol, 287 struct snd_ctl_elem_info *uinfo) 288{ 289 struct link_master *master = snd_kcontrol_chip(kcontrol); 290 int ret; 291 292 ret = master_init(master); 293 if (ret < 0) 294 return ret; 295 uinfo->type = master->info.type; 296 uinfo->count = master->info.count; 297 uinfo->value.integer.min = master->info.min_val; 298 uinfo->value.integer.max = master->info.max_val; 299 return 0; 300} 301 302static int master_get(struct snd_kcontrol *kcontrol, 303 struct snd_ctl_elem_value *ucontrol) 304{ 305 struct link_master *master = snd_kcontrol_chip(kcontrol); 306 int err = master_init(master); 307 if (err < 0) 308 return err; 309 ucontrol->value.integer.value[0] = master->val; 310 return 0; 311} 312 313static int sync_slaves(struct link_master *master, int old_val, int new_val) 314{ 315 struct link_slave *slave; 316 struct snd_ctl_elem_value *uval; 317 318 uval = kmalloc(sizeof(*uval), GFP_KERNEL); 319 if (!uval) 320 return -ENOMEM; 321 list_for_each_entry(slave, &master->slaves, list) { 322 master->val = old_val; 323 uval->id = slave->slave.id; 324 slave_get_val(slave, uval); 325 master->val = new_val; 326 slave_put_val(slave, uval); 327 } 328 kfree(uval); 329 return 0; 330} 331 332static int master_put(struct snd_kcontrol *kcontrol, 333 struct snd_ctl_elem_value *ucontrol) 334{ 335 struct link_master *master = snd_kcontrol_chip(kcontrol); 336 int err, new_val, old_val; 337 bool first_init; 338 339 err = master_init(master); 340 if (err < 0) 341 return err; 342 first_init = err; 343 old_val = master->val; 344 new_val = ucontrol->value.integer.value[0]; 345 if (new_val == old_val) 346 return 0; 347 348 err = sync_slaves(master, old_val, new_val); 349 if (err < 0) 350 return err; 351 if (master->hook && !first_init) 352 master->hook(master->hook_private_data, master->val); 353 return 1; 354} 355 356static void master_free(struct snd_kcontrol *kcontrol) 357{ 358 struct link_master *master = snd_kcontrol_chip(kcontrol); 359 struct link_slave *slave, *n; 360 361 /* free all slave links and retore the original slave kctls */ 362 list_for_each_entry_safe(slave, n, &master->slaves, list) { 363 struct snd_kcontrol *sctl = slave->kctl; 364 struct list_head olist = sctl->list; 365 memcpy(sctl, &slave->slave, sizeof(*sctl)); 366 memcpy(sctl->vd, slave->slave.vd, 367 sctl->count * sizeof(*sctl->vd)); 368 sctl->list = olist; /* keep the current linked-list */ 369 kfree(slave); 370 } 371 kfree(master); 372} 373 374 375/** 376 * snd_ctl_make_virtual_master - Create a virtual master control 377 * @name: name string of the control element to create 378 * @tlv: optional TLV int array for dB information 379 * 380 * Creates a virtual master control with the given name string. 381 * 382 * After creating a vmaster element, you can add the slave controls 383 * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached(). 384 * 385 * The optional argument @tlv can be used to specify the TLV information 386 * for dB scale of the master control. It should be a single element 387 * with #SNDRV_CTL_TLVT_DB_SCALE, #SNDRV_CTL_TLV_DB_MINMAX or 388 * #SNDRV_CTL_TLVT_DB_MINMAX_MUTE type, and should be the max 0dB. 389 * 390 * Return: The created control element, or %NULL for errors (ENOMEM). 391 */ 392struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, 393 const unsigned int *tlv) 394{ 395 struct link_master *master; 396 struct snd_kcontrol *kctl; 397 struct snd_kcontrol_new knew; 398 399 memset(&knew, 0, sizeof(knew)); 400 knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 401 knew.name = name; 402 knew.info = master_info; 403 404 master = kzalloc(sizeof(*master), GFP_KERNEL); 405 if (!master) 406 return NULL; 407 INIT_LIST_HEAD(&master->slaves); 408 409 kctl = snd_ctl_new1(&knew, master); 410 if (!kctl) { 411 kfree(master); 412 return NULL; 413 } 414 /* override some callbacks */ 415 kctl->info = master_info; 416 kctl->get = master_get; 417 kctl->put = master_put; 418 kctl->private_free = master_free; 419 420 /* additional (constant) TLV read */ 421 if (tlv && 422 (tlv[0] == SNDRV_CTL_TLVT_DB_SCALE || 423 tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX || 424 tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) { 425 kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; 426 memcpy(master->tlv, tlv, sizeof(master->tlv)); 427 kctl->tlv.p = master->tlv; 428 } 429 430 return kctl; 431} 432EXPORT_SYMBOL(snd_ctl_make_virtual_master); 433 434/** 435 * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control 436 * @kcontrol: vmaster kctl element 437 * @hook: the hook function 438 * @private_data: the private_data pointer to be saved 439 * 440 * Adds the given hook to the vmaster control element so that it's called 441 * at each time when the value is changed. 442 * 443 * Return: Zero. 444 */ 445int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol, 446 void (*hook)(void *private_data, int), 447 void *private_data) 448{ 449 struct link_master *master = snd_kcontrol_chip(kcontrol); 450 master->hook = hook; 451 master->hook_private_data = private_data; 452 return 0; 453} 454EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook); 455 456/** 457 * snd_ctl_sync_vmaster - Sync the vmaster slaves and hook 458 * @kcontrol: vmaster kctl element 459 * @hook_only: sync only the hook 460 * 461 * Forcibly call the put callback of each slave and call the hook function 462 * to synchronize with the current value of the given vmaster element. 463 * NOP when NULL is passed to @kcontrol. 464 */ 465void snd_ctl_sync_vmaster(struct snd_kcontrol *kcontrol, bool hook_only) 466{ 467 struct link_master *master; 468 bool first_init = false; 469 470 if (!kcontrol) 471 return; 472 master = snd_kcontrol_chip(kcontrol); 473 if (!hook_only) { 474 int err = master_init(master); 475 if (err < 0) 476 return; 477 first_init = err; 478 err = sync_slaves(master, master->val, master->val); 479 if (err < 0) 480 return; 481 } 482 483 if (master->hook && !first_init) 484 master->hook(master->hook_private_data, master->val); 485} 486EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster); 487