asoc: tegra: cs42l73: updated driver from cirrus
Dara Ramesh [Thu, 8 Nov 2012 06:19:32 +0000 (11:19 +0530)]
updated version of the driver v0.1 thats adds the
proper power down method.

Bug 1053365
Bug 1161544

Change-Id: Ia3f4f2827d3ef2330a927cb5140bb9954a852654
Signed-off-by: Dara Ramesh <dramesh@nvidia.com>
Reviewed-on: http://git-master/r/162265
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Vijay Mali <vmali@nvidia.com>
Tested-by: Vijay Mali <vmali@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Scott Peterson <speterson@nvidia.com>

sound/soc/codecs/cs42l73.c

index 90238bd..fd776f2 100644 (file)
@@ -40,6 +40,8 @@ struct  cs42l73_private {
        u32 sysclk;
        u8 mclksel;
        u32 mclk;
+       int shutdwn_delay;
+       int pwr_up_delay;
 };
 
 static const struct reg_default cs42l73_reg_defaults[] = {
@@ -591,6 +593,57 @@ static const struct snd_kcontrol_new cs42l73_snd_controls[] = {
        SOC_ENUM("XSPOUT Mono/Stereo Select", xsp_output_mux_enum),
 };
 
+static int cs42l73_spklo_spk_amp_event(struct snd_soc_dapm_widget *w,
+                               struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMD:
+               /* 150 ms delay between setting PDN and MCLKDIS */
+               priv->shutdwn_delay = 150;
+               break;
+       default:
+               dev_err(codec->dev, "Invalid event = 0x%x\n", event);
+       }
+       return 0;
+}
+
+static int cs42l73_ear_amp_event(struct snd_soc_dapm_widget *w,
+                               struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMD:
+               /* 50 ms delay between setting PDN and MCLKDIS */
+               if (priv->shutdwn_delay < 50)
+                       priv->shutdwn_delay = 50;
+                       break;
+       default:
+               dev_err(codec->dev, "Invalid event = 0x%x\n", event);
+       }
+               return 0;
+}
+
+
+static int cs42l73_hp_amp_event(struct snd_soc_dapm_widget *w,
+                               struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMD:
+               /* 30 ms delay between setting PDN and MCLKDIS */
+               if (priv->shutdwn_delay < 30)
+                       priv->shutdwn_delay = 30;
+               break;
+       default:
+               dev_err(codec->dev, "Invalid event = 0x%x\n", event);
+       }
+       return 0;
+}
+
 static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("LINEINA"),
        SND_SOC_DAPM_INPUT("LINEINB"),
@@ -677,16 +730,20 @@ static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = {
        SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("ESL DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
 
-       SND_SOC_DAPM_SWITCH("HP Amp", CS42L73_PWRCTL3, 0, 1,
-                           &hp_amp_ctl),
+       SND_SOC_DAPM_SWITCH_E("HP Amp",  CS42L73_PWRCTL3, 0, 1,
+                           &hp_amp_ctl, cs42l73_hp_amp_event,
+                       SND_SOC_DAPM_POST_PMD),
        SND_SOC_DAPM_SWITCH("LO Amp", CS42L73_PWRCTL3, 1, 1,
                            &lo_amp_ctl),
-       SND_SOC_DAPM_SWITCH("SPK Amp", CS42L73_PWRCTL3, 2, 1,
-                           &spk_amp_ctl),
-       SND_SOC_DAPM_SWITCH("EAR Amp", CS42L73_PWRCTL3, 3, 1,
-                           &ear_amp_ctl),
-       SND_SOC_DAPM_SWITCH("SPKLO Amp", CS42L73_PWRCTL3, 4, 1,
-                           &spklo_amp_ctl),
+       SND_SOC_DAPM_SWITCH_E("SPK Amp", CS42L73_PWRCTL3, 2, 1,
+                       &spk_amp_ctl, cs42l73_spklo_spk_amp_event,
+                       SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_SWITCH_E("EAR Amp", CS42L73_PWRCTL3, 3, 1,
+                           &ear_amp_ctl, cs42l73_ear_amp_event,
+                       SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_SWITCH_E("SPKLO Amp", CS42L73_PWRCTL3, 4, 1,
+                           &spklo_amp_ctl, cs42l73_spklo_spk_amp_event,
+                       SND_SOC_DAPM_POST_PMD),
 
        SND_SOC_DAPM_OUTPUT("HPOUTA"),
        SND_SOC_DAPM_OUTPUT("HPOUTB"),
@@ -1161,7 +1218,14 @@ static int cs42l73_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_OFF:
                snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
-               msleep(100);
+               if (cs42l73->shutdwn_delay > 0) {
+                       mdelay(cs42l73->shutdwn_delay);
+                       cs42l73->shutdwn_delay = 0;
+               } else {
+                       mdelay(15); /* Min amount of time requred to power
+                                    * down.
+                                    */
+               }
                snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 1);
                break;
        }