From 89b13706c4bb6dae0263014051dd59986376faa5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 16 Jul 2017 18:11:07 -0300 Subject: [PATCH 01/10] ASoC: wm8804: Remove unneeded gpiod NULL check The gpiod API checks for NULL descriptors, so there is no need to duplicate the check in the driver. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/wm8804.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index af95d648265b..fc69b87443d8 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -623,8 +623,7 @@ int wm8804_probe(struct device *dev, struct regmap *regmap) return ret; } - if (wm8804->reset) - gpiod_set_value_cansleep(wm8804->reset, 1); + gpiod_set_value_cansleep(wm8804->reset, 1); ret = regmap_read(regmap, WM8804_RST_DEVID1, &id1); if (ret < 0) { From 45d059a33aa48cb19a5ff589f71abcc4de4a8fbf Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 13 Jul 2017 00:22:09 -0500 Subject: [PATCH 02/10] ASoC: zx-i2s: constify snd_soc_dai_ops structure This structure is only stored in the ops field of a snd_soc_dai_driver structure. That field is declared const, so snd_soc_dai_ops structures that have this property can be declared as const also. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/zte/zx-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/zte/zx-i2s.c b/sound/soc/zte/zx-i2s.c index 8bbad1d72bc5..9a0565937d1f 100644 --- a/sound/soc/zte/zx-i2s.c +++ b/sound/soc/zte/zx-i2s.c @@ -357,7 +357,7 @@ static void zx_i2s_shutdown(struct snd_pcm_substream *substream, clk_disable_unprepare(zx_i2s->dai_pclk); } -static struct snd_soc_dai_ops zx_i2s_dai_ops = { +static const struct snd_soc_dai_ops zx_i2s_dai_ops = { .trigger = zx_i2s_trigger, .hw_params = zx_i2s_hw_params, .set_fmt = zx_i2s_set_fmt, From 171dd51655b11331928dd39ff0e51a516e41424d Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 13 Jul 2017 00:30:52 -0500 Subject: [PATCH 03/10] ASoC: zx-tdm: constify snd_soc_dai_ops structure This structure is only stored in the ops field of a snd_soc_dai_driver structure. That field is declared const, so snd_soc_dai_ops structures that have this property can be declared as const also. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/zte/zx-tdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/zte/zx-tdm.c b/sound/soc/zte/zx-tdm.c index bd632cc503b3..dc955272f58b 100644 --- a/sound/soc/zte/zx-tdm.c +++ b/sound/soc/zte/zx-tdm.c @@ -309,7 +309,7 @@ static void zx_tdm_shutdown(struct snd_pcm_substream *substream, clk_disable_unprepare(zx_tdm->dai_wclk); } -static struct snd_soc_dai_ops zx_tdm_dai_ops = { +static const struct snd_soc_dai_ops zx_tdm_dai_ops = { .trigger = zx_tdm_trigger, .hw_params = zx_tdm_hw_params, .set_fmt = zx_tdm_set_fmt, From 4d2c7e09a5c8ea3b20748c2942b6a686dced34ab Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 13 Jul 2017 00:37:55 -0500 Subject: [PATCH 04/10] ASoC: zte: spdif: constify snd_soc_dai_ops structure This structure is only stored in the ops field of a snd_soc_dai_driver structure. That field is declared const, so snd_soc_dai_ops structures that have this property can be declared as const also. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/zte/zx-spdif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/zte/zx-spdif.c b/sound/soc/zte/zx-spdif.c index 9fa6463ce5d7..b143f9f682d2 100644 --- a/sound/soc/zte/zx-spdif.c +++ b/sound/soc/zte/zx-spdif.c @@ -264,7 +264,7 @@ static void zx_spdif_shutdown(struct snd_pcm_substream *substream, (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE \ | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) -static struct snd_soc_dai_ops zx_spdif_dai_ops = { +static const struct snd_soc_dai_ops zx_spdif_dai_ops = { .trigger = zx_spdif_trigger, .startup = zx_spdif_startup, .shutdown = zx_spdif_shutdown, From 007b6a54c305688d1db7255e5c724e3d76ba5aa4 Mon Sep 17 00:00:00 2001 From: Mihai Serban Date: Thu, 27 Jul 2017 17:55:10 +0300 Subject: [PATCH 05/10] ASoC: codecs: add wm8524 codec driver WM8524 is a 24-bit 192KHz stereo digital/analog converter (DAC) with integral charge pump and a simple hardware control interface. Product information can be found at: https://www.cirrus.com/products/wm8524/ Signed-off-by: Mihai Serban Signed-off-by: Shengjiu Wang Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wm8524.txt | 16 ++ sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/wm8524.c | 265 ++++++++++++++++++ 4 files changed, 288 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/wm8524.txt create mode 100644 sound/soc/codecs/wm8524.c diff --git a/Documentation/devicetree/bindings/sound/wm8524.txt b/Documentation/devicetree/bindings/sound/wm8524.txt new file mode 100644 index 000000000000..20c62002cbcd --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8524.txt @@ -0,0 +1,16 @@ +WM8524 audio CODEC + +This device does not use I2C or SPI but a simple Hardware Control Interface. + +Required properties: + + - compatible : "wlf,wm8524" + + - wlf,mute-gpios: a GPIO spec for the MUTE pin. + +Example: + +codec: wm8524@0 { + compatible = "wlf,wm8524"; + wlf,mute-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; +}; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 6c78b0b49b81..c3d8aef98608 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -173,6 +173,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8400 if MFD_WM8400 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8523 if I2C + select SND_SOC_WM8524 if GPIOLIB select SND_SOC_WM8580 if I2C select SND_SOC_WM8711 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8727 @@ -967,6 +968,10 @@ config SND_SOC_WM8523 tristate "Wolfson Microelectronics WM8523 DAC" depends on I2C +config SND_SOC_WM8524 + tristate "Wolfson Microelectronics WM8524 DAC" + depends on GPIOLIB + config SND_SOC_WM8580 tristate "Wolfson Microelectronics WM8580 and WM8581 CODECs" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 1755a54e3dc9..66a8567d76d1 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -182,6 +182,7 @@ snd-soc-wm8350-objs := wm8350.o snd-soc-wm8400-objs := wm8400.o snd-soc-wm8510-objs := wm8510.o snd-soc-wm8523-objs := wm8523.o +snd-soc-wm8524-objs := wm8524.o snd-soc-wm8580-objs := wm8580.o snd-soc-wm8711-objs := wm8711.o snd-soc-wm8727-objs := wm8727.o @@ -414,6 +415,7 @@ obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o +obj-$(CONFIG_SND_SOC_WM8524) += snd-soc-wm8524.o obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o obj-$(CONFIG_SND_SOC_WM8727) += snd-soc-wm8727.o diff --git a/sound/soc/codecs/wm8524.c b/sound/soc/codecs/wm8524.c new file mode 100644 index 000000000000..f42ec664877c --- /dev/null +++ b/sound/soc/codecs/wm8524.c @@ -0,0 +1,265 @@ +/* + * wm8524.c -- WM8524 ALSA SoC Audio driver + * + * Copyright 2009 Wolfson Microelectronics plc + * Copyright 2017 NXP + * + * Based on WM8523 ALSA SoC Audio driver written by Mark Brown + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WM8524_NUM_RATES 7 + +/* codec private data */ +struct wm8524_priv { + struct gpio_desc *mute; + unsigned int sysclk; + unsigned int rate_constraint_list[WM8524_NUM_RATES]; + struct snd_pcm_hw_constraint_list rate_constraint; +}; + + +static const struct snd_soc_dapm_widget wm8524_dapm_widgets[] = { +SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), +SND_SOC_DAPM_OUTPUT("LINEVOUTL"), +SND_SOC_DAPM_OUTPUT("LINEVOUTR"), +}; + +static const struct snd_soc_dapm_route wm8524_dapm_routes[] = { + { "LINEVOUTL", NULL, "DAC" }, + { "LINEVOUTR", NULL, "DAC" }, +}; + +static const struct { + int value; + int ratio; +} lrclk_ratios[WM8524_NUM_RATES] = { + { 1, 128 }, + { 2, 192 }, + { 3, 256 }, + { 4, 384 }, + { 5, 512 }, + { 6, 768 }, + { 7, 1152 }, +}; + +static int wm8524_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct wm8524_priv *wm8524 = snd_soc_codec_get_drvdata(codec); + + /* The set of sample rates that can be supported depends on the + * MCLK supplied to the CODEC - enforce this. + */ + if (!wm8524->sysclk) { + dev_err(codec->dev, + "No MCLK configured, call set_sysclk() on init\n"); + return -EINVAL; + } + + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &wm8524->rate_constraint); + + gpiod_set_value_cansleep(wm8524->mute, 1); + + return 0; +} + +static void wm8524_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct wm8524_priv *wm8524 = snd_soc_codec_get_drvdata(codec); + + gpiod_set_value_cansleep(wm8524->mute, 0); +} + +static int wm8524_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct wm8524_priv *wm8524 = snd_soc_codec_get_drvdata(codec); + unsigned int val; + int i, j = 0; + + wm8524->sysclk = freq; + + wm8524->rate_constraint.count = 0; + for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { + val = freq / lrclk_ratios[i].ratio; + /* Check that it's a standard rate since core can't + * cope with others and having the odd rates confuses + * constraint matching. + */ + switch (val) { + case 8000: + case 32000: + case 44100: + case 48000: + case 88200: + case 96000: + case 176400: + case 192000: + dev_err(codec->dev, "Supported sample rate: %dHz\n", + val); + wm8524->rate_constraint_list[j++] = val; + wm8524->rate_constraint.count++; + break; + default: + dev_dbg(codec->dev, "Skipping sample rate: %dHz\n", + val); + } + } + + /* Need at least one supported rate... */ + if (wm8524->rate_constraint.count == 0) + return -EINVAL; + + return 0; +} + +static int wm8524_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + fmt &= (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK | + SND_SOC_DAIFMT_MASTER_MASK); + + if (fmt != (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS)) { + dev_err(codec_dai->dev, "Invalid DAI format\n"); + return -EINVAL; + } + + return 0; +} + +static int wm8524_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +{ + struct wm8524_priv *wm8524 = snd_soc_codec_get_drvdata(dai->codec); + + if (wm8524->mute) + gpiod_set_value_cansleep(wm8524->mute, mute); + + return 0; +} + +#define WM8524_RATES SNDRV_PCM_RATE_8000_192000 + +#define WM8524_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) + +static const struct snd_soc_dai_ops wm8524_dai_ops = { + .startup = wm8524_startup, + .shutdown = wm8524_shutdown, + .set_sysclk = wm8524_set_dai_sysclk, + .set_fmt = wm8524_set_fmt, + .mute_stream = wm8524_mute_stream, +}; + +static struct snd_soc_dai_driver wm8524_dai = { + .name = "wm8524-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = WM8524_RATES, + .formats = WM8524_FORMATS, + }, + .ops = &wm8524_dai_ops, +}; + +static int wm8524_probe(struct snd_soc_codec *codec) +{ + struct wm8524_priv *wm8524 = snd_soc_codec_get_drvdata(codec); + + wm8524->rate_constraint.list = &wm8524->rate_constraint_list[0]; + wm8524->rate_constraint.count = + ARRAY_SIZE(wm8524->rate_constraint_list); + + return 0; +} + +static const struct snd_soc_codec_driver soc_codec_dev_wm8524 = { + .probe = wm8524_probe, + + .component_driver = { + .dapm_widgets = wm8524_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8524_dapm_widgets), + .dapm_routes = wm8524_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(wm8524_dapm_routes), + }, +}; + +#ifdef CONFIG_OF +static const struct of_device_id wm8524_of_match[] = { + { .compatible = "wlf,wm8524" }, + { /* sentinel*/ } +}; +MODULE_DEVICE_TABLE(of, wm8524_of_match); +#endif + +static int wm8524_codec_probe(struct platform_device *pdev) +{ + struct wm8524_priv *wm8524; + int ret; + + wm8524 = devm_kzalloc(&pdev->dev, sizeof(struct wm8524_priv), + GFP_KERNEL); + if (wm8524 == NULL) + return -ENOMEM; + + platform_set_drvdata(pdev, wm8524); + + wm8524->mute = devm_gpiod_get(&pdev->dev, "wlf,mute", GPIOD_OUT_LOW); + if (IS_ERR(wm8524->mute)) { + ret = PTR_ERR(wm8524->mute); + dev_err(&pdev->dev, "Failed to get mute line: %d\n", ret); + return ret; + } + + ret = snd_soc_register_codec(&pdev->dev, + &soc_codec_dev_wm8524, &wm8524_dai, 1); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register codec: %d\n", ret); + snd_soc_unregister_platform(&pdev->dev); + } + + return ret; +} + +static int wm8524_codec_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static struct platform_driver wm8524_codec_driver = { + .probe = wm8524_codec_probe, + .remove = wm8524_codec_remove, + .driver = { + .name = "wm8524-codec", + .of_match_table = wm8524_of_match, + }, +}; +module_platform_driver(wm8524_codec_driver); + +MODULE_DESCRIPTION("ASoC WM8524 driver"); +MODULE_AUTHOR("Mihai Serban "); +MODULE_ALIAS("platform:wm8524-codec"); +MODULE_LICENSE("GPL"); From bf11ecb7eebd28d70bf5aa3170c6fe7156c33c5b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 31 Jul 2017 18:05:46 +0200 Subject: [PATCH 06/10] ASoC: codecs: fix wm8524 build error When CONFIG_OF is disabled, we run into a build error: sound/soc/codecs/wm8524.c:257:21: error: 'wm8524_of_match' undeclared here (not in a function); did you mean 'wm8524_dai'? This removes the unnecessary #ifdef around the match table. Fixes: 007b6a54c305 ("ASoC: codecs: add wm8524 codec driver") Signed-off-by: Arnd Bergmann Acked-by: Mihai Serban Signed-off-by: Mark Brown --- sound/soc/codecs/wm8524.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/wm8524.c b/sound/soc/codecs/wm8524.c index f42ec664877c..e22b76d64e32 100644 --- a/sound/soc/codecs/wm8524.c +++ b/sound/soc/codecs/wm8524.c @@ -206,13 +206,11 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8524 = { }, }; -#ifdef CONFIG_OF static const struct of_device_id wm8524_of_match[] = { { .compatible = "wlf,wm8524" }, { /* sentinel*/ } }; MODULE_DEVICE_TABLE(of, wm8524_of_match); -#endif static int wm8524_codec_probe(struct platform_device *pdev) { From 80bfd0431f7dc133f4edbc0b864f800c4ed7a3f4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 2 Aug 2017 16:13:46 +0800 Subject: [PATCH 07/10] ASoC: wm8524: Don't use dev_err to show supported sample rate Switch to use dev_dbg instead. Signed-off-by: Axel Lin Acked-by: Mihai Serban Signed-off-by: Mark Brown --- sound/soc/codecs/wm8524.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8524.c b/sound/soc/codecs/wm8524.c index e22b76d64e32..b66147e0631b 100644 --- a/sound/soc/codecs/wm8524.c +++ b/sound/soc/codecs/wm8524.c @@ -118,7 +118,7 @@ static int wm8524_set_dai_sysclk(struct snd_soc_dai *codec_dai, case 96000: case 176400: case 192000: - dev_err(codec->dev, "Supported sample rate: %dHz\n", + dev_dbg(codec->dev, "Supported sample rate: %dHz\n", val); wm8524->rate_constraint_list[j++] = val; wm8524->rate_constraint.count++; From def4b1243e56774fdc47de9292111a344f14e88c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 13 Aug 2017 16:28:08 +0100 Subject: [PATCH 08/10] ASoC: zx_aud96p22: make array aud96p22_dt_ids static The array aud96p22_dt_ids is local to the source and does not need to be in global scope, so make it static. Cleans up sparse warning: symbol 'aud96p22_dt_ids' was not declared. Should it be static? Signed-off-by: Colin Ian King Signed-off-by: Mark Brown --- sound/soc/codecs/zx_aud96p22.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/zx_aud96p22.c b/sound/soc/codecs/zx_aud96p22.c index 032fb7cf6cbd..bc23ce1a30a1 100644 --- a/sound/soc/codecs/zx_aud96p22.c +++ b/sound/soc/codecs/zx_aud96p22.c @@ -382,7 +382,7 @@ static int aud96p22_i2c_remove(struct i2c_client *i2c) return 0; } -const struct of_device_id aud96p22_dt_ids[] = { +static const struct of_device_id aud96p22_dt_ids[] = { { .compatible = "zte,zx-aud96p22", }, { } }; From 66f41da341cd97ad362c4a40e1c9a0a28d746f81 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 15 Aug 2017 17:10:11 +0200 Subject: [PATCH 09/10] ASoC: codecs: zx_aud96p22: constify snd_soc_dai_ops structures These snd_soc_dai_ops structures are only stored in the ops field of a snd_soc_dai_driver structure, which is const. Thus, the snd_soc_dai_ops structures can be const too. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Mark Brown --- sound/soc/codecs/zx_aud96p22.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/zx_aud96p22.c b/sound/soc/codecs/zx_aud96p22.c index bc23ce1a30a1..0e5b43b948b4 100644 --- a/sound/soc/codecs/zx_aud96p22.c +++ b/sound/soc/codecs/zx_aud96p22.c @@ -312,7 +312,7 @@ static int aud96p22_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return 0; } -static struct snd_soc_dai_ops aud96p22_dai_ops = { +static const struct snd_soc_dai_ops aud96p22_dai_ops = { .set_fmt = aud96p22_set_fmt, }; From 6cbcad079ecdb8ecd214d33688fd7f19167fe57a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 23 Aug 2017 05:11:44 +0000 Subject: [PATCH 10/10] ASoC: wm8524: remove unnecessary snd_soc_unregister_platform() wm8524 doesn't register platform, unregister platform is not needed Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/wm8524.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/codecs/wm8524.c b/sound/soc/codecs/wm8524.c index b66147e0631b..856a6950a451 100644 --- a/sound/soc/codecs/wm8524.c +++ b/sound/soc/codecs/wm8524.c @@ -233,10 +233,8 @@ static int wm8524_codec_probe(struct platform_device *pdev) ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8524, &wm8524_dai, 1); - if (ret < 0) { + if (ret < 0) dev_err(&pdev->dev, "Failed to register codec: %d\n", ret); - snd_soc_unregister_platform(&pdev->dev); - } return ret; }