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

Takashi Iwai tiwai at suse.de
Wed Nov 3 15:16:24 CET 2021


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 at perex.cz>
> Suggested-by: Mark Brown <broonie at kernel.org>
> Signed-off-by: Sameer Pujar <spujar at 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);
+
+	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)


More information about the Alsa-devel mailing list