2019-11-28 09:41:38

by Nikita Yushchenko

[permalink] [raw]
Subject: [PATCH] ASoC: tlv320aic31xx: Add HP output driver pop reduction controls

HP output driver has two parameters that can be configured to reduce
pop noise: power-on delay and ramp-up step time. Two new kcontrols
have been added to set these parameters.

Signed-off-by: Nikita Yushchenko <[email protected]>
---
sound/soc/codecs/tlv320aic31xx.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 67323188afd2..740e75032f36 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -263,6 +263,19 @@ static SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text);
static SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4,
mic_select_text);

+static const char * const hp_poweron_time_text[] = {
+ "0us", "15.3us", "153us", "1.53ms", "15.3ms", "76.2ms",
+ "153ms", "304ms", "610ms", "1.22s", "3.04s", "6.1s" };
+
+static SOC_ENUM_SINGLE_DECL(hp_poweron_time_enum, AIC31XX_HPPOP, 3,
+ hp_poweron_time_text);
+
+static const char * const hp_rampup_step_text[] = {
+ "0ms", "0.98ms", "1.95ms", "3.9ms" };
+
+static SOC_ENUM_SINGLE_DECL(hp_rampup_step_enum, AIC31XX_HPPOP, 1,
+ hp_rampup_step_text);
+
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0);
static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0);
static const DECLARE_TLV_DB_SCALE(adc_cgain_tlv, -2000, 50, 0);
@@ -286,6 +299,9 @@ static const struct snd_kcontrol_new common31xx_snd_controls[] = {

SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL,
AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv),
+
+ SOC_ENUM("HP Output Driver Power-On time", hp_poweron_time_enum),
+ SOC_ENUM("HP Output Driver Ramp-up step", hp_rampup_step_enum),
};

static const struct snd_kcontrol_new aic31xx_snd_controls[] = {
--
2.20.1


2019-11-28 12:15:22

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH] ASoC: tlv320aic31xx: Add HP output driver pop reduction controls

On Thu, Nov 28, 2019 at 12:39:55PM +0300, Nikita Yushchenko wrote:

> +static const char * const hp_poweron_time_text[] = {
> + "0us", "15.3us", "153us", "1.53ms", "15.3ms", "76.2ms",
> + "153ms", "304ms", "610ms", "1.22s", "3.04s", "6.1s" };
> +
> +static SOC_ENUM_SINGLE_DECL(hp_poweron_time_enum, AIC31XX_HPPOP, 3,
> + hp_poweron_time_text);
> +
> +static const char * const hp_rampup_step_text[] = {
> + "0ms", "0.98ms", "1.95ms", "3.9ms" };
> +
> +static SOC_ENUM_SINGLE_DECL(hp_rampup_step_enum, AIC31XX_HPPOP, 1,
> + hp_rampup_step_text);

I'm not seeing any integration with DAPM here, I'd expect to see that so
we don't cut off the start of audio especially with the longer times
available (which I'm frankly not sure are seriously usable).


Attachments:
(No filename) (768.00 B)
signature.asc (499.00 B)
Download all attachments

2019-11-28 12:24:34

by Nikita Yushchenko

[permalink] [raw]
Subject: Re: [PATCH] ASoC: tlv320aic31xx: Add HP output driver pop reduction controls

>> +static const char * const hp_poweron_time_text[] = {
>> + "0us", "15.3us", "153us", "1.53ms", "15.3ms", "76.2ms",
>> + "153ms", "304ms", "610ms", "1.22s", "3.04s", "6.1s" };
>> +
>> +static SOC_ENUM_SINGLE_DECL(hp_poweron_time_enum, AIC31XX_HPPOP, 3,
>> + hp_poweron_time_text);
>> +
>> +static const char * const hp_rampup_step_text[] = {
>> + "0ms", "0.98ms", "1.95ms", "3.9ms" };
>> +
>> +static SOC_ENUM_SINGLE_DECL(hp_rampup_step_enum, AIC31XX_HPPOP, 1,
>> + hp_rampup_step_text);
>
> I'm not seeing any integration with DAPM here, I'd expect to see that so
> we don't cut off the start of audio especially with the longer times
> available (which I'm frankly not sure are seriously usable).

I believe driver already has that integration, there is aic31xx_dapm_power_event() that is called on
DAPM events, and polls state in register bits waiting for operation to complete.

Btw, the default setting for register fields in question is "304ms" / "3.9ms" thus some delay is already
there. This patch just makes it explicitly controllable by those who wait it.

2019-11-28 12:26:03

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH] ASoC: tlv320aic31xx: Add HP output driver pop reduction controls

On Thu, Nov 28, 2019 at 03:19:38PM +0300, Nikita Yushchenko wrote:

> > I'm not seeing any integration with DAPM here, I'd expect to see that so
> > we don't cut off the start of audio especially with the longer times
> > available (which I'm frankly not sure are seriously usable).

> I believe driver already has that integration, there is
> aic31xx_dapm_power_event() that is called on DAPM events, and polls state in
> register bits waiting for operation to complete.

> Btw, the default setting for register fields in question is "304ms" /
> "3.9ms" thus some delay is already there. This patch just makes it
> explicitly controllable by those who wait it.

Can you confirm that this does take effect (should be easy with the
longer delays) and put a comment in indicating that please in case
someone is cut'n'pasting?


Attachments:
(No filename) (841.00 B)
signature.asc (499.00 B)
Download all attachments

2019-11-28 13:56:29

by Nikita Yushchenko

[permalink] [raw]
Subject: [PATCH v2] ASoC: tlv320aic31xx: Add HP output driver pop reduction controls

HP output driver has two parameters that can be configured to reduce
pop noise: power-on delay and ramp-up step time. Two new kcontrols
have been added to set these parameters.

Also have to alter timeout in aic31xx_dapm_power_event() because default
timeout does fire when higher supported power-on delay are configured.

Signed-off-by: Nikita Yushchenko <[email protected]>
---
sound/soc/codecs/tlv320aic31xx.c | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index f6f19fdc72f5..d6c462f21370 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -262,6 +262,19 @@ static SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2,
static SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4,
mic_select_text);

+static const char * const hp_poweron_time_text[] = {
+ "0us", "15.3us", "153us", "1.53ms", "15.3ms", "76.2ms",
+ "153ms", "304ms", "610ms", "1.22s", "3.04s", "6.1s" };
+
+static SOC_ENUM_SINGLE_DECL(hp_poweron_time_enum, AIC31XX_HPPOP, 3,
+ hp_poweron_time_text);
+
+static const char * const hp_rampup_step_text[] = {
+ "0ms", "0.98ms", "1.95ms", "3.9ms" };
+
+static SOC_ENUM_SINGLE_DECL(hp_rampup_step_enum, AIC31XX_HPPOP, 1,
+ hp_rampup_step_text);
+
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0);
static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0);
static const DECLARE_TLV_DB_SCALE(adc_cgain_tlv, -2000, 50, 0);
@@ -285,6 +298,14 @@ static const struct snd_kcontrol_new common31xx_snd_controls[] = {

SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL,
AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv),
+
+ /* HP de-pop control: apply power not immediately but via ramp
+ * function with these psarameters. Note that power up sequence
+ * has to wait for this to complete; this is implemented by
+ * polling HP driver status in aic31xx_dapm_power_event()
+ */
+ SOC_ENUM("HP Output Driver Power-On time", hp_poweron_time_enum),
+ SOC_ENUM("HP Output Driver Ramp-up step", hp_rampup_step_enum),
};

static const struct snd_kcontrol_new aic31xx_snd_controls[] = {
@@ -357,6 +378,7 @@ static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w,
struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
unsigned int reg = AIC31XX_DACFLAG1;
unsigned int mask;
+ unsigned int timeout = 500 * USEC_PER_MSEC;

switch (WIDGET_BIT(w->reg, w->shift)) {
case WIDGET_BIT(AIC31XX_DACSETUP, 7):
@@ -367,9 +389,13 @@ static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w,
break;
case WIDGET_BIT(AIC31XX_HPDRIVER, 7):
mask = AIC31XX_HPLDRVPWRSTATUS_MASK;
+ if (event == SND_SOC_DAPM_POST_PMU)
+ timeout = 7 * USEC_PER_SEC;
break;
case WIDGET_BIT(AIC31XX_HPDRIVER, 6):
mask = AIC31XX_HPRDRVPWRSTATUS_MASK;
+ if (event == SND_SOC_DAPM_POST_PMU)
+ timeout = 7 * USEC_PER_SEC;
break;
case WIDGET_BIT(AIC31XX_SPKAMP, 7):
mask = AIC31XX_SPLDRVPWRSTATUS_MASK;
@@ -389,9 +415,11 @@ static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w,

switch (event) {
case SND_SOC_DAPM_POST_PMU:
- return aic31xx_wait_bits(aic31xx, reg, mask, mask, 5000, 100);
+ return aic31xx_wait_bits(aic31xx, reg, mask, mask,
+ 5000, timeout / 5000);
case SND_SOC_DAPM_POST_PMD:
- return aic31xx_wait_bits(aic31xx, reg, mask, 0, 5000, 100);
+ return aic31xx_wait_bits(aic31xx, reg, mask, 0,
+ 5000, timeout / 5000);
default:
dev_dbg(component->dev,
"Unhandled dapm widget event %d from %s\n",
--
2.20.1