162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// Bells audio support
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright 2012 Wolfson Microelectronics
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <sound/soc.h>
862306a36Sopenharmony_ci#include <sound/soc-dapm.h>
962306a36Sopenharmony_ci#include <sound/jack.h>
1062306a36Sopenharmony_ci#include <linux/gpio.h>
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "../codecs/wm5102.h"
1462306a36Sopenharmony_ci#include "../codecs/wm9081.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/* BCLK2 is fixed at this currently */
1762306a36Sopenharmony_ci#define BCLK2_RATE (64 * 8000)
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/*
2062306a36Sopenharmony_ci * Expect a 24.576MHz crystal if one is fitted (the driver will function
2162306a36Sopenharmony_ci * if this is not fitted).
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_ci#define MCLK_RATE 24576000
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define SYS_AUDIO_RATE 44100
2662306a36Sopenharmony_ci#define SYS_MCLK_RATE  (SYS_AUDIO_RATE * 512)
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define DAI_AP_DSP    0
2962306a36Sopenharmony_ci#define DAI_DSP_CODEC 1
3062306a36Sopenharmony_ci#define DAI_CODEC_CP  2
3162306a36Sopenharmony_ci#define DAI_CODEC_SUB 3
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistruct bells_drvdata {
3462306a36Sopenharmony_ci	int sysclk_rate;
3562306a36Sopenharmony_ci	int asyncclk_rate;
3662306a36Sopenharmony_ci};
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic struct bells_drvdata wm2200_drvdata = {
3962306a36Sopenharmony_ci	.sysclk_rate = 22579200,
4062306a36Sopenharmony_ci};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic struct bells_drvdata wm5102_drvdata = {
4362306a36Sopenharmony_ci	.sysclk_rate = 45158400,
4462306a36Sopenharmony_ci	.asyncclk_rate = 49152000,
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic struct bells_drvdata wm5110_drvdata = {
4862306a36Sopenharmony_ci	.sysclk_rate = 135475200,
4962306a36Sopenharmony_ci	.asyncclk_rate = 147456000,
5062306a36Sopenharmony_ci};
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistatic int bells_set_bias_level(struct snd_soc_card *card,
5362306a36Sopenharmony_ci				struct snd_soc_dapm_context *dapm,
5462306a36Sopenharmony_ci				enum snd_soc_bias_level level)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd;
5762306a36Sopenharmony_ci	struct snd_soc_dai *codec_dai;
5862306a36Sopenharmony_ci	struct snd_soc_component *component;
5962306a36Sopenharmony_ci	struct bells_drvdata *bells = card->drvdata;
6062306a36Sopenharmony_ci	int ret;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]);
6362306a36Sopenharmony_ci	codec_dai = asoc_rtd_to_codec(rtd, 0);
6462306a36Sopenharmony_ci	component = codec_dai->component;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	if (dapm->dev != codec_dai->dev)
6762306a36Sopenharmony_ci		return 0;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	switch (level) {
7062306a36Sopenharmony_ci	case SND_SOC_BIAS_PREPARE:
7162306a36Sopenharmony_ci		if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
7262306a36Sopenharmony_ci			break;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci		ret = snd_soc_component_set_pll(component, WM5102_FLL1,
7562306a36Sopenharmony_ci					    ARIZONA_FLL_SRC_MCLK1,
7662306a36Sopenharmony_ci					    MCLK_RATE,
7762306a36Sopenharmony_ci					    bells->sysclk_rate);
7862306a36Sopenharmony_ci		if (ret < 0)
7962306a36Sopenharmony_ci			pr_err("Failed to start FLL: %d\n", ret);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci		if (bells->asyncclk_rate) {
8262306a36Sopenharmony_ci			ret = snd_soc_component_set_pll(component, WM5102_FLL2,
8362306a36Sopenharmony_ci						    ARIZONA_FLL_SRC_AIF2BCLK,
8462306a36Sopenharmony_ci						    BCLK2_RATE,
8562306a36Sopenharmony_ci						    bells->asyncclk_rate);
8662306a36Sopenharmony_ci			if (ret < 0)
8762306a36Sopenharmony_ci				pr_err("Failed to start FLL: %d\n", ret);
8862306a36Sopenharmony_ci		}
8962306a36Sopenharmony_ci		break;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	default:
9262306a36Sopenharmony_ci		break;
9362306a36Sopenharmony_ci	}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	return 0;
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic int bells_set_bias_level_post(struct snd_soc_card *card,
9962306a36Sopenharmony_ci				     struct snd_soc_dapm_context *dapm,
10062306a36Sopenharmony_ci				     enum snd_soc_bias_level level)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd;
10362306a36Sopenharmony_ci	struct snd_soc_dai *codec_dai;
10462306a36Sopenharmony_ci	struct snd_soc_component *component;
10562306a36Sopenharmony_ci	struct bells_drvdata *bells = card->drvdata;
10662306a36Sopenharmony_ci	int ret;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]);
10962306a36Sopenharmony_ci	codec_dai = asoc_rtd_to_codec(rtd, 0);
11062306a36Sopenharmony_ci	component = codec_dai->component;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	if (dapm->dev != codec_dai->dev)
11362306a36Sopenharmony_ci		return 0;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	switch (level) {
11662306a36Sopenharmony_ci	case SND_SOC_BIAS_STANDBY:
11762306a36Sopenharmony_ci		ret = snd_soc_component_set_pll(component, WM5102_FLL1, 0, 0, 0);
11862306a36Sopenharmony_ci		if (ret < 0) {
11962306a36Sopenharmony_ci			pr_err("Failed to stop FLL: %d\n", ret);
12062306a36Sopenharmony_ci			return ret;
12162306a36Sopenharmony_ci		}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci		if (bells->asyncclk_rate) {
12462306a36Sopenharmony_ci			ret = snd_soc_component_set_pll(component, WM5102_FLL2,
12562306a36Sopenharmony_ci						    0, 0, 0);
12662306a36Sopenharmony_ci			if (ret < 0) {
12762306a36Sopenharmony_ci				pr_err("Failed to stop FLL: %d\n", ret);
12862306a36Sopenharmony_ci				return ret;
12962306a36Sopenharmony_ci			}
13062306a36Sopenharmony_ci		}
13162306a36Sopenharmony_ci		break;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	default:
13462306a36Sopenharmony_ci		break;
13562306a36Sopenharmony_ci	}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	dapm->bias_level = level;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	return 0;
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic int bells_late_probe(struct snd_soc_card *card)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	struct bells_drvdata *bells = card->drvdata;
14562306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd;
14662306a36Sopenharmony_ci	struct snd_soc_component *wm0010;
14762306a36Sopenharmony_ci	struct snd_soc_component *component;
14862306a36Sopenharmony_ci	struct snd_soc_dai *aif1_dai;
14962306a36Sopenharmony_ci	struct snd_soc_dai *aif2_dai;
15062306a36Sopenharmony_ci	struct snd_soc_dai *aif3_dai;
15162306a36Sopenharmony_ci	struct snd_soc_dai *wm9081_dai;
15262306a36Sopenharmony_ci	int ret;
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_AP_DSP]);
15562306a36Sopenharmony_ci	wm0010 = asoc_rtd_to_codec(rtd, 0)->component;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]);
15862306a36Sopenharmony_ci	component = asoc_rtd_to_codec(rtd, 0)->component;
15962306a36Sopenharmony_ci	aif1_dai = asoc_rtd_to_codec(rtd, 0);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_SYSCLK,
16262306a36Sopenharmony_ci				       ARIZONA_CLK_SRC_FLL1,
16362306a36Sopenharmony_ci				       bells->sysclk_rate,
16462306a36Sopenharmony_ci				       SND_SOC_CLOCK_IN);
16562306a36Sopenharmony_ci	if (ret != 0) {
16662306a36Sopenharmony_ci		dev_err(component->dev, "Failed to set SYSCLK: %d\n", ret);
16762306a36Sopenharmony_ci		return ret;
16862306a36Sopenharmony_ci	}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	ret = snd_soc_component_set_sysclk(wm0010, 0, 0, SYS_MCLK_RATE, 0);
17162306a36Sopenharmony_ci	if (ret != 0) {
17262306a36Sopenharmony_ci		dev_err(wm0010->dev, "Failed to set WM0010 clock: %d\n", ret);
17362306a36Sopenharmony_ci		return ret;
17462306a36Sopenharmony_ci	}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
17762306a36Sopenharmony_ci	if (ret != 0)
17862306a36Sopenharmony_ci		dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_OPCLK, 0,
18162306a36Sopenharmony_ci				       SYS_MCLK_RATE, SND_SOC_CLOCK_OUT);
18262306a36Sopenharmony_ci	if (ret != 0)
18362306a36Sopenharmony_ci		dev_err(component->dev, "Failed to set OPCLK: %d\n", ret);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	if (card->num_rtd == DAI_CODEC_CP)
18662306a36Sopenharmony_ci		return 0;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_ASYNCCLK,
18962306a36Sopenharmony_ci				       ARIZONA_CLK_SRC_FLL2,
19062306a36Sopenharmony_ci				       bells->asyncclk_rate,
19162306a36Sopenharmony_ci				       SND_SOC_CLOCK_IN);
19262306a36Sopenharmony_ci	if (ret != 0) {
19362306a36Sopenharmony_ci		dev_err(component->dev, "Failed to set ASYNCCLK: %d\n", ret);
19462306a36Sopenharmony_ci		return ret;
19562306a36Sopenharmony_ci	}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_CODEC_CP]);
19862306a36Sopenharmony_ci	aif2_dai = asoc_rtd_to_cpu(rtd, 0);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
20162306a36Sopenharmony_ci	if (ret != 0) {
20262306a36Sopenharmony_ci		dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
20362306a36Sopenharmony_ci		return ret;
20462306a36Sopenharmony_ci	}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	if (card->num_rtd == DAI_CODEC_SUB)
20762306a36Sopenharmony_ci		return 0;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_CODEC_SUB]);
21062306a36Sopenharmony_ci	aif3_dai = asoc_rtd_to_cpu(rtd, 0);
21162306a36Sopenharmony_ci	wm9081_dai = asoc_rtd_to_codec(rtd, 0);
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
21462306a36Sopenharmony_ci	if (ret != 0) {
21562306a36Sopenharmony_ci		dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
21662306a36Sopenharmony_ci		return ret;
21762306a36Sopenharmony_ci	}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	ret = snd_soc_component_set_sysclk(wm9081_dai->component, WM9081_SYSCLK_MCLK,
22062306a36Sopenharmony_ci				       0, SYS_MCLK_RATE, 0);
22162306a36Sopenharmony_ci	if (ret != 0) {
22262306a36Sopenharmony_ci		dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret);
22362306a36Sopenharmony_ci		return ret;
22462306a36Sopenharmony_ci	}
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	return 0;
22762306a36Sopenharmony_ci}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistatic const struct snd_soc_pcm_stream baseband_params = {
23062306a36Sopenharmony_ci	.formats = SNDRV_PCM_FMTBIT_S32_LE,
23162306a36Sopenharmony_ci	.rate_min = 8000,
23262306a36Sopenharmony_ci	.rate_max = 8000,
23362306a36Sopenharmony_ci	.channels_min = 2,
23462306a36Sopenharmony_ci	.channels_max = 2,
23562306a36Sopenharmony_ci};
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistatic const struct snd_soc_pcm_stream sub_params = {
23862306a36Sopenharmony_ci	.formats = SNDRV_PCM_FMTBIT_S32_LE,
23962306a36Sopenharmony_ci	.rate_min = SYS_AUDIO_RATE,
24062306a36Sopenharmony_ci	.rate_max = SYS_AUDIO_RATE,
24162306a36Sopenharmony_ci	.channels_min = 2,
24262306a36Sopenharmony_ci	.channels_max = 2,
24362306a36Sopenharmony_ci};
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm2200_cpu_dsp,
24662306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")),
24762306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")),
24862306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm2200_dsp_codec,
25162306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")),
25262306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm2200.1-003a", "wm2200")));
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_cistatic struct snd_soc_dai_link bells_dai_wm2200[] = {
25562306a36Sopenharmony_ci	{
25662306a36Sopenharmony_ci		.name = "CPU-DSP",
25762306a36Sopenharmony_ci		.stream_name = "CPU-DSP",
25862306a36Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
25962306a36Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
26062306a36Sopenharmony_ci		SND_SOC_DAILINK_REG(wm2200_cpu_dsp),
26162306a36Sopenharmony_ci	},
26262306a36Sopenharmony_ci	{
26362306a36Sopenharmony_ci		.name = "DSP-CODEC",
26462306a36Sopenharmony_ci		.stream_name = "DSP-CODEC",
26562306a36Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
26662306a36Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
26762306a36Sopenharmony_ci		.c2c_params = &sub_params,
26862306a36Sopenharmony_ci		.num_c2c_params = 1,
26962306a36Sopenharmony_ci		.ignore_suspend = 1,
27062306a36Sopenharmony_ci		SND_SOC_DAILINK_REG(wm2200_dsp_codec),
27162306a36Sopenharmony_ci	},
27262306a36Sopenharmony_ci};
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5102_cpu_dsp,
27562306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")),
27662306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")),
27762306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5102_dsp_codec,
28062306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")),
28162306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm5102-codec", "wm5102-aif1")));
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5102_baseband,
28462306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif2")),
28562306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1")));
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5102_sub,
28862306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif3")),
28962306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi")));
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_cistatic struct snd_soc_dai_link bells_dai_wm5102[] = {
29262306a36Sopenharmony_ci	{
29362306a36Sopenharmony_ci		.name = "CPU-DSP",
29462306a36Sopenharmony_ci		.stream_name = "CPU-DSP",
29562306a36Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
29662306a36Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
29762306a36Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5102_cpu_dsp),
29862306a36Sopenharmony_ci	},
29962306a36Sopenharmony_ci	{
30062306a36Sopenharmony_ci		.name = "DSP-CODEC",
30162306a36Sopenharmony_ci		.stream_name = "DSP-CODEC",
30262306a36Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
30362306a36Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
30462306a36Sopenharmony_ci		.c2c_params = &sub_params,
30562306a36Sopenharmony_ci		.num_c2c_params = 1,
30662306a36Sopenharmony_ci		.ignore_suspend = 1,
30762306a36Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5102_dsp_codec),
30862306a36Sopenharmony_ci	},
30962306a36Sopenharmony_ci	{
31062306a36Sopenharmony_ci		.name = "Baseband",
31162306a36Sopenharmony_ci		.stream_name = "Baseband",
31262306a36Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
31362306a36Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
31462306a36Sopenharmony_ci		.ignore_suspend = 1,
31562306a36Sopenharmony_ci		.c2c_params = &baseband_params,
31662306a36Sopenharmony_ci		.num_c2c_params = 1,
31762306a36Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5102_baseband),
31862306a36Sopenharmony_ci	},
31962306a36Sopenharmony_ci	{
32062306a36Sopenharmony_ci		.name = "Sub",
32162306a36Sopenharmony_ci		.stream_name = "Sub",
32262306a36Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
32362306a36Sopenharmony_ci				| SND_SOC_DAIFMT_CBS_CFS,
32462306a36Sopenharmony_ci		.ignore_suspend = 1,
32562306a36Sopenharmony_ci		.c2c_params = &sub_params,
32662306a36Sopenharmony_ci		.num_c2c_params = 1,
32762306a36Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5102_sub),
32862306a36Sopenharmony_ci	},
32962306a36Sopenharmony_ci};
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5110_cpu_dsp,
33262306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")),
33362306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")),
33462306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5110_dsp_codec,
33762306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")),
33862306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm5110-codec", "wm5110-aif1")));
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5110_baseband,
34162306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm5110-aif2")),
34262306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1")));
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5110_sub,
34662306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm5110-aif3")),
34762306a36Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi")));
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_cistatic struct snd_soc_dai_link bells_dai_wm5110[] = {
35062306a36Sopenharmony_ci	{
35162306a36Sopenharmony_ci		.name = "CPU-DSP",
35262306a36Sopenharmony_ci		.stream_name = "CPU-DSP",
35362306a36Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
35462306a36Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
35562306a36Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5110_cpu_dsp),
35662306a36Sopenharmony_ci	},
35762306a36Sopenharmony_ci	{
35862306a36Sopenharmony_ci		.name = "DSP-CODEC",
35962306a36Sopenharmony_ci		.stream_name = "DSP-CODEC",
36062306a36Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
36162306a36Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
36262306a36Sopenharmony_ci		.c2c_params = &sub_params,
36362306a36Sopenharmony_ci		.num_c2c_params = 1,
36462306a36Sopenharmony_ci		.ignore_suspend = 1,
36562306a36Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5110_dsp_codec),
36662306a36Sopenharmony_ci	},
36762306a36Sopenharmony_ci	{
36862306a36Sopenharmony_ci		.name = "Baseband",
36962306a36Sopenharmony_ci		.stream_name = "Baseband",
37062306a36Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
37162306a36Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
37262306a36Sopenharmony_ci		.ignore_suspend = 1,
37362306a36Sopenharmony_ci		.c2c_params = &baseband_params,
37462306a36Sopenharmony_ci		.num_c2c_params = 1,
37562306a36Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5110_baseband),
37662306a36Sopenharmony_ci	},
37762306a36Sopenharmony_ci	{
37862306a36Sopenharmony_ci		.name = "Sub",
37962306a36Sopenharmony_ci		.stream_name = "Sub",
38062306a36Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
38162306a36Sopenharmony_ci				| SND_SOC_DAIFMT_CBS_CFS,
38262306a36Sopenharmony_ci		.ignore_suspend = 1,
38362306a36Sopenharmony_ci		.c2c_params = &sub_params,
38462306a36Sopenharmony_ci		.num_c2c_params = 1,
38562306a36Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5110_sub),
38662306a36Sopenharmony_ci	},
38762306a36Sopenharmony_ci};
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_cistatic struct snd_soc_codec_conf bells_codec_conf[] = {
39062306a36Sopenharmony_ci	{
39162306a36Sopenharmony_ci		.dlc = COMP_CODEC_CONF("wm9081.1-006c"),
39262306a36Sopenharmony_ci		.name_prefix = "Sub",
39362306a36Sopenharmony_ci	},
39462306a36Sopenharmony_ci};
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget bells_widgets[] = {
39762306a36Sopenharmony_ci	SND_SOC_DAPM_MIC("DMIC", NULL),
39862306a36Sopenharmony_ci};
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_cistatic const struct snd_soc_dapm_route bells_routes[] = {
40162306a36Sopenharmony_ci	{ "Sub CLK_SYS", NULL, "OPCLK" },
40262306a36Sopenharmony_ci	{ "CLKIN", NULL, "OPCLK" },
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	{ "DMIC", NULL, "MICBIAS2" },
40562306a36Sopenharmony_ci	{ "IN2L", NULL, "DMIC" },
40662306a36Sopenharmony_ci	{ "IN2R", NULL, "DMIC" },
40762306a36Sopenharmony_ci};
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_cistatic struct snd_soc_card bells_cards[] = {
41062306a36Sopenharmony_ci	{
41162306a36Sopenharmony_ci		.name = "Bells WM2200",
41262306a36Sopenharmony_ci		.owner = THIS_MODULE,
41362306a36Sopenharmony_ci		.dai_link = bells_dai_wm2200,
41462306a36Sopenharmony_ci		.num_links = ARRAY_SIZE(bells_dai_wm2200),
41562306a36Sopenharmony_ci		.codec_conf = bells_codec_conf,
41662306a36Sopenharmony_ci		.num_configs = ARRAY_SIZE(bells_codec_conf),
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci		.late_probe = bells_late_probe,
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci		.dapm_widgets = bells_widgets,
42162306a36Sopenharmony_ci		.num_dapm_widgets = ARRAY_SIZE(bells_widgets),
42262306a36Sopenharmony_ci		.dapm_routes = bells_routes,
42362306a36Sopenharmony_ci		.num_dapm_routes = ARRAY_SIZE(bells_routes),
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci		.set_bias_level = bells_set_bias_level,
42662306a36Sopenharmony_ci		.set_bias_level_post = bells_set_bias_level_post,
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci		.drvdata = &wm2200_drvdata,
42962306a36Sopenharmony_ci	},
43062306a36Sopenharmony_ci	{
43162306a36Sopenharmony_ci		.name = "Bells WM5102",
43262306a36Sopenharmony_ci		.owner = THIS_MODULE,
43362306a36Sopenharmony_ci		.dai_link = bells_dai_wm5102,
43462306a36Sopenharmony_ci		.num_links = ARRAY_SIZE(bells_dai_wm5102),
43562306a36Sopenharmony_ci		.codec_conf = bells_codec_conf,
43662306a36Sopenharmony_ci		.num_configs = ARRAY_SIZE(bells_codec_conf),
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci		.late_probe = bells_late_probe,
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci		.dapm_widgets = bells_widgets,
44162306a36Sopenharmony_ci		.num_dapm_widgets = ARRAY_SIZE(bells_widgets),
44262306a36Sopenharmony_ci		.dapm_routes = bells_routes,
44362306a36Sopenharmony_ci		.num_dapm_routes = ARRAY_SIZE(bells_routes),
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci		.set_bias_level = bells_set_bias_level,
44662306a36Sopenharmony_ci		.set_bias_level_post = bells_set_bias_level_post,
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci		.drvdata = &wm5102_drvdata,
44962306a36Sopenharmony_ci	},
45062306a36Sopenharmony_ci	{
45162306a36Sopenharmony_ci		.name = "Bells WM5110",
45262306a36Sopenharmony_ci		.owner = THIS_MODULE,
45362306a36Sopenharmony_ci		.dai_link = bells_dai_wm5110,
45462306a36Sopenharmony_ci		.num_links = ARRAY_SIZE(bells_dai_wm5110),
45562306a36Sopenharmony_ci		.codec_conf = bells_codec_conf,
45662306a36Sopenharmony_ci		.num_configs = ARRAY_SIZE(bells_codec_conf),
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci		.late_probe = bells_late_probe,
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci		.dapm_widgets = bells_widgets,
46162306a36Sopenharmony_ci		.num_dapm_widgets = ARRAY_SIZE(bells_widgets),
46262306a36Sopenharmony_ci		.dapm_routes = bells_routes,
46362306a36Sopenharmony_ci		.num_dapm_routes = ARRAY_SIZE(bells_routes),
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci		.set_bias_level = bells_set_bias_level,
46662306a36Sopenharmony_ci		.set_bias_level_post = bells_set_bias_level_post,
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci		.drvdata = &wm5110_drvdata,
46962306a36Sopenharmony_ci	},
47062306a36Sopenharmony_ci};
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_cistatic int bells_probe(struct platform_device *pdev)
47362306a36Sopenharmony_ci{
47462306a36Sopenharmony_ci	int ret;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	bells_cards[pdev->id].dev = &pdev->dev;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	ret = devm_snd_soc_register_card(&pdev->dev, &bells_cards[pdev->id]);
47962306a36Sopenharmony_ci	if (ret)
48062306a36Sopenharmony_ci		dev_err(&pdev->dev,
48162306a36Sopenharmony_ci			"snd_soc_register_card(%s) failed: %d\n",
48262306a36Sopenharmony_ci			bells_cards[pdev->id].name, ret);
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	return ret;
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_cistatic struct platform_driver bells_driver = {
48862306a36Sopenharmony_ci	.driver = {
48962306a36Sopenharmony_ci		.name = "bells",
49062306a36Sopenharmony_ci		.pm = &snd_soc_pm_ops,
49162306a36Sopenharmony_ci	},
49262306a36Sopenharmony_ci	.probe = bells_probe,
49362306a36Sopenharmony_ci};
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_cimodule_platform_driver(bells_driver);
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ciMODULE_DESCRIPTION("Bells audio support");
49862306a36Sopenharmony_ciMODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
49962306a36Sopenharmony_ciMODULE_LICENSE("GPL");
50062306a36Sopenharmony_ciMODULE_ALIAS("platform:bells");
501