Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: tas2770: Power cycle amp on ISENSE/VSENSE change

The ISENSE/VSENSE blocks are only powered up when the amplifier
transitions from shutdown to active. This means that if those controls
are flipped on while the amplifier is already playing back audio, they
will have no effect.

Fix this by forcing a power cycle around transitions in those controls.

Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
Link: https://patch.msgid.link/20250406-apple-codec-changes-v5-1-50a00ec850a3@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Hector Martin and committed by
Mark Brown
f529c91b 8ffd015d

+28 -2
+28 -2
sound/soc/codecs/tas2770.c
··· 156 156 static const struct snd_kcontrol_new vsense_switch = 157 157 SOC_DAPM_SINGLE("Switch", TAS2770_PWR_CTRL, 2, 1, 1); 158 158 159 + static int sense_event(struct snd_soc_dapm_widget *w, 160 + struct snd_kcontrol *kcontrol, int event) 161 + { 162 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 163 + struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component); 164 + 165 + /* 166 + * Powering up ISENSE/VSENSE requires a trip through the shutdown state. 167 + * Do that here to ensure that our changes are applied properly, otherwise 168 + * we might end up with non-functional IVSENSE if playback started earlier, 169 + * which would break software speaker protection. 170 + */ 171 + switch (event) { 172 + case SND_SOC_DAPM_PRE_REG: 173 + return snd_soc_component_update_bits(component, TAS2770_PWR_CTRL, 174 + TAS2770_PWR_CTRL_MASK, 175 + TAS2770_PWR_CTRL_SHUTDOWN); 176 + case SND_SOC_DAPM_POST_REG: 177 + return tas2770_update_pwr_ctrl(tas2770); 178 + default: 179 + return 0; 180 + } 181 + } 182 + 159 183 static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = { 160 184 SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0), 161 185 SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2770_asi1_mux), 162 - SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PWR_CTRL, 3, 1, &isense_switch), 163 - SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PWR_CTRL, 2, 1, &vsense_switch), 186 + SND_SOC_DAPM_SWITCH_E("ISENSE", TAS2770_PWR_CTRL, 3, 1, &isense_switch, 187 + sense_event, SND_SOC_DAPM_PRE_REG | SND_SOC_DAPM_POST_REG), 188 + SND_SOC_DAPM_SWITCH_E("VSENSE", TAS2770_PWR_CTRL, 2, 1, &vsense_switch, 189 + sense_event, SND_SOC_DAPM_PRE_REG | SND_SOC_DAPM_POST_REG), 164 190 SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2770_dac_event, 165 191 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 166 192 SND_SOC_DAPM_OUTPUT("OUT"),