aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Thomson <Adam.Thomson.Opensource@diasemi.com>2016-09-26 09:29:21 -0400
committerMark Brown <broonie@kernel.org>2016-09-26 12:39:50 -0400
commitbb0c35fcaf8f2ad3383dd43ca8abf5203cd06cc3 (patch)
tree0e97ce1ffbbfe4f9cb0fbdd5b53d63acb552cc2e
parenta7f16ea90ecffde4d4915eb7c81b11428e636920 (diff)
ASoC: da7219: Disable AAD if codec is not a wake-up source
Currently if AAD is enabled in the device, during system suspend the feature remains, regardless of whether the codec is a wake-up source or not. This means some additional power is being used which is unnecessary, and can causes issues with some platforms' IRQ handlers where state changes during system suspend aren't captured. This patch updates the driver to disable AAD during suspend, if we're not a wake-up source, and then re-enables this on resume. Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--include/sound/da7219.h2
-rw-r--r--sound/soc/codecs/da7219-aad.c56
-rw-r--r--sound/soc/codecs/da7219-aad.h5
-rw-r--r--sound/soc/codecs/da7219.c30
-rw-r--r--sound/soc/codecs/da7219.h1
5 files changed, 81 insertions, 13 deletions
diff --git a/include/sound/da7219.h b/include/sound/da7219.h
index 02876acdc840..409ef1397fd3 100644
--- a/include/sound/da7219.h
+++ b/include/sound/da7219.h
@@ -34,6 +34,8 @@ enum da7219_mic_amp_in_sel {
34struct da7219_aad_pdata; 34struct da7219_aad_pdata;
35 35
36struct da7219_pdata { 36struct da7219_pdata {
37 bool wakeup_source;
38
37 /* Mic */ 39 /* Mic */
38 enum da7219_micbias_voltage micbias_lvl; 40 enum da7219_micbias_voltage micbias_lvl;
39 enum da7219_mic_amp_in_sel mic_amp_in_sel; 41 enum da7219_mic_amp_in_sel mic_amp_in_sel;
diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c
index fc27dab3d6ba..2b8914dd5990 100644
--- a/sound/soc/codecs/da7219-aad.c
+++ b/sound/soc/codecs/da7219-aad.c
@@ -797,6 +797,62 @@ static void da7219_aad_handle_pdata(struct snd_soc_codec *codec)
797 797
798 798
799/* 799/*
800 * Suspend/Resume
801 */
802
803void da7219_aad_suspend(struct snd_soc_codec *codec)
804{
805 struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
806 struct da7219_aad_priv *da7219_aad = da7219->aad;
807 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
808 u8 micbias_ctrl;
809
810 if (da7219_aad->jack) {
811 /* Disable jack detection during suspend */
812 snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1,
813 DA7219_ACCDET_EN_MASK, 0);
814
815 /*
816 * If we have a 4-pole jack inserted, then micbias will be
817 * enabled. We can disable micbias here, and keep a note to
818 * re-enable it on resume. If jack removal occurred during
819 * suspend then this will be dealt with through the IRQ handler.
820 */
821 if (da7219_aad->jack_inserted) {
822 micbias_ctrl = snd_soc_read(codec, DA7219_MICBIAS_CTRL);
823 if (micbias_ctrl & DA7219_MICBIAS1_EN_MASK) {
824 snd_soc_dapm_disable_pin(dapm, "Mic Bias");
825 snd_soc_dapm_sync(dapm);
826 da7219_aad->micbias_resume_enable = true;
827 }
828 }
829 }
830}
831
832void da7219_aad_resume(struct snd_soc_codec *codec)
833{
834 struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
835 struct da7219_aad_priv *da7219_aad = da7219->aad;
836 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
837
838 if (da7219_aad->jack) {
839 /* Re-enable micbias if previously enabled for 4-pole jack */
840 if (da7219_aad->jack_inserted &&
841 da7219_aad->micbias_resume_enable) {
842 snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
843 snd_soc_dapm_sync(dapm);
844 da7219_aad->micbias_resume_enable = false;
845 }
846
847 /* Re-enable jack detection */
848 snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1,
849 DA7219_ACCDET_EN_MASK,
850 DA7219_ACCDET_EN_MASK);
851 }
852}
853
854
855/*
800 * Init/Exit 856 * Init/Exit
801 */ 857 */
802 858
diff --git a/sound/soc/codecs/da7219-aad.h b/sound/soc/codecs/da7219-aad.h
index a34be4828f97..117a3d7ccd31 100644
--- a/sound/soc/codecs/da7219-aad.h
+++ b/sound/soc/codecs/da7219-aad.h
@@ -201,12 +201,17 @@ struct da7219_aad_priv {
201 struct work_struct hptest_work; 201 struct work_struct hptest_work;
202 202
203 struct snd_soc_jack *jack; 203 struct snd_soc_jack *jack;
204 bool micbias_resume_enable;
204 bool jack_inserted; 205 bool jack_inserted;
205}; 206};
206 207
207/* AAD control */ 208/* AAD control */
208void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack); 209void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
209 210
211/* Suspend/Resume */
212void da7219_aad_suspend(struct snd_soc_codec *codec);
213void da7219_aad_resume(struct snd_soc_codec *codec);
214
210/* Init/Exit */ 215/* Init/Exit */
211int da7219_aad_init(struct snd_soc_codec *codec); 216int da7219_aad_init(struct snd_soc_codec *codec);
212void da7219_aad_exit(struct snd_soc_codec *codec); 217void da7219_aad_exit(struct snd_soc_codec *codec);
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index eecb6d6c29cf..65f7e9807659 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -1482,6 +1482,8 @@ static struct da7219_pdata *da7219_fw_to_pdata(struct snd_soc_codec *codec)
1482 if (!pdata) 1482 if (!pdata)
1483 return NULL; 1483 return NULL;
1484 1484
1485 pdata->wakeup_source = device_property_read_bool(dev, "wakeup-source");
1486
1485 if (device_property_read_u32(dev, "dlg,micbias-lvl", &of_val32) >= 0) 1487 if (device_property_read_u32(dev, "dlg,micbias-lvl", &of_val32) >= 0)
1486 pdata->micbias_lvl = da7219_fw_micbias_lvl(dev, of_val32); 1488 pdata->micbias_lvl = da7219_fw_micbias_lvl(dev, of_val32);
1487 else 1489 else
@@ -1524,20 +1526,21 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec,
1524 1526
1525 break; 1527 break;
1526 case SND_SOC_BIAS_STANDBY: 1528 case SND_SOC_BIAS_STANDBY:
1527 if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { 1529 if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF)
1528 /* Master bias */ 1530 /* Master bias */
1529 snd_soc_update_bits(codec, DA7219_REFERENCES, 1531 snd_soc_update_bits(codec, DA7219_REFERENCES,
1530 DA7219_BIAS_EN_MASK, 1532 DA7219_BIAS_EN_MASK,
1531 DA7219_BIAS_EN_MASK); 1533 DA7219_BIAS_EN_MASK);
1532 } else { 1534
1535 if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE) {
1533 /* Remove MCLK */ 1536 /* Remove MCLK */
1534 if (da7219->mclk) 1537 if (da7219->mclk)
1535 clk_disable_unprepare(da7219->mclk); 1538 clk_disable_unprepare(da7219->mclk);
1536 } 1539 }
1537 break; 1540 break;
1538 case SND_SOC_BIAS_OFF: 1541 case SND_SOC_BIAS_OFF:
1539 /* Only disable master bias if jack detection not active */ 1542 /* Only disable master bias if we're not a wake-up source */
1540 if (!da7219->aad->jack) 1543 if (!da7219->wakeup_source)
1541 snd_soc_update_bits(codec, DA7219_REFERENCES, 1544 snd_soc_update_bits(codec, DA7219_REFERENCES,
1542 DA7219_BIAS_EN_MASK, 0); 1545 DA7219_BIAS_EN_MASK, 0);
1543 1546
@@ -1603,6 +1606,8 @@ static void da7219_handle_pdata(struct snd_soc_codec *codec)
1603 if (pdata) { 1606 if (pdata) {
1604 u8 micbias_lvl = 0; 1607 u8 micbias_lvl = 0;
1605 1608
1609 da7219->wakeup_source = pdata->wakeup_source;
1610
1606 /* Mic Bias voltages */ 1611 /* Mic Bias voltages */
1607 switch (pdata->micbias_lvl) { 1612 switch (pdata->micbias_lvl) {
1608 case DA7219_MICBIAS_1_6V: 1613 case DA7219_MICBIAS_1_6V:
@@ -1737,11 +1742,11 @@ static int da7219_suspend(struct snd_soc_codec *codec)
1737{ 1742{
1738 struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1743 struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
1739 1744
1740 snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); 1745 /* Suspend AAD if we're not a wake-up source */
1746 if (!da7219->wakeup_source)
1747 da7219_aad_suspend(codec);
1741 1748
1742 /* Put device into standby mode if jack detection disabled */ 1749 snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
1743 if (!da7219->aad->jack)
1744 snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, 0);
1745 1750
1746 return 0; 1751 return 0;
1747} 1752}
@@ -1750,13 +1755,12 @@ static int da7219_resume(struct snd_soc_codec *codec)
1750{ 1755{
1751 struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); 1756 struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
1752 1757
1753 /* Put device into active mode if previously pushed to standby */
1754 if (!da7219->aad->jack)
1755 snd_soc_write(codec, DA7219_SYSTEM_ACTIVE,
1756 DA7219_SYSTEM_ACTIVE_MASK);
1757
1758 snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY); 1758 snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_STANDBY);
1759 1759
1760 /* Resume AAD if previously suspended */
1761 if (!da7219->wakeup_source)
1762 da7219_aad_resume(codec);
1763
1760 return 0; 1764 return 0;
1761} 1765}
1762#else 1766#else
diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h
index f1b3ad835270..66d3bad86739 100644
--- a/sound/soc/codecs/da7219.h
+++ b/sound/soc/codecs/da7219.h
@@ -803,6 +803,7 @@ struct da7219_priv {
803 struct da7219_aad_priv *aad; 803 struct da7219_aad_priv *aad;
804 struct da7219_pdata *pdata; 804 struct da7219_pdata *pdata;
805 805
806 bool wakeup_source;
806 struct regulator_bulk_data supplies[DA7219_NUM_SUPPLIES]; 807 struct regulator_bulk_data supplies[DA7219_NUM_SUPPLIES];
807 struct regmap *regmap; 808 struct regmap *regmap;
808 struct mutex lock; 809 struct mutex lock;