From b545dd924b4ffaf1e4fdd73fe7e9b6eb01e45aea Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 7 Aug 2012 20:03:02 +0100 Subject: ASoC: bells: Add machine driver for Wolfson Bells boards The Wolfson Bells board takes submodules for various audio functions but since the system integrations are virtually identical for most of them we can support the overwhemling majority from the same machine driver. Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 8 ++ sound/soc/samsung/Makefile | 2 + sound/soc/samsung/bells.c | 346 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 356 insertions(+) create mode 100644 sound/soc/samsung/bells.c (limited to 'sound/soc/samsung') diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index fe3995ce9b3..fb560008361 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -199,6 +199,14 @@ config SND_SOC_TOBERMORY select SND_SAMSUNG_I2S select SND_SOC_WM8962 +config SND_SOC_BELLS + tristate "Audio support for Wolfson Bells" + depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 + select SND_SAMSUNG_I2S + select SND_SOC_WM5102 + select SND_SOC_WM5110 + select SND_SOC_WM9081 + config SND_SOC_LOWLAND tristate "Audio support for Wolfson Lowland" depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 9d03beb40c8..709f6059ad6 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -42,6 +42,7 @@ snd-soc-speyside-objs := speyside.o snd-soc-tobermory-objs := tobermory.o snd-soc-lowland-objs := lowland.o snd-soc-littlemill-objs := littlemill.o +snd-soc-bells-objs := bells.o obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o @@ -65,3 +66,4 @@ obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o +obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c new file mode 100644 index 00000000000..5dc10dfc0d4 --- /dev/null +++ b/sound/soc/samsung/bells.c @@ -0,0 +1,346 @@ +/* + * Bells audio support + * + * Copyright 2012 Wolfson Microelectronics + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include + +#include "../codecs/wm5102.h" +#include "../codecs/wm9081.h" + +/* + * 44.1kHz based clocks for the SYSCLK domain, use a very high clock + * to allow all the DSP functionality to be enabled if desired. + */ +#define SYSCLK_RATE (44100 * 1024) + +/* 48kHz based clocks for the ASYNC domain */ +#define ASYNCCLK_RATE (48000 * 512) + +/* BCLK2 is fixed at this currently */ +#define BCLK2_RATE (64 * 8000) + +/* + * Expect a 24.576MHz crystal if one is fitted (the driver will function + * if this is not fitted). + */ +#define MCLK_RATE 24576000 + +#define WM9081_AUDIO_RATE 44100 +#define WM9081_MCLK_RATE (WM9081_AUDIO_RATE * 256) + +static int bells_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_codec *codec = codec_dai->codec; + int ret; + + if (dapm->dev != codec_dai->dev) + return 0; + + switch (level) { + case SND_SOC_BIAS_PREPARE: + if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { + ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, + ARIZONA_FLL_SRC_MCLK1, + MCLK_RATE, + SYSCLK_RATE); + if (ret < 0) + pr_err("Failed to start FLL: %d\n", ret); + + ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, + ARIZONA_FLL_SRC_AIF2BCLK, + BCLK2_RATE, + ASYNCCLK_RATE); + if (ret < 0) + pr_err("Failed to start FLL: %d\n", ret); + } + break; + + default: + break; + } + + return 0; +} + +static int bells_set_bias_level_post(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_codec *codec = codec_dai->codec; + int ret; + + if (dapm->dev != codec_dai->dev) + return 0; + + switch (level) { + case SND_SOC_BIAS_STANDBY: + ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, 0, 0, 0); + if (ret < 0) { + pr_err("Failed to stop FLL: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 0, 0, 0); + if (ret < 0) { + pr_err("Failed to stop FLL: %d\n", ret); + return ret; + } + break; + + default: + break; + } + + dapm->bias_level = level; + + return 0; +} + +static int bells_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_codec *codec = card->rtd[0].codec; + struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai; + struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai; + struct snd_soc_dai *aif3_dai = card->rtd[2].cpu_dai; + struct snd_soc_dai *wm9081_dai = card->rtd[2].codec_dai; + int ret; + + ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0); + if (ret != 0) { + dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0); + if (ret != 0) { + dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0); + if (ret != 0) { + dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK, + ARIZONA_CLK_SRC_FLL1, SYSCLK_RATE, + SND_SOC_CLOCK_IN); + if (ret != 0) { + dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0, + WM9081_MCLK_RATE, SND_SOC_CLOCK_OUT); + if (ret != 0) { + dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK, + ARIZONA_CLK_SRC_FLL2, ASYNCCLK_RATE, + SND_SOC_CLOCK_IN); + if (ret != 0) { + dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(wm9081_dai->codec, WM9081_SYSCLK_MCLK, + 0, WM9081_MCLK_RATE, 0); + if (ret != 0) { + dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct snd_soc_pcm_stream baseband_params = { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rate_min = 8000, + .rate_max = 8000, + .channels_min = 2, + .channels_max = 2, +}; + +static const struct snd_soc_pcm_stream sub_params = { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rate_min = WM9081_AUDIO_RATE, + .rate_max = WM9081_AUDIO_RATE, + .channels_min = 2, + .channels_max = 2, +}; + +static struct snd_soc_dai_link bells_dai_wm5102[] = { + { + .name = "CPU", + .stream_name = "CPU", + .cpu_dai_name = "samsung-i2s.0", + .codec_dai_name = "wm5102-aif1", + .platform_name = "samsung-audio", + .codec_name = "wm5102-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + }, + { + .name = "Baseband", + .stream_name = "Baseband", + .cpu_dai_name = "wm5102-aif2", + .codec_dai_name = "wm1250-ev1", + .codec_name = "wm1250-ev1.1-0027", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .ignore_suspend = 1, + .params = &baseband_params, + }, + { + .name = "Sub", + .stream_name = "Sub", + .cpu_dai_name = "wm5102-aif3", + .codec_dai_name = "wm9081-hifi", + .codec_name = "wm9081.1-006c", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBS_CFS, + .ignore_suspend = 1, + .params = &sub_params, + }, +}; + +static struct snd_soc_dai_link bells_dai_wm5110[] = { + { + .name = "CPU", + .stream_name = "CPU", + .cpu_dai_name = "samsung-i2s.0", + .codec_dai_name = "wm5110-aif1", + .platform_name = "samsung-audio", + .codec_name = "wm5110-codec", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + }, + { + .name = "Baseband", + .stream_name = "Baseband", + .cpu_dai_name = "wm5110-aif2", + .codec_dai_name = "wm1250-ev1", + .codec_name = "wm1250-ev1.1-0027", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .ignore_suspend = 1, + .params = &baseband_params, + }, + { + .name = "Sub", + .stream_name = "Sub", + .cpu_dai_name = "wm5102-aif3", + .codec_dai_name = "wm9081-hifi", + .codec_name = "wm9081.1-006c", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBS_CFS, + .ignore_suspend = 1, + .params = &sub_params, + }, +}; + +static struct snd_soc_codec_conf bells_codec_conf[] = { + { + .dev_name = "wm9081.1-006c", + .name_prefix = "Sub", + }, +}; + +static struct snd_soc_dapm_route bells_routes[] = { + { "Sub CLK_SYS", NULL, "OPCLK" }, +}; + +static struct snd_soc_card bells_cards[] = { + { + .name = "Bells WM5102", + .owner = THIS_MODULE, + .dai_link = bells_dai_wm5102, + .num_links = ARRAY_SIZE(bells_dai_wm5102), + .codec_conf = bells_codec_conf, + .num_configs = ARRAY_SIZE(bells_codec_conf), + + .late_probe = bells_late_probe, + + .dapm_routes = bells_routes, + .num_dapm_routes = ARRAY_SIZE(bells_routes), + + .set_bias_level = bells_set_bias_level, + .set_bias_level_post = bells_set_bias_level_post, + }, + { + .name = "Bells WM5110", + .owner = THIS_MODULE, + .dai_link = bells_dai_wm5110, + .num_links = ARRAY_SIZE(bells_dai_wm5110), + .codec_conf = bells_codec_conf, + .num_configs = ARRAY_SIZE(bells_codec_conf), + + .late_probe = bells_late_probe, + + .dapm_routes = bells_routes, + .num_dapm_routes = ARRAY_SIZE(bells_routes), + + .set_bias_level = bells_set_bias_level, + .set_bias_level_post = bells_set_bias_level_post, + }, +}; + + +static __devinit int bells_probe(struct platform_device *pdev) +{ + int ret; + + bells_cards[pdev->id].dev = &pdev->dev; + + ret = snd_soc_register_card(&bells_cards[pdev->id]); + if (ret) { + dev_err(&pdev->dev, + "snd_soc_register_card(%s) failed: %d\n", + bells_cards[pdev->id].name, ret); + return ret; + } + + return 0; +} + +static int __devexit bells_remove(struct platform_device *pdev) +{ + snd_soc_unregister_card(&bells_cards[pdev->id]); + + return 0; +} + +static struct platform_driver bells_driver = { + .driver = { + .name = "bells", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + }, + .probe = bells_probe, + .remove = __devexit_p(bells_remove), +}; + +module_platform_driver(bells_driver); + +MODULE_DESCRIPTION("Bells audio support"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bells"); -- cgit v1.2.3-70-g09d2 From f9372c9c06166dc24a17cf25d325d83a9a06a02d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Aug 2012 17:05:48 +0100 Subject: ASoC: samsung: Add hookup of WM0010 on Speyside The Speyside platform by default has a WM0010 fitted. Now that we have a public driver hook it up in the machine integration. Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 1 + sound/soc/samsung/speyside.c | 42 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) (limited to 'sound/soc/samsung') diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index fb560008361..f17dd25e0f4 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -191,6 +191,7 @@ config SND_SOC_SPEYSIDE select SND_SAMSUNG_I2S select SND_SOC_WM8996 select SND_SOC_WM9081 + select SND_SOC_WM0010 select SND_SOC_WM1250_EV1 config SND_SOC_TOBERMORY diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index a4a9fc7e8c7..c7e1c28528a 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -25,7 +25,7 @@ static int speyside_set_bias_level(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) { - struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai; int ret; if (dapm->dev != codec_dai->dev) @@ -57,7 +57,7 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) { - struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai; int ret; if (dapm->dev != codec_dai->dev) @@ -126,6 +126,18 @@ static void speyside_set_polarity(struct snd_soc_codec *codec, snd_soc_dapm_sync(&codec->dapm); } +static int speyside_wm0010_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *dai = rtd->codec_dai; + int ret; + + ret = snd_soc_dai_set_sysclk(dai, 0, MCLK_AUDIO_RATE, 0); + if (ret < 0) + return ret; + + return 0; +} + static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *dai = rtd->codec_dai; @@ -172,17 +184,37 @@ static int speyside_late_probe(struct snd_soc_card *card) return 0; } +static const struct snd_soc_pcm_stream dsp_codec_params = { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, +}; + static struct snd_soc_dai_link speyside_dai[] = { { - .name = "CPU", - .stream_name = "CPU", + .name = "CPU-DSP", + .stream_name = "CPU-DSP", .cpu_dai_name = "samsung-i2s.0", - .codec_dai_name = "wm8996-aif1", + .codec_dai_name = "wm0010-sdi1", .platform_name = "samsung-audio", + .codec_name = "spi0.0", + .init = speyside_wm0010_init, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + }, + { + .name = "DSP-CODEC", + .stream_name = "DSP-CODEC", + .cpu_dai_name = "wm0010-sdi2", + .codec_dai_name = "wm8996-aif1", .codec_name = "wm8996.1-001a", .init = speyside_wm8996_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, + .params = &dsp_codec_params, + .ignore_suspend = 1, }, { .name = "Baseband", -- cgit v1.2.3-70-g09d2 From 3d721a34e66e8133404bda6852897b818df69b4c Mon Sep 17 00:00:00 2001 From: Sangsu Park Date: Tue, 28 Aug 2012 17:55:49 +0900 Subject: ASoC: SAMSUNG: Change Kconfig to support all SAMSUNG ASoC All SAMSUNG ASoC needs SND_SOC_SAMSUNG configuration. This patch change Kconfig to support all SAMSUNG ASoC. Signed-off-by: Sangsu Park Acked-by: Sangbeom Kim Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/samsung') diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index f17dd25e0f4..e7b83179aca 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -1,6 +1,6 @@ config SND_SOC_SAMSUNG tristate "ASoC support for Samsung" - depends on ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5P64X0 || ARCH_EXYNOS4 + depends on PLAT_SAMSUNG select S3C64XX_DMA if ARCH_S3C64XX select S3C2410_DMA if ARCH_S3C24XX help -- cgit v1.2.3-70-g09d2