Lines Matching +full:ch +full:- +full:func

1 // SPDX-License-Identifier: GPL-2.0-only
24 * link master - this contains a list of follower controls that are
41 * link follower - this contains a follower control element
60 int err, ch; in follower_update() local
64 return -ENOMEM; in follower_update()
65 uctl->id = follower->follower.id; in follower_update()
66 err = follower->follower.get(&follower->follower, uctl); in follower_update()
69 for (ch = 0; ch < follower->info.count; ch++) in follower_update()
70 follower->vals[ch] = uctl->value.integer.value[ch]; in follower_update()
80 if (follower->info.count) { in follower_init()
82 if (follower->flags & SND_CTL_FOLLOWER_NEED_UPDATE) in follower_init()
89 return -ENOMEM; in follower_init()
90 uinfo->id = follower->follower.id; in follower_init()
91 err = follower->follower.info(&follower->follower, uinfo); in follower_init()
94 follower->info.type = uinfo->type; in follower_init()
95 follower->info.count = uinfo->count; in follower_init()
96 if (follower->info.count > 2 || in follower_init()
97 (follower->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER && in follower_init()
98 follower->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) { in follower_init()
100 return -EINVAL; in follower_init()
102 follower->info.min_val = uinfo->value.integer.min; in follower_init()
103 follower->info.max_val = uinfo->value.integer.max; in follower_init()
113 if (master->info.count) in master_init()
116 list_for_each_entry(follower, &master->followers, list) { in master_init()
120 master->info = follower->info; in master_init()
121 master->info.count = 1; /* always mono */ in master_init()
123 master->val = master->info.max_val; in master_init()
124 if (master->hook) in master_init()
125 master->hook(master->hook_private_data, master->val); in master_init()
128 return -ENOENT; in master_init()
134 int err, ch; in follower_get_val() local
139 for (ch = 0; ch < follower->info.count; ch++) in follower_get_val()
140 ucontrol->value.integer.value[ch] = follower->vals[ch]; in follower_get_val()
147 int err, ch, vol; in follower_put_val() local
149 err = master_init(follower->master); in follower_put_val()
153 switch (follower->info.type) { in follower_put_val()
155 for (ch = 0; ch < follower->info.count; ch++) in follower_put_val()
156 ucontrol->value.integer.value[ch] &= in follower_put_val()
157 !!follower->master->val; in follower_put_val()
160 for (ch = 0; ch < follower->info.count; ch++) { in follower_put_val()
162 vol = ucontrol->value.integer.value[ch]; in follower_put_val()
163 vol += follower->master->val - follower->master->info.max_val; in follower_put_val()
164 if (vol < follower->info.min_val) in follower_put_val()
165 vol = follower->info.min_val; in follower_put_val()
166 else if (vol > follower->info.max_val) in follower_put_val()
167 vol = follower->info.max_val; in follower_put_val()
168 ucontrol->value.integer.value[ch] = vol; in follower_put_val()
172 return follower->follower.put(&follower->follower, ucontrol); in follower_put_val()
182 return follower->follower.info(&follower->follower, uinfo); in follower_info()
196 int err, ch, changed = 0; in follower_put() local
201 for (ch = 0; ch < follower->info.count; ch++) { in follower_put()
202 if (ucontrol->value.integer.value[ch] < follower->info.min_val || in follower_put()
203 ucontrol->value.integer.value[ch] > follower->info.max_val) in follower_put()
204 return -EINVAL; in follower_put()
207 for (ch = 0; ch < follower->info.count; ch++) { in follower_put()
208 if (follower->vals[ch] != ucontrol->value.integer.value[ch]) { in follower_put()
210 follower->vals[ch] = ucontrol->value.integer.value[ch]; in follower_put()
227 return follower->follower.tlv.c(&follower->follower, op_flag, size, tlv); in follower_tlv_cmd()
233 if (follower->follower.private_free) in follower_free()
234 follower->follower.private_free(&follower->follower); in follower_free()
235 if (follower->master) in follower_free()
236 list_del(&follower->list); in follower_free()
248 * - at most two channels
249 * - logarithmic volume control (dB level), no linear volume
250 * - master can only attenuate the volume, no gain
259 srec = kzalloc(struct_size(srec, follower.vd, follower->count), in _snd_ctl_add_follower()
262 return -ENOMEM; in _snd_ctl_add_follower()
263 srec->kctl = follower; in _snd_ctl_add_follower()
264 srec->follower = *follower; in _snd_ctl_add_follower()
265 memcpy(srec->follower.vd, follower->vd, follower->count * sizeof(*follower->vd)); in _snd_ctl_add_follower()
266 srec->master = master_link; in _snd_ctl_add_follower()
267 srec->flags = flags; in _snd_ctl_add_follower()
270 follower->info = follower_info; in _snd_ctl_add_follower()
271 follower->get = follower_get; in _snd_ctl_add_follower()
272 follower->put = follower_put; in _snd_ctl_add_follower()
273 if (follower->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) in _snd_ctl_add_follower()
274 follower->tlv.c = follower_tlv_cmd; in _snd_ctl_add_follower()
275 follower->private_data = srec; in _snd_ctl_add_follower()
276 follower->private_free = follower_free; in _snd_ctl_add_follower()
278 list_add_tail(&srec->list, &master_link->followers); in _snd_ctl_add_follower()
284 * snd_ctl_add_followers - add multiple followers to vmaster
287 * @list: NULL-terminated list of name strings of followers to be added
323 uinfo->type = master->info.type; in master_info()
324 uinfo->count = master->info.count; in master_info()
325 uinfo->value.integer.min = master->info.min_val; in master_info()
326 uinfo->value.integer.max = master->info.max_val; in master_info()
337 ucontrol->value.integer.value[0] = master->val; in master_get()
348 return -ENOMEM; in sync_followers()
349 list_for_each_entry(follower, &master->followers, list) { in sync_followers()
350 master->val = old_val; in sync_followers()
351 uval->id = follower->follower.id; in sync_followers()
353 master->val = new_val; in sync_followers()
370 old_val = master->val; in master_put()
371 new_val = ucontrol->value.integer.value[0]; in master_put()
374 if (new_val < master->info.min_val || new_val > master->info.max_val) in master_put()
375 return -EINVAL; in master_put()
380 if (master->hook && !first_init) in master_put()
381 master->hook(master->hook_private_data, master->val); in master_put()
391 list_for_each_entry_safe(follower, n, &master->followers, list) { in master_free()
392 struct snd_kcontrol *sctl = follower->kctl; in master_free()
393 struct list_head olist = sctl->list; in master_free()
394 memcpy(sctl, &follower->follower, sizeof(*sctl)); in master_free()
395 memcpy(sctl->vd, follower->follower.vd, in master_free()
396 sctl->count * sizeof(*sctl->vd)); in master_free()
397 sctl->list = olist; /* keep the current linked-list */ in master_free()
405 * snd_ctl_make_virtual_master - Create a virtual master control
436 INIT_LIST_HEAD(&master->followers); in snd_ctl_make_virtual_master()
444 kctl->info = master_info; in snd_ctl_make_virtual_master()
445 kctl->get = master_get; in snd_ctl_make_virtual_master()
446 kctl->put = master_put; in snd_ctl_make_virtual_master()
447 kctl->private_free = master_free; in snd_ctl_make_virtual_master()
455 kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; in snd_ctl_make_virtual_master()
456 memcpy(master->tlv, tlv, sizeof(master->tlv)); in snd_ctl_make_virtual_master()
457 kctl->tlv.p = master->tlv; in snd_ctl_make_virtual_master()
466 * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control
481 master->hook = hook; in snd_ctl_add_vmaster_hook()
482 master->hook_private_data = private_data; in snd_ctl_add_vmaster_hook()
488 * snd_ctl_sync_vmaster - Sync the vmaster followers and hook
509 err = sync_followers(master, master->val, master->val); in snd_ctl_sync_vmaster()
514 if (master->hook && !first_init) in snd_ctl_sync_vmaster()
515 master->hook(master->hook_private_data, master->val); in snd_ctl_sync_vmaster()
520 * snd_ctl_apply_vmaster_followers - Apply function to each vmaster follower
522 * @func: function to apply
525 * Apply the function @func to each follower kctl of the given vmaster kctl.
530 int (*func)(struct snd_kcontrol *vfollower, in snd_ctl_apply_vmaster_followers()
543 list_for_each_entry(follower, &master->followers, list) { in snd_ctl_apply_vmaster_followers()
544 err = func(follower->kctl, &follower->follower, arg); in snd_ctl_apply_vmaster_followers()