aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorMarek Vasut <marek.vasut@gmail.com>2010-04-05 00:13:38 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-04-12 06:33:16 -0400
commitd21e0f4cd16656f71207683ee27465600ad21625 (patch)
treee56c403b09ded2dc458a24a10a44279089031fc8 /sound/soc
parente135443e2133473f44aa439ad333554dad14c21a (diff)
ASoC: Zipit Z2 WM8750 ASoC driver
This patch adds support for sound through the WM8750 codec on Zipit Z2. Also, this patch incorporates support for detecting headset jack insertion through the jack detection API. Signed-off-by: Marek Vasut <marek.vasut@gmail.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/pxa/Kconfig8
-rw-r--r--sound/soc/pxa/Makefile2
-rw-r--r--sound/soc/pxa/z2.c246
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
45config 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
45config SND_PXA2XX_SOC_POODLE 53config 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
22snd-soc-zylonite-objs := zylonite.o 22snd-soc-zylonite-objs := zylonite.o
23snd-soc-magician-objs := magician.o 23snd-soc-magician-objs := magician.o
24snd-soc-mioa701-objs := mioa701_wm9713.o 24snd-soc-mioa701-objs := mioa701_wm9713.o
25snd-soc-z2-objs := z2.o
25snd-soc-imote2-objs := imote2.o 26snd-soc-imote2-objs := imote2.o
26snd-soc-raumfeld-objs := raumfeld.o 27snd-soc-raumfeld-objs := raumfeld.o
27 28
@@ -36,6 +37,7 @@ obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
36obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o 37obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
37obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o 38obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o
38obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o 39obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
40obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o
39obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o 41obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
40obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o 42obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o
41obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o 43obj-$(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
36static struct snd_soc_card snd_soc_z2;
37
38static 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
88static struct snd_soc_jack hs_jack;
89
90/* Headset jack detection DAPM pins */
91static 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 */
103static 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 */
113static 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 */
123static 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 */
141static 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
180err:
181 return ret;
182}
183
184static struct snd_soc_ops z2_ops = {
185 .hw_params = z2_hw_params,
186};
187
188/* z2 digital audio interface glue - connects codec <--> CPU */
189static 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 */
199static 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 */
207static struct snd_soc_device z2_snd_devdata = {
208 .card = &snd_soc_z2,
209 .codec_dev = &soc_codec_dev_wm8750,
210};
211
212static struct platform_device *z2_snd_device;
213
214static 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
235static void __exit z2_exit(void)
236{
237 platform_device_unregister(z2_snd_device);
238}
239
240module_init(z2_init);
241module_exit(z2_exit);
242
243MODULE_AUTHOR("Ken McGuire <kenm@desertweyr.com>, "
244 "Marek Vasut <marek.vasut@gmail.com>");
245MODULE_DESCRIPTION("ALSA SoC ZipitZ2");
246MODULE_LICENSE("GPL");