diff options
Diffstat (limited to 'sound/soc/pxa/e800_wm9712.c')
-rw-r--r-- | sound/soc/pxa/e800_wm9712.c | 115 |
1 files changed, 100 insertions, 15 deletions
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 2e3386dfa0f0..bc019cdce429 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * e800-wm9712.c -- SoC audio for e800 | 2 | * e800-wm9712.c -- SoC audio for e800 |
3 | * | 3 | * |
4 | * Based on tosa.c | ||
5 | * | ||
6 | * Copyright 2007 (c) Ian Molton <spyro@f2s.com> | 4 | * Copyright 2007 (c) Ian Molton <spyro@f2s.com> |
7 | * | 5 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
@@ -13,7 +11,7 @@ | |||
13 | 11 | ||
14 | #include <linux/module.h> | 12 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | 13 | #include <linux/moduleparam.h> |
16 | #include <linux/device.h> | 14 | #include <linux/gpio.h> |
17 | 15 | ||
18 | #include <sound/core.h> | 16 | #include <sound/core.h> |
19 | #include <sound/pcm.h> | 17 | #include <sound/pcm.h> |
@@ -21,23 +19,85 @@ | |||
21 | #include <sound/soc-dapm.h> | 19 | #include <sound/soc-dapm.h> |
22 | 20 | ||
23 | #include <asm/mach-types.h> | 21 | #include <asm/mach-types.h> |
24 | #include <mach/pxa-regs.h> | ||
25 | #include <mach/hardware.h> | ||
26 | #include <mach/audio.h> | 22 | #include <mach/audio.h> |
23 | #include <mach/eseries-gpio.h> | ||
27 | 24 | ||
28 | #include "../codecs/wm9712.h" | 25 | #include "../codecs/wm9712.h" |
29 | #include "pxa2xx-pcm.h" | 26 | #include "pxa2xx-pcm.h" |
30 | #include "pxa2xx-ac97.h" | 27 | #include "pxa2xx-ac97.h" |
31 | 28 | ||
32 | static struct snd_soc_card e800; | 29 | static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, |
30 | struct snd_kcontrol *kcontrol, int event) | ||
31 | { | ||
32 | if (event & SND_SOC_DAPM_PRE_PMU) | ||
33 | gpio_set_value(GPIO_E800_SPK_AMP_ON, 1); | ||
34 | else if (event & SND_SOC_DAPM_POST_PMD) | ||
35 | gpio_set_value(GPIO_E800_SPK_AMP_ON, 0); | ||
33 | 36 | ||
34 | static struct snd_soc_dai_link e800_dai[] = { | 37 | return 0; |
38 | } | ||
39 | |||
40 | static int e800_hp_amp_event(struct snd_soc_dapm_widget *w, | ||
41 | struct snd_kcontrol *kcontrol, int event) | ||
42 | { | ||
43 | if (event & SND_SOC_DAPM_PRE_PMU) | ||
44 | gpio_set_value(GPIO_E800_HP_AMP_OFF, 0); | ||
45 | else if (event & SND_SOC_DAPM_POST_PMD) | ||
46 | gpio_set_value(GPIO_E800_HP_AMP_OFF, 1); | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static const struct snd_soc_dapm_widget e800_dapm_widgets[] = { | ||
52 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
53 | SND_SOC_DAPM_MIC("Mic (Internal1)", NULL), | ||
54 | SND_SOC_DAPM_MIC("Mic (Internal2)", NULL), | ||
55 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
56 | SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
57 | e800_hp_amp_event, SND_SOC_DAPM_PRE_PMU | | ||
58 | SND_SOC_DAPM_POST_PMD), | ||
59 | SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0, | ||
60 | e800_spk_amp_event, SND_SOC_DAPM_PRE_PMU | | ||
61 | SND_SOC_DAPM_POST_PMD), | ||
62 | }; | ||
63 | |||
64 | static const struct snd_soc_dapm_route audio_map[] = { | ||
65 | {"Headphone Jack", NULL, "HPOUTL"}, | ||
66 | {"Headphone Jack", NULL, "HPOUTR"}, | ||
67 | {"Headphone Jack", NULL, "Headphone Amp"}, | ||
68 | |||
69 | {"Speaker Amp", NULL, "MONOOUT"}, | ||
70 | {"Speaker", NULL, "Speaker Amp"}, | ||
71 | |||
72 | {"MIC1", NULL, "Mic (Internal1)"}, | ||
73 | {"MIC2", NULL, "Mic (Internal2)"}, | ||
74 | }; | ||
75 | |||
76 | static int e800_ac97_init(struct snd_soc_codec *codec) | ||
35 | { | 77 | { |
36 | .name = "AC97 Aux", | 78 | snd_soc_dapm_new_controls(codec, e800_dapm_widgets, |
37 | .stream_name = "AC97 Aux", | 79 | ARRAY_SIZE(e800_dapm_widgets)); |
38 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | 80 | |
39 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], | 81 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
40 | }, | 82 | snd_soc_dapm_sync(codec); |
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static struct snd_soc_dai_link e800_dai[] = { | ||
88 | { | ||
89 | .name = "AC97", | ||
90 | .stream_name = "AC97 HiFi", | ||
91 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | ||
92 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], | ||
93 | .init = e800_ac97_init, | ||
94 | }, | ||
95 | { | ||
96 | .name = "AC97 Aux", | ||
97 | .stream_name = "AC97 Aux", | ||
98 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | ||
99 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], | ||
100 | }, | ||
41 | }; | 101 | }; |
42 | 102 | ||
43 | static struct snd_soc_card e800 = { | 103 | static struct snd_soc_card e800 = { |
@@ -61,6 +121,22 @@ static int __init e800_init(void) | |||
61 | if (!machine_is_e800()) | 121 | if (!machine_is_e800()) |
62 | return -ENODEV; | 122 | return -ENODEV; |
63 | 123 | ||
124 | ret = gpio_request(GPIO_E800_HP_AMP_OFF, "Headphone amp"); | ||
125 | if (ret) | ||
126 | return ret; | ||
127 | |||
128 | ret = gpio_request(GPIO_E800_SPK_AMP_ON, "Speaker amp"); | ||
129 | if (ret) | ||
130 | goto free_hp_amp_gpio; | ||
131 | |||
132 | ret = gpio_direction_output(GPIO_E800_HP_AMP_OFF, 1); | ||
133 | if (ret) | ||
134 | goto free_spk_amp_gpio; | ||
135 | |||
136 | ret = gpio_direction_output(GPIO_E800_SPK_AMP_ON, 1); | ||
137 | if (ret) | ||
138 | goto free_spk_amp_gpio; | ||
139 | |||
64 | e800_snd_device = platform_device_alloc("soc-audio", -1); | 140 | e800_snd_device = platform_device_alloc("soc-audio", -1); |
65 | if (!e800_snd_device) | 141 | if (!e800_snd_device) |
66 | return -ENOMEM; | 142 | return -ENOMEM; |
@@ -69,8 +145,15 @@ static int __init e800_init(void) | |||
69 | e800_snd_devdata.dev = &e800_snd_device->dev; | 145 | e800_snd_devdata.dev = &e800_snd_device->dev; |
70 | ret = platform_device_add(e800_snd_device); | 146 | ret = platform_device_add(e800_snd_device); |
71 | 147 | ||
72 | if (ret) | 148 | if (!ret) |
73 | platform_device_put(e800_snd_device); | 149 | return 0; |
150 | |||
151 | /* Fail gracefully */ | ||
152 | platform_device_put(e800_snd_device); | ||
153 | free_spk_amp_gpio: | ||
154 | gpio_free(GPIO_E800_SPK_AMP_ON); | ||
155 | free_hp_amp_gpio: | ||
156 | gpio_free(GPIO_E800_HP_AMP_OFF); | ||
74 | 157 | ||
75 | return ret; | 158 | return ret; |
76 | } | 159 | } |
@@ -78,6 +161,8 @@ static int __init e800_init(void) | |||
78 | static void __exit e800_exit(void) | 161 | static void __exit e800_exit(void) |
79 | { | 162 | { |
80 | platform_device_unregister(e800_snd_device); | 163 | platform_device_unregister(e800_snd_device); |
164 | gpio_free(GPIO_E800_SPK_AMP_ON); | ||
165 | gpio_free(GPIO_E800_HP_AMP_OFF); | ||
81 | } | 166 | } |
82 | 167 | ||
83 | module_init(e800_init); | 168 | module_init(e800_init); |
@@ -86,4 +171,4 @@ module_exit(e800_exit); | |||
86 | /* Module information */ | 171 | /* Module information */ |
87 | MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); | 172 | MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); |
88 | MODULE_DESCRIPTION("ALSA SoC driver for e800"); | 173 | MODULE_DESCRIPTION("ALSA SoC driver for e800"); |
89 | MODULE_LICENSE("GPL"); | 174 | MODULE_LICENSE("GPL v2"); |