Commit a6cea9655bfa821dbf53c6fffb9b2b99fe77367c

Authored by Peter Ujfalusi
Committed by Liam Girdwood
1 parent 23ac3b6133

ASoC: tlv320dac33: Power down digital parts, when not needed

If the following scenario has been followed:
1. Enable analog bypass
amixer sset 'Analog Left Bypass' on
amixer sset 'Analog Right Bypass' on

2. Start playback
aplay -fdat -d3 /dev/zero

After the playback stopped (3 sec), and the soc timeout (5 sec),
the digital parts of the codec will remain powered up.
This means that the DAI clocks are continue to run, the
oscillator remain operational, etc.

Use the SND_SOC_DAPM_POST_PMD widget to get notification
about the stopped stream, and power down the digital
part of the codec.
If the analog bypass is enabled, than the codec will remain in
BIAS_ON level, and things will work correctly.
In case, if the bypass is disabled, than the codec will
fall to BIAS_STANDBY than to BIAS_OFF level, as it used
to.

The digital part of DAC33 is initialized at every stream start
(DAPM_PRE:PRE_PMU event), so subsequent streams (within 5 sec)
will have working DAI.
When the codec is coming out from BIAS_OFF, the full power-up
sequence followed by the same DAPM_PRE widget event will power up
the digital part.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>

Showing 1 changed file with 21 additions and 2 deletions Side-by-side Diff

sound/soc/codecs/tlv320dac33.c
... ... @@ -354,6 +354,21 @@
354 354 dac33_write(codec, DAC33_PWR_CTRL, reg);
355 355 }
356 356  
  357 +static inline void dac33_disable_digital(struct snd_soc_codec *codec)
  358 +{
  359 + u8 reg;
  360 +
  361 + /* Stop the DAI clock */
  362 + reg = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B);
  363 + reg &= ~DAC33_BCLKON;
  364 + dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_B, reg);
  365 +
  366 + /* Power down the Oscillator, and DACs */
  367 + reg = dac33_read_reg_cache(codec, DAC33_PWR_CTRL);
  368 + reg &= ~(DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB);
  369 + dac33_write(codec, DAC33_PWR_CTRL, reg);
  370 +}
  371 +
357 372 static int dac33_hard_power(struct snd_soc_codec *codec, int power)
358 373 {
359 374 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
... ... @@ -402,7 +417,7 @@
402 417 return ret;
403 418 }
404 419  
405   -static int playback_event(struct snd_soc_dapm_widget *w,
  420 +static int dac33_playback_event(struct snd_soc_dapm_widget *w,
406 421 struct snd_kcontrol *kcontrol, int event)
407 422 {
408 423 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec);
... ... @@ -414,6 +429,9 @@
414 429 dac33_prepare_chip(dac33->substream);
415 430 }
416 431 break;
  432 + case SND_SOC_DAPM_POST_PMD:
  433 + dac33_disable_digital(w->codec);
  434 + break;
417 435 }
418 436 return 0;
419 437 }
... ... @@ -609,7 +627,8 @@
609 627 SND_SOC_DAPM_SUPPLY("Right DAC Power",
610 628 DAC33_RDAC_PWR_CTRL, 2, 0, NULL, 0),
611 629  
612   - SND_SOC_DAPM_PRE("Prepare Playback", playback_event),
  630 + SND_SOC_DAPM_PRE("Pre Playback", dac33_playback_event),
  631 + SND_SOC_DAPM_POST("Post Playback", dac33_playback_event),
613 632 };
614 633  
615 634 static const struct snd_soc_dapm_route audio_map[] = {