141ce2ac0SSylwester Nawrocki // SPDX-License-Identifier: GPL-2.0+ 241ce2ac0SSylwester Nawrocki // 341ce2ac0SSylwester Nawrocki // Bells audio support 441ce2ac0SSylwester Nawrocki // 541ce2ac0SSylwester Nawrocki // Copyright 2012 Wolfson Microelectronics 6b545dd92SMark Brown 7b545dd92SMark Brown #include <sound/soc.h> 8b545dd92SMark Brown #include <sound/soc-dapm.h> 9b545dd92SMark Brown #include <sound/jack.h> 10b545dd92SMark Brown #include <linux/gpio.h> 11b545dd92SMark Brown #include <linux/module.h> 12b545dd92SMark Brown 13b545dd92SMark Brown #include "../codecs/wm5102.h" 14b545dd92SMark Brown #include "../codecs/wm9081.h" 15b545dd92SMark Brown 16b545dd92SMark Brown /* BCLK2 is fixed at this currently */ 17b545dd92SMark Brown #define BCLK2_RATE (64 * 8000) 18b545dd92SMark Brown 19b545dd92SMark Brown /* 20b545dd92SMark Brown * Expect a 24.576MHz crystal if one is fitted (the driver will function 21b545dd92SMark Brown * if this is not fitted). 22b545dd92SMark Brown */ 23b545dd92SMark Brown #define MCLK_RATE 24576000 24b545dd92SMark Brown 25344c5edeSMark Brown #define SYS_AUDIO_RATE 44100 26208229ecSDimitris Papastamos #define SYS_MCLK_RATE (SYS_AUDIO_RATE * 512) 27344c5edeSMark Brown 28344c5edeSMark Brown #define DAI_AP_DSP 0 29344c5edeSMark Brown #define DAI_DSP_CODEC 1 30344c5edeSMark Brown #define DAI_CODEC_CP 2 31344c5edeSMark Brown #define DAI_CODEC_SUB 3 32b545dd92SMark Brown 33b1387078SMark Brown struct bells_drvdata { 34b1387078SMark Brown int sysclk_rate; 35b1387078SMark Brown int asyncclk_rate; 36b1387078SMark Brown }; 37b1387078SMark Brown 388d47e8a5SMark Brown static struct bells_drvdata wm2200_drvdata = { 398d47e8a5SMark Brown .sysclk_rate = 22579200, 408d47e8a5SMark Brown }; 418d47e8a5SMark Brown 42b1387078SMark Brown static struct bells_drvdata wm5102_drvdata = { 43b1387078SMark Brown .sysclk_rate = 45158400, 44b1387078SMark Brown .asyncclk_rate = 49152000, 45b1387078SMark Brown }; 46b1387078SMark Brown 47b1387078SMark Brown static struct bells_drvdata wm5110_drvdata = { 48b1387078SMark Brown .sysclk_rate = 135475200, 49b1387078SMark Brown .asyncclk_rate = 147456000, 50b1387078SMark Brown }; 51b1387078SMark Brown 52b545dd92SMark Brown static int bells_set_bias_level(struct snd_soc_card *card, 53b545dd92SMark Brown struct snd_soc_dapm_context *dapm, 54b545dd92SMark Brown enum snd_soc_bias_level level) 55b545dd92SMark Brown { 565015920aSMengdong Lin struct snd_soc_pcm_runtime *rtd; 575015920aSMengdong Lin struct snd_soc_dai *codec_dai; 58f4a2be1cSKuninori Morimoto struct snd_soc_component *component; 59b1387078SMark Brown struct bells_drvdata *bells = card->drvdata; 60b545dd92SMark Brown int ret; 61b545dd92SMark Brown 624468189fSKuninori Morimoto rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]); 635015920aSMengdong Lin codec_dai = rtd->codec_dai; 64f4a2be1cSKuninori Morimoto component = codec_dai->component; 655015920aSMengdong Lin 66b545dd92SMark Brown if (dapm->dev != codec_dai->dev) 67b545dd92SMark Brown return 0; 68b545dd92SMark Brown 69b545dd92SMark Brown switch (level) { 70b545dd92SMark Brown case SND_SOC_BIAS_PREPARE: 71b1387078SMark Brown if (dapm->bias_level != SND_SOC_BIAS_STANDBY) 72b1387078SMark Brown break; 73b1387078SMark Brown 74f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_pll(component, WM5102_FLL1, 75b545dd92SMark Brown ARIZONA_FLL_SRC_MCLK1, 76b545dd92SMark Brown MCLK_RATE, 77b1387078SMark Brown bells->sysclk_rate); 78b545dd92SMark Brown if (ret < 0) 79b545dd92SMark Brown pr_err("Failed to start FLL: %d\n", ret); 80b545dd92SMark Brown 81b1387078SMark Brown if (bells->asyncclk_rate) { 82f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_pll(component, WM5102_FLL2, 83b545dd92SMark Brown ARIZONA_FLL_SRC_AIF2BCLK, 84b545dd92SMark Brown BCLK2_RATE, 85b1387078SMark Brown bells->asyncclk_rate); 86b545dd92SMark Brown if (ret < 0) 87b545dd92SMark Brown pr_err("Failed to start FLL: %d\n", ret); 88b545dd92SMark Brown } 89b545dd92SMark Brown break; 90b545dd92SMark Brown 91b545dd92SMark Brown default: 92b545dd92SMark Brown break; 93b545dd92SMark Brown } 94b545dd92SMark Brown 95b545dd92SMark Brown return 0; 96b545dd92SMark Brown } 97b545dd92SMark Brown 98b545dd92SMark Brown static int bells_set_bias_level_post(struct snd_soc_card *card, 99b545dd92SMark Brown struct snd_soc_dapm_context *dapm, 100b545dd92SMark Brown enum snd_soc_bias_level level) 101b545dd92SMark Brown { 1025015920aSMengdong Lin struct snd_soc_pcm_runtime *rtd; 1035015920aSMengdong Lin struct snd_soc_dai *codec_dai; 104f4a2be1cSKuninori Morimoto struct snd_soc_component *component; 105b1387078SMark Brown struct bells_drvdata *bells = card->drvdata; 106b545dd92SMark Brown int ret; 107b545dd92SMark Brown 1084468189fSKuninori Morimoto rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]); 1095015920aSMengdong Lin codec_dai = rtd->codec_dai; 110f4a2be1cSKuninori Morimoto component = codec_dai->component; 1115015920aSMengdong Lin 112b545dd92SMark Brown if (dapm->dev != codec_dai->dev) 113b545dd92SMark Brown return 0; 114b545dd92SMark Brown 115b545dd92SMark Brown switch (level) { 116b545dd92SMark Brown case SND_SOC_BIAS_STANDBY: 117f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_pll(component, WM5102_FLL1, 0, 0, 0); 118b545dd92SMark Brown if (ret < 0) { 119b545dd92SMark Brown pr_err("Failed to stop FLL: %d\n", ret); 120b545dd92SMark Brown return ret; 121b545dd92SMark Brown } 122b545dd92SMark Brown 123b1387078SMark Brown if (bells->asyncclk_rate) { 124f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_pll(component, WM5102_FLL2, 125b1387078SMark Brown 0, 0, 0); 126b545dd92SMark Brown if (ret < 0) { 127b545dd92SMark Brown pr_err("Failed to stop FLL: %d\n", ret); 128b545dd92SMark Brown return ret; 129b545dd92SMark Brown } 130b1387078SMark Brown } 131b545dd92SMark Brown break; 132b545dd92SMark Brown 133b545dd92SMark Brown default: 134b545dd92SMark Brown break; 135b545dd92SMark Brown } 136b545dd92SMark Brown 137b545dd92SMark Brown dapm->bias_level = level; 138b545dd92SMark Brown 139b545dd92SMark Brown return 0; 140b545dd92SMark Brown } 141b545dd92SMark Brown 142b545dd92SMark Brown static int bells_late_probe(struct snd_soc_card *card) 143b545dd92SMark Brown { 144b1387078SMark Brown struct bells_drvdata *bells = card->drvdata; 1455015920aSMengdong Lin struct snd_soc_pcm_runtime *rtd; 146f4a2be1cSKuninori Morimoto struct snd_soc_component *wm0010; 147f4a2be1cSKuninori Morimoto struct snd_soc_component *component; 1485015920aSMengdong Lin struct snd_soc_dai *aif1_dai; 149b1387078SMark Brown struct snd_soc_dai *aif2_dai; 150b1387078SMark Brown struct snd_soc_dai *aif3_dai; 151b1387078SMark Brown struct snd_soc_dai *wm9081_dai; 152b545dd92SMark Brown int ret; 153b545dd92SMark Brown 1544468189fSKuninori Morimoto rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_AP_DSP]); 155f4a2be1cSKuninori Morimoto wm0010 = rtd->codec_dai->component; 1565015920aSMengdong Lin 1574468189fSKuninori Morimoto rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_DSP_CODEC]); 158f4a2be1cSKuninori Morimoto component = rtd->codec_dai->component; 1595015920aSMengdong Lin aif1_dai = rtd->codec_dai; 1605015920aSMengdong Lin 161f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_SYSCLK, 162b1387078SMark Brown ARIZONA_CLK_SRC_FLL1, 163b1387078SMark Brown bells->sysclk_rate, 164b1387078SMark Brown SND_SOC_CLOCK_IN); 165b1387078SMark Brown if (ret != 0) { 166f4a2be1cSKuninori Morimoto dev_err(component->dev, "Failed to set SYSCLK: %d\n", ret); 167b1387078SMark Brown return ret; 168b1387078SMark Brown } 169b1387078SMark Brown 170f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_sysclk(wm0010, 0, 0, SYS_MCLK_RATE, 0); 171344c5edeSMark Brown if (ret != 0) { 172344c5edeSMark Brown dev_err(wm0010->dev, "Failed to set WM0010 clock: %d\n", ret); 173344c5edeSMark Brown return ret; 174344c5edeSMark Brown } 175344c5edeSMark Brown 176b545dd92SMark Brown ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0); 177b1387078SMark Brown if (ret != 0) 178b545dd92SMark Brown dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); 179b1387078SMark Brown 180f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_OPCLK, 0, 181b1387078SMark Brown SYS_MCLK_RATE, SND_SOC_CLOCK_OUT); 182b1387078SMark Brown if (ret != 0) 183f4a2be1cSKuninori Morimoto dev_err(component->dev, "Failed to set OPCLK: %d\n", ret); 184b1387078SMark Brown 185b1387078SMark Brown if (card->num_rtd == DAI_CODEC_CP) 186b1387078SMark Brown return 0; 187b1387078SMark Brown 188f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_ASYNCCLK, 189b1387078SMark Brown ARIZONA_CLK_SRC_FLL2, 190b1387078SMark Brown bells->asyncclk_rate, 191b1387078SMark Brown SND_SOC_CLOCK_IN); 192b1387078SMark Brown if (ret != 0) { 193f4a2be1cSKuninori Morimoto dev_err(component->dev, "Failed to set ASYNCCLK: %d\n", ret); 194b545dd92SMark Brown return ret; 195b545dd92SMark Brown } 196b545dd92SMark Brown 1974468189fSKuninori Morimoto rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_CODEC_CP]); 1985015920aSMengdong Lin aif2_dai = rtd->cpu_dai; 199b1387078SMark Brown 200b545dd92SMark Brown ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0); 201b545dd92SMark Brown if (ret != 0) { 202b545dd92SMark Brown dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret); 203b545dd92SMark Brown return ret; 204b545dd92SMark Brown } 205b545dd92SMark Brown 206b1387078SMark Brown if (card->num_rtd == DAI_CODEC_SUB) 207b1387078SMark Brown return 0; 208b1387078SMark Brown 2094468189fSKuninori Morimoto rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_CODEC_SUB]); 2105015920aSMengdong Lin aif3_dai = rtd->cpu_dai; 2115015920aSMengdong Lin wm9081_dai = rtd->codec_dai; 212b1387078SMark Brown 213b545dd92SMark Brown ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0); 214b545dd92SMark Brown if (ret != 0) { 215b545dd92SMark Brown dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); 216b545dd92SMark Brown return ret; 217b545dd92SMark Brown } 218b545dd92SMark Brown 219f4a2be1cSKuninori Morimoto ret = snd_soc_component_set_sysclk(wm9081_dai->component, WM9081_SYSCLK_MCLK, 220344c5edeSMark Brown 0, SYS_MCLK_RATE, 0); 221b545dd92SMark Brown if (ret != 0) { 222b545dd92SMark Brown dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret); 223b545dd92SMark Brown return ret; 224b545dd92SMark Brown } 225b545dd92SMark Brown 226b545dd92SMark Brown return 0; 227b545dd92SMark Brown } 228b545dd92SMark Brown 229b545dd92SMark Brown static const struct snd_soc_pcm_stream baseband_params = { 230b545dd92SMark Brown .formats = SNDRV_PCM_FMTBIT_S32_LE, 231b545dd92SMark Brown .rate_min = 8000, 232b545dd92SMark Brown .rate_max = 8000, 233b545dd92SMark Brown .channels_min = 2, 234b545dd92SMark Brown .channels_max = 2, 235b545dd92SMark Brown }; 236b545dd92SMark Brown 237b545dd92SMark Brown static const struct snd_soc_pcm_stream sub_params = { 238b545dd92SMark Brown .formats = SNDRV_PCM_FMTBIT_S32_LE, 239344c5edeSMark Brown .rate_min = SYS_AUDIO_RATE, 240344c5edeSMark Brown .rate_max = SYS_AUDIO_RATE, 241b545dd92SMark Brown .channels_min = 2, 242b545dd92SMark Brown .channels_max = 2, 243b545dd92SMark Brown }; 244b545dd92SMark Brown 2455af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm2200_cpu_dsp, 2465af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), 2475af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")), 2485af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); 2495af5e760SKuninori Morimoto 2505af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm2200_dsp_codec, 2515af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")), 2525af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm2200.1-003a", "wm2200"))); 2535af5e760SKuninori Morimoto 2548d47e8a5SMark Brown static struct snd_soc_dai_link bells_dai_wm2200[] = { 2558d47e8a5SMark Brown { 2568d47e8a5SMark Brown .name = "CPU-DSP", 2578d47e8a5SMark Brown .stream_name = "CPU-DSP", 2588d47e8a5SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 2598d47e8a5SMark Brown | SND_SOC_DAIFMT_CBM_CFM, 2605af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm2200_cpu_dsp), 2618d47e8a5SMark Brown }, 2628d47e8a5SMark Brown { 2638d47e8a5SMark Brown .name = "DSP-CODEC", 2648d47e8a5SMark Brown .stream_name = "DSP-CODEC", 2658d47e8a5SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 2668d47e8a5SMark Brown | SND_SOC_DAIFMT_CBM_CFM, 2678d47e8a5SMark Brown .params = &sub_params, 2688d47e8a5SMark Brown .ignore_suspend = 1, 2695af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm2200_dsp_codec), 2708d47e8a5SMark Brown }, 2718d47e8a5SMark Brown }; 2728d47e8a5SMark Brown 2735af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5102_cpu_dsp, 2745af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), 2755af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")), 2765af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); 2775af5e760SKuninori Morimoto 2785af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5102_dsp_codec, 2795af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")), 2805af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm5102-codec", "wm5102-aif1"))); 2815af5e760SKuninori Morimoto 2825af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5102_baseband, 2835af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif2")), 2845af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1"))); 2855af5e760SKuninori Morimoto 2865af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5102_sub, 2875af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif3")), 2885af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi"))); 2895af5e760SKuninori Morimoto 290b545dd92SMark Brown static struct snd_soc_dai_link bells_dai_wm5102[] = { 291b545dd92SMark Brown { 292344c5edeSMark Brown .name = "CPU-DSP", 293344c5edeSMark Brown .stream_name = "CPU-DSP", 294344c5edeSMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 295344c5edeSMark Brown | SND_SOC_DAIFMT_CBM_CFM, 2965af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5102_cpu_dsp), 297344c5edeSMark Brown }, 298344c5edeSMark Brown { 299344c5edeSMark Brown .name = "DSP-CODEC", 300344c5edeSMark Brown .stream_name = "DSP-CODEC", 301b545dd92SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 302b545dd92SMark Brown | SND_SOC_DAIFMT_CBM_CFM, 303344c5edeSMark Brown .params = &sub_params, 304344c5edeSMark Brown .ignore_suspend = 1, 3055af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5102_dsp_codec), 306b545dd92SMark Brown }, 307b545dd92SMark Brown { 308b545dd92SMark Brown .name = "Baseband", 309b545dd92SMark Brown .stream_name = "Baseband", 310b545dd92SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 311b545dd92SMark Brown | SND_SOC_DAIFMT_CBM_CFM, 312b545dd92SMark Brown .ignore_suspend = 1, 313b545dd92SMark Brown .params = &baseband_params, 3145af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5102_baseband), 315b545dd92SMark Brown }, 316b545dd92SMark Brown { 317b545dd92SMark Brown .name = "Sub", 318b545dd92SMark Brown .stream_name = "Sub", 319b545dd92SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 320b545dd92SMark Brown | SND_SOC_DAIFMT_CBS_CFS, 321b545dd92SMark Brown .ignore_suspend = 1, 322b545dd92SMark Brown .params = &sub_params, 3235af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5102_sub), 324b545dd92SMark Brown }, 325b545dd92SMark Brown }; 326b545dd92SMark Brown 3275af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5110_cpu_dsp, 3285af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.0")), 3295af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("spi0.0", "wm0010-sdi1")), 3305af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0"))); 3315af5e760SKuninori Morimoto 3325af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5110_dsp_codec, 3335af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm0010-sdi2")), 3345af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm5110-codec", "wm5110-aif1"))); 3355af5e760SKuninori Morimoto 3365af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5110_baseband, 3375af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm5110-aif2")), 3385af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm1250-ev1.1-0027", "wm1250-ev1"))); 3395af5e760SKuninori Morimoto 3405af5e760SKuninori Morimoto 3415af5e760SKuninori Morimoto SND_SOC_DAILINK_DEFS(wm5110_sub, 3425af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("wm5110-aif3")), 3435af5e760SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("wm9081.1-006c", "wm9081-hifi"))); 3445af5e760SKuninori Morimoto 345b545dd92SMark Brown static struct snd_soc_dai_link bells_dai_wm5110[] = { 346b545dd92SMark Brown { 347344c5edeSMark Brown .name = "CPU-DSP", 348344c5edeSMark Brown .stream_name = "CPU-DSP", 349344c5edeSMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 350344c5edeSMark Brown | SND_SOC_DAIFMT_CBM_CFM, 3515af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5110_cpu_dsp), 352344c5edeSMark Brown }, 353344c5edeSMark Brown { 354344c5edeSMark Brown .name = "DSP-CODEC", 355344c5edeSMark Brown .stream_name = "DSP-CODEC", 356b545dd92SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 357b545dd92SMark Brown | SND_SOC_DAIFMT_CBM_CFM, 358344c5edeSMark Brown .params = &sub_params, 359344c5edeSMark Brown .ignore_suspend = 1, 3605af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5110_dsp_codec), 361b545dd92SMark Brown }, 362b545dd92SMark Brown { 363b545dd92SMark Brown .name = "Baseband", 364b545dd92SMark Brown .stream_name = "Baseband", 365b545dd92SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 366b545dd92SMark Brown | SND_SOC_DAIFMT_CBM_CFM, 367b545dd92SMark Brown .ignore_suspend = 1, 368b545dd92SMark Brown .params = &baseband_params, 3695af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5110_baseband), 370b545dd92SMark Brown }, 371b545dd92SMark Brown { 372b545dd92SMark Brown .name = "Sub", 373b545dd92SMark Brown .stream_name = "Sub", 374b545dd92SMark Brown .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 375b545dd92SMark Brown | SND_SOC_DAIFMT_CBS_CFS, 376b545dd92SMark Brown .ignore_suspend = 1, 377b545dd92SMark Brown .params = &sub_params, 3785af5e760SKuninori Morimoto SND_SOC_DAILINK_REG(wm5110_sub), 379b545dd92SMark Brown }, 380b545dd92SMark Brown }; 381b545dd92SMark Brown 382b545dd92SMark Brown static struct snd_soc_codec_conf bells_codec_conf[] = { 383b545dd92SMark Brown { 384*3874b215SKuninori Morimoto .dlc = COMP_CODEC_CONF("wm9081.1-006c"), 385b545dd92SMark Brown .name_prefix = "Sub", 386b545dd92SMark Brown }, 387b545dd92SMark Brown }; 388b545dd92SMark Brown 389939d3c6aSCharles Keepax static struct snd_soc_dapm_widget bells_widgets[] = { 390939d3c6aSCharles Keepax SND_SOC_DAPM_MIC("DMIC", NULL), 391939d3c6aSCharles Keepax }; 392939d3c6aSCharles Keepax 393b545dd92SMark Brown static struct snd_soc_dapm_route bells_routes[] = { 394b545dd92SMark Brown { "Sub CLK_SYS", NULL, "OPCLK" }, 395b3a6006eSCharles Keepax { "CLKIN", NULL, "OPCLK" }, 396939d3c6aSCharles Keepax 397939d3c6aSCharles Keepax { "DMIC", NULL, "MICBIAS2" }, 398939d3c6aSCharles Keepax { "IN2L", NULL, "DMIC" }, 399939d3c6aSCharles Keepax { "IN2R", NULL, "DMIC" }, 400b545dd92SMark Brown }; 401b545dd92SMark Brown 402b545dd92SMark Brown static struct snd_soc_card bells_cards[] = { 403b545dd92SMark Brown { 4048d47e8a5SMark Brown .name = "Bells WM2200", 4058d47e8a5SMark Brown .owner = THIS_MODULE, 4068d47e8a5SMark Brown .dai_link = bells_dai_wm2200, 4078d47e8a5SMark Brown .num_links = ARRAY_SIZE(bells_dai_wm2200), 4088d47e8a5SMark Brown .codec_conf = bells_codec_conf, 4098d47e8a5SMark Brown .num_configs = ARRAY_SIZE(bells_codec_conf), 4108d47e8a5SMark Brown 4118d47e8a5SMark Brown .late_probe = bells_late_probe, 4128d47e8a5SMark Brown 413939d3c6aSCharles Keepax .dapm_widgets = bells_widgets, 414939d3c6aSCharles Keepax .num_dapm_widgets = ARRAY_SIZE(bells_widgets), 4158d47e8a5SMark Brown .dapm_routes = bells_routes, 4168d47e8a5SMark Brown .num_dapm_routes = ARRAY_SIZE(bells_routes), 4178d47e8a5SMark Brown 4188d47e8a5SMark Brown .set_bias_level = bells_set_bias_level, 4198d47e8a5SMark Brown .set_bias_level_post = bells_set_bias_level_post, 4208d47e8a5SMark Brown 4218d47e8a5SMark Brown .drvdata = &wm2200_drvdata, 4228d47e8a5SMark Brown }, 4238d47e8a5SMark Brown { 424b545dd92SMark Brown .name = "Bells WM5102", 425b545dd92SMark Brown .owner = THIS_MODULE, 426b545dd92SMark Brown .dai_link = bells_dai_wm5102, 427b545dd92SMark Brown .num_links = ARRAY_SIZE(bells_dai_wm5102), 428b545dd92SMark Brown .codec_conf = bells_codec_conf, 429b545dd92SMark Brown .num_configs = ARRAY_SIZE(bells_codec_conf), 430b545dd92SMark Brown 431b545dd92SMark Brown .late_probe = bells_late_probe, 432b545dd92SMark Brown 433939d3c6aSCharles Keepax .dapm_widgets = bells_widgets, 434939d3c6aSCharles Keepax .num_dapm_widgets = ARRAY_SIZE(bells_widgets), 435b545dd92SMark Brown .dapm_routes = bells_routes, 436b545dd92SMark Brown .num_dapm_routes = ARRAY_SIZE(bells_routes), 437b545dd92SMark Brown 438b545dd92SMark Brown .set_bias_level = bells_set_bias_level, 439b545dd92SMark Brown .set_bias_level_post = bells_set_bias_level_post, 440b1387078SMark Brown 441b1387078SMark Brown .drvdata = &wm5102_drvdata, 442b545dd92SMark Brown }, 443b545dd92SMark Brown { 444b545dd92SMark Brown .name = "Bells WM5110", 445b545dd92SMark Brown .owner = THIS_MODULE, 446b545dd92SMark Brown .dai_link = bells_dai_wm5110, 447b545dd92SMark Brown .num_links = ARRAY_SIZE(bells_dai_wm5110), 448b545dd92SMark Brown .codec_conf = bells_codec_conf, 449b545dd92SMark Brown .num_configs = ARRAY_SIZE(bells_codec_conf), 450b545dd92SMark Brown 451b545dd92SMark Brown .late_probe = bells_late_probe, 452b545dd92SMark Brown 453939d3c6aSCharles Keepax .dapm_widgets = bells_widgets, 454939d3c6aSCharles Keepax .num_dapm_widgets = ARRAY_SIZE(bells_widgets), 455b545dd92SMark Brown .dapm_routes = bells_routes, 456b545dd92SMark Brown .num_dapm_routes = ARRAY_SIZE(bells_routes), 457b545dd92SMark Brown 458b545dd92SMark Brown .set_bias_level = bells_set_bias_level, 459b545dd92SMark Brown .set_bias_level_post = bells_set_bias_level_post, 460b1387078SMark Brown 461b1387078SMark Brown .drvdata = &wm5110_drvdata, 462b545dd92SMark Brown }, 463b545dd92SMark Brown }; 464b545dd92SMark Brown 465fdca21adSBill Pemberton static int bells_probe(struct platform_device *pdev) 466b545dd92SMark Brown { 467b545dd92SMark Brown int ret; 468b545dd92SMark Brown 469b545dd92SMark Brown bells_cards[pdev->id].dev = &pdev->dev; 470b545dd92SMark Brown 471c583883eSTushar Behera ret = devm_snd_soc_register_card(&pdev->dev, &bells_cards[pdev->id]); 472c583883eSTushar Behera if (ret) 473b545dd92SMark Brown dev_err(&pdev->dev, 474b545dd92SMark Brown "snd_soc_register_card(%s) failed: %d\n", 475b545dd92SMark Brown bells_cards[pdev->id].name, ret); 476c583883eSTushar Behera 477b545dd92SMark Brown return ret; 478b545dd92SMark Brown } 479b545dd92SMark Brown 480b545dd92SMark Brown static struct platform_driver bells_driver = { 481b545dd92SMark Brown .driver = { 482b545dd92SMark Brown .name = "bells", 483b545dd92SMark Brown .pm = &snd_soc_pm_ops, 484b545dd92SMark Brown }, 485b545dd92SMark Brown .probe = bells_probe, 486b545dd92SMark Brown }; 487b545dd92SMark Brown 488b545dd92SMark Brown module_platform_driver(bells_driver); 489b545dd92SMark Brown 490b545dd92SMark Brown MODULE_DESCRIPTION("Bells audio support"); 491b545dd92SMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 492b545dd92SMark Brown MODULE_LICENSE("GPL"); 493b545dd92SMark Brown MODULE_ALIAS("platform:bells"); 494