aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitris Papastamos <dp@opensource.wolfsonmicro.com>2011-02-11 11:32:12 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-02-13 14:45:01 -0500
commitc52fd021bc027a90a10782c0dcf667ac0135e478 (patch)
treef01f88c04ee4aacfd898aea8b0e09bd66e67c45b
parent173efa09e4c807a2a764509ddd593ad13a44d1df (diff)
ASoC: WM8994: Improve playback robustness
On WM8994 revision D and earlier ensure proper playback robustness as some rare use cases can trigger issues. Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Cc: stable@kernel.org
-rw-r--r--sound/soc/codecs/wm8994.c59
1 files changed, 52 insertions, 7 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index bd0cfdd1386f..a60b5dbf0154 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -1083,6 +1083,17 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w,
1083 return 0; 1083 return 0;
1084} 1084}
1085 1085
1086static int dac_ev(struct snd_soc_dapm_widget *w,
1087 struct snd_kcontrol *kcontrol, int event)
1088{
1089 struct snd_soc_codec *codec = w->codec;
1090 unsigned int mask = 1 << w->shift;
1091
1092 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5,
1093 mask, mask);
1094 return 0;
1095}
1096
1086static const char *hp_mux_text[] = { 1097static const char *hp_mux_text[] = {
1087 "Mixer", 1098 "Mixer",
1088 "DAC", 1099 "DAC",
@@ -1374,6 +1385,24 @@ SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, NULL, 0),
1374SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0) 1385SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0)
1375}; 1386};
1376 1387
1388static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = {
1389SND_SOC_DAPM_DAC_E("DAC2L", NULL, SND_SOC_NOPM, 3, 0,
1390 dac_ev, SND_SOC_DAPM_PRE_PMU),
1391SND_SOC_DAPM_DAC_E("DAC2R", NULL, SND_SOC_NOPM, 2, 0,
1392 dac_ev, SND_SOC_DAPM_PRE_PMU),
1393SND_SOC_DAPM_DAC_E("DAC1L", NULL, SND_SOC_NOPM, 1, 0,
1394 dac_ev, SND_SOC_DAPM_PRE_PMU),
1395SND_SOC_DAPM_DAC_E("DAC1R", NULL, SND_SOC_NOPM, 0, 0,
1396 dac_ev, SND_SOC_DAPM_PRE_PMU),
1397};
1398
1399static const struct snd_soc_dapm_widget wm8994_dac_widgets[] = {
1400SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0),
1401SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0),
1402SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0),
1403SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0),
1404};
1405
1377static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { 1406static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = {
1378SND_SOC_DAPM_INPUT("DMIC1DAT"), 1407SND_SOC_DAPM_INPUT("DMIC1DAT"),
1379SND_SOC_DAPM_INPUT("DMIC2DAT"), 1408SND_SOC_DAPM_INPUT("DMIC2DAT"),
@@ -1471,11 +1500,6 @@ SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0),
1471SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), 1500SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
1472SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), 1501SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
1473 1502
1474SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0),
1475SND_SOC_DAPM_DAC("DAC2R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0),
1476SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0),
1477SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0),
1478
1479SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), 1503SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
1480SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), 1504SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
1481 1505
@@ -2627,6 +2651,22 @@ static int wm8994_resume(struct snd_soc_codec *codec)
2627{ 2651{
2628 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 2652 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
2629 int i, ret; 2653 int i, ret;
2654 unsigned int val, mask;
2655
2656 if (wm8994->revision < 4) {
2657 /* force a HW read */
2658 val = wm8994_reg_read(codec->control_data,
2659 WM8994_POWER_MANAGEMENT_5);
2660
2661 /* modify the cache only */
2662 codec->cache_only = 1;
2663 mask = WM8994_DAC1R_ENA | WM8994_DAC1L_ENA |
2664 WM8994_DAC2R_ENA | WM8994_DAC2L_ENA;
2665 val &= mask;
2666 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5,
2667 mask, val);
2668 codec->cache_only = 0;
2669 }
2630 2670
2631 /* Restore the registers */ 2671 /* Restore the registers */
2632 ret = snd_soc_cache_sync(codec); 2672 ret = snd_soc_cache_sync(codec);
@@ -3238,12 +3278,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3238 case WM8994: 3278 case WM8994:
3239 snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets, 3279 snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets,
3240 ARRAY_SIZE(wm8994_specific_dapm_widgets)); 3280 ARRAY_SIZE(wm8994_specific_dapm_widgets));
3241 if (wm8994->revision < 4) 3281 if (wm8994->revision < 4) {
3242 snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, 3282 snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets,
3243 ARRAY_SIZE(wm8994_lateclk_revd_widgets)); 3283 ARRAY_SIZE(wm8994_lateclk_revd_widgets));
3244 else 3284 snd_soc_dapm_new_controls(dapm, wm8994_dac_revd_widgets,
3285 ARRAY_SIZE(wm8994_dac_revd_widgets));
3286 } else {
3245 snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, 3287 snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets,
3246 ARRAY_SIZE(wm8994_lateclk_widgets)); 3288 ARRAY_SIZE(wm8994_lateclk_widgets));
3289 snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets,
3290 ARRAY_SIZE(wm8994_dac_widgets));
3291 }
3247 break; 3292 break;
3248 case WM8958: 3293 case WM8958:
3249 snd_soc_add_controls(codec, wm8958_snd_controls, 3294 snd_soc_add_controls(codec, wm8958_snd_controls,