ASoC: tegra-alt: Fix MVC gain issues

The Applied gain in dB never reflected in the output data with
the current driver code. There was few issues related to the
way we program the sequences. As a first step cleaning up the
driver to make sure the applied gain is proper in the output and
bitmatch works with multiple runs.

- Do MVC soft reset to clear the state in the hw_params before
processing the input data.
- Assign the init volume and target volume to the same value at
start of processing.
- Trigger the switch only after programming all the registers related
to Volume, duration and polynomial coefficients.

Bug 200532059

Change-Id: I2c77bd225284f31892ed8c2ff7c228dd19f8c63e
Signed-off-by: Mohan Kumar <mkumard@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2170333
(cherry picked from commit 6f56c3df3f2f6a55e33d9071cb5d05d0992a6b28)
Reviewed-on: https://git-master.nvidia.com/r/2173817
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Mohan Kumar
2019-08-08 00:11:29 +05:30
committed by Sameer Pujar
parent a4c55519f8
commit 919e8b00bd

View File

@@ -75,6 +75,24 @@ static int tegra210_mvc_runtime_resume(struct device *dev)
return 0; return 0;
} }
static int tegra210_mvc_soft_reset(struct tegra210_mvc *mvc)
{
int value;
int dcnt = 10;
/* issue soft reset */
regmap_write(mvc->regmap, TEGRA210_MVC_SOFT_RESET, 1);
/* wait for soft reset bit to clear */
do {
udelay(10);
regmap_read(mvc->regmap, TEGRA210_MVC_SOFT_RESET, &value);
dcnt--;
if (dcnt < 0)
return -EINVAL;
} while (value);
return 0;
}
static int tegra210_mvc_write_ram(struct tegra210_mvc *mvc, static int tegra210_mvc_write_ram(struct tegra210_mvc *mvc,
unsigned int addr, unsigned int addr,
unsigned int val) unsigned int val)
@@ -209,9 +227,7 @@ static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol,
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct tegra210_mvc *mvc = snd_soc_codec_get_drvdata(codec); struct tegra210_mvc *mvc = snd_soc_codec_get_drvdata(codec);
unsigned int reg = TEGRA210_MVC_CTRL; unsigned int reg = TEGRA210_MVC_CTRL;
int dcnt = 10;
int ret = 0; int ret = 0;
u32 value;
/* if no change in curve type, do nothing */ /* if no change in curve type, do nothing */
if (mvc->curve_type == ucontrol->value.integer.value[0]) if (mvc->curve_type == ucontrol->value.integer.value[0])
@@ -226,18 +242,11 @@ static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol,
TEGRA210_MVC_CURVE_TYPE_SHIFT); TEGRA210_MVC_CURVE_TYPE_SHIFT);
mvc->curve_type = ucontrol->value.integer.value[0]; mvc->curve_type = ucontrol->value.integer.value[0];
/* issue soft reset */ ret = tegra210_mvc_soft_reset(mvc);
regmap_write(mvc->regmap, TEGRA210_MVC_SOFT_RESET, 1); if (ret < 0) {
/* wait for soft reset bit to clear */ dev_err(codec->dev, "SOFT_RESET error: %d\n", ret);
do { return ret;
udelay(10); }
ret = regmap_read(mvc->regmap, TEGRA210_MVC_SOFT_RESET, &value);
dcnt--;
if (dcnt < 0) {
ret = -EINVAL;
goto end;
}
} while (value);
/* change volume to default init for new curve type */ /* change volume to default init for new curve type */
if (ucontrol->value.integer.value[0] == CURVE_POLY) if (ucontrol->value.integer.value[0] == CURVE_POLY)
@@ -250,7 +259,6 @@ static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol,
TEGRA210_MVC_VOLUME_SWITCH_MASK, TEGRA210_MVC_VOLUME_SWITCH_MASK,
TEGRA210_MVC_VOLUME_SWITCH_TRIGGER); TEGRA210_MVC_VOLUME_SWITCH_TRIGGER);
end:
pm_runtime_put(codec->dev); pm_runtime_put(codec->dev);
return ret; return ret;
@@ -376,6 +384,12 @@ static int tegra210_mvc_hw_params(struct snd_pcm_substream *substream,
struct tegra210_mvc *mvc = snd_soc_dai_get_drvdata(dai); struct tegra210_mvc *mvc = snd_soc_dai_get_drvdata(dai);
int i, ret; int i, ret;
ret = tegra210_mvc_soft_reset(mvc);
if (ret < 0) {
dev_err(dev, "SOFT_RESET error: %d\n", ret);
return ret;
}
/* set RX cif and TX cif */ /* set RX cif and TX cif */
ret = tegra210_mvc_set_audio_cif(mvc, params, ret = tegra210_mvc_set_audio_cif(mvc, params,
TEGRA210_MVC_AXBAR_RX_CIF_CTRL); TEGRA210_MVC_AXBAR_RX_CIF_CTRL);
@@ -396,23 +410,14 @@ static int tegra210_mvc_hw_params(struct snd_pcm_substream *substream,
~(TEGRA210_MVC_PER_CHAN_CTRL_EN_MASK)); ~(TEGRA210_MVC_PER_CHAN_CTRL_EN_MASK));
/* init the default volume=1 for MVC */ /* init the default volume=1 for MVC */
regmap_write(mvc->regmap, TEGRA210_MVC_INIT_VOL, regmap_write(mvc->regmap, TEGRA210_MVC_INIT_VOL, mvc->volume);
(mvc->curve_type == CURVE_POLY) ?
TEGRA210_MVC_INIT_VOL_DEFAULT_POLY :
TEGRA210_MVC_INIT_VOL_DEFAULT_LINEAR);
regmap_write(mvc->regmap, TEGRA210_MVC_TARGET_VOL, mvc->volume); regmap_write(mvc->regmap, TEGRA210_MVC_TARGET_VOL, mvc->volume);
/* trigger volume switch */
ret |= regmap_update_bits(mvc->regmap, TEGRA210_MVC_SWITCH,
TEGRA210_MVC_VOLUME_SWITCH_MASK,
TEGRA210_MVC_VOLUME_SWITCH_TRIGGER);
/* program the poly coefficients */ /* program the poly coefficients */
for (i = 0; i < 9; i++) for (i = 0; i < 9; i++)
tegra210_mvc_write_ram(mvc, i, mvc->poly_coeff[i]); tegra210_mvc_write_ram(mvc, i, mvc->poly_coeff[i]);
/* program poly_n1, poly_n2, duration */ /* program poly_n1, poly_n2, duration */
regmap_write(mvc->regmap, TEGRA210_MVC_POLY_N1, mvc->poly_n1); regmap_write(mvc->regmap, TEGRA210_MVC_POLY_N1, mvc->poly_n1);
regmap_write(mvc->regmap, TEGRA210_MVC_POLY_N2, mvc->poly_n2); regmap_write(mvc->regmap, TEGRA210_MVC_POLY_N2, mvc->poly_n2);
@@ -421,6 +426,10 @@ static int tegra210_mvc_hw_params(struct snd_pcm_substream *substream,
/* program duration_inv */ /* program duration_inv */
regmap_write(mvc->regmap, TEGRA210_MVC_DURATION_INV, mvc->duration_inv); regmap_write(mvc->regmap, TEGRA210_MVC_DURATION_INV, mvc->duration_inv);
/* trigger volume switch */
ret |= regmap_update_bits(mvc->regmap, TEGRA210_MVC_SWITCH,
TEGRA210_MVC_VOLUME_SWITCH_MASK,
TEGRA210_MVC_VOLUME_SWITCH_TRIGGER);
return ret; return ret;
} }