lede/target/linux/silicon/patches-5.19/0082-ASoC-tas2764-Add-workaround-for-spurious-shutdowns-o.patch

148 lines
4.2 KiB
Diff

From b94fc3351432c6a0a75962c4af03750d8879d205 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Sun, 13 Mar 2022 03:13:08 +0900
Subject: [PATCH 082/171] ASoC: tas2764: Add workaround for spurious shutdowns
on SN012776
It seems that on SHUTDOWN -> MUTE transitions, the SN012776 can end up
in a borked state raising an overcurrent error.
Going through the ACTIVE state seems to make it work reliably, so do
that.
Signed-off-by: Hector Martin <marcan@marcan.st>
---
sound/soc/codecs/tas2764.c | 65 +++++++++++++++++++++-----------------
1 file changed, 36 insertions(+), 29 deletions(-)
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index dd36c99e633b..b3c99f470916 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -58,27 +58,47 @@ static void tas2764_reset(struct tas2764_priv *tas2764)
usleep_range(1000, 2000);
}
+static int tas2764_set_power(struct tas2764_priv *tas2764, u8 mode)
+{
+ int ret;
+
+ // TODO: Does this only affect the SN012776 variant?
+ if (tas2764->devid == DEVID_SN012776 && mode == TAS2764_PWR_CTRL_MUTE) {
+ ret = snd_soc_component_update_bits(tas2764->component,
+ TAS2764_PWR_CTRL,
+ TAS2764_PWR_CTRL_MASK,
+ TAS2764_PWR_CTRL_ACTIVE);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = snd_soc_component_update_bits(tas2764->component,
+ TAS2764_PWR_CTRL,
+ TAS2764_PWR_CTRL_MASK,
+ mode);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+
static int tas2764_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
+ u8 mode;
switch (level) {
case SND_SOC_BIAS_ON:
- snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_ACTIVE);
+ mode = TAS2764_PWR_CTRL_ACTIVE;
break;
case SND_SOC_BIAS_STANDBY:
case SND_SOC_BIAS_PREPARE:
- snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_MUTE);
+ mode = TAS2764_PWR_CTRL_MUTE;
break;
case SND_SOC_BIAS_OFF:
- snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_SHUTDOWN);
+ mode = TAS2764_PWR_CTRL_SHUTDOWN;
break;
default:
@@ -87,7 +107,7 @@ static int tas2764_set_bias_level(struct snd_soc_component *component,
return -EINVAL;
}
- return 0;
+ return tas2764_set_power(tas2764, mode);
}
#ifdef CONFIG_PM
@@ -96,10 +116,7 @@ static int tas2764_codec_suspend(struct snd_soc_component *component)
struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
int ret;
- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_SHUTDOWN);
-
+ ret = tas2764_set_power(tas2764, TAS2764_PWR_CTRL_SHUTDOWN);
if (ret < 0)
return ret;
@@ -122,10 +139,7 @@ static int tas2764_codec_resume(struct snd_soc_component *component)
usleep_range(1000, 2000);
}
- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_ACTIVE);
-
+ ret = tas2764_set_power(tas2764, TAS2764_PWR_CTRL_ACTIVE);
if (ret < 0)
return ret;
@@ -154,28 +168,21 @@ static int tas2764_dac_event(struct snd_soc_dapm_widget *w,
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
- int ret;
+ u8 mode;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_MUTE);
+ mode = TAS2764_PWR_CTRL_MUTE;
break;
case SND_SOC_DAPM_PRE_PMD:
- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
- TAS2764_PWR_CTRL_MASK,
- TAS2764_PWR_CTRL_SHUTDOWN);
+ mode = TAS2764_PWR_CTRL_SHUTDOWN;
break;
default:
dev_err(tas2764->dev, "Unsupported event\n");
return -EINVAL;
}
- if (ret < 0)
- return ret;
-
- return 0;
+ return tas2764_set_power(tas2764, mode);
}
static const struct snd_kcontrol_new isense_switch =
--
2.34.1