summaryrefslogtreecommitdiffstats
path: root/sound/soc/sunxi
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2020-08-18 14:52:55 +0100
committerMark Brown <broonie@kernel.org>2020-08-18 14:52:55 +0100
commit4782e6cc29482a1d6688312a344d4772c336ba4d (patch)
treeefb55423e085972986616074640950031b1571cf /sound/soc/sunxi
parent163ae5d1e102927af87e7456e3b5ac287b033a16 (diff)
parent7829e68d55692c9f7f5665ebec9fa1f33d5ad72f (diff)
downloadlinux-4782e6cc29482a1d6688312a344d4772c336ba4d.tar.bz2
Merge series "ASoC: sun50i-codec-analog: Cleanup and power management" from Samuel Holland <samuel@sholland.org>:
This series performs some minor cleanup on the driver for the analog codec in the Allwinner A64, and hooks up the existing mute switches to DAPM widgets, in order to provide improved power management. Changes since v1: - Collected Acked-by/Reviewed-by tags - Used SOC_MIXER_NAMED_CTL_ARRAY to avoid naming a widget "Earpiece" Samuel Holland (8): ASoC: sun50i-codec-analog: Fix duplicate use of ADC enable bits ASoC: sun50i-codec-analog: Gate the amplifier clock during suspend ASoC: sun50i-codec-analog: Group and sort mixer routes ASoC: sun50i-codec-analog: Make headphone routes stereo ASoC: sun50i-codec-analog: Enable DAPM for headphone switch ASoC: sun50i-codec-analog: Make line out routes stereo ASoC: sun50i-codec-analog: Enable DAPM for line out switch ASoC: sun50i-codec-analog: Enable DAPM for earpiece switch sound/soc/sunxi/sun50i-codec-analog.c | 176 ++++++++++++++++---------- 1 file changed, 111 insertions(+), 65 deletions(-) -- 2.26.2
Diffstat (limited to 'sound/soc/sunxi')
-rw-r--r--sound/soc/sunxi/sun50i-codec-analog.c176
1 files changed, 111 insertions, 65 deletions
diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c
index f5b7069bcca2..a41e25ad0aaf 100644
--- a/sound/soc/sunxi/sun50i-codec-analog.c
+++ b/sound/soc/sunxi/sun50i-codec-analog.c
@@ -121,50 +121,50 @@
/* mixer controls */
static const struct snd_kcontrol_new sun50i_a64_codec_mixer_controls[] = {
- SOC_DAPM_DOUBLE_R("DAC Playback Switch",
+ SOC_DAPM_DOUBLE_R("Mic1 Playback Switch",
SUN50I_ADDA_OL_MIX_CTRL,
SUN50I_ADDA_OR_MIX_CTRL,
- SUN50I_ADDA_OL_MIX_CTRL_DACL, 1, 0),
- SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch",
+ SUN50I_ADDA_OL_MIX_CTRL_MIC1, 1, 0),
+ SOC_DAPM_DOUBLE_R("Mic2 Playback Switch",
SUN50I_ADDA_OL_MIX_CTRL,
SUN50I_ADDA_OR_MIX_CTRL,
- SUN50I_ADDA_OL_MIX_CTRL_DACR, 1, 0),
+ SUN50I_ADDA_OL_MIX_CTRL_MIC2, 1, 0),
SOC_DAPM_DOUBLE_R("Line In Playback Switch",
SUN50I_ADDA_OL_MIX_CTRL,
SUN50I_ADDA_OR_MIX_CTRL,
SUN50I_ADDA_OL_MIX_CTRL_LINEINL, 1, 0),
- SOC_DAPM_DOUBLE_R("Mic1 Playback Switch",
+ SOC_DAPM_DOUBLE_R("DAC Playback Switch",
SUN50I_ADDA_OL_MIX_CTRL,
SUN50I_ADDA_OR_MIX_CTRL,
- SUN50I_ADDA_OL_MIX_CTRL_MIC1, 1, 0),
- SOC_DAPM_DOUBLE_R("Mic2 Playback Switch",
+ SUN50I_ADDA_OL_MIX_CTRL_DACL, 1, 0),
+ SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch",
SUN50I_ADDA_OL_MIX_CTRL,
SUN50I_ADDA_OR_MIX_CTRL,
- SUN50I_ADDA_OL_MIX_CTRL_MIC2, 1, 0),
+ SUN50I_ADDA_OL_MIX_CTRL_DACR, 1, 0),
};
/* ADC mixer controls */
static const struct snd_kcontrol_new sun50i_codec_adc_mixer_controls[] = {
- SOC_DAPM_DOUBLE_R("Mixer Capture Switch",
+ SOC_DAPM_DOUBLE_R("Mic1 Capture Switch",
SUN50I_ADDA_L_ADCMIX_SRC,
SUN50I_ADDA_R_ADCMIX_SRC,
- SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL, 1, 0),
- SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch",
+ SUN50I_ADDA_L_ADCMIX_SRC_MIC1, 1, 0),
+ SOC_DAPM_DOUBLE_R("Mic2 Capture Switch",
SUN50I_ADDA_L_ADCMIX_SRC,
SUN50I_ADDA_R_ADCMIX_SRC,
- SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR, 1, 0),
+ SUN50I_ADDA_L_ADCMIX_SRC_MIC2, 1, 0),
SOC_DAPM_DOUBLE_R("Line In Capture Switch",
SUN50I_ADDA_L_ADCMIX_SRC,
SUN50I_ADDA_R_ADCMIX_SRC,
SUN50I_ADDA_L_ADCMIX_SRC_LINEINL, 1, 0),
- SOC_DAPM_DOUBLE_R("Mic1 Capture Switch",
+ SOC_DAPM_DOUBLE_R("Mixer Capture Switch",
SUN50I_ADDA_L_ADCMIX_SRC,
SUN50I_ADDA_R_ADCMIX_SRC,
- SUN50I_ADDA_L_ADCMIX_SRC_MIC1, 1, 0),
- SOC_DAPM_DOUBLE_R("Mic2 Capture Switch",
+ SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL, 1, 0),
+ SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch",
SUN50I_ADDA_L_ADCMIX_SRC,
SUN50I_ADDA_R_ADCMIX_SRC,
- SUN50I_ADDA_L_ADCMIX_SRC_MIC2, 1, 0),
+ SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR, 1, 0),
};
static const DECLARE_TLV_DB_SCALE(sun50i_codec_out_mixer_pregain_scale,
@@ -193,11 +193,6 @@ static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = {
SUN50I_ADDA_HP_CTRL_HPVOL, 0x3f, 0,
sun50i_codec_hp_vol_scale),
- SOC_DOUBLE("Headphone Playback Switch",
- SUN50I_ADDA_MIX_DAC_CTRL,
- SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE,
- SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE, 1, 0),
-
/* Mixer pre-gain */
SOC_SINGLE_TLV("Mic1 Playback Volume", SUN50I_ADDA_MIC1_CTRL,
SUN50I_ADDA_MIC1_CTRL_MIC1G,
@@ -233,20 +228,10 @@ static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = {
SUN50I_ADDA_LINEOUT_CTRL1_VOL, 0x1f, 0,
sun50i_codec_lineout_vol_scale),
- SOC_DOUBLE("Line Out Playback Switch",
- SUN50I_ADDA_LINEOUT_CTRL0,
- SUN50I_ADDA_LINEOUT_CTRL0_LEN,
- SUN50I_ADDA_LINEOUT_CTRL0_REN, 1, 0),
-
SOC_SINGLE_TLV("Earpiece Playback Volume",
SUN50I_ADDA_EARPIECE_CTRL1,
SUN50I_ADDA_EARPIECE_CTRL1_ESP_VOL, 0x1f, 0,
sun50i_codec_earpiece_vol_scale),
-
- SOC_SINGLE("Earpiece Playback Switch",
- SUN50I_ADDA_EARPIECE_CTRL1,
- SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE, 1, 0),
-
};
static const char * const sun50i_codec_hp_src_enum_text[] = {
@@ -264,6 +249,12 @@ static const struct snd_kcontrol_new sun50i_codec_hp_src[] = {
sun50i_codec_hp_src_enum),
};
+static const struct snd_kcontrol_new sun50i_codec_hp_switch =
+ SOC_DAPM_DOUBLE("Headphone Playback Switch",
+ SUN50I_ADDA_MIX_DAC_CTRL,
+ SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE,
+ SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE, 1, 0);
+
static const char * const sun50i_codec_lineout_src_enum_text[] = {
"Stereo", "Mono Differential",
};
@@ -279,6 +270,12 @@ static const struct snd_kcontrol_new sun50i_codec_lineout_src[] = {
sun50i_codec_lineout_src_enum),
};
+static const struct snd_kcontrol_new sun50i_codec_lineout_switch =
+ SOC_DAPM_DOUBLE("Line Out Playback Switch",
+ SUN50I_ADDA_LINEOUT_CTRL0,
+ SUN50I_ADDA_LINEOUT_CTRL0_LEN,
+ SUN50I_ADDA_LINEOUT_CTRL0_REN, 1, 0);
+
static const char * const sun50i_codec_earpiece_src_enum_text[] = {
"DACR", "DACL", "Right Mixer", "Left Mixer",
};
@@ -293,6 +290,12 @@ static const struct snd_kcontrol_new sun50i_codec_earpiece_src[] = {
sun50i_codec_earpiece_src_enum),
};
+static const struct snd_kcontrol_new sun50i_codec_earpiece_switch[] = {
+ SOC_DAPM_SINGLE("Earpiece Playback Switch",
+ SUN50I_ADDA_EARPIECE_CTRL1,
+ SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE, 1, 0),
+};
+
static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = {
/* DAC */
SND_SOC_DAPM_DAC("Left DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL,
@@ -311,18 +314,37 @@ static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = {
*/
SND_SOC_DAPM_REGULATOR_SUPPLY("cpvdd", 0, 0),
- SND_SOC_DAPM_MUX("Headphone Source Playback Route",
+ SND_SOC_DAPM_MUX("Left Headphone Source",
+ SND_SOC_NOPM, 0, 0, sun50i_codec_hp_src),
+ SND_SOC_DAPM_MUX("Right Headphone Source",
SND_SOC_NOPM, 0, 0, sun50i_codec_hp_src),
- SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUN50I_ADDA_HP_CTRL,
+ SND_SOC_DAPM_SWITCH("Left Headphone Switch",
+ SND_SOC_NOPM, 0, 0, &sun50i_codec_hp_switch),
+ SND_SOC_DAPM_SWITCH("Right Headphone Switch",
+ SND_SOC_NOPM, 0, 0, &sun50i_codec_hp_switch),
+ SND_SOC_DAPM_OUT_DRV("Left Headphone Amp",
+ SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("Right Headphone Amp",
+ SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Headphone Amp", SUN50I_ADDA_HP_CTRL,
SUN50I_ADDA_HP_CTRL_HPPA_EN, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("HP"),
- SND_SOC_DAPM_MUX("Line Out Source Playback Route",
+ SND_SOC_DAPM_MUX("Left Line Out Source",
SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src),
+ SND_SOC_DAPM_MUX("Right Line Out Source",
+ SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src),
+ SND_SOC_DAPM_SWITCH("Left Line Out Switch",
+ SND_SOC_NOPM, 0, 0, &sun50i_codec_lineout_switch),
+ SND_SOC_DAPM_SWITCH("Right Line Out Switch",
+ SND_SOC_NOPM, 0, 0, &sun50i_codec_lineout_switch),
SND_SOC_DAPM_OUTPUT("LINEOUT"),
SND_SOC_DAPM_MUX("Earpiece Source Playback Route",
SND_SOC_NOPM, 0, 0, sun50i_codec_earpiece_src),
+ SOC_MIXER_NAMED_CTL_ARRAY("Earpiece Switch",
+ SND_SOC_NOPM, 0, 0,
+ sun50i_codec_earpiece_switch),
SND_SOC_DAPM_OUT_DRV("Earpiece Amp", SUN50I_ADDA_EARPIECE_CTRL1,
SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_EN, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("EARPIECE"),
@@ -363,83 +385,105 @@ static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = {
SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN, 0,
sun50i_a64_codec_mixer_controls,
ARRAY_SIZE(sun50i_a64_codec_mixer_controls)),
- SND_SOC_DAPM_MIXER("Left ADC Mixer", SUN50I_ADDA_ADC_CTRL,
- SUN50I_ADDA_ADC_CTRL_ADCLEN, 0,
+ SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
sun50i_codec_adc_mixer_controls,
ARRAY_SIZE(sun50i_codec_adc_mixer_controls)),
- SND_SOC_DAPM_MIXER("Right ADC Mixer", SUN50I_ADDA_ADC_CTRL,
- SUN50I_ADDA_ADC_CTRL_ADCREN, 0,
+ SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0,
sun50i_codec_adc_mixer_controls,
ARRAY_SIZE(sun50i_codec_adc_mixer_controls)),
};
static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = {
/* Left Mixer Routes */
+ { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
+ { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
+ { "Left Mixer", "Line In Playback Switch", "LINEIN" },
{ "Left Mixer", "DAC Playback Switch", "Left DAC" },
{ "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
- { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
/* Right Mixer Routes */
+ { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
+ { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
+ { "Right Mixer", "Line In Playback Switch", "LINEIN" },
{ "Right Mixer", "DAC Playback Switch", "Right DAC" },
{ "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
- { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
/* Left ADC Mixer Routes */
+ { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
+ { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
+ { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
{ "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" },
{ "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" },
- { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
/* Right ADC Mixer Routes */
+ { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
+ { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
+ { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
{ "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" },
{ "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" },
- { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
/* ADC Routes */
{ "Left ADC", NULL, "Left ADC Mixer" },
{ "Right ADC", NULL, "Right ADC Mixer" },
/* Headphone Routes */
- { "Headphone Source Playback Route", "DAC", "Left DAC" },
- { "Headphone Source Playback Route", "DAC", "Right DAC" },
- { "Headphone Source Playback Route", "Mixer", "Left Mixer" },
- { "Headphone Source Playback Route", "Mixer", "Right Mixer" },
- { "Headphone Amp", NULL, "Headphone Source Playback Route" },
+ { "Left Headphone Source", "DAC", "Left DAC" },
+ { "Left Headphone Source", "Mixer", "Left Mixer" },
+ { "Left Headphone Switch", "Headphone Playback Switch", "Left Headphone Source" },
+ { "Left Headphone Amp", NULL, "Left Headphone Switch" },
+ { "Left Headphone Amp", NULL, "Headphone Amp" },
+ { "HP", NULL, "Left Headphone Amp" },
+
+ { "Right Headphone Source", "DAC", "Right DAC" },
+ { "Right Headphone Source", "Mixer", "Right Mixer" },
+ { "Right Headphone Switch", "Headphone Playback Switch", "Right Headphone Source" },
+ { "Right Headphone Amp", NULL, "Right Headphone Switch" },
+ { "Right Headphone Amp", NULL, "Headphone Amp" },
+ { "HP", NULL, "Right Headphone Amp" },
+
{ "Headphone Amp", NULL, "cpvdd" },
- { "HP", NULL, "Headphone Amp" },
/* Microphone Routes */
{ "Mic1 Amplifier", NULL, "MIC1"},
/* Microphone Routes */
{ "Mic2 Amplifier", NULL, "MIC2"},
- { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
- { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
- { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
- { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
-
- /* Line-in Routes */
- { "Left Mixer", "Line In Playback Switch", "LINEIN" },
- { "Right Mixer", "Line In Playback Switch", "LINEIN" },
- { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
- { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
/* Line-out Routes */
- { "Line Out Source Playback Route", "Stereo", "Left Mixer" },
- { "Line Out Source Playback Route", "Stereo", "Right Mixer" },
- { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" },
- { "Line Out Source Playback Route", "Mono Differential",
- "Right Mixer" },
- { "LINEOUT", NULL, "Line Out Source Playback Route" },
+ { "Left Line Out Source", "Stereo", "Left Mixer" },
+ { "Left Line Out Source", "Mono Differential", "Left Mixer" },
+ { "Left Line Out Source", "Mono Differential", "Right Mixer" },
+ { "Left Line Out Switch", "Line Out Playback Switch", "Left Line Out Source" },
+ { "LINEOUT", NULL, "Left Line Out Switch" },
+
+ { "Right Line Out Switch", "Line Out Playback Switch", "Right Mixer" },
+ { "Right Line Out Source", "Stereo", "Right Line Out Switch" },
+ { "Right Line Out Source", "Mono Differential", "Left Line Out Switch" },
+ { "LINEOUT", NULL, "Right Line Out Source" },
/* Earpiece Routes */
{ "Earpiece Source Playback Route", "DACL", "Left DAC" },
{ "Earpiece Source Playback Route", "DACR", "Right DAC" },
{ "Earpiece Source Playback Route", "Left Mixer", "Left Mixer" },
{ "Earpiece Source Playback Route", "Right Mixer", "Right Mixer" },
- { "Earpiece Amp", NULL, "Earpiece Source Playback Route" },
+ { "Earpiece Switch", "Earpiece Playback Switch", "Earpiece Source Playback Route" },
+ { "Earpiece Amp", NULL, "Earpiece Switch" },
{ "EARPIECE", NULL, "Earpiece Amp" },
};
+static int sun50i_a64_codec_suspend(struct snd_soc_component *component)
+{
+ return regmap_update_bits(component->regmap, SUN50I_ADDA_HP_CTRL,
+ BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE),
+ BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE));
+}
+
+static int sun50i_a64_codec_resume(struct snd_soc_component *component)
+{
+ return regmap_update_bits(component->regmap, SUN50I_ADDA_HP_CTRL,
+ BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE), 0);
+}
+
static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = {
.controls = sun50i_a64_codec_controls,
.num_controls = ARRAY_SIZE(sun50i_a64_codec_controls),
@@ -447,6 +491,8 @@ static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = {
.num_dapm_widgets = ARRAY_SIZE(sun50i_a64_codec_widgets),
.dapm_routes = sun50i_a64_codec_routes,
.num_dapm_routes = ARRAY_SIZE(sun50i_a64_codec_routes),
+ .suspend = sun50i_a64_codec_suspend,
+ .resume = sun50i_a64_codec_resume,
};
static const struct of_device_id sun50i_codec_analog_of_match[] = {