xref: /openbmc/linux/sound/soc/samsung/bells.c (revision 3874b2154be7abd3e5eb1c19af7e556f6a22d2fa)
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 
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]);
635015920aSMengdong Lin 	codec_dai = rtd->codec_dai;
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 
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]);
1095015920aSMengdong Lin 	codec_dai = rtd->codec_dai;
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 
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]);
155f4a2be1cSKuninori Morimoto 	wm0010 = rtd->codec_dai->component;
1565015920aSMengdong Lin 
1574468189fSKuninori Morimoto 	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]);
158f4a2be1cSKuninori Morimoto 	component = rtd->codec_dai->component;
1595015920aSMengdong Lin 	aif1_dai = rtd->codec_dai;
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]);
1985015920aSMengdong Lin 	aif2_dai = rtd->cpu_dai;
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]);
2105015920aSMengdong Lin 	aif3_dai = rtd->cpu_dai;
2115015920aSMengdong Lin 	wm9081_dai = rtd->codec_dai;
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,
2678d47e8a5SMark Brown 		.params = &sub_params,
2688d47e8a5SMark Brown 		.ignore_suspend = 1,
2695af5e760SKuninori Morimoto 		SND_SOC_DAILINK_REG(wm2200_dsp_codec),
2708d47e8a5SMark Brown 	},
2718d47e8a5SMark Brown };
2728d47e8a5SMark Brown 
2735af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5102_cpu_dsp,
2745af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")),
2755af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")),
2765af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
2775af5e760SKuninori Morimoto 
2785af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5102_dsp_codec,
2795af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")),
2805af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("wm5102-codec", "wm5102-aif1")));
2815af5e760SKuninori Morimoto 
2825af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5102_baseband,
2835af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif2")),
2845af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1")));
2855af5e760SKuninori Morimoto 
2865af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5102_sub,
2875af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif3")),
2885af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi")));
2895af5e760SKuninori Morimoto 
290b545dd92SMark Brown static struct snd_soc_dai_link bells_dai_wm5102[] = {
291b545dd92SMark Brown 	{
292344c5edeSMark Brown 		.name = "CPU-DSP",
293344c5edeSMark Brown 		.stream_name = "CPU-DSP",
294344c5edeSMark Brown 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
295344c5edeSMark Brown 				| SND_SOC_DAIFMT_CBM_CFM,
2965af5e760SKuninori Morimoto 		SND_SOC_DAILINK_REG(wm5102_cpu_dsp),
297344c5edeSMark Brown 	},
298344c5edeSMark Brown 	{
299344c5edeSMark Brown 		.name = "DSP-CODEC",
300344c5edeSMark Brown 		.stream_name = "DSP-CODEC",
301b545dd92SMark Brown 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
302b545dd92SMark Brown 				| SND_SOC_DAIFMT_CBM_CFM,
303344c5edeSMark Brown 		.params = &sub_params,
304344c5edeSMark Brown 		.ignore_suspend = 1,
3055af5e760SKuninori Morimoto 		SND_SOC_DAILINK_REG(wm5102_dsp_codec),
306b545dd92SMark Brown 	},
307b545dd92SMark Brown 	{
308b545dd92SMark Brown 		.name = "Baseband",
309b545dd92SMark Brown 		.stream_name = "Baseband",
310b545dd92SMark Brown 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
311b545dd92SMark Brown 				| SND_SOC_DAIFMT_CBM_CFM,
312b545dd92SMark Brown 		.ignore_suspend = 1,
313b545dd92SMark Brown 		.params = &baseband_params,
3145af5e760SKuninori Morimoto 		SND_SOC_DAILINK_REG(wm5102_baseband),
315b545dd92SMark Brown 	},
316b545dd92SMark Brown 	{
317b545dd92SMark Brown 		.name = "Sub",
318b545dd92SMark Brown 		.stream_name = "Sub",
319b545dd92SMark Brown 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
320b545dd92SMark Brown 				| SND_SOC_DAIFMT_CBS_CFS,
321b545dd92SMark Brown 		.ignore_suspend = 1,
322b545dd92SMark Brown 		.params = &sub_params,
3235af5e760SKuninori Morimoto 		SND_SOC_DAILINK_REG(wm5102_sub),
324b545dd92SMark Brown 	},
325b545dd92SMark Brown };
326b545dd92SMark Brown 
3275af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5110_cpu_dsp,
3285af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")),
3295af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")),
3305af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
3315af5e760SKuninori Morimoto 
3325af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5110_dsp_codec,
3335af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")),
3345af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("wm5110-codec", "wm5110-aif1")));
3355af5e760SKuninori Morimoto 
3365af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5110_baseband,
3375af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("wm5110-aif2")),
3385af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1")));
3395af5e760SKuninori Morimoto 
3405af5e760SKuninori Morimoto 
3415af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5110_sub,
3425af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("wm5110-aif3")),
3435af5e760SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi")));
3445af5e760SKuninori Morimoto 
345b545dd92SMark Brown static struct snd_soc_dai_link bells_dai_wm5110[] = {
346b545dd92SMark Brown 	{
347344c5edeSMark Brown 		.name = "CPU-DSP",
348344c5edeSMark Brown 		.stream_name = "CPU-DSP",
349344c5edeSMark Brown 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
350344c5edeSMark Brown 				| SND_SOC_DAIFMT_CBM_CFM,
3515af5e760SKuninori Morimoto 		SND_SOC_DAILINK_REG(wm5110_cpu_dsp),
352344c5edeSMark Brown 	},
353344c5edeSMark Brown 	{
354344c5edeSMark Brown 		.name = "DSP-CODEC",
355344c5edeSMark Brown 		.stream_name = "DSP-CODEC",
356b545dd92SMark Brown 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
357b545dd92SMark Brown 				| SND_SOC_DAIFMT_CBM_CFM,
358344c5edeSMark Brown 		.params = &sub_params,
359344c5edeSMark Brown 		.ignore_suspend = 1,
3605af5e760SKuninori Morimoto 		SND_SOC_DAILINK_REG(wm5110_dsp_codec),
361b545dd92SMark Brown 	},
362b545dd92SMark Brown 	{
363b545dd92SMark Brown 		.name = "Baseband",
364b545dd92SMark Brown 		.stream_name = "Baseband",
365b545dd92SMark Brown 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
366b545dd92SMark Brown 				| SND_SOC_DAIFMT_CBM_CFM,
367b545dd92SMark Brown 		.ignore_suspend = 1,
368b545dd92SMark Brown 		.params = &baseband_params,
3695af5e760SKuninori Morimoto 		SND_SOC_DAILINK_REG(wm5110_baseband),
370b545dd92SMark Brown 	},
371b545dd92SMark Brown 	{
372b545dd92SMark Brown 		.name = "Sub",
373b545dd92SMark Brown 		.stream_name = "Sub",
374b545dd92SMark Brown 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
375b545dd92SMark Brown 				| SND_SOC_DAIFMT_CBS_CFS,
376b545dd92SMark Brown 		.ignore_suspend = 1,
377b545dd92SMark Brown 		.params = &sub_params,
3785af5e760SKuninori Morimoto 		SND_SOC_DAILINK_REG(wm5110_sub),
379b545dd92SMark Brown 	},
380b545dd92SMark Brown };
381b545dd92SMark Brown 
382b545dd92SMark Brown static struct snd_soc_codec_conf bells_codec_conf[] = {
383b545dd92SMark Brown 	{
384*3874b215SKuninori Morimoto 		.dlc = COMP_CODEC_CONF("wm9081.1-006c"),
385b545dd92SMark Brown 		.name_prefix = "Sub",
386b545dd92SMark Brown 	},
387b545dd92SMark Brown };
388b545dd92SMark Brown 
389939d3c6aSCharles Keepax static struct snd_soc_dapm_widget bells_widgets[] = {
390939d3c6aSCharles Keepax 	SND_SOC_DAPM_MIC("DMIC", NULL),
391939d3c6aSCharles Keepax };
392939d3c6aSCharles Keepax 
393b545dd92SMark Brown static struct snd_soc_dapm_route bells_routes[] = {
394b545dd92SMark Brown 	{ "Sub CLK_SYS", NULL, "OPCLK" },
395b3a6006eSCharles Keepax 	{ "CLKIN", NULL, "OPCLK" },
396939d3c6aSCharles Keepax 
397939d3c6aSCharles Keepax 	{ "DMIC", NULL, "MICBIAS2" },
398939d3c6aSCharles Keepax 	{ "IN2L", NULL, "DMIC" },
399939d3c6aSCharles Keepax 	{ "IN2R", NULL, "DMIC" },
400b545dd92SMark Brown };
401b545dd92SMark Brown 
402b545dd92SMark Brown static struct snd_soc_card bells_cards[] = {
403b545dd92SMark Brown 	{
4048d47e8a5SMark Brown 		.name = "Bells WM2200",
4058d47e8a5SMark Brown 		.owner = THIS_MODULE,
4068d47e8a5SMark Brown 		.dai_link = bells_dai_wm2200,
4078d47e8a5SMark Brown 		.num_links = ARRAY_SIZE(bells_dai_wm2200),
4088d47e8a5SMark Brown 		.codec_conf = bells_codec_conf,
4098d47e8a5SMark Brown 		.num_configs = ARRAY_SIZE(bells_codec_conf),
4108d47e8a5SMark Brown 
4118d47e8a5SMark Brown 		.late_probe = bells_late_probe,
4128d47e8a5SMark Brown 
413939d3c6aSCharles Keepax 		.dapm_widgets = bells_widgets,
414939d3c6aSCharles Keepax 		.num_dapm_widgets = ARRAY_SIZE(bells_widgets),
4158d47e8a5SMark Brown 		.dapm_routes = bells_routes,
4168d47e8a5SMark Brown 		.num_dapm_routes = ARRAY_SIZE(bells_routes),
4178d47e8a5SMark Brown 
4188d47e8a5SMark Brown 		.set_bias_level = bells_set_bias_level,
4198d47e8a5SMark Brown 		.set_bias_level_post = bells_set_bias_level_post,
4208d47e8a5SMark Brown 
4218d47e8a5SMark Brown 		.drvdata = &wm2200_drvdata,
4228d47e8a5SMark Brown 	},
4238d47e8a5SMark Brown 	{
424b545dd92SMark Brown 		.name = "Bells WM5102",
425b545dd92SMark Brown 		.owner = THIS_MODULE,
426b545dd92SMark Brown 		.dai_link = bells_dai_wm5102,
427b545dd92SMark Brown 		.num_links = ARRAY_SIZE(bells_dai_wm5102),
428b545dd92SMark Brown 		.codec_conf = bells_codec_conf,
429b545dd92SMark Brown 		.num_configs = ARRAY_SIZE(bells_codec_conf),
430b545dd92SMark Brown 
431b545dd92SMark Brown 		.late_probe = bells_late_probe,
432b545dd92SMark Brown 
433939d3c6aSCharles Keepax 		.dapm_widgets = bells_widgets,
434939d3c6aSCharles Keepax 		.num_dapm_widgets = ARRAY_SIZE(bells_widgets),
435b545dd92SMark Brown 		.dapm_routes = bells_routes,
436b545dd92SMark Brown 		.num_dapm_routes = ARRAY_SIZE(bells_routes),
437b545dd92SMark Brown 
438b545dd92SMark Brown 		.set_bias_level = bells_set_bias_level,
439b545dd92SMark Brown 		.set_bias_level_post = bells_set_bias_level_post,
440b1387078SMark Brown 
441b1387078SMark Brown 		.drvdata = &wm5102_drvdata,
442b545dd92SMark Brown 	},
443b545dd92SMark Brown 	{
444b545dd92SMark Brown 		.name = "Bells WM5110",
445b545dd92SMark Brown 		.owner = THIS_MODULE,
446b545dd92SMark Brown 		.dai_link = bells_dai_wm5110,
447b545dd92SMark Brown 		.num_links = ARRAY_SIZE(bells_dai_wm5110),
448b545dd92SMark Brown 		.codec_conf = bells_codec_conf,
449b545dd92SMark Brown 		.num_configs = ARRAY_SIZE(bells_codec_conf),
450b545dd92SMark Brown 
451b545dd92SMark Brown 		.late_probe = bells_late_probe,
452b545dd92SMark Brown 
453939d3c6aSCharles Keepax 		.dapm_widgets = bells_widgets,
454939d3c6aSCharles Keepax 		.num_dapm_widgets = ARRAY_SIZE(bells_widgets),
455b545dd92SMark Brown 		.dapm_routes = bells_routes,
456b545dd92SMark Brown 		.num_dapm_routes = ARRAY_SIZE(bells_routes),
457b545dd92SMark Brown 
458b545dd92SMark Brown 		.set_bias_level = bells_set_bias_level,
459b545dd92SMark Brown 		.set_bias_level_post = bells_set_bias_level_post,
460b1387078SMark Brown 
461b1387078SMark Brown 		.drvdata = &wm5110_drvdata,
462b545dd92SMark Brown 	},
463b545dd92SMark Brown };
464b545dd92SMark Brown 
465fdca21adSBill Pemberton static int bells_probe(struct platform_device *pdev)
466b545dd92SMark Brown {
467b545dd92SMark Brown 	int ret;
468b545dd92SMark Brown 
469b545dd92SMark Brown 	bells_cards[pdev->id].dev = &pdev->dev;
470b545dd92SMark Brown 
471c583883eSTushar Behera 	ret = devm_snd_soc_register_card(&pdev->dev, &bells_cards[pdev->id]);
472c583883eSTushar Behera 	if (ret)
473b545dd92SMark Brown 		dev_err(&pdev->dev,
474b545dd92SMark Brown 			"snd_soc_register_card(%s) failed: %d\n",
475b545dd92SMark Brown 			bells_cards[pdev->id].name, ret);
476c583883eSTushar Behera 
477b545dd92SMark Brown 	return ret;
478b545dd92SMark Brown }
479b545dd92SMark Brown 
480b545dd92SMark Brown static struct platform_driver bells_driver = {
481b545dd92SMark Brown 	.driver = {
482b545dd92SMark Brown 		.name = "bells",
483b545dd92SMark Brown 		.pm = &snd_soc_pm_ops,
484b545dd92SMark Brown 	},
485b545dd92SMark Brown 	.probe = bells_probe,
486b545dd92SMark Brown };
487b545dd92SMark Brown 
488b545dd92SMark Brown module_platform_driver(bells_driver);
489b545dd92SMark Brown 
490b545dd92SMark Brown MODULE_DESCRIPTION("Bells audio support");
491b545dd92SMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
492b545dd92SMark Brown MODULE_LICENSE("GPL");
493b545dd92SMark Brown MODULE_ALIAS("platform:bells");
494