141ce2ac0SSylwester Nawrocki // SPDX-License-Identifier: GPL-2.0+
241ce2ac0SSylwester Nawrocki //
341ce2ac0SSylwester Nawrocki // Bells audio support
441ce2ac0SSylwester Nawrocki //
541ce2ac0SSylwester Nawrocki // Copyright 2012 Wolfson Microelectronics
6b545dd92SMark Brown
7b545dd92SMark Brown #include <sound/soc.h>
8b545dd92SMark Brown #include <sound/soc-dapm.h>
9b545dd92SMark Brown #include <sound/jack.h>
10b545dd92SMark Brown #include <linux/gpio.h>
11b545dd92SMark Brown #include <linux/module.h>
12b545dd92SMark Brown
13b545dd92SMark Brown #include "../codecs/wm5102.h"
14b545dd92SMark Brown #include "../codecs/wm9081.h"
15b545dd92SMark Brown
16b545dd92SMark Brown /* BCLK2 is fixed at this currently */
17b545dd92SMark Brown #define BCLK2_RATE (64 * 8000)
18b545dd92SMark Brown
19b545dd92SMark Brown /*
20b545dd92SMark Brown * Expect a 24.576MHz crystal if one is fitted (the driver will function
21b545dd92SMark Brown * if this is not fitted).
22b545dd92SMark Brown */
23b545dd92SMark Brown #define MCLK_RATE 24576000
24b545dd92SMark Brown
25344c5edeSMark Brown #define SYS_AUDIO_RATE 44100
26208229ecSDimitris Papastamos #define SYS_MCLK_RATE (SYS_AUDIO_RATE * 512)
27344c5edeSMark Brown
28344c5edeSMark Brown #define DAI_AP_DSP 0
29344c5edeSMark Brown #define DAI_DSP_CODEC 1
30344c5edeSMark Brown #define DAI_CODEC_CP 2
31344c5edeSMark Brown #define DAI_CODEC_SUB 3
32b545dd92SMark Brown
33b1387078SMark Brown struct bells_drvdata {
34b1387078SMark Brown int sysclk_rate;
35b1387078SMark Brown int asyncclk_rate;
36b1387078SMark Brown };
37b1387078SMark Brown
388d47e8a5SMark Brown static struct bells_drvdata wm2200_drvdata = {
398d47e8a5SMark Brown .sysclk_rate = 22579200,
408d47e8a5SMark Brown };
418d47e8a5SMark Brown
42b1387078SMark Brown static struct bells_drvdata wm5102_drvdata = {
43b1387078SMark Brown .sysclk_rate = 45158400,
44b1387078SMark Brown .asyncclk_rate = 49152000,
45b1387078SMark Brown };
46b1387078SMark Brown
47b1387078SMark Brown static struct bells_drvdata wm5110_drvdata = {
48b1387078SMark Brown .sysclk_rate = 135475200,
49b1387078SMark Brown .asyncclk_rate = 147456000,
50b1387078SMark Brown };
51b1387078SMark Brown
bells_set_bias_level(struct snd_soc_card * card,struct snd_soc_dapm_context * dapm,enum snd_soc_bias_level level)52b545dd92SMark Brown static int bells_set_bias_level(struct snd_soc_card *card,
53b545dd92SMark Brown struct snd_soc_dapm_context *dapm,
54b545dd92SMark Brown enum snd_soc_bias_level level)
55b545dd92SMark Brown {
565015920aSMengdong Lin struct snd_soc_pcm_runtime *rtd;
575015920aSMengdong Lin struct snd_soc_dai *codec_dai;
58f4a2be1cSKuninori Morimoto struct snd_soc_component *component;
59b1387078SMark Brown struct bells_drvdata *bells = card->drvdata;
60b545dd92SMark Brown int ret;
61b545dd92SMark Brown
624468189fSKuninori Morimoto rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]);
637de6b6bcSKuninori Morimoto codec_dai = asoc_rtd_to_codec(rtd, 0);
64f4a2be1cSKuninori Morimoto component = codec_dai->component;
655015920aSMengdong Lin
66b545dd92SMark Brown if (dapm->dev != codec_dai->dev)
67b545dd92SMark Brown return 0;
68b545dd92SMark Brown
69b545dd92SMark Brown switch (level) {
70b545dd92SMark Brown case SND_SOC_BIAS_PREPARE:
71b1387078SMark Brown if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
72b1387078SMark Brown break;
73b1387078SMark Brown
74f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_pll(component, WM5102_FLL1,
75b545dd92SMark Brown ARIZONA_FLL_SRC_MCLK1,
76b545dd92SMark Brown MCLK_RATE,
77b1387078SMark Brown bells->sysclk_rate);
78b545dd92SMark Brown if (ret < 0)
79b545dd92SMark Brown pr_err("Failed to start FLL: %d\n", ret);
80b545dd92SMark Brown
81b1387078SMark Brown if (bells->asyncclk_rate) {
82f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_pll(component, WM5102_FLL2,
83b545dd92SMark Brown ARIZONA_FLL_SRC_AIF2BCLK,
84b545dd92SMark Brown BCLK2_RATE,
85b1387078SMark Brown bells->asyncclk_rate);
86b545dd92SMark Brown if (ret < 0)
87b545dd92SMark Brown pr_err("Failed to start FLL: %d\n", ret);
88b545dd92SMark Brown }
89b545dd92SMark Brown break;
90b545dd92SMark Brown
91b545dd92SMark Brown default:
92b545dd92SMark Brown break;
93b545dd92SMark Brown }
94b545dd92SMark Brown
95b545dd92SMark Brown return 0;
96b545dd92SMark Brown }
97b545dd92SMark Brown
bells_set_bias_level_post(struct snd_soc_card * card,struct snd_soc_dapm_context * dapm,enum snd_soc_bias_level level)98b545dd92SMark Brown static int bells_set_bias_level_post(struct snd_soc_card *card,
99b545dd92SMark Brown struct snd_soc_dapm_context *dapm,
100b545dd92SMark Brown enum snd_soc_bias_level level)
101b545dd92SMark Brown {
1025015920aSMengdong Lin struct snd_soc_pcm_runtime *rtd;
1035015920aSMengdong Lin struct snd_soc_dai *codec_dai;
104f4a2be1cSKuninori Morimoto struct snd_soc_component *component;
105b1387078SMark Brown struct bells_drvdata *bells = card->drvdata;
106b545dd92SMark Brown int ret;
107b545dd92SMark Brown
1084468189fSKuninori Morimoto rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]);
1097de6b6bcSKuninori Morimoto codec_dai = asoc_rtd_to_codec(rtd, 0);
110f4a2be1cSKuninori Morimoto component = codec_dai->component;
1115015920aSMengdong Lin
112b545dd92SMark Brown if (dapm->dev != codec_dai->dev)
113b545dd92SMark Brown return 0;
114b545dd92SMark Brown
115b545dd92SMark Brown switch (level) {
116b545dd92SMark Brown case SND_SOC_BIAS_STANDBY:
117f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_pll(component, WM5102_FLL1, 0, 0, 0);
118b545dd92SMark Brown if (ret < 0) {
119b545dd92SMark Brown pr_err("Failed to stop FLL: %d\n", ret);
120b545dd92SMark Brown return ret;
121b545dd92SMark Brown }
122b545dd92SMark Brown
123b1387078SMark Brown if (bells->asyncclk_rate) {
124f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_pll(component, WM5102_FLL2,
125b1387078SMark Brown 0, 0, 0);
126b545dd92SMark Brown if (ret < 0) {
127b545dd92SMark Brown pr_err("Failed to stop FLL: %d\n", ret);
128b545dd92SMark Brown return ret;
129b545dd92SMark Brown }
130b1387078SMark Brown }
131b545dd92SMark Brown break;
132b545dd92SMark Brown
133b545dd92SMark Brown default:
134b545dd92SMark Brown break;
135b545dd92SMark Brown }
136b545dd92SMark Brown
137b545dd92SMark Brown dapm->bias_level = level;
138b545dd92SMark Brown
139b545dd92SMark Brown return 0;
140b545dd92SMark Brown }
141b545dd92SMark Brown
bells_late_probe(struct snd_soc_card * card)142b545dd92SMark Brown static int bells_late_probe(struct snd_soc_card *card)
143b545dd92SMark Brown {
144b1387078SMark Brown struct bells_drvdata *bells = card->drvdata;
1455015920aSMengdong Lin struct snd_soc_pcm_runtime *rtd;
146f4a2be1cSKuninori Morimoto struct snd_soc_component *wm0010;
147f4a2be1cSKuninori Morimoto struct snd_soc_component *component;
1485015920aSMengdong Lin struct snd_soc_dai *aif1_dai;
149b1387078SMark Brown struct snd_soc_dai *aif2_dai;
150b1387078SMark Brown struct snd_soc_dai *aif3_dai;
151b1387078SMark Brown struct snd_soc_dai *wm9081_dai;
152b545dd92SMark Brown int ret;
153b545dd92SMark Brown
1544468189fSKuninori Morimoto rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_AP_DSP]);
1557de6b6bcSKuninori Morimoto wm0010 = asoc_rtd_to_codec(rtd, 0)->component;
1565015920aSMengdong Lin
1574468189fSKuninori Morimoto rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]);
1587de6b6bcSKuninori Morimoto component = asoc_rtd_to_codec(rtd, 0)->component;
1597de6b6bcSKuninori Morimoto aif1_dai = asoc_rtd_to_codec(rtd, 0);
1605015920aSMengdong Lin
161f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_SYSCLK,
162b1387078SMark Brown ARIZONA_CLK_SRC_FLL1,
163b1387078SMark Brown bells->sysclk_rate,
164b1387078SMark Brown SND_SOC_CLOCK_IN);
165b1387078SMark Brown if (ret != 0) {
166f4a2be1cSKuninori Morimoto dev_err(component->dev, "Failed to set SYSCLK: %d\n", ret);
167b1387078SMark Brown return ret;
168b1387078SMark Brown }
169b1387078SMark Brown
170f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_sysclk(wm0010, 0, 0, SYS_MCLK_RATE, 0);
171344c5edeSMark Brown if (ret != 0) {
172344c5edeSMark Brown dev_err(wm0010->dev, "Failed to set WM0010 clock: %d\n", ret);
173344c5edeSMark Brown return ret;
174344c5edeSMark Brown }
175344c5edeSMark Brown
176b545dd92SMark Brown ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
177b1387078SMark Brown if (ret != 0)
178b545dd92SMark Brown dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
179b1387078SMark Brown
180f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_OPCLK, 0,
181b1387078SMark Brown SYS_MCLK_RATE, SND_SOC_CLOCK_OUT);
182b1387078SMark Brown if (ret != 0)
183f4a2be1cSKuninori Morimoto dev_err(component->dev, "Failed to set OPCLK: %d\n", ret);
184b1387078SMark Brown
185b1387078SMark Brown if (card->num_rtd == DAI_CODEC_CP)
186b1387078SMark Brown return 0;
187b1387078SMark Brown
188f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_ASYNCCLK,
189b1387078SMark Brown ARIZONA_CLK_SRC_FLL2,
190b1387078SMark Brown bells->asyncclk_rate,
191b1387078SMark Brown SND_SOC_CLOCK_IN);
192b1387078SMark Brown if (ret != 0) {
193f4a2be1cSKuninori Morimoto dev_err(component->dev, "Failed to set ASYNCCLK: %d\n", ret);
194b545dd92SMark Brown return ret;
195b545dd92SMark Brown }
196b545dd92SMark Brown
1974468189fSKuninori Morimoto rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_CODEC_CP]);
1987de6b6bcSKuninori Morimoto aif2_dai = asoc_rtd_to_cpu(rtd, 0);
199b1387078SMark Brown
200b545dd92SMark Brown ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
201b545dd92SMark Brown if (ret != 0) {
202b545dd92SMark Brown dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
203b545dd92SMark Brown return ret;
204b545dd92SMark Brown }
205b545dd92SMark Brown
206b1387078SMark Brown if (card->num_rtd == DAI_CODEC_SUB)
207b1387078SMark Brown return 0;
208b1387078SMark Brown
2094468189fSKuninori Morimoto rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_CODEC_SUB]);
2107de6b6bcSKuninori Morimoto aif3_dai = asoc_rtd_to_cpu(rtd, 0);
2117de6b6bcSKuninori Morimoto wm9081_dai = asoc_rtd_to_codec(rtd, 0);
212b1387078SMark Brown
213b545dd92SMark Brown ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
214b545dd92SMark Brown if (ret != 0) {
215b545dd92SMark Brown dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
216b545dd92SMark Brown return ret;
217b545dd92SMark Brown }
218b545dd92SMark Brown
219f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_sysclk(wm9081_dai->component, WM9081_SYSCLK_MCLK,
220344c5edeSMark Brown 0, SYS_MCLK_RATE, 0);
221b545dd92SMark Brown if (ret != 0) {
222b545dd92SMark Brown dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret);
223b545dd92SMark Brown return ret;
224b545dd92SMark Brown }
225b545dd92SMark Brown
226b545dd92SMark Brown return 0;
227b545dd92SMark Brown }
228b545dd92SMark Brown
229b545dd92SMark Brown static const struct snd_soc_pcm_stream baseband_params = {
230b545dd92SMark Brown .formats = SNDRV_PCM_FMTBIT_S32_LE,
231b545dd92SMark Brown .rate_min = 8000,
232b545dd92SMark Brown .rate_max = 8000,
233b545dd92SMark Brown .channels_min = 2,
234b545dd92SMark Brown .channels_max = 2,
235b545dd92SMark Brown };
236b545dd92SMark Brown
237b545dd92SMark Brown static const struct snd_soc_pcm_stream sub_params = {
238b545dd92SMark Brown .formats = SNDRV_PCM_FMTBIT_S32_LE,
239344c5edeSMark Brown .rate_min = SYS_AUDIO_RATE,
240344c5edeSMark Brown .rate_max = SYS_AUDIO_RATE,
241b545dd92SMark Brown .channels_min = 2,
242b545dd92SMark Brown .channels_max = 2,
243b545dd92SMark Brown };
244b545dd92SMark Brown
2455af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm2200_cpu_dsp,
2465af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")),
2475af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")),
2485af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
2495af5e760SKuninori Morimoto
2505af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm2200_dsp_codec,
2515af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")),
2525af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm2200.1-003a", "wm2200")));
2535af5e760SKuninori Morimoto
2548d47e8a5SMark Brown static struct snd_soc_dai_link bells_dai_wm2200[] = {
2558d47e8a5SMark Brown {
2568d47e8a5SMark Brown .name = "CPU-DSP",
2578d47e8a5SMark Brown .stream_name = "CPU-DSP",
2588d47e8a5SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
2598d47e8a5SMark Brown | SND_SOC_DAIFMT_CBM_CFM,
2605af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm2200_cpu_dsp),
2618d47e8a5SMark Brown },
2628d47e8a5SMark Brown {
2638d47e8a5SMark Brown .name = "DSP-CODEC",
2648d47e8a5SMark Brown .stream_name = "DSP-CODEC",
2658d47e8a5SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
2668d47e8a5SMark Brown | SND_SOC_DAIFMT_CBM_CFM,
267*e7a73b05SKuninori Morimoto .c2c_params = &sub_params,
268*e7a73b05SKuninori Morimoto .num_c2c_params = 1,
2698d47e8a5SMark Brown .ignore_suspend = 1,
2705af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm2200_dsp_codec),
2718d47e8a5SMark Brown },
2728d47e8a5SMark Brown };
2738d47e8a5SMark Brown
2745af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5102_cpu_dsp,
2755af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")),
2765af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")),
2775af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
2785af5e760SKuninori Morimoto
2795af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5102_dsp_codec,
2805af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")),
2815af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm5102-codec", "wm5102-aif1")));
2825af5e760SKuninori Morimoto
2835af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5102_baseband,
2845af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif2")),
2855af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1")));
2865af5e760SKuninori Morimoto
2875af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5102_sub,
2885af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif3")),
2895af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi")));
2905af5e760SKuninori Morimoto
291b545dd92SMark Brown static struct snd_soc_dai_link bells_dai_wm5102[] = {
292b545dd92SMark Brown {
293344c5edeSMark Brown .name = "CPU-DSP",
294344c5edeSMark Brown .stream_name = "CPU-DSP",
295344c5edeSMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
296344c5edeSMark Brown | SND_SOC_DAIFMT_CBM_CFM,
2975af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5102_cpu_dsp),
298344c5edeSMark Brown },
299344c5edeSMark Brown {
300344c5edeSMark Brown .name = "DSP-CODEC",
301344c5edeSMark Brown .stream_name = "DSP-CODEC",
302b545dd92SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
303b545dd92SMark Brown | SND_SOC_DAIFMT_CBM_CFM,
304*e7a73b05SKuninori Morimoto .c2c_params = &sub_params,
305*e7a73b05SKuninori Morimoto .num_c2c_params = 1,
306344c5edeSMark Brown .ignore_suspend = 1,
3075af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5102_dsp_codec),
308b545dd92SMark Brown },
309b545dd92SMark Brown {
310b545dd92SMark Brown .name = "Baseband",
311b545dd92SMark Brown .stream_name = "Baseband",
312b545dd92SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
313b545dd92SMark Brown | SND_SOC_DAIFMT_CBM_CFM,
314b545dd92SMark Brown .ignore_suspend = 1,
315*e7a73b05SKuninori Morimoto .c2c_params = &baseband_params,
316*e7a73b05SKuninori Morimoto .num_c2c_params = 1,
3175af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5102_baseband),
318b545dd92SMark Brown },
319b545dd92SMark Brown {
320b545dd92SMark Brown .name = "Sub",
321b545dd92SMark Brown .stream_name = "Sub",
322b545dd92SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
323b545dd92SMark Brown | SND_SOC_DAIFMT_CBS_CFS,
324b545dd92SMark Brown .ignore_suspend = 1,
325*e7a73b05SKuninori Morimoto .c2c_params = &sub_params,
326*e7a73b05SKuninori Morimoto .num_c2c_params = 1,
3275af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5102_sub),
328b545dd92SMark Brown },
329b545dd92SMark Brown };
330b545dd92SMark Brown
3315af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5110_cpu_dsp,
3325af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")),
3335af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")),
3345af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
3355af5e760SKuninori Morimoto
3365af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5110_dsp_codec,
3375af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")),
3385af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm5110-codec", "wm5110-aif1")));
3395af5e760SKuninori Morimoto
3405af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5110_baseband,
3415af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm5110-aif2")),
3425af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1")));
3435af5e760SKuninori Morimoto
3445af5e760SKuninori Morimoto
3455af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5110_sub,
3465af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm5110-aif3")),
3475af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi")));
3485af5e760SKuninori Morimoto
349b545dd92SMark Brown static struct snd_soc_dai_link bells_dai_wm5110[] = {
350b545dd92SMark Brown {
351344c5edeSMark Brown .name = "CPU-DSP",
352344c5edeSMark Brown .stream_name = "CPU-DSP",
353344c5edeSMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
354344c5edeSMark Brown | SND_SOC_DAIFMT_CBM_CFM,
3555af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5110_cpu_dsp),
356344c5edeSMark Brown },
357344c5edeSMark Brown {
358344c5edeSMark Brown .name = "DSP-CODEC",
359344c5edeSMark Brown .stream_name = "DSP-CODEC",
360b545dd92SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
361b545dd92SMark Brown | SND_SOC_DAIFMT_CBM_CFM,
362*e7a73b05SKuninori Morimoto .c2c_params = &sub_params,
363*e7a73b05SKuninori Morimoto .num_c2c_params = 1,
364344c5edeSMark Brown .ignore_suspend = 1,
3655af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5110_dsp_codec),
366b545dd92SMark Brown },
367b545dd92SMark Brown {
368b545dd92SMark Brown .name = "Baseband",
369b545dd92SMark Brown .stream_name = "Baseband",
370b545dd92SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
371b545dd92SMark Brown | SND_SOC_DAIFMT_CBM_CFM,
372b545dd92SMark Brown .ignore_suspend = 1,
373*e7a73b05SKuninori Morimoto .c2c_params = &baseband_params,
374*e7a73b05SKuninori Morimoto .num_c2c_params = 1,
3755af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5110_baseband),
376b545dd92SMark Brown },
377b545dd92SMark Brown {
378b545dd92SMark Brown .name = "Sub",
379b545dd92SMark Brown .stream_name = "Sub",
380b545dd92SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
381b545dd92SMark Brown | SND_SOC_DAIFMT_CBS_CFS,
382b545dd92SMark Brown .ignore_suspend = 1,
383*e7a73b05SKuninori Morimoto .c2c_params = &sub_params,
384*e7a73b05SKuninori Morimoto .num_c2c_params = 1,
3855af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5110_sub),
386b545dd92SMark Brown },
387b545dd92SMark Brown };
388b545dd92SMark Brown
389b545dd92SMark Brown static struct snd_soc_codec_conf bells_codec_conf[] = {
390b545dd92SMark Brown {
3913874b215SKuninori Morimoto .dlc = COMP_CODEC_CONF("wm9081.1-006c"),
392b545dd92SMark Brown .name_prefix = "Sub",
393b545dd92SMark Brown },
394b545dd92SMark Brown };
395b545dd92SMark Brown
3965449fd7bSRikard Falkeborn static const struct snd_soc_dapm_widget bells_widgets[] = {
397939d3c6aSCharles Keepax SND_SOC_DAPM_MIC("DMIC", NULL),
398939d3c6aSCharles Keepax };
399939d3c6aSCharles Keepax
4005449fd7bSRikard Falkeborn static const struct snd_soc_dapm_route bells_routes[] = {
401b545dd92SMark Brown { "Sub CLK_SYS", NULL, "OPCLK" },
402b3a6006eSCharles Keepax { "CLKIN", NULL, "OPCLK" },
403939d3c6aSCharles Keepax
404939d3c6aSCharles Keepax { "DMIC", NULL, "MICBIAS2" },
405939d3c6aSCharles Keepax { "IN2L", NULL, "DMIC" },
406939d3c6aSCharles Keepax { "IN2R", NULL, "DMIC" },
407b545dd92SMark Brown };
408b545dd92SMark Brown
409b545dd92SMark Brown static struct snd_soc_card bells_cards[] = {
410b545dd92SMark Brown {
4118d47e8a5SMark Brown .name = "Bells WM2200",
4128d47e8a5SMark Brown .owner = THIS_MODULE,
4138d47e8a5SMark Brown .dai_link = bells_dai_wm2200,
4148d47e8a5SMark Brown .num_links = ARRAY_SIZE(bells_dai_wm2200),
4158d47e8a5SMark Brown .codec_conf = bells_codec_conf,
4168d47e8a5SMark Brown .num_configs = ARRAY_SIZE(bells_codec_conf),
4178d47e8a5SMark Brown
4188d47e8a5SMark Brown .late_probe = bells_late_probe,
4198d47e8a5SMark Brown
420939d3c6aSCharles Keepax .dapm_widgets = bells_widgets,
421939d3c6aSCharles Keepax .num_dapm_widgets = ARRAY_SIZE(bells_widgets),
4228d47e8a5SMark Brown .dapm_routes = bells_routes,
4238d47e8a5SMark Brown .num_dapm_routes = ARRAY_SIZE(bells_routes),
4248d47e8a5SMark Brown
4258d47e8a5SMark Brown .set_bias_level = bells_set_bias_level,
4268d47e8a5SMark Brown .set_bias_level_post = bells_set_bias_level_post,
4278d47e8a5SMark Brown
4288d47e8a5SMark Brown .drvdata = &wm2200_drvdata,
4298d47e8a5SMark Brown },
4308d47e8a5SMark Brown {
431b545dd92SMark Brown .name = "Bells WM5102",
432b545dd92SMark Brown .owner = THIS_MODULE,
433b545dd92SMark Brown .dai_link = bells_dai_wm5102,
434b545dd92SMark Brown .num_links = ARRAY_SIZE(bells_dai_wm5102),
435b545dd92SMark Brown .codec_conf = bells_codec_conf,
436b545dd92SMark Brown .num_configs = ARRAY_SIZE(bells_codec_conf),
437b545dd92SMark Brown
438b545dd92SMark Brown .late_probe = bells_late_probe,
439b545dd92SMark Brown
440939d3c6aSCharles Keepax .dapm_widgets = bells_widgets,
441939d3c6aSCharles Keepax .num_dapm_widgets = ARRAY_SIZE(bells_widgets),
442b545dd92SMark Brown .dapm_routes = bells_routes,
443b545dd92SMark Brown .num_dapm_routes = ARRAY_SIZE(bells_routes),
444b545dd92SMark Brown
445b545dd92SMark Brown .set_bias_level = bells_set_bias_level,
446b545dd92SMark Brown .set_bias_level_post = bells_set_bias_level_post,
447b1387078SMark Brown
448b1387078SMark Brown .drvdata = &wm5102_drvdata,
449b545dd92SMark Brown },
450b545dd92SMark Brown {
451b545dd92SMark Brown .name = "Bells WM5110",
452b545dd92SMark Brown .owner = THIS_MODULE,
453b545dd92SMark Brown .dai_link = bells_dai_wm5110,
454b545dd92SMark Brown .num_links = ARRAY_SIZE(bells_dai_wm5110),
455b545dd92SMark Brown .codec_conf = bells_codec_conf,
456b545dd92SMark Brown .num_configs = ARRAY_SIZE(bells_codec_conf),
457b545dd92SMark Brown
458b545dd92SMark Brown .late_probe = bells_late_probe,
459b545dd92SMark Brown
460939d3c6aSCharles Keepax .dapm_widgets = bells_widgets,
461939d3c6aSCharles Keepax .num_dapm_widgets = ARRAY_SIZE(bells_widgets),
462b545dd92SMark Brown .dapm_routes = bells_routes,
463b545dd92SMark Brown .num_dapm_routes = ARRAY_SIZE(bells_routes),
464b545dd92SMark Brown
465b545dd92SMark Brown .set_bias_level = bells_set_bias_level,
466b545dd92SMark Brown .set_bias_level_post = bells_set_bias_level_post,
467b1387078SMark Brown
468b1387078SMark Brown .drvdata = &wm5110_drvdata,
469b545dd92SMark Brown },
470b545dd92SMark Brown };
471b545dd92SMark Brown
bells_probe(struct platform_device * pdev)472fdca21adSBill Pemberton static int bells_probe(struct platform_device *pdev)
473b545dd92SMark Brown {
474b545dd92SMark Brown int ret;
475b545dd92SMark Brown
476b545dd92SMark Brown bells_cards[pdev->id].dev = &pdev->dev;
477b545dd92SMark Brown
478c583883eSTushar Behera ret = devm_snd_soc_register_card(&pdev->dev, &bells_cards[pdev->id]);
479c583883eSTushar Behera if (ret)
480b545dd92SMark Brown dev_err(&pdev->dev,
481b545dd92SMark Brown "snd_soc_register_card(%s) failed: %d\n",
482b545dd92SMark Brown bells_cards[pdev->id].name, ret);
483c583883eSTushar Behera
484b545dd92SMark Brown return ret;
485b545dd92SMark Brown }
486b545dd92SMark Brown
487b545dd92SMark Brown static struct platform_driver bells_driver = {
488b545dd92SMark Brown .driver = {
489b545dd92SMark Brown .name = "bells",
490b545dd92SMark Brown .pm = &snd_soc_pm_ops,
491b545dd92SMark Brown },
492b545dd92SMark Brown .probe = bells_probe,
493b545dd92SMark Brown };
494b545dd92SMark Brown
495b545dd92SMark Brown module_platform_driver(bells_driver);
496b545dd92SMark Brown
497b545dd92SMark Brown MODULE_DESCRIPTION("Bells audio support");
498b545dd92SMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
499b545dd92SMark Brown MODULE_LICENSE("GPL");
500b545dd92SMark Brown MODULE_ALIAS("platform:bells");
501