[PATCH] ASoC: sun8i-codec: Add AIF, ADC, and DAC volume controls
This allows changing the volume of each digital input/output independently, and provides the only "master volume" for the DAC. (The ADC also has a gain control on the analog side.)
While the hardware supports digital gain up to +72dB, the controls here are limited to +24dB maximum, as any gain above that level makes volume sliders difficult to use, and is extremely likely to cause clipping.
Signed-off-by: Samuel Holland samuel@sholland.org --- sound/soc/sunxi/sun8i-codec.c | 56 +++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 518bfb724a5b..0bea2162f68d 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -21,6 +21,7 @@ #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/soc-dapm.h> +#include <sound/tlv.h>
#define SUN8I_SYSCLK_CTL 0x00c #define SUN8I_SYSCLK_CTL_AIF1CLK_ENA 11 @@ -72,6 +73,12 @@ #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR 10 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR 9 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL 8 +#define SUN8I_AIF1_VOL_CTRL1 0x050 +#define SUN8I_AIF1_VOL_CTRL1_AD0L_VOL 8 +#define SUN8I_AIF1_VOL_CTRL1_AD0R_VOL 0 +#define SUN8I_AIF1_VOL_CTRL3 0x058 +#define SUN8I_AIF1_VOL_CTRL3_DA0L_VOL 8 +#define SUN8I_AIF1_VOL_CTRL3_DA0R_VOL 0 #define SUN8I_AIF2_ADCDAT_CTRL 0x084 #define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA 15 #define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA 14 @@ -91,6 +98,12 @@ #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R 10 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL 9 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR 8 +#define SUN8I_AIF2_VOL_CTRL1 0x090 +#define SUN8I_AIF2_VOL_CTRL1_ADCL_VOL 8 +#define SUN8I_AIF2_VOL_CTRL1_ADCR_VOL 0 +#define SUN8I_AIF2_VOL_CTRL2 0x098 +#define SUN8I_AIF2_VOL_CTRL2_DACL_VOL 8 +#define SUN8I_AIF2_VOL_CTRL2_DACR_VOL 0 #define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1 (0x0 << 0) #define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2 (0x1 << 0) #define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1CLK (0x2 << 0) @@ -102,8 +115,14 @@ #define SUN8I_ADC_DIG_CTRL_ENAD 15 #define SUN8I_ADC_DIG_CTRL_ADOUT_DTS 2 #define SUN8I_ADC_DIG_CTRL_ADOUT_DLY 1 +#define SUN8I_ADC_VOL_CTRL 0x104 +#define SUN8I_ADC_VOL_CTRL_ADCL_VOL 8 +#define SUN8I_ADC_VOL_CTRL_ADCR_VOL 0 #define SUN8I_DAC_DIG_CTRL 0x120 #define SUN8I_DAC_DIG_CTRL_ENDA 15 +#define SUN8I_DAC_VOL_CTRL 0x124 +#define SUN8I_DAC_VOL_CTRL_DACL_VOL 8 +#define SUN8I_DAC_VOL_CTRL_DACR_VOL 0 #define SUN8I_DAC_MXR_SRC 0x130 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L 15 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L 14 @@ -696,6 +715,41 @@ static struct snd_soc_dai_driver sun8i_codec_dais[] = { }, };
+static const DECLARE_TLV_DB_SCALE(sun8i_codec_vol_scale, -12000, 75, 1); + +static const struct snd_kcontrol_new sun8i_codec_controls[] = { + SOC_DOUBLE_TLV("AIF1 AD0 Capture Volume", + SUN8I_AIF1_VOL_CTRL1, + SUN8I_AIF1_VOL_CTRL1_AD0L_VOL, + SUN8I_AIF1_VOL_CTRL1_AD0R_VOL, + 0xc0, 0, sun8i_codec_vol_scale), + SOC_DOUBLE_TLV("AIF1 DA0 Playback Volume", + SUN8I_AIF1_VOL_CTRL3, + SUN8I_AIF1_VOL_CTRL3_DA0L_VOL, + SUN8I_AIF1_VOL_CTRL3_DA0R_VOL, + 0xc0, 0, sun8i_codec_vol_scale), + SOC_DOUBLE_TLV("AIF2 ADC Capture Volume", + SUN8I_AIF2_VOL_CTRL1, + SUN8I_AIF2_VOL_CTRL1_ADCL_VOL, + SUN8I_AIF2_VOL_CTRL1_ADCR_VOL, + 0xc0, 0, sun8i_codec_vol_scale), + SOC_DOUBLE_TLV("AIF2 DAC Playback Volume", + SUN8I_AIF2_VOL_CTRL2, + SUN8I_AIF2_VOL_CTRL2_DACL_VOL, + SUN8I_AIF2_VOL_CTRL2_DACR_VOL, + 0xc0, 0, sun8i_codec_vol_scale), + SOC_DOUBLE_TLV("ADC Capture Volume", + SUN8I_ADC_VOL_CTRL, + SUN8I_ADC_VOL_CTRL_ADCL_VOL, + SUN8I_ADC_VOL_CTRL_ADCR_VOL, + 0xc0, 0, sun8i_codec_vol_scale), + SOC_DOUBLE_TLV("DAC Playback Volume", + SUN8I_DAC_VOL_CTRL, + SUN8I_DAC_VOL_CTRL_DACL_VOL, + SUN8I_DAC_VOL_CTRL_DACR_VOL, + 0xc0, 0, sun8i_codec_vol_scale), +}; + static int sun8i_codec_aif_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -1215,6 +1269,8 @@ static int sun8i_codec_component_probe(struct snd_soc_component *component) }
static const struct snd_soc_component_driver sun8i_soc_component = { + .controls = sun8i_codec_controls, + .num_controls = ARRAY_SIZE(sun8i_codec_controls), .dapm_widgets = sun8i_codec_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets), .dapm_routes = sun8i_codec_dapm_routes,
On Wed, 17 Nov 2021 21:36:45 -0600, Samuel Holland wrote:
This allows changing the volume of each digital input/output independently, and provides the only "master volume" for the DAC. (The ADC also has a gain control on the analog side.)
While the hardware supports digital gain up to +72dB, the controls here are limited to +24dB maximum, as any gain above that level makes volume sliders difficult to use, and is extremely likely to cause clipping.
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/1] ASoC: sun8i-codec: Add AIF, ADC, and DAC volume controls commit: fd03cf7f5b4726028cfc2ef76e42d0d5c66377aa
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (2)
-
Mark Brown
-
Samuel Holland