diff --git a/sound/soc/tegra/tegra210_mbdrc.c b/sound/soc/tegra/tegra210_mbdrc.c index 0f450d95..d1d18b70 100644 --- a/sound/soc/tegra/tegra210_mbdrc.c +++ b/sound/soc/tegra/tegra210_mbdrc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "tegra210_ahub.h" #include "tegra210_mbdrc.h" @@ -344,6 +345,43 @@ static int tegra210_mbdrc_param_info(struct snd_kcontrol *kcontrol, return 0; } +static int tegra210_mbdrc_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + unsigned long long fls_val = 1ULL << fls(mc->max); + unsigned int mask = fls_val - 1; + int val; + + regmap_read(ope->mbdrc_regmap, mc->reg, &val); + + ucontrol->value.integer.value[0] = ((val >> mc->shift) - + TEGRA210_MBDRC_MASTER_VOL_MIN) & mask; + + return 0; +} + +static int tegra210_mbdrc_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + unsigned long long fls_val = 1ULL << fls(mc->max); + unsigned int mask = fls_val - 1; + unsigned int val; + + val = (ucontrol->value.integer.value[0] & mask); + val = val + TEGRA210_MBDRC_MASTER_VOL_MIN; + val = val << mc->shift; + + return regmap_write(ope->mbdrc_regmap, mc->reg, val); +} + static const char * const tegra210_mbdrc_mode_text[] = { "bypass", "fullband", "dualband", "multiband" }; @@ -389,6 +427,8 @@ static const struct soc_enum tegra210_mbdrc_frame_size_enum = TEGRA_MBDRC_BYTES_EXT(xname, xbase, TEGRA210_MBDRC_FILTER_COUNT, \ xshift, xmask, xinfo) +static const DECLARE_TLV_DB_MINMAX(mdbrc_vol_tlv, -25600, 25500); + static const struct snd_kcontrol_new tegra210_mbdrc_controls[] = { SOC_ENUM_EXT("mbdrc peak-rms mode", tegra210_mbdrc_peak_rms_enum, tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum), @@ -406,9 +446,6 @@ static const struct snd_kcontrol_new tegra210_mbdrc_controls[] = { SOC_SINGLE_EXT("mbdrc shift control", TEGRA210_MBDRC_CONFIG, TEGRA210_MBDRC_CONFIG_SHIFT_CTRL_SHIFT, 0x1f, 0, tegra210_mbdrc_get, tegra210_mbdrc_put), - SOC_SINGLE_EXT("mbdrc master volume", TEGRA210_MBDRC_MASTER_VOLUME, - TEGRA210_MBDRC_MASTER_VOLUME_SHIFT, 0xffffffff, 0, - tegra210_mbdrc_get, tegra210_mbdrc_put), SOC_SINGLE_EXT("mbdrc fast attack factor", TEGRA210_MBDRC_FAST_FACTOR, TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT, 0xffff, 0, tegra210_mbdrc_get, tegra210_mbdrc_put), @@ -416,6 +453,11 @@ static const struct snd_kcontrol_new tegra210_mbdrc_controls[] = { TEGRA210_MBDRC_FAST_FACTOR_RELEASE_SHIFT, 0xffff, 0, tegra210_mbdrc_get, tegra210_mbdrc_put), + SOC_SINGLE_RANGE_EXT_TLV("mbdrc master volume", TEGRA210_MBDRC_MASTER_VOLUME, + TEGRA210_MBDRC_MASTER_VOLUME_SHIFT, TEGRA210_MBDRC_MASTER_VOL_MIN, + TEGRA210_MBDRC_MASTER_VOL_MAX, 0, + tegra210_mbdrc_vol_get, tegra210_mbdrc_vol_put, mdbrc_vol_tlv), + TEGRA_SOC_BYTES_EXT("mbdrc iir stages", TEGRA210_MBDRC_IIR_CONFIG, TEGRA210_MBDRC_FILTER_COUNT, TEGRA210_MBDRC_IIR_CONFIG_NUM_STAGES_SHIFT, @@ -602,6 +644,7 @@ static bool tegra210_mbdrc_volatile_reg(struct device *dev, unsigned int reg) switch (reg) { case TEGRA210_MBDRC_SOFT_RESET: + case TEGRA210_MBDRC_STATUS: case TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_CTRL: case TEGRA210_MBDRC_AHUBRAMCTL_CONFIG_RAM_DATA: return true; diff --git a/sound/soc/tegra/tegra210_mbdrc.h b/sound/soc/tegra/tegra210_mbdrc.h index 291d021a..fd6b14bc 100644 --- a/sound/soc/tegra/tegra210_mbdrc.h +++ b/sound/soc/tegra/tegra210_mbdrc.h @@ -89,8 +89,9 @@ enum { #define TEGRA210_MBDRC_CHANNEL_MASK_MASK (0xff << TEGRA210_MBDRC_CHANNEL_MASK_SHIFT) /* Fields for TEGRA210_MBDRC_MASTER_VOLUME */ -#define TEGRA210_MBDRC_MASTER_VOLUME_SHIFT 0 -#define TEGRA210_MBDRC_MASTER_VOLUME_MASK (0xffffffff << TEGRA210_MBDRC_MASTER_VOLUME_SHIFT) +#define TEGRA210_MBDRC_MASTER_VOLUME_SHIFT 23 +#define TEGRA210_MBDRC_MASTER_VOL_MIN -256 +#define TEGRA210_MBDRC_MASTER_VOL_MAX 256 /* Fields for TEGRA210_MBDRC_FAST_FACTOR */ #define TEGRA210_MBDRC_FAST_FACTOR_RELEASE_SHIFT 16