At Fri, 29 Aug 2008 14:56:33 +0100, Liam Girdwood wrote:
On Fri, 2008-08-29 at 15:41 +0200, Takashi Iwai wrote:
At Fri, 29 Aug 2008 14:16:52 +0100, Liam Girdwood wrote:
I'd prefer an addition to our API to handle this more _common_ case rather than just removing controls.
Something where we can mark controls as "disabled" so alsamixer and friends wont render/get them. This would also allow scenario code to disable relevant mixers and then re-enable when required.
Something like below?
Takashi
diff --git a/sound/core/control.c b/sound/core/control.c index 3c5e746..c6f7062 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -410,6 +410,52 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id) EXPORT_SYMBOL(snd_ctl_remove_id);
/**
- snd_ctl_activate_id - activate/inactivate the control of the given id
- @card: the card instance
- @id: the control id to activate/inactivate
- @active: non-zero to activate
- Finds the control instance with the given id, and activate or
- inactivate the control together with notification, if changed.
- Returns 0 if unchanged, 1 if changed, or a negative error code on failure.
- */
+int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
int active)
+{
- struct snd_kcontrol *kctl;
- struct snd_kcontrol_volatile *vd;
- unsigned int index_offset;
- int ret;
- down_write(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, id);
- if (kctl == NULL) {
up_write(&card->controls_rwsem);
return -ENOENT;
- }
- index_offset = snd_ctl_get_ioff(kctl, &control->id);
- vd = &kctl->vd[index_offset];
- ret = 0;
- if (active) {
if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE))
goto unlock;
vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
- } else {
if (vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)
goto unlock;
vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
- }
- ret = 1;
- unlock:
- up_write(&card->controls_rwsem);
- if (ret)
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id);
- return ret;
+} +EXPORT_SYMBOL(snd_ctl_activate_id);
+/**
- snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it
- @file: active control handle
- @id: the control id to remove
Wow - that was quick !
Yes, exactly :) We can now add this to our machine drivers to disable never used controls (for each machine) and also call this when scenario changes too.
Even more interestingly, it could also be called by DAPM......
Good to hear that. Just let me know if you need this in the upstream. I don't want to push such an API addition too early before any use.
FWIW, below is the latest version, found in my sound-unstable tree.
thanks,
Takashi
From c4ef566498f37140bcef852109e44bea580f4bc8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai tiwai@suse.de Date: Fri, 29 Aug 2008 16:09:01 +0200 Subject: [PATCH] ALSA: Add snd_ctl_activate_id()
Added a new API function snd_ctl_activate_id() for activate / inactivate the control element dynamically.
Signed-off-by: Takashi Iwai tiwai@suse.de
diff --git a/include/sound/control.h b/include/sound/control.h index 4721b4b..6c0002a 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -114,6 +114,8 @@ int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol); int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol); int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id); int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id); +int snd_ctl_activate_id(struct snd_card * card, struct snd_ctl_elem_id *id, + int active); struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid); struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id);
diff --git a/sound/core/control.c b/sound/core/control.c index 3c5e746..c6f7062 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -410,6 +410,52 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id) EXPORT_SYMBOL(snd_ctl_remove_id);
/** + * snd_ctl_activate_id - activate/inactivate the control of the given id + * @card: the card instance + * @id: the control id to activate/inactivate + * @active: non-zero to activate + * + * Finds the control instance with the given id, and activate or + * inactivate the control together with notification, if changed. + * + * Returns 0 if unchanged, 1 if changed, or a negative error code on failure. + */ +int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, + int active) +{ + struct snd_kcontrol *kctl; + struct snd_kcontrol_volatile *vd; + unsigned int index_offset; + int ret; + + down_write(&card->controls_rwsem); + kctl = snd_ctl_find_id(card, id); + if (kctl == NULL) { + up_write(&card->controls_rwsem); + return -ENOENT; + } + index_offset = snd_ctl_get_ioff(kctl, &control->id); + vd = &kctl->vd[index_offset]; + ret = 0; + if (active) { + if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)) + goto unlock; + vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; + } else { + if (vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) + goto unlock; + vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; + } + ret = 1; + unlock: + up_write(&card->controls_rwsem); + if (ret) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id); + return ret; +} +EXPORT_SYMBOL(snd_ctl_activate_id); + +/** * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it * @file: active control handle * @id: the control id to remove