xref: /openbmc/linux/sound/soc/samsung/bells.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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