18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// Bells audio support
48c2ecf20Sopenharmony_ci//
58c2ecf20Sopenharmony_ci// Copyright 2012 Wolfson Microelectronics
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <sound/soc.h>
88c2ecf20Sopenharmony_ci#include <sound/soc-dapm.h>
98c2ecf20Sopenharmony_ci#include <sound/jack.h>
108c2ecf20Sopenharmony_ci#include <linux/gpio.h>
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "../codecs/wm5102.h"
148c2ecf20Sopenharmony_ci#include "../codecs/wm9081.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/* BCLK2 is fixed at this currently */
178c2ecf20Sopenharmony_ci#define BCLK2_RATE (64 * 8000)
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/*
208c2ecf20Sopenharmony_ci * Expect a 24.576MHz crystal if one is fitted (the driver will function
218c2ecf20Sopenharmony_ci * if this is not fitted).
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_ci#define MCLK_RATE 24576000
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define SYS_AUDIO_RATE 44100
268c2ecf20Sopenharmony_ci#define SYS_MCLK_RATE  (SYS_AUDIO_RATE * 512)
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#define DAI_AP_DSP    0
298c2ecf20Sopenharmony_ci#define DAI_DSP_CODEC 1
308c2ecf20Sopenharmony_ci#define DAI_CODEC_CP  2
318c2ecf20Sopenharmony_ci#define DAI_CODEC_SUB 3
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistruct bells_drvdata {
348c2ecf20Sopenharmony_ci	int sysclk_rate;
358c2ecf20Sopenharmony_ci	int asyncclk_rate;
368c2ecf20Sopenharmony_ci};
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistatic struct bells_drvdata wm2200_drvdata = {
398c2ecf20Sopenharmony_ci	.sysclk_rate = 22579200,
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic struct bells_drvdata wm5102_drvdata = {
438c2ecf20Sopenharmony_ci	.sysclk_rate = 45158400,
448c2ecf20Sopenharmony_ci	.asyncclk_rate = 49152000,
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic struct bells_drvdata wm5110_drvdata = {
488c2ecf20Sopenharmony_ci	.sysclk_rate = 135475200,
498c2ecf20Sopenharmony_ci	.asyncclk_rate = 147456000,
508c2ecf20Sopenharmony_ci};
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic int bells_set_bias_level(struct snd_soc_card *card,
538c2ecf20Sopenharmony_ci				struct snd_soc_dapm_context *dapm,
548c2ecf20Sopenharmony_ci				enum snd_soc_bias_level level)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd;
578c2ecf20Sopenharmony_ci	struct snd_soc_dai *codec_dai;
588c2ecf20Sopenharmony_ci	struct snd_soc_component *component;
598c2ecf20Sopenharmony_ci	struct bells_drvdata *bells = card->drvdata;
608c2ecf20Sopenharmony_ci	int ret;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]);
638c2ecf20Sopenharmony_ci	codec_dai = asoc_rtd_to_codec(rtd, 0);
648c2ecf20Sopenharmony_ci	component = codec_dai->component;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	if (dapm->dev != codec_dai->dev)
678c2ecf20Sopenharmony_ci		return 0;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	switch (level) {
708c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_PREPARE:
718c2ecf20Sopenharmony_ci		if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
728c2ecf20Sopenharmony_ci			break;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci		ret = snd_soc_component_set_pll(component, WM5102_FLL1,
758c2ecf20Sopenharmony_ci					    ARIZONA_FLL_SRC_MCLK1,
768c2ecf20Sopenharmony_ci					    MCLK_RATE,
778c2ecf20Sopenharmony_ci					    bells->sysclk_rate);
788c2ecf20Sopenharmony_ci		if (ret < 0)
798c2ecf20Sopenharmony_ci			pr_err("Failed to start FLL: %d\n", ret);
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci		if (bells->asyncclk_rate) {
828c2ecf20Sopenharmony_ci			ret = snd_soc_component_set_pll(component, WM5102_FLL2,
838c2ecf20Sopenharmony_ci						    ARIZONA_FLL_SRC_AIF2BCLK,
848c2ecf20Sopenharmony_ci						    BCLK2_RATE,
858c2ecf20Sopenharmony_ci						    bells->asyncclk_rate);
868c2ecf20Sopenharmony_ci			if (ret < 0)
878c2ecf20Sopenharmony_ci				pr_err("Failed to start FLL: %d\n", ret);
888c2ecf20Sopenharmony_ci		}
898c2ecf20Sopenharmony_ci		break;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	default:
928c2ecf20Sopenharmony_ci		break;
938c2ecf20Sopenharmony_ci	}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	return 0;
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic int bells_set_bias_level_post(struct snd_soc_card *card,
998c2ecf20Sopenharmony_ci				     struct snd_soc_dapm_context *dapm,
1008c2ecf20Sopenharmony_ci				     enum snd_soc_bias_level level)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd;
1038c2ecf20Sopenharmony_ci	struct snd_soc_dai *codec_dai;
1048c2ecf20Sopenharmony_ci	struct snd_soc_component *component;
1058c2ecf20Sopenharmony_ci	struct bells_drvdata *bells = card->drvdata;
1068c2ecf20Sopenharmony_ci	int ret;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]);
1098c2ecf20Sopenharmony_ci	codec_dai = asoc_rtd_to_codec(rtd, 0);
1108c2ecf20Sopenharmony_ci	component = codec_dai->component;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	if (dapm->dev != codec_dai->dev)
1138c2ecf20Sopenharmony_ci		return 0;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	switch (level) {
1168c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_STANDBY:
1178c2ecf20Sopenharmony_ci		ret = snd_soc_component_set_pll(component, WM5102_FLL1, 0, 0, 0);
1188c2ecf20Sopenharmony_ci		if (ret < 0) {
1198c2ecf20Sopenharmony_ci			pr_err("Failed to stop FLL: %d\n", ret);
1208c2ecf20Sopenharmony_ci			return ret;
1218c2ecf20Sopenharmony_ci		}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci		if (bells->asyncclk_rate) {
1248c2ecf20Sopenharmony_ci			ret = snd_soc_component_set_pll(component, WM5102_FLL2,
1258c2ecf20Sopenharmony_ci						    0, 0, 0);
1268c2ecf20Sopenharmony_ci			if (ret < 0) {
1278c2ecf20Sopenharmony_ci				pr_err("Failed to stop FLL: %d\n", ret);
1288c2ecf20Sopenharmony_ci				return ret;
1298c2ecf20Sopenharmony_ci			}
1308c2ecf20Sopenharmony_ci		}
1318c2ecf20Sopenharmony_ci		break;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	default:
1348c2ecf20Sopenharmony_ci		break;
1358c2ecf20Sopenharmony_ci	}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	dapm->bias_level = level;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	return 0;
1408c2ecf20Sopenharmony_ci}
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_cistatic int bells_late_probe(struct snd_soc_card *card)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	struct bells_drvdata *bells = card->drvdata;
1458c2ecf20Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd;
1468c2ecf20Sopenharmony_ci	struct snd_soc_component *wm0010;
1478c2ecf20Sopenharmony_ci	struct snd_soc_component *component;
1488c2ecf20Sopenharmony_ci	struct snd_soc_dai *aif1_dai;
1498c2ecf20Sopenharmony_ci	struct snd_soc_dai *aif2_dai;
1508c2ecf20Sopenharmony_ci	struct snd_soc_dai *aif3_dai;
1518c2ecf20Sopenharmony_ci	struct snd_soc_dai *wm9081_dai;
1528c2ecf20Sopenharmony_ci	int ret;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_AP_DSP]);
1558c2ecf20Sopenharmony_ci	wm0010 = asoc_rtd_to_codec(rtd, 0)->component;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]);
1588c2ecf20Sopenharmony_ci	component = asoc_rtd_to_codec(rtd, 0)->component;
1598c2ecf20Sopenharmony_ci	aif1_dai = asoc_rtd_to_codec(rtd, 0);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_SYSCLK,
1628c2ecf20Sopenharmony_ci				       ARIZONA_CLK_SRC_FLL1,
1638c2ecf20Sopenharmony_ci				       bells->sysclk_rate,
1648c2ecf20Sopenharmony_ci				       SND_SOC_CLOCK_IN);
1658c2ecf20Sopenharmony_ci	if (ret != 0) {
1668c2ecf20Sopenharmony_ci		dev_err(component->dev, "Failed to set SYSCLK: %d\n", ret);
1678c2ecf20Sopenharmony_ci		return ret;
1688c2ecf20Sopenharmony_ci	}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	ret = snd_soc_component_set_sysclk(wm0010, 0, 0, SYS_MCLK_RATE, 0);
1718c2ecf20Sopenharmony_ci	if (ret != 0) {
1728c2ecf20Sopenharmony_ci		dev_err(wm0010->dev, "Failed to set WM0010 clock: %d\n", ret);
1738c2ecf20Sopenharmony_ci		return ret;
1748c2ecf20Sopenharmony_ci	}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
1778c2ecf20Sopenharmony_ci	if (ret != 0)
1788c2ecf20Sopenharmony_ci		dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_OPCLK, 0,
1818c2ecf20Sopenharmony_ci				       SYS_MCLK_RATE, SND_SOC_CLOCK_OUT);
1828c2ecf20Sopenharmony_ci	if (ret != 0)
1838c2ecf20Sopenharmony_ci		dev_err(component->dev, "Failed to set OPCLK: %d\n", ret);
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	if (card->num_rtd == DAI_CODEC_CP)
1868c2ecf20Sopenharmony_ci		return 0;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_ASYNCCLK,
1898c2ecf20Sopenharmony_ci				       ARIZONA_CLK_SRC_FLL2,
1908c2ecf20Sopenharmony_ci				       bells->asyncclk_rate,
1918c2ecf20Sopenharmony_ci				       SND_SOC_CLOCK_IN);
1928c2ecf20Sopenharmony_ci	if (ret != 0) {
1938c2ecf20Sopenharmony_ci		dev_err(component->dev, "Failed to set ASYNCCLK: %d\n", ret);
1948c2ecf20Sopenharmony_ci		return ret;
1958c2ecf20Sopenharmony_ci	}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_CODEC_CP]);
1988c2ecf20Sopenharmony_ci	aif2_dai = asoc_rtd_to_cpu(rtd, 0);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
2018c2ecf20Sopenharmony_ci	if (ret != 0) {
2028c2ecf20Sopenharmony_ci		dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
2038c2ecf20Sopenharmony_ci		return ret;
2048c2ecf20Sopenharmony_ci	}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	if (card->num_rtd == DAI_CODEC_SUB)
2078c2ecf20Sopenharmony_ci		return 0;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_CODEC_SUB]);
2108c2ecf20Sopenharmony_ci	aif3_dai = asoc_rtd_to_cpu(rtd, 0);
2118c2ecf20Sopenharmony_ci	wm9081_dai = asoc_rtd_to_codec(rtd, 0);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
2148c2ecf20Sopenharmony_ci	if (ret != 0) {
2158c2ecf20Sopenharmony_ci		dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
2168c2ecf20Sopenharmony_ci		return ret;
2178c2ecf20Sopenharmony_ci	}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	ret = snd_soc_component_set_sysclk(wm9081_dai->component, WM9081_SYSCLK_MCLK,
2208c2ecf20Sopenharmony_ci				       0, SYS_MCLK_RATE, 0);
2218c2ecf20Sopenharmony_ci	if (ret != 0) {
2228c2ecf20Sopenharmony_ci		dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret);
2238c2ecf20Sopenharmony_ci		return ret;
2248c2ecf20Sopenharmony_ci	}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	return 0;
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_cistatic const struct snd_soc_pcm_stream baseband_params = {
2308c2ecf20Sopenharmony_ci	.formats = SNDRV_PCM_FMTBIT_S32_LE,
2318c2ecf20Sopenharmony_ci	.rate_min = 8000,
2328c2ecf20Sopenharmony_ci	.rate_max = 8000,
2338c2ecf20Sopenharmony_ci	.channels_min = 2,
2348c2ecf20Sopenharmony_ci	.channels_max = 2,
2358c2ecf20Sopenharmony_ci};
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_cistatic const struct snd_soc_pcm_stream sub_params = {
2388c2ecf20Sopenharmony_ci	.formats = SNDRV_PCM_FMTBIT_S32_LE,
2398c2ecf20Sopenharmony_ci	.rate_min = SYS_AUDIO_RATE,
2408c2ecf20Sopenharmony_ci	.rate_max = SYS_AUDIO_RATE,
2418c2ecf20Sopenharmony_ci	.channels_min = 2,
2428c2ecf20Sopenharmony_ci	.channels_max = 2,
2438c2ecf20Sopenharmony_ci};
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm2200_cpu_dsp,
2468c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")),
2478c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")),
2488c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm2200_dsp_codec,
2518c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")),
2528c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm2200.1-003a", "wm2200")));
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistatic struct snd_soc_dai_link bells_dai_wm2200[] = {
2558c2ecf20Sopenharmony_ci	{
2568c2ecf20Sopenharmony_ci		.name = "CPU-DSP",
2578c2ecf20Sopenharmony_ci		.stream_name = "CPU-DSP",
2588c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
2598c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
2608c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(wm2200_cpu_dsp),
2618c2ecf20Sopenharmony_ci	},
2628c2ecf20Sopenharmony_ci	{
2638c2ecf20Sopenharmony_ci		.name = "DSP-CODEC",
2648c2ecf20Sopenharmony_ci		.stream_name = "DSP-CODEC",
2658c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
2668c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
2678c2ecf20Sopenharmony_ci		.params = &sub_params,
2688c2ecf20Sopenharmony_ci		.ignore_suspend = 1,
2698c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(wm2200_dsp_codec),
2708c2ecf20Sopenharmony_ci	},
2718c2ecf20Sopenharmony_ci};
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5102_cpu_dsp,
2748c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")),
2758c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")),
2768c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5102_dsp_codec,
2798c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")),
2808c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm5102-codec", "wm5102-aif1")));
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5102_baseband,
2838c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif2")),
2848c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1")));
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5102_sub,
2878c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif3")),
2888c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi")));
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistatic struct snd_soc_dai_link bells_dai_wm5102[] = {
2918c2ecf20Sopenharmony_ci	{
2928c2ecf20Sopenharmony_ci		.name = "CPU-DSP",
2938c2ecf20Sopenharmony_ci		.stream_name = "CPU-DSP",
2948c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
2958c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
2968c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5102_cpu_dsp),
2978c2ecf20Sopenharmony_ci	},
2988c2ecf20Sopenharmony_ci	{
2998c2ecf20Sopenharmony_ci		.name = "DSP-CODEC",
3008c2ecf20Sopenharmony_ci		.stream_name = "DSP-CODEC",
3018c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
3028c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
3038c2ecf20Sopenharmony_ci		.params = &sub_params,
3048c2ecf20Sopenharmony_ci		.ignore_suspend = 1,
3058c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5102_dsp_codec),
3068c2ecf20Sopenharmony_ci	},
3078c2ecf20Sopenharmony_ci	{
3088c2ecf20Sopenharmony_ci		.name = "Baseband",
3098c2ecf20Sopenharmony_ci		.stream_name = "Baseband",
3108c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
3118c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
3128c2ecf20Sopenharmony_ci		.ignore_suspend = 1,
3138c2ecf20Sopenharmony_ci		.params = &baseband_params,
3148c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5102_baseband),
3158c2ecf20Sopenharmony_ci	},
3168c2ecf20Sopenharmony_ci	{
3178c2ecf20Sopenharmony_ci		.name = "Sub",
3188c2ecf20Sopenharmony_ci		.stream_name = "Sub",
3198c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
3208c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBS_CFS,
3218c2ecf20Sopenharmony_ci		.ignore_suspend = 1,
3228c2ecf20Sopenharmony_ci		.params = &sub_params,
3238c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5102_sub),
3248c2ecf20Sopenharmony_ci	},
3258c2ecf20Sopenharmony_ci};
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5110_cpu_dsp,
3288c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")),
3298c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")),
3308c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5110_dsp_codec,
3338c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")),
3348c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm5110-codec", "wm5110-aif1")));
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5110_baseband,
3378c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm5110-aif2")),
3388c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1")));
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(wm5110_sub,
3428c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("wm5110-aif3")),
3438c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi")));
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic struct snd_soc_dai_link bells_dai_wm5110[] = {
3468c2ecf20Sopenharmony_ci	{
3478c2ecf20Sopenharmony_ci		.name = "CPU-DSP",
3488c2ecf20Sopenharmony_ci		.stream_name = "CPU-DSP",
3498c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
3508c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
3518c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5110_cpu_dsp),
3528c2ecf20Sopenharmony_ci	},
3538c2ecf20Sopenharmony_ci	{
3548c2ecf20Sopenharmony_ci		.name = "DSP-CODEC",
3558c2ecf20Sopenharmony_ci		.stream_name = "DSP-CODEC",
3568c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
3578c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
3588c2ecf20Sopenharmony_ci		.params = &sub_params,
3598c2ecf20Sopenharmony_ci		.ignore_suspend = 1,
3608c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5110_dsp_codec),
3618c2ecf20Sopenharmony_ci	},
3628c2ecf20Sopenharmony_ci	{
3638c2ecf20Sopenharmony_ci		.name = "Baseband",
3648c2ecf20Sopenharmony_ci		.stream_name = "Baseband",
3658c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
3668c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
3678c2ecf20Sopenharmony_ci		.ignore_suspend = 1,
3688c2ecf20Sopenharmony_ci		.params = &baseband_params,
3698c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5110_baseband),
3708c2ecf20Sopenharmony_ci	},
3718c2ecf20Sopenharmony_ci	{
3728c2ecf20Sopenharmony_ci		.name = "Sub",
3738c2ecf20Sopenharmony_ci		.stream_name = "Sub",
3748c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
3758c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBS_CFS,
3768c2ecf20Sopenharmony_ci		.ignore_suspend = 1,
3778c2ecf20Sopenharmony_ci		.params = &sub_params,
3788c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(wm5110_sub),
3798c2ecf20Sopenharmony_ci	},
3808c2ecf20Sopenharmony_ci};
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_cistatic struct snd_soc_codec_conf bells_codec_conf[] = {
3838c2ecf20Sopenharmony_ci	{
3848c2ecf20Sopenharmony_ci		.dlc = COMP_CODEC_CONF("wm9081.1-006c"),
3858c2ecf20Sopenharmony_ci		.name_prefix = "Sub",
3868c2ecf20Sopenharmony_ci	},
3878c2ecf20Sopenharmony_ci};
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_cistatic struct snd_soc_dapm_widget bells_widgets[] = {
3908c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MIC("DMIC", NULL),
3918c2ecf20Sopenharmony_ci};
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_cistatic struct snd_soc_dapm_route bells_routes[] = {
3948c2ecf20Sopenharmony_ci	{ "Sub CLK_SYS", NULL, "OPCLK" },
3958c2ecf20Sopenharmony_ci	{ "CLKIN", NULL, "OPCLK" },
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	{ "DMIC", NULL, "MICBIAS2" },
3988c2ecf20Sopenharmony_ci	{ "IN2L", NULL, "DMIC" },
3998c2ecf20Sopenharmony_ci	{ "IN2R", NULL, "DMIC" },
4008c2ecf20Sopenharmony_ci};
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_cistatic struct snd_soc_card bells_cards[] = {
4038c2ecf20Sopenharmony_ci	{
4048c2ecf20Sopenharmony_ci		.name = "Bells WM2200",
4058c2ecf20Sopenharmony_ci		.owner = THIS_MODULE,
4068c2ecf20Sopenharmony_ci		.dai_link = bells_dai_wm2200,
4078c2ecf20Sopenharmony_ci		.num_links = ARRAY_SIZE(bells_dai_wm2200),
4088c2ecf20Sopenharmony_ci		.codec_conf = bells_codec_conf,
4098c2ecf20Sopenharmony_ci		.num_configs = ARRAY_SIZE(bells_codec_conf),
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci		.late_probe = bells_late_probe,
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci		.dapm_widgets = bells_widgets,
4148c2ecf20Sopenharmony_ci		.num_dapm_widgets = ARRAY_SIZE(bells_widgets),
4158c2ecf20Sopenharmony_ci		.dapm_routes = bells_routes,
4168c2ecf20Sopenharmony_ci		.num_dapm_routes = ARRAY_SIZE(bells_routes),
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci		.set_bias_level = bells_set_bias_level,
4198c2ecf20Sopenharmony_ci		.set_bias_level_post = bells_set_bias_level_post,
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci		.drvdata = &wm2200_drvdata,
4228c2ecf20Sopenharmony_ci	},
4238c2ecf20Sopenharmony_ci	{
4248c2ecf20Sopenharmony_ci		.name = "Bells WM5102",
4258c2ecf20Sopenharmony_ci		.owner = THIS_MODULE,
4268c2ecf20Sopenharmony_ci		.dai_link = bells_dai_wm5102,
4278c2ecf20Sopenharmony_ci		.num_links = ARRAY_SIZE(bells_dai_wm5102),
4288c2ecf20Sopenharmony_ci		.codec_conf = bells_codec_conf,
4298c2ecf20Sopenharmony_ci		.num_configs = ARRAY_SIZE(bells_codec_conf),
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci		.late_probe = bells_late_probe,
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci		.dapm_widgets = bells_widgets,
4348c2ecf20Sopenharmony_ci		.num_dapm_widgets = ARRAY_SIZE(bells_widgets),
4358c2ecf20Sopenharmony_ci		.dapm_routes = bells_routes,
4368c2ecf20Sopenharmony_ci		.num_dapm_routes = ARRAY_SIZE(bells_routes),
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci		.set_bias_level = bells_set_bias_level,
4398c2ecf20Sopenharmony_ci		.set_bias_level_post = bells_set_bias_level_post,
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci		.drvdata = &wm5102_drvdata,
4428c2ecf20Sopenharmony_ci	},
4438c2ecf20Sopenharmony_ci	{
4448c2ecf20Sopenharmony_ci		.name = "Bells WM5110",
4458c2ecf20Sopenharmony_ci		.owner = THIS_MODULE,
4468c2ecf20Sopenharmony_ci		.dai_link = bells_dai_wm5110,
4478c2ecf20Sopenharmony_ci		.num_links = ARRAY_SIZE(bells_dai_wm5110),
4488c2ecf20Sopenharmony_ci		.codec_conf = bells_codec_conf,
4498c2ecf20Sopenharmony_ci		.num_configs = ARRAY_SIZE(bells_codec_conf),
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci		.late_probe = bells_late_probe,
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci		.dapm_widgets = bells_widgets,
4548c2ecf20Sopenharmony_ci		.num_dapm_widgets = ARRAY_SIZE(bells_widgets),
4558c2ecf20Sopenharmony_ci		.dapm_routes = bells_routes,
4568c2ecf20Sopenharmony_ci		.num_dapm_routes = ARRAY_SIZE(bells_routes),
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci		.set_bias_level = bells_set_bias_level,
4598c2ecf20Sopenharmony_ci		.set_bias_level_post = bells_set_bias_level_post,
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci		.drvdata = &wm5110_drvdata,
4628c2ecf20Sopenharmony_ci	},
4638c2ecf20Sopenharmony_ci};
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_cistatic int bells_probe(struct platform_device *pdev)
4668c2ecf20Sopenharmony_ci{
4678c2ecf20Sopenharmony_ci	int ret;
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	bells_cards[pdev->id].dev = &pdev->dev;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	ret = devm_snd_soc_register_card(&pdev->dev, &bells_cards[pdev->id]);
4728c2ecf20Sopenharmony_ci	if (ret)
4738c2ecf20Sopenharmony_ci		dev_err(&pdev->dev,
4748c2ecf20Sopenharmony_ci			"snd_soc_register_card(%s) failed: %d\n",
4758c2ecf20Sopenharmony_ci			bells_cards[pdev->id].name, ret);
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	return ret;
4788c2ecf20Sopenharmony_ci}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_cistatic struct platform_driver bells_driver = {
4818c2ecf20Sopenharmony_ci	.driver = {
4828c2ecf20Sopenharmony_ci		.name = "bells",
4838c2ecf20Sopenharmony_ci		.pm = &snd_soc_pm_ops,
4848c2ecf20Sopenharmony_ci	},
4858c2ecf20Sopenharmony_ci	.probe = bells_probe,
4868c2ecf20Sopenharmony_ci};
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_cimodule_platform_driver(bells_driver);
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Bells audio support");
4918c2ecf20Sopenharmony_ciMODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
4928c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
4938c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:bells");
494