diff options
Diffstat (limited to 'sound/soc/codecs/tlv320dac33.c')
-rw-r--r-- | sound/soc/codecs/tlv320dac33.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index ccb267f4e96..776ac80cc1a 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -315,8 +315,6 @@ static void dac33_init_chip(struct snd_soc_codec *codec) clock source = internal osc (?) */ dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN); - dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB); - /* Restore only selected registers (gains mostly) */ dac33_write(codec, DAC33_LDAC_DIG_VOL_CTRL, dac33_read_reg_cache(codec, DAC33_LDAC_DIG_VOL_CTRL)); @@ -356,6 +354,21 @@ static inline void dac33_soft_power(struct snd_soc_codec *codec, int power) dac33_write(codec, DAC33_PWR_CTRL, reg); } +static inline void dac33_disable_digital(struct snd_soc_codec *codec) +{ + u8 reg; + + /* Stop the DAI clock */ + reg = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B); + reg &= ~DAC33_BCLKON; + dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_B, reg); + + /* Power down the Oscillator, and DACs */ + reg = dac33_read_reg_cache(codec, DAC33_PWR_CTRL); + reg &= ~(DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB); + dac33_write(codec, DAC33_PWR_CTRL, reg); +} + static int dac33_hard_power(struct snd_soc_codec *codec, int power) { struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); @@ -404,7 +417,7 @@ exit: return ret; } -static int playback_event(struct snd_soc_dapm_widget *w, +static int dac33_playback_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec); @@ -416,6 +429,9 @@ static int playback_event(struct snd_soc_dapm_widget *w, dac33_prepare_chip(dac33->substream); } break; + case SND_SOC_DAPM_POST_PMD: + dac33_disable_digital(w->codec); + break; } return 0; } @@ -592,8 +608,8 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = { SND_SOC_DAPM_INPUT("LINEL"), SND_SOC_DAPM_INPUT("LINER"), - SND_SOC_DAPM_DAC("DACL", "Left Playback", DAC33_LDAC_PWR_CTRL, 2, 0), - SND_SOC_DAPM_DAC("DACR", "Right Playback", DAC33_RDAC_PWR_CTRL, 2, 0), + SND_SOC_DAPM_DAC("DACL", "Left Playback", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DACR", "Right Playback", SND_SOC_NOPM, 0, 0), /* Analog bypass */ SND_SOC_DAPM_SWITCH("Analog Left Bypass", SND_SOC_NOPM, 0, 0, @@ -601,12 +617,18 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = { SND_SOC_DAPM_SWITCH("Analog Right Bypass", SND_SOC_NOPM, 0, 0, &dac33_dapm_abypassr_control), - SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amp Power", + SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amplifier", DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), - SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power", + SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amplifier", DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0), - SND_SOC_DAPM_PRE("Prepare Playback", playback_event), + SND_SOC_DAPM_SUPPLY("Left DAC Power", + DAC33_LDAC_PWR_CTRL, 2, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Right DAC Power", + DAC33_RDAC_PWR_CTRL, 2, 0, NULL, 0), + + SND_SOC_DAPM_PRE("Pre Playback", dac33_playback_event), + SND_SOC_DAPM_POST("Post Playback", dac33_playback_event), }; static const struct snd_soc_dapm_route audio_map[] = { @@ -614,15 +636,18 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Analog Left Bypass", "Switch", "LINEL"}, {"Analog Right Bypass", "Switch", "LINER"}, - {"Output Left Amp Power", NULL, "DACL"}, - {"Output Right Amp Power", NULL, "DACR"}, + {"Output Left Amplifier", NULL, "DACL"}, + {"Output Right Amplifier", NULL, "DACR"}, + + {"Output Left Amplifier", NULL, "Analog Left Bypass"}, + {"Output Right Amplifier", NULL, "Analog Right Bypass"}, - {"Output Left Amp Power", NULL, "Analog Left Bypass"}, - {"Output Right Amp Power", NULL, "Analog Right Bypass"}, + {"Output Left Amplifier", NULL, "Left DAC Power"}, + {"Output Right Amplifier", NULL, "Right DAC Power"}, /* output */ - {"LEFT_LO", NULL, "Output Left Amp Power"}, - {"RIGHT_LO", NULL, "Output Right Amp Power"}, + {"LEFT_LO", NULL, "Output Left Amplifier"}, + {"RIGHT_LO", NULL, "Output Right Amplifier"}, }; static int dac33_add_widgets(struct snd_soc_codec *codec) @@ -640,11 +665,13 @@ static int dac33_add_widgets(struct snd_soc_codec *codec) static int dac33_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); int ret; switch (level) { case SND_SOC_BIAS_ON: - dac33_soft_power(codec, 1); + if (!dac33->substream) + dac33_soft_power(codec, 1); break; case SND_SOC_BIAS_PREPARE: break; |