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@xxxxxxx> 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@xxxxxxx> 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 _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel