aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/control.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/control.c')
-rw-r--r--sound/core/control.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/sound/core/control.c b/sound/core/control.c
index a08ad57c49b6..5d98194bcad5 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -366,6 +366,70 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
366EXPORT_SYMBOL(snd_ctl_add); 366EXPORT_SYMBOL(snd_ctl_add);
367 367
368/** 368/**
369 * snd_ctl_replace - replace the control instance of the card
370 * @card: the card instance
371 * @kcontrol: the control instance to replace
372 * @add_on_replace: add the control if not already added
373 *
374 * Replaces the given control. If the given control does not exist
375 * and the add_on_replace flag is set, the control is added. If the
376 * control exists, it is destroyed first.
377 *
378 * Returns zero if successful, or a negative error code on failure.
379 *
380 * It frees automatically the control which cannot be added or replaced.
381 */
382int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
383 bool add_on_replace)
384{
385 struct snd_ctl_elem_id id;
386 unsigned int idx;
387 struct snd_kcontrol *old;
388 int ret;
389
390 if (!kcontrol)
391 return -EINVAL;
392 if (snd_BUG_ON(!card || !kcontrol->info)) {
393 ret = -EINVAL;
394 goto error;
395 }
396 id = kcontrol->id;
397 down_write(&card->controls_rwsem);
398 old = snd_ctl_find_id(card, &id);
399 if (!old) {
400 if (add_on_replace)
401 goto add;
402 up_write(&card->controls_rwsem);
403 ret = -EINVAL;
404 goto error;
405 }
406 ret = snd_ctl_remove(card, old);
407 if (ret < 0) {
408 up_write(&card->controls_rwsem);
409 goto error;
410 }
411add:
412 if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
413 up_write(&card->controls_rwsem);
414 ret = -ENOMEM;
415 goto error;
416 }
417 list_add_tail(&kcontrol->list, &card->controls);
418 card->controls_count += kcontrol->count;
419 kcontrol->id.numid = card->last_numid + 1;
420 card->last_numid += kcontrol->count;
421 up_write(&card->controls_rwsem);
422 for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
423 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
424 return 0;
425
426error:
427 snd_ctl_free_one(kcontrol);
428 return ret;
429}
430EXPORT_SYMBOL(snd_ctl_replace);
431
432/**
369 * snd_ctl_remove - remove the control from the card and release it 433 * snd_ctl_remove - remove the control from the card and release it
370 * @card: the card instance 434 * @card: the card instance
371 * @kcontrol: the control instance to remove 435 * @kcontrol: the control instance to remove