Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge remote-tracking branches 'asoc/topic/wm8524', 'asoc/topic/wm8804' and 'asoc/topic/zte' into asoc-next

+289 -6
+16
Documentation/devicetree/bindings/sound/wm8524.txt
··· 1 + WM8524 audio CODEC 2 + 3 + This device does not use I2C or SPI but a simple Hardware Control Interface. 4 + 5 + Required properties: 6 + 7 + - compatible : "wlf,wm8524" 8 + 9 + - wlf,mute-gpios: a GPIO spec for the MUTE pin. 10 + 11 + Example: 12 + 13 + codec: wm8524@0 { 14 + compatible = "wlf,wm8524"; 15 + wlf,mute-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; 16 + };
+5
sound/soc/codecs/Kconfig
··· 175 175 select SND_SOC_WM8400 if MFD_WM8400 176 176 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI 177 177 select SND_SOC_WM8523 if I2C 178 + select SND_SOC_WM8524 if GPIOLIB 178 179 select SND_SOC_WM8580 if I2C 179 180 select SND_SOC_WM8711 if SND_SOC_I2C_AND_SPI 180 181 select SND_SOC_WM8727 ··· 980 979 config SND_SOC_WM8523 981 980 tristate "Wolfson Microelectronics WM8523 DAC" 982 981 depends on I2C 982 + 983 + config SND_SOC_WM8524 984 + tristate "Wolfson Microelectronics WM8524 DAC" 985 + depends on GPIOLIB 983 986 984 987 config SND_SOC_WM8580 985 988 tristate "Wolfson Microelectronics WM8580 and WM8581 CODECs"
+2
sound/soc/codecs/Makefile
··· 184 184 snd-soc-wm8400-objs := wm8400.o 185 185 snd-soc-wm8510-objs := wm8510.o 186 186 snd-soc-wm8523-objs := wm8523.o 187 + snd-soc-wm8524-objs := wm8524.o 187 188 snd-soc-wm8580-objs := wm8580.o 188 189 snd-soc-wm8711-objs := wm8711.o 189 190 snd-soc-wm8727-objs := wm8727.o ··· 421 420 obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o 422 421 obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o 423 422 obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o 423 + obj-$(CONFIG_SND_SOC_WM8524) += snd-soc-wm8524.o 424 424 obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o 425 425 obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o 426 426 obj-$(CONFIG_SND_SOC_WM8727) += snd-soc-wm8727.o
+261
sound/soc/codecs/wm8524.c
··· 1 + /* 2 + * wm8524.c -- WM8524 ALSA SoC Audio driver 3 + * 4 + * Copyright 2009 Wolfson Microelectronics plc 5 + * Copyright 2017 NXP 6 + * 7 + * Based on WM8523 ALSA SoC Audio driver written by Mark Brown 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License version 2 as 11 + * published by the Free Software Foundation. 12 + */ 13 + 14 + #include <linux/module.h> 15 + #include <linux/moduleparam.h> 16 + #include <linux/init.h> 17 + #include <linux/delay.h> 18 + #include <linux/slab.h> 19 + #include <linux/gpio/consumer.h> 20 + #include <linux/of_device.h> 21 + #include <sound/core.h> 22 + #include <sound/pcm.h> 23 + #include <sound/pcm_params.h> 24 + #include <sound/soc.h> 25 + #include <sound/initval.h> 26 + 27 + #define WM8524_NUM_RATES 7 28 + 29 + /* codec private data */ 30 + struct wm8524_priv { 31 + struct gpio_desc *mute; 32 + unsigned int sysclk; 33 + unsigned int rate_constraint_list[WM8524_NUM_RATES]; 34 + struct snd_pcm_hw_constraint_list rate_constraint; 35 + }; 36 + 37 + 38 + static const struct snd_soc_dapm_widget wm8524_dapm_widgets[] = { 39 + SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), 40 + SND_SOC_DAPM_OUTPUT("LINEVOUTL"), 41 + SND_SOC_DAPM_OUTPUT("LINEVOUTR"), 42 + }; 43 + 44 + static const struct snd_soc_dapm_route wm8524_dapm_routes[] = { 45 + { "LINEVOUTL", NULL, "DAC" }, 46 + { "LINEVOUTR", NULL, "DAC" }, 47 + }; 48 + 49 + static const struct { 50 + int value; 51 + int ratio; 52 + } lrclk_ratios[WM8524_NUM_RATES] = { 53 + { 1, 128 }, 54 + { 2, 192 }, 55 + { 3, 256 }, 56 + { 4, 384 }, 57 + { 5, 512 }, 58 + { 6, 768 }, 59 + { 7, 1152 }, 60 + }; 61 + 62 + static int wm8524_startup(struct snd_pcm_substream *substream, 63 + struct snd_soc_dai *dai) 64 + { 65 + struct snd_soc_codec *codec = dai->codec; 66 + struct wm8524_priv *wm8524 = snd_soc_codec_get_drvdata(codec); 67 + 68 + /* The set of sample rates that can be supported depends on the 69 + * MCLK supplied to the CODEC - enforce this. 70 + */ 71 + if (!wm8524->sysclk) { 72 + dev_err(codec->dev, 73 + "No MCLK configured, call set_sysclk() on init\n"); 74 + return -EINVAL; 75 + } 76 + 77 + snd_pcm_hw_constraint_list(substream->runtime, 0, 78 + SNDRV_PCM_HW_PARAM_RATE, 79 + &wm8524->rate_constraint); 80 + 81 + gpiod_set_value_cansleep(wm8524->mute, 1); 82 + 83 + return 0; 84 + } 85 + 86 + static void wm8524_shutdown(struct snd_pcm_substream *substream, 87 + struct snd_soc_dai *dai) 88 + { 89 + struct snd_soc_codec *codec = dai->codec; 90 + struct wm8524_priv *wm8524 = snd_soc_codec_get_drvdata(codec); 91 + 92 + gpiod_set_value_cansleep(wm8524->mute, 0); 93 + } 94 + 95 + static int wm8524_set_dai_sysclk(struct snd_soc_dai *codec_dai, 96 + int clk_id, unsigned int freq, int dir) 97 + { 98 + struct snd_soc_codec *codec = codec_dai->codec; 99 + struct wm8524_priv *wm8524 = snd_soc_codec_get_drvdata(codec); 100 + unsigned int val; 101 + int i, j = 0; 102 + 103 + wm8524->sysclk = freq; 104 + 105 + wm8524->rate_constraint.count = 0; 106 + for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { 107 + val = freq / lrclk_ratios[i].ratio; 108 + /* Check that it's a standard rate since core can't 109 + * cope with others and having the odd rates confuses 110 + * constraint matching. 111 + */ 112 + switch (val) { 113 + case 8000: 114 + case 32000: 115 + case 44100: 116 + case 48000: 117 + case 88200: 118 + case 96000: 119 + case 176400: 120 + case 192000: 121 + dev_dbg(codec->dev, "Supported sample rate: %dHz\n", 122 + val); 123 + wm8524->rate_constraint_list[j++] = val; 124 + wm8524->rate_constraint.count++; 125 + break; 126 + default: 127 + dev_dbg(codec->dev, "Skipping sample rate: %dHz\n", 128 + val); 129 + } 130 + } 131 + 132 + /* Need at least one supported rate... */ 133 + if (wm8524->rate_constraint.count == 0) 134 + return -EINVAL; 135 + 136 + return 0; 137 + } 138 + 139 + static int wm8524_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 140 + { 141 + fmt &= (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK | 142 + SND_SOC_DAIFMT_MASTER_MASK); 143 + 144 + if (fmt != (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 145 + SND_SOC_DAIFMT_CBS_CFS)) { 146 + dev_err(codec_dai->dev, "Invalid DAI format\n"); 147 + return -EINVAL; 148 + } 149 + 150 + return 0; 151 + } 152 + 153 + static int wm8524_mute_stream(struct snd_soc_dai *dai, int mute, int stream) 154 + { 155 + struct wm8524_priv *wm8524 = snd_soc_codec_get_drvdata(dai->codec); 156 + 157 + if (wm8524->mute) 158 + gpiod_set_value_cansleep(wm8524->mute, mute); 159 + 160 + return 0; 161 + } 162 + 163 + #define WM8524_RATES SNDRV_PCM_RATE_8000_192000 164 + 165 + #define WM8524_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) 166 + 167 + static const struct snd_soc_dai_ops wm8524_dai_ops = { 168 + .startup = wm8524_startup, 169 + .shutdown = wm8524_shutdown, 170 + .set_sysclk = wm8524_set_dai_sysclk, 171 + .set_fmt = wm8524_set_fmt, 172 + .mute_stream = wm8524_mute_stream, 173 + }; 174 + 175 + static struct snd_soc_dai_driver wm8524_dai = { 176 + .name = "wm8524-hifi", 177 + .playback = { 178 + .stream_name = "Playback", 179 + .channels_min = 2, 180 + .channels_max = 2, 181 + .rates = WM8524_RATES, 182 + .formats = WM8524_FORMATS, 183 + }, 184 + .ops = &wm8524_dai_ops, 185 + }; 186 + 187 + static int wm8524_probe(struct snd_soc_codec *codec) 188 + { 189 + struct wm8524_priv *wm8524 = snd_soc_codec_get_drvdata(codec); 190 + 191 + wm8524->rate_constraint.list = &wm8524->rate_constraint_list[0]; 192 + wm8524->rate_constraint.count = 193 + ARRAY_SIZE(wm8524->rate_constraint_list); 194 + 195 + return 0; 196 + } 197 + 198 + static const struct snd_soc_codec_driver soc_codec_dev_wm8524 = { 199 + .probe = wm8524_probe, 200 + 201 + .component_driver = { 202 + .dapm_widgets = wm8524_dapm_widgets, 203 + .num_dapm_widgets = ARRAY_SIZE(wm8524_dapm_widgets), 204 + .dapm_routes = wm8524_dapm_routes, 205 + .num_dapm_routes = ARRAY_SIZE(wm8524_dapm_routes), 206 + }, 207 + }; 208 + 209 + static const struct of_device_id wm8524_of_match[] = { 210 + { .compatible = "wlf,wm8524" }, 211 + { /* sentinel*/ } 212 + }; 213 + MODULE_DEVICE_TABLE(of, wm8524_of_match); 214 + 215 + static int wm8524_codec_probe(struct platform_device *pdev) 216 + { 217 + struct wm8524_priv *wm8524; 218 + int ret; 219 + 220 + wm8524 = devm_kzalloc(&pdev->dev, sizeof(struct wm8524_priv), 221 + GFP_KERNEL); 222 + if (wm8524 == NULL) 223 + return -ENOMEM; 224 + 225 + platform_set_drvdata(pdev, wm8524); 226 + 227 + wm8524->mute = devm_gpiod_get(&pdev->dev, "wlf,mute", GPIOD_OUT_LOW); 228 + if (IS_ERR(wm8524->mute)) { 229 + ret = PTR_ERR(wm8524->mute); 230 + dev_err(&pdev->dev, "Failed to get mute line: %d\n", ret); 231 + return ret; 232 + } 233 + 234 + ret = snd_soc_register_codec(&pdev->dev, 235 + &soc_codec_dev_wm8524, &wm8524_dai, 1); 236 + if (ret < 0) 237 + dev_err(&pdev->dev, "Failed to register codec: %d\n", ret); 238 + 239 + return ret; 240 + } 241 + 242 + static int wm8524_codec_remove(struct platform_device *pdev) 243 + { 244 + snd_soc_unregister_codec(&pdev->dev); 245 + return 0; 246 + } 247 + 248 + static struct platform_driver wm8524_codec_driver = { 249 + .probe = wm8524_codec_probe, 250 + .remove = wm8524_codec_remove, 251 + .driver = { 252 + .name = "wm8524-codec", 253 + .of_match_table = wm8524_of_match, 254 + }, 255 + }; 256 + module_platform_driver(wm8524_codec_driver); 257 + 258 + MODULE_DESCRIPTION("ASoC WM8524 driver"); 259 + MODULE_AUTHOR("Mihai Serban <mihai.serban@nxp.com>"); 260 + MODULE_ALIAS("platform:wm8524-codec"); 261 + MODULE_LICENSE("GPL");
+1 -2
sound/soc/codecs/wm8804.c
··· 623 623 return ret; 624 624 } 625 625 626 - if (wm8804->reset) 627 - gpiod_set_value_cansleep(wm8804->reset, 1); 626 + gpiod_set_value_cansleep(wm8804->reset, 1); 628 627 629 628 ret = regmap_read(regmap, WM8804_RST_DEVID1, &id1); 630 629 if (ret < 0) {
+1 -1
sound/soc/codecs/zx_aud96p22.c
··· 382 382 return 0; 383 383 } 384 384 385 - const struct of_device_id aud96p22_dt_ids[] = { 385 + static const struct of_device_id aud96p22_dt_ids[] = { 386 386 { .compatible = "zte,zx-aud96p22", }, 387 387 { } 388 388 };
+1 -1
sound/soc/zte/zx-i2s.c
··· 357 357 clk_disable_unprepare(zx_i2s->dai_pclk); 358 358 } 359 359 360 - static struct snd_soc_dai_ops zx_i2s_dai_ops = { 360 + static const struct snd_soc_dai_ops zx_i2s_dai_ops = { 361 361 .trigger = zx_i2s_trigger, 362 362 .hw_params = zx_i2s_hw_params, 363 363 .set_fmt = zx_i2s_set_fmt,
+1 -1
sound/soc/zte/zx-spdif.c
··· 264 264 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE \ 265 265 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) 266 266 267 - static struct snd_soc_dai_ops zx_spdif_dai_ops = { 267 + static const struct snd_soc_dai_ops zx_spdif_dai_ops = { 268 268 .trigger = zx_spdif_trigger, 269 269 .startup = zx_spdif_startup, 270 270 .shutdown = zx_spdif_shutdown,
+1 -1
sound/soc/zte/zx-tdm.c
··· 309 309 clk_disable_unprepare(zx_tdm->dai_wclk); 310 310 } 311 311 312 - static struct snd_soc_dai_ops zx_tdm_dai_ops = { 312 + static const struct snd_soc_dai_ops zx_tdm_dai_ops = { 313 313 .trigger = zx_tdm_trigger, 314 314 .hw_params = zx_tdm_hw_params, 315 315 .set_fmt = zx_tdm_set_fmt,