Re: [PATCH v2 01/10] ASoC: tegra: Fix kcontrol put callback in ADMAIF

Takashi Iwai
2021-11-03T14:18:48Z

On Wed, 03 Nov 2021 15:16:24 +0100,
Takashi Iwai wrote:
>
> On Wed, 03 Nov 2021 14:52:17 +0100,
> Sameer Pujar wrote:
> >
> > The kcontrol put callback is expected to return 1 when there is change
> > in HW or when the update is acknowledged by driver. This would ensure
> > that change notifications are sent to subscribed applications. Update
> > the ADMAIF driver accordingly
> >
> > Fixes: f74028e159bb ("ASoC: tegra: Add Tegra210 based ADMAIF driver")
> > Suggested-by: Jaroslav Kysela <perex@perex.cz>
> > Suggested-by: Mark Brown <broonie@kernel.org>
> > Signed-off-by: Sameer Pujar <spujar@nvidia.com>
> > ---
> > sound/soc/tegra/tegra210_admaif.c | 23 ++++++++++++++++++-----
> > 1 file changed, 18 insertions(+), 5 deletions(-)
> >
> > diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c
> > index bcccdf3..dc71075 100644
> > --- a/sound/soc/tegra/tegra210_admaif.c
> > +++ b/sound/soc/tegra/tegra210_admaif.c
> > @@ -452,16 +452,29 @@ static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol,
> > struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
> > int value = ucontrol->value.integer.value[0];
> >
> > - if (strstr(kcontrol->id.name, "Playback Mono To Stereo"))
> > + if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) {
> > + if (admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] == value)
> > + return 0;
> > +
> > admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
> > - else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))
> > + } else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) {
> > + if (admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] == value)
> > + return 0;
> > +
> > admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
> > - else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))
> > + } else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) {
> > + if (admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] == value)
> > + return 0;
> > +
> > admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
> > - else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))
> > + } else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) {
> > + if (admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] == value)
> > + return 0;
> > +
> > admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
> > + }
> >
> > - return 0;
> > + return 1;
>
> Hrm, that looks too redundant. The similar checks are seen in the get
> part, so we may have a better helper function to reduce the string
> checks, something like below.
>
>
> BTW, independent from this patch set, I noticed that those get/put
> callbacks handle the wrong type. For enum ctls, you have to use
> ucontrol->value.enumerated.value instead of
> ucontrol->value.integer.value. The former is long while the latter is
> int, hence they may have different sizes.
>
> Such a bug could be caught if you test once with
> CONFIG_SND_CTL_VALIDATION=y. It's recommended to test with that
> config once for a new driver code.
>
> So, please submit the fix patch(es) for correcting the ctl value
> types, too.
>
>
> thanks,
>
> Takashi
>
> --- a/sound/soc/tegra/tegra210_admaif.c
> +++ b/sound/soc/tegra/tegra210_admaif.c
> @@ -424,44 +424,46 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
> .trigger = tegra_admaif_trigger,
> };
>
> -static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol,
> - struct snd_ctl_elem_value *ucontrol)
> +static unsigned int *tegra_admaif_route_val(struct snd_kcontrol *kcontrol)
> {
> struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
> struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
> struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
> - long *uctl_val = &ucontrol->value.integer.value[0];
>
> if (strstr(kcontrol->id.name, "Playback Mono To Stereo"))
> - *uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
> + return &admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
> else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))
> - *uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
> + return &admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
> else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))
> - *uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
> + return &admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
> else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))
> - *uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
> + return &admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
> + return NULL;
> +}
>
> +static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + unsigned int *valp = tegra_admaif_route_val(admaif, kcontrol);

The admaif argument is superfluous here, drop it.

My patch is just for bringing an idea, and feel free to cook in your
own way, of course.

Takashi

> +
> + if (!valp)
> + return -EINVAL;
> + ucontrol->value.integer.value[0] = *valp;
> return 0;
> }
>
> static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol,
> struct snd_ctl_elem_value *ucontrol)
> {
> - struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
> - struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
> - struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
> + unsigned int *valp = tegra_admaif_route_val(admaif, kcontrol);
> int value = ucontrol->value.integer.value[0];
>
> - if (strstr(kcontrol->id.name, "Playback Mono To Stereo"))
> - admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
> - else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))
> - admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
> - else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))
> - admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
> - else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))
> - admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
> -
> - return 0;
> + if (!valp)
> + return -EINVAL;
> + if (value == *valp)
> + return 0;
> + *valp = value;
> + return 1;
> }
>
> static int tegra_admaif_dai_probe(struct snd_soc_dai *dai)
>