aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/pxa/saarb.c
diff options
context:
space:
mode:
authorHaojian Zhuang <haojian.zhuang@gmail.com>2010-08-18 12:36:30 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-08-18 13:04:55 -0400
commitb6905d0b1652efddb96cefdb3c8552cac8d98ed2 (patch)
treebb7d1814bc8e99ba65ed6631e9ed3c0be468e40d /sound/soc/pxa/saarb.c
parentb0547a70db38ee851a32306ee2e1e43a1e0d28ea (diff)
ASoC: add saarb machine driver for 88pm860x
88PM860x codec is used in Marvell saarb development board. 88PM860x codec is used as master mode for SSP communication. Only I2S format is supported. Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/pxa/saarb.c')
-rw-r--r--sound/soc/pxa/saarb.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/sound/soc/pxa/saarb.c b/sound/soc/pxa/saarb.c
new file mode 100644
index 000000000000..d63cb474b4e1
--- /dev/null
+++ b/sound/soc/pxa/saarb.c
@@ -0,0 +1,200 @@
1/*
2 * saarb.c -- SoC audio for saarb
3 *
4 * Copyright (C) 2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/device.h>
15#include <linux/clk.h>
16#include <linux/i2c.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h>
21#include <sound/soc-dapm.h>
22#include <sound/jack.h>
23
24#include <asm/mach-types.h>
25
26#include "../codecs/88pm860x-codec.h"
27#include "pxa-ssp.h"
28
29static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd);
30
31static struct platform_device *saarb_snd_device;
32
33static struct snd_soc_jack hs_jack, mic_jack;
34
35static struct snd_soc_jack_pin hs_jack_pins[] = {
36 { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, },
37};
38
39static struct snd_soc_jack_pin mic_jack_pins[] = {
40 { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, },
41};
42
43/* saarb machine dapm widgets */
44static const struct snd_soc_dapm_widget saarb_dapm_widgets[] = {
45 SND_SOC_DAPM_HP("Headphone Stereophone", NULL),
46 SND_SOC_DAPM_LINE("Lineout Out 1", NULL),
47 SND_SOC_DAPM_LINE("Lineout Out 2", NULL),
48 SND_SOC_DAPM_SPK("Ext Speaker", NULL),
49 SND_SOC_DAPM_MIC("Ext Mic 1", NULL),
50 SND_SOC_DAPM_MIC("Headset Mic", NULL),
51 SND_SOC_DAPM_MIC("Ext Mic 3", NULL),
52};
53
54/* saarb machine audio map */
55static const struct snd_soc_dapm_route audio_map[] = {
56 {"Headset Stereophone", NULL, "HS1"},
57 {"Headset Stereophone", NULL, "HS2"},
58
59 {"Ext Speaker", NULL, "LSP"},
60 {"Ext Speaker", NULL, "LSN"},
61
62 {"Lineout Out 1", NULL, "LINEOUT1"},
63 {"Lineout Out 2", NULL, "LINEOUT2"},
64
65 {"MIC1P", NULL, "Mic1 Bias"},
66 {"MIC1N", NULL, "Mic1 Bias"},
67 {"Mic1 Bias", NULL, "Ext Mic 1"},
68
69 {"MIC2P", NULL, "Mic1 Bias"},
70 {"MIC2N", NULL, "Mic1 Bias"},
71 {"Mic1 Bias", NULL, "Headset Mic 2"},
72
73 {"MIC3P", NULL, "Mic3 Bias"},
74 {"MIC3N", NULL, "Mic3 Bias"},
75 {"Mic3 Bias", NULL, "Ext Mic 3"},
76};
77
78static int saarb_i2s_hw_params(struct snd_pcm_substream *substream,
79 struct snd_pcm_hw_params *params)
80{
81 struct snd_soc_pcm_runtime *rtd = substream->private_data;
82 struct snd_soc_dai *codec_dai = rtd->codec_dai;
83 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
84 int width = snd_pcm_format_physical_width(params_format(params));
85 int ret;
86
87 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0,
88 PM860X_CLK_DIR_OUT);
89 if (ret < 0)
90 return ret;
91
92 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT);
93 if (ret < 0)
94 return ret;
95
96 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
97 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
98 if (ret < 0)
99 return ret;
100 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
101 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
102 if (ret < 0)
103 return ret;
104
105 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
106
107 return ret;
108}
109
110static struct snd_soc_ops saarb_i2s_ops = {
111 .hw_params = saarb_i2s_hw_params,
112};
113
114static struct snd_soc_dai_link saarb_dai[] = {
115 {
116 .name = "88PM860x I2S",
117 .stream_name = "I2S Audio",
118 .cpu_dai_name = "pxa-ssp-dai.1",
119 .codec_dai_name = "88pm860x-i2s",
120 .platform_name = "pxa-pcm-audio",
121 .codec_name = "88pm860x-codec",
122 .init = saarb_pm860x_init,
123 .ops = &saarb_i2s_ops,
124 },
125};
126
127static struct snd_soc_card snd_soc_card_saarb = {
128 .name = "Saarb",
129 .dai_link = saarb_dai,
130 .num_links = ARRAY_SIZE(saarb_dai),
131};
132
133static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd)
134{
135 struct snd_soc_codec *codec = rtd->codec;
136 int ret;
137
138 snd_soc_dapm_new_controls(codec, saarb_dapm_widgets,
139 ARRAY_SIZE(saarb_dapm_widgets));
140 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
141
142 /* connected pins */
143 snd_soc_dapm_enable_pin(codec, "Ext Speaker");
144 snd_soc_dapm_enable_pin(codec, "Ext Mic 1");
145 snd_soc_dapm_enable_pin(codec, "Ext Mic 3");
146 snd_soc_dapm_disable_pin(codec, "Headset Mic 2");
147 snd_soc_dapm_disable_pin(codec, "Headset Stereophone");
148
149 ret = snd_soc_dapm_sync(codec);
150 if (ret)
151 return ret;
152
153 /* Headset jack detection */
154 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
155 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
156 &hs_jack);
157 snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
158 hs_jack_pins);
159 snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE,
160 &mic_jack);
161 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
162 mic_jack_pins);
163
164 /* headphone, microphone detection & headset short detection */
165 pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE,
166 SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2);
167 pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE);
168 return 0;
169}
170
171static int __init saarb_init(void)
172{
173 int ret;
174
175 if (!machine_is_saarb())
176 return -ENODEV;
177 saarb_snd_device = platform_device_alloc("soc-audio", -1);
178 if (!saarb_snd_device)
179 return -ENOMEM;
180
181 platform_set_drvdata(saarb_snd_device, &snd_soc_card_saarb);
182
183 ret = platform_device_add(saarb_snd_device);
184 if (ret)
185 platform_device_put(saarb_snd_device);
186
187 return ret;
188}
189
190static void __exit saarb_exit(void)
191{
192 platform_device_unregister(saarb_snd_device);
193}
194
195module_init(saarb_init);
196module_exit(saarb_exit);
197
198MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
199MODULE_DESCRIPTION("ALSA SoC 88PM860x Saarb");
200MODULE_LICENSE("GPL");