aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-02-09 12:42:55 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-02-09 17:49:52 -0500
commit13a9983eb197254dffd9ea63a2d5f12c54eb651c (patch)
tree7a3461070e40c1bff37cfe798eccc27a121f54b3 /sound
parent1e113bf9e088f1a6f4a1cdadce598ccc340f8fc1 (diff)
ASoC: Convert WM8903 to use PGA_S for output stage enables
This simplfies the code and slightly reduces the startup time. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/wm8903.c180
1 files changed, 60 insertions, 120 deletions
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 0190c5aa44f8..9793775d5798 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -246,6 +246,8 @@ static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int re
246 case WM8903_REVISION_NUMBER: 246 case WM8903_REVISION_NUMBER:
247 case WM8903_INTERRUPT_STATUS_1: 247 case WM8903_INTERRUPT_STATUS_1:
248 case WM8903_WRITE_SEQUENCER_4: 248 case WM8903_WRITE_SEQUENCER_4:
249 case WM8903_POWER_MANAGEMENT_3:
250 case WM8903_POWER_MANAGEMENT_2:
249 return 1; 251 return 1;
250 252
251 default: 253 default:
@@ -304,11 +306,6 @@ static void wm8903_reset(struct snd_soc_codec *codec)
304 sizeof(wm8903_reg_defaults)); 306 sizeof(wm8903_reg_defaults));
305} 307}
306 308
307#define WM8903_OUTPUT_SHORT 0x8
308#define WM8903_OUTPUT_OUT 0x4
309#define WM8903_OUTPUT_INT 0x2
310#define WM8903_OUTPUT_IN 0x1
311
312static int wm8903_cp_event(struct snd_soc_dapm_widget *w, 309static int wm8903_cp_event(struct snd_soc_dapm_widget *w,
313 struct snd_kcontrol *kcontrol, int event) 310 struct snd_kcontrol *kcontrol, int event)
314{ 311{
@@ -319,99 +316,6 @@ static int wm8903_cp_event(struct snd_soc_dapm_widget *w,
319} 316}
320 317
321/* 318/*
322 * Event for headphone and line out amplifier power changes. Special
323 * power up/down sequences are required in order to maximise pop/click
324 * performance.
325 */
326static int wm8903_output_event(struct snd_soc_dapm_widget *w,
327 struct snd_kcontrol *kcontrol, int event)
328{
329 struct snd_soc_codec *codec = w->codec;
330 u16 val;
331 u16 reg;
332 u16 dcs_reg;
333 u16 dcs_bit;
334 int shift;
335
336 switch (w->reg) {
337 case WM8903_POWER_MANAGEMENT_2:
338 reg = WM8903_ANALOGUE_HP_0;
339 dcs_bit = 0 + w->shift;
340 break;
341 case WM8903_POWER_MANAGEMENT_3:
342 reg = WM8903_ANALOGUE_LINEOUT_0;
343 dcs_bit = 2 + w->shift;
344 break;
345 default:
346 BUG();
347 return -EINVAL; /* Spurious warning from some compilers */
348 }
349
350 switch (w->shift) {
351 case 0:
352 shift = 0;
353 break;
354 case 1:
355 shift = 4;
356 break;
357 default:
358 BUG();
359 return -EINVAL; /* Spurious warning from some compilers */
360 }
361
362 if (event & SND_SOC_DAPM_PRE_PMU) {
363 val = snd_soc_read(codec, reg);
364
365 /* Short the output */
366 val &= ~(WM8903_OUTPUT_SHORT << shift);
367 snd_soc_write(codec, reg, val);
368 }
369
370 if (event & SND_SOC_DAPM_POST_PMU) {
371 val = snd_soc_read(codec, reg);
372
373 val |= (WM8903_OUTPUT_IN << shift);
374 snd_soc_write(codec, reg, val);
375
376 val |= (WM8903_OUTPUT_INT << shift);
377 snd_soc_write(codec, reg, val);
378
379 /* Turn on the output ENA_OUTP */
380 val |= (WM8903_OUTPUT_OUT << shift);
381 snd_soc_write(codec, reg, val);
382
383 /* Enable the DC servo */
384 dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0);
385 dcs_reg |= dcs_bit;
386 snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg);
387
388 /* Remove the short */
389 val |= (WM8903_OUTPUT_SHORT << shift);
390 snd_soc_write(codec, reg, val);
391 }
392
393 if (event & SND_SOC_DAPM_PRE_PMD) {
394 val = snd_soc_read(codec, reg);
395
396 /* Short the output */
397 val &= ~(WM8903_OUTPUT_SHORT << shift);
398 snd_soc_write(codec, reg, val);
399
400 /* Disable the DC servo */
401 dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0);
402 dcs_reg &= ~dcs_bit;
403 snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg);
404
405 /* Then disable the intermediate and output stages */
406 val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT |
407 WM8903_OUTPUT_IN) << shift);
408 snd_soc_write(codec, reg, val);
409 }
410
411 return 0;
412}
413
414/*
415 * When used with DAC outputs only the WM8903 charge pump supports 319 * When used with DAC outputs only the WM8903 charge pump supports
416 * operation in class W mode, providing very low power consumption 320 * operation in class W mode, providing very low power consumption
417 * when used with digital sources. Enable and disable this mode 321 * when used with digital sources. Enable and disable this mode
@@ -913,23 +817,40 @@ SND_SOC_DAPM_MIXER("Left Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 1, 0,
913SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0, 817SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0,
914 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), 818 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
915 819
916SND_SOC_DAPM_PGA_E("Left Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, 820SND_SOC_DAPM_PGA_S("Left Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0,
917 1, 0, NULL, 0, wm8903_output_event, 821 4, 0, NULL, 0),
918 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 822SND_SOC_DAPM_PGA_S("Right Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0,
919 SND_SOC_DAPM_PRE_PMD), 823 0, 0, NULL, 0),
920SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, 824
921 0, 0, NULL, 0, wm8903_output_event, 825SND_SOC_DAPM_PGA_S("Left Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 4, 0,
922 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 826 NULL, 0),
923 SND_SOC_DAPM_PRE_PMD), 827SND_SOC_DAPM_PGA_S("Right Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 0, 0,
924 828 NULL, 0),
925SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0, 829
926 NULL, 0, wm8903_output_event, 830SND_SOC_DAPM_PGA_S("HPL_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 7, 0, NULL, 0),
927 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 831SND_SOC_DAPM_PGA_S("HPL_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 6, 0, NULL, 0),
928 SND_SOC_DAPM_PRE_PMD), 832SND_SOC_DAPM_PGA_S("HPL_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 5, 0, NULL, 0),
929SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0, 833SND_SOC_DAPM_PGA_S("HPR_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 3, 0, NULL, 0),
930 NULL, 0, wm8903_output_event, 834SND_SOC_DAPM_PGA_S("HPR_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 2, 0, NULL, 0),
931 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 835SND_SOC_DAPM_PGA_S("HPR_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 1, 0, NULL, 0),
932 SND_SOC_DAPM_PRE_PMD), 836
837SND_SOC_DAPM_PGA_S("LINEOUTL_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 7, 0,
838 NULL, 0),
839SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 6, 0,
840 NULL, 0),
841SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 5, 0,
842 NULL, 0),
843SND_SOC_DAPM_PGA_S("LINEOUTR_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 3, 0,
844 NULL, 0),
845SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 2, 0,
846 NULL, 0),
847SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 1, 0,
848 NULL, 0),
849
850SND_SOC_DAPM_PGA_S("HPL_DCS", 3, WM8903_DC_SERVO_0, 3, 0, NULL, 0),
851SND_SOC_DAPM_PGA_S("HPR_DCS", 3, WM8903_DC_SERVO_0, 2, 0, NULL, 0),
852SND_SOC_DAPM_PGA_S("LINEOUTL_DCS", 3, WM8903_DC_SERVO_0, 1, 0, NULL, 0),
853SND_SOC_DAPM_PGA_S("LINEOUTR_DCS", 3, WM8903_DC_SERVO_0, 0, 0, NULL, 0),
933 854
934SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0, 855SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0,
935 NULL, 0), 856 NULL, 0),
@@ -1045,11 +966,30 @@ static const struct snd_soc_dapm_route intercon[] = {
1045 { "Left Speaker PGA", NULL, "Left Speaker Mixer" }, 966 { "Left Speaker PGA", NULL, "Left Speaker Mixer" },
1046 { "Right Speaker PGA", NULL, "Right Speaker Mixer" }, 967 { "Right Speaker PGA", NULL, "Right Speaker Mixer" },
1047 968
1048 { "HPOUTL", NULL, "Left Headphone Output PGA" }, 969 { "HPL_ENA_DLY", NULL, "Left Headphone Output PGA" },
1049 { "HPOUTR", NULL, "Right Headphone Output PGA" }, 970 { "HPR_ENA_DLY", NULL, "Right Headphone Output PGA" },
1050 971 { "LINEOUTL_ENA_DLY", NULL, "Left Line Output PGA" },
1051 { "LINEOUTL", NULL, "Left Line Output PGA" }, 972 { "LINEOUTR_ENA_DLY", NULL, "Right Line Output PGA" },
1052 { "LINEOUTR", NULL, "Right Line Output PGA" }, 973
974 { "HPL_DCS", NULL, "HPL_ENA_DLY" },
975 { "HPR_DCS", NULL, "HPR_ENA_DLY" },
976 { "LINEOUTL_DCS", NULL, "LINEOUTL_ENA_DLY" },
977 { "LINEOUTR_DCS", NULL, "LINEOUTR_ENA_DLY" },
978
979 { "HPL_ENA_OUTP", NULL, "HPL_DCS" },
980 { "HPR_ENA_OUTP", NULL, "HPR_DCS" },
981 { "LINEOUTL_ENA_OUTP", NULL, "LINEOUTL_DCS" },
982 { "LINEOUTR_ENA_OUTP", NULL, "LINEOUTR_DCS" },
983
984 { "HPL_RMV_SHORT", NULL, "HPL_ENA_OUTP" },
985 { "HPR_RMV_SHORT", NULL, "HPR_ENA_OUTP" },
986 { "LINEOUTL_RMV_SHORT", NULL, "LINEOUTL_ENA_OUTP" },
987 { "LINEOUTR_RMV_SHORT", NULL, "LINEOUTR_ENA_OUTP" },
988
989 { "HPOUTL", NULL, "HPL_RMV_SHORT" },
990 { "HPOUTR", NULL, "HPR_RMV_SHORT" },
991 { "LINEOUTL", NULL, "LINEOUTL_RMV_SHORT" },
992 { "LINEOUTR", NULL, "LINEOUTR_RMV_SHORT" },
1053 993
1054 { "LOP", NULL, "Left Speaker PGA" }, 994 { "LOP", NULL, "Left Speaker PGA" },
1055 { "LON", NULL, "Left Speaker PGA" }, 995 { "LON", NULL, "Left Speaker PGA" },