diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/cs42l73.c | 80 |
1 files changed, 72 insertions, 8 deletions
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 476679510dff..fb9b178d6ffe 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c | |||
@@ -40,6 +40,7 @@ struct cs42l73_private { | |||
40 | u32 sysclk; | 40 | u32 sysclk; |
41 | u8 mclksel; | 41 | u8 mclksel; |
42 | u32 mclk; | 42 | u32 mclk; |
43 | int shutdwn_delay; | ||
43 | }; | 44 | }; |
44 | 45 | ||
45 | static const struct reg_default cs42l73_reg_defaults[] = { | 46 | static const struct reg_default cs42l73_reg_defaults[] = { |
@@ -588,6 +589,57 @@ static const struct snd_kcontrol_new cs42l73_snd_controls[] = { | |||
588 | SOC_ENUM("XSPOUT Mono/Stereo Select", xsp_output_mux_enum), | 589 | SOC_ENUM("XSPOUT Mono/Stereo Select", xsp_output_mux_enum), |
589 | }; | 590 | }; |
590 | 591 | ||
592 | static int cs42l73_spklo_spk_amp_event(struct snd_soc_dapm_widget *w, | ||
593 | struct snd_kcontrol *kcontrol, int event) | ||
594 | { | ||
595 | struct snd_soc_codec *codec = w->codec; | ||
596 | struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); | ||
597 | switch (event) { | ||
598 | case SND_SOC_DAPM_POST_PMD: | ||
599 | /* 150 ms delay between setting PDN and MCLKDIS */ | ||
600 | priv->shutdwn_delay = 150; | ||
601 | break; | ||
602 | default: | ||
603 | pr_err("Invalid event = 0x%x\n", event); | ||
604 | } | ||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | static int cs42l73_ear_amp_event(struct snd_soc_dapm_widget *w, | ||
609 | struct snd_kcontrol *kcontrol, int event) | ||
610 | { | ||
611 | struct snd_soc_codec *codec = w->codec; | ||
612 | struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); | ||
613 | switch (event) { | ||
614 | case SND_SOC_DAPM_POST_PMD: | ||
615 | /* 50 ms delay between setting PDN and MCLKDIS */ | ||
616 | if (priv->shutdwn_delay < 50) | ||
617 | priv->shutdwn_delay = 50; | ||
618 | break; | ||
619 | default: | ||
620 | pr_err("Invalid event = 0x%x\n", event); | ||
621 | } | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | |||
626 | static int cs42l73_hp_amp_event(struct snd_soc_dapm_widget *w, | ||
627 | struct snd_kcontrol *kcontrol, int event) | ||
628 | { | ||
629 | struct snd_soc_codec *codec = w->codec; | ||
630 | struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); | ||
631 | switch (event) { | ||
632 | case SND_SOC_DAPM_POST_PMD: | ||
633 | /* 30 ms delay between setting PDN and MCLKDIS */ | ||
634 | if (priv->shutdwn_delay < 30) | ||
635 | priv->shutdwn_delay = 30; | ||
636 | break; | ||
637 | default: | ||
638 | pr_err("Invalid event = 0x%x\n", event); | ||
639 | } | ||
640 | return 0; | ||
641 | } | ||
642 | |||
591 | static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = { | 643 | static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = { |
592 | SND_SOC_DAPM_INPUT("DMICA"), | 644 | SND_SOC_DAPM_INPUT("DMICA"), |
593 | SND_SOC_DAPM_INPUT("DMICB"), | 645 | SND_SOC_DAPM_INPUT("DMICB"), |
@@ -676,16 +728,20 @@ static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = { | |||
676 | SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0), | 728 | SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0), |
677 | SND_SOC_DAPM_PGA("ESL DAC", SND_SOC_NOPM, 0, 0, NULL, 0), | 729 | SND_SOC_DAPM_PGA("ESL DAC", SND_SOC_NOPM, 0, 0, NULL, 0), |
678 | 730 | ||
679 | SND_SOC_DAPM_SWITCH("HP Amp", CS42L73_PWRCTL3, 0, 1, | 731 | SND_SOC_DAPM_SWITCH_E("HP Amp", CS42L73_PWRCTL3, 0, 1, |
680 | &hp_amp_ctl), | 732 | &hp_amp_ctl, cs42l73_hp_amp_event, |
733 | SND_SOC_DAPM_POST_PMD), | ||
681 | SND_SOC_DAPM_SWITCH("LO Amp", CS42L73_PWRCTL3, 1, 1, | 734 | SND_SOC_DAPM_SWITCH("LO Amp", CS42L73_PWRCTL3, 1, 1, |
682 | &lo_amp_ctl), | 735 | &lo_amp_ctl), |
683 | SND_SOC_DAPM_SWITCH("SPK Amp", CS42L73_PWRCTL3, 2, 1, | 736 | SND_SOC_DAPM_SWITCH_E("SPK Amp", CS42L73_PWRCTL3, 2, 1, |
684 | &spk_amp_ctl), | 737 | &spk_amp_ctl, cs42l73_spklo_spk_amp_event, |
685 | SND_SOC_DAPM_SWITCH("EAR Amp", CS42L73_PWRCTL3, 3, 1, | 738 | SND_SOC_DAPM_POST_PMD), |
686 | &ear_amp_ctl), | 739 | SND_SOC_DAPM_SWITCH_E("EAR Amp", CS42L73_PWRCTL3, 3, 1, |
687 | SND_SOC_DAPM_SWITCH("SPKLO Amp", CS42L73_PWRCTL3, 4, 1, | 740 | &ear_amp_ctl, cs42l73_ear_amp_event, |
688 | &spklo_amp_ctl), | 741 | SND_SOC_DAPM_POST_PMD), |
742 | SND_SOC_DAPM_SWITCH_E("SPKLO Amp", CS42L73_PWRCTL3, 4, 1, | ||
743 | &spklo_amp_ctl, cs42l73_spklo_spk_amp_event, | ||
744 | SND_SOC_DAPM_POST_PMD), | ||
689 | 745 | ||
690 | SND_SOC_DAPM_OUTPUT("HPOUTA"), | 746 | SND_SOC_DAPM_OUTPUT("HPOUTA"), |
691 | SND_SOC_DAPM_OUTPUT("HPOUTB"), | 747 | SND_SOC_DAPM_OUTPUT("HPOUTB"), |
@@ -1171,6 +1227,14 @@ static int cs42l73_set_bias_level(struct snd_soc_codec *codec, | |||
1171 | 1227 | ||
1172 | case SND_SOC_BIAS_OFF: | 1228 | case SND_SOC_BIAS_OFF: |
1173 | snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1); | 1229 | snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1); |
1230 | if (cs42l73->shutdwn_delay > 0) { | ||
1231 | mdelay(cs42l73->shutdwn_delay); | ||
1232 | cs42l73->shutdwn_delay = 0; | ||
1233 | } else { | ||
1234 | mdelay(15); /* Min amount of time requred to power | ||
1235 | * down. | ||
1236 | */ | ||
1237 | } | ||
1174 | snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 1); | 1238 | snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 1); |
1175 | break; | 1239 | break; |
1176 | } | 1240 | } |