[PATCH v2 00/10] Fix kcontrol put callback in Tegra drivers
This series fixes kcontrol put callback in some of the Tegra drivers which are used on platforms based on Tegra210 and later. The callback is expected to return 1 whenever the HW update is done.
This idea is suggested by Jaroslav. Similar suggestion came from Mark during review of series [0] and drivers under this were updated to return 1, but missed to take care of duplicate updates. This series updates all concerned drivers to return proper values and duplicate updates are filtered out. I have added 'Suggested-by" tags accordingly.
[0] https://lore.kernel.org/linux-arm-kernel/20210913142307.GF4283@sirena.org.uk...
Changelog ========= v1->v2: ------- * ADMAIF, I2S, DMIC and DSPK drivers updated to take care of duplicate updates. * Similarly new patches are added for AHUB, MVC, SFC, AMX, ADX and Mixer drivers.
Sameer Pujar (10): ASoC: tegra: Fix kcontrol put callback in ADMAIF ASoC: tegra: Fix kcontrol put callback in I2S ASoC: tegra: Fix kcontrol put callback in DMIC ASoC: tegra: Fix kcontrol put callback in DSPK ASoC: tegra: Fix kcontrol put callback in AHUB ASoC: tegra: Fix kcontrol put callback in MVC ASoC: tegra: Fix kcontrol put callback in SFC ASoC: tegra: Fix kcontrol put callback in AMX ASoC: tegra: Fix kcontrol put callback in ADX ASoC: tegra: Fix kcontrol put callback in Mixer
sound/soc/tegra/tegra186_dspk.c | 33 ++++++++++++++++++++++++++------- sound/soc/tegra/tegra210_admaif.c | 23 ++++++++++++++++++----- sound/soc/tegra/tegra210_adx.c | 3 +++ sound/soc/tegra/tegra210_ahub.c | 11 +++++++---- sound/soc/tegra/tegra210_amx.c | 3 +++ sound/soc/tegra/tegra210_dmic.c | 35 +++++++++++++++++++++++++++-------- sound/soc/tegra/tegra210_i2s.c | 26 +++++++++++++++++++++++++- sound/soc/tegra/tegra210_mixer.c | 3 +++ sound/soc/tegra/tegra210_mvc.c | 18 ++++++++++++++++-- sound/soc/tegra/tegra210_sfc.c | 23 +++++++++++++++++------ 10 files changed, 145 insertions(+), 33 deletions(-)
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; }
static int tegra_admaif_dai_probe(struct snd_soc_dai *dai)
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); + + 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)
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];
else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))return &admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
*uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))return &admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
*uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))return &admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
*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)
On 03. 11. 21 15:16, 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.
While proposing such cleanups, I would create separate get/put callbacks for all four ops instead using strstr(). The callbacks may put the common code to one function. It may reduce the code size (and the text segment size).
Jaroslav
On 11/3/2021 10:55 PM, Jaroslav Kysela wrote:
On 03. 11. 21 15:16, 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.
Thanks Takashi for your inputs. This would make the get/put callbacks simpler. But in some cases, for few controls additional handling is required (tegra210_i2s.c driver for example). In such cases additional checks would be required if the callback is common.
While proposing such cleanups, I would create separate get/put callbacks for all four ops instead using strstr(). The callbacks may put the common code to one function. It may reduce the code size (and the text segment size).
With separate callbacks, the string checks can be removed. However for most of the controls, the common part is minimal. So there would be multiple independent small functions depending on the number of controls and the local variables are duplicated that many times. Would there be any concern on the space these local variables take? One pair of callbacks for a control may look like this.
static int kctl_pget_mono_to_stereo(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);
ucontrol->value.integer.value[0] = admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
return 0; }
static int kctl_pput_mono_to_stereo(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); int value = ucontrol->value.integer.value[0];
if (value == admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]) return 0;
admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
return 1; }
Looks like having separate callbacks make it look more cleaner. If this appears fine, I can send next revision.
On Mon, Nov 08, 2021 at 09:33:25PM +0530, Sameer Pujar wrote:
With separate callbacks, the string checks can be removed. However for most of the controls, the common part is minimal. So there would be multiple independent small functions depending on the number of controls and the local variables are duplicated that many times. Would there be any concern on the space these local variables take? One pair of callbacks for a control may look like this.
...
Looks like having separate callbacks make it look more cleaner. If this appears fine, I can send next revision.
Looks fine. It'll result in more code but hopefully they should be smaller, especially if you're using substrings rather than the full control name to identify the control and we need to store all them separately to the copy used to identify the control to userspace (I didn't go check).
On 11/3/2021 7:46 PM, Takashi Iwai wrote:
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 for suggesting. I will include fixes for this as well in current series.
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 I2S driver accordingly.
Fixes: c0bfa98349d1 ("ASoC: tegra: Add Tegra210 based I2S 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_i2s.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c index 45f31cc..70505b5 100644 --- a/sound/soc/tegra/tegra210_i2s.c +++ b/sound/soc/tegra/tegra210_i2s.c @@ -347,6 +347,9 @@ static int tegra210_i2s_put_control(struct snd_kcontrol *kcontrol, int value = ucontrol->value.integer.value[0];
if (strstr(kcontrol->id.name, "Loopback")) { + if (i2s->loopback == value) + return 0; + i2s->loopback = value;
regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, @@ -362,6 +365,9 @@ static int tegra210_i2s_put_control(struct snd_kcontrol *kcontrol, * cases mixer control is used to update custom values. A value * of "N" here means, width is "N + 1" bit clock wide. */ + if (i2s->fsync_width == value) + return 0; + i2s->fsync_width = value;
regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, @@ -369,20 +375,38 @@ static int tegra210_i2s_put_control(struct snd_kcontrol *kcontrol, i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT);
} else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) { + if (i2s->stereo_to_mono[I2S_TX_PATH] == value) + return 0; + i2s->stereo_to_mono[I2S_TX_PATH] = value; } else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) { + if (i2s->mono_to_stereo[I2S_TX_PATH] == value) + return 0; + i2s->mono_to_stereo[I2S_TX_PATH] = value; } else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) { + if (i2s->stereo_to_mono[I2S_RX_PATH] == value) + return 0; + i2s->stereo_to_mono[I2S_RX_PATH] = value; } else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) { + if (i2s->mono_to_stereo[I2S_RX_PATH] == value) + return 0; + i2s->mono_to_stereo[I2S_RX_PATH] = value; } else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) { + if (i2s->rx_fifo_th == value) + return 0; + i2s->rx_fifo_th = value; } else if (strstr(kcontrol->id.name, "BCLK Ratio")) { + if (i2s->bclk_ratio == value) + return 0; + i2s->bclk_ratio = value; }
- return 0; + return 1; }
static int tegra210_i2s_set_timing_params(struct device *dev,
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 DMIC driver accordingly.
Fixes: 8c8ff982e9e2 ("ASoC: tegra: Add Tegra210 based DMIC 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_dmic.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c index b096478..39a63ed 100644 --- a/sound/soc/tegra/tegra210_dmic.c +++ b/sound/soc/tegra/tegra210_dmic.c @@ -185,20 +185,39 @@ static int tegra210_dmic_put_control(struct snd_kcontrol *kcontrol, struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); int value = ucontrol->value.integer.value[0];
- if (strstr(kcontrol->id.name, "Boost Gain Volume")) + if (strstr(kcontrol->id.name, "Boost Gain Volume")) { + if (dmic->boost_gain == value) + return 0; + dmic->boost_gain = value; - else if (strstr(kcontrol->id.name, "Channel Select")) - dmic->ch_select = ucontrol->value.integer.value[0]; - else if (strstr(kcontrol->id.name, "Mono To Stereo")) + } else if (strstr(kcontrol->id.name, "Channel Select")) { + if (dmic->ch_select == value) + return 0; + + dmic->ch_select = value; + } else if (strstr(kcontrol->id.name, "Mono To Stereo")) { + if (dmic->mono_to_stereo == value) + return 0; + dmic->mono_to_stereo = value; - else if (strstr(kcontrol->id.name, "Stereo To Mono")) + } else if (strstr(kcontrol->id.name, "Stereo To Mono")) { + if (dmic->stereo_to_mono == value) + return 0; + dmic->stereo_to_mono = value; - else if (strstr(kcontrol->id.name, "OSR Value")) + } else if (strstr(kcontrol->id.name, "OSR Value")) { + if (dmic->osr_val == value) + return 0; + dmic->osr_val = value; - else if (strstr(kcontrol->id.name, "LR Polarity Select")) + } else if (strstr(kcontrol->id.name, "LR Polarity Select")) { + if (dmic->lrsel == value) + return 0; + dmic->lrsel = value; + }
- return 0; + return 1; }
static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = {
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 DSPK driver accordingly.
Fixes: 327ef6470266 ("ASoC: tegra: Add Tegra186 based DSPK 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/tegra186_dspk.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c index 8ee9a77..4cc06e9 100644 --- a/sound/soc/tegra/tegra186_dspk.c +++ b/sound/soc/tegra/tegra186_dspk.c @@ -55,20 +55,39 @@ static int tegra186_dspk_put_control(struct snd_kcontrol *kcontrol, struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); int val = ucontrol->value.integer.value[0];
- if (strstr(kcontrol->id.name, "FIFO Threshold")) + if (strstr(kcontrol->id.name, "FIFO Threshold")) { + if (dspk->rx_fifo_th == val) + return 0; + dspk->rx_fifo_th = val; - else if (strstr(kcontrol->id.name, "OSR Value")) + } else if (strstr(kcontrol->id.name, "OSR Value")) { + if (dspk->osr_val == val) + return 0; + dspk->osr_val = val; - else if (strstr(kcontrol->id.name, "LR Polarity Select")) + } else if (strstr(kcontrol->id.name, "LR Polarity Select")) { + if (dspk->lrsel == val) + return 0; + dspk->lrsel = val; - else if (strstr(kcontrol->id.name, "Channel Select")) + } else if (strstr(kcontrol->id.name, "Channel Select")) { + if (dspk->ch_sel == val) + return 0; + dspk->ch_sel = val; - else if (strstr(kcontrol->id.name, "Mono To Stereo")) + } else if (strstr(kcontrol->id.name, "Mono To Stereo")) { + if (dspk->mono_to_stereo == val) + return 0; + dspk->mono_to_stereo = val; - else if (strstr(kcontrol->id.name, "Stereo To Mono")) + } else if (strstr(kcontrol->id.name, "Stereo To Mono")) { + if (dspk->stereo_to_mono == val) + return 0; + dspk->stereo_to_mono = val; + }
- return 0; + return 1; }
static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev)
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 AHUB driver accordingly.
Fixes: 16e1bcc2caf4 ("ASoC: tegra: Add Tegra210 based AHUB driver") Signed-off-by: Sameer Pujar spujar@nvidia.com Suggested-by: Jaroslav Kysela perex@perex.cz Suggested-by: Mark Brown broonie@kernel.org --- sound/soc/tegra/tegra210_ahub.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c index a1989ea..388b815 100644 --- a/sound/soc/tegra/tegra210_ahub.c +++ b/sound/soc/tegra/tegra210_ahub.c @@ -62,6 +62,7 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl, unsigned int *item = uctl->value.enumerated.item; unsigned int value = e->values[item[0]]; unsigned int i, bit_pos, reg_idx = 0, reg_val = 0; + int change = 0;
if (item[0] >= e->items) return -EINVAL; @@ -86,12 +87,14 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl,
/* Update widget power if state has changed */ if (snd_soc_component_test_bits(cmpnt, update[i].reg, - update[i].mask, update[i].val)) - snd_soc_dapm_mux_update_power(dapm, kctl, item[0], e, - &update[i]); + update[i].mask, + update[i].val)) + change |= snd_soc_dapm_mux_update_power(dapm, kctl, + item[0], e, + &update[i]); }
- return 0; + return change; }
static struct snd_soc_dai_driver tegra210_ahub_dais[] = {
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. Filter out duplicate updates in MVC driver.
Fixes: e539891f9687 ("ASoC: tegra: Add Tegra210 based MVC driver") Signed-off-by: Sameer Pujar spujar@nvidia.com Suggested-by: Jaroslav Kysela perex@perex.cz Suggested-by: Mark Brown broonie@kernel.org --- sound/soc/tegra/tegra210_mvc.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/sound/soc/tegra/tegra210_mvc.c b/sound/soc/tegra/tegra210_mvc.c index 7b9c700..380686c 100644 --- a/sound/soc/tegra/tegra210_mvc.c +++ b/sound/soc/tegra/tegra210_mvc.c @@ -136,7 +136,7 @@ static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol, struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); unsigned int value; - u8 mute_mask; + u8 mute_mask, old_mask; int err;
pm_runtime_get_sync(cmpnt->dev); @@ -148,8 +148,16 @@ static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol, if (err < 0) goto end;
+ regmap_read(mvc->regmap, TEGRA210_MVC_CTRL, &value); + + old_mask = (value >> TEGRA210_MVC_MUTE_SHIFT) & TEGRA210_MUTE_MASK_EN; mute_mask = ucontrol->value.integer.value[0];
+ if (mute_mask == old_mask) { + err = 0; + goto end; + } + err = regmap_update_bits(mvc->regmap, mc->reg, TEGRA210_MVC_MUTE_MASK, mute_mask << TEGRA210_MVC_MUTE_SHIFT); @@ -195,7 +203,7 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol, unsigned int reg = mc->reg; unsigned int value; u8 chan; - int err; + int err, old_volume;
pm_runtime_get_sync(cmpnt->dev);
@@ -207,10 +215,16 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol, goto end;
chan = (reg - TEGRA210_MVC_TARGET_VOL) / REG_SIZE; + old_volume = mvc->volume[chan];
tegra210_mvc_conv_vol(mvc, chan, ucontrol->value.integer.value[0]);
+ if (mvc->volume[chan] == old_volume) { + err = 0; + goto end; + } + /* Configure init volume same as target volume */ regmap_write(mvc->regmap, TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_INIT_VOL, chan),
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. Filter out duplicate updates in SFC driver.
Fixes: b2f74ec53a6c ("ASoC: tegra: Add Tegra210 based SFC driver") Signed-off-by: Sameer Pujar spujar@nvidia.com Suggested-by: Jaroslav Kysela perex@perex.cz Suggested-by: Mark Brown broonie@kernel.org --- sound/soc/tegra/tegra210_sfc.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/sound/soc/tegra/tegra210_sfc.c b/sound/soc/tegra/tegra210_sfc.c index dc477ee..ac24980 100644 --- a/sound/soc/tegra/tegra210_sfc.c +++ b/sound/soc/tegra/tegra210_sfc.c @@ -3273,16 +3273,27 @@ static int tegra210_sfc_put_control(struct snd_kcontrol *kcontrol, struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt); int value = ucontrol->value.integer.value[0];
- if (strstr(kcontrol->id.name, "Input Stereo To Mono")) + if (strstr(kcontrol->id.name, "Input Stereo To Mono")) { + if (sfc->stereo_to_mono[SFC_RX_PATH] == value) + return 0; + sfc->stereo_to_mono[SFC_RX_PATH] = value; - else if (strstr(kcontrol->id.name, "Input Mono To Stereo")) + } else if (strstr(kcontrol->id.name, "Input Mono To Stereo")) { + if (sfc->mono_to_stereo[SFC_RX_PATH] == value) + return 0; + sfc->mono_to_stereo[SFC_RX_PATH] = value; - else if (strstr(kcontrol->id.name, "Output Stereo To Mono")) + } else if (strstr(kcontrol->id.name, "Output Stereo To Mono")) { + if (sfc->stereo_to_mono[SFC_TX_PATH] == value) + return 0; + sfc->stereo_to_mono[SFC_TX_PATH] = value; - else if (strstr(kcontrol->id.name, "Output Mono To Stereo")) + } else if (strstr(kcontrol->id.name, "Output Mono To Stereo")) { + if (sfc->mono_to_stereo[SFC_TX_PATH] == value) + return 0; + sfc->mono_to_stereo[SFC_TX_PATH] = value; - else - return 0; + }
return 1; }
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. Filter out duplicate updates in AMX driver.
Fixes: 77f7df346c45 ("ASoC: tegra: Add Tegra210 based AMX driver") Signed-off-by: Sameer Pujar spujar@nvidia.com Suggested-by: Jaroslav Kysela perex@perex.cz Suggested-by: Mark Brown broonie@kernel.org --- sound/soc/tegra/tegra210_amx.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/tegra/tegra210_amx.c b/sound/soc/tegra/tegra210_amx.c index af9bddf..6895763 100644 --- a/sound/soc/tegra/tegra210_amx.c +++ b/sound/soc/tegra/tegra210_amx.c @@ -222,6 +222,9 @@ static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol, int reg = mc->reg; int value = ucontrol->value.integer.value[0];
+ if (value == bytes_map[reg]) + return 0; + if (value >= 0 && value <= 255) { /* Update byte map and enable slot */ bytes_map[reg] = value;
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. Filter out duplicate updates in ADX driver.
Fixes: a99ab6f395a9 ("ASoC: tegra: Add Tegra210 based ADX driver") Signed-off-by: Sameer Pujar spujar@nvidia.com Suggested-by: Jaroslav Kysela perex@perex.cz Suggested-by: Mark Brown broonie@kernel.org --- sound/soc/tegra/tegra210_adx.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c index d7c7849..933c450 100644 --- a/sound/soc/tegra/tegra210_adx.c +++ b/sound/soc/tegra/tegra210_adx.c @@ -193,6 +193,9 @@ static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value;;
+ if (value == bytes_map[mc->reg]) + return 0; + if (value >= 0 && value <= 255) { /* update byte map and enable slot */ bytes_map[mc->reg] = value;
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. Filter out duplicate updates in Mixer driver.
Fixes: 05bb3d5ec64a ("ASoC: tegra: Add Tegra210 based Mixer driver") Signed-off-by: Sameer Pujar spujar@nvidia.com Suggested-by: Jaroslav Kysela perex@perex.cz Suggested-by: Mark Brown broonie@kernel.org --- sound/soc/tegra/tegra210_mixer.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/tegra/tegra210_mixer.c b/sound/soc/tegra/tegra210_mixer.c index 55e6177..d2d1946 100644 --- a/sound/soc/tegra/tegra210_mixer.c +++ b/sound/soc/tegra/tegra210_mixer.c @@ -210,6 +210,9 @@ static int tegra210_mixer_put_gain(struct snd_kcontrol *kcontrol, id = (reg - TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_0) / TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_STRIDE;
+ if (mixer->gain_value[id] == ucontrol->value.integer.value[0]) + return 0; + mixer->gain_value[id] = ucontrol->value.integer.value[0];
err = tegra210_mixer_configure_gain(cmpnt, id, instant_gain);
participants (4)
-
Jaroslav Kysela
-
Mark Brown
-
Sameer Pujar
-
Takashi Iwai