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