STMP37xx/iMX233: reduce popping noise on power on/off (Version 1)

Version 1: this patch prolongs startup time by 2 seconds, because the
sleep happens early before other threads have started.

The patch is tested on CreativeZEN and Fuze+.

The datasheet was not very helpfull, so some experimentation was needed.
I came to the following conclusions:
* setting HP to ground:
  to prevent popping noises, the headphone output can be set to ground.
  This however must be done before any part of the audioout module is
  powered up (setting HP to ground itself will lead to a pop otherwise).
  This consequently means that HP must NOT be set to ground for powerdown
  sequence!
  Further study showed that setting HP out to ground has no audible benefit,
  controversly not setting/resetting allows for noiseless RoLo-ing.
* headphone amp class A/AB mode:
  initially the HP amp is in class A mode, and should be set to
  class AB before playing audio, as the datasheet mentions.
  If the HP output is set to ground, it must be released BEFORE
  setting class AB! Releasing from ground while in AB mode leads
  to a very loud pop!
* release HP from ground:
  as said before: never release the HP from ground if the HP amp is
  set to class AB mode. Therefore the correct order is to power up the
  headphone amp, wait some time, release HP from ground, and then
  set the amp to class AB mode.
  To prevent pop, some time is needed before releasing the HP from gnd.
  On CreativeZEN 2 sec seems to be ideal; 1 sec have no audible effect,
  1.5 sec softenes the pop to some degree.
* shutting player off
  The popping noise when shutting off is much quieter that on power up,
  so depopping measures are not absolutely necessary.
  However the power off pop can be silenced by inserting a wait time
  after the audioout block is closed and before the rest of the chip
  is powered down. The longer the better, a time of 5 sec practically
  eliminates the pop.

Note that RoLo-ing can still produce noise, because the audio device
is not properly shut down.

Change-Id: Ib20e1d613b346433d2a711c442e303ededc26e78
This commit is contained in:
Sebastian Leonhardt 2025-10-13 20:31:50 +02:00 committed by Aidan MacDonald
parent 945ce06094
commit 9aafbf9ca9

View file

@ -54,6 +54,10 @@ static int hp_unmute_cb(struct timeout *tmo)
void imx233_audioout_preinit(void) void imx233_audioout_preinit(void)
{ {
/* we forego setting HP output to ground; it seems it doesn't have an
audible benefit, but produces loud noise if done at the wrong place */
/* when RoLo-ing the headphone is still unmuted; mute to reduce noise */
BF_SET(AUDIOOUT_HPVOL, MUTE);
/* Enable AUDIOOUT block */ /* Enable AUDIOOUT block */
imx233_reset_block(&HW_AUDIOOUT_CTRL); imx233_reset_block(&HW_AUDIOOUT_CTRL);
/* Enable digital filter clock */ /* Enable digital filter clock */
@ -70,10 +74,14 @@ void imx233_audioout_preinit(void)
BF_SET(AUDIOOUT_CTRL, WORD_LENGTH); BF_SET(AUDIOOUT_CTRL, WORD_LENGTH);
/* Power up DAC */ /* Power up DAC */
BF_CLR(AUDIOOUT_PWRDN, DAC); BF_CLR(AUDIOOUT_PWRDN, DAC);
/* Hold HP to ground to avoid pop, then release and power up HP */ /* power up HP */
BF_SET(AUDIOOUT_ANACTRL, HP_HOLD_GND);
BF_CLR(AUDIOOUT_PWRDN, HEADPHONE); BF_CLR(AUDIOOUT_PWRDN, HEADPHONE);
/* Set HP mode to AB */ /* wait until voltages have settled after powering on HP amp.
* The time delay may be target dependant; on CreativeZEN (STMP3760)
* 1.5 sec still isn't enough (only softening the pop) */
sleep(HZ*2);
/* Set HP mode to class AB. This must be done after HP is released from
* GND; releasing while AB mode is activated leads to a REALLY loud pop! */
BF_SET(AUDIOOUT_ANACTRL, HP_CLASSAB); BF_SET(AUDIOOUT_ANACTRL, HP_CLASSAB);
/* change bias to -50% */ /* change bias to -50% */
BF_WR(AUDIOOUT_TEST, HP_I1_ADJ(1)); BF_WR(AUDIOOUT_TEST, HP_I1_ADJ(1));
@ -82,8 +90,6 @@ void imx233_audioout_preinit(void)
BF_SET(AUDIOOUT_REFCTRL, RAISE_REF); BF_SET(AUDIOOUT_REFCTRL, RAISE_REF);
#endif #endif
BF_SET(AUDIOOUT_REFCTRL, XTAL_BGR_BIAS); BF_SET(AUDIOOUT_REFCTRL, XTAL_BGR_BIAS);
/* Stop holding to ground */
BF_CLR(AUDIOOUT_ANACTRL, HP_HOLD_GND);
/* Set dmawait count to 31 (see errata, workaround random stop) */ /* Set dmawait count to 31 (see errata, workaround random stop) */
BF_WR(AUDIOOUT_CTRL, DMAWAIT_COUNT(31)); BF_WR(AUDIOOUT_CTRL, DMAWAIT_COUNT(31));
/* start converting audio */ /* start converting audio */
@ -107,8 +113,6 @@ void imx233_audioout_close(void)
{ {
/* Switch to class A */ /* Switch to class A */
BF_CLR(AUDIOOUT_ANACTRL, HP_CLASSAB); BF_CLR(AUDIOOUT_ANACTRL, HP_CLASSAB);
/* Hold HP to ground */
BF_SET(AUDIOOUT_ANACTRL, HP_HOLD_GND);
/* Mute HP and power down */ /* Mute HP and power down */
BF_SET(AUDIOOUT_HPVOL, MUTE); BF_SET(AUDIOOUT_HPVOL, MUTE);
/* Power down HP */ /* Power down HP */
@ -123,6 +127,9 @@ void imx233_audioout_close(void)
imx233_clkctrl_enable(CLK_FILT, false); imx233_clkctrl_enable(CLK_FILT, false);
/* will also gate off the module */ /* will also gate off the module */
BF_CLR(AUDIOOUT_CTRL, RUN); BF_CLR(AUDIOOUT_CTRL, RUN);
/* power-off-pop is reduced when waiting after shutting off
* the audioout module and before powering down the whole chip. */
sleep(HZ*2);
} }
/* volume in half dB /* volume in half dB