diff options
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/pxa/Kconfig | 8 | ||||
-rw-r--r-- | sound/soc/pxa/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/pxa/z2.c | 246 |
3 files changed, 256 insertions, 0 deletions
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 376e14a9c273..495a36fba360 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
@@ -42,6 +42,14 @@ config SND_PXA2XX_SOC_SPITZ | |||
42 | Say Y if you want to add support for SoC audio on Sharp | 42 | Say Y if you want to add support for SoC audio on Sharp |
43 | Zaurus SL-Cxx00 models (Spitz, Borzoi and Akita). | 43 | Zaurus SL-Cxx00 models (Spitz, Borzoi and Akita). |
44 | 44 | ||
45 | config SND_PXA2XX_SOC_Z2 | ||
46 | tristate "SoC Audio support for Zipit Z2" | ||
47 | depends on SND_PXA2XX_SOC && MACH_ZIPIT2 | ||
48 | select SND_PXA2XX_SOC_I2S | ||
49 | select SND_SOC_WM8750 | ||
50 | help | ||
51 | Say Y if you want to add support for SoC audio on Zipit Z2. | ||
52 | |||
45 | config SND_PXA2XX_SOC_POODLE | 53 | config SND_PXA2XX_SOC_POODLE |
46 | tristate "SoC Audio support for Poodle" | 54 | tristate "SoC Audio support for Poodle" |
47 | depends on SND_PXA2XX_SOC && MACH_POODLE | 55 | depends on SND_PXA2XX_SOC && MACH_POODLE |
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index f3e08fd40ca2..caa03d8f4789 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile | |||
@@ -22,6 +22,7 @@ snd-soc-palm27x-objs := palm27x.o | |||
22 | snd-soc-zylonite-objs := zylonite.o | 22 | snd-soc-zylonite-objs := zylonite.o |
23 | snd-soc-magician-objs := magician.o | 23 | snd-soc-magician-objs := magician.o |
24 | snd-soc-mioa701-objs := mioa701_wm9713.o | 24 | snd-soc-mioa701-objs := mioa701_wm9713.o |
25 | snd-soc-z2-objs := z2.o | ||
25 | snd-soc-imote2-objs := imote2.o | 26 | snd-soc-imote2-objs := imote2.o |
26 | snd-soc-raumfeld-objs := raumfeld.o | 27 | snd-soc-raumfeld-objs := raumfeld.o |
27 | 28 | ||
@@ -36,6 +37,7 @@ obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o | |||
36 | obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o | 37 | obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o |
37 | obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o | 38 | obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o |
38 | obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o | 39 | obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o |
40 | obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o | ||
39 | obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o | 41 | obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o |
40 | obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o | 42 | obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o |
41 | obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o | 43 | obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o |
diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c new file mode 100644 index 000000000000..4e4d2fa8ddc5 --- /dev/null +++ b/sound/soc/pxa/z2.c | |||
@@ -0,0 +1,246 @@ | |||
1 | /* | ||
2 | * linux/sound/soc/pxa/z2.c | ||
3 | * | ||
4 | * SoC Audio driver for Aeronix Zipit Z2 | ||
5 | * | ||
6 | * Copyright (C) 2009 Ken McGuire <kenm@desertweyr.com> | ||
7 | * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/timer.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/gpio.h> | ||
20 | |||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/soc.h> | ||
24 | #include <sound/soc-dapm.h> | ||
25 | #include <sound/jack.h> | ||
26 | |||
27 | #include <asm/mach-types.h> | ||
28 | #include <mach/hardware.h> | ||
29 | #include <mach/audio.h> | ||
30 | #include <mach/z2.h> | ||
31 | |||
32 | #include "../codecs/wm8750.h" | ||
33 | #include "pxa2xx-pcm.h" | ||
34 | #include "pxa2xx-i2s.h" | ||
35 | |||
36 | static struct snd_soc_card snd_soc_z2; | ||
37 | |||
38 | static int z2_hw_params(struct snd_pcm_substream *substream, | ||
39 | struct snd_pcm_hw_params *params) | ||
40 | { | ||
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
42 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
43 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
44 | unsigned int clk = 0; | ||
45 | int ret = 0; | ||
46 | |||
47 | switch (params_rate(params)) { | ||
48 | case 8000: | ||
49 | case 16000: | ||
50 | case 48000: | ||
51 | case 96000: | ||
52 | clk = 12288000; | ||
53 | break; | ||
54 | case 11025: | ||
55 | case 22050: | ||
56 | case 44100: | ||
57 | clk = 11289600; | ||
58 | break; | ||
59 | } | ||
60 | |||
61 | /* set codec DAI configuration */ | ||
62 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
63 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
64 | if (ret < 0) | ||
65 | return ret; | ||
66 | |||
67 | /* set cpu DAI configuration */ | ||
68 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
69 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
70 | if (ret < 0) | ||
71 | return ret; | ||
72 | |||
73 | /* set the codec system clock for DAC and ADC */ | ||
74 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk, | ||
75 | SND_SOC_CLOCK_IN); | ||
76 | if (ret < 0) | ||
77 | return ret; | ||
78 | |||
79 | /* set the I2S system clock as input (unused) */ | ||
80 | ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0, | ||
81 | SND_SOC_CLOCK_IN); | ||
82 | if (ret < 0) | ||
83 | return ret; | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static struct snd_soc_jack hs_jack; | ||
89 | |||
90 | /* Headset jack detection DAPM pins */ | ||
91 | static struct snd_soc_jack_pin hs_jack_pins[] = { | ||
92 | { | ||
93 | .pin = "Mic Jack", | ||
94 | .mask = SND_JACK_MICROPHONE, | ||
95 | }, | ||
96 | { | ||
97 | .pin = "Headphone Jack", | ||
98 | .mask = SND_JACK_HEADPHONE, | ||
99 | }, | ||
100 | }; | ||
101 | |||
102 | /* Headset jack detection gpios */ | ||
103 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { | ||
104 | { | ||
105 | .gpio = GPIO37_ZIPITZ2_HEADSET_DETECT, | ||
106 | .name = "hsdet-gpio", | ||
107 | .report = SND_JACK_HEADSET, | ||
108 | .debounce_time = 200, | ||
109 | }, | ||
110 | }; | ||
111 | |||
112 | /* z2 machine dapm widgets */ | ||
113 | static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = { | ||
114 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
115 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
116 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | ||
117 | |||
118 | /* headset is a mic and mono headphone */ | ||
119 | SND_SOC_DAPM_HP("Headset Jack", NULL), | ||
120 | }; | ||
121 | |||
122 | /* Z2 machine audio_map */ | ||
123 | static const struct snd_soc_dapm_route audio_map[] = { | ||
124 | |||
125 | /* headphone connected to LOUT1, ROUT1 */ | ||
126 | {"Headphone Jack", NULL, "LOUT1"}, | ||
127 | {"Headphone Jack", NULL, "ROUT1"}, | ||
128 | |||
129 | /* ext speaker connected to LOUT2, ROUT2 */ | ||
130 | {"Ext Spk", NULL , "ROUT2"}, | ||
131 | {"Ext Spk", NULL , "LOUT2"}, | ||
132 | |||
133 | /* mic is connected to R input 2 - with bias */ | ||
134 | {"RINPUT2", NULL, "Mic Bias"}, | ||
135 | {"Mic Bias", NULL, "Mic Jack"}, | ||
136 | }; | ||
137 | |||
138 | /* | ||
139 | * Logic for a wm8750 as connected on a Z2 Device | ||
140 | */ | ||
141 | static int z2_wm8750_init(struct snd_soc_codec *codec) | ||
142 | { | ||
143 | int ret; | ||
144 | |||
145 | /* NC codec pins */ | ||
146 | snd_soc_dapm_disable_pin(codec, "LINPUT3"); | ||
147 | snd_soc_dapm_disable_pin(codec, "RINPUT3"); | ||
148 | snd_soc_dapm_disable_pin(codec, "OUT3"); | ||
149 | snd_soc_dapm_disable_pin(codec, "MONO"); | ||
150 | |||
151 | /* Add z2 specific widgets */ | ||
152 | snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets, | ||
153 | ARRAY_SIZE(wm8750_dapm_widgets)); | ||
154 | |||
155 | /* Set up z2 specific audio paths */ | ||
156 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
157 | |||
158 | ret = snd_soc_dapm_sync(codec); | ||
159 | if (ret) | ||
160 | goto err; | ||
161 | |||
162 | /* Jack detection API stuff */ | ||
163 | ret = snd_soc_jack_new(&snd_soc_z2, "Headset Jack", SND_JACK_HEADSET, | ||
164 | &hs_jack); | ||
165 | if (ret) | ||
166 | goto err; | ||
167 | |||
168 | ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), | ||
169 | hs_jack_pins); | ||
170 | if (ret) | ||
171 | goto err; | ||
172 | |||
173 | ret = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), | ||
174 | hs_jack_gpios); | ||
175 | if (ret) | ||
176 | goto err; | ||
177 | |||
178 | return 0; | ||
179 | |||
180 | err: | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | static struct snd_soc_ops z2_ops = { | ||
185 | .hw_params = z2_hw_params, | ||
186 | }; | ||
187 | |||
188 | /* z2 digital audio interface glue - connects codec <--> CPU */ | ||
189 | static struct snd_soc_dai_link z2_dai = { | ||
190 | .name = "wm8750", | ||
191 | .stream_name = "WM8750", | ||
192 | .cpu_dai = &pxa_i2s_dai, | ||
193 | .codec_dai = &wm8750_dai, | ||
194 | .init = z2_wm8750_init, | ||
195 | .ops = &z2_ops, | ||
196 | }; | ||
197 | |||
198 | /* z2 audio machine driver */ | ||
199 | static struct snd_soc_card snd_soc_z2 = { | ||
200 | .name = "Z2", | ||
201 | .platform = &pxa2xx_soc_platform, | ||
202 | .dai_link = &z2_dai, | ||
203 | .num_links = 1, | ||
204 | }; | ||
205 | |||
206 | /* z2 audio subsystem */ | ||
207 | static struct snd_soc_device z2_snd_devdata = { | ||
208 | .card = &snd_soc_z2, | ||
209 | .codec_dev = &soc_codec_dev_wm8750, | ||
210 | }; | ||
211 | |||
212 | static struct platform_device *z2_snd_device; | ||
213 | |||
214 | static int __init z2_init(void) | ||
215 | { | ||
216 | int ret; | ||
217 | |||
218 | if (!machine_is_zipit2()) | ||
219 | return -ENODEV; | ||
220 | |||
221 | z2_snd_device = platform_device_alloc("soc-audio", -1); | ||
222 | if (!z2_snd_device) | ||
223 | return -ENOMEM; | ||
224 | |||
225 | platform_set_drvdata(z2_snd_device, &z2_snd_devdata); | ||
226 | z2_snd_devdata.dev = &z2_snd_device->dev; | ||
227 | ret = platform_device_add(z2_snd_device); | ||
228 | |||
229 | if (ret) | ||
230 | platform_device_put(z2_snd_device); | ||
231 | |||
232 | return ret; | ||
233 | } | ||
234 | |||
235 | static void __exit z2_exit(void) | ||
236 | { | ||
237 | platform_device_unregister(z2_snd_device); | ||
238 | } | ||
239 | |||
240 | module_init(z2_init); | ||
241 | module_exit(z2_exit); | ||
242 | |||
243 | MODULE_AUTHOR("Ken McGuire <kenm@desertweyr.com>, " | ||
244 | "Marek Vasut <marek.vasut@gmail.com>"); | ||
245 | MODULE_DESCRIPTION("ALSA SoC ZipitZ2"); | ||
246 | MODULE_LICENSE("GPL"); | ||