| From e2b87a18a60c02d0dcd1de801d669587e516cc4d Mon Sep 17 00:00:00 2001 |
| From: Sameer Pujar <spujar@nvidia.com> |
| Date: Thu, 18 Nov 2021 12:37:02 +0530 |
| Subject: ASoC: tegra: Fix kcontrol put callback in ADMAIF |
| |
| From: Sameer Pujar <spujar@nvidia.com> |
| |
| commit e2b87a18a60c02d0dcd1de801d669587e516cc4d upstream. |
| |
| 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> |
| Reviewed-by: Takashi Iwai <tiwai@suse.de> |
| Link: https://lore.kernel.org/r/1637219231-406-8-git-send-email-spujar@nvidia.com |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| sound/soc/tegra/tegra210_admaif.c | 138 ++++++++++++++++++++++++++++++-------- |
| 1 file changed, 109 insertions(+), 29 deletions(-) |
| |
| --- a/sound/soc/tegra/tegra210_admaif.c |
| +++ b/sound/soc/tegra/tegra210_admaif.c |
| @@ -424,46 +424,122 @@ static const struct snd_soc_dai_ops tegr |
| .trigger = tegra_admaif_trigger, |
| }; |
| |
| -static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol, |
| - struct snd_ctl_elem_value *ucontrol) |
| +static int tegra210_admaif_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 tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); |
| struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; |
| + |
| + ucontrol->value.enumerated.item[0] = |
| + admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]; |
| + |
| + return 0; |
| +} |
| + |
| +static int tegra210_admaif_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 tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); |
| - unsigned int *uctl_val = &ucontrol->value.enumerated.item[0]; |
| + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; |
| + unsigned int value = ucontrol->value.enumerated.item[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")) |
| - *uctl_val = 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]; |
| - else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) |
| - *uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]; |
| + 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; |
| +} |
| + |
| +static int tegra210_admaif_cget_mono_to_stereo(struct snd_kcontrol *kcontrol, |
| + struct snd_ctl_elem_value *ucontrol) |
| +{ |
| + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); |
| + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; |
| + |
| + ucontrol->value.enumerated.item[0] = |
| + admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]; |
| |
| return 0; |
| } |
| |
| -static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol, |
| - struct snd_ctl_elem_value *ucontrol) |
| +static int tegra210_admaif_cput_mono_to_stereo(struct snd_kcontrol *kcontrol, |
| + struct snd_ctl_elem_value *ucontrol) |
| { |
| struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); |
| struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; |
| + unsigned int value = ucontrol->value.enumerated.item[0]; |
| + |
| + if (value == admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]) |
| + return 0; |
| + |
| + admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value; |
| + |
| + return 1; |
| +} |
| + |
| +static int tegra210_admaif_pget_stereo_to_mono(struct snd_kcontrol *kcontrol, |
| + struct snd_ctl_elem_value *ucontrol) |
| +{ |
| + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); |
| + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; |
| + |
| + ucontrol->value.enumerated.item[0] = |
| + admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]; |
| + |
| + return 0; |
| +} |
| + |
| +static int tegra210_admaif_pput_stereo_to_mono(struct snd_kcontrol *kcontrol, |
| + struct snd_ctl_elem_value *ucontrol) |
| +{ |
| + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); |
| + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; |
| unsigned int value = ucontrol->value.enumerated.item[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; |
| + if (value == admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]) |
| + return 0; |
| + |
| + admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value; |
| + |
| + return 1; |
| +} |
| + |
| +static int tegra210_admaif_cget_stereo_to_mono(struct snd_kcontrol *kcontrol, |
| + struct snd_ctl_elem_value *ucontrol) |
| +{ |
| + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); |
| + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; |
| + |
| + ucontrol->value.enumerated.item[0] = |
| + admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]; |
| |
| return 0; |
| } |
| |
| +static int tegra210_admaif_cput_stereo_to_mono(struct snd_kcontrol *kcontrol, |
| + struct snd_ctl_elem_value *ucontrol) |
| +{ |
| + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); |
| + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; |
| + unsigned int value = ucontrol->value.enumerated.item[0]; |
| + |
| + if (value == admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]) |
| + return 0; |
| + |
| + admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value; |
| + |
| + return 1; |
| +} |
| + |
| static int tegra_admaif_dai_probe(struct snd_soc_dai *dai) |
| { |
| struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); |
| @@ -559,17 +635,21 @@ static const char * const tegra_admaif_m |
| } |
| |
| #define TEGRA_ADMAIF_CIF_CTRL(reg) \ |
| - NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,\ |
| - tegra_admaif_get_control, tegra_admaif_put_control, \ |
| + NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1, \ |
| + tegra210_admaif_pget_mono_to_stereo, \ |
| + tegra210_admaif_pput_mono_to_stereo, \ |
| tegra_admaif_mono_conv_text), \ |
| - NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,\ |
| - tegra_admaif_get_control, tegra_admaif_put_control, \ |
| + NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1, \ |
| + tegra210_admaif_pget_stereo_to_mono, \ |
| + tegra210_admaif_pput_stereo_to_mono, \ |
| tegra_admaif_stereo_conv_text), \ |
| - NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ |
| - tegra_admaif_get_control, tegra_admaif_put_control, \ |
| + NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ |
| + tegra210_admaif_cget_mono_to_stereo, \ |
| + tegra210_admaif_cput_mono_to_stereo, \ |
| tegra_admaif_mono_conv_text), \ |
| - NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ |
| - tegra_admaif_get_control, tegra_admaif_put_control, \ |
| + NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ |
| + tegra210_admaif_cget_stereo_to_mono, \ |
| + tegra210_admaif_cput_stereo_to_mono, \ |
| tegra_admaif_stereo_conv_text) |
| |
| static struct snd_kcontrol_new tegra210_admaif_controls[] = { |