linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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);
> +
[...]


  reply	other threads:[~2014-04-01  7:47 UTC|newest]

Thread overview: 28+ 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  7:48 ` Lars-Peter Clausen [this message]
     [not found]   ` <781A12BB53C15A4BB37291FDE08C03F3A05CDCD63B@HQMAIL02.nvidia.com>
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:47           ` Lars-Peter Clausen
2014-04-02  6:56             ` Songhee Baek
2014-04-02  7:01               ` Lars-Peter Clausen
2014-04-02  7:06                 ` 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  8:27 ` Lars-Peter Clausen
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:53   ` Mark Brown
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-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).