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 */ 20 struct 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 */ 34 struct 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 48 struct 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 struct snd_kcontrol slave; /* the copy of original control entry */ 54 }; 55 56 /* get the slave ctl info and save the initial values */ 57 static int slave_init(struct link_slave *slave) 58 { 59 struct snd_ctl_elem_info *uinfo; 60 struct snd_ctl_elem_value *uctl; 61 int err, ch; 62 63 if (slave->info.count) 64 return 0; /* already initialized */ 65 66 uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL); 67 if (!uinfo) 68 return -ENOMEM; 69 uinfo->id = slave->slave.id; 70 err = slave->slave.info(&slave->slave, uinfo); 71 if (err < 0) { 72 kfree(uinfo); 73 return err; 74 } 75 slave->info.type = uinfo->type; 76 slave->info.count = uinfo->count; 77 if (slave->info.count > 2 || 78 (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER && 79 slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) { 80 snd_printk(KERN_ERR "invalid slave element\n"); 81 kfree(uinfo); 82 return -EINVAL; 83 } 84 slave->info.min_val = uinfo->value.integer.min; 85 slave->info.max_val = uinfo->value.integer.max; 86 kfree(uinfo); 87 88 uctl = kmalloc(sizeof(*uctl), GFP_KERNEL); 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 } 98 99 /* initialize master volume */ 100 static int master_init(struct link_master *master) 101 { 102 struct link_slave *slave; 103 104 if (master->info.count) 105 return 0; /* already initialized */ 106 107 list_for_each_entry(slave, &master->slaves, list) { 108 int err = slave_init(slave); 109 if (err < 0) 110 return err; 111 master->info = slave->info; 112 master->info.count = 1; /* always mono */ 113 /* set full volume as default (= no attenuation) */ 114 master->val = master->info.max_val; 115 return 0; 116 } 117 return -ENOENT; 118 } 119 120 static int slave_get_val(struct link_slave *slave, 121 struct snd_ctl_elem_value *ucontrol) 122 { 123 int err, ch; 124 125 err = slave_init(slave); 126 if (err < 0) 127 return err; 128 for (ch = 0; ch < slave->info.count; ch++) 129 ucontrol->value.integer.value[ch] = slave->vals[ch]; 130 return 0; 131 } 132 133 static int slave_put_val(struct link_slave *slave, 134 struct snd_ctl_elem_value *ucontrol) 135 { 136 int err, ch, vol; 137 138 err = master_init(slave->master); 139 if (err < 0) 140 return err; 141 142 switch (slave->info.type) { 143 case SNDRV_CTL_ELEM_TYPE_BOOLEAN: 144 for (ch = 0; ch < slave->info.count; ch++) 145 ucontrol->value.integer.value[ch] &= 146 !!slave->master->val; 147 break; 148 case SNDRV_CTL_ELEM_TYPE_INTEGER: 149 for (ch = 0; ch < slave->info.count; ch++) { 150 /* max master volume is supposed to be 0 dB */ 151 vol = ucontrol->value.integer.value[ch]; 152 vol += slave->master->val - slave->master->info.max_val; 153 if (vol < slave->info.min_val) 154 vol = slave->info.min_val; 155 else if (vol > slave->info.max_val) 156 vol = slave->info.max_val; 157 ucontrol->value.integer.value[ch] = vol; 158 } 159 break; 160 } 161 return slave->slave.put(&slave->slave, ucontrol); 162 } 163 164 /* 165 * ctl callbacks for slaves 166 */ 167 static int slave_info(struct snd_kcontrol *kcontrol, 168 struct snd_ctl_elem_info *uinfo) 169 { 170 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 171 return slave->slave.info(&slave->slave, uinfo); 172 } 173 174 static int slave_get(struct snd_kcontrol *kcontrol, 175 struct snd_ctl_elem_value *ucontrol) 176 { 177 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 178 return slave_get_val(slave, ucontrol); 179 } 180 181 static int slave_put(struct snd_kcontrol *kcontrol, 182 struct snd_ctl_elem_value *ucontrol) 183 { 184 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 185 int err, ch, changed = 0; 186 187 err = slave_init(slave); 188 if (err < 0) 189 return err; 190 for (ch = 0; ch < slave->info.count; ch++) { 191 if (slave->vals[ch] != ucontrol->value.integer.value[ch]) { 192 changed = 1; 193 slave->vals[ch] = ucontrol->value.integer.value[ch]; 194 } 195 } 196 if (!changed) 197 return 0; 198 return slave_put_val(slave, ucontrol); 199 } 200 201 static int slave_tlv_cmd(struct snd_kcontrol *kcontrol, 202 int op_flag, unsigned int size, 203 unsigned int __user *tlv) 204 { 205 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 206 /* FIXME: this assumes that the max volume is 0 dB */ 207 return slave->slave.tlv.c(&slave->slave, op_flag, size, tlv); 208 } 209 210 static void slave_free(struct snd_kcontrol *kcontrol) 211 { 212 struct link_slave *slave = snd_kcontrol_chip(kcontrol); 213 if (slave->slave.private_free) 214 slave->slave.private_free(&slave->slave); 215 if (slave->master) 216 list_del(&slave->list); 217 kfree(slave); 218 } 219 220 /* 221 * Add a slave control to the group with the given master control 222 * 223 * All slaves must be the same type (returning the same information 224 * via info callback). The fucntion doesn't check it, so it's your 225 * responsibility. 226 * 227 * Also, some additional limitations: 228 * - at most two channels 229 * - logarithmic volume control (dB level), no linear volume 230 * - master can only attenuate the volume, no gain 231 */ 232 int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave) 233 { 234 struct link_master *master_link = snd_kcontrol_chip(master); 235 struct link_slave *srec; 236 237 srec = kzalloc(sizeof(*srec) + 238 slave->count * sizeof(*slave->vd), GFP_KERNEL); 239 if (!srec) 240 return -ENOMEM; 241 srec->slave = *slave; 242 memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); 243 srec->master = master_link; 244 245 /* override callbacks */ 246 slave->info = slave_info; 247 slave->get = slave_get; 248 slave->put = slave_put; 249 if (slave->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) 250 slave->tlv.c = slave_tlv_cmd; 251 slave->private_data = srec; 252 slave->private_free = slave_free; 253 254 list_add_tail(&srec->list, &master_link->slaves); 255 return 0; 256 } 257 258 EXPORT_SYMBOL(snd_ctl_add_slave); 259 260 /* 261 * ctl callbacks for master controls 262 */ 263 static int master_info(struct snd_kcontrol *kcontrol, 264 struct snd_ctl_elem_info *uinfo) 265 { 266 struct link_master *master = snd_kcontrol_chip(kcontrol); 267 int ret; 268 269 ret = master_init(master); 270 if (ret < 0) 271 return ret; 272 uinfo->type = master->info.type; 273 uinfo->count = master->info.count; 274 uinfo->value.integer.min = master->info.min_val; 275 uinfo->value.integer.max = master->info.max_val; 276 return 0; 277 } 278 279 static int master_get(struct snd_kcontrol *kcontrol, 280 struct snd_ctl_elem_value *ucontrol) 281 { 282 struct link_master *master = snd_kcontrol_chip(kcontrol); 283 int err = master_init(master); 284 if (err < 0) 285 return err; 286 ucontrol->value.integer.value[0] = master->val; 287 return 0; 288 } 289 290 static int master_put(struct snd_kcontrol *kcontrol, 291 struct snd_ctl_elem_value *ucontrol) 292 { 293 struct link_master *master = snd_kcontrol_chip(kcontrol); 294 struct link_slave *slave; 295 struct snd_ctl_elem_value *uval; 296 int err, old_val; 297 298 err = master_init(master); 299 if (err < 0) 300 return err; 301 old_val = master->val; 302 if (ucontrol->value.integer.value[0] == old_val) 303 return 0; 304 305 uval = kmalloc(sizeof(*uval), GFP_KERNEL); 306 if (!uval) 307 return -ENOMEM; 308 list_for_each_entry(slave, &master->slaves, list) { 309 master->val = old_val; 310 uval->id = slave->slave.id; 311 slave_get_val(slave, uval); 312 master->val = ucontrol->value.integer.value[0]; 313 slave_put_val(slave, uval); 314 } 315 kfree(uval); 316 return 1; 317 } 318 319 static void master_free(struct snd_kcontrol *kcontrol) 320 { 321 struct link_master *master = snd_kcontrol_chip(kcontrol); 322 struct link_slave *slave; 323 324 list_for_each_entry(slave, &master->slaves, list) 325 slave->master = NULL; 326 kfree(master); 327 } 328 329 330 /* 331 * Create a virtual master control with the given name 332 */ 333 struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, 334 const unsigned int *tlv) 335 { 336 struct link_master *master; 337 struct snd_kcontrol *kctl; 338 struct snd_kcontrol_new knew; 339 340 memset(&knew, 0, sizeof(knew)); 341 knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 342 knew.name = name; 343 knew.info = master_info; 344 345 master = kzalloc(sizeof(*master), GFP_KERNEL); 346 if (!master) 347 return NULL; 348 INIT_LIST_HEAD(&master->slaves); 349 350 kctl = snd_ctl_new1(&knew, master); 351 if (!kctl) { 352 kfree(master); 353 return NULL; 354 } 355 /* override some callbacks */ 356 kctl->info = master_info; 357 kctl->get = master_get; 358 kctl->put = master_put; 359 kctl->private_free = master_free; 360 361 /* additional (constant) TLV read */ 362 if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) { 363 kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; 364 memcpy(master->tlv, tlv, sizeof(master->tlv)); 365 kctl->tlv.p = master->tlv; 366 } 367 368 return kctl; 369 } 370 371 EXPORT_SYMBOL(snd_ctl_make_virtual_master); 372