vmaster.c 15 KB

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