diff options
author | Dimitris Papastamos <dp@opensource.wolfsonmicro.com> | 2011-02-11 11:32:12 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-02-13 14:45:01 -0500 |
commit | c52fd021bc027a90a10782c0dcf667ac0135e478 (patch) | |
tree | f01f88c04ee4aacfd898aea8b0e09bd66e67c45b | |
parent | 173efa09e4c807a2a764509ddd593ad13a44d1df (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.c | 59 |
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 | ||
1086 | static 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 | |||
1086 | static const char *hp_mux_text[] = { | 1097 | static 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), | |||
1374 | SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0) | 1385 | SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, NULL, 0) |
1375 | }; | 1386 | }; |
1376 | 1387 | ||
1388 | static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = { | ||
1389 | SND_SOC_DAPM_DAC_E("DAC2L", NULL, SND_SOC_NOPM, 3, 0, | ||
1390 | dac_ev, SND_SOC_DAPM_PRE_PMU), | ||
1391 | SND_SOC_DAPM_DAC_E("DAC2R", NULL, SND_SOC_NOPM, 2, 0, | ||
1392 | dac_ev, SND_SOC_DAPM_PRE_PMU), | ||
1393 | SND_SOC_DAPM_DAC_E("DAC1L", NULL, SND_SOC_NOPM, 1, 0, | ||
1394 | dac_ev, SND_SOC_DAPM_PRE_PMU), | ||
1395 | SND_SOC_DAPM_DAC_E("DAC1R", NULL, SND_SOC_NOPM, 0, 0, | ||
1396 | dac_ev, SND_SOC_DAPM_PRE_PMU), | ||
1397 | }; | ||
1398 | |||
1399 | static const struct snd_soc_dapm_widget wm8994_dac_widgets[] = { | ||
1400 | SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0), | ||
1401 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), | ||
1402 | SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0), | ||
1403 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), | ||
1404 | }; | ||
1405 | |||
1377 | static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { | 1406 | static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { |
1378 | SND_SOC_DAPM_INPUT("DMIC1DAT"), | 1407 | SND_SOC_DAPM_INPUT("DMIC1DAT"), |
1379 | SND_SOC_DAPM_INPUT("DMIC2DAT"), | 1408 | SND_SOC_DAPM_INPUT("DMIC2DAT"), |
@@ -1471,11 +1500,6 @@ SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), | |||
1471 | SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), | 1500 | SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), |
1472 | SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), | 1501 | SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), |
1473 | 1502 | ||
1474 | SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0), | ||
1475 | SND_SOC_DAPM_DAC("DAC2R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), | ||
1476 | SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0), | ||
1477 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), | ||
1478 | |||
1479 | SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), | 1503 | SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), |
1480 | SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), | 1504 | SND_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, |