aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/cs42l73.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/cs42l73.c')
-rw-r--r--sound/soc/codecs/cs42l73.c80
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
45static const struct reg_default cs42l73_reg_defaults[] = { 46static 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
592static 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
608static 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
626static 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
591static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = { 643static 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 }