Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: nau8825: fix issue that pop noise when start playback

Reduce pop noise in power up and down sequence when playback.
The DAPM widgets graph is reconstructed to ensure the
register write sequence at playback matches exactly to the
v5 clickless sequence provided by Nuvoton.

Signed-off-by: John Hsu <KCHSU0@nuvoton.com>
Signed-off-by: Ben Zhang <benzh@chromium.org>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

John Hsu and committed by
Mark Brown
45d5eb3a 92e963f5

+141 -44
+126 -43
sound/soc/codecs/nau8825.c
··· 84 84 85 85 static const struct reg_default nau8825_reg_defaults[] = { 86 86 { NAU8825_REG_ENA_CTRL, 0x00ff }, 87 + { NAU8825_REG_IIC_ADDR_SET, 0x0 }, 87 88 { NAU8825_REG_CLK_DIVIDER, 0x0050 }, 88 89 { NAU8825_REG_FLL1, 0x0 }, 89 90 { NAU8825_REG_FLL2, 0x3126 }, ··· 159 158 static bool nau8825_readable_reg(struct device *dev, unsigned int reg) 160 159 { 161 160 switch (reg) { 162 - case NAU8825_REG_ENA_CTRL: 163 - case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV: 161 + case NAU8825_REG_ENA_CTRL ... NAU8825_REG_FLL_VCO_RSV: 164 162 case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL: 165 163 case NAU8825_REG_INTERRUPT_MASK ... NAU8825_REG_KEYDET_CTRL: 166 164 case NAU8825_REG_VDET_THRESHOLD_1 ... NAU8825_REG_DACR_CTRL: ··· 184 184 static bool nau8825_writeable_reg(struct device *dev, unsigned int reg) 185 185 { 186 186 switch (reg) { 187 - case NAU8825_REG_RESET ... NAU8825_REG_ENA_CTRL: 188 - case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV: 187 + case NAU8825_REG_RESET ... NAU8825_REG_FLL_VCO_RSV: 189 188 case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL: 190 189 case NAU8825_REG_INTERRUPT_MASK: 191 190 case NAU8825_REG_INT_CLR_KEY_STATUS ... NAU8825_REG_KEYDET_CTRL: ··· 226 227 static int nau8825_pump_event(struct snd_soc_dapm_widget *w, 227 228 struct snd_kcontrol *kcontrol, int event) 228 229 { 230 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 231 + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 232 + 229 233 switch (event) { 230 234 case SND_SOC_DAPM_POST_PMU: 231 235 /* Prevent startup click by letting charge pump to ramp up */ 232 236 msleep(10); 237 + regmap_update_bits(nau8825->regmap, NAU8825_REG_CHARGE_PUMP, 238 + NAU8825_JAMNODCLOW, NAU8825_JAMNODCLOW); 239 + break; 240 + case SND_SOC_DAPM_PRE_PMD: 241 + regmap_update_bits(nau8825->regmap, NAU8825_REG_CHARGE_PUMP, 242 + NAU8825_JAMNODCLOW, 0); 243 + break; 244 + default: 245 + return -EINVAL; 246 + } 247 + 248 + return 0; 249 + } 250 + 251 + static int nau8825_output_dac_event(struct snd_soc_dapm_widget *w, 252 + struct snd_kcontrol *kcontrol, int event) 253 + { 254 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 255 + struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); 256 + 257 + switch (event) { 258 + case SND_SOC_DAPM_PRE_PMU: 259 + /* Disables the TESTDAC to let DAC signal pass through. */ 260 + regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, 261 + NAU8825_BIAS_TESTDAC_EN, 0); 262 + break; 263 + case SND_SOC_DAPM_POST_PMD: 264 + regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, 265 + NAU8825_BIAS_TESTDAC_EN, NAU8825_BIAS_TESTDAC_EN); 233 266 break; 234 267 default: 235 268 return -EINVAL; ··· 347 316 SND_SOC_DAPM_ADC("SAR", NULL, NAU8825_REG_SAR_CTRL, 348 317 NAU8825_SAR_ADC_EN_SFT, 0), 349 318 350 - SND_SOC_DAPM_DAC("ADACL", NULL, NAU8825_REG_RDAC, 12, 0), 351 - SND_SOC_DAPM_DAC("ADACR", NULL, NAU8825_REG_RDAC, 13, 0), 352 - SND_SOC_DAPM_SUPPLY("ADACL Clock", NAU8825_REG_RDAC, 8, 0, NULL, 0), 353 - SND_SOC_DAPM_SUPPLY("ADACR Clock", NAU8825_REG_RDAC, 9, 0, NULL, 0), 319 + SND_SOC_DAPM_PGA_S("ADACL", 2, NAU8825_REG_RDAC, 12, 0, NULL, 0), 320 + SND_SOC_DAPM_PGA_S("ADACR", 2, NAU8825_REG_RDAC, 13, 0, NULL, 0), 321 + SND_SOC_DAPM_PGA_S("ADACL Clock", 3, NAU8825_REG_RDAC, 8, 0, NULL, 0), 322 + SND_SOC_DAPM_PGA_S("ADACR Clock", 3, NAU8825_REG_RDAC, 9, 0, NULL, 0), 354 323 355 324 SND_SOC_DAPM_DAC("DDACR", NULL, NAU8825_REG_ENA_CTRL, 356 325 NAU8825_ENABLE_DACR_SFT, 0), ··· 361 330 SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacl_mux), 362 331 SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacr_mux), 363 332 364 - SND_SOC_DAPM_PGA("HP amp L", NAU8825_REG_CLASSG_CTRL, 1, 0, NULL, 0), 365 - SND_SOC_DAPM_PGA("HP amp R", NAU8825_REG_CLASSG_CTRL, 2, 0, NULL, 0), 366 - SND_SOC_DAPM_SUPPLY("HP amp power", NAU8825_REG_CLASSG_CTRL, 0, 0, NULL, 367 - 0), 333 + SND_SOC_DAPM_PGA_S("HP amp L", 0, 334 + NAU8825_REG_CLASSG_CTRL, 1, 0, NULL, 0), 335 + SND_SOC_DAPM_PGA_S("HP amp R", 0, 336 + NAU8825_REG_CLASSG_CTRL, 2, 0, NULL, 0), 368 337 369 - SND_SOC_DAPM_SUPPLY("Charge Pump", NAU8825_REG_CHARGE_PUMP, 5, 0, 370 - nau8825_pump_event, SND_SOC_DAPM_POST_PMU), 338 + SND_SOC_DAPM_PGA_S("Charge Pump", 1, NAU8825_REG_CHARGE_PUMP, 5, 0, 339 + nau8825_pump_event, SND_SOC_DAPM_POST_PMU | 340 + SND_SOC_DAPM_PRE_PMD), 371 341 372 - SND_SOC_DAPM_PGA("Output Driver R Stage 1", 342 + SND_SOC_DAPM_PGA_S("Output Driver R Stage 1", 4, 373 343 NAU8825_REG_POWER_UP_CONTROL, 5, 0, NULL, 0), 374 - SND_SOC_DAPM_PGA("Output Driver L Stage 1", 344 + SND_SOC_DAPM_PGA_S("Output Driver L Stage 1", 4, 375 345 NAU8825_REG_POWER_UP_CONTROL, 4, 0, NULL, 0), 376 - SND_SOC_DAPM_PGA("Output Driver R Stage 2", 346 + SND_SOC_DAPM_PGA_S("Output Driver R Stage 2", 5, 377 347 NAU8825_REG_POWER_UP_CONTROL, 3, 0, NULL, 0), 378 - SND_SOC_DAPM_PGA("Output Driver L Stage 2", 348 + SND_SOC_DAPM_PGA_S("Output Driver L Stage 2", 5, 379 349 NAU8825_REG_POWER_UP_CONTROL, 2, 0, NULL, 0), 380 - SND_SOC_DAPM_PGA_S("Output Driver R Stage 3", 1, 350 + SND_SOC_DAPM_PGA_S("Output Driver R Stage 3", 6, 381 351 NAU8825_REG_POWER_UP_CONTROL, 1, 0, NULL, 0), 382 - SND_SOC_DAPM_PGA_S("Output Driver L Stage 3", 1, 352 + SND_SOC_DAPM_PGA_S("Output Driver L Stage 3", 6, 383 353 NAU8825_REG_POWER_UP_CONTROL, 0, 0, NULL, 0), 384 354 385 - SND_SOC_DAPM_PGA_S("Output DACL", 2, NAU8825_REG_CHARGE_PUMP, 8, 1, NULL, 0), 386 - SND_SOC_DAPM_PGA_S("Output DACR", 2, NAU8825_REG_CHARGE_PUMP, 9, 1, NULL, 0), 355 + SND_SOC_DAPM_PGA_S("Output DACL", 7, 356 + NAU8825_REG_CHARGE_PUMP, 8, 1, nau8825_output_dac_event, 357 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 358 + SND_SOC_DAPM_PGA_S("Output DACR", 7, 359 + NAU8825_REG_CHARGE_PUMP, 9, 1, nau8825_output_dac_event, 360 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 361 + 362 + /* HPOL/R are ungrounded by disabling 16 Ohm pull-downs on playback */ 363 + SND_SOC_DAPM_PGA_S("HPOL Pulldown", 8, 364 + NAU8825_REG_HSD_CTRL, 0, 1, NULL, 0), 365 + SND_SOC_DAPM_PGA_S("HPOR Pulldown", 8, 366 + NAU8825_REG_HSD_CTRL, 1, 1, NULL, 0), 367 + 368 + /* High current HPOL/R boost driver */ 369 + SND_SOC_DAPM_PGA_S("HP Boost Driver", 9, 370 + NAU8825_REG_BOOST, 9, 1, NULL, 0), 371 + 372 + /* Class G operation control*/ 373 + SND_SOC_DAPM_PGA_S("Class G", 10, 374 + NAU8825_REG_CLASSG_CTRL, 0, 0, NULL, 0), 387 375 388 376 SND_SOC_DAPM_OUTPUT("HPOL"), 389 377 SND_SOC_DAPM_OUTPUT("HPOR"), ··· 425 375 {"DACR Mux", "DACR", "DDACR"}, 426 376 {"HP amp L", NULL, "DACL Mux"}, 427 377 {"HP amp R", NULL, "DACR Mux"}, 428 - {"HP amp L", NULL, "HP amp power"}, 429 - {"HP amp R", NULL, "HP amp power"}, 430 - {"ADACL", NULL, "HP amp L"}, 431 - {"ADACR", NULL, "HP amp R"}, 432 - {"ADACL", NULL, "ADACL Clock"}, 433 - {"ADACR", NULL, "ADACR Clock"}, 434 - {"Output Driver L Stage 1", NULL, "ADACL"}, 435 - {"Output Driver R Stage 1", NULL, "ADACR"}, 378 + {"Charge Pump", NULL, "HP amp L"}, 379 + {"Charge Pump", NULL, "HP amp R"}, 380 + {"ADACL", NULL, "Charge Pump"}, 381 + {"ADACR", NULL, "Charge Pump"}, 382 + {"ADACL Clock", NULL, "ADACL"}, 383 + {"ADACR Clock", NULL, "ADACR"}, 384 + {"Output Driver L Stage 1", NULL, "ADACL Clock"}, 385 + {"Output Driver R Stage 1", NULL, "ADACR Clock"}, 436 386 {"Output Driver L Stage 2", NULL, "Output Driver L Stage 1"}, 437 387 {"Output Driver R Stage 2", NULL, "Output Driver R Stage 1"}, 438 388 {"Output Driver L Stage 3", NULL, "Output Driver L Stage 2"}, 439 389 {"Output Driver R Stage 3", NULL, "Output Driver R Stage 2"}, 440 390 {"Output DACL", NULL, "Output Driver L Stage 3"}, 441 391 {"Output DACR", NULL, "Output Driver R Stage 3"}, 442 - {"HPOL", NULL, "Output DACL"}, 443 - {"HPOR", NULL, "Output DACR"}, 444 - {"HPOL", NULL, "Charge Pump"}, 445 - {"HPOR", NULL, "Charge Pump"}, 392 + {"HPOL Pulldown", NULL, "Output DACL"}, 393 + {"HPOR Pulldown", NULL, "Output DACR"}, 394 + {"HP Boost Driver", NULL, "HPOL Pulldown"}, 395 + {"HP Boost Driver", NULL, "HPOR Pulldown"}, 396 + {"Class G", NULL, "HP Boost Driver"}, 397 + {"HPOL", NULL, "Class G"}, 398 + {"HPOR", NULL, "Class G"}, 446 399 }; 447 400 448 401 static int nau8825_hw_params(struct snd_pcm_substream *substream, ··· 712 659 break; 713 660 } 714 661 715 - if (type & SND_JACK_HEADPHONE) { 716 - /* Unground HPL/R */ 717 - regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 0x3, 0); 718 - } 719 - 662 + /* Leaving HPOL/R grounded after jack insert by default. They will be 663 + * ungrounded as part of the widget power up sequence at the beginning 664 + * of playback to reduce pop. 665 + */ 720 666 return type; 721 667 } 722 668 ··· 820 768 { 821 769 struct regmap *regmap = nau8825->regmap; 822 770 771 + /* Latch IIC LSB value */ 772 + regmap_write(regmap, NAU8825_REG_IIC_ADDR_SET, 0x0001); 823 773 /* Enable Bias/Vmid */ 824 774 regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, 825 775 NAU8825_BIAS_VMID, NAU8825_BIAS_VMID); ··· 834 780 nau8825->vref_impedance << NAU8825_BIAS_VMID_SEL_SFT); 835 781 /* Disable Boost Driver, Automatic Short circuit protection enable */ 836 782 regmap_update_bits(regmap, NAU8825_REG_BOOST, 837 - NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_G_DIS | 838 - NAU8825_SHORT_SHUTDOWN_EN, 839 - NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_G_DIS | 840 - NAU8825_SHORT_SHUTDOWN_EN); 783 + NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_DIS | 784 + NAU8825_HP_BOOST_G_DIS | NAU8825_SHORT_SHUTDOWN_EN, 785 + NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_DIS | 786 + NAU8825_HP_BOOST_G_DIS | NAU8825_SHORT_SHUTDOWN_EN); 841 787 842 788 regmap_update_bits(regmap, NAU8825_REG_GPIO12_CTRL, 843 789 NAU8825_JKDET_OUTPUT_EN, ··· 876 822 NAU8825_ADC_SYNC_DOWN_MASK, NAU8825_ADC_SYNC_DOWN_128); 877 823 regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1, 878 824 NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_128); 825 + /* Disable DACR/L power */ 826 + regmap_update_bits(regmap, NAU8825_REG_CHARGE_PUMP, 827 + NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL, 828 + NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL); 829 + /* Enable TESTDAC. This sets the analog DAC inputs to a '0' input 830 + * signal to avoid any glitches due to power up transients in both 831 + * the analog and digital DAC circuit. 832 + */ 833 + regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, 834 + NAU8825_BIAS_TESTDAC_EN, NAU8825_BIAS_TESTDAC_EN); 835 + /* CICCLP off */ 836 + regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1, 837 + NAU8825_DAC_CLIP_OFF, NAU8825_DAC_CLIP_OFF); 838 + 839 + /* Class AB bias current to 2x, DAC Capacitor enable MSB/LSB */ 840 + regmap_update_bits(regmap, NAU8825_REG_ANALOG_CONTROL_2, 841 + NAU8825_HP_NON_CLASSG_CURRENT_2xADJ | 842 + NAU8825_DAC_CAPACITOR_MSB | NAU8825_DAC_CAPACITOR_LSB, 843 + NAU8825_HP_NON_CLASSG_CURRENT_2xADJ | 844 + NAU8825_DAC_CAPACITOR_MSB | NAU8825_DAC_CAPACITOR_LSB); 845 + /* Class G timer 64ms */ 846 + regmap_update_bits(regmap, NAU8825_REG_CLASSG_CTRL, 847 + NAU8825_CLASSG_TIMER_MASK, 848 + 0x20 << NAU8825_CLASSG_TIMER_SFT); 849 + /* DAC clock delay 2ns, VREF */ 850 + regmap_update_bits(regmap, NAU8825_REG_RDAC, 851 + NAU8825_RDAC_CLK_DELAY_MASK | NAU8825_RDAC_VREF_MASK, 852 + (0x2 << NAU8825_RDAC_CLK_DELAY_SFT) | 853 + (0x3 << NAU8825_RDAC_VREF_SFT)); 879 854 } 880 855 881 856 static const struct regmap_config nau8825_regmap_config = {
+15 -1
sound/soc/codecs/nau8825.h
··· 14 14 15 15 #define NAU8825_REG_RESET 0x00 16 16 #define NAU8825_REG_ENA_CTRL 0x01 17 + #define NAU8825_REG_IIC_ADDR_SET 0x02 17 18 #define NAU8825_REG_CLK_DIVIDER 0x03 18 19 #define NAU8825_REG_FLL1 0x04 19 20 #define NAU8825_REG_FLL2 0x05 ··· 130 129 131 130 /* HSD_CTRL (0xc) */ 132 131 #define NAU8825_HSD_AUTO_MODE (1 << 6) 133 - /* 0 - short to GND, 1 - open */ 132 + /* 0 - open, 1 - short to GND */ 134 133 #define NAU8825_SPKR_DWN1R (1 << 1) 135 134 #define NAU8825_SPKR_DWN1L (1 << 0) 136 135 ··· 252 251 /* DACR_CTRL (0x34) */ 253 252 #define NAU8825_DACR_CH_SEL_SFT 9 254 253 254 + /* CLASSG_CTRL (0x50) */ 255 + #define NAU8825_CLASSG_TIMER_SFT 8 256 + #define NAU8825_CLASSG_TIMER_MASK (0x3f << NAU8825_CLASSG_TIMER_SFT) 257 + #define NAU8825_CLASSG_EN (1 << 0) 258 + 255 259 /* I2C_DEVICE_ID (0x58) */ 256 260 #define NAU8825_GPIO2JD1 (1 << 7) 257 261 #define NAU8825_SOFTWARE_ID_MASK 0x3 258 262 #define NAU8825_SOFTWARE_ID_NAU8825 0x0 259 263 260 264 /* BIAS_ADJ (0x66) */ 265 + #define NAU8825_BIAS_TESTDAC_EN (0x3 << 8) 261 266 #define NAU8825_BIAS_VMID (1 << 6) 262 267 #define NAU8825_BIAS_VMID_SEL_SFT 4 263 268 #define NAU8825_BIAS_VMID_SEL_MASK (3 << NAU8825_BIAS_VMID_SEL_SFT) ··· 281 274 #define NAU8825_ADC_VREFSEL_VMID_PLUS_1DB (3 << 8) 282 275 #define NAU8825_POWERUP_ADCL (1 << 6) 283 276 277 + /* RDAC (0x73) */ 278 + #define NAU8825_RDAC_CLK_DELAY_SFT 4 279 + #define NAU8825_RDAC_CLK_DELAY_MASK (0x7 << NAU8825_RDAC_CLK_DELAY_SFT) 280 + #define NAU8825_RDAC_VREF_SFT 2 281 + #define NAU8825_RDAC_VREF_MASK (0x3 << NAU8825_RDAC_VREF_SFT) 282 + 284 283 /* MIC_BIAS (0x74) */ 285 284 #define NAU8825_MICBIAS_JKSLV (1 << 14) 286 285 #define NAU8825_MICBIAS_JKR2 (1 << 12) ··· 297 284 /* BOOST (0x76) */ 298 285 #define NAU8825_PRECHARGE_DIS (1 << 13) 299 286 #define NAU8825_GLOBAL_BIAS_EN (1 << 12) 287 + #define NAU8825_HP_BOOST_DIS (1 << 9) 300 288 #define NAU8825_HP_BOOST_G_DIS (1 << 8) 301 289 #define NAU8825_SHORT_SHUTDOWN_EN (1 << 6) 302 290