[PATCH 0/3] ASoC: codecs: rtq9128: Several application fixes
From: ChiYuan Huang cy_huang@richtek.com
This patch series fix several issues that comes from the real application.
ChiYuan Huang (3): ASoC: codecs: rtq9128: Fix string compare in DAPM event callback ASoC: codecs: rtq9128: Fix TDM enable and DAI format control flow ASoC: codecs: rtq9128: Fix TKA470B E1 version amp on sequence
sound/soc/codecs/rtq9128.c | 130 ++++++++++++++++++++++++++----------- 1 file changed, 93 insertions(+), 37 deletions(-)
base-commit: ca34c962d70ab42fb578a36103ba7b8bb01f1f9b
From: ChiYuan Huang cy_huang@richtek.com
Since widget name may concatenate the component prefix. To compare the the name with 'strcmp' function in shared DAPM event callback will cause the wrong RG field control. Use 'strstr' function, instead.
Signed-off-by: ChiYuan Huang cy_huang@richtek.com --- sound/soc/codecs/rtq9128.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/rtq9128.c b/sound/soc/codecs/rtq9128.c index 371d622c6214..8c1c3c65475e 100644 --- a/sound/soc/codecs/rtq9128.c +++ b/sound/soc/codecs/rtq9128.c @@ -291,11 +291,11 @@ static int rtq9128_dac_power_event(struct snd_soc_dapm_widget *w, struct snd_kco
dev_dbg(comp->dev, "%s: %s event %d\n", __func__, w->name, event);
- if (strcmp(w->name, "DAC1") == 0) + if (strstr(w->name, "DAC1")) shift = 6; - else if (strcmp(w->name, "DAC2") == 0) + else if (strstr(w->name, "DAC2")) shift = 4; - else if (strcmp(w->name, "DAC3") == 0) + else if (strstr(w->name, "DAC3")) shift = 2; else shift = 0;
On Fri, Oct 20, 2023 at 05:50:33PM +0800, cy_huang@richtek.com wrote:
From: ChiYuan Huang cy_huang@richtek.com
Since widget name may concatenate the component prefix. To compare the the name with 'strcmp' function in shared DAPM event callback will cause the wrong RG field control. Use 'strstr' function, instead.
Signed-off-by: ChiYuan Huang cy_huang@richtek.com
sound/soc/codecs/rtq9128.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/rtq9128.c b/sound/soc/codecs/rtq9128.c index 371d622c6214..8c1c3c65475e 100644 --- a/sound/soc/codecs/rtq9128.c +++ b/sound/soc/codecs/rtq9128.c @@ -291,11 +291,11 @@ static int rtq9128_dac_power_event(struct snd_soc_dapm_widget *w, struct snd_kco
dev_dbg(comp->dev, "%s: %s event %d\n", __func__, w->name, event);
- if (strcmp(w->name, "DAC1") == 0)
- if (strstr(w->name, "DAC1")) shift = 6;
- else if (strcmp(w->name, "DAC2") == 0)
- else if (strstr(w->name, "DAC2")) shift = 4;
- else if (strcmp(w->name, "DAC3") == 0)
- else if (strstr(w->name, "DAC3")) shift = 2; else shift = 0;
https://lore.kernel.org/lkml/20231023095428.166563-8-krzysztof.kozlowski@lin... Since the better change is applied. Please ignore this one.
Still wait the other patch(2&3)'s feedback.
Thanks.
-- 2.34.1
From: ChiYuan Huang cy_huang@richtek.com
To enable TDM mode, the current control flow limits the function calling order should be 'set_tdm_slot->set_dai_fmt'. But not all platform sound card like as simeple card to follow this design. To bypass this limit, adjust the DAI format setting in runtime 'hw_param' callback.
Signed-off-by: ChiYuan Huang cy_huang@richtek.com --- sound/soc/codecs/rtq9128.c | 67 ++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 31 deletions(-)
diff --git a/sound/soc/codecs/rtq9128.c b/sound/soc/codecs/rtq9128.c index 8c1c3c65475e..8a61a8a32db1 100644 --- a/sound/soc/codecs/rtq9128.c +++ b/sound/soc/codecs/rtq9128.c @@ -59,6 +59,7 @@
struct rtq9128_data { struct gpio_desc *enable; + unsigned int daifmt; int tdm_slots; int tdm_slot_width; bool tdm_input_data2_select; @@ -437,10 +438,7 @@ static const struct snd_soc_component_driver rtq9128_comp_driver = { static int rtq9128_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct rtq9128_data *data = snd_soc_dai_get_drvdata(dai); - struct snd_soc_component *comp = dai->component; struct device *dev = dai->dev; - unsigned int audfmt, fmtval; - int ret;
dev_dbg(dev, "%s: fmt 0x%8x\n", __func__, fmt);
@@ -450,35 +448,10 @@ static int rtq9128_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return -EINVAL; }
- fmtval = fmt & SND_SOC_DAIFMT_FORMAT_MASK; - if (data->tdm_slots && fmtval != SND_SOC_DAIFMT_DSP_A && fmtval != SND_SOC_DAIFMT_DSP_B) { - dev_err(dev, "TDM is used, format only support DSP_A or DSP_B\n"); - return -EINVAL; - } + /* Store here and will be used in runtime hw_params for DAI format setting */ + data->daifmt = fmt;
- switch (fmtval) { - case SND_SOC_DAIFMT_I2S: - audfmt = 8; - break; - case SND_SOC_DAIFMT_LEFT_J: - audfmt = 9; - break; - case SND_SOC_DAIFMT_RIGHT_J: - audfmt = 10; - break; - case SND_SOC_DAIFMT_DSP_A: - audfmt = data->tdm_slots ? 12 : 11; - break; - case SND_SOC_DAIFMT_DSP_B: - audfmt = data->tdm_slots ? 4 : 3; - break; - default: - dev_err(dev, "Unsupported format 0x%8x\n", fmt); - return -EINVAL; - } - - ret = snd_soc_component_write_field(comp, RTQ9128_REG_I2S_OPT, RTQ9128_AUDFMT_MASK, audfmt); - return ret < 0 ? ret : 0; + return 0; }
static int rtq9128_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, @@ -554,10 +527,38 @@ static int rtq9128_dai_hw_params(struct snd_pcm_substream *stream, struct snd_pc unsigned int width, slot_width, bitrate, audbit, dolen; struct snd_soc_component *comp = dai->component; struct device *dev = dai->dev; + unsigned int fmtval, audfmt; int ret;
dev_dbg(dev, "%s: width %d\n", __func__, params_width(param));
+ fmtval = FIELD_GET(SND_SOC_DAIFMT_FORMAT_MASK, data->daifmt); + if (data->tdm_slots && fmtval != SND_SOC_DAIFMT_DSP_A && fmtval != SND_SOC_DAIFMT_DSP_B) { + dev_err(dev, "TDM is used, format only support DSP_A or DSP_B\n"); + return -EINVAL; + } + + switch (fmtval) { + case SND_SOC_DAIFMT_I2S: + audfmt = 8; + break; + case SND_SOC_DAIFMT_LEFT_J: + audfmt = 9; + break; + case SND_SOC_DAIFMT_RIGHT_J: + audfmt = 10; + break; + case SND_SOC_DAIFMT_DSP_A: + audfmt = data->tdm_slots ? 12 : 11; + break; + case SND_SOC_DAIFMT_DSP_B: + audfmt = data->tdm_slots ? 4 : 3; + break; + default: + dev_err(dev, "Unsupported format 0x%8x\n", fmtval); + return -EINVAL; + } + switch (width = params_width(param)) { case 16: audbit = 0; @@ -611,6 +612,10 @@ static int rtq9128_dai_hw_params(struct snd_pcm_substream *stream, struct snd_pc return -EINVAL; }
+ ret = snd_soc_component_write_field(comp, RTQ9128_REG_I2S_OPT, RTQ9128_AUDFMT_MASK, audfmt); + if (ret < 0) + return ret; + ret = snd_soc_component_write_field(comp, RTQ9128_REG_I2S_OPT, RTQ9128_AUDBIT_MASK, audbit); if (ret < 0) return ret;
From: ChiYuan Huang cy_huang@richtek.com
For E1 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 --- Hi, Our E1 sample is evaluated by some end customer. Alghouth it's not the final MP version. But to be compatible with the engineering sample, this fix can solve the amp on issue. --- sound/soc/codecs/rtq9128.c | 57 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/rtq9128.c b/sound/soc/codecs/rtq9128.c index 8a61a8a32db1..5d75dc63492b 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; @@ -398,6 +431,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; @@ -626,12 +660,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;
participants (2)
-
ChiYuan Huang
-
cy_huang@richtek.com