diff mbox series

[v1,3/3] ASoC: codecs: rtq9128: Fix E1 eng version amp on sequence

Message ID 1699862176-23710-4-git-send-email-cy_huang@richtek.com
State New
Headers show
Series rtq9128: Fix user reported issues | expand

Commit Message

ChiYuan Huang Nov. 13, 2023, 7:56 a.m. UTC
From: ChiYuan Huang <cy_huang@richtek.com>

For E1 eng sample, there's the current bias issue. Some undocumented RGs
should be runtime controlled during the DAPM flow to prevent the
abnormal false alarm protection latchup.

Signed-off-by: ChiYuan Huang <cy_huang@richtek.com>
---
 sound/soc/codecs/rtq9128.c | 57 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 54 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/sound/soc/codecs/rtq9128.c b/sound/soc/codecs/rtq9128.c
index aa3eadecd974..b1b889cbbc6f 100644
--- a/sound/soc/codecs/rtq9128.c
+++ b/sound/soc/codecs/rtq9128.c
@@ -63,6 +63,7 @@  struct rtq9128_data {
 	int tdm_slots;
 	int tdm_slot_width;
 	bool tdm_input_data2_select;
+	bool tka470b_e1_ver;
 };
 
 struct rtq9128_init_reg {
@@ -171,7 +172,7 @@  static bool rtq9128_is_writeable_reg(struct device *dev, unsigned int reg)
 	case 0x80 ... 0x8B:
 	case 0xA0 ... 0xAD:
 	case 0xB0 ... 0xBA:
-	case 0xC0:
+	case 0xC0 ... 0xC1:
 	case 0xD0 ... 0xDE:
 	case 0xE0 ... 0xE5:
 	case 0xF0 ... 0xF3:
@@ -283,6 +284,33 @@  static const struct snd_kcontrol_new rtq9128_snd_ctrls[] = {
 	SOC_ENUM("DVDD UV Threshold Select", rtq9128_dvdduv_select_enum),
 };
 
+static int rtq9128_int_power_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
+				   int event)
+{
+	struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+	struct rtq9128_data *data = snd_soc_component_get_drvdata(comp);
+	int ret;
+
+	dev_dbg(comp->dev, "%s: event %d, ver %d\n", __func__, event, data->tka470b_e1_ver);
+
+	if (!data->tka470b_e1_ver)
+		return 0;
+
+	if (event == SND_SOC_DAPM_POST_PMU) {
+		ret = snd_soc_component_write(comp, 0xB9, 0x03);
+		if (ret)
+			return ret;
+
+		return snd_soc_component_write(comp, 0xC1, 0);
+	}
+
+	ret = snd_soc_component_write(comp, 0xA1, 0x02);
+	if (ret)
+		return ret;
+
+	return snd_soc_component_write(comp, 0xA8, 0x01);
+}
+
 static int rtq9128_dac_power_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
 				   int event)
 {
@@ -320,6 +348,8 @@  static int rtq9128_dac_power_event(struct snd_soc_dapm_widget *w, struct snd_kco
 }
 
 static const struct snd_soc_dapm_widget rtq9128_dapm_widgets[] = {
+	SND_SOC_DAPM_SUPPLY("PWR", SND_SOC_NOPM, 0, 0, rtq9128_int_power_event,
+			    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 	SND_SOC_DAPM_DAC_E("DAC1", NULL, SND_SOC_NOPM, 0, 0, rtq9128_dac_power_event,
 			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 	SND_SOC_DAPM_DAC_E("DAC2", NULL, SND_SOC_NOPM, 0, 0, rtq9128_dac_power_event,
@@ -339,6 +369,10 @@  static const struct snd_soc_dapm_route rtq9128_dapm_routes[] = {
 	{ "DAC2", NULL, "Playback" },
 	{ "DAC3", NULL, "Playback" },
 	{ "DAC4", NULL, "Playback" },
+	{ "DAC1", NULL, "PWR" },
+	{ "DAC2", NULL, "PWR" },
+	{ "DAC3", NULL, "PWR" },
+	{ "DAC4", NULL, "PWR" },
 	{ "OUT1", NULL, "DAC1" },
 	{ "OUT2", NULL, "DAC2" },
 	{ "OUT3", NULL, "DAC3" },
@@ -358,9 +392,7 @@  static const struct rtq9128_init_reg rtq9128_tka470b_tables[] = {
 	{ 0x70, 0x11 },
 	{ 0x75, 0x1F },
 	{ 0xB6, 0x03 },
-	{ 0xB9, 0x03 },
 	{ 0xB8, 0x03 },
-	{ 0xC1, 0xFF },
 	{ 0xF8, 0x72 },
 	{ 0x30, 0x180 },
 };
@@ -387,6 +419,7 @@  static const struct rtq9128_init_reg rtq9128_dl_tables[] = {
 
 static int rtq9128_component_probe(struct snd_soc_component *comp)
 {
+	struct rtq9128_data *data = snd_soc_component_get_drvdata(comp);
 	const struct rtq9128_init_reg *table, *curr;
 	size_t table_size;
 	unsigned int val;
@@ -402,6 +435,7 @@  static int rtq9128_component_probe(struct snd_soc_component *comp)
 
 	switch (FIELD_GET(RTQ9128_DIE_CHECK_MASK, val)) {
 	case RTQ9128_TKA470B_VAL:
+		data->tka470b_e1_ver = true;
 		table = rtq9128_tka470b_tables;
 		table_size = ARRAY_SIZE(rtq9128_tka470b_tables);
 		break;
@@ -630,12 +664,29 @@  static int rtq9128_dai_hw_params(struct snd_pcm_substream *stream, struct snd_pc
 
 static int rtq9128_dai_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
 {
+	struct rtq9128_data *data = snd_soc_dai_get_drvdata(dai);
 	struct snd_soc_component *comp = dai->component;
 	struct device *dev = dai->dev;
 	int ret;
 
 	dev_dbg(dev, "%s: mute (%d), stream (%d)\n", __func__, mute, stream);
 
+	if (data->tka470b_e1_ver && !mute) {
+		ret = snd_soc_component_write(comp, 0xB9, 0x02);
+		if (ret)
+			return ret;
+
+		usleep_range(10000, 11000);
+
+		ret = snd_soc_component_write(comp, 0xA1, 0xF2);
+		if (ret)
+			return ret;
+
+		ret = snd_soc_component_write(comp, 0xA8, 0x00);
+		if (ret)
+			return ret;
+	}
+
 	ret = snd_soc_component_write_field(comp, RTQ9128_REG_DSP_EN, RTQ9128_MSMUTE_MASK,
 					    mute ? 1 : 0);
 	return ret < 0 ? ret : 0;