From: Lars-Peter Clausen <lars@metafoo.de>
To: Arun Shamanna Lakshmi <aruns@nvidia.com>
Cc: lgirdwood@gmail.com, broonie@kernel.org, swarren@wwwdotorg.org,
perex@perex.cz, tiwai@suse.de, alsa-devel@alsa-project.org,
linux-kernel@vger.kernel.org, Songhee Baek <sbaek@nvidia.com>
Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux
Date: Tue, 01 Apr 2014 09:48:26 +0200 [thread overview]
Message-ID: <533A6F4A.2060702@metafoo.de> (raw)
In-Reply-To: <1396333288-19113-1-git-send-email-aruns@nvidia.com>
On 04/01/2014 08:21 AM, Arun Shamanna Lakshmi wrote:
> Modify soc_enum struct to handle pointers for reg and mask. Add
> dapm get and put APIs for multi register mux with one hot encoding.
>
> Signed-off-by: Arun Shamanna Lakshmi <aruns@nvidia.com>
> Signed-off-by: Songhee Baek <sbaek@nvidia.com>
Looks in my opinion much better than the previous version :) Just a few
minor issues, comments inline
> ---
> include/sound/soc-dapm.h | 10 ++++
> include/sound/soc.h | 22 +++++--
> sound/soc/soc-core.c | 12 ++--
> sound/soc/soc-dapm.c | 143 +++++++++++++++++++++++++++++++++++++++++-----
> 4 files changed, 162 insertions(+), 25 deletions(-)
>
> diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
> index ef78f56..983b0ab 100644
> --- a/include/sound/soc-dapm.h
> +++ b/include/sound/soc-dapm.h
> @@ -305,6 +305,12 @@ struct device;
> .get = snd_soc_dapm_get_enum_double, \
> .put = snd_soc_dapm_put_enum_double, \
> .private_value = (unsigned long)&xenum }
> +#define SOC_DAPM_ENUM_WIDE(xname, xenum) \
maybe just call it ENUM_ONEHOT, since it doesn't actually have to be more
than one register.
[...]
> diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
> index cd52d52..aba0094 100644
> --- a/sound/soc/soc-core.c
> +++ b/sound/soc/soc-core.c
> @@ -2601,12 +2601,12 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
> unsigned int val, item;
> unsigned int reg_val;
>
> - reg_val = snd_soc_read(codec, e->reg);
> - val = (reg_val >> e->shift_l) & e->mask;
> + reg_val = snd_soc_read(codec, e->reg[0]);
> + val = (reg_val >> e->shift_l) & e->mask[0];
> item = snd_soc_enum_val_to_item(e, val);
> ucontrol->value.enumerated.item[0] = item;
> if (e->shift_l != e->shift_r) {
> - val = (reg_val >> e->shift_l) & e->mask;
> + val = (reg_val >> e->shift_l) & e->mask[0];
> item = snd_soc_enum_val_to_item(e, val);
> ucontrol->value.enumerated.item[1] = item;
> }
> @@ -2636,15 +2636,15 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
> if (item[0] >= e->items)
> return -EINVAL;
> val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
> - mask = e->mask << e->shift_l;
> + mask = e->mask[0] << e->shift_l;
> if (e->shift_l != e->shift_r) {
> if (item[1] >= e->items)
> return -EINVAL;
> val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;
> - mask |= e->mask << e->shift_r;
> + mask |= e->mask[0] << e->shift_r;
> }
>
> - return snd_soc_update_bits_locked(codec, e->reg, mask, val);
> + return snd_soc_update_bits_locked(codec, e->reg[0], mask, val);
> }
> EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
>
> diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
> index c8a780d..4d2b35c 100644
> --- a/sound/soc/soc-dapm.c
> +++ b/sound/soc/soc-dapm.c
> @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
> unsigned int val, item;
> int i;
>
> - if (e->reg != SND_SOC_NOPM) {
> - soc_widget_read(dest, e->reg, &val);
> - val = (val >> e->shift_l) & e->mask;
> + if (e->reg[0] != SND_SOC_NOPM) {
> + soc_widget_read(dest, e->reg[0], &val);
> + val = (val >> e->shift_l) & e->mask[0];
> item = snd_soc_enum_val_to_item(e, val);
This probably should handle the new enum type as well. You'll probably need
some kind of flag in the struct to distinguish between the two enum types.
> } else {
> /* since a virtual mux has no backing registers to
[...]
> /**
> + * snd_soc_dapm_get_enum_wide - dapm semi enumerated multiple registers
What's a semi-enumerated register?
> + * mixer get callback
> + * @kcontrol: mixer control
> + * @ucontrol: control element information
> + *
> + * Callback to get the value of a dapm semi enumerated multiple register mixer
> + * control.
> + *
> + * semi enumerated multiple registers mixer:
> + * the mixer has multiple registers to set the enumerated items. The enumerated
> + * items are referred as values.
> + * Can be used for handling bit field coded enumeration for example.
> + *
> + * Returns 0 for success.
> + */
> +int snd_soc_dapm_get_enum_wide(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
> + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
> + unsigned int reg_val, val, bit_pos = 0, reg_idx;
> +
> + for (reg_idx = 0; reg_idx < e->num_regs; reg_idx++) {
> + reg_val = snd_soc_read(codec, e->reg[reg_idx]);
> + val = reg_val & e->mask[reg_idx];
> + if (val != 0) {
> + bit_pos = ffs(val) + (e->reg_width * reg_idx);
Should be __ffs. __ffs returns the bits zero-indexed and ffs one-indexed.
That will work better for cases where there is not additional value table
necessary, since it means bit 1 maps to value 0.
> + break;
> + }
> + }
> +
> + ucontrol->value.enumerated.item[0] =
> + snd_soc_enum_val_to_item(e, bit_pos);
> +
> + return 0;
> +}
[...]
> +int snd_soc_dapm_put_enum_wide(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
> + struct snd_soc_card *card = codec->card;
> + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
> + unsigned int *item = ucontrol->value.enumerated.item;
> + unsigned int change = 0, reg_idx = 0, value, bit_pos;
> + struct snd_soc_dapm_update update;
> + int ret = 0, reg_val = 0, i;
> +
> + if (item[0] >= e->items)
> + return -EINVAL;
> +
> + value = snd_soc_enum_item_to_val(e, item[0]);
> +
> + if (value) {
> + /* get the register index and value to set */
> + reg_idx = (value - 1) / e->reg_width;
> + bit_pos = (value - 1) % e->reg_width;
Changing the ffs to __ffs also means you can drop the ' - 1' here.
Also e->reg_width should be (codec->val_bytes * 8) and reg_width field
should be dropped from the enum struct.
> + reg_val = BIT(bit_pos);
> + }
> +
> + for (i = 0; i < e->num_regs; i++) {
> + if (i == reg_idx) {
> + change = snd_soc_test_bits(codec, e->reg[i],
> + e->mask[i], reg_val);
> +
> + } else {
> + /* accumulate the change to update the DAPM path
> + when none is selected */
> + change += snd_soc_test_bits(codec, e->reg[i],
> + e->mask[i], 0);
change |=
> +
> + /* clear the register when not selected */
> + snd_soc_write(codec, e->reg[i], 0);
I think this should happen as part of the DAPM update sequence like you had
earlier. Some special care should probably be take to make sure that you
de-select the previous mux input before selecting the new one if the new one
is in a different register than the previous one.
> + }
> + }
> +
> + mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
> +
[...]
next prev parent reply other threads:[~2014-04-01 7:48 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-01 6:21 [PATCH] ASoC: DAPM: Add support for multi register mux Arun Shamanna Lakshmi
2014-04-01 6:21 ` Arun Shamanna Lakshmi
2014-04-01 7:48 ` Lars-Peter Clausen [this message]
[not found] ` <781A12BB53C15A4BB37291FDE08C03F3A05CDCD63B@HQMAIL02.nvidia.com>
2014-04-01 18:26 ` Arun Shamanna Lakshmi
2014-04-01 18:26 ` Arun Shamanna Lakshmi
2014-04-02 6:00 ` Lars-Peter Clausen
2014-04-02 6:17 ` Songhee Baek
2014-04-02 6:17 ` Songhee Baek
2014-04-02 6:47 ` Lars-Peter Clausen
2014-04-02 6:47 ` Lars-Peter Clausen
2014-04-02 6:56 ` Songhee Baek
2014-04-02 7:01 ` Lars-Peter Clausen
2014-04-02 7:01 ` Lars-Peter Clausen
2014-04-02 7:06 ` Songhee Baek
2014-04-02 7:06 ` Songhee Baek
2014-04-02 15:26 ` Songhee Baek
2014-04-02 15:26 ` Songhee Baek
2014-04-02 15:29 ` Lars-Peter Clausen
-- strict thread matches above, loose matches on Subject: below --
2014-04-03 3:11 [PATCH] ASoC: dapm: " Arun Shamanna Lakshmi
2014-04-03 3:11 ` Arun Shamanna Lakshmi
2014-04-03 8:27 ` Lars-Peter Clausen
2014-04-03 8:27 ` Lars-Peter Clausen
2014-04-03 9:40 ` Mark Brown
2014-04-03 9:40 ` Mark Brown
2014-04-03 20:11 ` Arun Shamanna Lakshmi
2014-04-04 7:31 ` Lars-Peter Clausen
2014-04-04 7:34 ` Arun Shamanna Lakshmi
2014-04-04 7:40 ` Lars-Peter Clausen
2014-04-03 9:47 ` Takashi Iwai
2014-04-03 9:47 ` Takashi Iwai
2014-04-03 9:53 ` Mark Brown
2014-04-03 9:53 ` Mark Brown
2014-04-03 13:31 ` Lars-Peter Clausen
2014-04-03 13:31 ` Lars-Peter Clausen
2014-04-03 15:06 ` Takashi Iwai
2014-04-03 16:02 ` Mark Brown
2014-04-05 0:12 Arun Shamanna Lakshmi
2014-04-05 0:12 ` Arun Shamanna Lakshmi
2014-04-07 12:54 ` Lars-Peter Clausen
2014-04-07 14:24 ` Takashi Iwai
2014-04-09 15:56 ` Mark Brown
2014-04-09 20:07 ` Arun S L
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=533A6F4A.2060702@metafoo.de \
--to=lars@metafoo.de \
--cc=alsa-devel@alsa-project.org \
--cc=aruns@nvidia.com \
--cc=broonie@kernel.org \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=perex@perex.cz \
--cc=sbaek@nvidia.com \
--cc=swarren@wwwdotorg.org \
--cc=tiwai@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.