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 ccb267f4e968..776ac80cc1a8 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) | |||
315 | clock source = internal osc (?) */ | 315 | clock source = internal osc (?) */ |
316 | dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN); | 316 | dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN); |
317 | 317 | ||
318 | dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB); | ||
319 | |||
320 | /* Restore only selected registers (gains mostly) */ | 318 | /* Restore only selected registers (gains mostly) */ |
321 | dac33_write(codec, DAC33_LDAC_DIG_VOL_CTRL, | 319 | dac33_write(codec, DAC33_LDAC_DIG_VOL_CTRL, |
322 | dac33_read_reg_cache(codec, DAC33_LDAC_DIG_VOL_CTRL)); | 320 | 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) | |||
356 | dac33_write(codec, DAC33_PWR_CTRL, reg); | 354 | dac33_write(codec, DAC33_PWR_CTRL, reg); |
357 | } | 355 | } |
358 | 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 | |||
359 | static int dac33_hard_power(struct snd_soc_codec *codec, int power) | 372 | static int dac33_hard_power(struct snd_soc_codec *codec, int power) |
360 | { | 373 | { |
361 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 374 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
@@ -404,7 +417,7 @@ exit: | |||
404 | return ret; | 417 | return ret; |
405 | } | 418 | } |
406 | 419 | ||
407 | static int playback_event(struct snd_soc_dapm_widget *w, | 420 | static int dac33_playback_event(struct snd_soc_dapm_widget *w, |
408 | struct snd_kcontrol *kcontrol, int event) | 421 | struct snd_kcontrol *kcontrol, int event) |
409 | { | 422 | { |
410 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec); | 423 | 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, | |||
416 | dac33_prepare_chip(dac33->substream); | 429 | dac33_prepare_chip(dac33->substream); |
417 | } | 430 | } |
418 | break; | 431 | break; |
432 | case SND_SOC_DAPM_POST_PMD: | ||
433 | dac33_disable_digital(w->codec); | ||
434 | break; | ||
419 | } | 435 | } |
420 | return 0; | 436 | return 0; |
421 | } | 437 | } |
@@ -592,8 +608,8 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = { | |||
592 | SND_SOC_DAPM_INPUT("LINEL"), | 608 | SND_SOC_DAPM_INPUT("LINEL"), |
593 | SND_SOC_DAPM_INPUT("LINER"), | 609 | SND_SOC_DAPM_INPUT("LINER"), |
594 | 610 | ||
595 | SND_SOC_DAPM_DAC("DACL", "Left Playback", DAC33_LDAC_PWR_CTRL, 2, 0), | 611 | SND_SOC_DAPM_DAC("DACL", "Left Playback", SND_SOC_NOPM, 0, 0), |
596 | SND_SOC_DAPM_DAC("DACR", "Right Playback", DAC33_RDAC_PWR_CTRL, 2, 0), | 612 | SND_SOC_DAPM_DAC("DACR", "Right Playback", SND_SOC_NOPM, 0, 0), |
597 | 613 | ||
598 | /* Analog bypass */ | 614 | /* Analog bypass */ |
599 | SND_SOC_DAPM_SWITCH("Analog Left Bypass", SND_SOC_NOPM, 0, 0, | 615 | 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[] = { | |||
601 | SND_SOC_DAPM_SWITCH("Analog Right Bypass", SND_SOC_NOPM, 0, 0, | 617 | SND_SOC_DAPM_SWITCH("Analog Right Bypass", SND_SOC_NOPM, 0, 0, |
602 | &dac33_dapm_abypassr_control), | 618 | &dac33_dapm_abypassr_control), |
603 | 619 | ||
604 | SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amp Power", | 620 | SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amplifier", |
605 | DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), | 621 | DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), |
606 | SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power", | 622 | SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amplifier", |
607 | DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0), | 623 | DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0), |
608 | 624 | ||
609 | SND_SOC_DAPM_PRE("Prepare Playback", playback_event), | 625 | SND_SOC_DAPM_SUPPLY("Left DAC Power", |
626 | DAC33_LDAC_PWR_CTRL, 2, 0, NULL, 0), | ||
627 | SND_SOC_DAPM_SUPPLY("Right DAC Power", | ||
628 | DAC33_RDAC_PWR_CTRL, 2, 0, NULL, 0), | ||
629 | |||
630 | SND_SOC_DAPM_PRE("Pre Playback", dac33_playback_event), | ||
631 | SND_SOC_DAPM_POST("Post Playback", dac33_playback_event), | ||
610 | }; | 632 | }; |
611 | 633 | ||
612 | static const struct snd_soc_dapm_route audio_map[] = { | 634 | static const struct snd_soc_dapm_route audio_map[] = { |
@@ -614,15 +636,18 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
614 | {"Analog Left Bypass", "Switch", "LINEL"}, | 636 | {"Analog Left Bypass", "Switch", "LINEL"}, |
615 | {"Analog Right Bypass", "Switch", "LINER"}, | 637 | {"Analog Right Bypass", "Switch", "LINER"}, |
616 | 638 | ||
617 | {"Output Left Amp Power", NULL, "DACL"}, | 639 | {"Output Left Amplifier", NULL, "DACL"}, |
618 | {"Output Right Amp Power", NULL, "DACR"}, | 640 | {"Output Right Amplifier", NULL, "DACR"}, |
641 | |||
642 | {"Output Left Amplifier", NULL, "Analog Left Bypass"}, | ||
643 | {"Output Right Amplifier", NULL, "Analog Right Bypass"}, | ||
619 | 644 | ||
620 | {"Output Left Amp Power", NULL, "Analog Left Bypass"}, | 645 | {"Output Left Amplifier", NULL, "Left DAC Power"}, |
621 | {"Output Right Amp Power", NULL, "Analog Right Bypass"}, | 646 | {"Output Right Amplifier", NULL, "Right DAC Power"}, |
622 | 647 | ||
623 | /* output */ | 648 | /* output */ |
624 | {"LEFT_LO", NULL, "Output Left Amp Power"}, | 649 | {"LEFT_LO", NULL, "Output Left Amplifier"}, |
625 | {"RIGHT_LO", NULL, "Output Right Amp Power"}, | 650 | {"RIGHT_LO", NULL, "Output Right Amplifier"}, |
626 | }; | 651 | }; |
627 | 652 | ||
628 | static int dac33_add_widgets(struct snd_soc_codec *codec) | 653 | static int dac33_add_widgets(struct snd_soc_codec *codec) |
@@ -640,11 +665,13 @@ static int dac33_add_widgets(struct snd_soc_codec *codec) | |||
640 | static int dac33_set_bias_level(struct snd_soc_codec *codec, | 665 | static int dac33_set_bias_level(struct snd_soc_codec *codec, |
641 | enum snd_soc_bias_level level) | 666 | enum snd_soc_bias_level level) |
642 | { | 667 | { |
668 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | ||
643 | int ret; | 669 | int ret; |
644 | 670 | ||
645 | switch (level) { | 671 | switch (level) { |
646 | case SND_SOC_BIAS_ON: | 672 | case SND_SOC_BIAS_ON: |
647 | dac33_soft_power(codec, 1); | 673 | if (!dac33->substream) |
674 | dac33_soft_power(codec, 1); | ||
648 | break; | 675 | break; |
649 | case SND_SOC_BIAS_PREPARE: | 676 | case SND_SOC_BIAS_PREPARE: |
650 | break; | 677 | break; |