[alsa-devel] [PATCH] ASoC: nau8825: reduce stanby power consumption
Fix unnecessary widget power up when standby; And decrease internal clock frequency to save power.
Signed-off-by: John Hsu KCHSU0@nuvoton.com --- sound/soc/codecs/nau8825.c | 49 +++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 14 deletions(-)
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 52882e4..f9752cc 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -262,6 +262,29 @@ static int nau8825_playback_event(struct snd_soc_dapm_widget *w, return 0; }
+static int nau8825_dacr_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_update_bits(nau8825->regmap, NAU8825_REG_ENA_CTRL, + NAU8825_ENABLE_DACR, NAU8825_ENABLE_DACR); + break; + case SND_SOC_DAPM_POST_PMD: + if (!nau8825->irq) + regmap_update_bits(nau8825->regmap, + NAU8825_REG_ENA_CTRL, NAU8825_ENABLE_DACR, 0); + break; + default: + return -EINVAL; + } + + return 0; +} +
static const char * const nau8825_adc_decimation[] = { "32", "64", "128", "256" @@ -337,16 +360,17 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = { 0),
/* ADC for button press detection */ - SND_SOC_DAPM_ADC("SAR", NULL, NAU8825_REG_SAR_CTRL, - NAU8825_SAR_ADC_EN_SFT, 0), + SND_SOC_DAPM_SUPPLY("SAR", NAU8825_REG_SAR_CTRL, + NAU8825_SAR_ADC_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_DAC("ADACL", NULL, NAU8825_REG_RDAC, 12, 0), SND_SOC_DAPM_DAC("ADACR", NULL, NAU8825_REG_RDAC, 13, 0), SND_SOC_DAPM_SUPPLY("ADACL Clock", NAU8825_REG_RDAC, 8, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ADACR Clock", NAU8825_REG_RDAC, 9, 0, NULL, 0),
- SND_SOC_DAPM_DAC("DDACR", NULL, NAU8825_REG_ENA_CTRL, - NAU8825_ENABLE_DACR_SFT, 0), + SND_SOC_DAPM_DAC_E("DDACR", NULL, SND_SOC_NOPM, 0, 0, + nau8825_dacr_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_DAC("DDACL", NULL, NAU8825_REG_ENA_CTRL, NAU8825_ENABLE_DACL_SFT, 0), SND_SOC_DAPM_SUPPLY("DDAC Clock", NAU8825_REG_ENA_CTRL, 6, 0, NULL, 0), @@ -878,13 +902,6 @@ static int nau8825_codec_probe(struct snd_soc_codec *codec)
nau8825->dapm = dapm;
- /* The interrupt clock is gated by x1[10:8], - * one of them needs to be enabled all the time for - * interrupts to happen. - */ - snd_soc_dapm_force_enable_pin(dapm, "DDACR"); - snd_soc_dapm_sync(dapm); - /* Unmask interruptions. Handler uses dapm object so we can enable * interruptions only after dapm is fully initialized. */ @@ -1075,6 +1092,12 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, NAU8825_DCO_EN); regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_VCO); + regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, + NAU8825_CLK_MCLK_SRC_MASK, 0xf); + regmap_update_bits(regmap, NAU8825_REG_FLL1, + NAU8825_FLL_RATIO_MASK, 0x10); + regmap_update_bits(regmap, NAU8825_REG_FLL6, + NAU8825_SDM_EN, NAU8825_SDM_EN); if (nau8825->mclk_freq) { clk_disable_unprepare(nau8825->mclk); nau8825->mclk_freq = 0; @@ -1309,9 +1332,7 @@ static int nau8825_setup_irq(struct nau8825 *nau8825) /* Enable internal VCO needed for interruptions */ nau8825_configure_sysclk(nau8825, NAU8825_CLK_INTERNAL, 0);
- /* Enable DDACR needed for interrupts - * It is the same as force_enable_pin("DDACR") we do later - */ + /* Enable DDACR needed for interrupts */ regmap_update_bits(regmap, NAU8825_REG_ENA_CTRL, NAU8825_ENABLE_DACR, NAU8825_ENABLE_DACR);
There is side effect at last patch. The playback has no sound with MCLK if internal clock frequency decreases. Thus, we need to recover frequency setting when MCLK case.
Signed-off-by: John Hsu KCHSU0@nuvoton.com --- sound/soc/codecs/nau8825.c | 51 +++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 14 deletions(-)
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 2e2e11a..b9bcb10 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -239,6 +239,29 @@ static int nau8825_pump_event(struct snd_soc_dapm_widget *w, return 0; }
+static int nau8825_dacr_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_update_bits(nau8825->regmap, NAU8825_REG_ENA_CTRL, + NAU8825_ENABLE_DACR, NAU8825_ENABLE_DACR); + break; + case SND_SOC_DAPM_POST_PMD: + if (!nau8825->irq) + regmap_update_bits(nau8825->regmap, + NAU8825_REG_ENA_CTRL, NAU8825_ENABLE_DACR, 0); + break; + default: + return -EINVAL; + } + + return 0; +} + static const char * const nau8825_adc_decimation[] = { "32", "64", "128", "256" }; @@ -313,16 +336,17 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = { 0),
/* ADC for button press detection */ - SND_SOC_DAPM_ADC("SAR", NULL, NAU8825_REG_SAR_CTRL, - NAU8825_SAR_ADC_EN_SFT, 0), + SND_SOC_DAPM_SUPPLY("SAR", NAU8825_REG_SAR_CTRL, + NAU8825_SAR_ADC_EN_SFT, 0, NULL, 0),
SND_SOC_DAPM_DAC("ADACL", NULL, NAU8825_REG_RDAC, 12, 0), SND_SOC_DAPM_DAC("ADACR", NULL, NAU8825_REG_RDAC, 13, 0), SND_SOC_DAPM_SUPPLY("ADACL Clock", NAU8825_REG_RDAC, 8, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ADACR Clock", NAU8825_REG_RDAC, 9, 0, NULL, 0),
- SND_SOC_DAPM_DAC("DDACR", NULL, NAU8825_REG_ENA_CTRL, - NAU8825_ENABLE_DACR_SFT, 0), + SND_SOC_DAPM_DAC_E("DDACR", NULL, SND_SOC_NOPM, 0, 0, + nau8825_dacr_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_DAC("DDACL", NULL, NAU8825_REG_ENA_CTRL, NAU8825_ENABLE_DACL_SFT, 0), SND_SOC_DAPM_SUPPLY("DDAC Clock", NAU8825_REG_ENA_CTRL, 6, 0, NULL, 0), @@ -845,13 +869,6 @@ static int nau8825_codec_probe(struct snd_soc_codec *codec)
nau8825->dapm = dapm;
- /* The interrupt clock is gated by x1[10:8], - * one of them needs to be enabled all the time for - * interrupts to happen. - */ - snd_soc_dapm_force_enable_pin(dapm, "DDACR"); - snd_soc_dapm_sync(dapm); - /* Unmask interruptions. Handler uses dapm object so we can enable * interruptions only after dapm is fully initialized. */ @@ -1032,6 +1049,8 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_MCLK); regmap_update_bits(regmap, NAU8825_REG_FLL6, NAU8825_DCO_EN, 0); + regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, + NAU8825_CLK_MCLK_SRC_MASK, 0); ret = nau8825_mclk_prepare(nau8825, freq); if (ret) return ret; @@ -1042,6 +1061,12 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id, NAU8825_DCO_EN); regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_VCO); + regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER, + NAU8825_CLK_MCLK_SRC_MASK, 0xf); + regmap_update_bits(regmap, NAU8825_REG_FLL1, + NAU8825_FLL_RATIO_MASK, 0x10); + regmap_update_bits(regmap, NAU8825_REG_FLL6, + NAU8825_SDM_EN, NAU8825_SDM_EN); if (nau8825->mclk_freq) { clk_disable_unprepare(nau8825->mclk); nau8825->mclk_freq = 0; @@ -1276,9 +1301,7 @@ static int nau8825_setup_irq(struct nau8825 *nau8825) /* Enable internal VCO needed for interruptions */ nau8825_configure_sysclk(nau8825, NAU8825_CLK_INTERNAL, 0);
- /* Enable DDACR needed for interrupts - * It is the same as force_enable_pin("DDACR") we do later - */ + /* Enable DDACR needed for interrupts */ regmap_update_bits(regmap, NAU8825_REG_ENA_CTRL, NAU8825_ENABLE_DACR, NAU8825_ENABLE_DACR);
Reduce pop noise in power up and down sequence when playback.
Signed-off-by: John Hsu KCHSU0@nuvoton.com --- sound/soc/codecs/nau8825.c | 200 +++++++++++++++++++++++++++++++++++++-------- sound/soc/codecs/nau8825.h | 14 ++++ 2 files changed, 180 insertions(+), 34 deletions(-)
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index b9bcb10..d270f63 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -84,6 +84,7 @@ static const struct nau8825_fll_attr fll_pre_scalar[] = {
static const struct reg_default nau8825_reg_defaults[] = { { NAU8825_REG_ENA_CTRL, 0x00ff }, + { NAU8825_REG_IIC_ADDR_SET, 0x0 }, { NAU8825_REG_CLK_DIVIDER, 0x0050 }, { NAU8825_REG_FLL1, 0x0 }, { NAU8825_REG_FLL2, 0x3126 }, @@ -158,8 +159,7 @@ static const struct reg_default nau8825_reg_defaults[] = { static bool nau8825_readable_reg(struct device *dev, unsigned int reg) { switch (reg) { - case NAU8825_REG_ENA_CTRL: - case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV: + case NAU8825_REG_ENA_CTRL ... NAU8825_REG_FLL_VCO_RSV: case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL: case NAU8825_REG_INTERRUPT_MASK ... NAU8825_REG_KEYDET_CTRL: case NAU8825_REG_VDET_THRESHOLD_1 ... NAU8825_REG_DACR_CTRL: @@ -184,8 +184,7 @@ static bool nau8825_readable_reg(struct device *dev, unsigned int reg) static bool nau8825_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { - case NAU8825_REG_RESET ... NAU8825_REG_ENA_CTRL: - case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV: + case NAU8825_REG_RESET ... NAU8825_REG_FLL_VCO_RSV: case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL: case NAU8825_REG_INTERRUPT_MASK: case NAU8825_REG_INT_CLR_KEY_STATUS ... NAU8825_REG_KEYDET_CTRL: @@ -227,10 +226,23 @@ static bool nau8825_volatile_reg(struct device *dev, unsigned int reg) static int nau8825_pump_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); + switch (event) { case SND_SOC_DAPM_POST_PMU: /* Prevent startup click by letting charge pump to ramp up */ msleep(10); + regmap_update_bits(nau8825->regmap, NAU8825_REG_CHARGE_PUMP, + NAU8825_JAMNODCLOW, NAU8825_JAMNODCLOW); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_update_bits(nau8825->regmap, NAU8825_REG_CLASSG_CTRL, + NAU8825_CLASSG_EN, 0); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(nau8825->regmap, NAU8825_REG_BOOST, + NAU8825_HP_BOOST_DIS, 0); break; default: return -EINVAL; @@ -239,6 +251,47 @@ static int nau8825_pump_event(struct snd_soc_dapm_widget *w, return 0; }
+static int nau8825_playback_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + regmap_update_bits(nau8825->regmap, NAU8825_REG_HSD_CTRL, + NAU8825_SPKR_DWN1R | NAU8825_SPKR_DWN1L, + NAU8825_SPKR_DWN1R | NAU8825_SPKR_DWN1L); + regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, + NAU8825_BIAS_TESTDAC_EN, NAU8825_BIAS_TESTDAC_EN); + regmap_update_bits(nau8825->regmap, NAU8825_REG_BOOST, + NAU8825_HP_BOOST_DIS, NAU8825_HP_BOOST_DIS); + break; + case SND_SOC_DAPM_POST_PMU: + regmap_update_bits(nau8825->regmap, NAU8825_REG_HSD_CTRL, + NAU8825_SPKR_DWN1R | NAU8825_SPKR_DWN1L, 0); + regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, + NAU8825_BIAS_TESTDAC_EN, 0); + regmap_update_bits(nau8825->regmap, NAU8825_REG_BOOST, + NAU8825_HP_BOOST_DIS, 0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_update_bits(nau8825->regmap, NAU8825_REG_BOOST, + NAU8825_HP_BOOST_DIS, NAU8825_HP_BOOST_DIS); + regmap_update_bits(nau8825->regmap, NAU8825_REG_HSD_CTRL, + NAU8825_SPKR_DWN1R | NAU8825_SPKR_DWN1L, + NAU8825_SPKR_DWN1R | NAU8825_SPKR_DWN1L); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(nau8825->regmap, NAU8825_REG_BOOST, + NAU8825_HP_BOOST_DIS, 0); + break; + default: + return -EINVAL; + } + return 0; +} + static int nau8825_dacr_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -262,6 +315,54 @@ static int nau8825_dacr_event(struct snd_soc_dapm_widget *w, return 0; }
+static int nau8825_output_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, + NAU8825_BIAS_TESTDAC_EN, 0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_update_bits(nau8825->regmap, NAU8825_REG_BOOST, + NAU8825_HP_BOOST_DIS, NAU8825_HP_BOOST_DIS); + regmap_update_bits(nau8825->regmap, NAU8825_REG_CHARGE_PUMP, + NAU8825_JAMNODCLOW, 0); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int nau8825_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_update_bits(nau8825->regmap, NAU8825_REG_HSD_CTRL, + NAU8825_SPKR_DWN1R | NAU8825_SPKR_DWN1L, 0); + regmap_update_bits(nau8825->regmap, NAU8825_REG_BOOST, + NAU8825_HP_BOOST_DIS, 0); + regmap_update_bits(nau8825->regmap, NAU8825_REG_CLASSG_CTRL, + NAU8825_CLASSG_EN, NAU8825_CLASSG_EN); + break; + case SND_SOC_DAPM_PRE_PMD: + break; + default: + return -EINVAL; + } + + return 0; +} + static const char * const nau8825_adc_decimation[] = { "32", "64", "128", "256" }; @@ -339,10 +440,10 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SAR", NAU8825_REG_SAR_CTRL, NAU8825_SAR_ADC_EN_SFT, 0, NULL, 0),
- SND_SOC_DAPM_DAC("ADACL", NULL, NAU8825_REG_RDAC, 12, 0), - SND_SOC_DAPM_DAC("ADACR", NULL, NAU8825_REG_RDAC, 13, 0), - SND_SOC_DAPM_SUPPLY("ADACL Clock", NAU8825_REG_RDAC, 8, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("ADACR Clock", NAU8825_REG_RDAC, 9, 0, NULL, 0), + SND_SOC_DAPM_PGA_S("ADACL", 2, NAU8825_REG_RDAC, 12, 0, NULL, 0), + SND_SOC_DAPM_PGA_S("ADACR", 2, NAU8825_REG_RDAC, 13, 0, NULL, 0), + SND_SOC_DAPM_PGA_S("ADACL Clock", 3, NAU8825_REG_RDAC, 8, 0, NULL, 0), + SND_SOC_DAPM_PGA_S("ADACR Clock", 3, NAU8825_REG_RDAC, 9, 0, NULL, 0),
SND_SOC_DAPM_DAC_E("DDACR", NULL, SND_SOC_NOPM, 0, 0, nau8825_dacr_event, SND_SOC_DAPM_POST_PMU | @@ -354,32 +455,40 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = { SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacl_mux), SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacr_mux),
- SND_SOC_DAPM_PGA("HP amp L", NAU8825_REG_CLASSG_CTRL, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("HP amp R", NAU8825_REG_CLASSG_CTRL, 2, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("HP amp power", NAU8825_REG_CLASSG_CTRL, 0, 0, NULL, - 0), + SND_SOC_DAPM_PGA_S("HP amp L", 0, + NAU8825_REG_CLASSG_CTRL, 1, 0, NULL, 0), + SND_SOC_DAPM_PGA_S("HP amp R", 0, + NAU8825_REG_CLASSG_CTRL, 2, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("Charge Pump", NAU8825_REG_CHARGE_PUMP, 5, 0, - nau8825_pump_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_PGA_S("Charge Pump", 1, NAU8825_REG_CHARGE_PUMP, 5, 0, + nau8825_pump_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_PGA("Output Driver R Stage 1", + SND_SOC_DAPM_PGA_S("Output Driver R Stage 1", 4, NAU8825_REG_POWER_UP_CONTROL, 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("Output Driver L Stage 1", + SND_SOC_DAPM_PGA_S("Output Driver L Stage 1", 4, NAU8825_REG_POWER_UP_CONTROL, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("Output Driver R Stage 2", + SND_SOC_DAPM_PGA_S("Output Driver R Stage 2", 5, NAU8825_REG_POWER_UP_CONTROL, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("Output Driver L Stage 2", + SND_SOC_DAPM_PGA_S("Output Driver L Stage 2", 5, NAU8825_REG_POWER_UP_CONTROL, 2, 0, NULL, 0), - SND_SOC_DAPM_PGA_S("Output Driver R Stage 3", 1, + SND_SOC_DAPM_PGA_S("Output Driver R Stage 3", 6, NAU8825_REG_POWER_UP_CONTROL, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA_S("Output Driver L Stage 3", 1, + SND_SOC_DAPM_PGA_S("Output Driver L Stage 3", 6, NAU8825_REG_POWER_UP_CONTROL, 0, 0, NULL, 0),
- SND_SOC_DAPM_PGA_S("Output DACL", 2, NAU8825_REG_CHARGE_PUMP, 8, 1, NULL, 0), - SND_SOC_DAPM_PGA_S("Output DACR", 2, NAU8825_REG_CHARGE_PUMP, 9, 1, NULL, 0), + SND_SOC_DAPM_PGA_S("Output DACL", 7, + NAU8825_REG_CHARGE_PUMP, 8, 1, nau8825_output_dac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PGA_S("Output DACR", 7, + NAU8825_REG_CHARGE_PUMP, 9, 1, nau8825_output_dac_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_HP("HPOL", nau8825_hp_event), + SND_SOC_DAPM_HP("HPOR", nau8825_hp_event),
- SND_SOC_DAPM_OUTPUT("HPOL"), - SND_SOC_DAPM_OUTPUT("HPOR"), + SND_SOC_DAPM_PRE("Pre Playback", nau8825_playback_event), + SND_SOC_DAPM_POST("Post Playback", nau8825_playback_event), };
static const struct snd_soc_dapm_route nau8825_dapm_routes[] = { @@ -399,14 +508,14 @@ static const struct snd_soc_dapm_route nau8825_dapm_routes[] = { {"DACR Mux", "DACR", "DDACR"}, {"HP amp L", NULL, "DACL Mux"}, {"HP amp R", NULL, "DACR Mux"}, - {"HP amp L", NULL, "HP amp power"}, - {"HP amp R", NULL, "HP amp power"}, - {"ADACL", NULL, "HP amp L"}, - {"ADACR", NULL, "HP amp R"}, - {"ADACL", NULL, "ADACL Clock"}, - {"ADACR", NULL, "ADACR Clock"}, - {"Output Driver L Stage 1", NULL, "ADACL"}, - {"Output Driver R Stage 1", NULL, "ADACR"}, + {"Charge Pump", NULL, "HP amp L"}, + {"Charge Pump", NULL, "HP amp R"}, + {"ADACL", NULL, "Charge Pump"}, + {"ADACR", NULL, "Charge Pump"}, + {"ADACL Clock", NULL, "ADACL"}, + {"ADACR Clock", NULL, "ADACR"}, + {"Output Driver L Stage 1", NULL, "ADACL Clock"}, + {"Output Driver R Stage 1", NULL, "ADACR Clock"}, {"Output Driver L Stage 2", NULL, "Output Driver L Stage 1"}, {"Output Driver R Stage 2", NULL, "Output Driver R Stage 1"}, {"Output Driver L Stage 3", NULL, "Output Driver L Stage 2"}, @@ -415,8 +524,6 @@ static const struct snd_soc_dapm_route nau8825_dapm_routes[] = { {"Output DACR", NULL, "Output Driver R Stage 3"}, {"HPOL", NULL, "Output DACL"}, {"HPOR", NULL, "Output DACR"}, - {"HPOL", NULL, "Charge Pump"}, - {"HPOR", NULL, "Charge Pump"}, };
static int nau8825_hw_params(struct snd_pcm_substream *substream, @@ -792,6 +899,8 @@ static void nau8825_init_regs(struct nau8825 *nau8825) { struct regmap *regmap = nau8825->regmap;
+ /* Latch IIC LSB value */ + regmap_write(regmap, NAU8825_REG_IIC_ADDR_SET, 0x0001); /* Enable Bias/Vmid */ regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, NAU8825_BIAS_VMID, NAU8825_BIAS_VMID); @@ -846,6 +955,29 @@ static void nau8825_init_regs(struct nau8825 *nau8825) NAU8825_ADC_SYNC_DOWN_MASK, NAU8825_ADC_SYNC_DOWN_128); regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1, NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_128); + /* Disable DACR/L power */ + regmap_update_bits(regmap, NAU8825_REG_CHARGE_PUMP, + NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL, + NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL); + /* CICCLP off */ + regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1, + NAU8825_DAC_CLIP_OFF, NAU8825_DAC_CLIP_OFF); + + /* Class AB bias current to 2x, DAC Capacitor enable MSB/LSB */ + regmap_update_bits(regmap, NAU8825_REG_ANALOG_CONTROL_2, + NAU8825_HP_NON_CLASSG_CURRENT_2xADJ | + NAU8825_DAC_CAPACITOR_MSB | NAU8825_DAC_CAPACITOR_LSB, + NAU8825_HP_NON_CLASSG_CURRENT_2xADJ | + NAU8825_DAC_CAPACITOR_MSB | NAU8825_DAC_CAPACITOR_LSB); + /* Class G timer 64ms */ + regmap_update_bits(regmap, NAU8825_REG_CLASSG_CTRL, + NAU8825_CLASSG_TIMER_MASK, + 0x20 << NAU8825_CLASSG_TIMER_SFT); + /* DAC clock delay 2ns, VREF */ + regmap_update_bits(regmap, NAU8825_REG_RDAC, + NAU8825_RDAC_CLK_DELAY_MASK | NAU8825_RDAC_VREF_MASK, + (0x2 << NAU8825_RDAC_CLK_DELAY_SFT) | + (0x3 << NAU8825_RDAC_VREF_SFT)); }
static const struct regmap_config nau8825_regmap_config = { diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h index 8237693..029134a 100644 --- a/sound/soc/codecs/nau8825.h +++ b/sound/soc/codecs/nau8825.h @@ -14,6 +14,7 @@
#define NAU8825_REG_RESET 0x00 #define NAU8825_REG_ENA_CTRL 0x01 +#define NAU8825_REG_IIC_ADDR_SET 0x02 #define NAU8825_REG_CLK_DIVIDER 0x03 #define NAU8825_REG_FLL1 0x04 #define NAU8825_REG_FLL2 0x05 @@ -259,12 +260,18 @@ /* DACR_CTRL (0x34) */ #define NAU8825_DACR_CH_SEL_SFT 9
+/* CLASSG_CTRL (0x50) */ +#define NAU8825_CLASSG_TIMER_SFT 8 +#define NAU8825_CLASSG_TIMER_MASK (0x3f << NAU8825_CLASSG_TIMER_SFT) +#define NAU8825_CLASSG_EN (1 << 0) + /* I2C_DEVICE_ID (0x58) */ #define NAU8825_GPIO2JD1 (1 << 7) #define NAU8825_SOFTWARE_ID_MASK 0x3 #define NAU8825_SOFTWARE_ID_NAU8825 0x0
/* BIAS_ADJ (0x66) */ +#define NAU8825_BIAS_TESTDAC_EN (0x3 << 8) #define NAU8825_BIAS_VMID (1 << 6) #define NAU8825_BIAS_VMID_SEL_SFT 4 #define NAU8825_BIAS_VMID_SEL_MASK (3 << NAU8825_BIAS_VMID_SEL_SFT) @@ -282,6 +289,12 @@ #define NAU8825_ADC_VREFSEL_VMID_PLUS_1DB (3 << 8) #define NAU8825_POWERUP_ADCL (1 << 6)
+/* RDAC (0x73) */ +#define NAU8825_RDAC_CLK_DELAY_SFT 4 +#define NAU8825_RDAC_CLK_DELAY_MASK (0x7 << NAU8825_RDAC_CLK_DELAY_SFT) +#define NAU8825_RDAC_VREF_SFT 2 +#define NAU8825_RDAC_VREF_MASK (0x3 << NAU8825_RDAC_VREF_SFT) + /* MIC_BIAS (0x74) */ #define NAU8825_MICBIAS_JKSLV (1 << 14) #define NAU8825_MICBIAS_JKR2 (1 << 12) @@ -292,6 +305,7 @@ /* BOOST (0x76) */ #define NAU8825_PRECHARGE_DIS (1 << 13) #define NAU8825_GLOBAL_BIAS_EN (1 << 12) +#define NAU8825_HP_BOOST_DIS (1 << 9) #define NAU8825_HP_BOOST_G_DIS (1 << 8) #define NAU8825_SHORT_SHUTDOWN_EN (1 << 6)
On Fri, Feb 05, 2016 at 04:32:45PM +0800, John Hsu wrote:
switch (event) { case SND_SOC_DAPM_POST_PMU: /* Prevent startup click by letting charge pump to ramp up */ msleep(10);
regmap_update_bits(nau8825->regmap, NAU8825_REG_CHARGE_PUMP,
NAU8825_JAMNODCLOW, NAU8825_JAMNODCLOW);
break;
- case SND_SOC_DAPM_PRE_PMD:
regmap_update_bits(nau8825->regmap, NAU8825_REG_CLASSG_CTRL,
NAU8825_CLASSG_EN, 0);
break;
- case SND_SOC_DAPM_POST_PMD:
regmap_update_bits(nau8825->regmap, NAU8825_REG_BOOST,
break;NAU8825_HP_BOOST_DIS, 0);
This is really hard to follow, the enables and disables here don't match up (I see that at least some of these are handled by other widgets on the other path). I at least need some words explaining what the intended effect of the change is.
Hi,
On 2/9/2016 12:52 AM, Mark Brown wrote:
On Fri, Feb 05, 2016 at 04:32:45PM +0800, John Hsu wrote:
switch (event) { case SND_SOC_DAPM_POST_PMU: /* Prevent startup click by letting charge pump to ramp up */ msleep(10);
regmap_update_bits(nau8825->regmap, NAU8825_REG_CHARGE_PUMP,
NAU8825_JAMNODCLOW, NAU8825_JAMNODCLOW);
break;
- case SND_SOC_DAPM_PRE_PMD:
regmap_update_bits(nau8825->regmap, NAU8825_REG_CLASSG_CTRL,
NAU8825_CLASSG_EN, 0);
break;
- case SND_SOC_DAPM_POST_PMD:
regmap_update_bits(nau8825->regmap, NAU8825_REG_BOOST,
break;NAU8825_HP_BOOST_DIS, 0);
This is really hard to follow, the enables and disables here don't match up (I see that at least some of these are handled by other widgets on the other path). I at least need some words explaining what the intended effect of the change is.
OK, we can arrange it again to avoid the configuration overlap. It's no problem to add more explaining.
On Tue, Feb 02, 2016 at 11:18:14AM +0800, John Hsu wrote:
There is side effect at last patch. The playback has no sound with MCLK if internal clock frequency decreases. Thus, we need to recover frequency setting when MCLK case.
This doesn't apply against current code, please check and resend.
participants (2)
-
John Hsu
-
Mark Brown