ASoC: bells: Correct typo in sub speaker DAI name for WM5110
[deliverable/linux.git] / sound / soc / samsung / bells.c
CommitLineData
b545dd92
MB
1/*
2 * Bells audio support
3 *
4 * Copyright 2012 Wolfson Microelectronics
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <sound/soc.h>
13#include <sound/soc-dapm.h>
14#include <sound/jack.h>
15#include <linux/gpio.h>
16#include <linux/module.h>
17
18#include "../codecs/wm5102.h"
19#include "../codecs/wm9081.h"
20
21/*
22 * 44.1kHz based clocks for the SYSCLK domain, use a very high clock
23 * to allow all the DSP functionality to be enabled if desired.
24 */
25#define SYSCLK_RATE (44100 * 1024)
26
27/* 48kHz based clocks for the ASYNC domain */
28#define ASYNCCLK_RATE (48000 * 512)
29
30/* BCLK2 is fixed at this currently */
31#define BCLK2_RATE (64 * 8000)
32
33/*
34 * Expect a 24.576MHz crystal if one is fitted (the driver will function
35 * if this is not fitted).
36 */
37#define MCLK_RATE 24576000
38
344c5ede
MB
39#define SYS_AUDIO_RATE 44100
40#define SYS_MCLK_RATE (SYS_AUDIO_RATE * 256)
41
42#define DAI_AP_DSP 0
43#define DAI_DSP_CODEC 1
44#define DAI_CODEC_CP 2
45#define DAI_CODEC_SUB 3
b545dd92
MB
46
47static int bells_set_bias_level(struct snd_soc_card *card,
48 struct snd_soc_dapm_context *dapm,
49 enum snd_soc_bias_level level)
50{
344c5ede 51 struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
b545dd92
MB
52 struct snd_soc_codec *codec = codec_dai->codec;
53 int ret;
54
55 if (dapm->dev != codec_dai->dev)
56 return 0;
57
58 switch (level) {
59 case SND_SOC_BIAS_PREPARE:
60 if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
61 ret = snd_soc_codec_set_pll(codec, WM5102_FLL1,
62 ARIZONA_FLL_SRC_MCLK1,
63 MCLK_RATE,
64 SYSCLK_RATE);
65 if (ret < 0)
66 pr_err("Failed to start FLL: %d\n", ret);
67
68 ret = snd_soc_codec_set_pll(codec, WM5102_FLL2,
69 ARIZONA_FLL_SRC_AIF2BCLK,
70 BCLK2_RATE,
71 ASYNCCLK_RATE);
72 if (ret < 0)
73 pr_err("Failed to start FLL: %d\n", ret);
74 }
75 break;
76
77 default:
78 break;
79 }
80
81 return 0;
82}
83
84static int bells_set_bias_level_post(struct snd_soc_card *card,
85 struct snd_soc_dapm_context *dapm,
86 enum snd_soc_bias_level level)
87{
344c5ede 88 struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
b545dd92
MB
89 struct snd_soc_codec *codec = codec_dai->codec;
90 int ret;
91
92 if (dapm->dev != codec_dai->dev)
93 return 0;
94
95 switch (level) {
96 case SND_SOC_BIAS_STANDBY:
97 ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, 0, 0, 0);
98 if (ret < 0) {
99 pr_err("Failed to stop FLL: %d\n", ret);
100 return ret;
101 }
102
103 ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 0, 0, 0);
104 if (ret < 0) {
105 pr_err("Failed to stop FLL: %d\n", ret);
106 return ret;
107 }
108 break;
109
110 default:
111 break;
112 }
113
114 dapm->bias_level = level;
115
116 return 0;
117}
118
119static int bells_late_probe(struct snd_soc_card *card)
120{
344c5ede
MB
121 struct snd_soc_codec *wm0010 = card->rtd[DAI_AP_DSP].codec;
122 struct snd_soc_codec *codec = card->rtd[DAI_DSP_CODEC].codec;
123 struct snd_soc_dai *aif1_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
124 struct snd_soc_dai *aif2_dai = card->rtd[DAI_CODEC_CP].cpu_dai;
125 struct snd_soc_dai *aif3_dai = card->rtd[DAI_CODEC_SUB].cpu_dai;
126 struct snd_soc_dai *wm9081_dai = card->rtd[DAI_CODEC_SUB].codec_dai;
b545dd92
MB
127 int ret;
128
344c5ede
MB
129 ret = snd_soc_codec_set_sysclk(wm0010, 0, 0, SYS_MCLK_RATE, 0);
130 if (ret != 0) {
131 dev_err(wm0010->dev, "Failed to set WM0010 clock: %d\n", ret);
132 return ret;
133 }
134
b545dd92
MB
135 ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
136 if (ret != 0) {
137 dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
138 return ret;
139 }
140
141 ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
142 if (ret != 0) {
143 dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
144 return ret;
145 }
146
147 ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
148 if (ret != 0) {
149 dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
150 return ret;
151 }
152
153 ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
154 ARIZONA_CLK_SRC_FLL1, SYSCLK_RATE,
155 SND_SOC_CLOCK_IN);
156 if (ret != 0) {
157 dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
158 return ret;
159 }
160
161 ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0,
344c5ede 162 SYS_MCLK_RATE, SND_SOC_CLOCK_OUT);
b545dd92
MB
163 if (ret != 0) {
164 dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret);
165 return ret;
166 }
167
168 ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK,
169 ARIZONA_CLK_SRC_FLL2, ASYNCCLK_RATE,
170 SND_SOC_CLOCK_IN);
171 if (ret != 0) {
172 dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
173 return ret;
174 }
175
176 ret = snd_soc_codec_set_sysclk(wm9081_dai->codec, WM9081_SYSCLK_MCLK,
344c5ede 177 0, SYS_MCLK_RATE, 0);
b545dd92
MB
178 if (ret != 0) {
179 dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret);
180 return ret;
181 }
182
183 return 0;
184}
185
186static const struct snd_soc_pcm_stream baseband_params = {
187 .formats = SNDRV_PCM_FMTBIT_S32_LE,
188 .rate_min = 8000,
189 .rate_max = 8000,
190 .channels_min = 2,
191 .channels_max = 2,
192};
193
194static const struct snd_soc_pcm_stream sub_params = {
195 .formats = SNDRV_PCM_FMTBIT_S32_LE,
344c5ede
MB
196 .rate_min = SYS_AUDIO_RATE,
197 .rate_max = SYS_AUDIO_RATE,
b545dd92
MB
198 .channels_min = 2,
199 .channels_max = 2,
200};
201
202static struct snd_soc_dai_link bells_dai_wm5102[] = {
203 {
344c5ede
MB
204 .name = "CPU-DSP",
205 .stream_name = "CPU-DSP",
b545dd92 206 .cpu_dai_name = "samsung-i2s.0",
344c5ede 207 .codec_dai_name = "wm0010-sdi1",
b545dd92 208 .platform_name = "samsung-audio",
344c5ede
MB
209 .codec_name = "spi0.0",
210 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
211 | SND_SOC_DAIFMT_CBM_CFM,
212 },
213 {
214 .name = "DSP-CODEC",
215 .stream_name = "DSP-CODEC",
216 .cpu_dai_name = "wm0010-sdi2",
217 .codec_dai_name = "wm5102-aif1",
b545dd92
MB
218 .codec_name = "wm5102-codec",
219 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
220 | SND_SOC_DAIFMT_CBM_CFM,
344c5ede
MB
221 .params = &sub_params,
222 .ignore_suspend = 1,
b545dd92
MB
223 },
224 {
225 .name = "Baseband",
226 .stream_name = "Baseband",
227 .cpu_dai_name = "wm5102-aif2",
228 .codec_dai_name = "wm1250-ev1",
229 .codec_name = "wm1250-ev1.1-0027",
230 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
231 | SND_SOC_DAIFMT_CBM_CFM,
232 .ignore_suspend = 1,
233 .params = &baseband_params,
234 },
235 {
236 .name = "Sub",
237 .stream_name = "Sub",
238 .cpu_dai_name = "wm5102-aif3",
239 .codec_dai_name = "wm9081-hifi",
240 .codec_name = "wm9081.1-006c",
241 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
242 | SND_SOC_DAIFMT_CBS_CFS,
243 .ignore_suspend = 1,
244 .params = &sub_params,
245 },
246};
247
248static struct snd_soc_dai_link bells_dai_wm5110[] = {
249 {
344c5ede
MB
250 .name = "CPU-DSP",
251 .stream_name = "CPU-DSP",
b545dd92 252 .cpu_dai_name = "samsung-i2s.0",
344c5ede 253 .codec_dai_name = "wm0010-sdi1",
b545dd92 254 .platform_name = "samsung-audio",
344c5ede
MB
255 .codec_name = "spi0.0",
256 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
257 | SND_SOC_DAIFMT_CBM_CFM,
258 },
259 {
260 .name = "DSP-CODEC",
261 .stream_name = "DSP-CODEC",
262 .cpu_dai_name = "wm0010-sdi2",
263 .codec_dai_name = "wm5110-aif1",
b545dd92
MB
264 .codec_name = "wm5110-codec",
265 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
266 | SND_SOC_DAIFMT_CBM_CFM,
344c5ede
MB
267 .params = &sub_params,
268 .ignore_suspend = 1,
b545dd92
MB
269 },
270 {
271 .name = "Baseband",
272 .stream_name = "Baseband",
273 .cpu_dai_name = "wm5110-aif2",
274 .codec_dai_name = "wm1250-ev1",
275 .codec_name = "wm1250-ev1.1-0027",
276 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
277 | SND_SOC_DAIFMT_CBM_CFM,
278 .ignore_suspend = 1,
279 .params = &baseband_params,
280 },
281 {
282 .name = "Sub",
283 .stream_name = "Sub",
ffaa839b 284 .cpu_dai_name = "wm5110-aif3",
b545dd92
MB
285 .codec_dai_name = "wm9081-hifi",
286 .codec_name = "wm9081.1-006c",
287 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
288 | SND_SOC_DAIFMT_CBS_CFS,
289 .ignore_suspend = 1,
290 .params = &sub_params,
291 },
292};
293
294static struct snd_soc_codec_conf bells_codec_conf[] = {
295 {
296 .dev_name = "wm9081.1-006c",
297 .name_prefix = "Sub",
298 },
299};
300
301static struct snd_soc_dapm_route bells_routes[] = {
302 { "Sub CLK_SYS", NULL, "OPCLK" },
303};
304
305static struct snd_soc_card bells_cards[] = {
306 {
307 .name = "Bells WM5102",
308 .owner = THIS_MODULE,
309 .dai_link = bells_dai_wm5102,
310 .num_links = ARRAY_SIZE(bells_dai_wm5102),
311 .codec_conf = bells_codec_conf,
312 .num_configs = ARRAY_SIZE(bells_codec_conf),
313
314 .late_probe = bells_late_probe,
315
316 .dapm_routes = bells_routes,
317 .num_dapm_routes = ARRAY_SIZE(bells_routes),
318
319 .set_bias_level = bells_set_bias_level,
320 .set_bias_level_post = bells_set_bias_level_post,
321 },
322 {
323 .name = "Bells WM5110",
324 .owner = THIS_MODULE,
325 .dai_link = bells_dai_wm5110,
326 .num_links = ARRAY_SIZE(bells_dai_wm5110),
327 .codec_conf = bells_codec_conf,
328 .num_configs = ARRAY_SIZE(bells_codec_conf),
329
330 .late_probe = bells_late_probe,
331
332 .dapm_routes = bells_routes,
333 .num_dapm_routes = ARRAY_SIZE(bells_routes),
334
335 .set_bias_level = bells_set_bias_level,
336 .set_bias_level_post = bells_set_bias_level_post,
337 },
338};
339
340
341static __devinit int bells_probe(struct platform_device *pdev)
342{
343 int ret;
344
345 bells_cards[pdev->id].dev = &pdev->dev;
346
347 ret = snd_soc_register_card(&bells_cards[pdev->id]);
348 if (ret) {
349 dev_err(&pdev->dev,
350 "snd_soc_register_card(%s) failed: %d\n",
351 bells_cards[pdev->id].name, ret);
352 return ret;
353 }
354
355 return 0;
356}
357
358static int __devexit bells_remove(struct platform_device *pdev)
359{
360 snd_soc_unregister_card(&bells_cards[pdev->id]);
361
362 return 0;
363}
364
365static struct platform_driver bells_driver = {
366 .driver = {
367 .name = "bells",
368 .owner = THIS_MODULE,
369 .pm = &snd_soc_pm_ops,
370 },
371 .probe = bells_probe,
372 .remove = __devexit_p(bells_remove),
373};
374
375module_platform_driver(bells_driver);
376
377MODULE_DESCRIPTION("Bells audio support");
378MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
379MODULE_LICENSE("GPL");
380MODULE_ALIAS("platform:bells");
This page took 0.045011 seconds and 5 git commands to generate.