aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-07-04 13:30:01 -0400
committerMark Brown <broonie@linaro.org>2013-07-04 13:30:01 -0400
commit986a622df307644af14618bee54c901aa74816da (patch)
tree6da87812b9120634381e3e3987e115f90bd562e0 /sound
parent8bb495e3f02401ee6f76d1b1d77f3ac9f079e376 (diff)
parent28e5ca73ef9072ed58dbb81cfff6f908be8e3cd4 (diff)
Merge remote-tracking branch 'asoc/fix/fsl' into asoc-linus
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/Kconfig1
-rw-r--r--sound/soc/Makefile1
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c9
-rw-r--r--sound/soc/blackfin/Kconfig47
-rw-r--r--sound/soc/blackfin/Makefile4
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c1
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.h26
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c8
-rw-r--r--sound/soc/blackfin/bf5xx-ad1836.c19
-rw-r--r--sound/soc/blackfin/bf5xx-ad193x.c40
-rw-r--r--sound/soc/blackfin/bf5xx-ad1980.c1
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c1
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c183
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.h21
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c129
-rw-r--r--sound/soc/blackfin/bf5xx-sport.c10
-rw-r--r--sound/soc/blackfin/bf5xx-sport.h2
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c1
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.c345
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.h18
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.c328
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.h23
-rw-r--r--sound/soc/cirrus/Kconfig2
-rw-r--r--sound/soc/cirrus/ep93xx-ac97.c16
-rw-r--r--sound/soc/cirrus/ep93xx-i2s.c16
-rw-r--r--sound/soc/cirrus/ep93xx-pcm.c138
-rw-r--r--sound/soc/codecs/88pm860x-codec.c9
-rw-r--r--sound/soc/codecs/Kconfig18
-rw-r--r--sound/soc/codecs/Makefile14
-rw-r--r--sound/soc/codecs/ab8500-codec.c85
-rw-r--r--sound/soc/codecs/ab8500-codec.h42
-rw-r--r--sound/soc/codecs/adau1701.c69
-rw-r--r--sound/soc/codecs/arizona.c7
-rw-r--r--sound/soc/codecs/arizona.h3
-rw-r--r--sound/soc/codecs/bt-sco.c (renamed from sound/soc/codecs/dfbmcs320.c)37
-rw-r--r--sound/soc/codecs/hdmi.c (renamed from sound/soc/codecs/omap-hdmi.c)26
-rw-r--r--sound/soc/codecs/jz4740.c2
-rw-r--r--sound/soc/codecs/max98090.c24
-rw-r--r--sound/soc/codecs/rt5640.c2128
-rw-r--r--sound/soc/codecs/rt5640.h2092
-rw-r--r--sound/soc/codecs/sgtl5000.c267
-rw-r--r--sound/soc/codecs/sgtl5000.h2
-rw-r--r--sound/soc/codecs/sn95031.c2
-rw-r--r--sound/soc/codecs/spdif_receiver.c10
-rw-r--r--sound/soc/codecs/spdif_transmitter.c (renamed from sound/soc/codecs/spdif_transciever.c)10
-rw-r--r--sound/soc/codecs/ssm2518.c856
-rw-r--r--sound/soc/codecs/ssm2518.h20
-rw-r--r--sound/soc/codecs/wm0010.c10
-rw-r--r--sound/soc/codecs/wm5102.c205
-rw-r--r--sound/soc/codecs/wm5110.c192
-rw-r--r--sound/soc/codecs/wm8962.c143
-rw-r--r--sound/soc/codecs/wm8994.c188
-rw-r--r--sound/soc/codecs/wm8994.h3
-rw-r--r--sound/soc/codecs/wm_adsp.c461
-rw-r--r--sound/soc/codecs/wm_adsp.h3
-rw-r--r--sound/soc/davinci/Kconfig10
-rw-r--r--sound/soc/davinci/Makefile2
-rw-r--r--sound/soc/davinci/davinci-mcasp.c4
-rw-r--r--sound/soc/davinci/davinci-sffsdr.c181
-rw-r--r--sound/soc/dwc/designware_i2s.c6
-rw-r--r--sound/soc/fsl/Kconfig17
-rw-r--r--sound/soc/fsl/Makefile13
-rw-r--r--sound/soc/fsl/eukrea-tlv320.c2
-rw-r--r--sound/soc/fsl/fsl_ssi.c13
-rw-r--r--sound/soc/fsl/imx-audmux.c8
-rw-r--r--sound/soc/fsl/imx-mc13783.c2
-rw-r--r--sound/soc/fsl/imx-pcm-dma.c2
-rw-r--r--sound/soc/fsl/imx-pcm-fiq.c92
-rw-r--r--sound/soc/fsl/imx-pcm.c145
-rw-r--r--sound/soc/fsl/imx-pcm.h10
-rw-r--r--sound/soc/fsl/imx-sgtl5000.c43
-rw-r--r--sound/soc/fsl/imx-ssi.c44
-rw-r--r--sound/soc/fsl/imx-ssi.h3
-rw-r--r--sound/soc/fsl/imx-wm8962.c323
-rw-r--r--sound/soc/fsl/mx27vis-aic32x4.c2
-rw-r--r--sound/soc/fsl/phycore-ac97.c2
-rw-r--r--sound/soc/fsl/wm1133-ev1.c2
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c17
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c2
-rw-r--r--sound/soc/mid-x86/mfld_machine.c1
-rw-r--r--sound/soc/mxs/mxs-pcm.c18
-rw-r--r--sound/soc/mxs/mxs-pcm.h7
-rw-r--r--sound/soc/mxs/mxs-saif.c37
-rw-r--r--sound/soc/mxs/mxs-saif.h1
-rw-r--r--sound/soc/mxs/mxs-sgtl5000.c10
-rw-r--r--sound/soc/omap/Makefile1
-rw-r--r--sound/soc/omap/omap-hdmi-card.c2
-rw-r--r--sound/soc/omap/omap-mcbsp.c2
-rw-r--r--sound/soc/pxa/Kconfig20
-rw-r--r--sound/soc/pxa/Makefile4
-rw-r--r--sound/soc/pxa/mmp-pcm.c6
-rw-r--r--sound/soc/pxa/mmp-sspa.c2
-rw-r--r--sound/soc/pxa/saarb.c190
-rw-r--r--sound/soc/pxa/tavorevb3.c189
-rw-r--r--sound/soc/pxa/zylonite.c1
-rw-r--r--sound/soc/samsung/Kconfig2
-rw-r--r--sound/soc/samsung/bells.c14
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c2
-rw-r--r--sound/soc/samsung/smdk_wm8580pcm.c1
-rw-r--r--sound/soc/samsung/smdk_wm8994pcm.c1
-rw-r--r--sound/soc/sh/fsi.c10
-rw-r--r--sound/soc/soc-core.c106
-rw-r--r--sound/soc/soc-dapm.c110
-rw-r--r--sound/soc/soc-pcm.c91
-rw-r--r--sound/soc/soc-utils.c13
-rw-r--r--sound/soc/spear/Kconfig9
-rw-r--r--sound/soc/spear/Makefile8
-rw-r--r--sound/soc/spear/spdif_in.c31
-rw-r--r--sound/soc/spear/spdif_out.c43
-rw-r--r--sound/soc/spear/spear_pcm.c152
-rw-r--r--sound/soc/tegra/Kconfig10
-rw-r--r--sound/soc/tegra/Makefile2
-rw-r--r--sound/soc/tegra/tegra30_ahub.c25
-rw-r--r--sound/soc/tegra/tegra30_i2s.c26
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c23
-rw-r--r--sound/soc/tegra/tegra_rt5640.c257
-rw-r--r--sound/soc/ux500/mop500.c2
-rw-r--r--sound/soc/ux500/mop500_ab8500.c62
-rw-r--r--sound/soc/ux500/ux500_msp_dai.c11
-rw-r--r--sound/soc/ux500/ux500_msp_dai.h4
-rw-r--r--sound/soc/ux500/ux500_msp_i2s.c88
-rw-r--r--sound/soc/ux500/ux500_msp_i2s.h74
-rw-r--r--sound/soc/ux500/ux500_pcm.c30
123 files changed, 8113 insertions, 2848 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 9e675c76436c..45eeaa9f7fec 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -51,6 +51,7 @@ source "sound/soc/pxa/Kconfig"
51source "sound/soc/samsung/Kconfig" 51source "sound/soc/samsung/Kconfig"
52source "sound/soc/s6000/Kconfig" 52source "sound/soc/s6000/Kconfig"
53source "sound/soc/sh/Kconfig" 53source "sound/soc/sh/Kconfig"
54source "sound/soc/spear/Kconfig"
54source "sound/soc/tegra/Kconfig" 55source "sound/soc/tegra/Kconfig"
55source "sound/soc/txx9/Kconfig" 56source "sound/soc/txx9/Kconfig"
56source "sound/soc/ux500/Kconfig" 57source "sound/soc/ux500/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 197b6ae54c8d..bc0261476d7a 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_SND_SOC) += pxa/
29obj-$(CONFIG_SND_SOC) += samsung/ 29obj-$(CONFIG_SND_SOC) += samsung/
30obj-$(CONFIG_SND_SOC) += s6000/ 30obj-$(CONFIG_SND_SOC) += s6000/
31obj-$(CONFIG_SND_SOC) += sh/ 31obj-$(CONFIG_SND_SOC) += sh/
32obj-$(CONFIG_SND_SOC) += spear/
32obj-$(CONFIG_SND_SOC) += tegra/ 33obj-$(CONFIG_SND_SOC) += tegra/
33obj-$(CONFIG_SND_SOC) += txx9/ 34obj-$(CONFIG_SND_SOC) += txx9/
34obj-$(CONFIG_SND_SOC) += ux500/ 35obj-$(CONFIG_SND_SOC) += ux500/
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index 2d6fbd0125b9..802717eccbd0 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -38,8 +38,6 @@
38#include <linux/platform_device.h> 38#include <linux/platform_device.h>
39#include <linux/i2c.h> 39#include <linux/i2c.h>
40 40
41#include <linux/pinctrl/consumer.h>
42
43#include <linux/atmel-ssc.h> 41#include <linux/atmel-ssc.h>
44 42
45#include <sound/core.h> 43#include <sound/core.h>
@@ -203,15 +201,8 @@ static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
203 struct device_node *codec_np, *cpu_np; 201 struct device_node *codec_np, *cpu_np;
204 struct clk *pllb; 202 struct clk *pllb;
205 struct snd_soc_card *card = &snd_soc_at91sam9g20ek; 203 struct snd_soc_card *card = &snd_soc_at91sam9g20ek;
206 struct pinctrl *pinctrl;
207 int ret; 204 int ret;
208 205
209 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
210 if (IS_ERR(pinctrl)) {
211 dev_err(&pdev->dev, "Failed to request pinctrl for mck\n");
212 return PTR_ERR(pinctrl);
213 }
214
215 if (!np) { 206 if (!np) {
216 if (!(machine_is_at91sam9g20ek() || 207 if (!(machine_is_at91sam9g20ek() ||
217 machine_is_at91sam9g20ek_2mmc())) 208 machine_is_at91sam9g20ek_2mmc()))
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index 16b88f5c26e2..54f74f8cbb75 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -56,6 +56,23 @@ config SND_SOC_BFIN_EVAL_ADAV80X
56 Note: This driver assumes that the ADAV80X digital record and playback 56 Note: This driver assumes that the ADAV80X digital record and playback
57 interfaces are connected to the first SPORT port on the BF5XX board. 57 interfaces are connected to the first SPORT port on the BF5XX board.
58 58
59config SND_BF5XX_SOC_AD1836
60 tristate "SoC AD1836 Audio support for BF5xx"
61 depends on SND_BF5XX_I2S
62 select SND_BF5XX_SOC_I2S
63 select SND_SOC_AD1836
64 help
65 Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
66
67config SND_BF5XX_SOC_AD193X
68 tristate "SoC AD193X Audio support for Blackfin"
69 depends on SND_BF5XX_I2S
70 select SND_BF5XX_SOC_I2S
71 select SND_SOC_AD193X
72 help
73 Say Y if you want to add support for AD193X codec on Blackfin.
74 This driver supports AD1936, AD1937, AD1938 and AD1939.
75
59config SND_BF5XX_SOC_AD73311 76config SND_BF5XX_SOC_AD73311
60 tristate "SoC AD73311 Audio support for Blackfin" 77 tristate "SoC AD73311 Audio support for Blackfin"
61 depends on SND_BF5XX_I2S 78 depends on SND_BF5XX_I2S
@@ -72,33 +89,6 @@ config SND_BFIN_AD73311_SE
72 Enter the GPIO used to control AD73311's SE pin. Acceptable 89 Enter the GPIO used to control AD73311's SE pin. Acceptable
73 values are 0 to 7 90 values are 0 to 7
74 91
75config SND_BF5XX_TDM
76 tristate "SoC I2S(TDM mode) Audio for the ADI BF5xx chip"
77 depends on (BLACKFIN && SND_SOC)
78 select SND_BF5XX_SOC_SPORT
79 help
80 Say Y or M if you want to add support for codecs attached to
81 the Blackfin SPORT (synchronous serial ports) interface in TDM
82 mode.
83 You will also need to select the audio interfaces to support below.
84
85config SND_BF5XX_SOC_AD1836
86 tristate "SoC AD1836 Audio support for BF5xx"
87 depends on SND_BF5XX_TDM
88 select SND_BF5XX_SOC_TDM
89 select SND_SOC_AD1836
90 help
91 Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
92
93config SND_BF5XX_SOC_AD193X
94 tristate "SoC AD193X Audio support for Blackfin"
95 depends on SND_BF5XX_TDM
96 select SND_BF5XX_SOC_TDM
97 select SND_SOC_AD193X
98 help
99 Say Y if you want to add support for AD193X codec on Blackfin.
100 This driver supports AD1936, AD1937, AD1938 and AD1939.
101
102config SND_BF5XX_AC97 92config SND_BF5XX_AC97
103 tristate "SoC AC97 Audio for the ADI BF5xx chip" 93 tristate "SoC AC97 Audio for the ADI BF5xx chip"
104 depends on BLACKFIN 94 depends on BLACKFIN
@@ -174,9 +164,6 @@ config SND_BF5XX_SOC_I2S
174config SND_BF6XX_SOC_I2S 164config SND_BF6XX_SOC_I2S
175 tristate 165 tristate
176 166
177config SND_BF5XX_SOC_TDM
178 tristate
179
180config SND_BF5XX_SOC_AC97 167config SND_BF5XX_SOC_AC97
181 tristate 168 tristate
182 169
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
index 6fea1f4cbee2..ad0a6e99bc5d 100644
--- a/sound/soc/blackfin/Makefile
+++ b/sound/soc/blackfin/Makefile
@@ -1,23 +1,19 @@
1# Blackfin Platform Support 1# Blackfin Platform Support
2snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o 2snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o
3snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o 3snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o
4snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o
5snd-soc-bf5xx-sport-objs := bf5xx-sport.o 4snd-soc-bf5xx-sport-objs := bf5xx-sport.o
6snd-soc-bf6xx-sport-objs := bf6xx-sport.o 5snd-soc-bf6xx-sport-objs := bf6xx-sport.o
7snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o 6snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o
8snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o 7snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o
9snd-soc-bf6xx-i2s-objs := bf6xx-i2s.o 8snd-soc-bf6xx-i2s-objs := bf6xx-i2s.o
10snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o
11 9
12obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o 10obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o
13obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o 11obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o
14obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o
15obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o 12obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o
16obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o 13obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o
17obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o 14obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o
18obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o 15obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
19obj-$(CONFIG_SND_BF6XX_SOC_I2S) += snd-soc-bf6xx-i2s.o 16obj-$(CONFIG_SND_BF6XX_SOC_I2S) += snd-soc-bf6xx-i2s.o
20obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o
21 17
22# Blackfin Machine Support 18# Blackfin Machine Support
23snd-ad1836-objs := bf5xx-ad1836.o 19snd-ad1836-objs := bf5xx-ad1836.o
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 7e2f36004a5a..53f84085bf1f 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -39,7 +39,6 @@
39 39
40#include <asm/dma.h> 40#include <asm/dma.h>
41 41
42#include "bf5xx-ac97-pcm.h"
43#include "bf5xx-ac97.h" 42#include "bf5xx-ac97.h"
44#include "bf5xx-sport.h" 43#include "bf5xx-sport.h"
45 44
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.h b/sound/soc/blackfin/bf5xx-ac97-pcm.h
deleted file mode 100644
index d324d5826a9b..000000000000
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.h
+++ /dev/null
@@ -1,26 +0,0 @@
1/*
2 * linux/sound/arm/bf5xx-ac97-pcm.h -- ALSA PCM interface for the Blackfin
3 *
4 * Copyright 2007 Analog Device Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef _BF5XX_AC97_PCM_H
12#define _BF5XX_AC97_PCM_H
13
14struct bf5xx_pcm_dma_params {
15 char *name; /* stream identifier */
16};
17
18struct bf5xx_gpio {
19 u32 sys;
20 u32 rx;
21 u32 tx;
22 u32 clk;
23 u32 frm;
24};
25
26#endif
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index 490217325975..c66bef826ac5 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -231,9 +231,9 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
231 return 0; 231 return 0;
232 232
233#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) 233#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
234 ret = sport_set_multichannel(sport, 16, 0x3FF, 1); 234 ret = sport_set_multichannel(sport, 16, 0x3FF, 0x3FF, 1);
235#else 235#else
236 ret = sport_set_multichannel(sport, 16, 0x1F, 1); 236 ret = sport_set_multichannel(sport, 16, 0x1F, 0x1F, 1);
237#endif 237#endif
238 if (ret) { 238 if (ret) {
239 pr_err("SPORT is busy!\n"); 239 pr_err("SPORT is busy!\n");
@@ -311,9 +311,9 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev)
311 311
312 /*SPORT works in TDM mode to simulate AC97 transfers*/ 312 /*SPORT works in TDM mode to simulate AC97 transfers*/
313#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) 313#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
314 ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 1); 314 ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 0x3FF, 1);
315#else 315#else
316 ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); 316 ret = sport_set_multichannel(sport_handle, 16, 0x1F, 0x1F, 1);
317#endif 317#endif
318 if (ret) { 318 if (ret) {
319 pr_err("SPORT is busy!\n"); 319 pr_err("SPORT is busy!\n");
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
index d23f4b0ea54f..8fcfc4ec3a51 100644
--- a/sound/soc/blackfin/bf5xx-ad1836.c
+++ b/sound/soc/blackfin/bf5xx-ad1836.c
@@ -30,15 +30,10 @@
30 30
31#include "../codecs/ad1836.h" 31#include "../codecs/ad1836.h"
32 32
33#include "bf5xx-tdm-pcm.h"
34#include "bf5xx-tdm.h"
35
36static struct snd_soc_card bf5xx_ad1836; 33static struct snd_soc_card bf5xx_ad1836;
37 34
38static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, 35static int bf5xx_ad1836_init(struct snd_soc_pcm_runtime *rtd)
39 struct snd_pcm_hw_params *params)
40{ 36{
41 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 37 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
43 unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7}; 38 unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
44 int ret = 0; 39 int ret = 0;
@@ -49,13 +44,13 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
49 if (ret < 0) 44 if (ret < 0)
50 return ret; 45 return ret;
51 46
47 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xFF, 0xFF, 8, 32);
48 if (ret < 0)
49 return ret;
50
52 return 0; 51 return 0;
53} 52}
54 53
55static struct snd_soc_ops bf5xx_ad1836_ops = {
56 .hw_params = bf5xx_ad1836_hw_params,
57};
58
59#define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ 54#define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
60 SND_SOC_DAIFMT_CBM_CFM) 55 SND_SOC_DAIFMT_CBM_CFM)
61 56
@@ -63,9 +58,9 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai = {
63 .name = "ad1836", 58 .name = "ad1836",
64 .stream_name = "AD1836", 59 .stream_name = "AD1836",
65 .codec_dai_name = "ad1836-hifi", 60 .codec_dai_name = "ad1836-hifi",
66 .platform_name = "bfin-tdm-pcm-audio", 61 .platform_name = "bfin-i2s-pcm-audio",
67 .ops = &bf5xx_ad1836_ops,
68 .dai_fmt = BF5XX_AD1836_DAIFMT, 62 .dai_fmt = BF5XX_AD1836_DAIFMT,
63 .init = bf5xx_ad1836_init,
69}; 64};
70 65
71static struct snd_soc_card bf5xx_ad1836 = { 66static struct snd_soc_card bf5xx_ad1836 = {
diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c
index 0e55e9f2a514..603ad1f2b9b9 100644
--- a/sound/soc/blackfin/bf5xx-ad193x.c
+++ b/sound/soc/blackfin/bf5xx-ad193x.c
@@ -39,30 +39,16 @@
39 39
40#include "../codecs/ad193x.h" 40#include "../codecs/ad193x.h"
41 41
42#include "bf5xx-tdm-pcm.h"
43#include "bf5xx-tdm.h"
44
45static struct snd_soc_card bf5xx_ad193x; 42static struct snd_soc_card bf5xx_ad193x;
46 43
47static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, 44static int bf5xx_ad193x_link_init(struct snd_soc_pcm_runtime *rtd)
48 struct snd_pcm_hw_params *params)
49{ 45{
50 struct snd_soc_pcm_runtime *rtd = substream->private_data;
51 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 46 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
52 struct snd_soc_dai *codec_dai = rtd->codec_dai; 47 struct snd_soc_dai *codec_dai = rtd->codec_dai;
53 unsigned int clk = 0; 48 int ret;
54 unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7};
55 int ret = 0;
56
57 switch (params_rate(params)) {
58 case 48000:
59 clk = 24576000;
60 break;
61 }
62 49
63 /* set the codec system clock for DAC and ADC */ 50 /* set the codec system clock for DAC and ADC */
64 ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk, 51 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN);
65 SND_SOC_CLOCK_IN);
66 if (ret < 0) 52 if (ret < 0)
67 return ret; 53 return ret;
68 54
@@ -71,9 +57,7 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
71 if (ret < 0) 57 if (ret < 0)
72 return ret; 58 return ret;
73 59
74 /* set cpu DAI channel mapping */ 60 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xFF, 0xFF, 8, 32);
75 ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
76 channel_map, ARRAY_SIZE(channel_map), channel_map);
77 if (ret < 0) 61 if (ret < 0)
78 return ret; 62 return ret;
79 63
@@ -83,30 +67,26 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
83#define BF5XX_AD193X_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ 67#define BF5XX_AD193X_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
84 SND_SOC_DAIFMT_CBM_CFM) 68 SND_SOC_DAIFMT_CBM_CFM)
85 69
86static struct snd_soc_ops bf5xx_ad193x_ops = {
87 .hw_params = bf5xx_ad193x_hw_params,
88};
89
90static struct snd_soc_dai_link bf5xx_ad193x_dai[] = { 70static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
91 { 71 {
92 .name = "ad193x", 72 .name = "ad193x",
93 .stream_name = "AD193X", 73 .stream_name = "AD193X",
94 .cpu_dai_name = "bfin-tdm.0", 74 .cpu_dai_name = "bfin-i2s.0",
95 .codec_dai_name ="ad193x-hifi", 75 .codec_dai_name ="ad193x-hifi",
96 .platform_name = "bfin-tdm-pcm-audio", 76 .platform_name = "bfin-i2s-pcm-audio",
97 .codec_name = "spi0.5", 77 .codec_name = "spi0.5",
98 .ops = &bf5xx_ad193x_ops,
99 .dai_fmt = BF5XX_AD193X_DAIFMT, 78 .dai_fmt = BF5XX_AD193X_DAIFMT,
79 .init = bf5xx_ad193x_link_init,
100 }, 80 },
101 { 81 {
102 .name = "ad193x", 82 .name = "ad193x",
103 .stream_name = "AD193X", 83 .stream_name = "AD193X",
104 .cpu_dai_name = "bfin-tdm.1", 84 .cpu_dai_name = "bfin-i2s.1",
105 .codec_dai_name ="ad193x-hifi", 85 .codec_dai_name ="ad193x-hifi",
106 .platform_name = "bfin-tdm-pcm-audio", 86 .platform_name = "bfin-i2s-pcm-audio",
107 .codec_name = "spi0.5", 87 .codec_name = "spi0.5",
108 .ops = &bf5xx_ad193x_ops,
109 .dai_fmt = BF5XX_AD193X_DAIFMT, 88 .dai_fmt = BF5XX_AD193X_DAIFMT,
89 .init = bf5xx_ad193x_link_init,
110 }, 90 },
111}; 91};
112 92
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c
index b30f88bbd703..3450e8f9080d 100644
--- a/sound/soc/blackfin/bf5xx-ad1980.c
+++ b/sound/soc/blackfin/bf5xx-ad1980.c
@@ -48,7 +48,6 @@
48 48
49#include "../codecs/ad1980.h" 49#include "../codecs/ad1980.h"
50 50
51#include "bf5xx-ac97-pcm.h"
52#include "bf5xx-ac97.h" 51#include "bf5xx-ac97.h"
53 52
54static struct snd_soc_card bf5xx_board; 53static struct snd_soc_card bf5xx_board;
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index 61cc91d4a028..786bbdd96e7c 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -45,7 +45,6 @@
45 45
46#include "../codecs/ad73311.h" 46#include "../codecs/ad73311.h"
47#include "bf5xx-sport.h" 47#include "bf5xx-sport.h"
48#include "bf5xx-i2s-pcm.h"
49 48
50#if CONFIG_SND_BF5XX_SPORT_NUM == 0 49#if CONFIG_SND_BF5XX_SPORT_NUM == 0
51#define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1 50#define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 262c1de364d8..9cb4a80df98e 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -39,8 +39,8 @@
39 39
40#include <asm/dma.h> 40#include <asm/dma.h>
41 41
42#include "bf5xx-i2s-pcm.h"
43#include "bf5xx-sport.h" 42#include "bf5xx-sport.h"
43#include "bf5xx-i2s-pcm.h"
44 44
45static void bf5xx_dma_irq(void *data) 45static void bf5xx_dma_irq(void *data)
46{ 46{
@@ -50,7 +50,6 @@ static void bf5xx_dma_irq(void *data)
50 50
51static const struct snd_pcm_hardware bf5xx_pcm_hardware = { 51static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
52 .info = SNDRV_PCM_INFO_INTERLEAVED | 52 .info = SNDRV_PCM_INFO_INTERLEAVED |
53 SNDRV_PCM_INFO_MMAP |
54 SNDRV_PCM_INFO_MMAP_VALID | 53 SNDRV_PCM_INFO_MMAP_VALID |
55 SNDRV_PCM_INFO_BLOCK_TRANSFER, 54 SNDRV_PCM_INFO_BLOCK_TRANSFER,
56 .formats = SNDRV_PCM_FMTBIT_S16_LE | 55 .formats = SNDRV_PCM_FMTBIT_S16_LE |
@@ -67,10 +66,16 @@ static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
67static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, 66static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
68 struct snd_pcm_hw_params *params) 67 struct snd_pcm_hw_params *params)
69{ 68{
70 size_t size = bf5xx_pcm_hardware.buffer_bytes_max; 69 struct snd_soc_pcm_runtime *rtd = substream->private_data;
71 snd_pcm_lib_malloc_pages(substream, size); 70 unsigned int buffer_size = params_buffer_bytes(params);
71 struct bf5xx_i2s_pcm_data *dma_data;
72 72
73 return 0; 73 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
74
75 if (dma_data->tdm_mode)
76 buffer_size = buffer_size / params_channels(params) * 8;
77
78 return snd_pcm_lib_malloc_pages(substream, buffer_size);
74} 79}
75 80
76static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) 81static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
@@ -82,9 +87,16 @@ static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
82 87
83static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) 88static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
84{ 89{
90 struct snd_soc_pcm_runtime *rtd = substream->private_data;
85 struct snd_pcm_runtime *runtime = substream->runtime; 91 struct snd_pcm_runtime *runtime = substream->runtime;
86 struct sport_device *sport = runtime->private_data; 92 struct sport_device *sport = runtime->private_data;
87 int period_bytes = frames_to_bytes(runtime, runtime->period_size); 93 int period_bytes = frames_to_bytes(runtime, runtime->period_size);
94 struct bf5xx_i2s_pcm_data *dma_data;
95
96 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
97
98 if (dma_data->tdm_mode)
99 period_bytes = period_bytes / runtime->channels * 8;
88 100
89 pr_debug("%s enter\n", __func__); 101 pr_debug("%s enter\n", __func__);
90 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 102 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -131,10 +143,15 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
131 143
132static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) 144static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
133{ 145{
146 struct snd_soc_pcm_runtime *rtd = substream->private_data;
134 struct snd_pcm_runtime *runtime = substream->runtime; 147 struct snd_pcm_runtime *runtime = substream->runtime;
135 struct sport_device *sport = runtime->private_data; 148 struct sport_device *sport = runtime->private_data;
136 unsigned int diff; 149 unsigned int diff;
137 snd_pcm_uframes_t frames; 150 snd_pcm_uframes_t frames;
151 struct bf5xx_i2s_pcm_data *dma_data;
152
153 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
154
138 pr_debug("%s enter\n", __func__); 155 pr_debug("%s enter\n", __func__);
139 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 156 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
140 diff = sport_curr_offset_tx(sport); 157 diff = sport_curr_offset_tx(sport);
@@ -151,6 +168,8 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
151 diff = 0; 168 diff = 0;
152 169
153 frames = bytes_to_frames(substream->runtime, diff); 170 frames = bytes_to_frames(substream->runtime, diff);
171 if (dma_data->tdm_mode)
172 frames = frames * runtime->channels / 8;
154 173
155 return frames; 174 return frames;
156} 175}
@@ -162,11 +181,18 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
162 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); 181 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai);
163 struct snd_pcm_runtime *runtime = substream->runtime; 182 struct snd_pcm_runtime *runtime = substream->runtime;
164 struct snd_dma_buffer *buf = &substream->dma_buffer; 183 struct snd_dma_buffer *buf = &substream->dma_buffer;
184 struct bf5xx_i2s_pcm_data *dma_data;
165 int ret; 185 int ret;
166 186
187 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
188
167 pr_debug("%s enter\n", __func__); 189 pr_debug("%s enter\n", __func__);
168 190
169 snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); 191 snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);
192 if (dma_data->tdm_mode)
193 runtime->hw.buffer_bytes_max /= 4;
194 else
195 runtime->hw.info |= SNDRV_PCM_INFO_MMAP;
170 196
171 ret = snd_pcm_hw_constraint_integer(runtime, 197 ret = snd_pcm_hw_constraint_integer(runtime,
172 SNDRV_PCM_HW_PARAM_PERIODS); 198 SNDRV_PCM_HW_PARAM_PERIODS);
@@ -202,6 +228,88 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
202 return 0 ; 228 return 0 ;
203} 229}
204 230
231static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
232 snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
233{
234 struct snd_soc_pcm_runtime *rtd = substream->private_data;
235 struct snd_pcm_runtime *runtime = substream->runtime;
236 unsigned int sample_size = runtime->sample_bits / 8;
237 struct bf5xx_i2s_pcm_data *dma_data;
238 unsigned int i;
239 void *src, *dst;
240
241 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
242
243 if (dma_data->tdm_mode) {
244 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
245 src = buf;
246 dst = runtime->dma_area;
247 dst += pos * sample_size * 8;
248
249 while (count--) {
250 for (i = 0; i < runtime->channels; i++) {
251 memcpy(dst + dma_data->map[i] *
252 sample_size, src, sample_size);
253 src += sample_size;
254 }
255 dst += 8 * sample_size;
256 }
257 } else {
258 src = runtime->dma_area;
259 src += pos * sample_size * 8;
260 dst = buf;
261
262 while (count--) {
263 for (i = 0; i < runtime->channels; i++) {
264 memcpy(dst, src + dma_data->map[i] *
265 sample_size, sample_size);
266 dst += sample_size;
267 }
268 src += 8 * sample_size;
269 }
270 }
271 } else {
272 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
273 src = buf;
274 dst = runtime->dma_area;
275 dst += frames_to_bytes(runtime, pos);
276 } else {
277 src = runtime->dma_area;
278 src += frames_to_bytes(runtime, pos);
279 dst = buf;
280 }
281
282 memcpy(dst, src, frames_to_bytes(runtime, count));
283 }
284
285 return 0;
286}
287
288static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
289 int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
290{
291 struct snd_soc_pcm_runtime *rtd = substream->private_data;
292 struct snd_pcm_runtime *runtime = substream->runtime;
293 unsigned int sample_size = runtime->sample_bits / 8;
294 void *buf = runtime->dma_area;
295 struct bf5xx_i2s_pcm_data *dma_data;
296 unsigned int offset, size;
297
298 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
299
300 if (dma_data->tdm_mode) {
301 offset = pos * 8 * sample_size;
302 size = count * 8 * sample_size;
303 } else {
304 offset = frames_to_bytes(runtime, pos);
305 size = frames_to_bytes(runtime, count);
306 }
307
308 snd_pcm_format_set_silence(runtime->format, buf + offset, size);
309
310 return 0;
311}
312
205static struct snd_pcm_ops bf5xx_pcm_i2s_ops = { 313static struct snd_pcm_ops bf5xx_pcm_i2s_ops = {
206 .open = bf5xx_pcm_open, 314 .open = bf5xx_pcm_open,
207 .ioctl = snd_pcm_lib_ioctl, 315 .ioctl = snd_pcm_lib_ioctl,
@@ -211,57 +319,16 @@ static struct snd_pcm_ops bf5xx_pcm_i2s_ops = {
211 .trigger = bf5xx_pcm_trigger, 319 .trigger = bf5xx_pcm_trigger,
212 .pointer = bf5xx_pcm_pointer, 320 .pointer = bf5xx_pcm_pointer,
213 .mmap = bf5xx_pcm_mmap, 321 .mmap = bf5xx_pcm_mmap,
322 .copy = bf5xx_pcm_copy,
323 .silence = bf5xx_pcm_silence,
214}; 324};
215 325
216static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
217{
218 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
219 struct snd_dma_buffer *buf = &substream->dma_buffer;
220 size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
221
222 buf->dev.type = SNDRV_DMA_TYPE_DEV;
223 buf->dev.dev = pcm->card->dev;
224 buf->private_data = NULL;
225 buf->area = dma_alloc_coherent(pcm->card->dev, size,
226 &buf->addr, GFP_KERNEL);
227 if (!buf->area) {
228 pr_err("Failed to allocate dma memory - Please increase uncached DMA memory region\n");
229 return -ENOMEM;
230 }
231 buf->bytes = size;
232
233 pr_debug("%s, area:%p, size:0x%08lx\n", __func__,
234 buf->area, buf->bytes);
235
236 return 0;
237}
238
239static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
240{
241 struct snd_pcm_substream *substream;
242 struct snd_dma_buffer *buf;
243 int stream;
244
245 for (stream = 0; stream < 2; stream++) {
246 substream = pcm->streams[stream].substream;
247 if (!substream)
248 continue;
249
250 buf = &substream->dma_buffer;
251 if (!buf->area)
252 continue;
253 dma_free_coherent(NULL, buf->bytes, buf->area, 0);
254 buf->area = NULL;
255 }
256}
257
258static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); 326static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
259 327
260static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd) 328static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
261{ 329{
262 struct snd_card *card = rtd->card->snd_card; 330 struct snd_card *card = rtd->card->snd_card;
263 struct snd_pcm *pcm = rtd->pcm; 331 size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
264 int ret = 0;
265 332
266 pr_debug("%s enter\n", __func__); 333 pr_debug("%s enter\n", __func__);
267 if (!card->dev->dma_mask) 334 if (!card->dev->dma_mask)
@@ -269,27 +336,13 @@ static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
269 if (!card->dev->coherent_dma_mask) 336 if (!card->dev->coherent_dma_mask)
270 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 337 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
271 338
272 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { 339 return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
273 ret = bf5xx_pcm_preallocate_dma_buffer(pcm, 340 SNDRV_DMA_TYPE_DEV, card->dev, size, size);
274 SNDRV_PCM_STREAM_PLAYBACK);
275 if (ret)
276 goto out;
277 }
278
279 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
280 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
281 SNDRV_PCM_STREAM_CAPTURE);
282 if (ret)
283 goto out;
284 }
285 out:
286 return ret;
287} 341}
288 342
289static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = { 343static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = {
290 .ops = &bf5xx_pcm_i2s_ops, 344 .ops = &bf5xx_pcm_i2s_ops,
291 .pcm_new = bf5xx_pcm_i2s_new, 345 .pcm_new = bf5xx_pcm_i2s_new,
292 .pcm_free = bf5xx_pcm_free_dma_buffers,
293}; 346};
294 347
295static int bfin_i2s_soc_platform_probe(struct platform_device *pdev) 348static int bfin_i2s_soc_platform_probe(struct platform_device *pdev)
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.h b/sound/soc/blackfin/bf5xx-i2s-pcm.h
index 0c2c5a68d4ff..1f0435249f88 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.h
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.h
@@ -1,26 +1,17 @@
1/* 1/*
2 * linux/sound/arm/bf5xx-i2s-pcm.h -- ALSA PCM interface for the Blackfin
3 *
4 * Copyright 2007 Analog Device Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify 2 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 3 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. 4 * published by the Free Software Foundation.
9 */ 5 */
10 6
11#ifndef _BF5XX_I2S_PCM_H 7#ifndef _BF5XX_TDM_PCM_H
12#define _BF5XX_I2S_PCM_H 8#define _BF5XX_TDM_PCM_H
13 9
14struct bf5xx_pcm_dma_params { 10#define BFIN_TDM_DAI_MAX_SLOTS 8
15 char *name; /* stream identifier */
16};
17 11
18struct bf5xx_gpio { 12struct bf5xx_i2s_pcm_data {
19 u32 sys; 13 unsigned int map[BFIN_TDM_DAI_MAX_SLOTS];
20 u32 rx; 14 bool tdm_mode;
21 u32 tx;
22 u32 clk;
23 u32 frm;
24}; 15};
25 16
26#endif 17#endif
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index dd0c2a4f83a3..9a174fc47d39 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -42,6 +42,7 @@
42#include <linux/gpio.h> 42#include <linux/gpio.h>
43 43
44#include "bf5xx-sport.h" 44#include "bf5xx-sport.h"
45#include "bf5xx-i2s-pcm.h"
45 46
46struct bf5xx_i2s_port { 47struct bf5xx_i2s_port {
47 u16 tcr1; 48 u16 tcr1;
@@ -49,6 +50,13 @@ struct bf5xx_i2s_port {
49 u16 tcr2; 50 u16 tcr2;
50 u16 rcr2; 51 u16 rcr2;
51 int configured; 52 int configured;
53
54 unsigned int slots;
55 unsigned int tx_mask;
56 unsigned int rx_mask;
57
58 struct bf5xx_i2s_pcm_data tx_dma_data;
59 struct bf5xx_i2s_pcm_data rx_dma_data;
52}; 60};
53 61
54static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, 62static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
@@ -74,7 +82,8 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
74 ret = -EINVAL; 82 ret = -EINVAL;
75 break; 83 break;
76 default: 84 default:
77 printk(KERN_ERR "%s: Unknown DAI format type\n", __func__); 85 dev_err(cpu_dai->dev, "%s: Unknown DAI format type\n",
86 __func__);
78 ret = -EINVAL; 87 ret = -EINVAL;
79 break; 88 break;
80 } 89 }
@@ -88,7 +97,8 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
88 ret = -EINVAL; 97 ret = -EINVAL;
89 break; 98 break;
90 default: 99 default:
91 printk(KERN_ERR "%s: Unknown DAI master type\n", __func__); 100 dev_err(cpu_dai->dev, "%s: Unknown DAI master type\n",
101 __func__);
92 ret = -EINVAL; 102 ret = -EINVAL;
93 break; 103 break;
94 } 104 }
@@ -141,14 +151,14 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
141 ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1, 151 ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1,
142 bf5xx_i2s->rcr2, 0, 0); 152 bf5xx_i2s->rcr2, 0, 0);
143 if (ret) { 153 if (ret) {
144 pr_err("SPORT is busy!\n"); 154 dev_err(dai->dev, "SPORT is busy!\n");
145 return -EBUSY; 155 return -EBUSY;
146 } 156 }
147 157
148 ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1, 158 ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1,
149 bf5xx_i2s->tcr2, 0, 0); 159 bf5xx_i2s->tcr2, 0, 0);
150 if (ret) { 160 if (ret) {
151 pr_err("SPORT is busy!\n"); 161 dev_err(dai->dev, "SPORT is busy!\n");
152 return -EBUSY; 162 return -EBUSY;
153 } 163 }
154 } 164 }
@@ -162,18 +172,76 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
162 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); 172 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
163 struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; 173 struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
164 174
165 pr_debug("%s enter\n", __func__); 175 dev_dbg(dai->dev, "%s enter\n", __func__);
166 /* No active stream, SPORT is allowed to be configured again. */ 176 /* No active stream, SPORT is allowed to be configured again. */
167 if (!dai->active) 177 if (!dai->active)
168 bf5xx_i2s->configured = 0; 178 bf5xx_i2s->configured = 0;
169} 179}
170 180
181static int bf5xx_i2s_set_channel_map(struct snd_soc_dai *dai,
182 unsigned int tx_num, unsigned int *tx_slot,
183 unsigned int rx_num, unsigned int *rx_slot)
184{
185 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
186 struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
187 unsigned int tx_mapped = 0, rx_mapped = 0;
188 unsigned int slot;
189 int i;
190
191 if ((tx_num > BFIN_TDM_DAI_MAX_SLOTS) ||
192 (rx_num > BFIN_TDM_DAI_MAX_SLOTS))
193 return -EINVAL;
194
195 for (i = 0; i < tx_num; i++) {
196 slot = tx_slot[i];
197 if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
198 (!(tx_mapped & (1 << slot)))) {
199 bf5xx_i2s->tx_dma_data.map[i] = slot;
200 tx_mapped |= 1 << slot;
201 } else
202 return -EINVAL;
203 }
204 for (i = 0; i < rx_num; i++) {
205 slot = rx_slot[i];
206 if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
207 (!(rx_mapped & (1 << slot)))) {
208 bf5xx_i2s->rx_dma_data.map[i] = slot;
209 rx_mapped |= 1 << slot;
210 } else
211 return -EINVAL;
212 }
213
214 return 0;
215}
216
217static int bf5xx_i2s_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
218 unsigned int rx_mask, int slots, int width)
219{
220 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
221 struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
222
223 if (slots % 8 != 0 || slots > 8)
224 return -EINVAL;
225
226 if (width != 32)
227 return -EINVAL;
228
229 bf5xx_i2s->slots = slots;
230 bf5xx_i2s->tx_mask = tx_mask;
231 bf5xx_i2s->rx_mask = rx_mask;
232
233 bf5xx_i2s->tx_dma_data.tdm_mode = slots != 0;
234 bf5xx_i2s->rx_dma_data.tdm_mode = slots != 0;
235
236 return sport_set_multichannel(sport_handle, slots, tx_mask, rx_mask, 0);
237}
238
171#ifdef CONFIG_PM 239#ifdef CONFIG_PM
172static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) 240static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
173{ 241{
174 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); 242 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
175 243
176 pr_debug("%s : sport %d\n", __func__, dai->id); 244 dev_dbg(dai->dev, "%s : sport %d\n", __func__, dai->id);
177 245
178 if (dai->capture_active) 246 if (dai->capture_active)
179 sport_rx_stop(sport_handle); 247 sport_rx_stop(sport_handle);
@@ -188,23 +256,24 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
188 struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; 256 struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
189 int ret; 257 int ret;
190 258
191 pr_debug("%s : sport %d\n", __func__, dai->id); 259 dev_dbg(dai->dev, "%s : sport %d\n", __func__, dai->id);
192 260
193 ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1, 261 ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1,
194 bf5xx_i2s->rcr2, 0, 0); 262 bf5xx_i2s->rcr2, 0, 0);
195 if (ret) { 263 if (ret) {
196 pr_err("SPORT is busy!\n"); 264 dev_err(dai->dev, "SPORT is busy!\n");
197 return -EBUSY; 265 return -EBUSY;
198 } 266 }
199 267
200 ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1, 268 ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1,
201 bf5xx_i2s->tcr2, 0, 0); 269 bf5xx_i2s->tcr2, 0, 0);
202 if (ret) { 270 if (ret) {
203 pr_err("SPORT is busy!\n"); 271 dev_err(dai->dev, "SPORT is busy!\n");
204 return -EBUSY; 272 return -EBUSY;
205 } 273 }
206 274
207 return 0; 275 return sport_set_multichannel(sport_handle, bf5xx_i2s->slots,
276 bf5xx_i2s->tx_mask, bf5xx_i2s->rx_mask, 0);
208} 277}
209 278
210#else 279#else
@@ -212,6 +281,23 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
212#define bf5xx_i2s_resume NULL 281#define bf5xx_i2s_resume NULL
213#endif 282#endif
214 283
284static int bf5xx_i2s_dai_probe(struct snd_soc_dai *dai)
285{
286 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
287 struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data;
288 unsigned int i;
289
290 for (i = 0; i < BFIN_TDM_DAI_MAX_SLOTS; i++) {
291 bf5xx_i2s->tx_dma_data.map[i] = i;
292 bf5xx_i2s->rx_dma_data.map[i] = i;
293 }
294
295 dai->playback_dma_data = &bf5xx_i2s->tx_dma_data;
296 dai->capture_dma_data = &bf5xx_i2s->rx_dma_data;
297
298 return 0;
299}
300
215#define BF5XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 301#define BF5XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
216 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ 302 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
217 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ 303 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
@@ -224,22 +310,25 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
224 SNDRV_PCM_FMTBIT_S32_LE) 310 SNDRV_PCM_FMTBIT_S32_LE)
225 311
226static const struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { 312static const struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
227 .shutdown = bf5xx_i2s_shutdown, 313 .shutdown = bf5xx_i2s_shutdown,
228 .hw_params = bf5xx_i2s_hw_params, 314 .hw_params = bf5xx_i2s_hw_params,
229 .set_fmt = bf5xx_i2s_set_dai_fmt, 315 .set_fmt = bf5xx_i2s_set_dai_fmt,
316 .set_tdm_slot = bf5xx_i2s_set_tdm_slot,
317 .set_channel_map = bf5xx_i2s_set_channel_map,
230}; 318};
231 319
232static struct snd_soc_dai_driver bf5xx_i2s_dai = { 320static struct snd_soc_dai_driver bf5xx_i2s_dai = {
321 .probe = bf5xx_i2s_dai_probe,
233 .suspend = bf5xx_i2s_suspend, 322 .suspend = bf5xx_i2s_suspend,
234 .resume = bf5xx_i2s_resume, 323 .resume = bf5xx_i2s_resume,
235 .playback = { 324 .playback = {
236 .channels_min = 1, 325 .channels_min = 2,
237 .channels_max = 2, 326 .channels_max = 8,
238 .rates = BF5XX_I2S_RATES, 327 .rates = BF5XX_I2S_RATES,
239 .formats = BF5XX_I2S_FORMATS,}, 328 .formats = BF5XX_I2S_FORMATS,},
240 .capture = { 329 .capture = {
241 .channels_min = 1, 330 .channels_min = 2,
242 .channels_max = 2, 331 .channels_max = 8,
243 .rates = BF5XX_I2S_RATES, 332 .rates = BF5XX_I2S_RATES,
244 .formats = BF5XX_I2S_FORMATS,}, 333 .formats = BF5XX_I2S_FORMATS,},
245 .ops = &bf5xx_i2s_dai_ops, 334 .ops = &bf5xx_i2s_dai_ops,
@@ -255,7 +344,7 @@ static int bf5xx_i2s_probe(struct platform_device *pdev)
255 int ret; 344 int ret;
256 345
257 /* configure SPORT for I2S */ 346 /* configure SPORT for I2S */
258 sport_handle = sport_init(pdev, 4, 2 * sizeof(u32), 347 sport_handle = sport_init(pdev, 4, 8 * sizeof(u32),
259 sizeof(struct bf5xx_i2s_port)); 348 sizeof(struct bf5xx_i2s_port));
260 if (!sport_handle) 349 if (!sport_handle)
261 return -ENODEV; 350 return -ENODEV;
@@ -264,7 +353,7 @@ static int bf5xx_i2s_probe(struct platform_device *pdev)
264 ret = snd_soc_register_component(&pdev->dev, &bf5xx_i2s_component, 353 ret = snd_soc_register_component(&pdev->dev, &bf5xx_i2s_component,
265 &bf5xx_i2s_dai, 1); 354 &bf5xx_i2s_dai, 1);
266 if (ret) { 355 if (ret) {
267 pr_err("Failed to register DAI: %d\n", ret); 356 dev_err(&pdev->dev, "Failed to register DAI: %d\n", ret);
268 sport_done(sport_handle); 357 sport_done(sport_handle);
269 return ret; 358 return ret;
270 } 359 }
@@ -276,7 +365,7 @@ static int bf5xx_i2s_remove(struct platform_device *pdev)
276{ 365{
277 struct sport_device *sport_handle = platform_get_drvdata(pdev); 366 struct sport_device *sport_handle = platform_get_drvdata(pdev);
278 367
279 pr_debug("%s enter\n", __func__); 368 dev_dbg(&pdev->dev, "%s enter\n", __func__);
280 369
281 snd_soc_unregister_component(&pdev->dev); 370 snd_soc_unregister_component(&pdev->dev);
282 sport_done(sport_handle); 371 sport_done(sport_handle);
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c
index 2fd9f2a06968..695351241db8 100644
--- a/sound/soc/blackfin/bf5xx-sport.c
+++ b/sound/soc/blackfin/bf5xx-sport.c
@@ -46,10 +46,10 @@
46/* note: multichannel is in units of 8 channels, 46/* note: multichannel is in units of 8 channels,
47 * tdm_count is # channels NOT / 8 ! */ 47 * tdm_count is # channels NOT / 8 ! */
48int sport_set_multichannel(struct sport_device *sport, 48int sport_set_multichannel(struct sport_device *sport,
49 int tdm_count, u32 mask, int packed) 49 int tdm_count, u32 tx_mask, u32 rx_mask, int packed)
50{ 50{
51 pr_debug("%s tdm_count=%d mask:0x%08x packed=%d\n", __func__, 51 pr_debug("%s tdm_count=%d tx_mask:0x%08x rx_mask:0x%08x packed=%d\n",
52 tdm_count, mask, packed); 52 __func__, tdm_count, tx_mask, rx_mask, packed);
53 53
54 if ((sport->regs->tcr1 & TSPEN) || (sport->regs->rcr1 & RSPEN)) 54 if ((sport->regs->tcr1 & TSPEN) || (sport->regs->rcr1 & RSPEN))
55 return -EBUSY; 55 return -EBUSY;
@@ -65,8 +65,8 @@ int sport_set_multichannel(struct sport_device *sport,
65 sport->regs->mcmc2 = FRAME_DELAY | MCMEN | \ 65 sport->regs->mcmc2 = FRAME_DELAY | MCMEN | \
66 (packed ? (MCDTXPE|MCDRXPE) : 0); 66 (packed ? (MCDTXPE|MCDRXPE) : 0);
67 67
68 sport->regs->mtcs0 = mask; 68 sport->regs->mtcs0 = tx_mask;
69 sport->regs->mrcs0 = mask; 69 sport->regs->mrcs0 = rx_mask;
70 sport->regs->mtcs1 = 0; 70 sport->regs->mtcs1 = 0;
71 sport->regs->mrcs1 = 0; 71 sport->regs->mrcs1 = 0;
72 sport->regs->mtcs2 = 0; 72 sport->regs->mtcs2 = 0;
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h
index 5ab60bd613ea..9fc2192feb3b 100644
--- a/sound/soc/blackfin/bf5xx-sport.h
+++ b/sound/soc/blackfin/bf5xx-sport.h
@@ -128,7 +128,7 @@ void sport_done(struct sport_device *sport);
128/* note: multichannel is in units of 8 channels, tdm_count is number of channels 128/* note: multichannel is in units of 8 channels, tdm_count is number of channels
129 * NOT / 8 ! all channels are enabled by default */ 129 * NOT / 8 ! all channels are enabled by default */
130int sport_set_multichannel(struct sport_device *sport, int tdm_count, 130int sport_set_multichannel(struct sport_device *sport, int tdm_count,
131 u32 mask, int packed); 131 u32 tx_mask, u32 rx_mask, int packed);
132 132
133int sport_config_rx(struct sport_device *sport, 133int sport_config_rx(struct sport_device *sport,
134 unsigned int rcr1, unsigned int rcr2, 134 unsigned int rcr1, unsigned int rcr2,
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
index 7dbeef1099b4..9c19ccc936e2 100644
--- a/sound/soc/blackfin/bf5xx-ssm2602.c
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -40,7 +40,6 @@
40#include <linux/gpio.h> 40#include <linux/gpio.h>
41#include "../codecs/ssm2602.h" 41#include "../codecs/ssm2602.h"
42#include "bf5xx-sport.h" 42#include "bf5xx-sport.h"
43#include "bf5xx-i2s-pcm.h"
44 43
45static struct snd_soc_card bf5xx_ssm2602; 44static struct snd_soc_card bf5xx_ssm2602;
46 45
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
deleted file mode 100644
index 0e6b888bb4cc..000000000000
--- a/sound/soc/blackfin/bf5xx-tdm-pcm.c
+++ /dev/null
@@ -1,345 +0,0 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-tdm-pcm.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: Tue June 06 2009
6 * Description: DMA driver for tdm codec
7 *
8 * Modified:
9 * Copyright 2009 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/platform_device.h>
32#include <linux/dma-mapping.h>
33#include <linux/gfp.h>
34
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/soc.h>
39
40#include <asm/dma.h>
41
42#include "bf5xx-tdm-pcm.h"
43#include "bf5xx-tdm.h"
44#include "bf5xx-sport.h"
45
46#define PCM_BUFFER_MAX 0x8000
47#define FRAGMENT_SIZE_MIN (4*1024)
48#define FRAGMENTS_MIN 2
49#define FRAGMENTS_MAX 32
50
51static void bf5xx_dma_irq(void *data)
52{
53 struct snd_pcm_substream *pcm = data;
54 snd_pcm_period_elapsed(pcm);
55}
56
57static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
58 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
59 SNDRV_PCM_INFO_RESUME),
60 .formats = SNDRV_PCM_FMTBIT_S32_LE,
61 .rates = SNDRV_PCM_RATE_48000,
62 .channels_min = 2,
63 .channels_max = 8,
64 .buffer_bytes_max = PCM_BUFFER_MAX,
65 .period_bytes_min = FRAGMENT_SIZE_MIN,
66 .period_bytes_max = PCM_BUFFER_MAX/2,
67 .periods_min = FRAGMENTS_MIN,
68 .periods_max = FRAGMENTS_MAX,
69};
70
71static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
72 struct snd_pcm_hw_params *params)
73{
74 size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
75 snd_pcm_lib_malloc_pages(substream, size * 4);
76
77 return 0;
78}
79
80static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
81{
82 snd_pcm_lib_free_pages(substream);
83
84 return 0;
85}
86
87static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
88{
89 struct snd_pcm_runtime *runtime = substream->runtime;
90 struct sport_device *sport = runtime->private_data;
91 int fragsize_bytes = frames_to_bytes(runtime, runtime->period_size);
92
93 fragsize_bytes /= runtime->channels;
94 /* inflate the fragsize to match the dma width of SPORT */
95 fragsize_bytes *= 8;
96
97 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
98 sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
99 sport_config_tx_dma(sport, runtime->dma_area,
100 runtime->periods, fragsize_bytes);
101 } else {
102 sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
103 sport_config_rx_dma(sport, runtime->dma_area,
104 runtime->periods, fragsize_bytes);
105 }
106
107 return 0;
108}
109
110static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
111{
112 struct snd_pcm_runtime *runtime = substream->runtime;
113 struct sport_device *sport = runtime->private_data;
114 int ret = 0;
115
116 switch (cmd) {
117 case SNDRV_PCM_TRIGGER_START:
118 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
119 sport_tx_start(sport);
120 else
121 sport_rx_start(sport);
122 break;
123 case SNDRV_PCM_TRIGGER_STOP:
124 case SNDRV_PCM_TRIGGER_SUSPEND:
125 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
126 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
127 sport_tx_stop(sport);
128 else
129 sport_rx_stop(sport);
130 break;
131 default:
132 ret = -EINVAL;
133 }
134
135 return ret;
136}
137
138static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
139{
140 struct snd_pcm_runtime *runtime = substream->runtime;
141 struct sport_device *sport = runtime->private_data;
142 unsigned int diff;
143 snd_pcm_uframes_t frames;
144
145 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
146 diff = sport_curr_offset_tx(sport);
147 frames = diff / (8*4); /* 32 bytes per frame */
148 } else {
149 diff = sport_curr_offset_rx(sport);
150 frames = diff / (8*4);
151 }
152 return frames;
153}
154
155static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
156{
157 struct snd_soc_pcm_runtime *rtd = substream->private_data;
158 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
159 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai);
160 struct snd_pcm_runtime *runtime = substream->runtime;
161 struct snd_dma_buffer *buf = &substream->dma_buffer;
162
163 int ret = 0;
164
165 snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);
166
167 ret = snd_pcm_hw_constraint_integer(runtime,
168 SNDRV_PCM_HW_PARAM_PERIODS);
169 if (ret < 0)
170 goto out;
171
172 if (sport_handle != NULL) {
173 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
174 sport_handle->tx_buf = buf->area;
175 else
176 sport_handle->rx_buf = buf->area;
177
178 runtime->private_data = sport_handle;
179 } else {
180 pr_err("sport_handle is NULL\n");
181 ret = -ENODEV;
182 }
183out:
184 return ret;
185}
186
187static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
188 snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
189{
190 struct snd_pcm_runtime *runtime = substream->runtime;
191 struct sport_device *sport = runtime->private_data;
192 struct bf5xx_tdm_port *tdm_port = sport->private_data;
193 unsigned int *src;
194 unsigned int *dst;
195 int i;
196
197 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
198 src = buf;
199 dst = (unsigned int *)substream->runtime->dma_area;
200
201 dst += pos * 8;
202 while (count--) {
203 for (i = 0; i < substream->runtime->channels; i++)
204 *(dst + tdm_port->tx_map[i]) = *src++;
205 dst += 8;
206 }
207 } else {
208 src = (unsigned int *)substream->runtime->dma_area;
209 dst = buf;
210
211 src += pos * 8;
212 while (count--) {
213 for (i = 0; i < substream->runtime->channels; i++)
214 *dst++ = *(src + tdm_port->rx_map[i]);
215 src += 8;
216 }
217 }
218
219 return 0;
220}
221
222static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
223 int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
224{
225 unsigned char *buf = substream->runtime->dma_area;
226 buf += pos * 8 * 4;
227 memset(buf, '\0', count * 8 * 4);
228
229 return 0;
230}
231
232
233struct snd_pcm_ops bf5xx_pcm_tdm_ops = {
234 .open = bf5xx_pcm_open,
235 .ioctl = snd_pcm_lib_ioctl,
236 .hw_params = bf5xx_pcm_hw_params,
237 .hw_free = bf5xx_pcm_hw_free,
238 .prepare = bf5xx_pcm_prepare,
239 .trigger = bf5xx_pcm_trigger,
240 .pointer = bf5xx_pcm_pointer,
241 .copy = bf5xx_pcm_copy,
242 .silence = bf5xx_pcm_silence,
243};
244
245static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
246{
247 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
248 struct snd_dma_buffer *buf = &substream->dma_buffer;
249 size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
250
251 buf->dev.type = SNDRV_DMA_TYPE_DEV;
252 buf->dev.dev = pcm->card->dev;
253 buf->private_data = NULL;
254 buf->area = dma_alloc_coherent(pcm->card->dev, size * 4,
255 &buf->addr, GFP_KERNEL);
256 if (!buf->area) {
257 pr_err("Failed to allocate dma memory - Please increase uncached DMA memory region\n");
258 return -ENOMEM;
259 }
260 buf->bytes = size;
261
262 return 0;
263}
264
265static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
266{
267 struct snd_pcm_substream *substream;
268 struct snd_dma_buffer *buf;
269 int stream;
270
271 for (stream = 0; stream < 2; stream++) {
272 substream = pcm->streams[stream].substream;
273 if (!substream)
274 continue;
275
276 buf = &substream->dma_buffer;
277 if (!buf->area)
278 continue;
279 dma_free_coherent(NULL, buf->bytes, buf->area, 0);
280 buf->area = NULL;
281 }
282}
283
284static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
285
286static int bf5xx_pcm_tdm_new(struct snd_soc_pcm_runtime *rtd)
287{
288 struct snd_card *card = rtd->card->snd_card;
289 struct snd_pcm *pcm = rtd->pcm;
290 int ret = 0;
291
292 if (!card->dev->dma_mask)
293 card->dev->dma_mask = &bf5xx_pcm_dmamask;
294 if (!card->dev->coherent_dma_mask)
295 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
296
297 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
298 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
299 SNDRV_PCM_STREAM_PLAYBACK);
300 if (ret)
301 goto out;
302 }
303
304 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
305 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
306 SNDRV_PCM_STREAM_CAPTURE);
307 if (ret)
308 goto out;
309 }
310out:
311 return ret;
312}
313
314static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = {
315 .ops = &bf5xx_pcm_tdm_ops,
316 .pcm_new = bf5xx_pcm_tdm_new,
317 .pcm_free = bf5xx_pcm_free_dma_buffers,
318};
319
320static int bf5xx_soc_platform_probe(struct platform_device *pdev)
321{
322 return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform);
323}
324
325static int bf5xx_soc_platform_remove(struct platform_device *pdev)
326{
327 snd_soc_unregister_platform(&pdev->dev);
328 return 0;
329}
330
331static struct platform_driver bfin_tdm_driver = {
332 .driver = {
333 .name = "bfin-tdm-pcm-audio",
334 .owner = THIS_MODULE,
335 },
336
337 .probe = bf5xx_soc_platform_probe,
338 .remove = bf5xx_soc_platform_remove,
339};
340
341module_platform_driver(bfin_tdm_driver);
342
343MODULE_AUTHOR("Barry Song");
344MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module");
345MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.h b/sound/soc/blackfin/bf5xx-tdm-pcm.h
deleted file mode 100644
index 7f8cc01c4477..000000000000
--- a/sound/soc/blackfin/bf5xx-tdm-pcm.h
+++ /dev/null
@@ -1,18 +0,0 @@
1/*
2 * sound/soc/blackfin/bf5xx-tdm-pcm.h -- ALSA PCM interface for the Blackfin
3 *
4 * Copyright 2009 Analog Device Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef _BF5XX_TDM_PCM_H
12#define _BF5XX_TDM_PCM_H
13
14struct bf5xx_pcm_dma_params {
15 char *name; /* stream identifier */
16};
17
18#endif
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
deleted file mode 100644
index 69e9a3e935bd..000000000000
--- a/sound/soc/blackfin/bf5xx-tdm.c
+++ /dev/null
@@ -1,328 +0,0 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-tdm.c
3 * Author: Barry Song <Barry.Song@analog.com>
4 *
5 * Created: Thurs June 04 2009
6 * Description: Blackfin I2S(TDM) CPU DAI driver
7 * Even though TDM mode can be as part of I2S DAI, but there
8 * are so much difference in configuration and data flow,
9 * it's very ugly to integrate I2S and TDM into a module
10 *
11 * Modified:
12 * Copyright 2009 Analog Devices Inc.
13 *
14 * Bugs: Enter bugs at http://blackfin.uclinux.org/
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see the file COPYING, or write
28 * to the Free Software Foundation, Inc.,
29 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 */
31
32#include <linux/init.h>
33#include <linux/module.h>
34#include <linux/device.h>
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/initval.h>
39#include <sound/soc.h>
40
41#include <asm/irq.h>
42#include <asm/portmux.h>
43#include <linux/mutex.h>
44#include <linux/gpio.h>
45
46#include "bf5xx-sport.h"
47#include "bf5xx-tdm.h"
48
49static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai,
50 unsigned int fmt)
51{
52 int ret = 0;
53
54 /* interface format:support TDM,slave mode */
55 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
56 case SND_SOC_DAIFMT_DSP_A:
57 break;
58 default:
59 printk(KERN_ERR "%s: Unknown DAI format type\n", __func__);
60 ret = -EINVAL;
61 break;
62 }
63
64 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
65 case SND_SOC_DAIFMT_CBM_CFM:
66 break;
67 case SND_SOC_DAIFMT_CBS_CFS:
68 case SND_SOC_DAIFMT_CBM_CFS:
69 case SND_SOC_DAIFMT_CBS_CFM:
70 ret = -EINVAL;
71 break;
72 default:
73 printk(KERN_ERR "%s: Unknown DAI master type\n", __func__);
74 ret = -EINVAL;
75 break;
76 }
77
78 return ret;
79}
80
81static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream,
82 struct snd_pcm_hw_params *params,
83 struct snd_soc_dai *dai)
84{
85 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
86 struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data;
87 int ret = 0;
88
89 bf5xx_tdm->tcr2 &= ~0x1f;
90 bf5xx_tdm->rcr2 &= ~0x1f;
91 switch (params_format(params)) {
92 case SNDRV_PCM_FORMAT_S32_LE:
93 bf5xx_tdm->tcr2 |= 31;
94 bf5xx_tdm->rcr2 |= 31;
95 sport_handle->wdsize = 4;
96 break;
97 /* at present, we only support 32bit transfer */
98 default:
99 pr_err("not supported PCM format yet\n");
100 return -EINVAL;
101 break;
102 }
103
104 if (!bf5xx_tdm->configured) {
105 /*
106 * TX and RX are not independent,they are enabled at the
107 * same time, even if only one side is running. So, we
108 * need to configure both of them at the time when the first
109 * stream is opened.
110 *
111 * CPU DAI:slave mode.
112 */
113 ret = sport_config_rx(sport_handle, bf5xx_tdm->rcr1,
114 bf5xx_tdm->rcr2, 0, 0);
115 if (ret) {
116 pr_err("SPORT is busy!\n");
117 return -EBUSY;
118 }
119
120 ret = sport_config_tx(sport_handle, bf5xx_tdm->tcr1,
121 bf5xx_tdm->tcr2, 0, 0);
122 if (ret) {
123 pr_err("SPORT is busy!\n");
124 return -EBUSY;
125 }
126
127 bf5xx_tdm->configured = 1;
128 }
129
130 return 0;
131}
132
133static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream,
134 struct snd_soc_dai *dai)
135{
136 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
137 struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data;
138
139 /* No active stream, SPORT is allowed to be configured again. */
140 if (!dai->active)
141 bf5xx_tdm->configured = 0;
142}
143
144static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai,
145 unsigned int tx_num, unsigned int *tx_slot,
146 unsigned int rx_num, unsigned int *rx_slot)
147{
148 struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai);
149 struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data;
150 int i;
151 unsigned int slot;
152 unsigned int tx_mapped = 0, rx_mapped = 0;
153
154 if ((tx_num > BFIN_TDM_DAI_MAX_SLOTS) ||
155 (rx_num > BFIN_TDM_DAI_MAX_SLOTS))
156 return -EINVAL;
157
158 for (i = 0; i < tx_num; i++) {
159 slot = tx_slot[i];
160 if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
161 (!(tx_mapped & (1 << slot)))) {
162 bf5xx_tdm->tx_map[i] = slot;
163 tx_mapped |= 1 << slot;
164 } else
165 return -EINVAL;
166 }
167 for (i = 0; i < rx_num; i++) {
168 slot = rx_slot[i];
169 if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
170 (!(rx_mapped & (1 << slot)))) {
171 bf5xx_tdm->rx_map[i] = slot;
172 rx_mapped |= 1 << slot;
173 } else
174 return -EINVAL;
175 }
176
177 return 0;
178}
179
180#ifdef CONFIG_PM
181static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
182{
183 struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
184
185 if (dai->playback_active)
186 sport_tx_stop(sport);
187 if (dai->capture_active)
188 sport_rx_stop(sport);
189
190 /* isolate sync/clock pins from codec while sports resume */
191 peripheral_free_list(sport->pin_req);
192
193 return 0;
194}
195
196static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
197{
198 int ret;
199 struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
200
201 ret = sport_set_multichannel(sport, 8, 0xFF, 1);
202 if (ret) {
203 pr_err("SPORT is busy!\n");
204 ret = -EBUSY;
205 }
206
207 ret = sport_config_rx(sport, 0, 0x1F, 0, 0);
208 if (ret) {
209 pr_err("SPORT is busy!\n");
210 ret = -EBUSY;
211 }
212
213 ret = sport_config_tx(sport, 0, 0x1F, 0, 0);
214 if (ret) {
215 pr_err("SPORT is busy!\n");
216 ret = -EBUSY;
217 }
218
219 peripheral_request_list(sport->pin_req, "soc-audio");
220
221 return 0;
222}
223
224#else
225#define bf5xx_tdm_suspend NULL
226#define bf5xx_tdm_resume NULL
227#endif
228
229static const struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
230 .hw_params = bf5xx_tdm_hw_params,
231 .set_fmt = bf5xx_tdm_set_dai_fmt,
232 .shutdown = bf5xx_tdm_shutdown,
233 .set_channel_map = bf5xx_tdm_set_channel_map,
234};
235
236static struct snd_soc_dai_driver bf5xx_tdm_dai = {
237 .suspend = bf5xx_tdm_suspend,
238 .resume = bf5xx_tdm_resume,
239 .playback = {
240 .channels_min = 2,
241 .channels_max = 8,
242 .rates = SNDRV_PCM_RATE_48000,
243 .formats = SNDRV_PCM_FMTBIT_S32_LE,},
244 .capture = {
245 .channels_min = 2,
246 .channels_max = 8,
247 .rates = SNDRV_PCM_RATE_48000,
248 .formats = SNDRV_PCM_FMTBIT_S32_LE,},
249 .ops = &bf5xx_tdm_dai_ops,
250};
251
252static const struct snd_soc_component_driver bf5xx_tdm_component = {
253 .name = "bf5xx-tdm",
254};
255
256static int bfin_tdm_probe(struct platform_device *pdev)
257{
258 struct sport_device *sport_handle;
259 int ret;
260
261 /* configure SPORT for TDM */
262 sport_handle = sport_init(pdev, 4, 8 * sizeof(u32),
263 sizeof(struct bf5xx_tdm_port));
264 if (!sport_handle)
265 return -ENODEV;
266
267 /* SPORT works in TDM mode */
268 ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1);
269 if (ret) {
270 pr_err("SPORT is busy!\n");
271 ret = -EBUSY;
272 goto sport_config_err;
273 }
274
275 ret = sport_config_rx(sport_handle, 0, 0x1F, 0, 0);
276 if (ret) {
277 pr_err("SPORT is busy!\n");
278 ret = -EBUSY;
279 goto sport_config_err;
280 }
281
282 ret = sport_config_tx(sport_handle, 0, 0x1F, 0, 0);
283 if (ret) {
284 pr_err("SPORT is busy!\n");
285 ret = -EBUSY;
286 goto sport_config_err;
287 }
288
289 ret = snd_soc_register_component(&pdev->dev, &bf5xx_tdm_component,
290 &bf5xx_tdm_dai, 1);
291 if (ret) {
292 pr_err("Failed to register DAI: %d\n", ret);
293 goto sport_config_err;
294 }
295
296 return 0;
297
298sport_config_err:
299 sport_done(sport_handle);
300 return ret;
301}
302
303static int bfin_tdm_remove(struct platform_device *pdev)
304{
305 struct sport_device *sport_handle = platform_get_drvdata(pdev);
306
307 snd_soc_unregister_component(&pdev->dev);
308 sport_done(sport_handle);
309
310 return 0;
311}
312
313static struct platform_driver bfin_tdm_driver = {
314 .probe = bfin_tdm_probe,
315 .remove = bfin_tdm_remove,
316 .driver = {
317 .name = "bfin-tdm",
318 .owner = THIS_MODULE,
319 },
320};
321
322module_platform_driver(bfin_tdm_driver);
323
324/* Module information */
325MODULE_AUTHOR("Barry Song");
326MODULE_DESCRIPTION("TDM driver for ADI Blackfin");
327MODULE_LICENSE("GPL");
328
diff --git a/sound/soc/blackfin/bf5xx-tdm.h b/sound/soc/blackfin/bf5xx-tdm.h
deleted file mode 100644
index e986a3ea3315..000000000000
--- a/sound/soc/blackfin/bf5xx-tdm.h
+++ /dev/null
@@ -1,23 +0,0 @@
1/*
2 * sound/soc/blackfin/bf5xx-tdm.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _BF5XX_TDM_H
10#define _BF5XX_TDM_H
11
12#define BFIN_TDM_DAI_MAX_SLOTS 8
13struct bf5xx_tdm_port {
14 u16 tcr1;
15 u16 rcr1;
16 u16 tcr2;
17 u16 rcr2;
18 unsigned int tx_map[BFIN_TDM_DAI_MAX_SLOTS];
19 unsigned int rx_map[BFIN_TDM_DAI_MAX_SLOTS];
20 int configured;
21};
22
23#endif
diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig
index 88143db7e753..2c20f01e1f7e 100644
--- a/sound/soc/cirrus/Kconfig
+++ b/sound/soc/cirrus/Kconfig
@@ -1,7 +1,7 @@
1config SND_EP93XX_SOC 1config SND_EP93XX_SOC
2 tristate "SoC Audio support for the Cirrus Logic EP93xx series" 2 tristate "SoC Audio support for the Cirrus Logic EP93xx series"
3 depends on ARCH_EP93XX && SND_SOC 3 depends on ARCH_EP93XX && SND_SOC
4 select SND_SOC_DMAENGINE_PCM 4 select SND_SOC_GENERIC_DMAENGINE_PCM
5 help 5 help
6 Say Y or M if you want to add support for codecs attached to 6 Say Y or M if you want to add support for codecs attached to
7 the EP93xx I2S or AC97 interfaces. 7 the EP93xx I2S or AC97 interfaces.
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c
index 7798fbd5e81d..3f4f88877c84 100644
--- a/sound/soc/cirrus/ep93xx-ac97.c
+++ b/sound/soc/cirrus/ep93xx-ac97.c
@@ -314,22 +314,15 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
314 return 0; 314 return 0;
315} 315}
316 316
317static int ep93xx_ac97_startup(struct snd_pcm_substream *substream, 317static int ep93xx_ac97_dai_probe(struct snd_soc_dai *dai)
318 struct snd_soc_dai *dai)
319{ 318{
320 struct ep93xx_dma_data *dma_data; 319 dai->playback_dma_data = &ep93xx_ac97_pcm_out;
320 dai->capture_dma_data = &ep93xx_ac97_pcm_in;
321 321
322 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
323 dma_data = &ep93xx_ac97_pcm_out;
324 else
325 dma_data = &ep93xx_ac97_pcm_in;
326
327 snd_soc_dai_set_dma_data(dai, substream, dma_data);
328 return 0; 322 return 0;
329} 323}
330 324
331static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = { 325static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
332 .startup = ep93xx_ac97_startup,
333 .trigger = ep93xx_ac97_trigger, 326 .trigger = ep93xx_ac97_trigger,
334}; 327};
335 328
@@ -337,6 +330,7 @@ static struct snd_soc_dai_driver ep93xx_ac97_dai = {
337 .name = "ep93xx-ac97", 330 .name = "ep93xx-ac97",
338 .id = 0, 331 .id = 0,
339 .ac97_control = 1, 332 .ac97_control = 1,
333 .probe = ep93xx_ac97_dai_probe,
340 .playback = { 334 .playback = {
341 .stream_name = "AC97 Playback", 335 .stream_name = "AC97 Playback",
342 .channels_min = 2, 336 .channels_min = 2,
@@ -403,7 +397,6 @@ static int ep93xx_ac97_probe(struct platform_device *pdev)
403 return 0; 397 return 0;
404 398
405fail: 399fail:
406 platform_set_drvdata(pdev, NULL);
407 ep93xx_ac97_info = NULL; 400 ep93xx_ac97_info = NULL;
408 dev_set_drvdata(&pdev->dev, NULL); 401 dev_set_drvdata(&pdev->dev, NULL);
409 return ret; 402 return ret;
@@ -418,7 +411,6 @@ static int ep93xx_ac97_remove(struct platform_device *pdev)
418 /* disable the AC97 controller */ 411 /* disable the AC97 controller */
419 ep93xx_ac97_write_reg(info, AC97GCR, 0); 412 ep93xx_ac97_write_reg(info, AC97GCR, 0);
420 413
421 platform_set_drvdata(pdev, NULL);
422 ep93xx_ac97_info = NULL; 414 ep93xx_ac97_info = NULL;
423 dev_set_drvdata(&pdev->dev, NULL); 415 dev_set_drvdata(&pdev->dev, NULL);
424 416
diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c
index 5c1102e9e159..17ad70bca9fe 100644
--- a/sound/soc/cirrus/ep93xx-i2s.c
+++ b/sound/soc/cirrus/ep93xx-i2s.c
@@ -60,11 +60,10 @@ struct ep93xx_i2s_info {
60 struct clk *mclk; 60 struct clk *mclk;
61 struct clk *sclk; 61 struct clk *sclk;
62 struct clk *lrclk; 62 struct clk *lrclk;
63 struct ep93xx_dma_data *dma_data;
64 void __iomem *regs; 63 void __iomem *regs;
65}; 64};
66 65
67struct ep93xx_dma_data ep93xx_i2s_dma_data[] = { 66static struct ep93xx_dma_data ep93xx_i2s_dma_data[] = {
68 [SNDRV_PCM_STREAM_PLAYBACK] = { 67 [SNDRV_PCM_STREAM_PLAYBACK] = {
69 .name = "i2s-pcm-out", 68 .name = "i2s-pcm-out",
70 .port = EP93XX_DMA_I2S1, 69 .port = EP93XX_DMA_I2S1,
@@ -139,15 +138,11 @@ static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream)
139 } 138 }
140} 139}
141 140
142static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, 141static int ep93xx_i2s_dai_probe(struct snd_soc_dai *dai)
143 struct snd_soc_dai *dai)
144{ 142{
145 struct snd_soc_pcm_runtime *rtd = substream->private_data; 143 dai->playback_dma_data = &ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_PLAYBACK];
146 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); 144 dai->capture_dma_data = &ep93xx_i2s_dma_data[SNDRV_PCM_STREAM_CAPTURE];
147 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
148 145
149 snd_soc_dai_set_dma_data(cpu_dai, substream,
150 &info->dma_data[substream->stream]);
151 return 0; 146 return 0;
152} 147}
153 148
@@ -338,7 +333,6 @@ static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
338#endif 333#endif
339 334
340static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { 335static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
341 .startup = ep93xx_i2s_startup,
342 .shutdown = ep93xx_i2s_shutdown, 336 .shutdown = ep93xx_i2s_shutdown,
343 .hw_params = ep93xx_i2s_hw_params, 337 .hw_params = ep93xx_i2s_hw_params,
344 .set_sysclk = ep93xx_i2s_set_sysclk, 338 .set_sysclk = ep93xx_i2s_set_sysclk,
@@ -349,6 +343,7 @@ static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
349 343
350static struct snd_soc_dai_driver ep93xx_i2s_dai = { 344static struct snd_soc_dai_driver ep93xx_i2s_dai = {
351 .symmetric_rates= 1, 345 .symmetric_rates= 1,
346 .probe = ep93xx_i2s_dai_probe,
352 .suspend = ep93xx_i2s_suspend, 347 .suspend = ep93xx_i2s_suspend,
353 .resume = ep93xx_i2s_resume, 348 .resume = ep93xx_i2s_resume,
354 .playback = { 349 .playback = {
@@ -407,7 +402,6 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
407 } 402 }
408 403
409 dev_set_drvdata(&pdev->dev, info); 404 dev_set_drvdata(&pdev->dev, info);
410 info->dma_data = ep93xx_i2s_dma_data;
411 405
412 err = snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component, 406 err = snd_soc_register_component(&pdev->dev, &ep93xx_i2s_component,
413 &ep93xx_i2s_dai, 1); 407 &ep93xx_i2s_dai, 1);
diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c
index 488032690378..0e9f56e0d4b2 100644
--- a/sound/soc/cirrus/ep93xx-pcm.c
+++ b/sound/soc/cirrus/ep93xx-pcm.c
@@ -14,20 +14,14 @@
14 14
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/device.h> 17#include <linux/platform_device.h>
18#include <linux/slab.h>
19#include <linux/dmaengine.h> 18#include <linux/dmaengine.h>
20#include <linux/dma-mapping.h>
21 19
22#include <sound/core.h>
23#include <sound/pcm.h> 20#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h> 21#include <sound/soc.h>
26#include <sound/dmaengine_pcm.h> 22#include <sound/dmaengine_pcm.h>
27 23
28#include <linux/platform_data/dma-ep93xx.h> 24#include <linux/platform_data/dma-ep93xx.h>
29#include <mach/hardware.h>
30#include <mach/ep93xx-regs.h>
31 25
32static const struct snd_pcm_hardware ep93xx_pcm_hardware = { 26static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
33 .info = (SNDRV_PCM_INFO_MMAP | 27 .info = (SNDRV_PCM_INFO_MMAP |
@@ -63,134 +57,24 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
63 return false; 57 return false;
64} 58}
65 59
66static int ep93xx_pcm_open(struct snd_pcm_substream *substream) 60static const struct snd_dmaengine_pcm_config ep93xx_dmaengine_pcm_config = {
67{ 61 .pcm_hardware = &ep93xx_pcm_hardware,
68 struct snd_soc_pcm_runtime *rtd = substream->private_data; 62 .compat_filter_fn = ep93xx_pcm_dma_filter,
69 63 .prealloc_buffer_size = 131072,
70 snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
71
72 return snd_dmaengine_pcm_open_request_chan(substream,
73 ep93xx_pcm_dma_filter,
74 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
75}
76
77static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
78 struct snd_pcm_hw_params *params)
79{
80 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
81
82 return 0;
83}
84
85static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
86{
87 snd_pcm_set_runtime_buffer(substream, NULL);
88 return 0;
89}
90
91static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
92 struct vm_area_struct *vma)
93{
94 struct snd_pcm_runtime *runtime = substream->runtime;
95
96 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
97 runtime->dma_area,
98 runtime->dma_addr,
99 runtime->dma_bytes);
100}
101
102static struct snd_pcm_ops ep93xx_pcm_ops = {
103 .open = ep93xx_pcm_open,
104 .close = snd_dmaengine_pcm_close_release_chan,
105 .ioctl = snd_pcm_lib_ioctl,
106 .hw_params = ep93xx_pcm_hw_params,
107 .hw_free = ep93xx_pcm_hw_free,
108 .trigger = snd_dmaengine_pcm_trigger,
109 .pointer = snd_dmaengine_pcm_pointer_no_residue,
110 .mmap = ep93xx_pcm_mmap,
111};
112
113static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
114{
115 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
116 struct snd_dma_buffer *buf = &substream->dma_buffer;
117 size_t size = ep93xx_pcm_hardware.buffer_bytes_max;
118
119 buf->dev.type = SNDRV_DMA_TYPE_DEV;
120 buf->dev.dev = pcm->card->dev;
121 buf->private_data = NULL;
122 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
123 &buf->addr, GFP_KERNEL);
124 buf->bytes = size;
125
126 return (buf->area == NULL) ? -ENOMEM : 0;
127}
128
129static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
130{
131 struct snd_pcm_substream *substream;
132 struct snd_dma_buffer *buf;
133 int stream;
134
135 for (stream = 0; stream < 2; stream++) {
136 substream = pcm->streams[stream].substream;
137 if (!substream)
138 continue;
139
140 buf = &substream->dma_buffer;
141 if (!buf->area)
142 continue;
143
144 dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area,
145 buf->addr);
146 buf->area = NULL;
147 }
148}
149
150static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32);
151
152static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
153{
154 struct snd_card *card = rtd->card->snd_card;
155 struct snd_pcm *pcm = rtd->pcm;
156 int ret = 0;
157
158 if (!card->dev->dma_mask)
159 card->dev->dma_mask = &ep93xx_pcm_dmamask;
160 if (!card->dev->coherent_dma_mask)
161 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
162
163 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
164 ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
165 SNDRV_PCM_STREAM_PLAYBACK);
166 if (ret)
167 return ret;
168 }
169
170 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
171 ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
172 SNDRV_PCM_STREAM_CAPTURE);
173 if (ret)
174 return ret;
175 }
176
177 return 0;
178}
179
180static struct snd_soc_platform_driver ep93xx_soc_platform = {
181 .ops = &ep93xx_pcm_ops,
182 .pcm_new = &ep93xx_pcm_new,
183 .pcm_free = &ep93xx_pcm_free_dma_buffers,
184}; 64};
185 65
186static int ep93xx_soc_platform_probe(struct platform_device *pdev) 66static int ep93xx_soc_platform_probe(struct platform_device *pdev)
187{ 67{
188 return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform); 68 return snd_dmaengine_pcm_register(&pdev->dev,
69 &ep93xx_dmaengine_pcm_config,
70 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
71 SND_DMAENGINE_PCM_FLAG_NO_DT |
72 SND_DMAENGINE_PCM_FLAG_COMPAT);
189} 73}
190 74
191static int ep93xx_soc_platform_remove(struct platform_device *pdev) 75static int ep93xx_soc_platform_remove(struct platform_device *pdev)
192{ 76{
193 snd_soc_unregister_platform(&pdev->dev); 77 snd_dmaengine_pcm_unregister(&pdev->dev);
194 return 0; 78 return 0;
195} 79}
196 80
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index 60159c07448d..1382f3f3f4bf 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -1444,7 +1444,7 @@ static int pm860x_codec_probe(struct platform_device *pdev)
1444 res = platform_get_resource(pdev, IORESOURCE_IRQ, i); 1444 res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
1445 if (!res) { 1445 if (!res) {
1446 dev_err(&pdev->dev, "Failed to get IRQ resources\n"); 1446 dev_err(&pdev->dev, "Failed to get IRQ resources\n");
1447 goto out; 1447 return -EINVAL;
1448 } 1448 }
1449 pm860x->irq[i] = res->start + chip->irq_base; 1449 pm860x->irq[i] = res->start + chip->irq_base;
1450 strncpy(pm860x->name[i], res->name, MAX_NAME_LEN); 1450 strncpy(pm860x->name[i], res->name, MAX_NAME_LEN);
@@ -1454,19 +1454,14 @@ static int pm860x_codec_probe(struct platform_device *pdev)
1454 pm860x_dai, ARRAY_SIZE(pm860x_dai)); 1454 pm860x_dai, ARRAY_SIZE(pm860x_dai));
1455 if (ret) { 1455 if (ret) {
1456 dev_err(&pdev->dev, "Failed to register codec\n"); 1456 dev_err(&pdev->dev, "Failed to register codec\n");
1457 goto out; 1457 return -EINVAL;
1458 } 1458 }
1459 return ret; 1459 return ret;
1460
1461out:
1462 platform_set_drvdata(pdev, NULL);
1463 return -EINVAL;
1464} 1460}
1465 1461
1466static int pm860x_codec_remove(struct platform_device *pdev) 1462static int pm860x_codec_remove(struct platform_device *pdev)
1467{ 1463{
1468 snd_soc_unregister_codec(&pdev->dev); 1464 snd_soc_unregister_codec(&pdev->dev);
1469 platform_set_drvdata(pdev, NULL);
1470 return 0; 1465 return 0;
1471} 1466}
1472 1467
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 2f45f00e31b0..badb6fbacaa6 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -19,7 +19,7 @@ config SND_SOC_ALL_CODECS
19 select SND_SOC_AD1980 if SND_SOC_AC97_BUS 19 select SND_SOC_AD1980 if SND_SOC_AC97_BUS
20 select SND_SOC_AD73311 20 select SND_SOC_AD73311
21 select SND_SOC_ADAU1373 if I2C 21 select SND_SOC_ADAU1373 if I2C
22 select SND_SOC_ADAV80X 22 select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI
23 select SND_SOC_ADS117X 23 select SND_SOC_ADS117X
24 select SND_SOC_AK4104 if SPI_MASTER 24 select SND_SOC_AK4104 if SPI_MASTER
25 select SND_SOC_AK4535 if I2C 25 select SND_SOC_AK4535 if I2C
@@ -40,7 +40,7 @@ config SND_SOC_ALL_CODECS
40 select SND_SOC_DA7213 if I2C 40 select SND_SOC_DA7213 if I2C
41 select SND_SOC_DA732X if I2C 41 select SND_SOC_DA732X if I2C
42 select SND_SOC_DA9055 if I2C 42 select SND_SOC_DA9055 if I2C
43 select SND_SOC_DFBMCS320 43 select SND_SOC_BT_SCO
44 select SND_SOC_ISABELLE if I2C 44 select SND_SOC_ISABELLE if I2C
45 select SND_SOC_JZ4740_CODEC 45 select SND_SOC_JZ4740_CODEC
46 select SND_SOC_LM4857 if I2C 46 select SND_SOC_LM4857 if I2C
@@ -53,13 +53,15 @@ config SND_SOC_ALL_CODECS
53 select SND_SOC_MAX9877 if I2C 53 select SND_SOC_MAX9877 if I2C
54 select SND_SOC_MC13783 if MFD_MC13XXX 54 select SND_SOC_MC13783 if MFD_MC13XXX
55 select SND_SOC_ML26124 if I2C 55 select SND_SOC_ML26124 if I2C
56 select SND_SOC_OMAP_HDMI_CODEC if OMAP4_DSS_HDMI 56 select SND_SOC_HDMI_CODEC
57 select SND_SOC_PCM3008 57 select SND_SOC_PCM3008
58 select SND_SOC_RT5631 if I2C 58 select SND_SOC_RT5631 if I2C
59 select SND_SOC_RT5640 if I2C
59 select SND_SOC_SGTL5000 if I2C 60 select SND_SOC_SGTL5000 if I2C
60 select SND_SOC_SI476X if MFD_SI476X_CORE 61 select SND_SOC_SI476X if MFD_SI476X_CORE
61 select SND_SOC_SN95031 if INTEL_SCU_IPC 62 select SND_SOC_SN95031 if INTEL_SCU_IPC
62 select SND_SOC_SPDIF 63 select SND_SOC_SPDIF
64 select SND_SOC_SSM2518 if I2C
63 select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI 65 select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
64 select SND_SOC_STA32X if I2C 66 select SND_SOC_STA32X if I2C
65 select SND_SOC_STA529 if I2C 67 select SND_SOC_STA529 if I2C
@@ -263,7 +265,7 @@ config SND_SOC_DA732X
263config SND_SOC_DA9055 265config SND_SOC_DA9055
264 tristate 266 tristate
265 267
266config SND_SOC_DFBMCS320 268config SND_SOC_BT_SCO
267 tristate 269 tristate
268 270
269config SND_SOC_DMIC 271config SND_SOC_DMIC
@@ -287,7 +289,7 @@ config SND_SOC_MAX98095
287config SND_SOC_MAX9850 289config SND_SOC_MAX9850
288 tristate 290 tristate
289 291
290config SND_SOC_OMAP_HDMI_CODEC 292config SND_SOC_HDMI_CODEC
291 tristate 293 tristate
292 294
293config SND_SOC_PCM3008 295config SND_SOC_PCM3008
@@ -296,6 +298,9 @@ config SND_SOC_PCM3008
296config SND_SOC_RT5631 298config SND_SOC_RT5631
297 tristate 299 tristate
298 300
301config SND_SOC_RT5640
302 tristate
303
299#Freescale sgtl5000 codec 304#Freescale sgtl5000 codec
300config SND_SOC_SGTL5000 305config SND_SOC_SGTL5000
301 tristate 306 tristate
@@ -313,6 +318,9 @@ config SND_SOC_SN95031
313config SND_SOC_SPDIF 318config SND_SOC_SPDIF
314 tristate 319 tristate
315 320
321config SND_SOC_SSM2518
322 tristate
323
316config SND_SOC_SSM2602 324config SND_SOC_SSM2602
317 tristate 325 tristate
318 326
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index b9e41c9a1f4c..70fd8066f546 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -27,7 +27,7 @@ snd-soc-da7210-objs := da7210.o
27snd-soc-da7213-objs := da7213.o 27snd-soc-da7213-objs := da7213.o
28snd-soc-da732x-objs := da732x.o 28snd-soc-da732x-objs := da732x.o
29snd-soc-da9055-objs := da9055.o 29snd-soc-da9055-objs := da9055.o
30snd-soc-dfbmcs320-objs := dfbmcs320.o 30snd-soc-bt-sco-objs := bt-sco.o
31snd-soc-dmic-objs := dmic.o 31snd-soc-dmic-objs := dmic.o
32snd-soc-isabelle-objs := isabelle.o 32snd-soc-isabelle-objs := isabelle.o
33snd-soc-jz4740-codec-objs := jz4740.o 33snd-soc-jz4740-codec-objs := jz4740.o
@@ -41,17 +41,19 @@ snd-soc-max98095-objs := max98095.o
41snd-soc-max9850-objs := max9850.o 41snd-soc-max9850-objs := max9850.o
42snd-soc-mc13783-objs := mc13783.o 42snd-soc-mc13783-objs := mc13783.o
43snd-soc-ml26124-objs := ml26124.o 43snd-soc-ml26124-objs := ml26124.o
44snd-soc-omap-hdmi-codec-objs := omap-hdmi.o 44snd-soc-hdmi-codec-objs := hdmi.o
45snd-soc-pcm3008-objs := pcm3008.o 45snd-soc-pcm3008-objs := pcm3008.o
46snd-soc-rt5631-objs := rt5631.o 46snd-soc-rt5631-objs := rt5631.o
47snd-soc-rt5640-objs := rt5640.o
47snd-soc-sgtl5000-objs := sgtl5000.o 48snd-soc-sgtl5000-objs := sgtl5000.o
48snd-soc-alc5623-objs := alc5623.o 49snd-soc-alc5623-objs := alc5623.o
49snd-soc-alc5632-objs := alc5632.o 50snd-soc-alc5632-objs := alc5632.o
50snd-soc-sigmadsp-objs := sigmadsp.o 51snd-soc-sigmadsp-objs := sigmadsp.o
51snd-soc-si476x-objs := si476x.o 52snd-soc-si476x-objs := si476x.o
52snd-soc-sn95031-objs := sn95031.o 53snd-soc-sn95031-objs := sn95031.o
53snd-soc-spdif-tx-objs := spdif_transciever.o 54snd-soc-spdif-tx-objs := spdif_transmitter.o
54snd-soc-spdif-rx-objs := spdif_receiver.o 55snd-soc-spdif-rx-objs := spdif_receiver.o
56snd-soc-ssm2518-objs := ssm2518.o
55snd-soc-ssm2602-objs := ssm2602.o 57snd-soc-ssm2602-objs := ssm2602.o
56snd-soc-sta32x-objs := sta32x.o 58snd-soc-sta32x-objs := sta32x.o
57snd-soc-sta529-objs := sta529.o 59snd-soc-sta529-objs := sta529.o
@@ -154,7 +156,7 @@ obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
154obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o 156obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o
155obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o 157obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o
156obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o 158obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o
157obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o 159obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o
158obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o 160obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
159obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o 161obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
160obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o 162obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
@@ -168,14 +170,16 @@ obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
168obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o 170obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
169obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o 171obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
170obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o 172obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
171obj-$(CONFIG_SND_SOC_OMAP_HDMI_CODEC) += snd-soc-omap-hdmi-codec.o 173obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
172obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o 174obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
173obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o 175obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
176obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
174obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o 177obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
175obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o 178obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
176obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o 179obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o
177obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o 180obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
178obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o 181obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
182obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o
179obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o 183obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
180obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o 184obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o
181obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o 185obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index a153b168129b..b8ba0adacfce 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -1496,6 +1496,12 @@ static const char * const enum_ad_to_slot_map[] = {"AD_OUT1",
1496 "AD_OUT7", 1496 "AD_OUT7",
1497 "AD_OUT8", 1497 "AD_OUT8",
1498 "zeroes", 1498 "zeroes",
1499 "zeroes",
1500 "zeroes",
1501 "zeroes",
1502 "tristate",
1503 "tristate",
1504 "tristate",
1499 "tristate"}; 1505 "tristate"};
1500static SOC_ENUM_SINGLE_DECL(soc_enum_adslot0map, 1506static SOC_ENUM_SINGLE_DECL(soc_enum_adslot0map,
1501 AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_EVEN_SHIFT, 1507 AB8500_ADSLOTSEL1, AB8500_ADSLOTSELX_EVEN_SHIFT,
@@ -2230,7 +2236,7 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
2230 int slots, int slot_width) 2236 int slots, int slot_width)
2231{ 2237{
2232 struct snd_soc_codec *codec = dai->codec; 2238 struct snd_soc_codec *codec = dai->codec;
2233 unsigned int val, mask, slots_active; 2239 unsigned int val, mask, slot, slots_active;
2234 2240
2235 mask = BIT(AB8500_DIGIFCONF2_IF0WL0) | 2241 mask = BIT(AB8500_DIGIFCONF2_IF0WL0) |
2236 BIT(AB8500_DIGIFCONF2_IF0WL1); 2242 BIT(AB8500_DIGIFCONF2_IF0WL1);
@@ -2286,27 +2292,34 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
2286 snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val); 2292 snd_soc_update_bits(codec, AB8500_DIGIFCONF1, mask, val);
2287 2293
2288 /* Setup TDM DA according to active tx slots */ 2294 /* Setup TDM DA according to active tx slots */
2295
2296 if (tx_mask & ~0xff)
2297 return -EINVAL;
2298
2289 mask = AB8500_DASLOTCONFX_SLTODAX_MASK; 2299 mask = AB8500_DASLOTCONFX_SLTODAX_MASK;
2300 tx_mask = tx_mask << AB8500_DA_DATA0_OFFSET;
2290 slots_active = hweight32(tx_mask); 2301 slots_active = hweight32(tx_mask);
2302
2291 dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__, 2303 dev_dbg(dai->codec->dev, "%s: Slots, active, TX: %d\n", __func__,
2292 slots_active); 2304 slots_active);
2305
2293 switch (slots_active) { 2306 switch (slots_active) {
2294 case 0: 2307 case 0:
2295 break; 2308 break;
2296 case 1: 2309 case 1:
2297 /* Slot 9 -> DA_IN1 & DA_IN3 */ 2310 slot = find_first_bit((unsigned long *)&tx_mask, 32);
2298 snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 11); 2311 snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot);
2299 snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 11); 2312 snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot);
2300 snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11); 2313 snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot);
2301 snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11); 2314 snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot);
2302 break; 2315 break;
2303 case 2: 2316 case 2:
2304 /* Slot 9 -> DA_IN1 & DA_IN3, Slot 11 -> DA_IN2 & DA_IN4 */ 2317 slot = find_first_bit((unsigned long *)&tx_mask, 32);
2305 snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, 9); 2318 snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot);
2306 snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, 9); 2319 snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot);
2307 snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, 11); 2320 slot = find_next_bit((unsigned long *)&tx_mask, 32, slot + 1);
2308 snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, 11); 2321 snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot);
2309 2322 snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot);
2310 break; 2323 break;
2311 case 8: 2324 case 8:
2312 dev_dbg(dai->codec->dev, 2325 dev_dbg(dai->codec->dev,
@@ -2321,25 +2334,36 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
2321 } 2334 }
2322 2335
2323 /* Setup TDM AD according to active RX-slots */ 2336 /* Setup TDM AD according to active RX-slots */
2337
2338 if (rx_mask & ~0xff)
2339 return -EINVAL;
2340
2341 rx_mask = rx_mask << AB8500_AD_DATA0_OFFSET;
2324 slots_active = hweight32(rx_mask); 2342 slots_active = hweight32(rx_mask);
2343
2325 dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__, 2344 dev_dbg(dai->codec->dev, "%s: Slots, active, RX: %d\n", __func__,
2326 slots_active); 2345 slots_active);
2346
2327 switch (slots_active) { 2347 switch (slots_active) {
2328 case 0: 2348 case 0:
2329 break; 2349 break;
2330 case 1: 2350 case 1:
2331 /* AD_OUT3 -> slot 0 & 1 */ 2351 slot = find_first_bit((unsigned long *)&rx_mask, 32);
2332 snd_soc_update_bits(codec, AB8500_ADSLOTSEL1, AB8500_MASK_ALL, 2352 snd_soc_update_bits(codec, AB8500_ADSLOTSEL(slot),
2333 AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN | 2353 AB8500_MASK_SLOT(slot),
2334 AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD); 2354 AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot));
2335 break; 2355 break;
2336 case 2: 2356 case 2:
2337 /* AD_OUT3 -> slot 0, AD_OUT2 -> slot 1 */ 2357 slot = find_first_bit((unsigned long *)&rx_mask, 32);
2338 snd_soc_update_bits(codec, 2358 snd_soc_update_bits(codec,
2339 AB8500_ADSLOTSEL1, 2359 AB8500_ADSLOTSEL(slot),
2340 AB8500_MASK_ALL, 2360 AB8500_MASK_SLOT(slot),
2341 AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN | 2361 AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot));
2342 AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD); 2362 slot = find_next_bit((unsigned long *)&rx_mask, 32, slot + 1);
2363 snd_soc_update_bits(codec,
2364 AB8500_ADSLOTSEL(slot),
2365 AB8500_MASK_SLOT(slot),
2366 AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT2, slot));
2343 break; 2367 break;
2344 case 8: 2368 case 8:
2345 dev_dbg(dai->codec->dev, 2369 dev_dbg(dai->codec->dev,
@@ -2356,6 +2380,11 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai,
2356 return 0; 2380 return 0;
2357} 2381}
2358 2382
2383static const struct snd_soc_dai_ops ab8500_codec_ops = {
2384 .set_fmt = ab8500_codec_set_dai_fmt,
2385 .set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
2386};
2387
2359static struct snd_soc_dai_driver ab8500_codec_dai[] = { 2388static struct snd_soc_dai_driver ab8500_codec_dai[] = {
2360 { 2389 {
2361 .name = "ab8500-codec-dai.0", 2390 .name = "ab8500-codec-dai.0",
@@ -2367,12 +2396,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
2367 .rates = AB8500_SUPPORTED_RATE, 2396 .rates = AB8500_SUPPORTED_RATE,
2368 .formats = AB8500_SUPPORTED_FMT, 2397 .formats = AB8500_SUPPORTED_FMT,
2369 }, 2398 },
2370 .ops = (struct snd_soc_dai_ops[]) { 2399 .ops = &ab8500_codec_ops,
2371 {
2372 .set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
2373 .set_fmt = ab8500_codec_set_dai_fmt,
2374 }
2375 },
2376 .symmetric_rates = 1 2400 .symmetric_rates = 1
2377 }, 2401 },
2378 { 2402 {
@@ -2385,12 +2409,7 @@ static struct snd_soc_dai_driver ab8500_codec_dai[] = {
2385 .rates = AB8500_SUPPORTED_RATE, 2409 .rates = AB8500_SUPPORTED_RATE,
2386 .formats = AB8500_SUPPORTED_FMT, 2410 .formats = AB8500_SUPPORTED_FMT,
2387 }, 2411 },
2388 .ops = (struct snd_soc_dai_ops[]) { 2412 .ops = &ab8500_codec_ops,
2389 {
2390 .set_tdm_slot = ab8500_codec_set_dai_tdm_slot,
2391 .set_fmt = ab8500_codec_set_dai_fmt,
2392 }
2393 },
2394 .symmetric_rates = 1 2413 .symmetric_rates = 1
2395 } 2414 }
2396}; 2415};
diff --git a/sound/soc/codecs/ab8500-codec.h b/sound/soc/codecs/ab8500-codec.h
index 306d0bc8455f..e2e54425d25e 100644
--- a/sound/soc/codecs/ab8500-codec.h
+++ b/sound/soc/codecs/ab8500-codec.h
@@ -24,6 +24,13 @@
24#define AB8500_SUPPORTED_RATE (SNDRV_PCM_RATE_48000) 24#define AB8500_SUPPORTED_RATE (SNDRV_PCM_RATE_48000)
25#define AB8500_SUPPORTED_FMT (SNDRV_PCM_FMTBIT_S16_LE) 25#define AB8500_SUPPORTED_FMT (SNDRV_PCM_FMTBIT_S16_LE)
26 26
27/* AB8500 interface slot offset definitions */
28
29#define AB8500_AD_DATA0_OFFSET 0
30#define AB8500_DA_DATA0_OFFSET 8
31#define AB8500_AD_DATA1_OFFSET 16
32#define AB8500_DA_DATA1_OFFSET 24
33
27/* AB8500 audio bank (0x0d) register definitions */ 34/* AB8500 audio bank (0x0d) register definitions */
28 35
29#define AB8500_POWERUP 0x00 36#define AB8500_POWERUP 0x00
@@ -73,6 +80,7 @@
73#define AB8500_ADSLOTSEL14 0x2C 80#define AB8500_ADSLOTSEL14 0x2C
74#define AB8500_ADSLOTSEL15 0x2D 81#define AB8500_ADSLOTSEL15 0x2D
75#define AB8500_ADSLOTSEL16 0x2E 82#define AB8500_ADSLOTSEL16 0x2E
83#define AB8500_ADSLOTSEL(slot) (AB8500_ADSLOTSEL1 + (slot >> 1))
76#define AB8500_ADSLOTHIZCTRL1 0x2F 84#define AB8500_ADSLOTHIZCTRL1 0x2F
77#define AB8500_ADSLOTHIZCTRL2 0x30 85#define AB8500_ADSLOTHIZCTRL2 0x30
78#define AB8500_ADSLOTHIZCTRL3 0x31 86#define AB8500_ADSLOTHIZCTRL3 0x31
@@ -144,6 +152,7 @@
144#define AB8500_CACHEREGNUM (AB8500_LAST_REG + 1) 152#define AB8500_CACHEREGNUM (AB8500_LAST_REG + 1)
145 153
146#define AB8500_MASK_ALL 0xFF 154#define AB8500_MASK_ALL 0xFF
155#define AB8500_MASK_SLOT(slot) ((slot & 1) ? 0xF0 : 0x0F)
147#define AB8500_MASK_NONE 0x00 156#define AB8500_MASK_NONE 0x00
148 157
149/* AB8500_POWERUP */ 158/* AB8500_POWERUP */
@@ -347,28 +356,21 @@
347#define AB8500_DIGIFCONF4_IF1WL0 0 356#define AB8500_DIGIFCONF4_IF1WL0 0
348 357
349/* AB8500_ADSLOTSELX */ 358/* AB8500_ADSLOTSELX */
350#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_ODD 0x00 359#define AB8500_AD_OUT1 0x0
351#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD 0x10 360#define AB8500_AD_OUT2 0x1
352#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD 0x20 361#define AB8500_AD_OUT3 0x2
353#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_ODD 0x30 362#define AB8500_AD_OUT4 0x3
354#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_ODD 0x40 363#define AB8500_AD_OUT5 0x4
355#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD 0x50 364#define AB8500_AD_OUT6 0x5
356#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_ODD 0x60 365#define AB8500_AD_OUT7 0x6
357#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_ODD 0x70 366#define AB8500_AD_OUT8 0x7
358#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_ODD 0x80 367#define AB8500_ZEROES 0x8
359#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_ODD 0xF0 368#define AB8500_TRISTATE 0xF
360#define AB8500_ADSLOTSELX_AD_OUT1_TO_SLOT_EVEN 0x00
361#define AB8500_ADSLOTSELX_AD_OUT2_TO_SLOT_EVEN 0x01
362#define AB8500_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN 0x02
363#define AB8500_ADSLOTSELX_AD_OUT4_TO_SLOT_EVEN 0x03
364#define AB8500_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN 0x04
365#define AB8500_ADSLOTSELX_AD_OUT6_TO_SLOT_EVEN 0x05
366#define AB8500_ADSLOTSELX_AD_OUT7_TO_SLOT_EVEN 0x06
367#define AB8500_ADSLOTSELX_AD_OUT8_TO_SLOT_EVEN 0x07
368#define AB8500_ADSLOTSELX_ZEROES_TO_SLOT_EVEN 0x08
369#define AB8500_ADSLOTSELX_TRISTATE_TO_SLOT_EVEN 0x0F
370#define AB8500_ADSLOTSELX_EVEN_SHIFT 0 369#define AB8500_ADSLOTSELX_EVEN_SHIFT 0
371#define AB8500_ADSLOTSELX_ODD_SHIFT 4 370#define AB8500_ADSLOTSELX_ODD_SHIFT 4
371#define AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(out, slot) \
372 ((out) << (((slot) & 1) ? \
373 AB8500_ADSLOTSELX_ODD_SHIFT : AB8500_ADSLOTSELX_EVEN_SHIFT))
372 374
373/* AB8500_ADSLOTHIZCTRL1 */ 375/* AB8500_ADSLOTHIZCTRL1 */
374/* AB8500_ADSLOTHIZCTRL2 */ 376/* AB8500_ADSLOTHIZCTRL2 */
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index dafdbe87edeb..b6b1a773bd37 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -13,6 +13,9 @@
13#include <linux/i2c.h> 13#include <linux/i2c.h>
14#include <linux/delay.h> 14#include <linux/delay.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/of.h>
17#include <linux/of_gpio.h>
18#include <linux/of_device.h>
16#include <sound/core.h> 19#include <sound/core.h>
17#include <sound/pcm.h> 20#include <sound/pcm.h>
18#include <sound/pcm_params.h> 21#include <sound/pcm_params.h>
@@ -87,6 +90,7 @@
87#define ADAU1701_FIRMWARE "adau1701.bin" 90#define ADAU1701_FIRMWARE "adau1701.bin"
88 91
89struct adau1701 { 92struct adau1701 {
93 int gpio_nreset;
90 unsigned int dai_fmt; 94 unsigned int dai_fmt;
91}; 95};
92 96
@@ -180,9 +184,37 @@ static unsigned int adau1701_read(struct snd_soc_codec *codec, unsigned int reg)
180 return value; 184 return value;
181} 185}
182 186
183static int adau1701_load_firmware(struct snd_soc_codec *codec) 187static void adau1701_reset(struct snd_soc_codec *codec)
184{ 188{
185 return process_sigma_firmware(codec->control_data, ADAU1701_FIRMWARE); 189 struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
190
191 if (!gpio_is_valid(adau1701->gpio_nreset))
192 return;
193
194 gpio_set_value(adau1701->gpio_nreset, 0);
195 /* minimum reset time is 20ns */
196 udelay(1);
197 gpio_set_value(adau1701->gpio_nreset, 1);
198 /* power-up time may be as long as 85ms */
199 mdelay(85);
200}
201
202static int adau1701_init(struct snd_soc_codec *codec)
203{
204 int ret;
205 struct i2c_client *client = to_i2c_client(codec->dev);
206
207 adau1701_reset(codec);
208
209 ret = process_sigma_firmware(client, ADAU1701_FIRMWARE);
210 if (ret) {
211 dev_warn(codec->dev, "Failed to load firmware\n");
212 return ret;
213 }
214
215 snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT);
216
217 return 0;
186} 218}
187 219
188static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, 220static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec,
@@ -452,17 +484,24 @@ static struct snd_soc_dai_driver adau1701_dai = {
452 .symmetric_rates = 1, 484 .symmetric_rates = 1,
453}; 485};
454 486
487#ifdef CONFIG_OF
488static const struct of_device_id adau1701_dt_ids[] = {
489 { .compatible = "adi,adau1701", },
490 { }
491};
492MODULE_DEVICE_TABLE(of, adau1701_dt_ids);
493#endif
494
455static int adau1701_probe(struct snd_soc_codec *codec) 495static int adau1701_probe(struct snd_soc_codec *codec)
456{ 496{
457 int ret; 497 int ret;
458 498
459 codec->control_data = to_i2c_client(codec->dev); 499 codec->control_data = to_i2c_client(codec->dev);
460 500
461 ret = adau1701_load_firmware(codec); 501 ret = adau1701_init(codec);
462 if (ret) 502 if (ret)
463 dev_warn(codec->dev, "Failed to load firmware\n"); 503 return ret;
464 504
465 snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT);
466 snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR); 505 snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR);
467 506
468 return 0; 507 return 0;
@@ -493,12 +532,29 @@ static int adau1701_i2c_probe(struct i2c_client *client,
493 const struct i2c_device_id *id) 532 const struct i2c_device_id *id)
494{ 533{
495 struct adau1701 *adau1701; 534 struct adau1701 *adau1701;
535 struct device *dev = &client->dev;
536 int gpio_nreset = -EINVAL;
496 int ret; 537 int ret;
497 538
498 adau1701 = devm_kzalloc(&client->dev, sizeof(*adau1701), GFP_KERNEL); 539 adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL);
499 if (!adau1701) 540 if (!adau1701)
500 return -ENOMEM; 541 return -ENOMEM;
501 542
543 if (dev->of_node) {
544 gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0);
545 if (gpio_nreset < 0 && gpio_nreset != -ENOENT)
546 return gpio_nreset;
547 }
548
549 if (gpio_is_valid(gpio_nreset)) {
550 ret = devm_gpio_request_one(dev, gpio_nreset, GPIOF_OUT_INIT_LOW,
551 "ADAU1701 Reset");
552 if (ret < 0)
553 return ret;
554 }
555
556 adau1701->gpio_nreset = gpio_nreset;
557
502 i2c_set_clientdata(client, adau1701); 558 i2c_set_clientdata(client, adau1701);
503 ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, 559 ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv,
504 &adau1701_dai, 1); 560 &adau1701_dai, 1);
@@ -521,6 +577,7 @@ static struct i2c_driver adau1701_i2c_driver = {
521 .driver = { 577 .driver = {
522 .name = "adau1701", 578 .name = "adau1701",
523 .owner = THIS_MODULE, 579 .owner = THIS_MODULE,
580 .of_match_table = of_match_ptr(adau1701_dt_ids),
524 }, 581 },
525 .probe = adau1701_i2c_probe, 582 .probe = adau1701_i2c_probe,
526 .remove = adau1701_i2c_remove, 583 .remove = adau1701_i2c_remove,
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 389f23253831..de625813c0e6 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -1198,6 +1198,13 @@ const struct snd_soc_dai_ops arizona_dai_ops = {
1198}; 1198};
1199EXPORT_SYMBOL_GPL(arizona_dai_ops); 1199EXPORT_SYMBOL_GPL(arizona_dai_ops);
1200 1200
1201const struct snd_soc_dai_ops arizona_simple_dai_ops = {
1202 .startup = arizona_startup,
1203 .hw_params = arizona_hw_params_rate,
1204 .set_sysclk = arizona_dai_set_sysclk,
1205};
1206EXPORT_SYMBOL_GPL(arizona_simple_dai_ops);
1207
1201int arizona_init_dai(struct arizona_priv *priv, int id) 1208int arizona_init_dai(struct arizona_priv *priv, int id)
1202{ 1209{
1203 struct arizona_dai_priv *dai_priv = &priv->dai[id]; 1210 struct arizona_dai_priv *dai_priv = &priv->dai[id];
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index af39f1006427..b60b08ccc1d0 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -57,7 +57,7 @@
57#define ARIZONA_CLK_98MHZ 5 57#define ARIZONA_CLK_98MHZ 5
58#define ARIZONA_CLK_147MHZ 6 58#define ARIZONA_CLK_147MHZ 6
59 59
60#define ARIZONA_MAX_DAI 4 60#define ARIZONA_MAX_DAI 6
61#define ARIZONA_MAX_ADSP 4 61#define ARIZONA_MAX_ADSP 4
62 62
63struct arizona; 63struct arizona;
@@ -213,6 +213,7 @@ extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
213 int source, unsigned int freq, int dir); 213 int source, unsigned int freq, int dir);
214 214
215extern const struct snd_soc_dai_ops arizona_dai_ops; 215extern const struct snd_soc_dai_ops arizona_dai_ops;
216extern const struct snd_soc_dai_ops arizona_simple_dai_ops;
216 217
217#define ARIZONA_FLL_NAME_LEN 20 218#define ARIZONA_FLL_NAME_LEN 20
218 219
diff --git a/sound/soc/codecs/dfbmcs320.c b/sound/soc/codecs/bt-sco.c
index 4f4f7f41a7d1..a081d9fcb166 100644
--- a/sound/soc/codecs/dfbmcs320.c
+++ b/sound/soc/codecs/bt-sco.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Driver for the DFBM-CS320 bluetooth module 2 * Driver for generic Bluetooth SCO link
3 * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de> 3 * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de>
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
@@ -15,8 +15,8 @@
15 15
16#include <sound/soc.h> 16#include <sound/soc.h>
17 17
18static struct snd_soc_dai_driver dfbmcs320_dai = { 18static struct snd_soc_dai_driver bt_sco_dai = {
19 .name = "dfbmcs320-pcm", 19 .name = "bt-sco-pcm",
20 .playback = { 20 .playback = {
21 .channels_min = 1, 21 .channels_min = 1,
22 .channels_max = 1, 22 .channels_max = 1,
@@ -31,32 +31,41 @@ static struct snd_soc_dai_driver dfbmcs320_dai = {
31 }, 31 },
32}; 32};
33 33
34static struct snd_soc_codec_driver soc_codec_dev_dfbmcs320; 34static struct snd_soc_codec_driver soc_codec_dev_bt_sco;
35 35
36static int dfbmcs320_probe(struct platform_device *pdev) 36static int bt_sco_probe(struct platform_device *pdev)
37{ 37{
38 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_dfbmcs320, 38 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_bt_sco,
39 &dfbmcs320_dai, 1); 39 &bt_sco_dai, 1);
40} 40}
41 41
42static int dfbmcs320_remove(struct platform_device *pdev) 42static int bt_sco_remove(struct platform_device *pdev)
43{ 43{
44 snd_soc_unregister_codec(&pdev->dev); 44 snd_soc_unregister_codec(&pdev->dev);
45 45
46 return 0; 46 return 0;
47} 47}
48 48
49static struct platform_driver dfmcs320_driver = { 49static struct platform_device_id bt_sco_driver_ids[] = {
50 {
51 .name = "dfbmcs320",
52 },
53 {},
54};
55MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids);
56
57static struct platform_driver bt_sco_driver = {
50 .driver = { 58 .driver = {
51 .name = "dfbmcs320", 59 .name = "bt-sco",
52 .owner = THIS_MODULE, 60 .owner = THIS_MODULE,
53 }, 61 },
54 .probe = dfbmcs320_probe, 62 .probe = bt_sco_probe,
55 .remove = dfbmcs320_remove, 63 .remove = bt_sco_remove,
64 .id_table = bt_sco_driver_ids,
56}; 65};
57 66
58module_platform_driver(dfmcs320_driver); 67module_platform_driver(bt_sco_driver);
59 68
60MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 69MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
61MODULE_DESCRIPTION("ASoC DFBM-CS320 bluethooth module driver"); 70MODULE_DESCRIPTION("ASoC generic bluethooth sco link driver");
62MODULE_LICENSE("GPL"); 71MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/omap-hdmi.c b/sound/soc/codecs/hdmi.c
index 529d06444c54..2bcae2b40c92 100644
--- a/sound/soc/codecs/omap-hdmi.c
+++ b/sound/soc/codecs/hdmi.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * ALSA SoC codec driver for HDMI audio on OMAP processors. 2 * ALSA SoC codec driver for HDMI audio codecs.
3 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ 3 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
4 * Author: Ricardo Neri <ricardo.neri@ti.com> 4 * Author: Ricardo Neri <ricardo.neri@ti.com>
5 * 5 *
@@ -23,10 +23,10 @@
23 23
24#define DRV_NAME "hdmi-audio-codec" 24#define DRV_NAME "hdmi-audio-codec"
25 25
26static struct snd_soc_codec_driver omap_hdmi_codec; 26static struct snd_soc_codec_driver hdmi_codec;
27 27
28static struct snd_soc_dai_driver omap_hdmi_codec_dai = { 28static struct snd_soc_dai_driver hdmi_codec_dai = {
29 .name = "omap-hdmi-hifi", 29 .name = "hdmi-hifi",
30 .playback = { 30 .playback = {
31 .channels_min = 2, 31 .channels_min = 2,
32 .channels_max = 8, 32 .channels_max = 8,
@@ -39,31 +39,31 @@ static struct snd_soc_dai_driver omap_hdmi_codec_dai = {
39 }, 39 },
40}; 40};
41 41
42static int omap_hdmi_codec_probe(struct platform_device *pdev) 42static int hdmi_codec_probe(struct platform_device *pdev)
43{ 43{
44 return snd_soc_register_codec(&pdev->dev, &omap_hdmi_codec, 44 return snd_soc_register_codec(&pdev->dev, &hdmi_codec,
45 &omap_hdmi_codec_dai, 1); 45 &hdmi_codec_dai, 1);
46} 46}
47 47
48static int omap_hdmi_codec_remove(struct platform_device *pdev) 48static int hdmi_codec_remove(struct platform_device *pdev)
49{ 49{
50 snd_soc_unregister_codec(&pdev->dev); 50 snd_soc_unregister_codec(&pdev->dev);
51 return 0; 51 return 0;
52} 52}
53 53
54static struct platform_driver omap_hdmi_codec_driver = { 54static struct platform_driver hdmi_codec_driver = {
55 .driver = { 55 .driver = {
56 .name = DRV_NAME, 56 .name = DRV_NAME,
57 .owner = THIS_MODULE, 57 .owner = THIS_MODULE,
58 }, 58 },
59 59
60 .probe = omap_hdmi_codec_probe, 60 .probe = hdmi_codec_probe,
61 .remove = omap_hdmi_codec_remove, 61 .remove = hdmi_codec_remove,
62}; 62};
63 63
64module_platform_driver(omap_hdmi_codec_driver); 64module_platform_driver(hdmi_codec_driver);
65 65
66MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>"); 66MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
67MODULE_DESCRIPTION("ASoC OMAP HDMI codec driver"); 67MODULE_DESCRIPTION("ASoC generic HDMI codec driver");
68MODULE_LICENSE("GPL"); 68MODULE_LICENSE("GPL");
69MODULE_ALIAS("platform:" DRV_NAME); 69MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index 5f607b35b68b..bcebd1a9ce31 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -384,8 +384,6 @@ static int jz4740_codec_remove(struct platform_device *pdev)
384{ 384{
385 snd_soc_unregister_codec(&pdev->dev); 385 snd_soc_unregister_codec(&pdev->dev);
386 386
387 platform_set_drvdata(pdev, NULL);
388
389 return 0; 387 return 0;
390} 388}
391 389
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index 8d14a76c7249..ad5313f98f28 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -857,6 +857,14 @@ static const struct soc_enum mic2_mux_enum =
857static const struct snd_kcontrol_new max98090_mic2_mux = 857static const struct snd_kcontrol_new max98090_mic2_mux =
858 SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum); 858 SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum);
859 859
860static const char *dmic_mux_text[] = { "ADC", "DMIC" };
861
862static const struct soc_enum dmic_mux_enum =
863 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dmic_mux_text), dmic_mux_text);
864
865static const struct snd_kcontrol_new max98090_dmic_mux =
866 SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum);
867
860static const char *max98090_micpre_text[] = { "Off", "On" }; 868static const char *max98090_micpre_text[] = { "Off", "On" };
861 869
862static const struct soc_enum max98090_pa1en_enum = 870static const struct soc_enum max98090_pa1en_enum =
@@ -1144,6 +1152,9 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
1144 SND_SOC_DAPM_MUX("MIC2 Mux", SND_SOC_NOPM, 1152 SND_SOC_DAPM_MUX("MIC2 Mux", SND_SOC_NOPM,
1145 0, 0, &max98090_mic2_mux), 1153 0, 0, &max98090_mic2_mux),
1146 1154
1155 SND_SOC_DAPM_VIRT_MUX("DMIC Mux", SND_SOC_NOPM,
1156 0, 0, &max98090_dmic_mux),
1157
1147 SND_SOC_DAPM_PGA_E("MIC1 Input", M98090_REG_MIC1_INPUT_LEVEL, 1158 SND_SOC_DAPM_PGA_E("MIC1 Input", M98090_REG_MIC1_INPUT_LEVEL,
1148 M98090_MIC_PA1EN_SHIFT, 0, NULL, 0, max98090_micinput_event, 1159 M98090_MIC_PA1EN_SHIFT, 0, NULL, 0, max98090_micinput_event,
1149 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 1160 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -1336,11 +1347,14 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
1336 {"ADCL", NULL, "SHDN"}, 1347 {"ADCL", NULL, "SHDN"},
1337 {"ADCR", NULL, "SHDN"}, 1348 {"ADCR", NULL, "SHDN"},
1338 1349
1339 {"LBENL Mux", "Normal", "ADCL"}, 1350 {"DMIC Mux", "ADC", "ADCL"},
1340 {"LBENL Mux", "Normal", "DMICL"}, 1351 {"DMIC Mux", "ADC", "ADCR"},
1352 {"DMIC Mux", "DMIC", "DMICL"},
1353 {"DMIC Mux", "DMIC", "DMICR"},
1354
1355 {"LBENL Mux", "Normal", "DMIC Mux"},
1341 {"LBENL Mux", "Loopback", "LTENL Mux"}, 1356 {"LBENL Mux", "Loopback", "LTENL Mux"},
1342 {"LBENR Mux", "Normal", "ADCR"}, 1357 {"LBENR Mux", "Normal", "DMIC Mux"},
1343 {"LBENR Mux", "Normal", "DMICR"},
1344 {"LBENR Mux", "Loopback", "LTENR Mux"}, 1358 {"LBENR Mux", "Loopback", "LTENR Mux"},
1345 1359
1346 {"AIFOUTL", NULL, "LBENL Mux"}, 1360 {"AIFOUTL", NULL, "LBENL Mux"},
@@ -2336,6 +2350,7 @@ static int max98090_i2c_remove(struct i2c_client *client)
2336 return 0; 2350 return 0;
2337} 2351}
2338 2352
2353#ifdef CONFIG_PM_RUNTIME
2339static int max98090_runtime_resume(struct device *dev) 2354static int max98090_runtime_resume(struct device *dev)
2340{ 2355{
2341 struct max98090_priv *max98090 = dev_get_drvdata(dev); 2356 struct max98090_priv *max98090 = dev_get_drvdata(dev);
@@ -2355,6 +2370,7 @@ static int max98090_runtime_suspend(struct device *dev)
2355 2370
2356 return 0; 2371 return 0;
2357} 2372}
2373#endif
2358 2374
2359static const struct dev_pm_ops max98090_pm = { 2375static const struct dev_pm_ops max98090_pm = {
2360 SET_RUNTIME_PM_OPS(max98090_runtime_suspend, 2376 SET_RUNTIME_PM_OPS(max98090_runtime_suspend,
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
new file mode 100644
index 000000000000..ce585e37e38a
--- /dev/null
+++ b/sound/soc/codecs/rt5640.c
@@ -0,0 +1,2128 @@
1/*
2 * rt5640.c -- RT5640 ALSA SoC audio codec driver
3 *
4 * Copyright 2011 Realtek Semiconductor Corp.
5 * Author: Johnny Hsu <johnnyhsu@realtek.com>
6 * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/pm.h>
18#include <linux/gpio.h>
19#include <linux/i2c.h>
20#include <linux/regmap.h>
21#include <linux/of_gpio.h>
22#include <linux/platform_device.h>
23#include <linux/spi/spi.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/soc.h>
28#include <sound/soc-dapm.h>
29#include <sound/initval.h>
30#include <sound/tlv.h>
31
32#include "rt5640.h"
33
34#define RT5640_DEVICE_ID 0x6231
35
36#define RT5640_PR_RANGE_BASE (0xff + 1)
37#define RT5640_PR_SPACING 0x100
38
39#define RT5640_PR_BASE (RT5640_PR_RANGE_BASE + (0 * RT5640_PR_SPACING))
40
41static const struct regmap_range_cfg rt5640_ranges[] = {
42 { .name = "PR", .range_min = RT5640_PR_BASE,
43 .range_max = RT5640_PR_BASE + 0xb4,
44 .selector_reg = RT5640_PRIV_INDEX,
45 .selector_mask = 0xff,
46 .selector_shift = 0x0,
47 .window_start = RT5640_PRIV_DATA,
48 .window_len = 0x1, },
49};
50
51static struct reg_default init_list[] = {
52 {RT5640_PR_BASE + 0x3d, 0x3600},
53 {RT5640_PR_BASE + 0x1c, 0x0D21},
54 {RT5640_PR_BASE + 0x1b, 0x0000},
55 {RT5640_PR_BASE + 0x12, 0x0aa8},
56 {RT5640_PR_BASE + 0x14, 0x0aaa},
57 {RT5640_PR_BASE + 0x20, 0x6110},
58 {RT5640_PR_BASE + 0x21, 0xe0e0},
59 {RT5640_PR_BASE + 0x23, 0x1804},
60};
61#define RT5640_INIT_REG_LEN ARRAY_SIZE(init_list)
62
63static const struct reg_default rt5640_reg[RT5640_VENDOR_ID2 + 1] = {
64 { 0x00, 0x000e },
65 { 0x01, 0xc8c8 },
66 { 0x02, 0xc8c8 },
67 { 0x03, 0xc8c8 },
68 { 0x04, 0x8000 },
69 { 0x0d, 0x0000 },
70 { 0x0e, 0x0000 },
71 { 0x0f, 0x0808 },
72 { 0x19, 0xafaf },
73 { 0x1a, 0xafaf },
74 { 0x1b, 0x0000 },
75 { 0x1c, 0x2f2f },
76 { 0x1d, 0x2f2f },
77 { 0x1e, 0x0000 },
78 { 0x27, 0x7060 },
79 { 0x28, 0x7070 },
80 { 0x29, 0x8080 },
81 { 0x2a, 0x5454 },
82 { 0x2b, 0x5454 },
83 { 0x2c, 0xaa00 },
84 { 0x2d, 0x0000 },
85 { 0x2e, 0xa000 },
86 { 0x2f, 0x0000 },
87 { 0x3b, 0x0000 },
88 { 0x3c, 0x007f },
89 { 0x3d, 0x0000 },
90 { 0x3e, 0x007f },
91 { 0x45, 0xe000 },
92 { 0x46, 0x003e },
93 { 0x47, 0x003e },
94 { 0x48, 0xf800 },
95 { 0x49, 0x3800 },
96 { 0x4a, 0x0004 },
97 { 0x4c, 0xfc00 },
98 { 0x4d, 0x0000 },
99 { 0x4f, 0x01ff },
100 { 0x50, 0x0000 },
101 { 0x51, 0x0000 },
102 { 0x52, 0x01ff },
103 { 0x53, 0xf000 },
104 { 0x61, 0x0000 },
105 { 0x62, 0x0000 },
106 { 0x63, 0x00c0 },
107 { 0x64, 0x0000 },
108 { 0x65, 0x0000 },
109 { 0x66, 0x0000 },
110 { 0x6a, 0x0000 },
111 { 0x6c, 0x0000 },
112 { 0x70, 0x8000 },
113 { 0x71, 0x8000 },
114 { 0x72, 0x8000 },
115 { 0x73, 0x1114 },
116 { 0x74, 0x0c00 },
117 { 0x75, 0x1d00 },
118 { 0x80, 0x0000 },
119 { 0x81, 0x0000 },
120 { 0x82, 0x0000 },
121 { 0x83, 0x0000 },
122 { 0x84, 0x0000 },
123 { 0x85, 0x0008 },
124 { 0x89, 0x0000 },
125 { 0x8a, 0x0000 },
126 { 0x8b, 0x0600 },
127 { 0x8c, 0x0228 },
128 { 0x8d, 0xa000 },
129 { 0x8e, 0x0004 },
130 { 0x8f, 0x1100 },
131 { 0x90, 0x0646 },
132 { 0x91, 0x0c00 },
133 { 0x92, 0x0000 },
134 { 0x93, 0x3000 },
135 { 0xb0, 0x2080 },
136 { 0xb1, 0x0000 },
137 { 0xb4, 0x2206 },
138 { 0xb5, 0x1f00 },
139 { 0xb6, 0x0000 },
140 { 0xb8, 0x034b },
141 { 0xb9, 0x0066 },
142 { 0xba, 0x000b },
143 { 0xbb, 0x0000 },
144 { 0xbc, 0x0000 },
145 { 0xbd, 0x0000 },
146 { 0xbe, 0x0000 },
147 { 0xbf, 0x0000 },
148 { 0xc0, 0x0400 },
149 { 0xc2, 0x0000 },
150 { 0xc4, 0x0000 },
151 { 0xc5, 0x0000 },
152 { 0xc6, 0x2000 },
153 { 0xc8, 0x0000 },
154 { 0xc9, 0x0000 },
155 { 0xca, 0x0000 },
156 { 0xcb, 0x0000 },
157 { 0xcc, 0x0000 },
158 { 0xcf, 0x0013 },
159 { 0xd0, 0x0680 },
160 { 0xd1, 0x1c17 },
161 { 0xd2, 0x8c00 },
162 { 0xd3, 0xaa20 },
163 { 0xd6, 0x0400 },
164 { 0xd9, 0x0809 },
165 { 0xfe, 0x10ec },
166 { 0xff, 0x6231 },
167};
168
169static int rt5640_reset(struct snd_soc_codec *codec)
170{
171 return snd_soc_write(codec, RT5640_RESET, 0);
172}
173
174static bool rt5640_volatile_register(struct device *dev, unsigned int reg)
175{
176 int i;
177
178 for (i = 0; i < ARRAY_SIZE(rt5640_ranges); i++)
179 if ((reg >= rt5640_ranges[i].window_start &&
180 reg <= rt5640_ranges[i].window_start +
181 rt5640_ranges[i].window_len) ||
182 (reg >= rt5640_ranges[i].range_min &&
183 reg <= rt5640_ranges[i].range_max))
184 return true;
185
186 switch (reg) {
187 case RT5640_RESET:
188 case RT5640_ASRC_5:
189 case RT5640_EQ_CTRL1:
190 case RT5640_DRC_AGC_1:
191 case RT5640_ANC_CTRL1:
192 case RT5640_IRQ_CTRL2:
193 case RT5640_INT_IRQ_ST:
194 case RT5640_DSP_CTRL2:
195 case RT5640_DSP_CTRL3:
196 case RT5640_PRIV_INDEX:
197 case RT5640_PRIV_DATA:
198 case RT5640_PGM_REG_ARR1:
199 case RT5640_PGM_REG_ARR3:
200 case RT5640_VENDOR_ID:
201 case RT5640_VENDOR_ID1:
202 case RT5640_VENDOR_ID2:
203 return true;
204 default:
205 return false;
206 }
207}
208
209static bool rt5640_readable_register(struct device *dev, unsigned int reg)
210{
211 int i;
212
213 for (i = 0; i < ARRAY_SIZE(rt5640_ranges); i++)
214 if ((reg >= rt5640_ranges[i].window_start &&
215 reg <= rt5640_ranges[i].window_start +
216 rt5640_ranges[i].window_len) ||
217 (reg >= rt5640_ranges[i].range_min &&
218 reg <= rt5640_ranges[i].range_max))
219 return true;
220
221 switch (reg) {
222 case RT5640_RESET:
223 case RT5640_SPK_VOL:
224 case RT5640_HP_VOL:
225 case RT5640_OUTPUT:
226 case RT5640_MONO_OUT:
227 case RT5640_IN1_IN2:
228 case RT5640_IN3_IN4:
229 case RT5640_INL_INR_VOL:
230 case RT5640_DAC1_DIG_VOL:
231 case RT5640_DAC2_DIG_VOL:
232 case RT5640_DAC2_CTRL:
233 case RT5640_ADC_DIG_VOL:
234 case RT5640_ADC_DATA:
235 case RT5640_ADC_BST_VOL:
236 case RT5640_STO_ADC_MIXER:
237 case RT5640_MONO_ADC_MIXER:
238 case RT5640_AD_DA_MIXER:
239 case RT5640_STO_DAC_MIXER:
240 case RT5640_MONO_DAC_MIXER:
241 case RT5640_DIG_MIXER:
242 case RT5640_DSP_PATH1:
243 case RT5640_DSP_PATH2:
244 case RT5640_DIG_INF_DATA:
245 case RT5640_REC_L1_MIXER:
246 case RT5640_REC_L2_MIXER:
247 case RT5640_REC_R1_MIXER:
248 case RT5640_REC_R2_MIXER:
249 case RT5640_HPO_MIXER:
250 case RT5640_SPK_L_MIXER:
251 case RT5640_SPK_R_MIXER:
252 case RT5640_SPO_L_MIXER:
253 case RT5640_SPO_R_MIXER:
254 case RT5640_SPO_CLSD_RATIO:
255 case RT5640_MONO_MIXER:
256 case RT5640_OUT_L1_MIXER:
257 case RT5640_OUT_L2_MIXER:
258 case RT5640_OUT_L3_MIXER:
259 case RT5640_OUT_R1_MIXER:
260 case RT5640_OUT_R2_MIXER:
261 case RT5640_OUT_R3_MIXER:
262 case RT5640_LOUT_MIXER:
263 case RT5640_PWR_DIG1:
264 case RT5640_PWR_DIG2:
265 case RT5640_PWR_ANLG1:
266 case RT5640_PWR_ANLG2:
267 case RT5640_PWR_MIXER:
268 case RT5640_PWR_VOL:
269 case RT5640_PRIV_INDEX:
270 case RT5640_PRIV_DATA:
271 case RT5640_I2S1_SDP:
272 case RT5640_I2S2_SDP:
273 case RT5640_ADDA_CLK1:
274 case RT5640_ADDA_CLK2:
275 case RT5640_DMIC:
276 case RT5640_GLB_CLK:
277 case RT5640_PLL_CTRL1:
278 case RT5640_PLL_CTRL2:
279 case RT5640_ASRC_1:
280 case RT5640_ASRC_2:
281 case RT5640_ASRC_3:
282 case RT5640_ASRC_4:
283 case RT5640_ASRC_5:
284 case RT5640_HP_OVCD:
285 case RT5640_CLS_D_OVCD:
286 case RT5640_CLS_D_OUT:
287 case RT5640_DEPOP_M1:
288 case RT5640_DEPOP_M2:
289 case RT5640_DEPOP_M3:
290 case RT5640_CHARGE_PUMP:
291 case RT5640_PV_DET_SPK_G:
292 case RT5640_MICBIAS:
293 case RT5640_EQ_CTRL1:
294 case RT5640_EQ_CTRL2:
295 case RT5640_WIND_FILTER:
296 case RT5640_DRC_AGC_1:
297 case RT5640_DRC_AGC_2:
298 case RT5640_DRC_AGC_3:
299 case RT5640_SVOL_ZC:
300 case RT5640_ANC_CTRL1:
301 case RT5640_ANC_CTRL2:
302 case RT5640_ANC_CTRL3:
303 case RT5640_JD_CTRL:
304 case RT5640_ANC_JD:
305 case RT5640_IRQ_CTRL1:
306 case RT5640_IRQ_CTRL2:
307 case RT5640_INT_IRQ_ST:
308 case RT5640_GPIO_CTRL1:
309 case RT5640_GPIO_CTRL2:
310 case RT5640_GPIO_CTRL3:
311 case RT5640_DSP_CTRL1:
312 case RT5640_DSP_CTRL2:
313 case RT5640_DSP_CTRL3:
314 case RT5640_DSP_CTRL4:
315 case RT5640_PGM_REG_ARR1:
316 case RT5640_PGM_REG_ARR2:
317 case RT5640_PGM_REG_ARR3:
318 case RT5640_PGM_REG_ARR4:
319 case RT5640_PGM_REG_ARR5:
320 case RT5640_SCB_FUNC:
321 case RT5640_SCB_CTRL:
322 case RT5640_BASE_BACK:
323 case RT5640_MP3_PLUS1:
324 case RT5640_MP3_PLUS2:
325 case RT5640_3D_HP:
326 case RT5640_ADJ_HPF:
327 case RT5640_HP_CALIB_AMP_DET:
328 case RT5640_HP_CALIB2:
329 case RT5640_SV_ZCD1:
330 case RT5640_SV_ZCD2:
331 case RT5640_DUMMY1:
332 case RT5640_DUMMY2:
333 case RT5640_DUMMY3:
334 case RT5640_VENDOR_ID:
335 case RT5640_VENDOR_ID1:
336 case RT5640_VENDOR_ID2:
337 return true;
338 default:
339 return false;
340 }
341}
342
343static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
344static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
345static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
346static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
347static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
348
349/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
350static unsigned int bst_tlv[] = {
351 TLV_DB_RANGE_HEAD(7),
352 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
353 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
354 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
355 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
356 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
357 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
358 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
359};
360
361/* Interface data select */
362static const char * const rt5640_data_select[] = {
363 "Normal", "left copy to right", "right copy to left", "Swap"};
364
365static const SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA,
366 RT5640_IF1_DAC_SEL_SFT, rt5640_data_select);
367
368static const SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA,
369 RT5640_IF1_ADC_SEL_SFT, rt5640_data_select);
370
371static const SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA,
372 RT5640_IF2_DAC_SEL_SFT, rt5640_data_select);
373
374static const SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA,
375 RT5640_IF2_ADC_SEL_SFT, rt5640_data_select);
376
377/* Class D speaker gain ratio */
378static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x",
379 "2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"};
380
381static const SOC_ENUM_SINGLE_DECL(
382 rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT,
383 RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio);
384
385static const struct snd_kcontrol_new rt5640_snd_controls[] = {
386 /* Speaker Output Volume */
387 SOC_DOUBLE("Speaker Playback Switch", RT5640_SPK_VOL,
388 RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
389 SOC_DOUBLE("Speaker Channel Switch", RT5640_SPK_VOL,
390 RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
391 SOC_DOUBLE_TLV("Speaker Playback Volume", RT5640_SPK_VOL,
392 RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv),
393 /* Headphone Output Volume */
394 SOC_DOUBLE("HP Playback Switch", RT5640_HP_VOL,
395 RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
396 SOC_DOUBLE("HP Channel Switch", RT5640_HP_VOL,
397 RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
398 SOC_DOUBLE_TLV("HP Playback Volume", RT5640_HP_VOL,
399 RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv),
400 /* OUTPUT Control */
401 SOC_DOUBLE("OUT Playback Switch", RT5640_OUTPUT,
402 RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
403 SOC_DOUBLE("OUT Channel Switch", RT5640_OUTPUT,
404 RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
405 SOC_DOUBLE_TLV("OUT Playback Volume", RT5640_OUTPUT,
406 RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv),
407 /* MONO Output Control */
408 SOC_SINGLE("Mono Playback Switch", RT5640_MONO_OUT,
409 RT5640_L_MUTE_SFT, 1, 1),
410 /* DAC Digital Volume */
411 SOC_DOUBLE("DAC2 Playback Switch", RT5640_DAC2_CTRL,
412 RT5640_M_DAC_L2_VOL_SFT, RT5640_M_DAC_R2_VOL_SFT, 1, 1),
413 SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5640_DAC1_DIG_VOL,
414 RT5640_L_VOL_SFT, RT5640_R_VOL_SFT,
415 175, 0, dac_vol_tlv),
416 SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5640_DAC2_DIG_VOL,
417 RT5640_L_VOL_SFT, RT5640_R_VOL_SFT,
418 175, 0, dac_vol_tlv),
419 /* IN1/IN2 Control */
420 SOC_SINGLE_TLV("IN1 Boost", RT5640_IN1_IN2,
421 RT5640_BST_SFT1, 8, 0, bst_tlv),
422 SOC_SINGLE_TLV("IN2 Boost", RT5640_IN3_IN4,
423 RT5640_BST_SFT2, 8, 0, bst_tlv),
424 /* INL/INR Volume Control */
425 SOC_DOUBLE_TLV("IN Capture Volume", RT5640_INL_INR_VOL,
426 RT5640_INL_VOL_SFT, RT5640_INR_VOL_SFT,
427 31, 1, in_vol_tlv),
428 /* ADC Digital Volume Control */
429 SOC_DOUBLE("ADC Capture Switch", RT5640_ADC_DIG_VOL,
430 RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
431 SOC_DOUBLE_TLV("ADC Capture Volume", RT5640_ADC_DIG_VOL,
432 RT5640_L_VOL_SFT, RT5640_R_VOL_SFT,
433 127, 0, adc_vol_tlv),
434 SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5640_ADC_DATA,
435 RT5640_L_VOL_SFT, RT5640_R_VOL_SFT,
436 127, 0, adc_vol_tlv),
437 /* ADC Boost Volume Control */
438 SOC_DOUBLE_TLV("ADC Boost Gain", RT5640_ADC_BST_VOL,
439 RT5640_ADC_L_BST_SFT, RT5640_ADC_R_BST_SFT,
440 3, 0, adc_bst_tlv),
441 /* Class D speaker gain ratio */
442 SOC_ENUM("Class D SPK Ratio Control", rt5640_clsd_spk_ratio_enum),
443
444 SOC_ENUM("ADC IF1 Data Switch", rt5640_if1_adc_enum),
445 SOC_ENUM("DAC IF1 Data Switch", rt5640_if1_dac_enum),
446 SOC_ENUM("ADC IF2 Data Switch", rt5640_if2_adc_enum),
447 SOC_ENUM("DAC IF2 Data Switch", rt5640_if2_dac_enum),
448};
449
450/**
451 * set_dmic_clk - Set parameter of dmic.
452 *
453 * @w: DAPM widget.
454 * @kcontrol: The kcontrol of this widget.
455 * @event: Event id.
456 *
457 * Choose dmic clock between 1MHz and 3MHz.
458 * It is better for clock to approximate 3MHz.
459 */
460static int set_dmic_clk(struct snd_soc_dapm_widget *w,
461 struct snd_kcontrol *kcontrol, int event)
462{
463 struct snd_soc_codec *codec = w->codec;
464 struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
465 int div[] = {2, 3, 4, 6, 8, 12};
466 int idx = -EINVAL, i;
467 int rate, red, bound, temp;
468
469 rate = rt5640->sysclk;
470 red = 3000000 * 12;
471 for (i = 0; i < ARRAY_SIZE(div); i++) {
472 bound = div[i] * 3000000;
473 if (rate > bound)
474 continue;
475 temp = bound - rate;
476 if (temp < red) {
477 red = temp;
478 idx = i;
479 }
480 }
481 if (idx < 0)
482 dev_err(codec->dev, "Failed to set DMIC clock\n");
483 else
484 snd_soc_update_bits(codec, RT5640_DMIC, RT5640_DMIC_CLK_MASK,
485 idx << RT5640_DMIC_CLK_SFT);
486 return idx;
487}
488
489static int check_sysclk1_source(struct snd_soc_dapm_widget *source,
490 struct snd_soc_dapm_widget *sink)
491{
492 unsigned int val;
493
494 val = snd_soc_read(source->codec, RT5640_GLB_CLK);
495 val &= RT5640_SCLK_SRC_MASK;
496 if (val == RT5640_SCLK_SRC_PLL1 || val == RT5640_SCLK_SRC_PLL1T)
497 return 1;
498 else
499 return 0;
500}
501
502/* Digital Mixer */
503static const struct snd_kcontrol_new rt5640_sto_adc_l_mix[] = {
504 SOC_DAPM_SINGLE("ADC1 Switch", RT5640_STO_ADC_MIXER,
505 RT5640_M_ADC_L1_SFT, 1, 1),
506 SOC_DAPM_SINGLE("ADC2 Switch", RT5640_STO_ADC_MIXER,
507 RT5640_M_ADC_L2_SFT, 1, 1),
508};
509
510static const struct snd_kcontrol_new rt5640_sto_adc_r_mix[] = {
511 SOC_DAPM_SINGLE("ADC1 Switch", RT5640_STO_ADC_MIXER,
512 RT5640_M_ADC_R1_SFT, 1, 1),
513 SOC_DAPM_SINGLE("ADC2 Switch", RT5640_STO_ADC_MIXER,
514 RT5640_M_ADC_R2_SFT, 1, 1),
515};
516
517static const struct snd_kcontrol_new rt5640_mono_adc_l_mix[] = {
518 SOC_DAPM_SINGLE("ADC1 Switch", RT5640_MONO_ADC_MIXER,
519 RT5640_M_MONO_ADC_L1_SFT, 1, 1),
520 SOC_DAPM_SINGLE("ADC2 Switch", RT5640_MONO_ADC_MIXER,
521 RT5640_M_MONO_ADC_L2_SFT, 1, 1),
522};
523
524static const struct snd_kcontrol_new rt5640_mono_adc_r_mix[] = {
525 SOC_DAPM_SINGLE("ADC1 Switch", RT5640_MONO_ADC_MIXER,
526 RT5640_M_MONO_ADC_R1_SFT, 1, 1),
527 SOC_DAPM_SINGLE("ADC2 Switch", RT5640_MONO_ADC_MIXER,
528 RT5640_M_MONO_ADC_R2_SFT, 1, 1),
529};
530
531static const struct snd_kcontrol_new rt5640_dac_l_mix[] = {
532 SOC_DAPM_SINGLE("Stereo ADC Switch", RT5640_AD_DA_MIXER,
533 RT5640_M_ADCMIX_L_SFT, 1, 1),
534 SOC_DAPM_SINGLE("INF1 Switch", RT5640_AD_DA_MIXER,
535 RT5640_M_IF1_DAC_L_SFT, 1, 1),
536};
537
538static const struct snd_kcontrol_new rt5640_dac_r_mix[] = {
539 SOC_DAPM_SINGLE("Stereo ADC Switch", RT5640_AD_DA_MIXER,
540 RT5640_M_ADCMIX_R_SFT, 1, 1),
541 SOC_DAPM_SINGLE("INF1 Switch", RT5640_AD_DA_MIXER,
542 RT5640_M_IF1_DAC_R_SFT, 1, 1),
543};
544
545static const struct snd_kcontrol_new rt5640_sto_dac_l_mix[] = {
546 SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_STO_DAC_MIXER,
547 RT5640_M_DAC_L1_SFT, 1, 1),
548 SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_STO_DAC_MIXER,
549 RT5640_M_DAC_L2_SFT, 1, 1),
550 SOC_DAPM_SINGLE("ANC Switch", RT5640_STO_DAC_MIXER,
551 RT5640_M_ANC_DAC_L_SFT, 1, 1),
552};
553
554static const struct snd_kcontrol_new rt5640_sto_dac_r_mix[] = {
555 SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_STO_DAC_MIXER,
556 RT5640_M_DAC_R1_SFT, 1, 1),
557 SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_STO_DAC_MIXER,
558 RT5640_M_DAC_R2_SFT, 1, 1),
559 SOC_DAPM_SINGLE("ANC Switch", RT5640_STO_DAC_MIXER,
560 RT5640_M_ANC_DAC_R_SFT, 1, 1),
561};
562
563static const struct snd_kcontrol_new rt5640_mono_dac_l_mix[] = {
564 SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_MONO_DAC_MIXER,
565 RT5640_M_DAC_L1_MONO_L_SFT, 1, 1),
566 SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_MONO_DAC_MIXER,
567 RT5640_M_DAC_L2_MONO_L_SFT, 1, 1),
568 SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_MONO_DAC_MIXER,
569 RT5640_M_DAC_R2_MONO_L_SFT, 1, 1),
570};
571
572static const struct snd_kcontrol_new rt5640_mono_dac_r_mix[] = {
573 SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_MONO_DAC_MIXER,
574 RT5640_M_DAC_R1_MONO_R_SFT, 1, 1),
575 SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_MONO_DAC_MIXER,
576 RT5640_M_DAC_R2_MONO_R_SFT, 1, 1),
577 SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_MONO_DAC_MIXER,
578 RT5640_M_DAC_L2_MONO_R_SFT, 1, 1),
579};
580
581static const struct snd_kcontrol_new rt5640_dig_l_mix[] = {
582 SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_DIG_MIXER,
583 RT5640_M_STO_L_DAC_L_SFT, 1, 1),
584 SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_DIG_MIXER,
585 RT5640_M_DAC_L2_DAC_L_SFT, 1, 1),
586};
587
588static const struct snd_kcontrol_new rt5640_dig_r_mix[] = {
589 SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_DIG_MIXER,
590 RT5640_M_STO_R_DAC_R_SFT, 1, 1),
591 SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_DIG_MIXER,
592 RT5640_M_DAC_R2_DAC_R_SFT, 1, 1),
593};
594
595/* Analog Input Mixer */
596static const struct snd_kcontrol_new rt5640_rec_l_mix[] = {
597 SOC_DAPM_SINGLE("HPOL Switch", RT5640_REC_L2_MIXER,
598 RT5640_M_HP_L_RM_L_SFT, 1, 1),
599 SOC_DAPM_SINGLE("INL Switch", RT5640_REC_L2_MIXER,
600 RT5640_M_IN_L_RM_L_SFT, 1, 1),
601 SOC_DAPM_SINGLE("BST2 Switch", RT5640_REC_L2_MIXER,
602 RT5640_M_BST4_RM_L_SFT, 1, 1),
603 SOC_DAPM_SINGLE("BST1 Switch", RT5640_REC_L2_MIXER,
604 RT5640_M_BST1_RM_L_SFT, 1, 1),
605 SOC_DAPM_SINGLE("OUT MIXL Switch", RT5640_REC_L2_MIXER,
606 RT5640_M_OM_L_RM_L_SFT, 1, 1),
607};
608
609static const struct snd_kcontrol_new rt5640_rec_r_mix[] = {
610 SOC_DAPM_SINGLE("HPOR Switch", RT5640_REC_R2_MIXER,
611 RT5640_M_HP_R_RM_R_SFT, 1, 1),
612 SOC_DAPM_SINGLE("INR Switch", RT5640_REC_R2_MIXER,
613 RT5640_M_IN_R_RM_R_SFT, 1, 1),
614 SOC_DAPM_SINGLE("BST2 Switch", RT5640_REC_R2_MIXER,
615 RT5640_M_BST4_RM_R_SFT, 1, 1),
616 SOC_DAPM_SINGLE("BST1 Switch", RT5640_REC_R2_MIXER,
617 RT5640_M_BST1_RM_R_SFT, 1, 1),
618 SOC_DAPM_SINGLE("OUT MIXR Switch", RT5640_REC_R2_MIXER,
619 RT5640_M_OM_R_RM_R_SFT, 1, 1),
620};
621
622/* Analog Output Mixer */
623static const struct snd_kcontrol_new rt5640_spk_l_mix[] = {
624 SOC_DAPM_SINGLE("REC MIXL Switch", RT5640_SPK_L_MIXER,
625 RT5640_M_RM_L_SM_L_SFT, 1, 1),
626 SOC_DAPM_SINGLE("INL Switch", RT5640_SPK_L_MIXER,
627 RT5640_M_IN_L_SM_L_SFT, 1, 1),
628 SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_SPK_L_MIXER,
629 RT5640_M_DAC_L1_SM_L_SFT, 1, 1),
630 SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_SPK_L_MIXER,
631 RT5640_M_DAC_L2_SM_L_SFT, 1, 1),
632 SOC_DAPM_SINGLE("OUT MIXL Switch", RT5640_SPK_L_MIXER,
633 RT5640_M_OM_L_SM_L_SFT, 1, 1),
634};
635
636static const struct snd_kcontrol_new rt5640_spk_r_mix[] = {
637 SOC_DAPM_SINGLE("REC MIXR Switch", RT5640_SPK_R_MIXER,
638 RT5640_M_RM_R_SM_R_SFT, 1, 1),
639 SOC_DAPM_SINGLE("INR Switch", RT5640_SPK_R_MIXER,
640 RT5640_M_IN_R_SM_R_SFT, 1, 1),
641 SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_SPK_R_MIXER,
642 RT5640_M_DAC_R1_SM_R_SFT, 1, 1),
643 SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_SPK_R_MIXER,
644 RT5640_M_DAC_R2_SM_R_SFT, 1, 1),
645 SOC_DAPM_SINGLE("OUT MIXR Switch", RT5640_SPK_R_MIXER,
646 RT5640_M_OM_R_SM_R_SFT, 1, 1),
647};
648
649static const struct snd_kcontrol_new rt5640_out_l_mix[] = {
650 SOC_DAPM_SINGLE("SPK MIXL Switch", RT5640_OUT_L3_MIXER,
651 RT5640_M_SM_L_OM_L_SFT, 1, 1),
652 SOC_DAPM_SINGLE("BST1 Switch", RT5640_OUT_L3_MIXER,
653 RT5640_M_BST1_OM_L_SFT, 1, 1),
654 SOC_DAPM_SINGLE("INL Switch", RT5640_OUT_L3_MIXER,
655 RT5640_M_IN_L_OM_L_SFT, 1, 1),
656 SOC_DAPM_SINGLE("REC MIXL Switch", RT5640_OUT_L3_MIXER,
657 RT5640_M_RM_L_OM_L_SFT, 1, 1),
658 SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_OUT_L3_MIXER,
659 RT5640_M_DAC_R2_OM_L_SFT, 1, 1),
660 SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_OUT_L3_MIXER,
661 RT5640_M_DAC_L2_OM_L_SFT, 1, 1),
662 SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_OUT_L3_MIXER,
663 RT5640_M_DAC_L1_OM_L_SFT, 1, 1),
664};
665
666static const struct snd_kcontrol_new rt5640_out_r_mix[] = {
667 SOC_DAPM_SINGLE("SPK MIXR Switch", RT5640_OUT_R3_MIXER,
668 RT5640_M_SM_L_OM_R_SFT, 1, 1),
669 SOC_DAPM_SINGLE("BST2 Switch", RT5640_OUT_R3_MIXER,
670 RT5640_M_BST4_OM_R_SFT, 1, 1),
671 SOC_DAPM_SINGLE("BST1 Switch", RT5640_OUT_R3_MIXER,
672 RT5640_M_BST1_OM_R_SFT, 1, 1),
673 SOC_DAPM_SINGLE("INR Switch", RT5640_OUT_R3_MIXER,
674 RT5640_M_IN_R_OM_R_SFT, 1, 1),
675 SOC_DAPM_SINGLE("REC MIXR Switch", RT5640_OUT_R3_MIXER,
676 RT5640_M_RM_R_OM_R_SFT, 1, 1),
677 SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_OUT_R3_MIXER,
678 RT5640_M_DAC_L2_OM_R_SFT, 1, 1),
679 SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_OUT_R3_MIXER,
680 RT5640_M_DAC_R2_OM_R_SFT, 1, 1),
681 SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_OUT_R3_MIXER,
682 RT5640_M_DAC_R1_OM_R_SFT, 1, 1),
683};
684
685static const struct snd_kcontrol_new rt5640_spo_l_mix[] = {
686 SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_SPO_L_MIXER,
687 RT5640_M_DAC_R1_SPM_L_SFT, 1, 1),
688 SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_SPO_L_MIXER,
689 RT5640_M_DAC_L1_SPM_L_SFT, 1, 1),
690 SOC_DAPM_SINGLE("SPKVOL R Switch", RT5640_SPO_L_MIXER,
691 RT5640_M_SV_R_SPM_L_SFT, 1, 1),
692 SOC_DAPM_SINGLE("SPKVOL L Switch", RT5640_SPO_L_MIXER,
693 RT5640_M_SV_L_SPM_L_SFT, 1, 1),
694 SOC_DAPM_SINGLE("BST1 Switch", RT5640_SPO_L_MIXER,
695 RT5640_M_BST1_SPM_L_SFT, 1, 1),
696};
697
698static const struct snd_kcontrol_new rt5640_spo_r_mix[] = {
699 SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_SPO_R_MIXER,
700 RT5640_M_DAC_R1_SPM_R_SFT, 1, 1),
701 SOC_DAPM_SINGLE("SPKVOL R Switch", RT5640_SPO_R_MIXER,
702 RT5640_M_SV_R_SPM_R_SFT, 1, 1),
703 SOC_DAPM_SINGLE("BST1 Switch", RT5640_SPO_R_MIXER,
704 RT5640_M_BST1_SPM_R_SFT, 1, 1),
705};
706
707static const struct snd_kcontrol_new rt5640_hpo_mix[] = {
708 SOC_DAPM_SINGLE("HPO MIX DAC2 Switch", RT5640_HPO_MIXER,
709 RT5640_M_DAC2_HM_SFT, 1, 1),
710 SOC_DAPM_SINGLE("HPO MIX DAC1 Switch", RT5640_HPO_MIXER,
711 RT5640_M_DAC1_HM_SFT, 1, 1),
712 SOC_DAPM_SINGLE("HPO MIX HPVOL Switch", RT5640_HPO_MIXER,
713 RT5640_M_HPVOL_HM_SFT, 1, 1),
714};
715
716static const struct snd_kcontrol_new rt5640_lout_mix[] = {
717 SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_LOUT_MIXER,
718 RT5640_M_DAC_L1_LM_SFT, 1, 1),
719 SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_LOUT_MIXER,
720 RT5640_M_DAC_R1_LM_SFT, 1, 1),
721 SOC_DAPM_SINGLE("OUTVOL L Switch", RT5640_LOUT_MIXER,
722 RT5640_M_OV_L_LM_SFT, 1, 1),
723 SOC_DAPM_SINGLE("OUTVOL R Switch", RT5640_LOUT_MIXER,
724 RT5640_M_OV_R_LM_SFT, 1, 1),
725};
726
727static const struct snd_kcontrol_new rt5640_mono_mix[] = {
728 SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_MONO_MIXER,
729 RT5640_M_DAC_R2_MM_SFT, 1, 1),
730 SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_MONO_MIXER,
731 RT5640_M_DAC_L2_MM_SFT, 1, 1),
732 SOC_DAPM_SINGLE("OUTVOL R Switch", RT5640_MONO_MIXER,
733 RT5640_M_OV_R_MM_SFT, 1, 1),
734 SOC_DAPM_SINGLE("OUTVOL L Switch", RT5640_MONO_MIXER,
735 RT5640_M_OV_L_MM_SFT, 1, 1),
736 SOC_DAPM_SINGLE("BST1 Switch", RT5640_MONO_MIXER,
737 RT5640_M_BST1_MM_SFT, 1, 1),
738};
739
740/* INL/R source */
741static const char * const rt5640_inl_src[] = {
742 "IN2P", "MONOP"
743};
744
745static const SOC_ENUM_SINGLE_DECL(
746 rt5640_inl_enum, RT5640_INL_INR_VOL,
747 RT5640_INL_SEL_SFT, rt5640_inl_src);
748
749static const struct snd_kcontrol_new rt5640_inl_mux =
750 SOC_DAPM_ENUM("INL source", rt5640_inl_enum);
751
752static const char * const rt5640_inr_src[] = {
753 "IN2N", "MONON"
754};
755
756static const SOC_ENUM_SINGLE_DECL(
757 rt5640_inr_enum, RT5640_INL_INR_VOL,
758 RT5640_INR_SEL_SFT, rt5640_inr_src);
759
760static const struct snd_kcontrol_new rt5640_inr_mux =
761 SOC_DAPM_ENUM("INR source", rt5640_inr_enum);
762
763/* Stereo ADC source */
764static const char * const rt5640_stereo_adc1_src[] = {
765 "DIG MIX", "ADC"
766};
767
768static const SOC_ENUM_SINGLE_DECL(
769 rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER,
770 RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src);
771
772static const struct snd_kcontrol_new rt5640_sto_adc_1_mux =
773 SOC_DAPM_ENUM("Stereo ADC1 Mux", rt5640_stereo_adc1_enum);
774
775static const char * const rt5640_stereo_adc2_src[] = {
776 "DMIC1", "DMIC2", "DIG MIX"
777};
778
779static const SOC_ENUM_SINGLE_DECL(
780 rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER,
781 RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src);
782
783static const struct snd_kcontrol_new rt5640_sto_adc_2_mux =
784 SOC_DAPM_ENUM("Stereo ADC2 Mux", rt5640_stereo_adc2_enum);
785
786/* Mono ADC source */
787static const char * const rt5640_mono_adc_l1_src[] = {
788 "Mono DAC MIXL", "ADCL"
789};
790
791static const SOC_ENUM_SINGLE_DECL(
792 rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER,
793 RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src);
794
795static const struct snd_kcontrol_new rt5640_mono_adc_l1_mux =
796 SOC_DAPM_ENUM("Mono ADC1 left source", rt5640_mono_adc_l1_enum);
797
798static const char * const rt5640_mono_adc_l2_src[] = {
799 "DMIC L1", "DMIC L2", "Mono DAC MIXL"
800};
801
802static const SOC_ENUM_SINGLE_DECL(
803 rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER,
804 RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src);
805
806static const struct snd_kcontrol_new rt5640_mono_adc_l2_mux =
807 SOC_DAPM_ENUM("Mono ADC2 left source", rt5640_mono_adc_l2_enum);
808
809static const char * const rt5640_mono_adc_r1_src[] = {
810 "Mono DAC MIXR", "ADCR"
811};
812
813static const SOC_ENUM_SINGLE_DECL(
814 rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER,
815 RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src);
816
817static const struct snd_kcontrol_new rt5640_mono_adc_r1_mux =
818 SOC_DAPM_ENUM("Mono ADC1 right source", rt5640_mono_adc_r1_enum);
819
820static const char * const rt5640_mono_adc_r2_src[] = {
821 "DMIC R1", "DMIC R2", "Mono DAC MIXR"
822};
823
824static const SOC_ENUM_SINGLE_DECL(
825 rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER,
826 RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src);
827
828static const struct snd_kcontrol_new rt5640_mono_adc_r2_mux =
829 SOC_DAPM_ENUM("Mono ADC2 right source", rt5640_mono_adc_r2_enum);
830
831/* DAC2 channel source */
832static const char * const rt5640_dac_l2_src[] = {
833 "IF2", "Base L/R"
834};
835
836static int rt5640_dac_l2_values[] = {
837 0,
838 3,
839};
840
841static const SOC_VALUE_ENUM_SINGLE_DECL(
842 rt5640_dac_l2_enum, RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT,
843 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values);
844
845static const struct snd_kcontrol_new rt5640_dac_l2_mux =
846 SOC_DAPM_VALUE_ENUM("DAC2 left channel source", rt5640_dac_l2_enum);
847
848static const char * const rt5640_dac_r2_src[] = {
849 "IF2",
850};
851
852static int rt5640_dac_r2_values[] = {
853 0,
854};
855
856static const SOC_VALUE_ENUM_SINGLE_DECL(
857 rt5640_dac_r2_enum, RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT,
858 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values);
859
860static const struct snd_kcontrol_new rt5640_dac_r2_mux =
861 SOC_DAPM_ENUM("DAC2 right channel source", rt5640_dac_r2_enum);
862
863/* digital interface and iis interface map */
864static const char * const rt5640_dai_iis_map[] = {
865 "1:1|2:2", "1:2|2:1", "1:1|2:1", "1:2|2:2"
866};
867
868static int rt5640_dai_iis_map_values[] = {
869 0,
870 5,
871 6,
872 7,
873};
874
875static const SOC_VALUE_ENUM_SINGLE_DECL(
876 rt5640_dai_iis_map_enum, RT5640_I2S1_SDP, RT5640_I2S_IF_SFT,
877 0x7, rt5640_dai_iis_map, rt5640_dai_iis_map_values);
878
879static const struct snd_kcontrol_new rt5640_dai_mux =
880 SOC_DAPM_VALUE_ENUM("DAI select", rt5640_dai_iis_map_enum);
881
882/* SDI select */
883static const char * const rt5640_sdi_sel[] = {
884 "IF1", "IF2"
885};
886
887static const SOC_ENUM_SINGLE_DECL(
888 rt5640_sdi_sel_enum, RT5640_I2S2_SDP,
889 RT5640_I2S2_SDI_SFT, rt5640_sdi_sel);
890
891static const struct snd_kcontrol_new rt5640_sdi_mux =
892 SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum);
893
894static int spk_event(struct snd_soc_dapm_widget *w,
895 struct snd_kcontrol *kcontrol, int event)
896{
897 struct snd_soc_codec *codec = w->codec;
898 struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
899
900 switch (event) {
901 case SND_SOC_DAPM_POST_PMU:
902 regmap_update_bits(rt5640->regmap, RT5640_PWR_DIG1,
903 0x0001, 0x0001);
904 regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + 0x1c,
905 0xf000, 0xf000);
906 break;
907
908 case SND_SOC_DAPM_PRE_PMD:
909 regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + 0x1c,
910 0xf000, 0x0000);
911 regmap_update_bits(rt5640->regmap, RT5640_PWR_DIG1,
912 0x0001, 0x0000);
913 break;
914
915 default:
916 return 0;
917 }
918 return 0;
919}
920
921static int rt5640_set_dmic1_event(struct snd_soc_dapm_widget *w,
922 struct snd_kcontrol *kcontrol, int event)
923{
924 struct snd_soc_codec *codec = w->codec;
925
926 switch (event) {
927 case SND_SOC_DAPM_PRE_PMU:
928 snd_soc_update_bits(codec, RT5640_GPIO_CTRL1,
929 RT5640_GP2_PIN_MASK | RT5640_GP3_PIN_MASK,
930 RT5640_GP2_PIN_DMIC1_SCL | RT5640_GP3_PIN_DMIC1_SDA);
931 snd_soc_update_bits(codec, RT5640_DMIC,
932 RT5640_DMIC_1L_LH_MASK | RT5640_DMIC_1R_LH_MASK |
933 RT5640_DMIC_1_DP_MASK,
934 RT5640_DMIC_1L_LH_FALLING | RT5640_DMIC_1R_LH_RISING |
935 RT5640_DMIC_1_DP_IN1P);
936 break;
937
938 default:
939 return 0;
940 }
941
942 return 0;
943}
944
945static int rt5640_set_dmic2_event(struct snd_soc_dapm_widget *w,
946 struct snd_kcontrol *kcontrol, int event)
947{
948 struct snd_soc_codec *codec = w->codec;
949
950 switch (event) {
951 case SND_SOC_DAPM_PRE_PMU:
952 snd_soc_update_bits(codec, RT5640_GPIO_CTRL1,
953 RT5640_GP2_PIN_MASK | RT5640_GP4_PIN_MASK,
954 RT5640_GP2_PIN_DMIC1_SCL | RT5640_GP4_PIN_DMIC2_SDA);
955 snd_soc_update_bits(codec, RT5640_DMIC,
956 RT5640_DMIC_2L_LH_MASK | RT5640_DMIC_2R_LH_MASK |
957 RT5640_DMIC_2_DP_MASK,
958 RT5640_DMIC_2L_LH_FALLING | RT5640_DMIC_2R_LH_RISING |
959 RT5640_DMIC_2_DP_IN1N);
960 break;
961
962 default:
963 return 0;
964 }
965
966 return 0;
967}
968
969static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
970 SND_SOC_DAPM_SUPPLY("PLL1", RT5640_PWR_ANLG2,
971 RT5640_PWR_PLL_BIT, 0, NULL, 0),
972 /* Input Side */
973 /* micbias */
974 SND_SOC_DAPM_SUPPLY("LDO2", RT5640_PWR_ANLG1,
975 RT5640_PWR_LDO2_BIT, 0, NULL, 0),
976 SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5640_PWR_ANLG2,
977 RT5640_PWR_MB1_BIT, 0, NULL, 0),
978 /* Input Lines */
979 SND_SOC_DAPM_INPUT("DMIC1"),
980 SND_SOC_DAPM_INPUT("DMIC2"),
981 SND_SOC_DAPM_INPUT("IN1P"),
982 SND_SOC_DAPM_INPUT("IN1N"),
983 SND_SOC_DAPM_INPUT("IN2P"),
984 SND_SOC_DAPM_INPUT("IN2N"),
985 SND_SOC_DAPM_PGA("DMIC L1", SND_SOC_NOPM, 0, 0, NULL, 0),
986 SND_SOC_DAPM_PGA("DMIC R1", SND_SOC_NOPM, 0, 0, NULL, 0),
987 SND_SOC_DAPM_PGA("DMIC L2", SND_SOC_NOPM, 0, 0, NULL, 0),
988 SND_SOC_DAPM_PGA("DMIC R2", SND_SOC_NOPM, 0, 0, NULL, 0),
989
990 SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
991 set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
992 SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5640_DMIC,
993 RT5640_DMIC_1_EN_SFT, 0, rt5640_set_dmic1_event,
994 SND_SOC_DAPM_PRE_PMU),
995 SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5640_DMIC,
996 RT5640_DMIC_2_EN_SFT, 0, rt5640_set_dmic2_event,
997 SND_SOC_DAPM_PRE_PMU),
998 /* Boost */
999 SND_SOC_DAPM_PGA("BST1", RT5640_PWR_ANLG2,
1000 RT5640_PWR_BST1_BIT, 0, NULL, 0),
1001 SND_SOC_DAPM_PGA("BST2", RT5640_PWR_ANLG2,
1002 RT5640_PWR_BST4_BIT, 0, NULL, 0),
1003 /* Input Volume */
1004 SND_SOC_DAPM_PGA("INL VOL", RT5640_PWR_VOL,
1005 RT5640_PWR_IN_L_BIT, 0, NULL, 0),
1006 SND_SOC_DAPM_PGA("INR VOL", RT5640_PWR_VOL,
1007 RT5640_PWR_IN_R_BIT, 0, NULL, 0),
1008 /* IN Mux */
1009 SND_SOC_DAPM_MUX("INL Mux", SND_SOC_NOPM, 0, 0, &rt5640_inl_mux),
1010 SND_SOC_DAPM_MUX("INR Mux", SND_SOC_NOPM, 0, 0, &rt5640_inr_mux),
1011 /* REC Mixer */
1012 SND_SOC_DAPM_MIXER("RECMIXL", RT5640_PWR_MIXER, RT5640_PWR_RM_L_BIT, 0,
1013 rt5640_rec_l_mix, ARRAY_SIZE(rt5640_rec_l_mix)),
1014 SND_SOC_DAPM_MIXER("RECMIXR", RT5640_PWR_MIXER, RT5640_PWR_RM_R_BIT, 0,
1015 rt5640_rec_r_mix, ARRAY_SIZE(rt5640_rec_r_mix)),
1016 /* ADCs */
1017 SND_SOC_DAPM_ADC("ADC L", NULL, RT5640_PWR_DIG1,
1018 RT5640_PWR_ADC_L_BIT, 0),
1019 SND_SOC_DAPM_ADC("ADC R", NULL, RT5640_PWR_DIG1,
1020 RT5640_PWR_ADC_R_BIT, 0),
1021 /* ADC Mux */
1022 SND_SOC_DAPM_MUX("Stereo ADC L2 Mux", SND_SOC_NOPM, 0, 0,
1023 &rt5640_sto_adc_2_mux),
1024 SND_SOC_DAPM_MUX("Stereo ADC R2 Mux", SND_SOC_NOPM, 0, 0,
1025 &rt5640_sto_adc_2_mux),
1026 SND_SOC_DAPM_MUX("Stereo ADC L1 Mux", SND_SOC_NOPM, 0, 0,
1027 &rt5640_sto_adc_1_mux),
1028 SND_SOC_DAPM_MUX("Stereo ADC R1 Mux", SND_SOC_NOPM, 0, 0,
1029 &rt5640_sto_adc_1_mux),
1030 SND_SOC_DAPM_MUX("Mono ADC L2 Mux", SND_SOC_NOPM, 0, 0,
1031 &rt5640_mono_adc_l2_mux),
1032 SND_SOC_DAPM_MUX("Mono ADC L1 Mux", SND_SOC_NOPM, 0, 0,
1033 &rt5640_mono_adc_l1_mux),
1034 SND_SOC_DAPM_MUX("Mono ADC R1 Mux", SND_SOC_NOPM, 0, 0,
1035 &rt5640_mono_adc_r1_mux),
1036 SND_SOC_DAPM_MUX("Mono ADC R2 Mux", SND_SOC_NOPM, 0, 0,
1037 &rt5640_mono_adc_r2_mux),
1038 /* ADC Mixer */
1039 SND_SOC_DAPM_SUPPLY("Stereo Filter", RT5640_PWR_DIG2,
1040 RT5640_PWR_ADC_SF_BIT, 0, NULL, 0),
1041 SND_SOC_DAPM_MIXER("Stereo ADC MIXL", SND_SOC_NOPM, 0, 0,
1042 rt5640_sto_adc_l_mix, ARRAY_SIZE(rt5640_sto_adc_l_mix)),
1043 SND_SOC_DAPM_MIXER("Stereo ADC MIXR", SND_SOC_NOPM, 0, 0,
1044 rt5640_sto_adc_r_mix, ARRAY_SIZE(rt5640_sto_adc_r_mix)),
1045 SND_SOC_DAPM_SUPPLY("Mono Left Filter", RT5640_PWR_DIG2,
1046 RT5640_PWR_ADC_MF_L_BIT, 0, NULL, 0),
1047 SND_SOC_DAPM_MIXER("Mono ADC MIXL", SND_SOC_NOPM, 0, 0,
1048 rt5640_mono_adc_l_mix, ARRAY_SIZE(rt5640_mono_adc_l_mix)),
1049 SND_SOC_DAPM_SUPPLY("Mono Right Filter", RT5640_PWR_DIG2,
1050 RT5640_PWR_ADC_MF_R_BIT, 0, NULL, 0),
1051 SND_SOC_DAPM_MIXER("Mono ADC MIXR", SND_SOC_NOPM, 0, 0,
1052 rt5640_mono_adc_r_mix, ARRAY_SIZE(rt5640_mono_adc_r_mix)),
1053
1054 /* Digital Interface */
1055 SND_SOC_DAPM_SUPPLY("I2S1", RT5640_PWR_DIG1,
1056 RT5640_PWR_I2S1_BIT, 0, NULL, 0),
1057 SND_SOC_DAPM_PGA("IF1 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
1058 SND_SOC_DAPM_PGA("IF1 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
1059 SND_SOC_DAPM_PGA("IF1 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
1060 SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
1061 SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0),
1062 SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0),
1063 SND_SOC_DAPM_SUPPLY("I2S2", RT5640_PWR_DIG1,
1064 RT5640_PWR_I2S2_BIT, 0, NULL, 0),
1065 SND_SOC_DAPM_PGA("IF2 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
1066 SND_SOC_DAPM_PGA("IF2 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
1067 SND_SOC_DAPM_PGA("IF2 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
1068 SND_SOC_DAPM_PGA("IF2 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
1069 SND_SOC_DAPM_PGA("IF2 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0),
1070 SND_SOC_DAPM_PGA("IF2 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0),
1071 /* Digital Interface Select */
1072 SND_SOC_DAPM_MUX("DAI1 RX Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux),
1073 SND_SOC_DAPM_MUX("DAI1 TX Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux),
1074 SND_SOC_DAPM_MUX("DAI1 IF1 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux),
1075 SND_SOC_DAPM_MUX("DAI1 IF2 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux),
1076 SND_SOC_DAPM_MUX("SDI1 TX Mux", SND_SOC_NOPM, 0, 0, &rt5640_sdi_mux),
1077 SND_SOC_DAPM_MUX("DAI2 RX Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux),
1078 SND_SOC_DAPM_MUX("DAI2 TX Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux),
1079 SND_SOC_DAPM_MUX("DAI2 IF1 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux),
1080 SND_SOC_DAPM_MUX("DAI2 IF2 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dai_mux),
1081 SND_SOC_DAPM_MUX("SDI2 TX Mux", SND_SOC_NOPM, 0, 0, &rt5640_sdi_mux),
1082 /* Audio Interface */
1083 SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
1084 SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
1085 SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
1086 SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
1087 /* Audio DSP */
1088 SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
1089 /* ANC */
1090 SND_SOC_DAPM_PGA("ANC", SND_SOC_NOPM, 0, 0, NULL, 0),
1091 /* Output Side */
1092 /* DAC mixer before sound effect */
1093 SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
1094 rt5640_dac_l_mix, ARRAY_SIZE(rt5640_dac_l_mix)),
1095 SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
1096 rt5640_dac_r_mix, ARRAY_SIZE(rt5640_dac_r_mix)),
1097 /* DAC2 channel Mux */
1098 SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0,
1099 &rt5640_dac_l2_mux),
1100 SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0,
1101 &rt5640_dac_r2_mux),
1102 /* DAC Mixer */
1103 SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
1104 rt5640_sto_dac_l_mix, ARRAY_SIZE(rt5640_sto_dac_l_mix)),
1105 SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
1106 rt5640_sto_dac_r_mix, ARRAY_SIZE(rt5640_sto_dac_r_mix)),
1107 SND_SOC_DAPM_MIXER("Mono DAC MIXL", SND_SOC_NOPM, 0, 0,
1108 rt5640_mono_dac_l_mix, ARRAY_SIZE(rt5640_mono_dac_l_mix)),
1109 SND_SOC_DAPM_MIXER("Mono DAC MIXR", SND_SOC_NOPM, 0, 0,
1110 rt5640_mono_dac_r_mix, ARRAY_SIZE(rt5640_mono_dac_r_mix)),
1111 SND_SOC_DAPM_MIXER("DIG MIXL", SND_SOC_NOPM, 0, 0,
1112 rt5640_dig_l_mix, ARRAY_SIZE(rt5640_dig_l_mix)),
1113 SND_SOC_DAPM_MIXER("DIG MIXR", SND_SOC_NOPM, 0, 0,
1114 rt5640_dig_r_mix, ARRAY_SIZE(rt5640_dig_r_mix)),
1115 /* DACs */
1116 SND_SOC_DAPM_DAC("DAC L1", NULL, RT5640_PWR_DIG1,
1117 RT5640_PWR_DAC_L1_BIT, 0),
1118 SND_SOC_DAPM_DAC("DAC L2", NULL, RT5640_PWR_DIG1,
1119 RT5640_PWR_DAC_L2_BIT, 0),
1120 SND_SOC_DAPM_DAC("DAC R1", NULL, RT5640_PWR_DIG1,
1121 RT5640_PWR_DAC_R1_BIT, 0),
1122 SND_SOC_DAPM_DAC("DAC R2", NULL, RT5640_PWR_DIG1,
1123 RT5640_PWR_DAC_R2_BIT, 0),
1124 /* SPK/OUT Mixer */
1125 SND_SOC_DAPM_MIXER("SPK MIXL", RT5640_PWR_MIXER, RT5640_PWR_SM_L_BIT,
1126 0, rt5640_spk_l_mix, ARRAY_SIZE(rt5640_spk_l_mix)),
1127 SND_SOC_DAPM_MIXER("SPK MIXR", RT5640_PWR_MIXER, RT5640_PWR_SM_R_BIT,
1128 0, rt5640_spk_r_mix, ARRAY_SIZE(rt5640_spk_r_mix)),
1129 SND_SOC_DAPM_MIXER("OUT MIXL", RT5640_PWR_MIXER, RT5640_PWR_OM_L_BIT,
1130 0, rt5640_out_l_mix, ARRAY_SIZE(rt5640_out_l_mix)),
1131 SND_SOC_DAPM_MIXER("OUT MIXR", RT5640_PWR_MIXER, RT5640_PWR_OM_R_BIT,
1132 0, rt5640_out_r_mix, ARRAY_SIZE(rt5640_out_r_mix)),
1133 /* Ouput Volume */
1134 SND_SOC_DAPM_PGA("SPKVOL L", RT5640_PWR_VOL,
1135 RT5640_PWR_SV_L_BIT, 0, NULL, 0),
1136 SND_SOC_DAPM_PGA("SPKVOL R", RT5640_PWR_VOL,
1137 RT5640_PWR_SV_R_BIT, 0, NULL, 0),
1138 SND_SOC_DAPM_PGA("OUTVOL L", RT5640_PWR_VOL,
1139 RT5640_PWR_OV_L_BIT, 0, NULL, 0),
1140 SND_SOC_DAPM_PGA("OUTVOL R", RT5640_PWR_VOL,
1141 RT5640_PWR_OV_R_BIT, 0, NULL, 0),
1142 SND_SOC_DAPM_PGA("HPOVOL L", RT5640_PWR_VOL,
1143 RT5640_PWR_HV_L_BIT, 0, NULL, 0),
1144 SND_SOC_DAPM_PGA("HPOVOL R", RT5640_PWR_VOL,
1145 RT5640_PWR_HV_R_BIT, 0, NULL, 0),
1146 /* SPO/HPO/LOUT/Mono Mixer */
1147 SND_SOC_DAPM_MIXER("SPOL MIX", SND_SOC_NOPM, 0,
1148 0, rt5640_spo_l_mix, ARRAY_SIZE(rt5640_spo_l_mix)),
1149 SND_SOC_DAPM_MIXER("SPOR MIX", SND_SOC_NOPM, 0,
1150 0, rt5640_spo_r_mix, ARRAY_SIZE(rt5640_spo_r_mix)),
1151 SND_SOC_DAPM_MIXER("HPO MIX L", SND_SOC_NOPM, 0, 0,
1152 rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
1153 SND_SOC_DAPM_MIXER("HPO MIX R", SND_SOC_NOPM, 0, 0,
1154 rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
1155 SND_SOC_DAPM_MIXER("LOUT MIX", RT5640_PWR_ANLG1, RT5640_PWR_LM_BIT, 0,
1156 rt5640_lout_mix, ARRAY_SIZE(rt5640_lout_mix)),
1157 SND_SOC_DAPM_MIXER("Mono MIX", RT5640_PWR_ANLG1, RT5640_PWR_MM_BIT, 0,
1158 rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)),
1159 SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1,
1160 RT5640_PWR_MA_BIT, 0, NULL, 0),
1161 SND_SOC_DAPM_SUPPLY("Improve HP Amp Drv", RT5640_PWR_ANLG1,
1162 SND_SOC_NOPM, 0, NULL, 0),
1163 SND_SOC_DAPM_PGA("HP L Amp", RT5640_PWR_ANLG1,
1164 RT5640_PWR_HP_L_BIT, 0, NULL, 0),
1165 SND_SOC_DAPM_PGA("HP R Amp", RT5640_PWR_ANLG1,
1166 RT5640_PWR_HP_R_BIT, 0, NULL, 0),
1167 SND_SOC_DAPM_SUPPLY("Improve SPK Amp Drv", RT5640_PWR_DIG1,
1168 SND_SOC_NOPM, 0, spk_event,
1169 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
1170 /* Output Lines */
1171 SND_SOC_DAPM_OUTPUT("SPOLP"),
1172 SND_SOC_DAPM_OUTPUT("SPOLN"),
1173 SND_SOC_DAPM_OUTPUT("SPORP"),
1174 SND_SOC_DAPM_OUTPUT("SPORN"),
1175 SND_SOC_DAPM_OUTPUT("HPOL"),
1176 SND_SOC_DAPM_OUTPUT("HPOR"),
1177 SND_SOC_DAPM_OUTPUT("LOUTL"),
1178 SND_SOC_DAPM_OUTPUT("LOUTR"),
1179 SND_SOC_DAPM_OUTPUT("MONOP"),
1180 SND_SOC_DAPM_OUTPUT("MONON"),
1181};
1182
1183static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
1184 {"IN1P", NULL, "LDO2"},
1185 {"IN2P", NULL, "LDO2"},
1186
1187 {"DMIC L1", NULL, "DMIC1"},
1188 {"DMIC R1", NULL, "DMIC1"},
1189 {"DMIC L2", NULL, "DMIC2"},
1190 {"DMIC R2", NULL, "DMIC2"},
1191
1192 {"BST1", NULL, "IN1P"},
1193 {"BST1", NULL, "IN1N"},
1194 {"BST2", NULL, "IN2P"},
1195 {"BST2", NULL, "IN2N"},
1196
1197 {"INL VOL", NULL, "IN2P"},
1198 {"INR VOL", NULL, "IN2N"},
1199
1200 {"RECMIXL", "HPOL Switch", "HPOL"},
1201 {"RECMIXL", "INL Switch", "INL VOL"},
1202 {"RECMIXL", "BST2 Switch", "BST2"},
1203 {"RECMIXL", "BST1 Switch", "BST1"},
1204 {"RECMIXL", "OUT MIXL Switch", "OUT MIXL"},
1205
1206 {"RECMIXR", "HPOR Switch", "HPOR"},
1207 {"RECMIXR", "INR Switch", "INR VOL"},
1208 {"RECMIXR", "BST2 Switch", "BST2"},
1209 {"RECMIXR", "BST1 Switch", "BST1"},
1210 {"RECMIXR", "OUT MIXR Switch", "OUT MIXR"},
1211
1212 {"ADC L", NULL, "RECMIXL"},
1213 {"ADC R", NULL, "RECMIXR"},
1214
1215 {"DMIC L1", NULL, "DMIC CLK"},
1216 {"DMIC L1", NULL, "DMIC1 Power"},
1217 {"DMIC R1", NULL, "DMIC CLK"},
1218 {"DMIC R1", NULL, "DMIC1 Power"},
1219 {"DMIC L2", NULL, "DMIC CLK"},
1220 {"DMIC L2", NULL, "DMIC2 Power"},
1221 {"DMIC R2", NULL, "DMIC CLK"},
1222 {"DMIC R2", NULL, "DMIC2 Power"},
1223
1224 {"Stereo ADC L2 Mux", "DMIC1", "DMIC L1"},
1225 {"Stereo ADC L2 Mux", "DMIC2", "DMIC L2"},
1226 {"Stereo ADC L2 Mux", "DIG MIX", "DIG MIXL"},
1227 {"Stereo ADC L1 Mux", "ADC", "ADC L"},
1228 {"Stereo ADC L1 Mux", "DIG MIX", "DIG MIXL"},
1229
1230 {"Stereo ADC R1 Mux", "ADC", "ADC R"},
1231 {"Stereo ADC R1 Mux", "DIG MIX", "DIG MIXR"},
1232 {"Stereo ADC R2 Mux", "DMIC1", "DMIC R1"},
1233 {"Stereo ADC R2 Mux", "DMIC2", "DMIC R2"},
1234 {"Stereo ADC R2 Mux", "DIG MIX", "DIG MIXR"},
1235
1236 {"Mono ADC L2 Mux", "DMIC L1", "DMIC L1"},
1237 {"Mono ADC L2 Mux", "DMIC L2", "DMIC L2"},
1238 {"Mono ADC L2 Mux", "Mono DAC MIXL", "Mono DAC MIXL"},
1239 {"Mono ADC L1 Mux", "Mono DAC MIXL", "Mono DAC MIXL"},
1240 {"Mono ADC L1 Mux", "ADCL", "ADC L"},
1241
1242 {"Mono ADC R1 Mux", "Mono DAC MIXR", "Mono DAC MIXR"},
1243 {"Mono ADC R1 Mux", "ADCR", "ADC R"},
1244 {"Mono ADC R2 Mux", "DMIC R1", "DMIC R1"},
1245 {"Mono ADC R2 Mux", "DMIC R2", "DMIC R2"},
1246 {"Mono ADC R2 Mux", "Mono DAC MIXR", "Mono DAC MIXR"},
1247
1248 {"Stereo ADC MIXL", "ADC1 Switch", "Stereo ADC L1 Mux"},
1249 {"Stereo ADC MIXL", "ADC2 Switch", "Stereo ADC L2 Mux"},
1250 {"Stereo ADC MIXL", NULL, "Stereo Filter"},
1251 {"Stereo Filter", NULL, "PLL1", check_sysclk1_source},
1252
1253 {"Stereo ADC MIXR", "ADC1 Switch", "Stereo ADC R1 Mux"},
1254 {"Stereo ADC MIXR", "ADC2 Switch", "Stereo ADC R2 Mux"},
1255 {"Stereo ADC MIXR", NULL, "Stereo Filter"},
1256 {"Stereo Filter", NULL, "PLL1", check_sysclk1_source},
1257
1258 {"Mono ADC MIXL", "ADC1 Switch", "Mono ADC L1 Mux"},
1259 {"Mono ADC MIXL", "ADC2 Switch", "Mono ADC L2 Mux"},
1260 {"Mono ADC MIXL", NULL, "Mono Left Filter"},
1261 {"Mono Left Filter", NULL, "PLL1", check_sysclk1_source},
1262
1263 {"Mono ADC MIXR", "ADC1 Switch", "Mono ADC R1 Mux"},
1264 {"Mono ADC MIXR", "ADC2 Switch", "Mono ADC R2 Mux"},
1265 {"Mono ADC MIXR", NULL, "Mono Right Filter"},
1266 {"Mono Right Filter", NULL, "PLL1", check_sysclk1_source},
1267
1268 {"IF2 ADC L", NULL, "Mono ADC MIXL"},
1269 {"IF2 ADC R", NULL, "Mono ADC MIXR"},
1270 {"IF1 ADC L", NULL, "Stereo ADC MIXL"},
1271 {"IF1 ADC R", NULL, "Stereo ADC MIXR"},
1272
1273 {"IF1 ADC", NULL, "I2S1"},
1274 {"IF1 ADC", NULL, "IF1 ADC L"},
1275 {"IF1 ADC", NULL, "IF1 ADC R"},
1276 {"IF2 ADC", NULL, "I2S2"},
1277 {"IF2 ADC", NULL, "IF2 ADC L"},
1278 {"IF2 ADC", NULL, "IF2 ADC R"},
1279
1280 {"DAI1 TX Mux", "1:1|2:2", "IF1 ADC"},
1281 {"DAI1 TX Mux", "1:2|2:1", "IF2 ADC"},
1282 {"DAI1 IF1 Mux", "1:1|2:1", "IF1 ADC"},
1283 {"DAI1 IF2 Mux", "1:1|2:1", "IF2 ADC"},
1284 {"SDI1 TX Mux", "IF1", "DAI1 IF1 Mux"},
1285 {"SDI1 TX Mux", "IF2", "DAI1 IF2 Mux"},
1286
1287 {"DAI2 TX Mux", "1:2|2:1", "IF1 ADC"},
1288 {"DAI2 TX Mux", "1:1|2:2", "IF2 ADC"},
1289 {"DAI2 IF1 Mux", "1:2|2:2", "IF1 ADC"},
1290 {"DAI2 IF2 Mux", "1:2|2:2", "IF2 ADC"},
1291 {"SDI2 TX Mux", "IF1", "DAI2 IF1 Mux"},
1292 {"SDI2 TX Mux", "IF2", "DAI2 IF2 Mux"},
1293
1294 {"AIF1TX", NULL, "DAI1 TX Mux"},
1295 {"AIF1TX", NULL, "SDI1 TX Mux"},
1296 {"AIF2TX", NULL, "DAI2 TX Mux"},
1297 {"AIF2TX", NULL, "SDI2 TX Mux"},
1298
1299 {"DAI1 RX Mux", "1:1|2:2", "AIF1RX"},
1300 {"DAI1 RX Mux", "1:1|2:1", "AIF1RX"},
1301 {"DAI1 RX Mux", "1:2|2:1", "AIF2RX"},
1302 {"DAI1 RX Mux", "1:2|2:2", "AIF2RX"},
1303
1304 {"DAI2 RX Mux", "1:2|2:1", "AIF1RX"},
1305 {"DAI2 RX Mux", "1:1|2:1", "AIF1RX"},
1306 {"DAI2 RX Mux", "1:1|2:2", "AIF2RX"},
1307 {"DAI2 RX Mux", "1:2|2:2", "AIF2RX"},
1308
1309 {"IF1 DAC", NULL, "I2S1"},
1310 {"IF1 DAC", NULL, "DAI1 RX Mux"},
1311 {"IF2 DAC", NULL, "I2S2"},
1312 {"IF2 DAC", NULL, "DAI2 RX Mux"},
1313
1314 {"IF1 DAC L", NULL, "IF1 DAC"},
1315 {"IF1 DAC R", NULL, "IF1 DAC"},
1316 {"IF2 DAC L", NULL, "IF2 DAC"},
1317 {"IF2 DAC R", NULL, "IF2 DAC"},
1318
1319 {"DAC MIXL", "Stereo ADC Switch", "Stereo ADC MIXL"},
1320 {"DAC MIXL", "INF1 Switch", "IF1 DAC L"},
1321 {"DAC MIXR", "Stereo ADC Switch", "Stereo ADC MIXR"},
1322 {"DAC MIXR", "INF1 Switch", "IF1 DAC R"},
1323
1324 {"ANC", NULL, "Stereo ADC MIXL"},
1325 {"ANC", NULL, "Stereo ADC MIXR"},
1326
1327 {"Audio DSP", NULL, "DAC MIXL"},
1328 {"Audio DSP", NULL, "DAC MIXR"},
1329
1330 {"DAC L2 Mux", "IF2", "IF2 DAC L"},
1331 {"DAC L2 Mux", "Base L/R", "Audio DSP"},
1332
1333 {"DAC R2 Mux", "IF2", "IF2 DAC R"},
1334
1335 {"Stereo DAC MIXL", "DAC L1 Switch", "DAC MIXL"},
1336 {"Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
1337 {"Stereo DAC MIXL", "ANC Switch", "ANC"},
1338 {"Stereo DAC MIXR", "DAC R1 Switch", "DAC MIXR"},
1339 {"Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
1340 {"Stereo DAC MIXR", "ANC Switch", "ANC"},
1341
1342 {"Mono DAC MIXL", "DAC L1 Switch", "DAC MIXL"},
1343 {"Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
1344 {"Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Mux"},
1345 {"Mono DAC MIXR", "DAC R1 Switch", "DAC MIXR"},
1346 {"Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
1347 {"Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Mux"},
1348
1349 {"DIG MIXL", "DAC L1 Switch", "DAC MIXL"},
1350 {"DIG MIXL", "DAC L2 Switch", "DAC L2 Mux"},
1351 {"DIG MIXR", "DAC R1 Switch", "DAC MIXR"},
1352 {"DIG MIXR", "DAC R2 Switch", "DAC R2 Mux"},
1353
1354 {"DAC L1", NULL, "Stereo DAC MIXL"},
1355 {"DAC L1", NULL, "PLL1", check_sysclk1_source},
1356 {"DAC R1", NULL, "Stereo DAC MIXR"},
1357 {"DAC R1", NULL, "PLL1", check_sysclk1_source},
1358 {"DAC L2", NULL, "Mono DAC MIXL"},
1359 {"DAC L2", NULL, "PLL1", check_sysclk1_source},
1360 {"DAC R2", NULL, "Mono DAC MIXR"},
1361 {"DAC R2", NULL, "PLL1", check_sysclk1_source},
1362
1363 {"SPK MIXL", "REC MIXL Switch", "RECMIXL"},
1364 {"SPK MIXL", "INL Switch", "INL VOL"},
1365 {"SPK MIXL", "DAC L1 Switch", "DAC L1"},
1366 {"SPK MIXL", "DAC L2 Switch", "DAC L2"},
1367 {"SPK MIXL", "OUT MIXL Switch", "OUT MIXL"},
1368 {"SPK MIXR", "REC MIXR Switch", "RECMIXR"},
1369 {"SPK MIXR", "INR Switch", "INR VOL"},
1370 {"SPK MIXR", "DAC R1 Switch", "DAC R1"},
1371 {"SPK MIXR", "DAC R2 Switch", "DAC R2"},
1372 {"SPK MIXR", "OUT MIXR Switch", "OUT MIXR"},
1373
1374 {"OUT MIXL", "SPK MIXL Switch", "SPK MIXL"},
1375 {"OUT MIXL", "BST1 Switch", "BST1"},
1376 {"OUT MIXL", "INL Switch", "INL VOL"},
1377 {"OUT MIXL", "REC MIXL Switch", "RECMIXL"},
1378 {"OUT MIXL", "DAC R2 Switch", "DAC R2"},
1379 {"OUT MIXL", "DAC L2 Switch", "DAC L2"},
1380 {"OUT MIXL", "DAC L1 Switch", "DAC L1"},
1381
1382 {"OUT MIXR", "SPK MIXR Switch", "SPK MIXR"},
1383 {"OUT MIXR", "BST2 Switch", "BST2"},
1384 {"OUT MIXR", "BST1 Switch", "BST1"},
1385 {"OUT MIXR", "INR Switch", "INR VOL"},
1386 {"OUT MIXR", "REC MIXR Switch", "RECMIXR"},
1387 {"OUT MIXR", "DAC L2 Switch", "DAC L2"},
1388 {"OUT MIXR", "DAC R2 Switch", "DAC R2"},
1389 {"OUT MIXR", "DAC R1 Switch", "DAC R1"},
1390
1391 {"SPKVOL L", NULL, "SPK MIXL"},
1392 {"SPKVOL R", NULL, "SPK MIXR"},
1393 {"HPOVOL L", NULL, "OUT MIXL"},
1394 {"HPOVOL R", NULL, "OUT MIXR"},
1395 {"OUTVOL L", NULL, "OUT MIXL"},
1396 {"OUTVOL R", NULL, "OUT MIXR"},
1397
1398 {"SPOL MIX", "DAC R1 Switch", "DAC R1"},
1399 {"SPOL MIX", "DAC L1 Switch", "DAC L1"},
1400 {"SPOL MIX", "SPKVOL R Switch", "SPKVOL R"},
1401 {"SPOL MIX", "SPKVOL L Switch", "SPKVOL L"},
1402 {"SPOL MIX", "BST1 Switch", "BST1"},
1403 {"SPOR MIX", "DAC R1 Switch", "DAC R1"},
1404 {"SPOR MIX", "SPKVOL R Switch", "SPKVOL R"},
1405 {"SPOR MIX", "BST1 Switch", "BST1"},
1406
1407 {"HPO MIX L", "HPO MIX DAC2 Switch", "DAC L2"},
1408 {"HPO MIX L", "HPO MIX DAC1 Switch", "DAC L1"},
1409 {"HPO MIX L", "HPO MIX HPVOL Switch", "HPOVOL L"},
1410 {"HPO MIX R", "HPO MIX DAC2 Switch", "DAC R2"},
1411 {"HPO MIX R", "HPO MIX DAC1 Switch", "DAC R1"},
1412 {"HPO MIX R", "HPO MIX HPVOL Switch", "HPOVOL R"},
1413
1414 {"LOUT MIX", "DAC L1 Switch", "DAC L1"},
1415 {"LOUT MIX", "DAC R1 Switch", "DAC R1"},
1416 {"LOUT MIX", "OUTVOL L Switch", "OUTVOL L"},
1417 {"LOUT MIX", "OUTVOL R Switch", "OUTVOL R"},
1418
1419 {"Mono MIX", "DAC R2 Switch", "DAC R2"},
1420 {"Mono MIX", "DAC L2 Switch", "DAC L2"},
1421 {"Mono MIX", "OUTVOL R Switch", "OUTVOL R"},
1422 {"Mono MIX", "OUTVOL L Switch", "OUTVOL L"},
1423 {"Mono MIX", "BST1 Switch", "BST1"},
1424
1425 {"HP L Amp", NULL, "HPO MIX L"},
1426 {"HP R Amp", NULL, "HPO MIX R"},
1427
1428 {"SPOLP", NULL, "SPOL MIX"},
1429 {"SPOLN", NULL, "SPOL MIX"},
1430 {"SPORP", NULL, "SPOR MIX"},
1431 {"SPORN", NULL, "SPOR MIX"},
1432
1433 {"SPOLP", NULL, "Improve SPK Amp Drv"},
1434 {"SPOLN", NULL, "Improve SPK Amp Drv"},
1435 {"SPORP", NULL, "Improve SPK Amp Drv"},
1436 {"SPORN", NULL, "Improve SPK Amp Drv"},
1437
1438 {"HPOL", NULL, "Improve HP Amp Drv"},
1439 {"HPOR", NULL, "Improve HP Amp Drv"},
1440
1441 {"HPOL", NULL, "HP L Amp"},
1442 {"HPOR", NULL, "HP R Amp"},
1443 {"LOUTL", NULL, "LOUT MIX"},
1444 {"LOUTR", NULL, "LOUT MIX"},
1445 {"MONOP", NULL, "Mono MIX"},
1446 {"MONON", NULL, "Mono MIX"},
1447 {"MONOP", NULL, "Improve MONO Amp Drv"},
1448};
1449
1450static int get_sdp_info(struct snd_soc_codec *codec, int dai_id)
1451{
1452 int ret = 0, val;
1453
1454 if (codec == NULL)
1455 return -EINVAL;
1456
1457 val = snd_soc_read(codec, RT5640_I2S1_SDP);
1458 val = (val & RT5640_I2S_IF_MASK) >> RT5640_I2S_IF_SFT;
1459 switch (dai_id) {
1460 case RT5640_AIF1:
1461 switch (val) {
1462 case RT5640_IF_123:
1463 case RT5640_IF_132:
1464 ret |= RT5640_U_IF1;
1465 break;
1466 case RT5640_IF_113:
1467 ret |= RT5640_U_IF1;
1468 case RT5640_IF_312:
1469 case RT5640_IF_213:
1470 ret |= RT5640_U_IF2;
1471 break;
1472 }
1473 break;
1474
1475 case RT5640_AIF2:
1476 switch (val) {
1477 case RT5640_IF_231:
1478 case RT5640_IF_213:
1479 ret |= RT5640_U_IF1;
1480 break;
1481 case RT5640_IF_223:
1482 ret |= RT5640_U_IF1;
1483 case RT5640_IF_123:
1484 case RT5640_IF_321:
1485 ret |= RT5640_U_IF2;
1486 break;
1487 }
1488 break;
1489
1490 default:
1491 ret = -EINVAL;
1492 break;
1493 }
1494
1495 return ret;
1496}
1497
1498static int get_clk_info(int sclk, int rate)
1499{
1500 int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
1501
1502 if (sclk <= 0 || rate <= 0)
1503 return -EINVAL;
1504
1505 rate = rate << 8;
1506 for (i = 0; i < ARRAY_SIZE(pd); i++)
1507 if (sclk == rate * pd[i])
1508 return i;
1509
1510 return -EINVAL;
1511}
1512
1513static int rt5640_hw_params(struct snd_pcm_substream *substream,
1514 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
1515{
1516 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1517 struct snd_soc_codec *codec = rtd->codec;
1518 struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
1519 unsigned int val_len = 0, val_clk, mask_clk, dai_sel;
1520 int pre_div, bclk_ms, frame_size;
1521
1522 rt5640->lrck[dai->id] = params_rate(params);
1523 pre_div = get_clk_info(rt5640->sysclk, rt5640->lrck[dai->id]);
1524 if (pre_div < 0) {
1525 dev_err(codec->dev, "Unsupported clock setting\n");
1526 return -EINVAL;
1527 }
1528 frame_size = snd_soc_params_to_frame_size(params);
1529 if (frame_size < 0) {
1530 dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size);
1531 return frame_size;
1532 }
1533 if (frame_size > 32)
1534 bclk_ms = 1;
1535 else
1536 bclk_ms = 0;
1537 rt5640->bclk[dai->id] = rt5640->lrck[dai->id] * (32 << bclk_ms);
1538
1539 dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n",
1540 rt5640->bclk[dai->id], rt5640->lrck[dai->id]);
1541 dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
1542 bclk_ms, pre_div, dai->id);
1543
1544 switch (params_format(params)) {
1545 case SNDRV_PCM_FORMAT_S16_LE:
1546 break;
1547 case SNDRV_PCM_FORMAT_S20_3LE:
1548 val_len |= RT5640_I2S_DL_20;
1549 break;
1550 case SNDRV_PCM_FORMAT_S24_LE:
1551 val_len |= RT5640_I2S_DL_24;
1552 break;
1553 case SNDRV_PCM_FORMAT_S8:
1554 val_len |= RT5640_I2S_DL_8;
1555 break;
1556 default:
1557 return -EINVAL;
1558 }
1559
1560 dai_sel = get_sdp_info(codec, dai->id);
1561 if (dai_sel < 0) {
1562 dev_err(codec->dev, "Failed to get sdp info: %d\n", dai_sel);
1563 return -EINVAL;
1564 }
1565 if (dai_sel & RT5640_U_IF1) {
1566 mask_clk = RT5640_I2S_BCLK_MS1_MASK | RT5640_I2S_PD1_MASK;
1567 val_clk = bclk_ms << RT5640_I2S_BCLK_MS1_SFT |
1568 pre_div << RT5640_I2S_PD1_SFT;
1569 snd_soc_update_bits(codec, RT5640_I2S1_SDP,
1570 RT5640_I2S_DL_MASK, val_len);
1571 snd_soc_update_bits(codec, RT5640_ADDA_CLK1, mask_clk, val_clk);
1572 }
1573 if (dai_sel & RT5640_U_IF2) {
1574 mask_clk = RT5640_I2S_BCLK_MS2_MASK | RT5640_I2S_PD2_MASK;
1575 val_clk = bclk_ms << RT5640_I2S_BCLK_MS2_SFT |
1576 pre_div << RT5640_I2S_PD2_SFT;
1577 snd_soc_update_bits(codec, RT5640_I2S2_SDP,
1578 RT5640_I2S_DL_MASK, val_len);
1579 snd_soc_update_bits(codec, RT5640_ADDA_CLK1, mask_clk, val_clk);
1580 }
1581
1582 return 0;
1583}
1584
1585static int rt5640_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1586{
1587 struct snd_soc_codec *codec = dai->codec;
1588 struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
1589 unsigned int reg_val = 0, dai_sel;
1590
1591 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1592 case SND_SOC_DAIFMT_CBM_CFM:
1593 rt5640->master[dai->id] = 1;
1594 break;
1595 case SND_SOC_DAIFMT_CBS_CFS:
1596 reg_val |= RT5640_I2S_MS_S;
1597 rt5640->master[dai->id] = 0;
1598 break;
1599 default:
1600 return -EINVAL;
1601 }
1602
1603 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1604 case SND_SOC_DAIFMT_NB_NF:
1605 break;
1606 case SND_SOC_DAIFMT_IB_NF:
1607 reg_val |= RT5640_I2S_BP_INV;
1608 break;
1609 default:
1610 return -EINVAL;
1611 }
1612
1613 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1614 case SND_SOC_DAIFMT_I2S:
1615 break;
1616 case SND_SOC_DAIFMT_LEFT_J:
1617 reg_val |= RT5640_I2S_DF_LEFT;
1618 break;
1619 case SND_SOC_DAIFMT_DSP_A:
1620 reg_val |= RT5640_I2S_DF_PCM_A;
1621 break;
1622 case SND_SOC_DAIFMT_DSP_B:
1623 reg_val |= RT5640_I2S_DF_PCM_B;
1624 break;
1625 default:
1626 return -EINVAL;
1627 }
1628
1629 dai_sel = get_sdp_info(codec, dai->id);
1630 if (dai_sel < 0) {
1631 dev_err(codec->dev, "Failed to get sdp info: %d\n", dai_sel);
1632 return -EINVAL;
1633 }
1634 if (dai_sel & RT5640_U_IF1) {
1635 snd_soc_update_bits(codec, RT5640_I2S1_SDP,
1636 RT5640_I2S_MS_MASK | RT5640_I2S_BP_MASK |
1637 RT5640_I2S_DF_MASK, reg_val);
1638 }
1639 if (dai_sel & RT5640_U_IF2) {
1640 snd_soc_update_bits(codec, RT5640_I2S2_SDP,
1641 RT5640_I2S_MS_MASK | RT5640_I2S_BP_MASK |
1642 RT5640_I2S_DF_MASK, reg_val);
1643 }
1644
1645 return 0;
1646}
1647
1648static int rt5640_set_dai_sysclk(struct snd_soc_dai *dai,
1649 int clk_id, unsigned int freq, int dir)
1650{
1651 struct snd_soc_codec *codec = dai->codec;
1652 struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
1653 unsigned int reg_val = 0;
1654
1655 if (freq == rt5640->sysclk && clk_id == rt5640->sysclk_src)
1656 return 0;
1657
1658 switch (clk_id) {
1659 case RT5640_SCLK_S_MCLK:
1660 reg_val |= RT5640_SCLK_SRC_MCLK;
1661 break;
1662 case RT5640_SCLK_S_PLL1:
1663 reg_val |= RT5640_SCLK_SRC_PLL1;
1664 break;
1665 case RT5640_SCLK_S_PLL1_TK:
1666 reg_val |= RT5640_SCLK_SRC_PLL1T;
1667 break;
1668 case RT5640_SCLK_S_RCCLK:
1669 reg_val |= RT5640_SCLK_SRC_RCCLK;
1670 break;
1671 default:
1672 dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
1673 return -EINVAL;
1674 }
1675 snd_soc_update_bits(codec, RT5640_GLB_CLK,
1676 RT5640_SCLK_SRC_MASK, reg_val);
1677 rt5640->sysclk = freq;
1678 rt5640->sysclk_src = clk_id;
1679
1680 dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
1681 return 0;
1682}
1683
1684/**
1685 * rt5640_pll_calc - Calculate PLL M/N/K code.
1686 * @freq_in: external clock provided to codec.
1687 * @freq_out: target clock which codec works on.
1688 * @pll_code: Pointer to structure with M, N, K and bypass flag.
1689 *
1690 * Calculate M/N/K code to configure PLL for codec. And K is assigned to 2
1691 * which make calculation more efficiently.
1692 *
1693 * Returns 0 for success or negative error code.
1694 */
1695static int rt5640_pll_calc(const unsigned int freq_in,
1696 const unsigned int freq_out, struct rt5640_pll_code *pll_code)
1697{
1698 int max_n = RT5640_PLL_N_MAX, max_m = RT5640_PLL_M_MAX;
1699 int n = 0, m = 0, red, n_t, m_t, in_t, out_t;
1700 int red_t = abs(freq_out - freq_in);
1701 bool bypass = false;
1702
1703 if (RT5640_PLL_INP_MAX < freq_in || RT5640_PLL_INP_MIN > freq_in)
1704 return -EINVAL;
1705
1706 for (n_t = 0; n_t <= max_n; n_t++) {
1707 in_t = (freq_in >> 1) + (freq_in >> 2) * n_t;
1708 if (in_t < 0)
1709 continue;
1710 if (in_t == freq_out) {
1711 bypass = true;
1712 n = n_t;
1713 goto code_find;
1714 }
1715 for (m_t = 0; m_t <= max_m; m_t++) {
1716 out_t = in_t / (m_t + 2);
1717 red = abs(out_t - freq_out);
1718 if (red < red_t) {
1719 n = n_t;
1720 m = m_t;
1721 if (red == 0)
1722 goto code_find;
1723 red_t = red;
1724 }
1725 }
1726 }
1727 pr_debug("Only get approximation about PLL\n");
1728
1729code_find:
1730 pll_code->m_bp = bypass;
1731 pll_code->m_code = m;
1732 pll_code->n_code = n;
1733 pll_code->k_code = 2;
1734 return 0;
1735}
1736
1737static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
1738 unsigned int freq_in, unsigned int freq_out)
1739{
1740 struct snd_soc_codec *codec = dai->codec;
1741 struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
1742 struct rt5640_pll_code *pll_code = &rt5640->pll_code;
1743 int ret, dai_sel;
1744
1745 if (source == rt5640->pll_src && freq_in == rt5640->pll_in &&
1746 freq_out == rt5640->pll_out)
1747 return 0;
1748
1749 if (!freq_in || !freq_out) {
1750 dev_dbg(codec->dev, "PLL disabled\n");
1751
1752 rt5640->pll_in = 0;
1753 rt5640->pll_out = 0;
1754 snd_soc_update_bits(codec, RT5640_GLB_CLK,
1755 RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_MCLK);
1756 return 0;
1757 }
1758
1759 switch (source) {
1760 case RT5640_PLL1_S_MCLK:
1761 snd_soc_update_bits(codec, RT5640_GLB_CLK,
1762 RT5640_PLL1_SRC_MASK, RT5640_PLL1_SRC_MCLK);
1763 break;
1764 case RT5640_PLL1_S_BCLK1:
1765 case RT5640_PLL1_S_BCLK2:
1766 dai_sel = get_sdp_info(codec, dai->id);
1767 if (dai_sel < 0) {
1768 dev_err(codec->dev,
1769 "Failed to get sdp info: %d\n", dai_sel);
1770 return -EINVAL;
1771 }
1772 if (dai_sel & RT5640_U_IF1) {
1773 snd_soc_update_bits(codec, RT5640_GLB_CLK,
1774 RT5640_PLL1_SRC_MASK, RT5640_PLL1_SRC_BCLK1);
1775 }
1776 if (dai_sel & RT5640_U_IF2) {
1777 snd_soc_update_bits(codec, RT5640_GLB_CLK,
1778 RT5640_PLL1_SRC_MASK, RT5640_PLL1_SRC_BCLK2);
1779 }
1780 break;
1781 default:
1782 dev_err(codec->dev, "Unknown PLL source %d\n", source);
1783 return -EINVAL;
1784 }
1785
1786 ret = rt5640_pll_calc(freq_in, freq_out, pll_code);
1787 if (ret < 0) {
1788 dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
1789 return ret;
1790 }
1791
1792 dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=2\n", pll_code->m_bp,
1793 (pll_code->m_bp ? 0 : pll_code->m_code), pll_code->n_code);
1794
1795 snd_soc_write(codec, RT5640_PLL_CTRL1,
1796 pll_code->n_code << RT5640_PLL_N_SFT | pll_code->k_code);
1797 snd_soc_write(codec, RT5640_PLL_CTRL2,
1798 (pll_code->m_bp ? 0 : pll_code->m_code) << RT5640_PLL_M_SFT |
1799 pll_code->m_bp << RT5640_PLL_M_BP_SFT);
1800
1801 rt5640->pll_in = freq_in;
1802 rt5640->pll_out = freq_out;
1803 rt5640->pll_src = source;
1804
1805 return 0;
1806}
1807
1808static int rt5640_set_bias_level(struct snd_soc_codec *codec,
1809 enum snd_soc_bias_level level)
1810{
1811 struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
1812 switch (level) {
1813 case SND_SOC_BIAS_STANDBY:
1814 if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
1815 regcache_cache_only(rt5640->regmap, false);
1816 snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
1817 RT5640_PWR_VREF1 | RT5640_PWR_MB |
1818 RT5640_PWR_BG | RT5640_PWR_VREF2,
1819 RT5640_PWR_VREF1 | RT5640_PWR_MB |
1820 RT5640_PWR_BG | RT5640_PWR_VREF2);
1821 mdelay(10);
1822 snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
1823 RT5640_PWR_FV1 | RT5640_PWR_FV2,
1824 RT5640_PWR_FV1 | RT5640_PWR_FV2);
1825 regcache_sync(rt5640->regmap);
1826 snd_soc_update_bits(codec, RT5640_DUMMY1,
1827 0x0301, 0x0301);
1828 snd_soc_update_bits(codec, RT5640_DEPOP_M1,
1829 0x001d, 0x0019);
1830 snd_soc_update_bits(codec, RT5640_DEPOP_M2,
1831 0x2000, 0x2000);
1832 snd_soc_update_bits(codec, RT5640_MICBIAS,
1833 0x0030, 0x0030);
1834 }
1835 break;
1836
1837 case SND_SOC_BIAS_OFF:
1838 snd_soc_write(codec, RT5640_DEPOP_M1, 0x0004);
1839 snd_soc_write(codec, RT5640_DEPOP_M2, 0x1100);
1840 snd_soc_update_bits(codec, RT5640_DUMMY1, 0x1, 0);
1841 snd_soc_write(codec, RT5640_PWR_DIG1, 0x0000);
1842 snd_soc_write(codec, RT5640_PWR_DIG2, 0x0000);
1843 snd_soc_write(codec, RT5640_PWR_VOL, 0x0000);
1844 snd_soc_write(codec, RT5640_PWR_MIXER, 0x0000);
1845 snd_soc_write(codec, RT5640_PWR_ANLG1, 0x0000);
1846 snd_soc_write(codec, RT5640_PWR_ANLG2, 0x0000);
1847 break;
1848
1849 default:
1850 break;
1851 }
1852 codec->dapm.bias_level = level;
1853
1854 return 0;
1855}
1856
1857static int rt5640_probe(struct snd_soc_codec *codec)
1858{
1859 struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
1860 int ret;
1861
1862 rt5640->codec = codec;
1863 codec->control_data = rt5640->regmap;
1864
1865 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
1866 if (ret != 0) {
1867 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1868 return ret;
1869 }
1870
1871 codec->dapm.idle_bias_off = 1;
1872 rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
1873
1874 snd_soc_update_bits(codec, RT5640_DUMMY1, 0x0301, 0x0301);
1875 snd_soc_update_bits(codec, RT5640_DEPOP_M1, 0x001d, 0x0019);
1876 snd_soc_update_bits(codec, RT5640_DEPOP_M2, 0x2000, 0x2000);
1877 snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030);
1878 snd_soc_update_bits(codec, RT5640_DSP_PATH2, 0xfc00, 0x0c00);
1879
1880 return 0;
1881}
1882
1883static int rt5640_remove(struct snd_soc_codec *codec)
1884{
1885 rt5640_reset(codec);
1886
1887 return 0;
1888}
1889
1890#ifdef CONFIG_PM
1891static int rt5640_suspend(struct snd_soc_codec *codec)
1892{
1893 struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
1894
1895 rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
1896 rt5640_reset(codec);
1897 regcache_cache_only(rt5640->regmap, true);
1898 regcache_mark_dirty(rt5640->regmap);
1899
1900 return 0;
1901}
1902
1903static int rt5640_resume(struct snd_soc_codec *codec)
1904{
1905 rt5640_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1906
1907 return 0;
1908}
1909#else
1910#define rt5640_suspend NULL
1911#define rt5640_resume NULL
1912#endif
1913
1914#define RT5640_STEREO_RATES SNDRV_PCM_RATE_8000_96000
1915#define RT5640_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
1916 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
1917
1918static const struct snd_soc_dai_ops rt5640_aif_dai_ops = {
1919 .hw_params = rt5640_hw_params,
1920 .set_fmt = rt5640_set_dai_fmt,
1921 .set_sysclk = rt5640_set_dai_sysclk,
1922 .set_pll = rt5640_set_dai_pll,
1923};
1924
1925static struct snd_soc_dai_driver rt5640_dai[] = {
1926 {
1927 .name = "rt5640-aif1",
1928 .id = RT5640_AIF1,
1929 .playback = {
1930 .stream_name = "AIF1 Playback",
1931 .channels_min = 1,
1932 .channels_max = 2,
1933 .rates = RT5640_STEREO_RATES,
1934 .formats = RT5640_FORMATS,
1935 },
1936 .capture = {
1937 .stream_name = "AIF1 Capture",
1938 .channels_min = 1,
1939 .channels_max = 2,
1940 .rates = RT5640_STEREO_RATES,
1941 .formats = RT5640_FORMATS,
1942 },
1943 .ops = &rt5640_aif_dai_ops,
1944 },
1945 {
1946 .name = "rt5640-aif2",
1947 .id = RT5640_AIF2,
1948 .playback = {
1949 .stream_name = "AIF2 Playback",
1950 .channels_min = 1,
1951 .channels_max = 2,
1952 .rates = RT5640_STEREO_RATES,
1953 .formats = RT5640_FORMATS,
1954 },
1955 .capture = {
1956 .stream_name = "AIF2 Capture",
1957 .channels_min = 1,
1958 .channels_max = 2,
1959 .rates = RT5640_STEREO_RATES,
1960 .formats = RT5640_FORMATS,
1961 },
1962 .ops = &rt5640_aif_dai_ops,
1963 },
1964};
1965
1966static struct snd_soc_codec_driver soc_codec_dev_rt5640 = {
1967 .probe = rt5640_probe,
1968 .remove = rt5640_remove,
1969 .suspend = rt5640_suspend,
1970 .resume = rt5640_resume,
1971 .set_bias_level = rt5640_set_bias_level,
1972 .controls = rt5640_snd_controls,
1973 .num_controls = ARRAY_SIZE(rt5640_snd_controls),
1974 .dapm_widgets = rt5640_dapm_widgets,
1975 .num_dapm_widgets = ARRAY_SIZE(rt5640_dapm_widgets),
1976 .dapm_routes = rt5640_dapm_routes,
1977 .num_dapm_routes = ARRAY_SIZE(rt5640_dapm_routes),
1978};
1979
1980static const struct regmap_config rt5640_regmap = {
1981 .reg_bits = 8,
1982 .val_bits = 16,
1983
1984 .max_register = RT5640_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5640_ranges) *
1985 RT5640_PR_SPACING),
1986 .volatile_reg = rt5640_volatile_register,
1987 .readable_reg = rt5640_readable_register,
1988
1989 .cache_type = REGCACHE_RBTREE,
1990 .reg_defaults = rt5640_reg,
1991 .num_reg_defaults = ARRAY_SIZE(rt5640_reg),
1992 .ranges = rt5640_ranges,
1993 .num_ranges = ARRAY_SIZE(rt5640_ranges),
1994};
1995
1996static const struct i2c_device_id rt5640_i2c_id[] = {
1997 { "rt5640", 0 },
1998 { }
1999};
2000MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
2001
2002static int rt5640_parse_dt(struct rt5640_priv *rt5640, struct device_node *np)
2003{
2004 rt5640->pdata.in1_diff = of_property_read_bool(np,
2005 "realtek,in1-differential");
2006 rt5640->pdata.in2_diff = of_property_read_bool(np,
2007 "realtek,in2-differential");
2008
2009 rt5640->pdata.ldo1_en = of_get_named_gpio(np,
2010 "realtek,ldo1-en-gpios", 0);
2011 /*
2012 * LDO1_EN is optional (it may be statically tied on the board).
2013 * -ENOENT means that the property doesn't exist, i.e. there is no
2014 * GPIO, so is not an error. Any other error code means the property
2015 * exists, but could not be parsed.
2016 */
2017 if (!gpio_is_valid(rt5640->pdata.ldo1_en) &&
2018 (rt5640->pdata.ldo1_en != -ENOENT))
2019 return rt5640->pdata.ldo1_en;
2020
2021 return 0;
2022}
2023
2024static int rt5640_i2c_probe(struct i2c_client *i2c,
2025 const struct i2c_device_id *id)
2026{
2027 struct rt5640_platform_data *pdata = dev_get_platdata(&i2c->dev);
2028 struct rt5640_priv *rt5640;
2029 int ret;
2030 unsigned int val;
2031
2032 rt5640 = devm_kzalloc(&i2c->dev,
2033 sizeof(struct rt5640_priv),
2034 GFP_KERNEL);
2035 if (NULL == rt5640)
2036 return -ENOMEM;
2037 i2c_set_clientdata(i2c, rt5640);
2038
2039 if (pdata) {
2040 rt5640->pdata = *pdata;
2041 /*
2042 * Translate zero'd out (default) pdata value to an invalid
2043 * GPIO ID. This makes the pdata and DT paths consistent in
2044 * terms of the value left in this field when no GPIO is
2045 * specified, but means we can't actually use GPIO 0.
2046 */
2047 if (!rt5640->pdata.ldo1_en)
2048 rt5640->pdata.ldo1_en = -EINVAL;
2049 } else if (i2c->dev.of_node) {
2050 ret = rt5640_parse_dt(rt5640, i2c->dev.of_node);
2051 if (ret)
2052 return ret;
2053 } else
2054 rt5640->pdata.ldo1_en = -EINVAL;
2055
2056 rt5640->regmap = devm_regmap_init_i2c(i2c, &rt5640_regmap);
2057 if (IS_ERR(rt5640->regmap)) {
2058 ret = PTR_ERR(rt5640->regmap);
2059 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
2060 ret);
2061 return ret;
2062 }
2063
2064 if (gpio_is_valid(rt5640->pdata.ldo1_en)) {
2065 ret = devm_gpio_request_one(&i2c->dev, rt5640->pdata.ldo1_en,
2066 GPIOF_OUT_INIT_HIGH,
2067 "RT5640 LDO1_EN");
2068 if (ret < 0) {
2069 dev_err(&i2c->dev, "Failed to request LDO1_EN %d: %d\n",
2070 rt5640->pdata.ldo1_en, ret);
2071 return ret;
2072 }
2073 msleep(400);
2074 }
2075
2076 regmap_read(rt5640->regmap, RT5640_VENDOR_ID2, &val);
2077 if ((val != RT5640_DEVICE_ID)) {
2078 dev_err(&i2c->dev,
2079 "Device with ID register %x is not rt5640/39\n", val);
2080 return -ENODEV;
2081 }
2082
2083 regmap_write(rt5640->regmap, RT5640_RESET, 0);
2084
2085 ret = regmap_register_patch(rt5640->regmap, init_list,
2086 ARRAY_SIZE(init_list));
2087 if (ret != 0)
2088 dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
2089
2090 if (rt5640->pdata.in1_diff)
2091 regmap_update_bits(rt5640->regmap, RT5640_IN1_IN2,
2092 RT5640_IN_DF1, RT5640_IN_DF1);
2093
2094 if (rt5640->pdata.in2_diff)
2095 regmap_update_bits(rt5640->regmap, RT5640_IN3_IN4,
2096 RT5640_IN_DF2, RT5640_IN_DF2);
2097
2098 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640,
2099 rt5640_dai, ARRAY_SIZE(rt5640_dai));
2100 if (ret < 0)
2101 goto err;
2102
2103 return 0;
2104err:
2105 return ret;
2106}
2107
2108static int rt5640_i2c_remove(struct i2c_client *i2c)
2109{
2110 snd_soc_unregister_codec(&i2c->dev);
2111
2112 return 0;
2113}
2114
2115static struct i2c_driver rt5640_i2c_driver = {
2116 .driver = {
2117 .name = "rt5640",
2118 .owner = THIS_MODULE,
2119 },
2120 .probe = rt5640_i2c_probe,
2121 .remove = rt5640_i2c_remove,
2122 .id_table = rt5640_i2c_id,
2123};
2124module_i2c_driver(rt5640_i2c_driver);
2125
2126MODULE_DESCRIPTION("ASoC RT5640 driver");
2127MODULE_AUTHOR("Johnny Hsu <johnnyhsu@realtek.com>");
2128MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
new file mode 100644
index 000000000000..c48286d7118f
--- /dev/null
+++ b/sound/soc/codecs/rt5640.h
@@ -0,0 +1,2092 @@
1/*
2 * rt5640.h -- RT5640 ALSA SoC audio driver
3 *
4 * Copyright 2011 Realtek Microelectronics
5 * Author: Johnny Hsu <johnnyhsu@realtek.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _RT5640_H
13#define _RT5640_H
14
15#include <sound/rt5640.h>
16
17/* Info */
18#define RT5640_RESET 0x00
19#define RT5640_VENDOR_ID 0xfd
20#define RT5640_VENDOR_ID1 0xfe
21#define RT5640_VENDOR_ID2 0xff
22/* I/O - Output */
23#define RT5640_SPK_VOL 0x01
24#define RT5640_HP_VOL 0x02
25#define RT5640_OUTPUT 0x03
26#define RT5640_MONO_OUT 0x04
27/* I/O - Input */
28#define RT5640_IN1_IN2 0x0d
29#define RT5640_IN3_IN4 0x0e
30#define RT5640_INL_INR_VOL 0x0f
31/* I/O - ADC/DAC/DMIC */
32#define RT5640_DAC1_DIG_VOL 0x19
33#define RT5640_DAC2_DIG_VOL 0x1a
34#define RT5640_DAC2_CTRL 0x1b
35#define RT5640_ADC_DIG_VOL 0x1c
36#define RT5640_ADC_DATA 0x1d
37#define RT5640_ADC_BST_VOL 0x1e
38/* Mixer - D-D */
39#define RT5640_STO_ADC_MIXER 0x27
40#define RT5640_MONO_ADC_MIXER 0x28
41#define RT5640_AD_DA_MIXER 0x29
42#define RT5640_STO_DAC_MIXER 0x2a
43#define RT5640_MONO_DAC_MIXER 0x2b
44#define RT5640_DIG_MIXER 0x2c
45#define RT5640_DSP_PATH1 0x2d
46#define RT5640_DSP_PATH2 0x2e
47#define RT5640_DIG_INF_DATA 0x2f
48/* Mixer - ADC */
49#define RT5640_REC_L1_MIXER 0x3b
50#define RT5640_REC_L2_MIXER 0x3c
51#define RT5640_REC_R1_MIXER 0x3d
52#define RT5640_REC_R2_MIXER 0x3e
53/* Mixer - DAC */
54#define RT5640_HPO_MIXER 0x45
55#define RT5640_SPK_L_MIXER 0x46
56#define RT5640_SPK_R_MIXER 0x47
57#define RT5640_SPO_L_MIXER 0x48
58#define RT5640_SPO_R_MIXER 0x49
59#define RT5640_SPO_CLSD_RATIO 0x4a
60#define RT5640_MONO_MIXER 0x4c
61#define RT5640_OUT_L1_MIXER 0x4d
62#define RT5640_OUT_L2_MIXER 0x4e
63#define RT5640_OUT_L3_MIXER 0x4f
64#define RT5640_OUT_R1_MIXER 0x50
65#define RT5640_OUT_R2_MIXER 0x51
66#define RT5640_OUT_R3_MIXER 0x52
67#define RT5640_LOUT_MIXER 0x53
68/* Power */
69#define RT5640_PWR_DIG1 0x61
70#define RT5640_PWR_DIG2 0x62
71#define RT5640_PWR_ANLG1 0x63
72#define RT5640_PWR_ANLG2 0x64
73#define RT5640_PWR_MIXER 0x65
74#define RT5640_PWR_VOL 0x66
75/* Private Register Control */
76#define RT5640_PRIV_INDEX 0x6a
77#define RT5640_PRIV_DATA 0x6c
78/* Format - ADC/DAC */
79#define RT5640_I2S1_SDP 0x70
80#define RT5640_I2S2_SDP 0x71
81#define RT5640_ADDA_CLK1 0x73
82#define RT5640_ADDA_CLK2 0x74
83#define RT5640_DMIC 0x75
84/* Function - Analog */
85#define RT5640_GLB_CLK 0x80
86#define RT5640_PLL_CTRL1 0x81
87#define RT5640_PLL_CTRL2 0x82
88#define RT5640_ASRC_1 0x83
89#define RT5640_ASRC_2 0x84
90#define RT5640_ASRC_3 0x85
91#define RT5640_ASRC_4 0x89
92#define RT5640_ASRC_5 0x8a
93#define RT5640_HP_OVCD 0x8b
94#define RT5640_CLS_D_OVCD 0x8c
95#define RT5640_CLS_D_OUT 0x8d
96#define RT5640_DEPOP_M1 0x8e
97#define RT5640_DEPOP_M2 0x8f
98#define RT5640_DEPOP_M3 0x90
99#define RT5640_CHARGE_PUMP 0x91
100#define RT5640_PV_DET_SPK_G 0x92
101#define RT5640_MICBIAS 0x93
102/* Function - Digital */
103#define RT5640_EQ_CTRL1 0xb0
104#define RT5640_EQ_CTRL2 0xb1
105#define RT5640_WIND_FILTER 0xb2
106#define RT5640_DRC_AGC_1 0xb4
107#define RT5640_DRC_AGC_2 0xb5
108#define RT5640_DRC_AGC_3 0xb6
109#define RT5640_SVOL_ZC 0xb7
110#define RT5640_ANC_CTRL1 0xb8
111#define RT5640_ANC_CTRL2 0xb9
112#define RT5640_ANC_CTRL3 0xba
113#define RT5640_JD_CTRL 0xbb
114#define RT5640_ANC_JD 0xbc
115#define RT5640_IRQ_CTRL1 0xbd
116#define RT5640_IRQ_CTRL2 0xbe
117#define RT5640_INT_IRQ_ST 0xbf
118#define RT5640_GPIO_CTRL1 0xc0
119#define RT5640_GPIO_CTRL2 0xc1
120#define RT5640_GPIO_CTRL3 0xc2
121#define RT5640_DSP_CTRL1 0xc4
122#define RT5640_DSP_CTRL2 0xc5
123#define RT5640_DSP_CTRL3 0xc6
124#define RT5640_DSP_CTRL4 0xc7
125#define RT5640_PGM_REG_ARR1 0xc8
126#define RT5640_PGM_REG_ARR2 0xc9
127#define RT5640_PGM_REG_ARR3 0xca
128#define RT5640_PGM_REG_ARR4 0xcb
129#define RT5640_PGM_REG_ARR5 0xcc
130#define RT5640_SCB_FUNC 0xcd
131#define RT5640_SCB_CTRL 0xce
132#define RT5640_BASE_BACK 0xcf
133#define RT5640_MP3_PLUS1 0xd0
134#define RT5640_MP3_PLUS2 0xd1
135#define RT5640_3D_HP 0xd2
136#define RT5640_ADJ_HPF 0xd3
137#define RT5640_HP_CALIB_AMP_DET 0xd6
138#define RT5640_HP_CALIB2 0xd7
139#define RT5640_SV_ZCD1 0xd9
140#define RT5640_SV_ZCD2 0xda
141/* Dummy Register */
142#define RT5640_DUMMY1 0xfa
143#define RT5640_DUMMY2 0xfb
144#define RT5640_DUMMY3 0xfc
145
146
147/* Index of Codec Private Register definition */
148#define RT5640_3D_SPK 0x63
149#define RT5640_WND_1 0x6c
150#define RT5640_WND_2 0x6d
151#define RT5640_WND_3 0x6e
152#define RT5640_WND_4 0x6f
153#define RT5640_WND_5 0x70
154#define RT5640_WND_8 0x73
155#define RT5640_DIP_SPK_INF 0x75
156#define RT5640_EQ_BW_LOP 0xa0
157#define RT5640_EQ_GN_LOP 0xa1
158#define RT5640_EQ_FC_BP1 0xa2
159#define RT5640_EQ_BW_BP1 0xa3
160#define RT5640_EQ_GN_BP1 0xa4
161#define RT5640_EQ_FC_BP2 0xa5
162#define RT5640_EQ_BW_BP2 0xa6
163#define RT5640_EQ_GN_BP2 0xa7
164#define RT5640_EQ_FC_BP3 0xa8
165#define RT5640_EQ_BW_BP3 0xa9
166#define RT5640_EQ_GN_BP3 0xaa
167#define RT5640_EQ_FC_BP4 0xab
168#define RT5640_EQ_BW_BP4 0xac
169#define RT5640_EQ_GN_BP4 0xad
170#define RT5640_EQ_FC_HIP1 0xae
171#define RT5640_EQ_GN_HIP1 0xaf
172#define RT5640_EQ_FC_HIP2 0xb0
173#define RT5640_EQ_BW_HIP2 0xb1
174#define RT5640_EQ_GN_HIP2 0xb2
175#define RT5640_EQ_PRE_VOL 0xb3
176#define RT5640_EQ_PST_VOL 0xb4
177
178/* global definition */
179#define RT5640_L_MUTE (0x1 << 15)
180#define RT5640_L_MUTE_SFT 15
181#define RT5640_VOL_L_MUTE (0x1 << 14)
182#define RT5640_VOL_L_SFT 14
183#define RT5640_R_MUTE (0x1 << 7)
184#define RT5640_R_MUTE_SFT 7
185#define RT5640_VOL_R_MUTE (0x1 << 6)
186#define RT5640_VOL_R_SFT 6
187#define RT5640_L_VOL_MASK (0x3f << 8)
188#define RT5640_L_VOL_SFT 8
189#define RT5640_R_VOL_MASK (0x3f)
190#define RT5640_R_VOL_SFT 0
191
192/* IN1 and IN2 Control (0x0d) */
193/* IN3 and IN4 Control (0x0e) */
194#define RT5640_BST_SFT1 12
195#define RT5640_BST_SFT2 8
196#define RT5640_IN_DF1 (0x1 << 7)
197#define RT5640_IN_SFT1 7
198#define RT5640_IN_DF2 (0x1 << 6)
199#define RT5640_IN_SFT2 6
200
201/* INL and INR Volume Control (0x0f) */
202#define RT5640_INL_SEL_MASK (0x1 << 15)
203#define RT5640_INL_SEL_SFT 15
204#define RT5640_INL_SEL_IN4P (0x0 << 15)
205#define RT5640_INL_SEL_MONOP (0x1 << 15)
206#define RT5640_INL_VOL_MASK (0x1f << 8)
207#define RT5640_INL_VOL_SFT 8
208#define RT5640_INR_SEL_MASK (0x1 << 7)
209#define RT5640_INR_SEL_SFT 7
210#define RT5640_INR_SEL_IN4N (0x0 << 7)
211#define RT5640_INR_SEL_MONON (0x1 << 7)
212#define RT5640_INR_VOL_MASK (0x1f)
213#define RT5640_INR_VOL_SFT 0
214
215/* DAC1 Digital Volume (0x19) */
216#define RT5640_DAC_L1_VOL_MASK (0xff << 8)
217#define RT5640_DAC_L1_VOL_SFT 8
218#define RT5640_DAC_R1_VOL_MASK (0xff)
219#define RT5640_DAC_R1_VOL_SFT 0
220
221/* DAC2 Digital Volume (0x1a) */
222#define RT5640_DAC_L2_VOL_MASK (0xff << 8)
223#define RT5640_DAC_L2_VOL_SFT 8
224#define RT5640_DAC_R2_VOL_MASK (0xff)
225#define RT5640_DAC_R2_VOL_SFT 0
226
227/* DAC2 Control (0x1b) */
228#define RT5640_M_DAC_L2_VOL (0x1 << 13)
229#define RT5640_M_DAC_L2_VOL_SFT 13
230#define RT5640_M_DAC_R2_VOL (0x1 << 12)
231#define RT5640_M_DAC_R2_VOL_SFT 12
232
233/* ADC Digital Volume Control (0x1c) */
234#define RT5640_ADC_L_VOL_MASK (0x7f << 8)
235#define RT5640_ADC_L_VOL_SFT 8
236#define RT5640_ADC_R_VOL_MASK (0x7f)
237#define RT5640_ADC_R_VOL_SFT 0
238
239/* Mono ADC Digital Volume Control (0x1d) */
240#define RT5640_MONO_ADC_L_VOL_MASK (0x7f << 8)
241#define RT5640_MONO_ADC_L_VOL_SFT 8
242#define RT5640_MONO_ADC_R_VOL_MASK (0x7f)
243#define RT5640_MONO_ADC_R_VOL_SFT 0
244
245/* ADC Boost Volume Control (0x1e) */
246#define RT5640_ADC_L_BST_MASK (0x3 << 14)
247#define RT5640_ADC_L_BST_SFT 14
248#define RT5640_ADC_R_BST_MASK (0x3 << 12)
249#define RT5640_ADC_R_BST_SFT 12
250#define RT5640_ADC_COMP_MASK (0x3 << 10)
251#define RT5640_ADC_COMP_SFT 10
252
253/* Stereo ADC Mixer Control (0x27) */
254#define RT5640_M_ADC_L1 (0x1 << 14)
255#define RT5640_M_ADC_L1_SFT 14
256#define RT5640_M_ADC_L2 (0x1 << 13)
257#define RT5640_M_ADC_L2_SFT 13
258#define RT5640_ADC_1_SRC_MASK (0x1 << 12)
259#define RT5640_ADC_1_SRC_SFT 12
260#define RT5640_ADC_1_SRC_ADC (0x1 << 12)
261#define RT5640_ADC_1_SRC_DACMIX (0x0 << 12)
262#define RT5640_ADC_2_SRC_MASK (0x3 << 10)
263#define RT5640_ADC_2_SRC_SFT 10
264#define RT5640_ADC_2_SRC_DMIC1 (0x0 << 10)
265#define RT5640_ADC_2_SRC_DMIC2 (0x1 << 10)
266#define RT5640_ADC_2_SRC_DACMIX (0x2 << 10)
267#define RT5640_M_ADC_R1 (0x1 << 6)
268#define RT5640_M_ADC_R1_SFT 6
269#define RT5640_M_ADC_R2 (0x1 << 5)
270#define RT5640_M_ADC_R2_SFT 5
271
272/* Mono ADC Mixer Control (0x28) */
273#define RT5640_M_MONO_ADC_L1 (0x1 << 14)
274#define RT5640_M_MONO_ADC_L1_SFT 14
275#define RT5640_M_MONO_ADC_L2 (0x1 << 13)
276#define RT5640_M_MONO_ADC_L2_SFT 13
277#define RT5640_MONO_ADC_L1_SRC_MASK (0x1 << 12)
278#define RT5640_MONO_ADC_L1_SRC_SFT 12
279#define RT5640_MONO_ADC_L1_SRC_DACMIXL (0x0 << 12)
280#define RT5640_MONO_ADC_L1_SRC_ADCL (0x1 << 12)
281#define RT5640_MONO_ADC_L2_SRC_MASK (0x3 << 10)
282#define RT5640_MONO_ADC_L2_SRC_SFT 10
283#define RT5640_MONO_ADC_L2_SRC_DMIC_L1 (0x0 << 10)
284#define RT5640_MONO_ADC_L2_SRC_DMIC_L2 (0x1 << 10)
285#define RT5640_MONO_ADC_L2_SRC_DACMIXL (0x2 << 10)
286#define RT5640_M_MONO_ADC_R1 (0x1 << 6)
287#define RT5640_M_MONO_ADC_R1_SFT 6
288#define RT5640_M_MONO_ADC_R2 (0x1 << 5)
289#define RT5640_M_MONO_ADC_R2_SFT 5
290#define RT5640_MONO_ADC_R1_SRC_MASK (0x1 << 4)
291#define RT5640_MONO_ADC_R1_SRC_SFT 4
292#define RT5640_MONO_ADC_R1_SRC_ADCR (0x1 << 4)
293#define RT5640_MONO_ADC_R1_SRC_DACMIXR (0x0 << 4)
294#define RT5640_MONO_ADC_R2_SRC_MASK (0x3 << 2)
295#define RT5640_MONO_ADC_R2_SRC_SFT 2
296#define RT5640_MONO_ADC_R2_SRC_DMIC_R1 (0x0 << 2)
297#define RT5640_MONO_ADC_R2_SRC_DMIC_R2 (0x1 << 2)
298#define RT5640_MONO_ADC_R2_SRC_DACMIXR (0x2 << 2)
299
300/* ADC Mixer to DAC Mixer Control (0x29) */
301#define RT5640_M_ADCMIX_L (0x1 << 15)
302#define RT5640_M_ADCMIX_L_SFT 15
303#define RT5640_M_IF1_DAC_L (0x1 << 14)
304#define RT5640_M_IF1_DAC_L_SFT 14
305#define RT5640_M_ADCMIX_R (0x1 << 7)
306#define RT5640_M_ADCMIX_R_SFT 7
307#define RT5640_M_IF1_DAC_R (0x1 << 6)
308#define RT5640_M_IF1_DAC_R_SFT 6
309
310/* Stereo DAC Mixer Control (0x2a) */
311#define RT5640_M_DAC_L1 (0x1 << 14)
312#define RT5640_M_DAC_L1_SFT 14
313#define RT5640_DAC_L1_STO_L_VOL_MASK (0x1 << 13)
314#define RT5640_DAC_L1_STO_L_VOL_SFT 13
315#define RT5640_M_DAC_L2 (0x1 << 12)
316#define RT5640_M_DAC_L2_SFT 12
317#define RT5640_DAC_L2_STO_L_VOL_MASK (0x1 << 11)
318#define RT5640_DAC_L2_STO_L_VOL_SFT 11
319#define RT5640_M_ANC_DAC_L (0x1 << 10)
320#define RT5640_M_ANC_DAC_L_SFT 10
321#define RT5640_M_DAC_R1 (0x1 << 6)
322#define RT5640_M_DAC_R1_SFT 6
323#define RT5640_DAC_R1_STO_R_VOL_MASK (0x1 << 5)
324#define RT5640_DAC_R1_STO_R_VOL_SFT 5
325#define RT5640_M_DAC_R2 (0x1 << 4)
326#define RT5640_M_DAC_R2_SFT 4
327#define RT5640_DAC_R2_STO_R_VOL_MASK (0x1 << 3)
328#define RT5640_DAC_R2_STO_R_VOL_SFT 3
329#define RT5640_M_ANC_DAC_R (0x1 << 2)
330#define RT5640_M_ANC_DAC_R_SFT 2
331
332/* Mono DAC Mixer Control (0x2b) */
333#define RT5640_M_DAC_L1_MONO_L (0x1 << 14)
334#define RT5640_M_DAC_L1_MONO_L_SFT 14
335#define RT5640_DAC_L1_MONO_L_VOL_MASK (0x1 << 13)
336#define RT5640_DAC_L1_MONO_L_VOL_SFT 13
337#define RT5640_M_DAC_L2_MONO_L (0x1 << 12)
338#define RT5640_M_DAC_L2_MONO_L_SFT 12
339#define RT5640_DAC_L2_MONO_L_VOL_MASK (0x1 << 11)
340#define RT5640_DAC_L2_MONO_L_VOL_SFT 11
341#define RT5640_M_DAC_R2_MONO_L (0x1 << 10)
342#define RT5640_M_DAC_R2_MONO_L_SFT 10
343#define RT5640_DAC_R2_MONO_L_VOL_MASK (0x1 << 9)
344#define RT5640_DAC_R2_MONO_L_VOL_SFT 9
345#define RT5640_M_DAC_R1_MONO_R (0x1 << 6)
346#define RT5640_M_DAC_R1_MONO_R_SFT 6
347#define RT5640_DAC_R1_MONO_R_VOL_MASK (0x1 << 5)
348#define RT5640_DAC_R1_MONO_R_VOL_SFT 5
349#define RT5640_M_DAC_R2_MONO_R (0x1 << 4)
350#define RT5640_M_DAC_R2_MONO_R_SFT 4
351#define RT5640_DAC_R2_MONO_R_VOL_MASK (0x1 << 3)
352#define RT5640_DAC_R2_MONO_R_VOL_SFT 3
353#define RT5640_M_DAC_L2_MONO_R (0x1 << 2)
354#define RT5640_M_DAC_L2_MONO_R_SFT 2
355#define RT5640_DAC_L2_MONO_R_VOL_MASK (0x1 << 1)
356#define RT5640_DAC_L2_MONO_R_VOL_SFT 1
357
358/* Digital Mixer Control (0x2c) */
359#define RT5640_M_STO_L_DAC_L (0x1 << 15)
360#define RT5640_M_STO_L_DAC_L_SFT 15
361#define RT5640_STO_L_DAC_L_VOL_MASK (0x1 << 14)
362#define RT5640_STO_L_DAC_L_VOL_SFT 14
363#define RT5640_M_DAC_L2_DAC_L (0x1 << 13)
364#define RT5640_M_DAC_L2_DAC_L_SFT 13
365#define RT5640_DAC_L2_DAC_L_VOL_MASK (0x1 << 12)
366#define RT5640_DAC_L2_DAC_L_VOL_SFT 12
367#define RT5640_M_STO_R_DAC_R (0x1 << 11)
368#define RT5640_M_STO_R_DAC_R_SFT 11
369#define RT5640_STO_R_DAC_R_VOL_MASK (0x1 << 10)
370#define RT5640_STO_R_DAC_R_VOL_SFT 10
371#define RT5640_M_DAC_R2_DAC_R (0x1 << 9)
372#define RT5640_M_DAC_R2_DAC_R_SFT 9
373#define RT5640_DAC_R2_DAC_R_VOL_MASK (0x1 << 8)
374#define RT5640_DAC_R2_DAC_R_VOL_SFT 8
375
376/* DSP Path Control 1 (0x2d) */
377#define RT5640_RXDP_SRC_MASK (0x1 << 15)
378#define RT5640_RXDP_SRC_SFT 15
379#define RT5640_RXDP_SRC_NOR (0x0 << 15)
380#define RT5640_RXDP_SRC_DIV3 (0x1 << 15)
381#define RT5640_TXDP_SRC_MASK (0x1 << 14)
382#define RT5640_TXDP_SRC_SFT 14
383#define RT5640_TXDP_SRC_NOR (0x0 << 14)
384#define RT5640_TXDP_SRC_DIV3 (0x1 << 14)
385
386/* DSP Path Control 2 (0x2e) */
387#define RT5640_DAC_L2_SEL_MASK (0x3 << 14)
388#define RT5640_DAC_L2_SEL_SFT 14
389#define RT5640_DAC_L2_SEL_IF2 (0x0 << 14)
390#define RT5640_DAC_L2_SEL_IF3 (0x1 << 14)
391#define RT5640_DAC_L2_SEL_TXDC (0x2 << 14)
392#define RT5640_DAC_L2_SEL_BASS (0x3 << 14)
393#define RT5640_DAC_R2_SEL_MASK (0x3 << 12)
394#define RT5640_DAC_R2_SEL_SFT 12
395#define RT5640_DAC_R2_SEL_IF2 (0x0 << 12)
396#define RT5640_DAC_R2_SEL_IF3 (0x1 << 12)
397#define RT5640_DAC_R2_SEL_TXDC (0x2 << 12)
398#define RT5640_IF2_ADC_L_SEL_MASK (0x1 << 11)
399#define RT5640_IF2_ADC_L_SEL_SFT 11
400#define RT5640_IF2_ADC_L_SEL_TXDP (0x0 << 11)
401#define RT5640_IF2_ADC_L_SEL_PASS (0x1 << 11)
402#define RT5640_IF2_ADC_R_SEL_MASK (0x1 << 10)
403#define RT5640_IF2_ADC_R_SEL_SFT 10
404#define RT5640_IF2_ADC_R_SEL_TXDP (0x0 << 10)
405#define RT5640_IF2_ADC_R_SEL_PASS (0x1 << 10)
406#define RT5640_RXDC_SEL_MASK (0x3 << 8)
407#define RT5640_RXDC_SEL_SFT 8
408#define RT5640_RXDC_SEL_NOR (0x0 << 8)
409#define RT5640_RXDC_SEL_L2R (0x1 << 8)
410#define RT5640_RXDC_SEL_R2L (0x2 << 8)
411#define RT5640_RXDC_SEL_SWAP (0x3 << 8)
412#define RT5640_RXDP_SEL_MASK (0x3 << 6)
413#define RT5640_RXDP_SEL_SFT 6
414#define RT5640_RXDP_SEL_NOR (0x0 << 6)
415#define RT5640_RXDP_SEL_L2R (0x1 << 6)
416#define RT5640_RXDP_SEL_R2L (0x2 << 6)
417#define RT5640_RXDP_SEL_SWAP (0x3 << 6)
418#define RT5640_TXDC_SEL_MASK (0x3 << 4)
419#define RT5640_TXDC_SEL_SFT 4
420#define RT5640_TXDC_SEL_NOR (0x0 << 4)
421#define RT5640_TXDC_SEL_L2R (0x1 << 4)
422#define RT5640_TXDC_SEL_R2L (0x2 << 4)
423#define RT5640_TXDC_SEL_SWAP (0x3 << 4)
424#define RT5640_TXDP_SEL_MASK (0x3 << 2)
425#define RT5640_TXDP_SEL_SFT 2
426#define RT5640_TXDP_SEL_NOR (0x0 << 2)
427#define RT5640_TXDP_SEL_L2R (0x1 << 2)
428#define RT5640_TXDP_SEL_R2L (0x2 << 2)
429#define RT5640_TRXDP_SEL_SWAP (0x3 << 2)
430
431/* Digital Interface Data Control (0x2f) */
432#define RT5640_IF1_DAC_SEL_MASK (0x3 << 14)
433#define RT5640_IF1_DAC_SEL_SFT 14
434#define RT5640_IF1_DAC_SEL_NOR (0x0 << 14)
435#define RT5640_IF1_DAC_SEL_L2R (0x1 << 14)
436#define RT5640_IF1_DAC_SEL_R2L (0x2 << 14)
437#define RT5640_IF1_DAC_SEL_SWAP (0x3 << 14)
438#define RT5640_IF1_ADC_SEL_MASK (0x3 << 12)
439#define RT5640_IF1_ADC_SEL_SFT 12
440#define RT5640_IF1_ADC_SEL_NOR (0x0 << 12)
441#define RT5640_IF1_ADC_SEL_L2R (0x1 << 12)
442#define RT5640_IF1_ADC_SEL_R2L (0x2 << 12)
443#define RT5640_IF1_ADC_SEL_SWAP (0x3 << 12)
444#define RT5640_IF2_DAC_SEL_MASK (0x3 << 10)
445#define RT5640_IF2_DAC_SEL_SFT 10
446#define RT5640_IF2_DAC_SEL_NOR (0x0 << 10)
447#define RT5640_IF2_DAC_SEL_L2R (0x1 << 10)
448#define RT5640_IF2_DAC_SEL_R2L (0x2 << 10)
449#define RT5640_IF2_DAC_SEL_SWAP (0x3 << 10)
450#define RT5640_IF2_ADC_SEL_MASK (0x3 << 8)
451#define RT5640_IF2_ADC_SEL_SFT 8
452#define RT5640_IF2_ADC_SEL_NOR (0x0 << 8)
453#define RT5640_IF2_ADC_SEL_L2R (0x1 << 8)
454#define RT5640_IF2_ADC_SEL_R2L (0x2 << 8)
455#define RT5640_IF2_ADC_SEL_SWAP (0x3 << 8)
456#define RT5640_IF3_DAC_SEL_MASK (0x3 << 6)
457#define RT5640_IF3_DAC_SEL_SFT 6
458#define RT5640_IF3_DAC_SEL_NOR (0x0 << 6)
459#define RT5640_IF3_DAC_SEL_L2R (0x1 << 6)
460#define RT5640_IF3_DAC_SEL_R2L (0x2 << 6)
461#define RT5640_IF3_DAC_SEL_SWAP (0x3 << 6)
462#define RT5640_IF3_ADC_SEL_MASK (0x3 << 4)
463#define RT5640_IF3_ADC_SEL_SFT 4
464#define RT5640_IF3_ADC_SEL_NOR (0x0 << 4)
465#define RT5640_IF3_ADC_SEL_L2R (0x1 << 4)
466#define RT5640_IF3_ADC_SEL_R2L (0x2 << 4)
467#define RT5640_IF3_ADC_SEL_SWAP (0x3 << 4)
468
469/* REC Left Mixer Control 1 (0x3b) */
470#define RT5640_G_HP_L_RM_L_MASK (0x7 << 13)
471#define RT5640_G_HP_L_RM_L_SFT 13
472#define RT5640_G_IN_L_RM_L_MASK (0x7 << 10)
473#define RT5640_G_IN_L_RM_L_SFT 10
474#define RT5640_G_BST4_RM_L_MASK (0x7 << 7)
475#define RT5640_G_BST4_RM_L_SFT 7
476#define RT5640_G_BST3_RM_L_MASK (0x7 << 4)
477#define RT5640_G_BST3_RM_L_SFT 4
478#define RT5640_G_BST2_RM_L_MASK (0x7 << 1)
479#define RT5640_G_BST2_RM_L_SFT 1
480
481/* REC Left Mixer Control 2 (0x3c) */
482#define RT5640_G_BST1_RM_L_MASK (0x7 << 13)
483#define RT5640_G_BST1_RM_L_SFT 13
484#define RT5640_G_OM_L_RM_L_MASK (0x7 << 10)
485#define RT5640_G_OM_L_RM_L_SFT 10
486#define RT5640_M_HP_L_RM_L (0x1 << 6)
487#define RT5640_M_HP_L_RM_L_SFT 6
488#define RT5640_M_IN_L_RM_L (0x1 << 5)
489#define RT5640_M_IN_L_RM_L_SFT 5
490#define RT5640_M_BST4_RM_L (0x1 << 4)
491#define RT5640_M_BST4_RM_L_SFT 4
492#define RT5640_M_BST3_RM_L (0x1 << 3)
493#define RT5640_M_BST3_RM_L_SFT 3
494#define RT5640_M_BST2_RM_L (0x1 << 2)
495#define RT5640_M_BST2_RM_L_SFT 2
496#define RT5640_M_BST1_RM_L (0x1 << 1)
497#define RT5640_M_BST1_RM_L_SFT 1
498#define RT5640_M_OM_L_RM_L (0x1)
499#define RT5640_M_OM_L_RM_L_SFT 0
500
501/* REC Right Mixer Control 1 (0x3d) */
502#define RT5640_G_HP_R_RM_R_MASK (0x7 << 13)
503#define RT5640_G_HP_R_RM_R_SFT 13
504#define RT5640_G_IN_R_RM_R_MASK (0x7 << 10)
505#define RT5640_G_IN_R_RM_R_SFT 10
506#define RT5640_G_BST4_RM_R_MASK (0x7 << 7)
507#define RT5640_G_BST4_RM_R_SFT 7
508#define RT5640_G_BST3_RM_R_MASK (0x7 << 4)
509#define RT5640_G_BST3_RM_R_SFT 4
510#define RT5640_G_BST2_RM_R_MASK (0x7 << 1)
511#define RT5640_G_BST2_RM_R_SFT 1
512
513/* REC Right Mixer Control 2 (0x3e) */
514#define RT5640_G_BST1_RM_R_MASK (0x7 << 13)
515#define RT5640_G_BST1_RM_R_SFT 13
516#define RT5640_G_OM_R_RM_R_MASK (0x7 << 10)
517#define RT5640_G_OM_R_RM_R_SFT 10
518#define RT5640_M_HP_R_RM_R (0x1 << 6)
519#define RT5640_M_HP_R_RM_R_SFT 6
520#define RT5640_M_IN_R_RM_R (0x1 << 5)
521#define RT5640_M_IN_R_RM_R_SFT 5
522#define RT5640_M_BST4_RM_R (0x1 << 4)
523#define RT5640_M_BST4_RM_R_SFT 4
524#define RT5640_M_BST3_RM_R (0x1 << 3)
525#define RT5640_M_BST3_RM_R_SFT 3
526#define RT5640_M_BST2_RM_R (0x1 << 2)
527#define RT5640_M_BST2_RM_R_SFT 2
528#define RT5640_M_BST1_RM_R (0x1 << 1)
529#define RT5640_M_BST1_RM_R_SFT 1
530#define RT5640_M_OM_R_RM_R (0x1)
531#define RT5640_M_OM_R_RM_R_SFT 0
532
533/* HPMIX Control (0x45) */
534#define RT5640_M_DAC2_HM (0x1 << 15)
535#define RT5640_M_DAC2_HM_SFT 15
536#define RT5640_M_DAC1_HM (0x1 << 14)
537#define RT5640_M_DAC1_HM_SFT 14
538#define RT5640_M_HPVOL_HM (0x1 << 13)
539#define RT5640_M_HPVOL_HM_SFT 13
540#define RT5640_G_HPOMIX_MASK (0x1 << 12)
541#define RT5640_G_HPOMIX_SFT 12
542
543/* SPK Left Mixer Control (0x46) */
544#define RT5640_G_RM_L_SM_L_MASK (0x3 << 14)
545#define RT5640_G_RM_L_SM_L_SFT 14
546#define RT5640_G_IN_L_SM_L_MASK (0x3 << 12)
547#define RT5640_G_IN_L_SM_L_SFT 12
548#define RT5640_G_DAC_L1_SM_L_MASK (0x3 << 10)
549#define RT5640_G_DAC_L1_SM_L_SFT 10
550#define RT5640_G_DAC_L2_SM_L_MASK (0x3 << 8)
551#define RT5640_G_DAC_L2_SM_L_SFT 8
552#define RT5640_G_OM_L_SM_L_MASK (0x3 << 6)
553#define RT5640_G_OM_L_SM_L_SFT 6
554#define RT5640_M_RM_L_SM_L (0x1 << 5)
555#define RT5640_M_RM_L_SM_L_SFT 5
556#define RT5640_M_IN_L_SM_L (0x1 << 4)
557#define RT5640_M_IN_L_SM_L_SFT 4
558#define RT5640_M_DAC_L1_SM_L (0x1 << 3)
559#define RT5640_M_DAC_L1_SM_L_SFT 3
560#define RT5640_M_DAC_L2_SM_L (0x1 << 2)
561#define RT5640_M_DAC_L2_SM_L_SFT 2
562#define RT5640_M_OM_L_SM_L (0x1 << 1)
563#define RT5640_M_OM_L_SM_L_SFT 1
564
565/* SPK Right Mixer Control (0x47) */
566#define RT5640_G_RM_R_SM_R_MASK (0x3 << 14)
567#define RT5640_G_RM_R_SM_R_SFT 14
568#define RT5640_G_IN_R_SM_R_MASK (0x3 << 12)
569#define RT5640_G_IN_R_SM_R_SFT 12
570#define RT5640_G_DAC_R1_SM_R_MASK (0x3 << 10)
571#define RT5640_G_DAC_R1_SM_R_SFT 10
572#define RT5640_G_DAC_R2_SM_R_MASK (0x3 << 8)
573#define RT5640_G_DAC_R2_SM_R_SFT 8
574#define RT5640_G_OM_R_SM_R_MASK (0x3 << 6)
575#define RT5640_G_OM_R_SM_R_SFT 6
576#define RT5640_M_RM_R_SM_R (0x1 << 5)
577#define RT5640_M_RM_R_SM_R_SFT 5
578#define RT5640_M_IN_R_SM_R (0x1 << 4)
579#define RT5640_M_IN_R_SM_R_SFT 4
580#define RT5640_M_DAC_R1_SM_R (0x1 << 3)
581#define RT5640_M_DAC_R1_SM_R_SFT 3
582#define RT5640_M_DAC_R2_SM_R (0x1 << 2)
583#define RT5640_M_DAC_R2_SM_R_SFT 2
584#define RT5640_M_OM_R_SM_R (0x1 << 1)
585#define RT5640_M_OM_R_SM_R_SFT 1
586
587/* SPOLMIX Control (0x48) */
588#define RT5640_M_DAC_R1_SPM_L (0x1 << 15)
589#define RT5640_M_DAC_R1_SPM_L_SFT 15
590#define RT5640_M_DAC_L1_SPM_L (0x1 << 14)
591#define RT5640_M_DAC_L1_SPM_L_SFT 14
592#define RT5640_M_SV_R_SPM_L (0x1 << 13)
593#define RT5640_M_SV_R_SPM_L_SFT 13
594#define RT5640_M_SV_L_SPM_L (0x1 << 12)
595#define RT5640_M_SV_L_SPM_L_SFT 12
596#define RT5640_M_BST1_SPM_L (0x1 << 11)
597#define RT5640_M_BST1_SPM_L_SFT 11
598
599/* SPORMIX Control (0x49) */
600#define RT5640_M_DAC_R1_SPM_R (0x1 << 13)
601#define RT5640_M_DAC_R1_SPM_R_SFT 13
602#define RT5640_M_SV_R_SPM_R (0x1 << 12)
603#define RT5640_M_SV_R_SPM_R_SFT 12
604#define RT5640_M_BST1_SPM_R (0x1 << 11)
605#define RT5640_M_BST1_SPM_R_SFT 11
606
607/* SPOLMIX / SPORMIX Ratio Control (0x4a) */
608#define RT5640_SPO_CLSD_RATIO_MASK (0x7)
609#define RT5640_SPO_CLSD_RATIO_SFT 0
610
611/* Mono Output Mixer Control (0x4c) */
612#define RT5640_M_DAC_R2_MM (0x1 << 15)
613#define RT5640_M_DAC_R2_MM_SFT 15
614#define RT5640_M_DAC_L2_MM (0x1 << 14)
615#define RT5640_M_DAC_L2_MM_SFT 14
616#define RT5640_M_OV_R_MM (0x1 << 13)
617#define RT5640_M_OV_R_MM_SFT 13
618#define RT5640_M_OV_L_MM (0x1 << 12)
619#define RT5640_M_OV_L_MM_SFT 12
620#define RT5640_M_BST1_MM (0x1 << 11)
621#define RT5640_M_BST1_MM_SFT 11
622#define RT5640_G_MONOMIX_MASK (0x1 << 10)
623#define RT5640_G_MONOMIX_SFT 10
624
625/* Output Left Mixer Control 1 (0x4d) */
626#define RT5640_G_BST3_OM_L_MASK (0x7 << 13)
627#define RT5640_G_BST3_OM_L_SFT 13
628#define RT5640_G_BST2_OM_L_MASK (0x7 << 10)
629#define RT5640_G_BST2_OM_L_SFT 10
630#define RT5640_G_BST1_OM_L_MASK (0x7 << 7)
631#define RT5640_G_BST1_OM_L_SFT 7
632#define RT5640_G_IN_L_OM_L_MASK (0x7 << 4)
633#define RT5640_G_IN_L_OM_L_SFT 4
634#define RT5640_G_RM_L_OM_L_MASK (0x7 << 1)
635#define RT5640_G_RM_L_OM_L_SFT 1
636
637/* Output Left Mixer Control 2 (0x4e) */
638#define RT5640_G_DAC_R2_OM_L_MASK (0x7 << 13)
639#define RT5640_G_DAC_R2_OM_L_SFT 13
640#define RT5640_G_DAC_L2_OM_L_MASK (0x7 << 10)
641#define RT5640_G_DAC_L2_OM_L_SFT 10
642#define RT5640_G_DAC_L1_OM_L_MASK (0x7 << 7)
643#define RT5640_G_DAC_L1_OM_L_SFT 7
644
645/* Output Left Mixer Control 3 (0x4f) */
646#define RT5640_M_SM_L_OM_L (0x1 << 8)
647#define RT5640_M_SM_L_OM_L_SFT 8
648#define RT5640_M_BST3_OM_L (0x1 << 7)
649#define RT5640_M_BST3_OM_L_SFT 7
650#define RT5640_M_BST2_OM_L (0x1 << 6)
651#define RT5640_M_BST2_OM_L_SFT 6
652#define RT5640_M_BST1_OM_L (0x1 << 5)
653#define RT5640_M_BST1_OM_L_SFT 5
654#define RT5640_M_IN_L_OM_L (0x1 << 4)
655#define RT5640_M_IN_L_OM_L_SFT 4
656#define RT5640_M_RM_L_OM_L (0x1 << 3)
657#define RT5640_M_RM_L_OM_L_SFT 3
658#define RT5640_M_DAC_R2_OM_L (0x1 << 2)
659#define RT5640_M_DAC_R2_OM_L_SFT 2
660#define RT5640_M_DAC_L2_OM_L (0x1 << 1)
661#define RT5640_M_DAC_L2_OM_L_SFT 1
662#define RT5640_M_DAC_L1_OM_L (0x1)
663#define RT5640_M_DAC_L1_OM_L_SFT 0
664
665/* Output Right Mixer Control 1 (0x50) */
666#define RT5640_G_BST4_OM_R_MASK (0x7 << 13)
667#define RT5640_G_BST4_OM_R_SFT 13
668#define RT5640_G_BST2_OM_R_MASK (0x7 << 10)
669#define RT5640_G_BST2_OM_R_SFT 10
670#define RT5640_G_BST1_OM_R_MASK (0x7 << 7)
671#define RT5640_G_BST1_OM_R_SFT 7
672#define RT5640_G_IN_R_OM_R_MASK (0x7 << 4)
673#define RT5640_G_IN_R_OM_R_SFT 4
674#define RT5640_G_RM_R_OM_R_MASK (0x7 << 1)
675#define RT5640_G_RM_R_OM_R_SFT 1
676
677/* Output Right Mixer Control 2 (0x51) */
678#define RT5640_G_DAC_L2_OM_R_MASK (0x7 << 13)
679#define RT5640_G_DAC_L2_OM_R_SFT 13
680#define RT5640_G_DAC_R2_OM_R_MASK (0x7 << 10)
681#define RT5640_G_DAC_R2_OM_R_SFT 10
682#define RT5640_G_DAC_R1_OM_R_MASK (0x7 << 7)
683#define RT5640_G_DAC_R1_OM_R_SFT 7
684
685/* Output Right Mixer Control 3 (0x52) */
686#define RT5640_M_SM_L_OM_R (0x1 << 8)
687#define RT5640_M_SM_L_OM_R_SFT 8
688#define RT5640_M_BST4_OM_R (0x1 << 7)
689#define RT5640_M_BST4_OM_R_SFT 7
690#define RT5640_M_BST2_OM_R (0x1 << 6)
691#define RT5640_M_BST2_OM_R_SFT 6
692#define RT5640_M_BST1_OM_R (0x1 << 5)
693#define RT5640_M_BST1_OM_R_SFT 5
694#define RT5640_M_IN_R_OM_R (0x1 << 4)
695#define RT5640_M_IN_R_OM_R_SFT 4
696#define RT5640_M_RM_R_OM_R (0x1 << 3)
697#define RT5640_M_RM_R_OM_R_SFT 3
698#define RT5640_M_DAC_L2_OM_R (0x1 << 2)
699#define RT5640_M_DAC_L2_OM_R_SFT 2
700#define RT5640_M_DAC_R2_OM_R (0x1 << 1)
701#define RT5640_M_DAC_R2_OM_R_SFT 1
702#define RT5640_M_DAC_R1_OM_R (0x1)
703#define RT5640_M_DAC_R1_OM_R_SFT 0
704
705/* LOUT Mixer Control (0x53) */
706#define RT5640_M_DAC_L1_LM (0x1 << 15)
707#define RT5640_M_DAC_L1_LM_SFT 15
708#define RT5640_M_DAC_R1_LM (0x1 << 14)
709#define RT5640_M_DAC_R1_LM_SFT 14
710#define RT5640_M_OV_L_LM (0x1 << 13)
711#define RT5640_M_OV_L_LM_SFT 13
712#define RT5640_M_OV_R_LM (0x1 << 12)
713#define RT5640_M_OV_R_LM_SFT 12
714#define RT5640_G_LOUTMIX_MASK (0x1 << 11)
715#define RT5640_G_LOUTMIX_SFT 11
716
717/* Power Management for Digital 1 (0x61) */
718#define RT5640_PWR_I2S1 (0x1 << 15)
719#define RT5640_PWR_I2S1_BIT 15
720#define RT5640_PWR_I2S2 (0x1 << 14)
721#define RT5640_PWR_I2S2_BIT 14
722#define RT5640_PWR_DAC_L1 (0x1 << 12)
723#define RT5640_PWR_DAC_L1_BIT 12
724#define RT5640_PWR_DAC_R1 (0x1 << 11)
725#define RT5640_PWR_DAC_R1_BIT 11
726#define RT5640_PWR_DAC_L2 (0x1 << 7)
727#define RT5640_PWR_DAC_L2_BIT 7
728#define RT5640_PWR_DAC_R2 (0x1 << 6)
729#define RT5640_PWR_DAC_R2_BIT 6
730#define RT5640_PWR_ADC_L (0x1 << 2)
731#define RT5640_PWR_ADC_L_BIT 2
732#define RT5640_PWR_ADC_R (0x1 << 1)
733#define RT5640_PWR_ADC_R_BIT 1
734#define RT5640_PWR_CLS_D (0x1)
735#define RT5640_PWR_CLS_D_BIT 0
736
737/* Power Management for Digital 2 (0x62) */
738#define RT5640_PWR_ADC_SF (0x1 << 15)
739#define RT5640_PWR_ADC_SF_BIT 15
740#define RT5640_PWR_ADC_MF_L (0x1 << 14)
741#define RT5640_PWR_ADC_MF_L_BIT 14
742#define RT5640_PWR_ADC_MF_R (0x1 << 13)
743#define RT5640_PWR_ADC_MF_R_BIT 13
744#define RT5640_PWR_I2S_DSP (0x1 << 12)
745#define RT5640_PWR_I2S_DSP_BIT 12
746
747/* Power Management for Analog 1 (0x63) */
748#define RT5640_PWR_VREF1 (0x1 << 15)
749#define RT5640_PWR_VREF1_BIT 15
750#define RT5640_PWR_FV1 (0x1 << 14)
751#define RT5640_PWR_FV1_BIT 14
752#define RT5640_PWR_MB (0x1 << 13)
753#define RT5640_PWR_MB_BIT 13
754#define RT5640_PWR_LM (0x1 << 12)
755#define RT5640_PWR_LM_BIT 12
756#define RT5640_PWR_BG (0x1 << 11)
757#define RT5640_PWR_BG_BIT 11
758#define RT5640_PWR_MM (0x1 << 10)
759#define RT5640_PWR_MM_BIT 10
760#define RT5640_PWR_MA (0x1 << 8)
761#define RT5640_PWR_MA_BIT 8
762#define RT5640_PWR_HP_L (0x1 << 7)
763#define RT5640_PWR_HP_L_BIT 7
764#define RT5640_PWR_HP_R (0x1 << 6)
765#define RT5640_PWR_HP_R_BIT 6
766#define RT5640_PWR_HA (0x1 << 5)
767#define RT5640_PWR_HA_BIT 5
768#define RT5640_PWR_VREF2 (0x1 << 4)
769#define RT5640_PWR_VREF2_BIT 4
770#define RT5640_PWR_FV2 (0x1 << 3)
771#define RT5640_PWR_FV2_BIT 3
772#define RT5640_PWR_LDO2 (0x1 << 2)
773#define RT5640_PWR_LDO2_BIT 2
774
775/* Power Management for Analog 2 (0x64) */
776#define RT5640_PWR_BST1 (0x1 << 15)
777#define RT5640_PWR_BST1_BIT 15
778#define RT5640_PWR_BST2 (0x1 << 14)
779#define RT5640_PWR_BST2_BIT 14
780#define RT5640_PWR_BST3 (0x1 << 13)
781#define RT5640_PWR_BST3_BIT 13
782#define RT5640_PWR_BST4 (0x1 << 12)
783#define RT5640_PWR_BST4_BIT 12
784#define RT5640_PWR_MB1 (0x1 << 11)
785#define RT5640_PWR_MB1_BIT 11
786#define RT5640_PWR_PLL (0x1 << 9)
787#define RT5640_PWR_PLL_BIT 9
788
789/* Power Management for Mixer (0x65) */
790#define RT5640_PWR_OM_L (0x1 << 15)
791#define RT5640_PWR_OM_L_BIT 15
792#define RT5640_PWR_OM_R (0x1 << 14)
793#define RT5640_PWR_OM_R_BIT 14
794#define RT5640_PWR_SM_L (0x1 << 13)
795#define RT5640_PWR_SM_L_BIT 13
796#define RT5640_PWR_SM_R (0x1 << 12)
797#define RT5640_PWR_SM_R_BIT 12
798#define RT5640_PWR_RM_L (0x1 << 11)
799#define RT5640_PWR_RM_L_BIT 11
800#define RT5640_PWR_RM_R (0x1 << 10)
801#define RT5640_PWR_RM_R_BIT 10
802
803/* Power Management for Volume (0x66) */
804#define RT5640_PWR_SV_L (0x1 << 15)
805#define RT5640_PWR_SV_L_BIT 15
806#define RT5640_PWR_SV_R (0x1 << 14)
807#define RT5640_PWR_SV_R_BIT 14
808#define RT5640_PWR_OV_L (0x1 << 13)
809#define RT5640_PWR_OV_L_BIT 13
810#define RT5640_PWR_OV_R (0x1 << 12)
811#define RT5640_PWR_OV_R_BIT 12
812#define RT5640_PWR_HV_L (0x1 << 11)
813#define RT5640_PWR_HV_L_BIT 11
814#define RT5640_PWR_HV_R (0x1 << 10)
815#define RT5640_PWR_HV_R_BIT 10
816#define RT5640_PWR_IN_L (0x1 << 9)
817#define RT5640_PWR_IN_L_BIT 9
818#define RT5640_PWR_IN_R (0x1 << 8)
819#define RT5640_PWR_IN_R_BIT 8
820
821/* I2S1/2/3 Audio Serial Data Port Control (0x70 0x71 0x72) */
822#define RT5640_I2S_MS_MASK (0x1 << 15)
823#define RT5640_I2S_MS_SFT 15
824#define RT5640_I2S_MS_M (0x0 << 15)
825#define RT5640_I2S_MS_S (0x1 << 15)
826#define RT5640_I2S_IF_MASK (0x7 << 12)
827#define RT5640_I2S_IF_SFT 12
828#define RT5640_I2S_O_CP_MASK (0x3 << 10)
829#define RT5640_I2S_O_CP_SFT 10
830#define RT5640_I2S_O_CP_OFF (0x0 << 10)
831#define RT5640_I2S_O_CP_U_LAW (0x1 << 10)
832#define RT5640_I2S_O_CP_A_LAW (0x2 << 10)
833#define RT5640_I2S_I_CP_MASK (0x3 << 8)
834#define RT5640_I2S_I_CP_SFT 8
835#define RT5640_I2S_I_CP_OFF (0x0 << 8)
836#define RT5640_I2S_I_CP_U_LAW (0x1 << 8)
837#define RT5640_I2S_I_CP_A_LAW (0x2 << 8)
838#define RT5640_I2S_BP_MASK (0x1 << 7)
839#define RT5640_I2S_BP_SFT 7
840#define RT5640_I2S_BP_NOR (0x0 << 7)
841#define RT5640_I2S_BP_INV (0x1 << 7)
842#define RT5640_I2S_DL_MASK (0x3 << 2)
843#define RT5640_I2S_DL_SFT 2
844#define RT5640_I2S_DL_16 (0x0 << 2)
845#define RT5640_I2S_DL_20 (0x1 << 2)
846#define RT5640_I2S_DL_24 (0x2 << 2)
847#define RT5640_I2S_DL_8 (0x3 << 2)
848#define RT5640_I2S_DF_MASK (0x3)
849#define RT5640_I2S_DF_SFT 0
850#define RT5640_I2S_DF_I2S (0x0)
851#define RT5640_I2S_DF_LEFT (0x1)
852#define RT5640_I2S_DF_PCM_A (0x2)
853#define RT5640_I2S_DF_PCM_B (0x3)
854
855/* I2S2 Audio Serial Data Port Control (0x71) */
856#define RT5640_I2S2_SDI_MASK (0x1 << 6)
857#define RT5640_I2S2_SDI_SFT 6
858#define RT5640_I2S2_SDI_I2S1 (0x0 << 6)
859#define RT5640_I2S2_SDI_I2S2 (0x1 << 6)
860
861/* ADC/DAC Clock Control 1 (0x73) */
862#define RT5640_I2S_BCLK_MS1_MASK (0x1 << 15)
863#define RT5640_I2S_BCLK_MS1_SFT 15
864#define RT5640_I2S_BCLK_MS1_32 (0x0 << 15)
865#define RT5640_I2S_BCLK_MS1_64 (0x1 << 15)
866#define RT5640_I2S_PD1_MASK (0x7 << 12)
867#define RT5640_I2S_PD1_SFT 12
868#define RT5640_I2S_PD1_1 (0x0 << 12)
869#define RT5640_I2S_PD1_2 (0x1 << 12)
870#define RT5640_I2S_PD1_3 (0x2 << 12)
871#define RT5640_I2S_PD1_4 (0x3 << 12)
872#define RT5640_I2S_PD1_6 (0x4 << 12)
873#define RT5640_I2S_PD1_8 (0x5 << 12)
874#define RT5640_I2S_PD1_12 (0x6 << 12)
875#define RT5640_I2S_PD1_16 (0x7 << 12)
876#define RT5640_I2S_BCLK_MS2_MASK (0x1 << 11)
877#define RT5640_I2S_BCLK_MS2_SFT 11
878#define RT5640_I2S_BCLK_MS2_32 (0x0 << 11)
879#define RT5640_I2S_BCLK_MS2_64 (0x1 << 11)
880#define RT5640_I2S_PD2_MASK (0x7 << 8)
881#define RT5640_I2S_PD2_SFT 8
882#define RT5640_I2S_PD2_1 (0x0 << 8)
883#define RT5640_I2S_PD2_2 (0x1 << 8)
884#define RT5640_I2S_PD2_3 (0x2 << 8)
885#define RT5640_I2S_PD2_4 (0x3 << 8)
886#define RT5640_I2S_PD2_6 (0x4 << 8)
887#define RT5640_I2S_PD2_8 (0x5 << 8)
888#define RT5640_I2S_PD2_12 (0x6 << 8)
889#define RT5640_I2S_PD2_16 (0x7 << 8)
890#define RT5640_I2S_BCLK_MS3_MASK (0x1 << 7)
891#define RT5640_I2S_BCLK_MS3_SFT 7
892#define RT5640_I2S_BCLK_MS3_32 (0x0 << 7)
893#define RT5640_I2S_BCLK_MS3_64 (0x1 << 7)
894#define RT5640_I2S_PD3_MASK (0x7 << 4)
895#define RT5640_I2S_PD3_SFT 4
896#define RT5640_I2S_PD3_1 (0x0 << 4)
897#define RT5640_I2S_PD3_2 (0x1 << 4)
898#define RT5640_I2S_PD3_3 (0x2 << 4)
899#define RT5640_I2S_PD3_4 (0x3 << 4)
900#define RT5640_I2S_PD3_6 (0x4 << 4)
901#define RT5640_I2S_PD3_8 (0x5 << 4)
902#define RT5640_I2S_PD3_12 (0x6 << 4)
903#define RT5640_I2S_PD3_16 (0x7 << 4)
904#define RT5640_DAC_OSR_MASK (0x3 << 2)
905#define RT5640_DAC_OSR_SFT 2
906#define RT5640_DAC_OSR_128 (0x0 << 2)
907#define RT5640_DAC_OSR_64 (0x1 << 2)
908#define RT5640_DAC_OSR_32 (0x2 << 2)
909#define RT5640_DAC_OSR_16 (0x3 << 2)
910#define RT5640_ADC_OSR_MASK (0x3)
911#define RT5640_ADC_OSR_SFT 0
912#define RT5640_ADC_OSR_128 (0x0)
913#define RT5640_ADC_OSR_64 (0x1)
914#define RT5640_ADC_OSR_32 (0x2)
915#define RT5640_ADC_OSR_16 (0x3)
916
917/* ADC/DAC Clock Control 2 (0x74) */
918#define RT5640_DAC_L_OSR_MASK (0x3 << 14)
919#define RT5640_DAC_L_OSR_SFT 14
920#define RT5640_DAC_L_OSR_128 (0x0 << 14)
921#define RT5640_DAC_L_OSR_64 (0x1 << 14)
922#define RT5640_DAC_L_OSR_32 (0x2 << 14)
923#define RT5640_DAC_L_OSR_16 (0x3 << 14)
924#define RT5640_ADC_R_OSR_MASK (0x3 << 12)
925#define RT5640_ADC_R_OSR_SFT 12
926#define RT5640_ADC_R_OSR_128 (0x0 << 12)
927#define RT5640_ADC_R_OSR_64 (0x1 << 12)
928#define RT5640_ADC_R_OSR_32 (0x2 << 12)
929#define RT5640_ADC_R_OSR_16 (0x3 << 12)
930#define RT5640_DAHPF_EN (0x1 << 11)
931#define RT5640_DAHPF_EN_SFT 11
932#define RT5640_ADHPF_EN (0x1 << 10)
933#define RT5640_ADHPF_EN_SFT 10
934
935/* Digital Microphone Control (0x75) */
936#define RT5640_DMIC_1_EN_MASK (0x1 << 15)
937#define RT5640_DMIC_1_EN_SFT 15
938#define RT5640_DMIC_1_DIS (0x0 << 15)
939#define RT5640_DMIC_1_EN (0x1 << 15)
940#define RT5640_DMIC_2_EN_MASK (0x1 << 14)
941#define RT5640_DMIC_2_EN_SFT 14
942#define RT5640_DMIC_2_DIS (0x0 << 14)
943#define RT5640_DMIC_2_EN (0x1 << 14)
944#define RT5640_DMIC_1L_LH_MASK (0x1 << 13)
945#define RT5640_DMIC_1L_LH_SFT 13
946#define RT5640_DMIC_1L_LH_FALLING (0x0 << 13)
947#define RT5640_DMIC_1L_LH_RISING (0x1 << 13)
948#define RT5640_DMIC_1R_LH_MASK (0x1 << 12)
949#define RT5640_DMIC_1R_LH_SFT 12
950#define RT5640_DMIC_1R_LH_FALLING (0x0 << 12)
951#define RT5640_DMIC_1R_LH_RISING (0x1 << 12)
952#define RT5640_DMIC_1_DP_MASK (0x1 << 11)
953#define RT5640_DMIC_1_DP_SFT 11
954#define RT5640_DMIC_1_DP_GPIO3 (0x0 << 11)
955#define RT5640_DMIC_1_DP_IN1P (0x1 << 11)
956#define RT5640_DMIC_2_DP_MASK (0x1 << 10)
957#define RT5640_DMIC_2_DP_SFT 10
958#define RT5640_DMIC_2_DP_GPIO4 (0x0 << 10)
959#define RT5640_DMIC_2_DP_IN1N (0x1 << 10)
960#define RT5640_DMIC_2L_LH_MASK (0x1 << 9)
961#define RT5640_DMIC_2L_LH_SFT 9
962#define RT5640_DMIC_2L_LH_FALLING (0x0 << 9)
963#define RT5640_DMIC_2L_LH_RISING (0x1 << 9)
964#define RT5640_DMIC_2R_LH_MASK (0x1 << 8)
965#define RT5640_DMIC_2R_LH_SFT 8
966#define RT5640_DMIC_2R_LH_FALLING (0x0 << 8)
967#define RT5640_DMIC_2R_LH_RISING (0x1 << 8)
968#define RT5640_DMIC_CLK_MASK (0x7 << 5)
969#define RT5640_DMIC_CLK_SFT 5
970
971/* Global Clock Control (0x80) */
972#define RT5640_SCLK_SRC_MASK (0x3 << 14)
973#define RT5640_SCLK_SRC_SFT 14
974#define RT5640_SCLK_SRC_MCLK (0x0 << 14)
975#define RT5640_SCLK_SRC_PLL1 (0x1 << 14)
976#define RT5640_SCLK_SRC_PLL1T (0x2 << 14)
977#define RT5640_SCLK_SRC_RCCLK (0x3 << 14) /* 15MHz */
978#define RT5640_PLL1_SRC_MASK (0x3 << 12)
979#define RT5640_PLL1_SRC_SFT 12
980#define RT5640_PLL1_SRC_MCLK (0x0 << 12)
981#define RT5640_PLL1_SRC_BCLK1 (0x1 << 12)
982#define RT5640_PLL1_SRC_BCLK2 (0x2 << 12)
983#define RT5640_PLL1_SRC_BCLK3 (0x3 << 12)
984#define RT5640_PLL1_PD_MASK (0x1 << 3)
985#define RT5640_PLL1_PD_SFT 3
986#define RT5640_PLL1_PD_1 (0x0 << 3)
987#define RT5640_PLL1_PD_2 (0x1 << 3)
988
989#define RT5640_PLL_INP_MAX 40000000
990#define RT5640_PLL_INP_MIN 256000
991/* PLL M/N/K Code Control 1 (0x81) */
992#define RT5640_PLL_N_MAX 0x1ff
993#define RT5640_PLL_N_MASK (RT5640_PLL_N_MAX << 7)
994#define RT5640_PLL_N_SFT 7
995#define RT5640_PLL_K_MAX 0x1f
996#define RT5640_PLL_K_MASK (RT5640_PLL_K_MAX)
997#define RT5640_PLL_K_SFT 0
998
999/* PLL M/N/K Code Control 2 (0x82) */
1000#define RT5640_PLL_M_MAX 0xf
1001#define RT5640_PLL_M_MASK (RT5640_PLL_M_MAX << 12)
1002#define RT5640_PLL_M_SFT 12
1003#define RT5640_PLL_M_BP (0x1 << 11)
1004#define RT5640_PLL_M_BP_SFT 11
1005
1006/* ASRC Control 1 (0x83) */
1007#define RT5640_STO_T_MASK (0x1 << 15)
1008#define RT5640_STO_T_SFT 15
1009#define RT5640_STO_T_SCLK (0x0 << 15)
1010#define RT5640_STO_T_LRCK1 (0x1 << 15)
1011#define RT5640_M1_T_MASK (0x1 << 14)
1012#define RT5640_M1_T_SFT 14
1013#define RT5640_M1_T_I2S2 (0x0 << 14)
1014#define RT5640_M1_T_I2S2_D3 (0x1 << 14)
1015#define RT5640_I2S2_F_MASK (0x1 << 12)
1016#define RT5640_I2S2_F_SFT 12
1017#define RT5640_I2S2_F_I2S2_D2 (0x0 << 12)
1018#define RT5640_I2S2_F_I2S1_TCLK (0x1 << 12)
1019#define RT5640_DMIC_1_M_MASK (0x1 << 9)
1020#define RT5640_DMIC_1_M_SFT 9
1021#define RT5640_DMIC_1_M_NOR (0x0 << 9)
1022#define RT5640_DMIC_1_M_ASYN (0x1 << 9)
1023#define RT5640_DMIC_2_M_MASK (0x1 << 8)
1024#define RT5640_DMIC_2_M_SFT 8
1025#define RT5640_DMIC_2_M_NOR (0x0 << 8)
1026#define RT5640_DMIC_2_M_ASYN (0x1 << 8)
1027
1028/* ASRC Control 2 (0x84) */
1029#define RT5640_MDA_L_M_MASK (0x1 << 15)
1030#define RT5640_MDA_L_M_SFT 15
1031#define RT5640_MDA_L_M_NOR (0x0 << 15)
1032#define RT5640_MDA_L_M_ASYN (0x1 << 15)
1033#define RT5640_MDA_R_M_MASK (0x1 << 14)
1034#define RT5640_MDA_R_M_SFT 14
1035#define RT5640_MDA_R_M_NOR (0x0 << 14)
1036#define RT5640_MDA_R_M_ASYN (0x1 << 14)
1037#define RT5640_MAD_L_M_MASK (0x1 << 13)
1038#define RT5640_MAD_L_M_SFT 13
1039#define RT5640_MAD_L_M_NOR (0x0 << 13)
1040#define RT5640_MAD_L_M_ASYN (0x1 << 13)
1041#define RT5640_MAD_R_M_MASK (0x1 << 12)
1042#define RT5640_MAD_R_M_SFT 12
1043#define RT5640_MAD_R_M_NOR (0x0 << 12)
1044#define RT5640_MAD_R_M_ASYN (0x1 << 12)
1045#define RT5640_ADC_M_MASK (0x1 << 11)
1046#define RT5640_ADC_M_SFT 11
1047#define RT5640_ADC_M_NOR (0x0 << 11)
1048#define RT5640_ADC_M_ASYN (0x1 << 11)
1049#define RT5640_STO_DAC_M_MASK (0x1 << 5)
1050#define RT5640_STO_DAC_M_SFT 5
1051#define RT5640_STO_DAC_M_NOR (0x0 << 5)
1052#define RT5640_STO_DAC_M_ASYN (0x1 << 5)
1053#define RT5640_I2S1_R_D_MASK (0x1 << 4)
1054#define RT5640_I2S1_R_D_SFT 4
1055#define RT5640_I2S1_R_D_DIS (0x0 << 4)
1056#define RT5640_I2S1_R_D_EN (0x1 << 4)
1057#define RT5640_I2S2_R_D_MASK (0x1 << 3)
1058#define RT5640_I2S2_R_D_SFT 3
1059#define RT5640_I2S2_R_D_DIS (0x0 << 3)
1060#define RT5640_I2S2_R_D_EN (0x1 << 3)
1061#define RT5640_PRE_SCLK_MASK (0x3)
1062#define RT5640_PRE_SCLK_SFT 0
1063#define RT5640_PRE_SCLK_512 (0x0)
1064#define RT5640_PRE_SCLK_1024 (0x1)
1065#define RT5640_PRE_SCLK_2048 (0x2)
1066
1067/* ASRC Control 3 (0x85) */
1068#define RT5640_I2S1_RATE_MASK (0xf << 12)
1069#define RT5640_I2S1_RATE_SFT 12
1070#define RT5640_I2S2_RATE_MASK (0xf << 8)
1071#define RT5640_I2S2_RATE_SFT 8
1072
1073/* ASRC Control 4 (0x89) */
1074#define RT5640_I2S1_PD_MASK (0x7 << 12)
1075#define RT5640_I2S1_PD_SFT 12
1076#define RT5640_I2S2_PD_MASK (0x7 << 8)
1077#define RT5640_I2S2_PD_SFT 8
1078
1079/* HPOUT Over Current Detection (0x8b) */
1080#define RT5640_HP_OVCD_MASK (0x1 << 10)
1081#define RT5640_HP_OVCD_SFT 10
1082#define RT5640_HP_OVCD_DIS (0x0 << 10)
1083#define RT5640_HP_OVCD_EN (0x1 << 10)
1084#define RT5640_HP_OC_TH_MASK (0x3 << 8)
1085#define RT5640_HP_OC_TH_SFT 8
1086#define RT5640_HP_OC_TH_90 (0x0 << 8)
1087#define RT5640_HP_OC_TH_105 (0x1 << 8)
1088#define RT5640_HP_OC_TH_120 (0x2 << 8)
1089#define RT5640_HP_OC_TH_135 (0x3 << 8)
1090
1091/* Class D Over Current Control (0x8c) */
1092#define RT5640_CLSD_OC_MASK (0x1 << 9)
1093#define RT5640_CLSD_OC_SFT 9
1094#define RT5640_CLSD_OC_PU (0x0 << 9)
1095#define RT5640_CLSD_OC_PD (0x1 << 9)
1096#define RT5640_AUTO_PD_MASK (0x1 << 8)
1097#define RT5640_AUTO_PD_SFT 8
1098#define RT5640_AUTO_PD_DIS (0x0 << 8)
1099#define RT5640_AUTO_PD_EN (0x1 << 8)
1100#define RT5640_CLSD_OC_TH_MASK (0x3f)
1101#define RT5640_CLSD_OC_TH_SFT 0
1102
1103/* Class D Output Control (0x8d) */
1104#define RT5640_CLSD_RATIO_MASK (0xf << 12)
1105#define RT5640_CLSD_RATIO_SFT 12
1106#define RT5640_CLSD_OM_MASK (0x1 << 11)
1107#define RT5640_CLSD_OM_SFT 11
1108#define RT5640_CLSD_OM_MONO (0x0 << 11)
1109#define RT5640_CLSD_OM_STO (0x1 << 11)
1110#define RT5640_CLSD_SCH_MASK (0x1 << 10)
1111#define RT5640_CLSD_SCH_SFT 10
1112#define RT5640_CLSD_SCH_L (0x0 << 10)
1113#define RT5640_CLSD_SCH_S (0x1 << 10)
1114
1115/* Depop Mode Control 1 (0x8e) */
1116#define RT5640_SMT_TRIG_MASK (0x1 << 15)
1117#define RT5640_SMT_TRIG_SFT 15
1118#define RT5640_SMT_TRIG_DIS (0x0 << 15)
1119#define RT5640_SMT_TRIG_EN (0x1 << 15)
1120#define RT5640_HP_L_SMT_MASK (0x1 << 9)
1121#define RT5640_HP_L_SMT_SFT 9
1122#define RT5640_HP_L_SMT_DIS (0x0 << 9)
1123#define RT5640_HP_L_SMT_EN (0x1 << 9)
1124#define RT5640_HP_R_SMT_MASK (0x1 << 8)
1125#define RT5640_HP_R_SMT_SFT 8
1126#define RT5640_HP_R_SMT_DIS (0x0 << 8)
1127#define RT5640_HP_R_SMT_EN (0x1 << 8)
1128#define RT5640_HP_CD_PD_MASK (0x1 << 7)
1129#define RT5640_HP_CD_PD_SFT 7
1130#define RT5640_HP_CD_PD_DIS (0x0 << 7)
1131#define RT5640_HP_CD_PD_EN (0x1 << 7)
1132#define RT5640_RSTN_MASK (0x1 << 6)
1133#define RT5640_RSTN_SFT 6
1134#define RT5640_RSTN_DIS (0x0 << 6)
1135#define RT5640_RSTN_EN (0x1 << 6)
1136#define RT5640_RSTP_MASK (0x1 << 5)
1137#define RT5640_RSTP_SFT 5
1138#define RT5640_RSTP_DIS (0x0 << 5)
1139#define RT5640_RSTP_EN (0x1 << 5)
1140#define RT5640_HP_CO_MASK (0x1 << 4)
1141#define RT5640_HP_CO_SFT 4
1142#define RT5640_HP_CO_DIS (0x0 << 4)
1143#define RT5640_HP_CO_EN (0x1 << 4)
1144#define RT5640_HP_CP_MASK (0x1 << 3)
1145#define RT5640_HP_CP_SFT 3
1146#define RT5640_HP_CP_PD (0x0 << 3)
1147#define RT5640_HP_CP_PU (0x1 << 3)
1148#define RT5640_HP_SG_MASK (0x1 << 2)
1149#define RT5640_HP_SG_SFT 2
1150#define RT5640_HP_SG_DIS (0x0 << 2)
1151#define RT5640_HP_SG_EN (0x1 << 2)
1152#define RT5640_HP_DP_MASK (0x1 << 1)
1153#define RT5640_HP_DP_SFT 1
1154#define RT5640_HP_DP_PD (0x0 << 1)
1155#define RT5640_HP_DP_PU (0x1 << 1)
1156#define RT5640_HP_CB_MASK (0x1)
1157#define RT5640_HP_CB_SFT 0
1158#define RT5640_HP_CB_PD (0x0)
1159#define RT5640_HP_CB_PU (0x1)
1160
1161/* Depop Mode Control 2 (0x8f) */
1162#define RT5640_DEPOP_MASK (0x1 << 13)
1163#define RT5640_DEPOP_SFT 13
1164#define RT5640_DEPOP_AUTO (0x0 << 13)
1165#define RT5640_DEPOP_MAN (0x1 << 13)
1166#define RT5640_RAMP_MASK (0x1 << 12)
1167#define RT5640_RAMP_SFT 12
1168#define RT5640_RAMP_DIS (0x0 << 12)
1169#define RT5640_RAMP_EN (0x1 << 12)
1170#define RT5640_BPS_MASK (0x1 << 11)
1171#define RT5640_BPS_SFT 11
1172#define RT5640_BPS_DIS (0x0 << 11)
1173#define RT5640_BPS_EN (0x1 << 11)
1174#define RT5640_FAST_UPDN_MASK (0x1 << 10)
1175#define RT5640_FAST_UPDN_SFT 10
1176#define RT5640_FAST_UPDN_DIS (0x0 << 10)
1177#define RT5640_FAST_UPDN_EN (0x1 << 10)
1178#define RT5640_MRES_MASK (0x3 << 8)
1179#define RT5640_MRES_SFT 8
1180#define RT5640_MRES_15MO (0x0 << 8)
1181#define RT5640_MRES_25MO (0x1 << 8)
1182#define RT5640_MRES_35MO (0x2 << 8)
1183#define RT5640_MRES_45MO (0x3 << 8)
1184#define RT5640_VLO_MASK (0x1 << 7)
1185#define RT5640_VLO_SFT 7
1186#define RT5640_VLO_3V (0x0 << 7)
1187#define RT5640_VLO_32V (0x1 << 7)
1188#define RT5640_DIG_DP_MASK (0x1 << 6)
1189#define RT5640_DIG_DP_SFT 6
1190#define RT5640_DIG_DP_DIS (0x0 << 6)
1191#define RT5640_DIG_DP_EN (0x1 << 6)
1192#define RT5640_DP_TH_MASK (0x3 << 4)
1193#define RT5640_DP_TH_SFT 4
1194
1195/* Depop Mode Control 3 (0x90) */
1196#define RT5640_CP_SYS_MASK (0x7 << 12)
1197#define RT5640_CP_SYS_SFT 12
1198#define RT5640_CP_FQ1_MASK (0x7 << 8)
1199#define RT5640_CP_FQ1_SFT 8
1200#define RT5640_CP_FQ2_MASK (0x7 << 4)
1201#define RT5640_CP_FQ2_SFT 4
1202#define RT5640_CP_FQ3_MASK (0x7)
1203#define RT5640_CP_FQ3_SFT 0
1204
1205/* HPOUT charge pump (0x91) */
1206#define RT5640_OSW_L_MASK (0x1 << 11)
1207#define RT5640_OSW_L_SFT 11
1208#define RT5640_OSW_L_DIS (0x0 << 11)
1209#define RT5640_OSW_L_EN (0x1 << 11)
1210#define RT5640_OSW_R_MASK (0x1 << 10)
1211#define RT5640_OSW_R_SFT 10
1212#define RT5640_OSW_R_DIS (0x0 << 10)
1213#define RT5640_OSW_R_EN (0x1 << 10)
1214#define RT5640_PM_HP_MASK (0x3 << 8)
1215#define RT5640_PM_HP_SFT 8
1216#define RT5640_PM_HP_LV (0x0 << 8)
1217#define RT5640_PM_HP_MV (0x1 << 8)
1218#define RT5640_PM_HP_HV (0x2 << 8)
1219#define RT5640_IB_HP_MASK (0x3 << 6)
1220#define RT5640_IB_HP_SFT 6
1221#define RT5640_IB_HP_125IL (0x0 << 6)
1222#define RT5640_IB_HP_25IL (0x1 << 6)
1223#define RT5640_IB_HP_5IL (0x2 << 6)
1224#define RT5640_IB_HP_1IL (0x3 << 6)
1225
1226/* PV detection and SPK gain control (0x92) */
1227#define RT5640_PVDD_DET_MASK (0x1 << 15)
1228#define RT5640_PVDD_DET_SFT 15
1229#define RT5640_PVDD_DET_DIS (0x0 << 15)
1230#define RT5640_PVDD_DET_EN (0x1 << 15)
1231#define RT5640_SPK_AG_MASK (0x1 << 14)
1232#define RT5640_SPK_AG_SFT 14
1233#define RT5640_SPK_AG_DIS (0x0 << 14)
1234#define RT5640_SPK_AG_EN (0x1 << 14)
1235
1236/* Micbias Control (0x93) */
1237#define RT5640_MIC1_BS_MASK (0x1 << 15)
1238#define RT5640_MIC1_BS_SFT 15
1239#define RT5640_MIC1_BS_9AV (0x0 << 15)
1240#define RT5640_MIC1_BS_75AV (0x1 << 15)
1241#define RT5640_MIC2_BS_MASK (0x1 << 14)
1242#define RT5640_MIC2_BS_SFT 14
1243#define RT5640_MIC2_BS_9AV (0x0 << 14)
1244#define RT5640_MIC2_BS_75AV (0x1 << 14)
1245#define RT5640_MIC1_CLK_MASK (0x1 << 13)
1246#define RT5640_MIC1_CLK_SFT 13
1247#define RT5640_MIC1_CLK_DIS (0x0 << 13)
1248#define RT5640_MIC1_CLK_EN (0x1 << 13)
1249#define RT5640_MIC2_CLK_MASK (0x1 << 12)
1250#define RT5640_MIC2_CLK_SFT 12
1251#define RT5640_MIC2_CLK_DIS (0x0 << 12)
1252#define RT5640_MIC2_CLK_EN (0x1 << 12)
1253#define RT5640_MIC1_OVCD_MASK (0x1 << 11)
1254#define RT5640_MIC1_OVCD_SFT 11
1255#define RT5640_MIC1_OVCD_DIS (0x0 << 11)
1256#define RT5640_MIC1_OVCD_EN (0x1 << 11)
1257#define RT5640_MIC1_OVTH_MASK (0x3 << 9)
1258#define RT5640_MIC1_OVTH_SFT 9
1259#define RT5640_MIC1_OVTH_600UA (0x0 << 9)
1260#define RT5640_MIC1_OVTH_1500UA (0x1 << 9)
1261#define RT5640_MIC1_OVTH_2000UA (0x2 << 9)
1262#define RT5640_MIC2_OVCD_MASK (0x1 << 8)
1263#define RT5640_MIC2_OVCD_SFT 8
1264#define RT5640_MIC2_OVCD_DIS (0x0 << 8)
1265#define RT5640_MIC2_OVCD_EN (0x1 << 8)
1266#define RT5640_MIC2_OVTH_MASK (0x3 << 6)
1267#define RT5640_MIC2_OVTH_SFT 6
1268#define RT5640_MIC2_OVTH_600UA (0x0 << 6)
1269#define RT5640_MIC2_OVTH_1500UA (0x1 << 6)
1270#define RT5640_MIC2_OVTH_2000UA (0x2 << 6)
1271#define RT5640_PWR_MB_MASK (0x1 << 5)
1272#define RT5640_PWR_MB_SFT 5
1273#define RT5640_PWR_MB_PD (0x0 << 5)
1274#define RT5640_PWR_MB_PU (0x1 << 5)
1275#define RT5640_PWR_CLK25M_MASK (0x1 << 4)
1276#define RT5640_PWR_CLK25M_SFT 4
1277#define RT5640_PWR_CLK25M_PD (0x0 << 4)
1278#define RT5640_PWR_CLK25M_PU (0x1 << 4)
1279
1280/* EQ Control 1 (0xb0) */
1281#define RT5640_EQ_SRC_MASK (0x1 << 15)
1282#define RT5640_EQ_SRC_SFT 15
1283#define RT5640_EQ_SRC_DAC (0x0 << 15)
1284#define RT5640_EQ_SRC_ADC (0x1 << 15)
1285#define RT5640_EQ_UPD (0x1 << 14)
1286#define RT5640_EQ_UPD_BIT 14
1287#define RT5640_EQ_CD_MASK (0x1 << 13)
1288#define RT5640_EQ_CD_SFT 13
1289#define RT5640_EQ_CD_DIS (0x0 << 13)
1290#define RT5640_EQ_CD_EN (0x1 << 13)
1291#define RT5640_EQ_DITH_MASK (0x3 << 8)
1292#define RT5640_EQ_DITH_SFT 8
1293#define RT5640_EQ_DITH_NOR (0x0 << 8)
1294#define RT5640_EQ_DITH_LSB (0x1 << 8)
1295#define RT5640_EQ_DITH_LSB_1 (0x2 << 8)
1296#define RT5640_EQ_DITH_LSB_2 (0x3 << 8)
1297
1298/* EQ Control 2 (0xb1) */
1299#define RT5640_EQ_HPF1_M_MASK (0x1 << 8)
1300#define RT5640_EQ_HPF1_M_SFT 8
1301#define RT5640_EQ_HPF1_M_HI (0x0 << 8)
1302#define RT5640_EQ_HPF1_M_1ST (0x1 << 8)
1303#define RT5640_EQ_LPF1_M_MASK (0x1 << 7)
1304#define RT5640_EQ_LPF1_M_SFT 7
1305#define RT5640_EQ_LPF1_M_LO (0x0 << 7)
1306#define RT5640_EQ_LPF1_M_1ST (0x1 << 7)
1307#define RT5640_EQ_HPF2_MASK (0x1 << 6)
1308#define RT5640_EQ_HPF2_SFT 6
1309#define RT5640_EQ_HPF2_DIS (0x0 << 6)
1310#define RT5640_EQ_HPF2_EN (0x1 << 6)
1311#define RT5640_EQ_HPF1_MASK (0x1 << 5)
1312#define RT5640_EQ_HPF1_SFT 5
1313#define RT5640_EQ_HPF1_DIS (0x0 << 5)
1314#define RT5640_EQ_HPF1_EN (0x1 << 5)
1315#define RT5640_EQ_BPF4_MASK (0x1 << 4)
1316#define RT5640_EQ_BPF4_SFT 4
1317#define RT5640_EQ_BPF4_DIS (0x0 << 4)
1318#define RT5640_EQ_BPF4_EN (0x1 << 4)
1319#define RT5640_EQ_BPF3_MASK (0x1 << 3)
1320#define RT5640_EQ_BPF3_SFT 3
1321#define RT5640_EQ_BPF3_DIS (0x0 << 3)
1322#define RT5640_EQ_BPF3_EN (0x1 << 3)
1323#define RT5640_EQ_BPF2_MASK (0x1 << 2)
1324#define RT5640_EQ_BPF2_SFT 2
1325#define RT5640_EQ_BPF2_DIS (0x0 << 2)
1326#define RT5640_EQ_BPF2_EN (0x1 << 2)
1327#define RT5640_EQ_BPF1_MASK (0x1 << 1)
1328#define RT5640_EQ_BPF1_SFT 1
1329#define RT5640_EQ_BPF1_DIS (0x0 << 1)
1330#define RT5640_EQ_BPF1_EN (0x1 << 1)
1331#define RT5640_EQ_LPF_MASK (0x1)
1332#define RT5640_EQ_LPF_SFT 0
1333#define RT5640_EQ_LPF_DIS (0x0)
1334#define RT5640_EQ_LPF_EN (0x1)
1335
1336/* Memory Test (0xb2) */
1337#define RT5640_MT_MASK (0x1 << 15)
1338#define RT5640_MT_SFT 15
1339#define RT5640_MT_DIS (0x0 << 15)
1340#define RT5640_MT_EN (0x1 << 15)
1341
1342/* DRC/AGC Control 1 (0xb4) */
1343#define RT5640_DRC_AGC_P_MASK (0x1 << 15)
1344#define RT5640_DRC_AGC_P_SFT 15
1345#define RT5640_DRC_AGC_P_DAC (0x0 << 15)
1346#define RT5640_DRC_AGC_P_ADC (0x1 << 15)
1347#define RT5640_DRC_AGC_MASK (0x1 << 14)
1348#define RT5640_DRC_AGC_SFT 14
1349#define RT5640_DRC_AGC_DIS (0x0 << 14)
1350#define RT5640_DRC_AGC_EN (0x1 << 14)
1351#define RT5640_DRC_AGC_UPD (0x1 << 13)
1352#define RT5640_DRC_AGC_UPD_BIT 13
1353#define RT5640_DRC_AGC_AR_MASK (0x1f << 8)
1354#define RT5640_DRC_AGC_AR_SFT 8
1355#define RT5640_DRC_AGC_R_MASK (0x7 << 5)
1356#define RT5640_DRC_AGC_R_SFT 5
1357#define RT5640_DRC_AGC_R_48K (0x1 << 5)
1358#define RT5640_DRC_AGC_R_96K (0x2 << 5)
1359#define RT5640_DRC_AGC_R_192K (0x3 << 5)
1360#define RT5640_DRC_AGC_R_441K (0x5 << 5)
1361#define RT5640_DRC_AGC_R_882K (0x6 << 5)
1362#define RT5640_DRC_AGC_R_1764K (0x7 << 5)
1363#define RT5640_DRC_AGC_RC_MASK (0x1f)
1364#define RT5640_DRC_AGC_RC_SFT 0
1365
1366/* DRC/AGC Control 2 (0xb5) */
1367#define RT5640_DRC_AGC_POB_MASK (0x3f << 8)
1368#define RT5640_DRC_AGC_POB_SFT 8
1369#define RT5640_DRC_AGC_CP_MASK (0x1 << 7)
1370#define RT5640_DRC_AGC_CP_SFT 7
1371#define RT5640_DRC_AGC_CP_DIS (0x0 << 7)
1372#define RT5640_DRC_AGC_CP_EN (0x1 << 7)
1373#define RT5640_DRC_AGC_CPR_MASK (0x3 << 5)
1374#define RT5640_DRC_AGC_CPR_SFT 5
1375#define RT5640_DRC_AGC_CPR_1_1 (0x0 << 5)
1376#define RT5640_DRC_AGC_CPR_1_2 (0x1 << 5)
1377#define RT5640_DRC_AGC_CPR_1_3 (0x2 << 5)
1378#define RT5640_DRC_AGC_CPR_1_4 (0x3 << 5)
1379#define RT5640_DRC_AGC_PRB_MASK (0x1f)
1380#define RT5640_DRC_AGC_PRB_SFT 0
1381
1382/* DRC/AGC Control 3 (0xb6) */
1383#define RT5640_DRC_AGC_NGB_MASK (0xf << 12)
1384#define RT5640_DRC_AGC_NGB_SFT 12
1385#define RT5640_DRC_AGC_TAR_MASK (0x1f << 7)
1386#define RT5640_DRC_AGC_TAR_SFT 7
1387#define RT5640_DRC_AGC_NG_MASK (0x1 << 6)
1388#define RT5640_DRC_AGC_NG_SFT 6
1389#define RT5640_DRC_AGC_NG_DIS (0x0 << 6)
1390#define RT5640_DRC_AGC_NG_EN (0x1 << 6)
1391#define RT5640_DRC_AGC_NGH_MASK (0x1 << 5)
1392#define RT5640_DRC_AGC_NGH_SFT 5
1393#define RT5640_DRC_AGC_NGH_DIS (0x0 << 5)
1394#define RT5640_DRC_AGC_NGH_EN (0x1 << 5)
1395#define RT5640_DRC_AGC_NGT_MASK (0x1f)
1396#define RT5640_DRC_AGC_NGT_SFT 0
1397
1398/* ANC Control 1 (0xb8) */
1399#define RT5640_ANC_M_MASK (0x1 << 15)
1400#define RT5640_ANC_M_SFT 15
1401#define RT5640_ANC_M_NOR (0x0 << 15)
1402#define RT5640_ANC_M_REV (0x1 << 15)
1403#define RT5640_ANC_MASK (0x1 << 14)
1404#define RT5640_ANC_SFT 14
1405#define RT5640_ANC_DIS (0x0 << 14)
1406#define RT5640_ANC_EN (0x1 << 14)
1407#define RT5640_ANC_MD_MASK (0x3 << 12)
1408#define RT5640_ANC_MD_SFT 12
1409#define RT5640_ANC_MD_DIS (0x0 << 12)
1410#define RT5640_ANC_MD_67MS (0x1 << 12)
1411#define RT5640_ANC_MD_267MS (0x2 << 12)
1412#define RT5640_ANC_MD_1067MS (0x3 << 12)
1413#define RT5640_ANC_SN_MASK (0x1 << 11)
1414#define RT5640_ANC_SN_SFT 11
1415#define RT5640_ANC_SN_DIS (0x0 << 11)
1416#define RT5640_ANC_SN_EN (0x1 << 11)
1417#define RT5640_ANC_CLK_MASK (0x1 << 10)
1418#define RT5640_ANC_CLK_SFT 10
1419#define RT5640_ANC_CLK_ANC (0x0 << 10)
1420#define RT5640_ANC_CLK_REG (0x1 << 10)
1421#define RT5640_ANC_ZCD_MASK (0x3 << 8)
1422#define RT5640_ANC_ZCD_SFT 8
1423#define RT5640_ANC_ZCD_DIS (0x0 << 8)
1424#define RT5640_ANC_ZCD_T1 (0x1 << 8)
1425#define RT5640_ANC_ZCD_T2 (0x2 << 8)
1426#define RT5640_ANC_ZCD_WT (0x3 << 8)
1427#define RT5640_ANC_CS_MASK (0x1 << 7)
1428#define RT5640_ANC_CS_SFT 7
1429#define RT5640_ANC_CS_DIS (0x0 << 7)
1430#define RT5640_ANC_CS_EN (0x1 << 7)
1431#define RT5640_ANC_SW_MASK (0x1 << 6)
1432#define RT5640_ANC_SW_SFT 6
1433#define RT5640_ANC_SW_NOR (0x0 << 6)
1434#define RT5640_ANC_SW_AUTO (0x1 << 6)
1435#define RT5640_ANC_CO_L_MASK (0x3f)
1436#define RT5640_ANC_CO_L_SFT 0
1437
1438/* ANC Control 2 (0xb6) */
1439#define RT5640_ANC_FG_R_MASK (0xf << 12)
1440#define RT5640_ANC_FG_R_SFT 12
1441#define RT5640_ANC_FG_L_MASK (0xf << 8)
1442#define RT5640_ANC_FG_L_SFT 8
1443#define RT5640_ANC_CG_R_MASK (0xf << 4)
1444#define RT5640_ANC_CG_R_SFT 4
1445#define RT5640_ANC_CG_L_MASK (0xf)
1446#define RT5640_ANC_CG_L_SFT 0
1447
1448/* ANC Control 3 (0xb6) */
1449#define RT5640_ANC_CD_MASK (0x1 << 6)
1450#define RT5640_ANC_CD_SFT 6
1451#define RT5640_ANC_CD_BOTH (0x0 << 6)
1452#define RT5640_ANC_CD_IND (0x1 << 6)
1453#define RT5640_ANC_CO_R_MASK (0x3f)
1454#define RT5640_ANC_CO_R_SFT 0
1455
1456/* Jack Detect Control (0xbb) */
1457#define RT5640_JD_MASK (0x7 << 13)
1458#define RT5640_JD_SFT 13
1459#define RT5640_JD_DIS (0x0 << 13)
1460#define RT5640_JD_GPIO1 (0x1 << 13)
1461#define RT5640_JD_JD1_IN4P (0x2 << 13)
1462#define RT5640_JD_JD2_IN4N (0x3 << 13)
1463#define RT5640_JD_GPIO2 (0x4 << 13)
1464#define RT5640_JD_GPIO3 (0x5 << 13)
1465#define RT5640_JD_GPIO4 (0x6 << 13)
1466#define RT5640_JD_HP_MASK (0x1 << 11)
1467#define RT5640_JD_HP_SFT 11
1468#define RT5640_JD_HP_DIS (0x0 << 11)
1469#define RT5640_JD_HP_EN (0x1 << 11)
1470#define RT5640_JD_HP_TRG_MASK (0x1 << 10)
1471#define RT5640_JD_HP_TRG_SFT 10
1472#define RT5640_JD_HP_TRG_LO (0x0 << 10)
1473#define RT5640_JD_HP_TRG_HI (0x1 << 10)
1474#define RT5640_JD_SPL_MASK (0x1 << 9)
1475#define RT5640_JD_SPL_SFT 9
1476#define RT5640_JD_SPL_DIS (0x0 << 9)
1477#define RT5640_JD_SPL_EN (0x1 << 9)
1478#define RT5640_JD_SPL_TRG_MASK (0x1 << 8)
1479#define RT5640_JD_SPL_TRG_SFT 8
1480#define RT5640_JD_SPL_TRG_LO (0x0 << 8)
1481#define RT5640_JD_SPL_TRG_HI (0x1 << 8)
1482#define RT5640_JD_SPR_MASK (0x1 << 7)
1483#define RT5640_JD_SPR_SFT 7
1484#define RT5640_JD_SPR_DIS (0x0 << 7)
1485#define RT5640_JD_SPR_EN (0x1 << 7)
1486#define RT5640_JD_SPR_TRG_MASK (0x1 << 6)
1487#define RT5640_JD_SPR_TRG_SFT 6
1488#define RT5640_JD_SPR_TRG_LO (0x0 << 6)
1489#define RT5640_JD_SPR_TRG_HI (0x1 << 6)
1490#define RT5640_JD_MO_MASK (0x1 << 5)
1491#define RT5640_JD_MO_SFT 5
1492#define RT5640_JD_MO_DIS (0x0 << 5)
1493#define RT5640_JD_MO_EN (0x1 << 5)
1494#define RT5640_JD_MO_TRG_MASK (0x1 << 4)
1495#define RT5640_JD_MO_TRG_SFT 4
1496#define RT5640_JD_MO_TRG_LO (0x0 << 4)
1497#define RT5640_JD_MO_TRG_HI (0x1 << 4)
1498#define RT5640_JD_LO_MASK (0x1 << 3)
1499#define RT5640_JD_LO_SFT 3
1500#define RT5640_JD_LO_DIS (0x0 << 3)
1501#define RT5640_JD_LO_EN (0x1 << 3)
1502#define RT5640_JD_LO_TRG_MASK (0x1 << 2)
1503#define RT5640_JD_LO_TRG_SFT 2
1504#define RT5640_JD_LO_TRG_LO (0x0 << 2)
1505#define RT5640_JD_LO_TRG_HI (0x1 << 2)
1506#define RT5640_JD1_IN4P_MASK (0x1 << 1)
1507#define RT5640_JD1_IN4P_SFT 1
1508#define RT5640_JD1_IN4P_DIS (0x0 << 1)
1509#define RT5640_JD1_IN4P_EN (0x1 << 1)
1510#define RT5640_JD2_IN4N_MASK (0x1)
1511#define RT5640_JD2_IN4N_SFT 0
1512#define RT5640_JD2_IN4N_DIS (0x0)
1513#define RT5640_JD2_IN4N_EN (0x1)
1514
1515/* Jack detect for ANC (0xbc) */
1516#define RT5640_ANC_DET_MASK (0x3 << 4)
1517#define RT5640_ANC_DET_SFT 4
1518#define RT5640_ANC_DET_DIS (0x0 << 4)
1519#define RT5640_ANC_DET_MB1 (0x1 << 4)
1520#define RT5640_ANC_DET_MB2 (0x2 << 4)
1521#define RT5640_ANC_DET_JD (0x3 << 4)
1522#define RT5640_AD_TRG_MASK (0x1 << 3)
1523#define RT5640_AD_TRG_SFT 3
1524#define RT5640_AD_TRG_LO (0x0 << 3)
1525#define RT5640_AD_TRG_HI (0x1 << 3)
1526#define RT5640_ANCM_DET_MASK (0x3 << 4)
1527#define RT5640_ANCM_DET_SFT 4
1528#define RT5640_ANCM_DET_DIS (0x0 << 4)
1529#define RT5640_ANCM_DET_MB1 (0x1 << 4)
1530#define RT5640_ANCM_DET_MB2 (0x2 << 4)
1531#define RT5640_ANCM_DET_JD (0x3 << 4)
1532#define RT5640_AMD_TRG_MASK (0x1 << 3)
1533#define RT5640_AMD_TRG_SFT 3
1534#define RT5640_AMD_TRG_LO (0x0 << 3)
1535#define RT5640_AMD_TRG_HI (0x1 << 3)
1536
1537/* IRQ Control 1 (0xbd) */
1538#define RT5640_IRQ_JD_MASK (0x1 << 15)
1539#define RT5640_IRQ_JD_SFT 15
1540#define RT5640_IRQ_JD_BP (0x0 << 15)
1541#define RT5640_IRQ_JD_NOR (0x1 << 15)
1542#define RT5640_IRQ_OT_MASK (0x1 << 14)
1543#define RT5640_IRQ_OT_SFT 14
1544#define RT5640_IRQ_OT_BP (0x0 << 14)
1545#define RT5640_IRQ_OT_NOR (0x1 << 14)
1546#define RT5640_JD_STKY_MASK (0x1 << 13)
1547#define RT5640_JD_STKY_SFT 13
1548#define RT5640_JD_STKY_DIS (0x0 << 13)
1549#define RT5640_JD_STKY_EN (0x1 << 13)
1550#define RT5640_OT_STKY_MASK (0x1 << 12)
1551#define RT5640_OT_STKY_SFT 12
1552#define RT5640_OT_STKY_DIS (0x0 << 12)
1553#define RT5640_OT_STKY_EN (0x1 << 12)
1554#define RT5640_JD_P_MASK (0x1 << 11)
1555#define RT5640_JD_P_SFT 11
1556#define RT5640_JD_P_NOR (0x0 << 11)
1557#define RT5640_JD_P_INV (0x1 << 11)
1558#define RT5640_OT_P_MASK (0x1 << 10)
1559#define RT5640_OT_P_SFT 10
1560#define RT5640_OT_P_NOR (0x0 << 10)
1561#define RT5640_OT_P_INV (0x1 << 10)
1562
1563/* IRQ Control 2 (0xbe) */
1564#define RT5640_IRQ_MB1_OC_MASK (0x1 << 15)
1565#define RT5640_IRQ_MB1_OC_SFT 15
1566#define RT5640_IRQ_MB1_OC_BP (0x0 << 15)
1567#define RT5640_IRQ_MB1_OC_NOR (0x1 << 15)
1568#define RT5640_IRQ_MB2_OC_MASK (0x1 << 14)
1569#define RT5640_IRQ_MB2_OC_SFT 14
1570#define RT5640_IRQ_MB2_OC_BP (0x0 << 14)
1571#define RT5640_IRQ_MB2_OC_NOR (0x1 << 14)
1572#define RT5640_MB1_OC_STKY_MASK (0x1 << 11)
1573#define RT5640_MB1_OC_STKY_SFT 11
1574#define RT5640_MB1_OC_STKY_DIS (0x0 << 11)
1575#define RT5640_MB1_OC_STKY_EN (0x1 << 11)
1576#define RT5640_MB2_OC_STKY_MASK (0x1 << 10)
1577#define RT5640_MB2_OC_STKY_SFT 10
1578#define RT5640_MB2_OC_STKY_DIS (0x0 << 10)
1579#define RT5640_MB2_OC_STKY_EN (0x1 << 10)
1580#define RT5640_MB1_OC_P_MASK (0x1 << 7)
1581#define RT5640_MB1_OC_P_SFT 7
1582#define RT5640_MB1_OC_P_NOR (0x0 << 7)
1583#define RT5640_MB1_OC_P_INV (0x1 << 7)
1584#define RT5640_MB2_OC_P_MASK (0x1 << 6)
1585#define RT5640_MB2_OC_P_SFT 6
1586#define RT5640_MB2_OC_P_NOR (0x0 << 6)
1587#define RT5640_MB2_OC_P_INV (0x1 << 6)
1588#define RT5640_MB1_OC_CLR (0x1 << 3)
1589#define RT5640_MB1_OC_CLR_SFT 3
1590#define RT5640_MB2_OC_CLR (0x1 << 2)
1591#define RT5640_MB2_OC_CLR_SFT 2
1592
1593/* GPIO Control 1 (0xc0) */
1594#define RT5640_GP1_PIN_MASK (0x1 << 15)
1595#define RT5640_GP1_PIN_SFT 15
1596#define RT5640_GP1_PIN_GPIO1 (0x0 << 15)
1597#define RT5640_GP1_PIN_IRQ (0x1 << 15)
1598#define RT5640_GP2_PIN_MASK (0x1 << 14)
1599#define RT5640_GP2_PIN_SFT 14
1600#define RT5640_GP2_PIN_GPIO2 (0x0 << 14)
1601#define RT5640_GP2_PIN_DMIC1_SCL (0x1 << 14)
1602#define RT5640_GP3_PIN_MASK (0x3 << 12)
1603#define RT5640_GP3_PIN_SFT 12
1604#define RT5640_GP3_PIN_GPIO3 (0x0 << 12)
1605#define RT5640_GP3_PIN_DMIC1_SDA (0x1 << 12)
1606#define RT5640_GP3_PIN_IRQ (0x2 << 12)
1607#define RT5640_GP4_PIN_MASK (0x1 << 11)
1608#define RT5640_GP4_PIN_SFT 11
1609#define RT5640_GP4_PIN_GPIO4 (0x0 << 11)
1610#define RT5640_GP4_PIN_DMIC2_SDA (0x1 << 11)
1611#define RT5640_DP_SIG_MASK (0x1 << 10)
1612#define RT5640_DP_SIG_SFT 10
1613#define RT5640_DP_SIG_TEST (0x0 << 10)
1614#define RT5640_DP_SIG_AP (0x1 << 10)
1615#define RT5640_GPIO_M_MASK (0x1 << 9)
1616#define RT5640_GPIO_M_SFT 9
1617#define RT5640_GPIO_M_FLT (0x0 << 9)
1618#define RT5640_GPIO_M_PH (0x1 << 9)
1619
1620/* GPIO Control 3 (0xc2) */
1621#define RT5640_GP4_PF_MASK (0x1 << 11)
1622#define RT5640_GP4_PF_SFT 11
1623#define RT5640_GP4_PF_IN (0x0 << 11)
1624#define RT5640_GP4_PF_OUT (0x1 << 11)
1625#define RT5640_GP4_OUT_MASK (0x1 << 10)
1626#define RT5640_GP4_OUT_SFT 10
1627#define RT5640_GP4_OUT_LO (0x0 << 10)
1628#define RT5640_GP4_OUT_HI (0x1 << 10)
1629#define RT5640_GP4_P_MASK (0x1 << 9)
1630#define RT5640_GP4_P_SFT 9
1631#define RT5640_GP4_P_NOR (0x0 << 9)
1632#define RT5640_GP4_P_INV (0x1 << 9)
1633#define RT5640_GP3_PF_MASK (0x1 << 8)
1634#define RT5640_GP3_PF_SFT 8
1635#define RT5640_GP3_PF_IN (0x0 << 8)
1636#define RT5640_GP3_PF_OUT (0x1 << 8)
1637#define RT5640_GP3_OUT_MASK (0x1 << 7)
1638#define RT5640_GP3_OUT_SFT 7
1639#define RT5640_GP3_OUT_LO (0x0 << 7)
1640#define RT5640_GP3_OUT_HI (0x1 << 7)
1641#define RT5640_GP3_P_MASK (0x1 << 6)
1642#define RT5640_GP3_P_SFT 6
1643#define RT5640_GP3_P_NOR (0x0 << 6)
1644#define RT5640_GP3_P_INV (0x1 << 6)
1645#define RT5640_GP2_PF_MASK (0x1 << 5)
1646#define RT5640_GP2_PF_SFT 5
1647#define RT5640_GP2_PF_IN (0x0 << 5)
1648#define RT5640_GP2_PF_OUT (0x1 << 5)
1649#define RT5640_GP2_OUT_MASK (0x1 << 4)
1650#define RT5640_GP2_OUT_SFT 4
1651#define RT5640_GP2_OUT_LO (0x0 << 4)
1652#define RT5640_GP2_OUT_HI (0x1 << 4)
1653#define RT5640_GP2_P_MASK (0x1 << 3)
1654#define RT5640_GP2_P_SFT 3
1655#define RT5640_GP2_P_NOR (0x0 << 3)
1656#define RT5640_GP2_P_INV (0x1 << 3)
1657#define RT5640_GP1_PF_MASK (0x1 << 2)
1658#define RT5640_GP1_PF_SFT 2
1659#define RT5640_GP1_PF_IN (0x0 << 2)
1660#define RT5640_GP1_PF_OUT (0x1 << 2)
1661#define RT5640_GP1_OUT_MASK (0x1 << 1)
1662#define RT5640_GP1_OUT_SFT 1
1663#define RT5640_GP1_OUT_LO (0x0 << 1)
1664#define RT5640_GP1_OUT_HI (0x1 << 1)
1665#define RT5640_GP1_P_MASK (0x1)
1666#define RT5640_GP1_P_SFT 0
1667#define RT5640_GP1_P_NOR (0x0)
1668#define RT5640_GP1_P_INV (0x1)
1669
1670/* FM34-500 Register Control 1 (0xc4) */
1671#define RT5640_DSP_ADD_SFT 0
1672
1673/* FM34-500 Register Control 2 (0xc5) */
1674#define RT5640_DSP_DAT_SFT 0
1675
1676/* FM34-500 Register Control 3 (0xc6) */
1677#define RT5640_DSP_BUSY_MASK (0x1 << 15)
1678#define RT5640_DSP_BUSY_BIT 15
1679#define RT5640_DSP_DS_MASK (0x1 << 14)
1680#define RT5640_DSP_DS_SFT 14
1681#define RT5640_DSP_DS_FM3010 (0x1 << 14)
1682#define RT5640_DSP_DS_TEMP (0x1 << 14)
1683#define RT5640_DSP_CLK_MASK (0x3 << 12)
1684#define RT5640_DSP_CLK_SFT 12
1685#define RT5640_DSP_CLK_384K (0x0 << 12)
1686#define RT5640_DSP_CLK_192K (0x1 << 12)
1687#define RT5640_DSP_CLK_96K (0x2 << 12)
1688#define RT5640_DSP_CLK_64K (0x3 << 12)
1689#define RT5640_DSP_PD_PIN_MASK (0x1 << 11)
1690#define RT5640_DSP_PD_PIN_SFT 11
1691#define RT5640_DSP_PD_PIN_LO (0x0 << 11)
1692#define RT5640_DSP_PD_PIN_HI (0x1 << 11)
1693#define RT5640_DSP_RST_PIN_MASK (0x1 << 10)
1694#define RT5640_DSP_RST_PIN_SFT 10
1695#define RT5640_DSP_RST_PIN_LO (0x0 << 10)
1696#define RT5640_DSP_RST_PIN_HI (0x1 << 10)
1697#define RT5640_DSP_R_EN (0x1 << 9)
1698#define RT5640_DSP_R_EN_BIT 9
1699#define RT5640_DSP_W_EN (0x1 << 8)
1700#define RT5640_DSP_W_EN_BIT 8
1701#define RT5640_DSP_CMD_MASK (0xff)
1702#define RT5640_DSP_CMD_SFT 0
1703#define RT5640_DSP_CMD_MW (0x3B) /* Memory Write */
1704#define RT5640_DSP_CMD_MR (0x37) /* Memory Read */
1705#define RT5640_DSP_CMD_RR (0x60) /* Register Read */
1706#define RT5640_DSP_CMD_RW (0x68) /* Register Write */
1707
1708/* Programmable Register Array Control 1 (0xc8) */
1709#define RT5640_REG_SEQ_MASK (0xf << 12)
1710#define RT5640_REG_SEQ_SFT 12
1711#define RT5640_SEQ1_ST_MASK (0x1 << 11) /*RO*/
1712#define RT5640_SEQ1_ST_SFT 11
1713#define RT5640_SEQ1_ST_RUN (0x0 << 11)
1714#define RT5640_SEQ1_ST_FIN (0x1 << 11)
1715#define RT5640_SEQ2_ST_MASK (0x1 << 10) /*RO*/
1716#define RT5640_SEQ2_ST_SFT 10
1717#define RT5640_SEQ2_ST_RUN (0x0 << 10)
1718#define RT5640_SEQ2_ST_FIN (0x1 << 10)
1719#define RT5640_REG_LV_MASK (0x1 << 9)
1720#define RT5640_REG_LV_SFT 9
1721#define RT5640_REG_LV_MX (0x0 << 9)
1722#define RT5640_REG_LV_PR (0x1 << 9)
1723#define RT5640_SEQ_2_PT_MASK (0x1 << 8)
1724#define RT5640_SEQ_2_PT_BIT 8
1725#define RT5640_REG_IDX_MASK (0xff)
1726#define RT5640_REG_IDX_SFT 0
1727
1728/* Programmable Register Array Control 2 (0xc9) */
1729#define RT5640_REG_DAT_MASK (0xffff)
1730#define RT5640_REG_DAT_SFT 0
1731
1732/* Programmable Register Array Control 3 (0xca) */
1733#define RT5640_SEQ_DLY_MASK (0xff << 8)
1734#define RT5640_SEQ_DLY_SFT 8
1735#define RT5640_PROG_MASK (0x1 << 7)
1736#define RT5640_PROG_SFT 7
1737#define RT5640_PROG_DIS (0x0 << 7)
1738#define RT5640_PROG_EN (0x1 << 7)
1739#define RT5640_SEQ1_PT_RUN (0x1 << 6)
1740#define RT5640_SEQ1_PT_RUN_BIT 6
1741#define RT5640_SEQ2_PT_RUN (0x1 << 5)
1742#define RT5640_SEQ2_PT_RUN_BIT 5
1743
1744/* Programmable Register Array Control 4 (0xcb) */
1745#define RT5640_SEQ1_START_MASK (0xf << 8)
1746#define RT5640_SEQ1_START_SFT 8
1747#define RT5640_SEQ1_END_MASK (0xf)
1748#define RT5640_SEQ1_END_SFT 0
1749
1750/* Programmable Register Array Control 5 (0xcc) */
1751#define RT5640_SEQ2_START_MASK (0xf << 8)
1752#define RT5640_SEQ2_START_SFT 8
1753#define RT5640_SEQ2_END_MASK (0xf)
1754#define RT5640_SEQ2_END_SFT 0
1755
1756/* Scramble Function (0xcd) */
1757#define RT5640_SCB_KEY_MASK (0xff)
1758#define RT5640_SCB_KEY_SFT 0
1759
1760/* Scramble Control (0xce) */
1761#define RT5640_SCB_SWAP_MASK (0x1 << 15)
1762#define RT5640_SCB_SWAP_SFT 15
1763#define RT5640_SCB_SWAP_DIS (0x0 << 15)
1764#define RT5640_SCB_SWAP_EN (0x1 << 15)
1765#define RT5640_SCB_MASK (0x1 << 14)
1766#define RT5640_SCB_SFT 14
1767#define RT5640_SCB_DIS (0x0 << 14)
1768#define RT5640_SCB_EN (0x1 << 14)
1769
1770/* Baseback Control (0xcf) */
1771#define RT5640_BB_MASK (0x1 << 15)
1772#define RT5640_BB_SFT 15
1773#define RT5640_BB_DIS (0x0 << 15)
1774#define RT5640_BB_EN (0x1 << 15)
1775#define RT5640_BB_CT_MASK (0x7 << 12)
1776#define RT5640_BB_CT_SFT 12
1777#define RT5640_BB_CT_A (0x0 << 12)
1778#define RT5640_BB_CT_B (0x1 << 12)
1779#define RT5640_BB_CT_C (0x2 << 12)
1780#define RT5640_BB_CT_D (0x3 << 12)
1781#define RT5640_M_BB_L_MASK (0x1 << 9)
1782#define RT5640_M_BB_L_SFT 9
1783#define RT5640_M_BB_R_MASK (0x1 << 8)
1784#define RT5640_M_BB_R_SFT 8
1785#define RT5640_M_BB_HPF_L_MASK (0x1 << 7)
1786#define RT5640_M_BB_HPF_L_SFT 7
1787#define RT5640_M_BB_HPF_R_MASK (0x1 << 6)
1788#define RT5640_M_BB_HPF_R_SFT 6
1789#define RT5640_G_BB_BST_MASK (0x3f)
1790#define RT5640_G_BB_BST_SFT 0
1791
1792/* MP3 Plus Control 1 (0xd0) */
1793#define RT5640_M_MP3_L_MASK (0x1 << 15)
1794#define RT5640_M_MP3_L_SFT 15
1795#define RT5640_M_MP3_R_MASK (0x1 << 14)
1796#define RT5640_M_MP3_R_SFT 14
1797#define RT5640_M_MP3_MASK (0x1 << 13)
1798#define RT5640_M_MP3_SFT 13
1799#define RT5640_M_MP3_DIS (0x0 << 13)
1800#define RT5640_M_MP3_EN (0x1 << 13)
1801#define RT5640_EG_MP3_MASK (0x1f << 8)
1802#define RT5640_EG_MP3_SFT 8
1803#define RT5640_MP3_HLP_MASK (0x1 << 7)
1804#define RT5640_MP3_HLP_SFT 7
1805#define RT5640_MP3_HLP_DIS (0x0 << 7)
1806#define RT5640_MP3_HLP_EN (0x1 << 7)
1807#define RT5640_M_MP3_ORG_L_MASK (0x1 << 6)
1808#define RT5640_M_MP3_ORG_L_SFT 6
1809#define RT5640_M_MP3_ORG_R_MASK (0x1 << 5)
1810#define RT5640_M_MP3_ORG_R_SFT 5
1811
1812/* MP3 Plus Control 2 (0xd1) */
1813#define RT5640_MP3_WT_MASK (0x1 << 13)
1814#define RT5640_MP3_WT_SFT 13
1815#define RT5640_MP3_WT_1_4 (0x0 << 13)
1816#define RT5640_MP3_WT_1_2 (0x1 << 13)
1817#define RT5640_OG_MP3_MASK (0x1f << 8)
1818#define RT5640_OG_MP3_SFT 8
1819#define RT5640_HG_MP3_MASK (0x3f)
1820#define RT5640_HG_MP3_SFT 0
1821
1822/* 3D HP Control 1 (0xd2) */
1823#define RT5640_3D_CF_MASK (0x1 << 15)
1824#define RT5640_3D_CF_SFT 15
1825#define RT5640_3D_CF_DIS (0x0 << 15)
1826#define RT5640_3D_CF_EN (0x1 << 15)
1827#define RT5640_3D_HP_MASK (0x1 << 14)
1828#define RT5640_3D_HP_SFT 14
1829#define RT5640_3D_HP_DIS (0x0 << 14)
1830#define RT5640_3D_HP_EN (0x1 << 14)
1831#define RT5640_3D_BT_MASK (0x1 << 13)
1832#define RT5640_3D_BT_SFT 13
1833#define RT5640_3D_BT_DIS (0x0 << 13)
1834#define RT5640_3D_BT_EN (0x1 << 13)
1835#define RT5640_3D_1F_MIX_MASK (0x3 << 11)
1836#define RT5640_3D_1F_MIX_SFT 11
1837#define RT5640_3D_HP_M_MASK (0x1 << 10)
1838#define RT5640_3D_HP_M_SFT 10
1839#define RT5640_3D_HP_M_SUR (0x0 << 10)
1840#define RT5640_3D_HP_M_FRO (0x1 << 10)
1841#define RT5640_M_3D_HRTF_MASK (0x1 << 9)
1842#define RT5640_M_3D_HRTF_SFT 9
1843#define RT5640_M_3D_D2H_MASK (0x1 << 8)
1844#define RT5640_M_3D_D2H_SFT 8
1845#define RT5640_M_3D_D2R_MASK (0x1 << 7)
1846#define RT5640_M_3D_D2R_SFT 7
1847#define RT5640_M_3D_REVB_MASK (0x1 << 6)
1848#define RT5640_M_3D_REVB_SFT 6
1849
1850/* Adjustable high pass filter control 1 (0xd3) */
1851#define RT5640_2ND_HPF_MASK (0x1 << 15)
1852#define RT5640_2ND_HPF_SFT 15
1853#define RT5640_2ND_HPF_DIS (0x0 << 15)
1854#define RT5640_2ND_HPF_EN (0x1 << 15)
1855#define RT5640_HPF_CF_L_MASK (0x7 << 12)
1856#define RT5640_HPF_CF_L_SFT 12
1857#define RT5640_1ST_HPF_MASK (0x1 << 11)
1858#define RT5640_1ST_HPF_SFT 11
1859#define RT5640_1ST_HPF_DIS (0x0 << 11)
1860#define RT5640_1ST_HPF_EN (0x1 << 11)
1861#define RT5640_HPF_CF_R_MASK (0x7 << 8)
1862#define RT5640_HPF_CF_R_SFT 8
1863#define RT5640_ZD_T_MASK (0x3 << 6)
1864#define RT5640_ZD_T_SFT 6
1865#define RT5640_ZD_F_MASK (0x3 << 4)
1866#define RT5640_ZD_F_SFT 4
1867#define RT5640_ZD_F_IM (0x0 << 4)
1868#define RT5640_ZD_F_ZC_IM (0x1 << 4)
1869#define RT5640_ZD_F_ZC_IOD (0x2 << 4)
1870#define RT5640_ZD_F_UN (0x3 << 4)
1871
1872/* HP calibration control and Amp detection (0xd6) */
1873#define RT5640_SI_DAC_MASK (0x1 << 11)
1874#define RT5640_SI_DAC_SFT 11
1875#define RT5640_SI_DAC_AUTO (0x0 << 11)
1876#define RT5640_SI_DAC_TEST (0x1 << 11)
1877#define RT5640_DC_CAL_M_MASK (0x1 << 10)
1878#define RT5640_DC_CAL_M_SFT 10
1879#define RT5640_DC_CAL_M_CAL (0x0 << 10)
1880#define RT5640_DC_CAL_M_NOR (0x1 << 10)
1881#define RT5640_DC_CAL_MASK (0x1 << 9)
1882#define RT5640_DC_CAL_SFT 9
1883#define RT5640_DC_CAL_DIS (0x0 << 9)
1884#define RT5640_DC_CAL_EN (0x1 << 9)
1885#define RT5640_HPD_RCV_MASK (0x7 << 6)
1886#define RT5640_HPD_RCV_SFT 6
1887#define RT5640_HPD_PS_MASK (0x1 << 5)
1888#define RT5640_HPD_PS_SFT 5
1889#define RT5640_HPD_PS_DIS (0x0 << 5)
1890#define RT5640_HPD_PS_EN (0x1 << 5)
1891#define RT5640_CAL_M_MASK (0x1 << 4)
1892#define RT5640_CAL_M_SFT 4
1893#define RT5640_CAL_M_DEP (0x0 << 4)
1894#define RT5640_CAL_M_CAL (0x1 << 4)
1895#define RT5640_CAL_MASK (0x1 << 3)
1896#define RT5640_CAL_SFT 3
1897#define RT5640_CAL_DIS (0x0 << 3)
1898#define RT5640_CAL_EN (0x1 << 3)
1899#define RT5640_CAL_TEST_MASK (0x1 << 2)
1900#define RT5640_CAL_TEST_SFT 2
1901#define RT5640_CAL_TEST_DIS (0x0 << 2)
1902#define RT5640_CAL_TEST_EN (0x1 << 2)
1903#define RT5640_CAL_P_MASK (0x3)
1904#define RT5640_CAL_P_SFT 0
1905#define RT5640_CAL_P_NONE (0x0)
1906#define RT5640_CAL_P_CAL (0x1)
1907#define RT5640_CAL_P_DAC_CAL (0x2)
1908
1909/* Soft volume and zero cross control 1 (0xd9) */
1910#define RT5640_SV_MASK (0x1 << 15)
1911#define RT5640_SV_SFT 15
1912#define RT5640_SV_DIS (0x0 << 15)
1913#define RT5640_SV_EN (0x1 << 15)
1914#define RT5640_SPO_SV_MASK (0x1 << 14)
1915#define RT5640_SPO_SV_SFT 14
1916#define RT5640_SPO_SV_DIS (0x0 << 14)
1917#define RT5640_SPO_SV_EN (0x1 << 14)
1918#define RT5640_OUT_SV_MASK (0x1 << 13)
1919#define RT5640_OUT_SV_SFT 13
1920#define RT5640_OUT_SV_DIS (0x0 << 13)
1921#define RT5640_OUT_SV_EN (0x1 << 13)
1922#define RT5640_HP_SV_MASK (0x1 << 12)
1923#define RT5640_HP_SV_SFT 12
1924#define RT5640_HP_SV_DIS (0x0 << 12)
1925#define RT5640_HP_SV_EN (0x1 << 12)
1926#define RT5640_ZCD_DIG_MASK (0x1 << 11)
1927#define RT5640_ZCD_DIG_SFT 11
1928#define RT5640_ZCD_DIG_DIS (0x0 << 11)
1929#define RT5640_ZCD_DIG_EN (0x1 << 11)
1930#define RT5640_ZCD_MASK (0x1 << 10)
1931#define RT5640_ZCD_SFT 10
1932#define RT5640_ZCD_PD (0x0 << 10)
1933#define RT5640_ZCD_PU (0x1 << 10)
1934#define RT5640_M_ZCD_MASK (0x3f << 4)
1935#define RT5640_M_ZCD_SFT 4
1936#define RT5640_M_ZCD_RM_L (0x1 << 9)
1937#define RT5640_M_ZCD_RM_R (0x1 << 8)
1938#define RT5640_M_ZCD_SM_L (0x1 << 7)
1939#define RT5640_M_ZCD_SM_R (0x1 << 6)
1940#define RT5640_M_ZCD_OM_L (0x1 << 5)
1941#define RT5640_M_ZCD_OM_R (0x1 << 4)
1942#define RT5640_SV_DLY_MASK (0xf)
1943#define RT5640_SV_DLY_SFT 0
1944
1945/* Soft volume and zero cross control 2 (0xda) */
1946#define RT5640_ZCD_HP_MASK (0x1 << 15)
1947#define RT5640_ZCD_HP_SFT 15
1948#define RT5640_ZCD_HP_DIS (0x0 << 15)
1949#define RT5640_ZCD_HP_EN (0x1 << 15)
1950
1951
1952/* Codec Private Register definition */
1953/* 3D Speaker Control (0x63) */
1954#define RT5640_3D_SPK_MASK (0x1 << 15)
1955#define RT5640_3D_SPK_SFT 15
1956#define RT5640_3D_SPK_DIS (0x0 << 15)
1957#define RT5640_3D_SPK_EN (0x1 << 15)
1958#define RT5640_3D_SPK_M_MASK (0x3 << 13)
1959#define RT5640_3D_SPK_M_SFT 13
1960#define RT5640_3D_SPK_CG_MASK (0x1f << 8)
1961#define RT5640_3D_SPK_CG_SFT 8
1962#define RT5640_3D_SPK_SG_MASK (0x1f)
1963#define RT5640_3D_SPK_SG_SFT 0
1964
1965/* Wind Noise Detection Control 1 (0x6c) */
1966#define RT5640_WND_MASK (0x1 << 15)
1967#define RT5640_WND_SFT 15
1968#define RT5640_WND_DIS (0x0 << 15)
1969#define RT5640_WND_EN (0x1 << 15)
1970
1971/* Wind Noise Detection Control 2 (0x6d) */
1972#define RT5640_WND_FC_NW_MASK (0x3f << 10)
1973#define RT5640_WND_FC_NW_SFT 10
1974#define RT5640_WND_FC_WK_MASK (0x3f << 4)
1975#define RT5640_WND_FC_WK_SFT 4
1976
1977/* Wind Noise Detection Control 3 (0x6e) */
1978#define RT5640_HPF_FC_MASK (0x3f << 6)
1979#define RT5640_HPF_FC_SFT 6
1980#define RT5640_WND_FC_ST_MASK (0x3f)
1981#define RT5640_WND_FC_ST_SFT 0
1982
1983/* Wind Noise Detection Control 4 (0x6f) */
1984#define RT5640_WND_TH_LO_MASK (0x3ff)
1985#define RT5640_WND_TH_LO_SFT 0
1986
1987/* Wind Noise Detection Control 5 (0x70) */
1988#define RT5640_WND_TH_HI_MASK (0x3ff)
1989#define RT5640_WND_TH_HI_SFT 0
1990
1991/* Wind Noise Detection Control 8 (0x73) */
1992#define RT5640_WND_WIND_MASK (0x1 << 13) /* Read-Only */
1993#define RT5640_WND_WIND_SFT 13
1994#define RT5640_WND_STRONG_MASK (0x1 << 12) /* Read-Only */
1995#define RT5640_WND_STRONG_SFT 12
1996enum {
1997 RT5640_NO_WIND,
1998 RT5640_BREEZE,
1999 RT5640_STORM,
2000};
2001
2002/* Dipole Speaker Interface (0x75) */
2003#define RT5640_DP_ATT_MASK (0x3 << 14)
2004#define RT5640_DP_ATT_SFT 14
2005#define RT5640_DP_SPK_MASK (0x1 << 10)
2006#define RT5640_DP_SPK_SFT 10
2007#define RT5640_DP_SPK_DIS (0x0 << 10)
2008#define RT5640_DP_SPK_EN (0x1 << 10)
2009
2010/* EQ Pre Volume Control (0xb3) */
2011#define RT5640_EQ_PRE_VOL_MASK (0xffff)
2012#define RT5640_EQ_PRE_VOL_SFT 0
2013
2014/* EQ Post Volume Control (0xb4) */
2015#define RT5640_EQ_PST_VOL_MASK (0xffff)
2016#define RT5640_EQ_PST_VOL_SFT 0
2017
2018#define RT5640_NO_JACK BIT(0)
2019#define RT5640_HEADSET_DET BIT(1)
2020#define RT5640_HEADPHO_DET BIT(2)
2021
2022/* System Clock Source */
2023#define RT5640_SCLK_S_MCLK 0
2024#define RT5640_SCLK_S_PLL1 1
2025#define RT5640_SCLK_S_PLL1_TK 2
2026#define RT5640_SCLK_S_RCCLK 3
2027
2028/* PLL1 Source */
2029#define RT5640_PLL1_S_MCLK 0
2030#define RT5640_PLL1_S_BCLK1 1
2031#define RT5640_PLL1_S_BCLK2 2
2032#define RT5640_PLL1_S_BCLK3 3
2033
2034
2035enum {
2036 RT5640_AIF1,
2037 RT5640_AIF2,
2038 RT5640_AIF3,
2039 RT5640_AIFS,
2040};
2041
2042enum {
2043 RT5640_U_IF1 = 0x1,
2044 RT5640_U_IF2 = 0x2,
2045 RT5640_U_IF3 = 0x4,
2046};
2047
2048enum {
2049 RT5640_IF_123,
2050 RT5640_IF_132,
2051 RT5640_IF_312,
2052 RT5640_IF_321,
2053 RT5640_IF_231,
2054 RT5640_IF_213,
2055 RT5640_IF_113,
2056 RT5640_IF_223,
2057 RT5640_IF_ALL,
2058};
2059
2060enum {
2061 RT5640_DMIC_DIS,
2062 RT5640_DMIC1,
2063 RT5640_DMIC2,
2064};
2065
2066struct rt5640_pll_code {
2067 bool m_bp; /* Indicates bypass m code or not. */
2068 int m_code;
2069 int n_code;
2070 int k_code;
2071};
2072
2073struct rt5640_priv {
2074 struct snd_soc_codec *codec;
2075 struct rt5640_platform_data pdata;
2076 struct regmap *regmap;
2077
2078 int sysclk;
2079 int sysclk_src;
2080 int lrck[RT5640_AIFS];
2081 int bclk[RT5640_AIFS];
2082 int master[RT5640_AIFS];
2083
2084 struct rt5640_pll_code pll_code;
2085 int pll_src;
2086 int pll_in;
2087 int pll_out;
2088
2089 int dmic_en;
2090};
2091
2092#endif
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 92bbfec9b107..d441559dc92c 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -16,6 +16,7 @@
16#include <linux/pm.h> 16#include <linux/pm.h>
17#include <linux/i2c.h> 17#include <linux/i2c.h>
18#include <linux/clk.h> 18#include <linux/clk.h>
19#include <linux/regmap.h>
19#include <linux/regulator/driver.h> 20#include <linux/regulator/driver.h>
20#include <linux/regulator/machine.h> 21#include <linux/regulator/machine.h>
21#include <linux/regulator/consumer.h> 22#include <linux/regulator/consumer.h>
@@ -34,30 +35,30 @@
34#define SGTL5000_MAX_REG_OFFSET 0x013A 35#define SGTL5000_MAX_REG_OFFSET 0x013A
35 36
36/* default value of sgtl5000 registers */ 37/* default value of sgtl5000 registers */
37static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET] = { 38static const struct reg_default sgtl5000_reg_defaults[] = {
38 [SGTL5000_CHIP_CLK_CTRL] = 0x0008, 39 { SGTL5000_CHIP_CLK_CTRL, 0x0008 },
39 [SGTL5000_CHIP_I2S_CTRL] = 0x0010, 40 { SGTL5000_CHIP_I2S_CTRL, 0x0010 },
40 [SGTL5000_CHIP_SSS_CTRL] = 0x0008, 41 { SGTL5000_CHIP_SSS_CTRL, 0x0008 },
41 [SGTL5000_CHIP_DAC_VOL] = 0x3c3c, 42 { SGTL5000_CHIP_DAC_VOL, 0x3c3c },
42 [SGTL5000_CHIP_PAD_STRENGTH] = 0x015f, 43 { SGTL5000_CHIP_PAD_STRENGTH, 0x015f },
43 [SGTL5000_CHIP_ANA_HP_CTRL] = 0x1818, 44 { SGTL5000_CHIP_ANA_HP_CTRL, 0x1818 },
44 [SGTL5000_CHIP_ANA_CTRL] = 0x0111, 45 { SGTL5000_CHIP_ANA_CTRL, 0x0111 },
45 [SGTL5000_CHIP_LINE_OUT_VOL] = 0x0404, 46 { SGTL5000_CHIP_LINE_OUT_VOL, 0x0404 },
46 [SGTL5000_CHIP_ANA_POWER] = 0x7060, 47 { SGTL5000_CHIP_ANA_POWER, 0x7060 },
47 [SGTL5000_CHIP_PLL_CTRL] = 0x5000, 48 { SGTL5000_CHIP_PLL_CTRL, 0x5000 },
48 [SGTL5000_DAP_BASS_ENHANCE] = 0x0040, 49 { SGTL5000_DAP_BASS_ENHANCE, 0x0040 },
49 [SGTL5000_DAP_BASS_ENHANCE_CTRL] = 0x051f, 50 { SGTL5000_DAP_BASS_ENHANCE_CTRL, 0x051f },
50 [SGTL5000_DAP_SURROUND] = 0x0040, 51 { SGTL5000_DAP_SURROUND, 0x0040 },
51 [SGTL5000_DAP_EQ_BASS_BAND0] = 0x002f, 52 { SGTL5000_DAP_EQ_BASS_BAND0, 0x002f },
52 [SGTL5000_DAP_EQ_BASS_BAND1] = 0x002f, 53 { SGTL5000_DAP_EQ_BASS_BAND1, 0x002f },
53 [SGTL5000_DAP_EQ_BASS_BAND2] = 0x002f, 54 { SGTL5000_DAP_EQ_BASS_BAND2, 0x002f },
54 [SGTL5000_DAP_EQ_BASS_BAND3] = 0x002f, 55 { SGTL5000_DAP_EQ_BASS_BAND3, 0x002f },
55 [SGTL5000_DAP_EQ_BASS_BAND4] = 0x002f, 56 { SGTL5000_DAP_EQ_BASS_BAND4, 0x002f },
56 [SGTL5000_DAP_MAIN_CHAN] = 0x8000, 57 { SGTL5000_DAP_MAIN_CHAN, 0x8000 },
57 [SGTL5000_DAP_AVC_CTRL] = 0x0510, 58 { SGTL5000_DAP_AVC_CTRL, 0x0510 },
58 [SGTL5000_DAP_AVC_THRESHOLD] = 0x1473, 59 { SGTL5000_DAP_AVC_THRESHOLD, 0x1473 },
59 [SGTL5000_DAP_AVC_ATTACK] = 0x0028, 60 { SGTL5000_DAP_AVC_ATTACK, 0x0028 },
60 [SGTL5000_DAP_AVC_DECAY] = 0x0050, 61 { SGTL5000_DAP_AVC_DECAY, 0x0050 },
61}; 62};
62 63
63/* regulator supplies for sgtl5000, VDDD is an optional external supply */ 64/* regulator supplies for sgtl5000, VDDD is an optional external supply */
@@ -112,6 +113,8 @@ struct sgtl5000_priv {
112 int fmt; /* i2s data format */ 113 int fmt; /* i2s data format */
113 struct regulator_bulk_data supplies[SGTL5000_SUPPLY_NUM]; 114 struct regulator_bulk_data supplies[SGTL5000_SUPPLY_NUM];
114 struct ldo_regulator *ldo; 115 struct ldo_regulator *ldo;
116 struct regmap *regmap;
117 struct clk *mclk;
115}; 118};
116 119
117/* 120/*
@@ -151,12 +154,12 @@ static int power_vag_event(struct snd_soc_dapm_widget *w,
151 struct snd_kcontrol *kcontrol, int event) 154 struct snd_kcontrol *kcontrol, int event)
152{ 155{
153 switch (event) { 156 switch (event) {
154 case SND_SOC_DAPM_PRE_PMU: 157 case SND_SOC_DAPM_POST_PMU:
155 snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, 158 snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
156 SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); 159 SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP);
157 break; 160 break;
158 161
159 case SND_SOC_DAPM_POST_PMD: 162 case SND_SOC_DAPM_PRE_PMD:
160 snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, 163 snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
161 SGTL5000_VAG_POWERUP, 0); 164 SGTL5000_VAG_POWERUP, 0);
162 msleep(400); 165 msleep(400);
@@ -217,12 +220,11 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
217 0, SGTL5000_CHIP_DIG_POWER, 220 0, SGTL5000_CHIP_DIG_POWER,
218 1, 0), 221 1, 0),
219 222
220 SND_SOC_DAPM_SUPPLY("VAG_POWER", SGTL5000_CHIP_ANA_POWER, 7, 0,
221 power_vag_event,
222 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
223
224 SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), 223 SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0),
225 SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0), 224 SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0),
225
226 SND_SOC_DAPM_PRE("VAG_POWER_PRE", power_vag_event),
227 SND_SOC_DAPM_POST("VAG_POWER_POST", power_vag_event),
226}; 228};
227 229
228/* routes for sgtl5000 */ 230/* routes for sgtl5000 */
@@ -230,16 +232,13 @@ static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = {
230 {"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */ 232 {"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */
231 {"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */ 233 {"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */
232 234
233 {"ADC", NULL, "VAG_POWER"},
234 {"ADC", NULL, "Capture Mux"}, /* adc_mux --> adc */ 235 {"ADC", NULL, "Capture Mux"}, /* adc_mux --> adc */
235 {"AIFOUT", NULL, "ADC"}, /* adc --> i2s_out */ 236 {"AIFOUT", NULL, "ADC"}, /* adc --> i2s_out */
236 237
237 {"DAC", NULL, "VAG_POWER"},
238 {"DAC", NULL, "AIFIN"}, /* i2s-->dac,skip audio mux */ 238 {"DAC", NULL, "AIFIN"}, /* i2s-->dac,skip audio mux */
239 {"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */ 239 {"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */
240 {"LO", NULL, "DAC"}, /* dac --> line_out */ 240 {"LO", NULL, "DAC"}, /* dac --> line_out */
241 241
242 {"LINE_IN", NULL, "VAG_POWER"},
243 {"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */ 242 {"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */
244 {"HP", NULL, "Headphone Mux"}, /* hp_mux --> hp */ 243 {"HP", NULL, "Headphone Mux"}, /* hp_mux --> hp */
245 244
@@ -909,10 +908,25 @@ static int sgtl5000_set_bias_level(struct snd_soc_codec *codec,
909 if (ret) 908 if (ret)
910 return ret; 909 return ret;
911 udelay(10); 910 udelay(10);
911
912 regcache_cache_only(sgtl5000->regmap, false);
913
914 ret = regcache_sync(sgtl5000->regmap);
915 if (ret != 0) {
916 dev_err(codec->dev,
917 "Failed to restore cache: %d\n", ret);
918
919 regcache_cache_only(sgtl5000->regmap, true);
920 regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
921 sgtl5000->supplies);
922
923 return ret;
924 }
912 } 925 }
913 926
914 break; 927 break;
915 case SND_SOC_BIAS_OFF: 928 case SND_SOC_BIAS_OFF:
929 regcache_cache_only(sgtl5000->regmap, true);
916 regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), 930 regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
917 sgtl5000->supplies); 931 sgtl5000->supplies);
918 break; 932 break;
@@ -958,17 +972,76 @@ static struct snd_soc_dai_driver sgtl5000_dai = {
958 .symmetric_rates = 1, 972 .symmetric_rates = 1,
959}; 973};
960 974
961static int sgtl5000_volatile_register(struct snd_soc_codec *codec, 975static bool sgtl5000_volatile(struct device *dev, unsigned int reg)
962 unsigned int reg)
963{ 976{
964 switch (reg) { 977 switch (reg) {
965 case SGTL5000_CHIP_ID: 978 case SGTL5000_CHIP_ID:
966 case SGTL5000_CHIP_ADCDAC_CTRL: 979 case SGTL5000_CHIP_ADCDAC_CTRL:
967 case SGTL5000_CHIP_ANA_STATUS: 980 case SGTL5000_CHIP_ANA_STATUS:
968 return 1; 981 return true;
969 } 982 }
970 983
971 return 0; 984 return false;
985}
986
987static bool sgtl5000_readable(struct device *dev, unsigned int reg)
988{
989 switch (reg) {
990 case SGTL5000_CHIP_ID:
991 case SGTL5000_CHIP_DIG_POWER:
992 case SGTL5000_CHIP_CLK_CTRL:
993 case SGTL5000_CHIP_I2S_CTRL:
994 case SGTL5000_CHIP_SSS_CTRL:
995 case SGTL5000_CHIP_ADCDAC_CTRL:
996 case SGTL5000_CHIP_DAC_VOL:
997 case SGTL5000_CHIP_PAD_STRENGTH:
998 case SGTL5000_CHIP_ANA_ADC_CTRL:
999 case SGTL5000_CHIP_ANA_HP_CTRL:
1000 case SGTL5000_CHIP_ANA_CTRL:
1001 case SGTL5000_CHIP_LINREG_CTRL:
1002 case SGTL5000_CHIP_REF_CTRL:
1003 case SGTL5000_CHIP_MIC_CTRL:
1004 case SGTL5000_CHIP_LINE_OUT_CTRL:
1005 case SGTL5000_CHIP_LINE_OUT_VOL:
1006 case SGTL5000_CHIP_ANA_POWER:
1007 case SGTL5000_CHIP_PLL_CTRL:
1008 case SGTL5000_CHIP_CLK_TOP_CTRL:
1009 case SGTL5000_CHIP_ANA_STATUS:
1010 case SGTL5000_CHIP_SHORT_CTRL:
1011 case SGTL5000_CHIP_ANA_TEST2:
1012 case SGTL5000_DAP_CTRL:
1013 case SGTL5000_DAP_PEQ:
1014 case SGTL5000_DAP_BASS_ENHANCE:
1015 case SGTL5000_DAP_BASS_ENHANCE_CTRL:
1016 case SGTL5000_DAP_AUDIO_EQ:
1017 case SGTL5000_DAP_SURROUND:
1018 case SGTL5000_DAP_FLT_COEF_ACCESS:
1019 case SGTL5000_DAP_COEF_WR_B0_MSB:
1020 case SGTL5000_DAP_COEF_WR_B0_LSB:
1021 case SGTL5000_DAP_EQ_BASS_BAND0:
1022 case SGTL5000_DAP_EQ_BASS_BAND1:
1023 case SGTL5000_DAP_EQ_BASS_BAND2:
1024 case SGTL5000_DAP_EQ_BASS_BAND3:
1025 case SGTL5000_DAP_EQ_BASS_BAND4:
1026 case SGTL5000_DAP_MAIN_CHAN:
1027 case SGTL5000_DAP_MIX_CHAN:
1028 case SGTL5000_DAP_AVC_CTRL:
1029 case SGTL5000_DAP_AVC_THRESHOLD:
1030 case SGTL5000_DAP_AVC_ATTACK:
1031 case SGTL5000_DAP_AVC_DECAY:
1032 case SGTL5000_DAP_COEF_WR_B1_MSB:
1033 case SGTL5000_DAP_COEF_WR_B1_LSB:
1034 case SGTL5000_DAP_COEF_WR_B2_MSB:
1035 case SGTL5000_DAP_COEF_WR_B2_LSB:
1036 case SGTL5000_DAP_COEF_WR_A1_MSB:
1037 case SGTL5000_DAP_COEF_WR_A1_LSB:
1038 case SGTL5000_DAP_COEF_WR_A2_MSB:
1039 case SGTL5000_DAP_COEF_WR_A2_LSB:
1040 return true;
1041
1042 default:
1043 return false;
1044 }
972} 1045}
973 1046
974#ifdef CONFIG_SUSPEND 1047#ifdef CONFIG_SUSPEND
@@ -1214,7 +1287,7 @@ static int sgtl5000_replace_vddd_with_ldo(struct snd_soc_codec *codec)
1214 1287
1215static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) 1288static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
1216{ 1289{
1217 u16 reg; 1290 int reg;
1218 int ret; 1291 int ret;
1219 int rev; 1292 int rev;
1220 int i; 1293 int i;
@@ -1242,23 +1315,17 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
1242 /* wait for all power rails bring up */ 1315 /* wait for all power rails bring up */
1243 udelay(10); 1316 udelay(10);
1244 1317
1245 /* read chip information */
1246 reg = snd_soc_read(codec, SGTL5000_CHIP_ID);
1247 if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) !=
1248 SGTL5000_PARTID_PART_ID) {
1249 dev_err(codec->dev,
1250 "Device with ID register %x is not a sgtl5000\n", reg);
1251 ret = -ENODEV;
1252 goto err_regulator_disable;
1253 }
1254
1255 rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
1256 dev_info(codec->dev, "sgtl5000 revision 0x%x\n", rev);
1257
1258 /* 1318 /*
1259 * workaround for revision 0x11 and later, 1319 * workaround for revision 0x11 and later,
1260 * roll back to use internal LDO 1320 * roll back to use internal LDO
1261 */ 1321 */
1322
1323 ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, &reg);
1324 if (ret)
1325 goto err_regulator_disable;
1326
1327 rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
1328
1262 if (external_vddd && rev >= 0x11) { 1329 if (external_vddd && rev >= 0x11) {
1263 /* disable all regulator first */ 1330 /* disable all regulator first */
1264 regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), 1331 regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
@@ -1300,7 +1367,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
1300 struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); 1367 struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
1301 1368
1302 /* setup i2c data ops */ 1369 /* setup i2c data ops */
1303 ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C); 1370 codec->control_data = sgtl5000->regmap;
1371 ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
1304 if (ret < 0) { 1372 if (ret < 0) {
1305 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 1373 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1306 return ret; 1374 return ret;
@@ -1391,11 +1459,6 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
1391 .suspend = sgtl5000_suspend, 1459 .suspend = sgtl5000_suspend,
1392 .resume = sgtl5000_resume, 1460 .resume = sgtl5000_resume,
1393 .set_bias_level = sgtl5000_set_bias_level, 1461 .set_bias_level = sgtl5000_set_bias_level,
1394 .reg_cache_size = ARRAY_SIZE(sgtl5000_regs),
1395 .reg_word_size = sizeof(u16),
1396 .reg_cache_step = 2,
1397 .reg_cache_default = sgtl5000_regs,
1398 .volatile_register = sgtl5000_volatile_register,
1399 .controls = sgtl5000_snd_controls, 1462 .controls = sgtl5000_snd_controls,
1400 .num_controls = ARRAY_SIZE(sgtl5000_snd_controls), 1463 .num_controls = ARRAY_SIZE(sgtl5000_snd_controls),
1401 .dapm_widgets = sgtl5000_dapm_widgets, 1464 .dapm_widgets = sgtl5000_dapm_widgets,
@@ -1404,28 +1467,114 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
1404 .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes), 1467 .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes),
1405}; 1468};
1406 1469
1470static const struct regmap_config sgtl5000_regmap = {
1471 .reg_bits = 16,
1472 .val_bits = 16,
1473
1474 .max_register = SGTL5000_MAX_REG_OFFSET,
1475 .volatile_reg = sgtl5000_volatile,
1476 .readable_reg = sgtl5000_readable,
1477
1478 .cache_type = REGCACHE_RBTREE,
1479 .reg_defaults = sgtl5000_reg_defaults,
1480 .num_reg_defaults = ARRAY_SIZE(sgtl5000_reg_defaults),
1481};
1482
1483/*
1484 * Write all the default values from sgtl5000_reg_defaults[] array into the
1485 * sgtl5000 registers, to make sure we always start with the sane registers
1486 * values as stated in the datasheet.
1487 *
1488 * Since sgtl5000 does not have a reset line, nor a reset command in software,
1489 * we follow this approach to guarantee we always start from the default values
1490 * and avoid problems like, not being able to probe after an audio playback
1491 * followed by a system reset or a 'reboot' command in Linux
1492 */
1493static int sgtl5000_fill_defaults(struct sgtl5000_priv *sgtl5000)
1494{
1495 int i, ret, val, index;
1496
1497 for (i = 0; i < ARRAY_SIZE(sgtl5000_reg_defaults); i++) {
1498 val = sgtl5000_reg_defaults[i].def;
1499 index = sgtl5000_reg_defaults[i].reg;
1500 ret = regmap_write(sgtl5000->regmap, index, val);
1501 if (ret)
1502 return ret;
1503 }
1504
1505 return 0;
1506}
1507
1407static int sgtl5000_i2c_probe(struct i2c_client *client, 1508static int sgtl5000_i2c_probe(struct i2c_client *client,
1408 const struct i2c_device_id *id) 1509 const struct i2c_device_id *id)
1409{ 1510{
1410 struct sgtl5000_priv *sgtl5000; 1511 struct sgtl5000_priv *sgtl5000;
1411 int ret; 1512 int ret, reg, rev;
1412 1513
1413 sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv), 1514 sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv),
1414 GFP_KERNEL); 1515 GFP_KERNEL);
1415 if (!sgtl5000) 1516 if (!sgtl5000)
1416 return -ENOMEM; 1517 return -ENOMEM;
1417 1518
1519 sgtl5000->regmap = devm_regmap_init_i2c(client, &sgtl5000_regmap);
1520 if (IS_ERR(sgtl5000->regmap)) {
1521 ret = PTR_ERR(sgtl5000->regmap);
1522 dev_err(&client->dev, "Failed to allocate regmap: %d\n", ret);
1523 return ret;
1524 }
1525
1526 sgtl5000->mclk = devm_clk_get(&client->dev, NULL);
1527 if (IS_ERR(sgtl5000->mclk)) {
1528 ret = PTR_ERR(sgtl5000->mclk);
1529 dev_err(&client->dev, "Failed to get mclock: %d\n", ret);
1530 return ret;
1531 }
1532
1533 ret = clk_prepare_enable(sgtl5000->mclk);
1534 if (ret)
1535 return ret;
1536
1537 /* read chip information */
1538 ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, &reg);
1539 if (ret)
1540 goto disable_clk;
1541
1542 if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) !=
1543 SGTL5000_PARTID_PART_ID) {
1544 dev_err(&client->dev,
1545 "Device with ID register %x is not a sgtl5000\n", reg);
1546 ret = -ENODEV;
1547 goto disable_clk;
1548 }
1549
1550 rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
1551 dev_info(&client->dev, "sgtl5000 revision 0x%x\n", rev);
1552
1418 i2c_set_clientdata(client, sgtl5000); 1553 i2c_set_clientdata(client, sgtl5000);
1419 1554
1555 /* Ensure sgtl5000 will start with sane register values */
1556 ret = sgtl5000_fill_defaults(sgtl5000);
1557 if (ret)
1558 goto disable_clk;
1559
1420 ret = snd_soc_register_codec(&client->dev, 1560 ret = snd_soc_register_codec(&client->dev,
1421 &sgtl5000_driver, &sgtl5000_dai, 1); 1561 &sgtl5000_driver, &sgtl5000_dai, 1);
1562 if (ret)
1563 goto disable_clk;
1564
1565 return 0;
1566
1567disable_clk:
1568 clk_disable_unprepare(sgtl5000->mclk);
1422 return ret; 1569 return ret;
1423} 1570}
1424 1571
1425static int sgtl5000_i2c_remove(struct i2c_client *client) 1572static int sgtl5000_i2c_remove(struct i2c_client *client)
1426{ 1573{
1427 snd_soc_unregister_codec(&client->dev); 1574 struct sgtl5000_priv *sgtl5000 = i2c_get_clientdata(client);
1428 1575
1576 snd_soc_unregister_codec(&client->dev);
1577 clk_disable_unprepare(sgtl5000->mclk);
1429 return 0; 1578 return 0;
1430} 1579}
1431 1580
diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h
index 8a9f43534b79..4b69229a9818 100644
--- a/sound/soc/codecs/sgtl5000.h
+++ b/sound/soc/codecs/sgtl5000.h
@@ -12,7 +12,7 @@
12#define _SGTL5000_H 12#define _SGTL5000_H
13 13
14/* 14/*
15 * Register values. 15 * Registers addresses
16 */ 16 */
17#define SGTL5000_CHIP_ID 0x0000 17#define SGTL5000_CHIP_ID 0x0000
18#define SGTL5000_CHIP_DIG_POWER 0x0002 18#define SGTL5000_CHIP_DIG_POWER 0x0002
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index d1ae869d3181..dba26e63844e 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -883,7 +883,7 @@ static int sn95031_codec_remove(struct snd_soc_codec *codec)
883 return 0; 883 return 0;
884} 884}
885 885
886struct snd_soc_codec_driver sn95031_codec = { 886static struct snd_soc_codec_driver sn95031_codec = {
887 .probe = sn95031_codec_probe, 887 .probe = sn95031_codec_probe,
888 .remove = sn95031_codec_remove, 888 .remove = sn95031_codec_remove,
889 .read = sn95031_read, 889 .read = sn95031_read,
diff --git a/sound/soc/codecs/spdif_receiver.c b/sound/soc/codecs/spdif_receiver.c
index dd8d856053fc..e9d7881ed2c8 100644
--- a/sound/soc/codecs/spdif_receiver.c
+++ b/sound/soc/codecs/spdif_receiver.c
@@ -21,6 +21,7 @@
21#include <sound/soc.h> 21#include <sound/soc.h>
22#include <sound/pcm.h> 22#include <sound/pcm.h>
23#include <sound/initval.h> 23#include <sound/initval.h>
24#include <linux/of.h>
24 25
25#define STUB_RATES SNDRV_PCM_RATE_8000_192000 26#define STUB_RATES SNDRV_PCM_RATE_8000_192000
26#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 27#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
@@ -51,12 +52,21 @@ static int spdif_dir_remove(struct platform_device *pdev)
51 return 0; 52 return 0;
52} 53}
53 54
55#ifdef CONFIG_OF
56static const struct of_device_id spdif_dir_dt_ids[] = {
57 { .compatible = "linux,spdif-dir", },
58 { }
59};
60MODULE_DEVICE_TABLE(of, spdif_dir_dt_ids);
61#endif
62
54static struct platform_driver spdif_dir_driver = { 63static struct platform_driver spdif_dir_driver = {
55 .probe = spdif_dir_probe, 64 .probe = spdif_dir_probe,
56 .remove = spdif_dir_remove, 65 .remove = spdif_dir_remove,
57 .driver = { 66 .driver = {
58 .name = "spdif-dir", 67 .name = "spdif-dir",
59 .owner = THIS_MODULE, 68 .owner = THIS_MODULE,
69 .of_match_table = of_match_ptr(spdif_dir_dt_ids),
60 }, 70 },
61}; 71};
62 72
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transmitter.c
index 112a49d66e39..18280499fd55 100644
--- a/sound/soc/codecs/spdif_transciever.c
+++ b/sound/soc/codecs/spdif_transmitter.c
@@ -20,6 +20,7 @@
20#include <sound/soc.h> 20#include <sound/soc.h>
21#include <sound/pcm.h> 21#include <sound/pcm.h>
22#include <sound/initval.h> 22#include <sound/initval.h>
23#include <linux/of.h>
23 24
24#define DRV_NAME "spdif-dit" 25#define DRV_NAME "spdif-dit"
25 26
@@ -52,12 +53,21 @@ static int spdif_dit_remove(struct platform_device *pdev)
52 return 0; 53 return 0;
53} 54}
54 55
56#ifdef CONFIG_OF
57static const struct of_device_id spdif_dit_dt_ids[] = {
58 { .compatible = "linux,spdif-dit", },
59 { }
60};
61MODULE_DEVICE_TABLE(of, spdif_dit_dt_ids);
62#endif
63
55static struct platform_driver spdif_dit_driver = { 64static struct platform_driver spdif_dit_driver = {
56 .probe = spdif_dit_probe, 65 .probe = spdif_dit_probe,
57 .remove = spdif_dit_remove, 66 .remove = spdif_dit_remove,
58 .driver = { 67 .driver = {
59 .name = DRV_NAME, 68 .name = DRV_NAME,
60 .owner = THIS_MODULE, 69 .owner = THIS_MODULE,
70 .of_match_table = of_match_ptr(spdif_dit_dt_ids),
61 }, 71 },
62}; 72};
63 73
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c
new file mode 100644
index 000000000000..95aed552139a
--- /dev/null
+++ b/sound/soc/codecs/ssm2518.c
@@ -0,0 +1,856 @@
1/*
2 * SSM2518 amplifier audio driver
3 *
4 * Copyright 2013 Analog Devices Inc.
5 * Author: Lars-Peter Clausen <lars@metafoo.de>
6 *
7 * Licensed under the GPL-2.
8 */
9
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/i2c.h>
13#include <linux/regmap.h>
14#include <linux/slab.h>
15#include <linux/gpio.h>
16#include <linux/of_gpio.h>
17#include <linux/platform_data/ssm2518.h>
18#include <sound/core.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/soc.h>
22#include <sound/initval.h>
23#include <sound/tlv.h>
24
25#include "ssm2518.h"
26
27#define SSM2518_REG_POWER1 0x00
28#define SSM2518_REG_CLOCK 0x01
29#define SSM2518_REG_SAI_CTRL1 0x02
30#define SSM2518_REG_SAI_CTRL2 0x03
31#define SSM2518_REG_CHAN_MAP 0x04
32#define SSM2518_REG_LEFT_VOL 0x05
33#define SSM2518_REG_RIGHT_VOL 0x06
34#define SSM2518_REG_MUTE_CTRL 0x07
35#define SSM2518_REG_FAULT_CTRL 0x08
36#define SSM2518_REG_POWER2 0x09
37#define SSM2518_REG_DRC_1 0x0a
38#define SSM2518_REG_DRC_2 0x0b
39#define SSM2518_REG_DRC_3 0x0c
40#define SSM2518_REG_DRC_4 0x0d
41#define SSM2518_REG_DRC_5 0x0e
42#define SSM2518_REG_DRC_6 0x0f
43#define SSM2518_REG_DRC_7 0x10
44#define SSM2518_REG_DRC_8 0x11
45#define SSM2518_REG_DRC_9 0x12
46
47#define SSM2518_POWER1_RESET BIT(7)
48#define SSM2518_POWER1_NO_BCLK BIT(5)
49#define SSM2518_POWER1_MCS_MASK (0xf << 1)
50#define SSM2518_POWER1_MCS_64FS (0x0 << 1)
51#define SSM2518_POWER1_MCS_128FS (0x1 << 1)
52#define SSM2518_POWER1_MCS_256FS (0x2 << 1)
53#define SSM2518_POWER1_MCS_384FS (0x3 << 1)
54#define SSM2518_POWER1_MCS_512FS (0x4 << 1)
55#define SSM2518_POWER1_MCS_768FS (0x5 << 1)
56#define SSM2518_POWER1_MCS_100FS (0x6 << 1)
57#define SSM2518_POWER1_MCS_200FS (0x7 << 1)
58#define SSM2518_POWER1_MCS_400FS (0x8 << 1)
59#define SSM2518_POWER1_SPWDN BIT(0)
60
61#define SSM2518_CLOCK_ASR BIT(0)
62
63#define SSM2518_SAI_CTRL1_FMT_MASK (0x3 << 5)
64#define SSM2518_SAI_CTRL1_FMT_I2S (0x0 << 5)
65#define SSM2518_SAI_CTRL1_FMT_LJ (0x1 << 5)
66#define SSM2518_SAI_CTRL1_FMT_RJ_24BIT (0x2 << 5)
67#define SSM2518_SAI_CTRL1_FMT_RJ_16BIT (0x3 << 5)
68
69#define SSM2518_SAI_CTRL1_SAI_MASK (0x7 << 2)
70#define SSM2518_SAI_CTRL1_SAI_I2S (0x0 << 2)
71#define SSM2518_SAI_CTRL1_SAI_TDM_2 (0x1 << 2)
72#define SSM2518_SAI_CTRL1_SAI_TDM_4 (0x2 << 2)
73#define SSM2518_SAI_CTRL1_SAI_TDM_8 (0x3 << 2)
74#define SSM2518_SAI_CTRL1_SAI_TDM_16 (0x4 << 2)
75#define SSM2518_SAI_CTRL1_SAI_MONO (0x5 << 2)
76
77#define SSM2518_SAI_CTRL1_FS_MASK (0x3)
78#define SSM2518_SAI_CTRL1_FS_8000_12000 (0x0)
79#define SSM2518_SAI_CTRL1_FS_16000_24000 (0x1)
80#define SSM2518_SAI_CTRL1_FS_32000_48000 (0x2)
81#define SSM2518_SAI_CTRL1_FS_64000_96000 (0x3)
82
83#define SSM2518_SAI_CTRL2_BCLK_INTERAL BIT(7)
84#define SSM2518_SAI_CTRL2_LRCLK_PULSE BIT(6)
85#define SSM2518_SAI_CTRL2_LRCLK_INVERT BIT(5)
86#define SSM2518_SAI_CTRL2_MSB BIT(4)
87#define SSM2518_SAI_CTRL2_SLOT_WIDTH_MASK (0x3 << 2)
88#define SSM2518_SAI_CTRL2_SLOT_WIDTH_32 (0x0 << 2)
89#define SSM2518_SAI_CTRL2_SLOT_WIDTH_24 (0x1 << 2)
90#define SSM2518_SAI_CTRL2_SLOT_WIDTH_16 (0x2 << 2)
91#define SSM2518_SAI_CTRL2_BCLK_INVERT BIT(1)
92
93#define SSM2518_CHAN_MAP_RIGHT_SLOT_OFFSET 4
94#define SSM2518_CHAN_MAP_RIGHT_SLOT_MASK 0xf0
95#define SSM2518_CHAN_MAP_LEFT_SLOT_OFFSET 0
96#define SSM2518_CHAN_MAP_LEFT_SLOT_MASK 0x0f
97
98#define SSM2518_MUTE_CTRL_ANA_GAIN BIT(5)
99#define SSM2518_MUTE_CTRL_MUTE_MASTER BIT(0)
100
101#define SSM2518_POWER2_APWDN BIT(0)
102
103#define SSM2518_DAC_MUTE BIT(6)
104#define SSM2518_DAC_FS_MASK 0x07
105#define SSM2518_DAC_FS_8000 0x00
106#define SSM2518_DAC_FS_16000 0x01
107#define SSM2518_DAC_FS_32000 0x02
108#define SSM2518_DAC_FS_64000 0x03
109#define SSM2518_DAC_FS_128000 0x04
110
111struct ssm2518 {
112 struct regmap *regmap;
113 bool right_j;
114
115 unsigned int sysclk;
116 const struct snd_pcm_hw_constraint_list *constraints;
117
118 int enable_gpio;
119};
120
121static const struct reg_default ssm2518_reg_defaults[] = {
122 { 0x00, 0x05 },
123 { 0x01, 0x00 },
124 { 0x02, 0x02 },
125 { 0x03, 0x00 },
126 { 0x04, 0x10 },
127 { 0x05, 0x40 },
128 { 0x06, 0x40 },
129 { 0x07, 0x81 },
130 { 0x08, 0x0c },
131 { 0x09, 0x99 },
132 { 0x0a, 0x7c },
133 { 0x0b, 0x5b },
134 { 0x0c, 0x57 },
135 { 0x0d, 0x89 },
136 { 0x0e, 0x8c },
137 { 0x0f, 0x77 },
138 { 0x10, 0x26 },
139 { 0x11, 0x1c },
140 { 0x12, 0x97 },
141};
142
143static const DECLARE_TLV_DB_MINMAX_MUTE(ssm2518_vol_tlv, -7125, 2400);
144static const DECLARE_TLV_DB_SCALE(ssm2518_compressor_tlv, -3400, 200, 0);
145static const DECLARE_TLV_DB_SCALE(ssm2518_expander_tlv, -8100, 300, 0);
146static const DECLARE_TLV_DB_SCALE(ssm2518_noise_gate_tlv, -9600, 300, 0);
147static const DECLARE_TLV_DB_SCALE(ssm2518_post_drc_tlv, -2400, 300, 0);
148
149static const DECLARE_TLV_DB_RANGE(ssm2518_limiter_tlv,
150 0, 7, TLV_DB_SCALE_ITEM(-2200, 200, 0),
151 7, 15, TLV_DB_SCALE_ITEM(-800, 100, 0),
152);
153
154static const char * const ssm2518_drc_peak_detector_attack_time_text[] = {
155 "0 ms", "0.1 ms", "0.19 ms", "0.37 ms", "0.75 ms", "1.5 ms", "3 ms",
156 "6 ms", "12 ms", "24 ms", "48 ms", "96 ms", "192 ms", "384 ms",
157 "768 ms", "1536 ms",
158};
159
160static const char * const ssm2518_drc_peak_detector_release_time_text[] = {
161 "0 ms", "1.5 ms", "3 ms", "6 ms", "12 ms", "24 ms", "48 ms", "96 ms",
162 "192 ms", "384 ms", "768 ms", "1536 ms", "3072 ms", "6144 ms",
163 "12288 ms", "24576 ms"
164};
165
166static const char * const ssm2518_drc_hold_time_text[] = {
167 "0 ms", "0.67 ms", "1.33 ms", "2.67 ms", "5.33 ms", "10.66 ms",
168 "21.32 ms", "42.64 ms", "85.28 ms", "170.56 ms", "341.12 ms",
169 "682.24 ms", "1364 ms",
170};
171
172static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum,
173 SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text);
174static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum,
175 SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text);
176static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum,
177 SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text);
178static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum,
179 SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text);
180static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum,
181 SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text);
182static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum,
183 SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text);
184static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum,
185 SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text);
186
187static const struct snd_kcontrol_new ssm2518_snd_controls[] = {
188 SOC_SINGLE("Playback De-emphasis Switch", SSM2518_REG_MUTE_CTRL,
189 4, 1, 0),
190 SOC_DOUBLE_R_TLV("Master Playback Volume", SSM2518_REG_LEFT_VOL,
191 SSM2518_REG_RIGHT_VOL, 0, 0xff, 1, ssm2518_vol_tlv),
192 SOC_DOUBLE("Master Playback Switch", SSM2518_REG_MUTE_CTRL, 2, 1, 1, 1),
193
194 SOC_SINGLE("Amp Low Power Mode Switch", SSM2518_REG_POWER2, 4, 1, 0),
195 SOC_SINGLE("DAC Low Power Mode Switch", SSM2518_REG_POWER2, 3, 1, 0),
196
197 SOC_SINGLE("DRC Limiter Switch", SSM2518_REG_DRC_1, 5, 1, 0),
198 SOC_SINGLE("DRC Compressor Switch", SSM2518_REG_DRC_1, 4, 1, 0),
199 SOC_SINGLE("DRC Expander Switch", SSM2518_REG_DRC_1, 3, 1, 0),
200 SOC_SINGLE("DRC Noise Gate Switch", SSM2518_REG_DRC_1, 2, 1, 0),
201 SOC_DOUBLE("DRC Switch", SSM2518_REG_DRC_1, 0, 1, 1, 0),
202
203 SOC_SINGLE_TLV("DRC Limiter Threshold Volume",
204 SSM2518_REG_DRC_3, 4, 15, 1, ssm2518_limiter_tlv),
205 SOC_SINGLE_TLV("DRC Compressor Lower Threshold Volume",
206 SSM2518_REG_DRC_3, 0, 15, 1, ssm2518_compressor_tlv),
207 SOC_SINGLE_TLV("DRC Expander Upper Threshold Volume", SSM2518_REG_DRC_4,
208 4, 15, 1, ssm2518_expander_tlv),
209 SOC_SINGLE_TLV("DRC Noise Gate Threshold Volume",
210 SSM2518_REG_DRC_4, 0, 15, 1, ssm2518_noise_gate_tlv),
211 SOC_SINGLE_TLV("DRC Upper Output Threshold Volume",
212 SSM2518_REG_DRC_5, 4, 15, 1, ssm2518_limiter_tlv),
213 SOC_SINGLE_TLV("DRC Lower Output Threshold Volume",
214 SSM2518_REG_DRC_5, 0, 15, 1, ssm2518_noise_gate_tlv),
215 SOC_SINGLE_TLV("DRC Post Volume", SSM2518_REG_DRC_8,
216 2, 15, 1, ssm2518_post_drc_tlv),
217
218 SOC_ENUM("DRC Peak Detector Attack Time",
219 ssm2518_drc_peak_detector_attack_time_enum),
220 SOC_ENUM("DRC Peak Detector Release Time",
221 ssm2518_drc_peak_detector_release_time_enum),
222 SOC_ENUM("DRC Attack Time", ssm2518_drc_attack_time_enum),
223 SOC_ENUM("DRC Decay Time", ssm2518_drc_decay_time_enum),
224 SOC_ENUM("DRC Hold Time", ssm2518_drc_hold_time_enum),
225 SOC_ENUM("DRC Noise Gate Hold Time",
226 ssm2518_drc_noise_gate_hold_time_enum),
227 SOC_ENUM("DRC RMS Averaging Time", ssm2518_drc_rms_averaging_time_enum),
228};
229
230static const struct snd_soc_dapm_widget ssm2518_dapm_widgets[] = {
231 SND_SOC_DAPM_DAC("DACL", "HiFi Playback", SSM2518_REG_POWER2, 1, 1),
232 SND_SOC_DAPM_DAC("DACR", "HiFi Playback", SSM2518_REG_POWER2, 2, 1),
233
234 SND_SOC_DAPM_OUTPUT("OUTL"),
235 SND_SOC_DAPM_OUTPUT("OUTR"),
236};
237
238static const struct snd_soc_dapm_route ssm2518_routes[] = {
239 { "OUTL", NULL, "DACL" },
240 { "OUTR", NULL, "DACR" },
241};
242
243struct ssm2518_mcs_lut {
244 unsigned int rate;
245 const unsigned int *sysclks;
246};
247
248static const unsigned int ssm2518_sysclks_2048000[] = {
249 2048000, 4096000, 8192000, 12288000, 16384000, 24576000,
250 3200000, 6400000, 12800000, 0
251};
252
253static const unsigned int ssm2518_sysclks_2822000[] = {
254 2822000, 5644800, 11289600, 16934400, 22579200, 33868800,
255 4410000, 8820000, 17640000, 0
256};
257
258static const unsigned int ssm2518_sysclks_3072000[] = {
259 3072000, 6144000, 12288000, 16384000, 24576000, 38864000,
260 4800000, 9600000, 19200000, 0
261};
262
263static const struct ssm2518_mcs_lut ssm2518_mcs_lut[] = {
264 { 8000, ssm2518_sysclks_2048000, },
265 { 11025, ssm2518_sysclks_2822000, },
266 { 12000, ssm2518_sysclks_3072000, },
267 { 16000, ssm2518_sysclks_2048000, },
268 { 24000, ssm2518_sysclks_3072000, },
269 { 22050, ssm2518_sysclks_2822000, },
270 { 32000, ssm2518_sysclks_2048000, },
271 { 44100, ssm2518_sysclks_2822000, },
272 { 48000, ssm2518_sysclks_3072000, },
273 { 96000, ssm2518_sysclks_3072000, },
274};
275
276static const unsigned int ssm2518_rates_2048000[] = {
277 8000, 16000, 32000,
278};
279
280static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2048000 = {
281 .list = ssm2518_rates_2048000,
282 .count = ARRAY_SIZE(ssm2518_rates_2048000),
283};
284
285static const unsigned int ssm2518_rates_2822000[] = {
286 11025, 22050, 44100,
287};
288
289static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2822000 = {
290 .list = ssm2518_rates_2822000,
291 .count = ARRAY_SIZE(ssm2518_rates_2822000),
292};
293
294static const unsigned int ssm2518_rates_3072000[] = {
295 12000, 24000, 48000, 96000,
296};
297
298static const struct snd_pcm_hw_constraint_list ssm2518_constraints_3072000 = {
299 .list = ssm2518_rates_3072000,
300 .count = ARRAY_SIZE(ssm2518_rates_3072000),
301};
302
303static const unsigned int ssm2518_rates_12288000[] = {
304 8000, 12000, 16000, 24000, 32000, 48000, 96000,
305};
306
307static const struct snd_pcm_hw_constraint_list ssm2518_constraints_12288000 = {
308 .list = ssm2518_rates_12288000,
309 .count = ARRAY_SIZE(ssm2518_rates_12288000),
310};
311
312static unsigned int ssm2518_lookup_mcs(struct ssm2518 *ssm2518,
313 unsigned int rate)
314{
315 const unsigned int *sysclks = NULL;
316 int i;
317
318 for (i = 0; i < ARRAY_SIZE(ssm2518_mcs_lut); i++) {
319 if (ssm2518_mcs_lut[i].rate == rate) {
320 sysclks = ssm2518_mcs_lut[i].sysclks;
321 break;
322 }
323 }
324
325 if (!sysclks)
326 return -EINVAL;
327
328 for (i = 0; sysclks[i]; i++) {
329 if (sysclks[i] == ssm2518->sysclk)
330 return i;
331 }
332
333 return -EINVAL;
334}
335
336static int ssm2518_hw_params(struct snd_pcm_substream *substream,
337 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
338{
339 struct snd_soc_codec *codec = dai->codec;
340 struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec);
341 unsigned int rate = params_rate(params);
342 unsigned int ctrl1, ctrl1_mask;
343 int mcs;
344 int ret;
345
346 mcs = ssm2518_lookup_mcs(ssm2518, rate);
347 if (mcs < 0)
348 return mcs;
349
350 ctrl1_mask = SSM2518_SAI_CTRL1_FS_MASK;
351
352 if (rate >= 8000 && rate <= 12000)
353 ctrl1 = SSM2518_SAI_CTRL1_FS_8000_12000;
354 else if (rate >= 16000 && rate <= 24000)
355 ctrl1 = SSM2518_SAI_CTRL1_FS_16000_24000;
356 else if (rate >= 32000 && rate <= 48000)
357 ctrl1 = SSM2518_SAI_CTRL1_FS_32000_48000;
358 else if (rate >= 64000 && rate <= 96000)
359 ctrl1 = SSM2518_SAI_CTRL1_FS_64000_96000;
360 else
361 return -EINVAL;
362
363 if (ssm2518->right_j) {
364 switch (params_format(params)) {
365 case SNDRV_PCM_FORMAT_S16_LE:
366 ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_16BIT;
367 break;
368 case SNDRV_PCM_FORMAT_S24_LE:
369 ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT;
370 break;
371 default:
372 return -EINVAL;
373 }
374 ctrl1_mask |= SSM2518_SAI_CTRL1_FMT_MASK;
375 }
376
377 /* Disable auto samplerate detection */
378 ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_CLOCK,
379 SSM2518_CLOCK_ASR, SSM2518_CLOCK_ASR);
380 if (ret < 0)
381 return ret;
382
383 ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL1,
384 ctrl1_mask, ctrl1);
385 if (ret < 0)
386 return ret;
387
388 return regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
389 SSM2518_POWER1_MCS_MASK, mcs << 1);
390}
391
392static int ssm2518_mute(struct snd_soc_dai *dai, int mute)
393{
394 struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(dai->codec);
395 unsigned int val;
396
397 if (mute)
398 val = SSM2518_MUTE_CTRL_MUTE_MASTER;
399 else
400 val = 0;
401
402 return regmap_update_bits(ssm2518->regmap, SSM2518_REG_MUTE_CTRL,
403 SSM2518_MUTE_CTRL_MUTE_MASTER, val);
404}
405
406static int ssm2518_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
407{
408 struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(dai->codec);
409 unsigned int ctrl1 = 0, ctrl2 = 0;
410 bool invert_fclk;
411 int ret;
412
413 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
414 case SND_SOC_DAIFMT_CBS_CFS:
415 break;
416 default:
417 return -EINVAL;
418 }
419
420 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
421 case SND_SOC_DAIFMT_NB_NF:
422 invert_fclk = false;
423 break;
424 case SND_SOC_DAIFMT_IB_NF:
425 ctrl2 |= SSM2518_SAI_CTRL2_BCLK_INVERT;
426 invert_fclk = false;
427 break;
428 case SND_SOC_DAIFMT_NB_IF:
429 invert_fclk = true;
430 break;
431 case SND_SOC_DAIFMT_IB_IF:
432 ctrl2 |= SSM2518_SAI_CTRL2_BCLK_INVERT;
433 invert_fclk = true;
434 break;
435 default:
436 return -EINVAL;
437 }
438
439 ssm2518->right_j = false;
440 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
441 case SND_SOC_DAIFMT_I2S:
442 ctrl1 |= SSM2518_SAI_CTRL1_FMT_I2S;
443 break;
444 case SND_SOC_DAIFMT_LEFT_J:
445 ctrl1 |= SSM2518_SAI_CTRL1_FMT_LJ;
446 invert_fclk = !invert_fclk;
447 break;
448 case SND_SOC_DAIFMT_RIGHT_J:
449 ctrl1 |= SSM2518_SAI_CTRL1_FMT_RJ_24BIT;
450 ssm2518->right_j = true;
451 invert_fclk = !invert_fclk;
452 break;
453 case SND_SOC_DAIFMT_DSP_A:
454 ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_PULSE;
455 ctrl1 |= SSM2518_SAI_CTRL1_FMT_I2S;
456 invert_fclk = false;
457 break;
458 case SND_SOC_DAIFMT_DSP_B:
459 ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_PULSE;
460 ctrl1 |= SSM2518_SAI_CTRL1_FMT_LJ;
461 invert_fclk = false;
462 break;
463 default:
464 return -EINVAL;
465 }
466
467 if (invert_fclk)
468 ctrl2 |= SSM2518_SAI_CTRL2_LRCLK_INVERT;
469
470 ret = regmap_write(ssm2518->regmap, SSM2518_REG_SAI_CTRL1, ctrl1);
471 if (ret)
472 return ret;
473
474 return regmap_write(ssm2518->regmap, SSM2518_REG_SAI_CTRL2, ctrl2);
475}
476
477static int ssm2518_set_power(struct ssm2518 *ssm2518, bool enable)
478{
479 int ret = 0;
480
481 if (!enable) {
482 ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
483 SSM2518_POWER1_SPWDN, SSM2518_POWER1_SPWDN);
484 regcache_mark_dirty(ssm2518->regmap);
485 }
486
487 if (gpio_is_valid(ssm2518->enable_gpio))
488 gpio_set_value(ssm2518->enable_gpio, enable);
489
490 regcache_cache_only(ssm2518->regmap, !enable);
491
492 if (enable) {
493 ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
494 SSM2518_POWER1_SPWDN | SSM2518_POWER1_RESET, 0x00);
495 regcache_sync(ssm2518->regmap);
496 }
497
498 return ret;
499}
500
501static int ssm2518_set_bias_level(struct snd_soc_codec *codec,
502 enum snd_soc_bias_level level)
503{
504 struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec);
505 int ret = 0;
506
507 switch (level) {
508 case SND_SOC_BIAS_ON:
509 break;
510 case SND_SOC_BIAS_PREPARE:
511 break;
512 case SND_SOC_BIAS_STANDBY:
513 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
514 ret = ssm2518_set_power(ssm2518, true);
515 break;
516 case SND_SOC_BIAS_OFF:
517 ret = ssm2518_set_power(ssm2518, false);
518 break;
519 }
520
521 if (ret)
522 return ret;
523
524 codec->dapm.bias_level = level;
525
526 return 0;
527}
528
529static int ssm2518_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
530 unsigned int rx_mask, int slots, int width)
531{
532 struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(dai->codec);
533 unsigned int ctrl1, ctrl2;
534 int left_slot, right_slot;
535 int ret;
536
537 if (slots == 0)
538 return regmap_update_bits(ssm2518->regmap,
539 SSM2518_REG_SAI_CTRL1, SSM2518_SAI_CTRL1_SAI_MASK,
540 SSM2518_SAI_CTRL1_SAI_I2S);
541
542 if (tx_mask == 0 || rx_mask != 0)
543 return -EINVAL;
544
545 if (slots == 1) {
546 if (tx_mask != 1)
547 return -EINVAL;
548 left_slot = 0;
549 right_slot = 0;
550 } else {
551 /* We assume the left channel < right channel */
552 left_slot = ffs(tx_mask);
553 tx_mask &= ~(1 << tx_mask);
554 if (tx_mask == 0) {
555 right_slot = left_slot;
556 } else {
557 right_slot = ffs(tx_mask);
558 tx_mask &= ~(1 << tx_mask);
559 }
560 }
561
562 if (tx_mask != 0 || left_slot >= slots || right_slot >= slots)
563 return -EINVAL;
564
565 switch (width) {
566 case 16:
567 ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_16;
568 break;
569 case 24:
570 ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_24;
571 break;
572 case 32:
573 ctrl2 = SSM2518_SAI_CTRL2_SLOT_WIDTH_32;
574 break;
575 default:
576 return -EINVAL;
577 }
578
579 switch (slots) {
580 case 1:
581 ctrl1 = SSM2518_SAI_CTRL1_SAI_MONO;
582 break;
583 case 2:
584 ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_2;
585 break;
586 case 4:
587 ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_4;
588 break;
589 case 8:
590 ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_8;
591 break;
592 case 16:
593 ctrl1 = SSM2518_SAI_CTRL1_SAI_TDM_16;
594 break;
595 default:
596 return -EINVAL;
597 }
598
599 ret = regmap_write(ssm2518->regmap, SSM2518_REG_CHAN_MAP,
600 (left_slot << SSM2518_CHAN_MAP_LEFT_SLOT_OFFSET) |
601 (right_slot << SSM2518_CHAN_MAP_RIGHT_SLOT_OFFSET));
602 if (ret)
603 return ret;
604
605 ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL1,
606 SSM2518_SAI_CTRL1_SAI_MASK, ctrl1);
607 if (ret)
608 return ret;
609
610 return regmap_update_bits(ssm2518->regmap, SSM2518_REG_SAI_CTRL2,
611 SSM2518_SAI_CTRL2_SLOT_WIDTH_MASK, ctrl2);
612}
613
614static int ssm2518_startup(struct snd_pcm_substream *substream,
615 struct snd_soc_dai *dai)
616{
617 struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(dai->codec);
618
619 if (ssm2518->constraints)
620 snd_pcm_hw_constraint_list(substream->runtime, 0,
621 SNDRV_PCM_HW_PARAM_RATE, ssm2518->constraints);
622
623 return 0;
624}
625
626#define SSM2518_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
627 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32)
628
629static const struct snd_soc_dai_ops ssm2518_dai_ops = {
630 .startup = ssm2518_startup,
631 .hw_params = ssm2518_hw_params,
632 .digital_mute = ssm2518_mute,
633 .set_fmt = ssm2518_set_dai_fmt,
634 .set_tdm_slot = ssm2518_set_tdm_slot,
635};
636
637static struct snd_soc_dai_driver ssm2518_dai = {
638 .name = "ssm2518-hifi",
639 .playback = {
640 .stream_name = "Playback",
641 .channels_min = 2,
642 .channels_max = 2,
643 .rates = SNDRV_PCM_RATE_8000_96000,
644 .formats = SSM2518_FORMATS,
645 },
646 .ops = &ssm2518_dai_ops,
647};
648
649static int ssm2518_probe(struct snd_soc_codec *codec)
650{
651 struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec);
652 int ret;
653
654 codec->control_data = ssm2518->regmap;
655 ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
656 if (ret < 0) {
657 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
658 return ret;
659 }
660
661 return ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF);
662}
663
664static int ssm2518_remove(struct snd_soc_codec *codec)
665{
666 ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF);
667 return 0;
668}
669
670static int ssm2518_set_sysclk(struct snd_soc_codec *codec, int clk_id,
671 int source, unsigned int freq, int dir)
672{
673 struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec);
674 unsigned int val;
675
676 if (clk_id != SSM2518_SYSCLK)
677 return -EINVAL;
678
679 switch (source) {
680 case SSM2518_SYSCLK_SRC_MCLK:
681 val = 0;
682 break;
683 case SSM2518_SYSCLK_SRC_BCLK:
684 /* In this case the bitclock is used as the system clock, and
685 * the bitclock signal needs to be connected to the MCLK pin and
686 * the BCLK pin is left unconnected */
687 val = SSM2518_POWER1_NO_BCLK;
688 break;
689 default:
690 return -EINVAL;
691 }
692
693 switch (freq) {
694 case 0:
695 ssm2518->constraints = NULL;
696 break;
697 case 2048000:
698 case 4096000:
699 case 8192000:
700 case 3200000:
701 case 6400000:
702 case 12800000:
703 ssm2518->constraints = &ssm2518_constraints_2048000;
704 break;
705 case 2822000:
706 case 5644800:
707 case 11289600:
708 case 16934400:
709 case 22579200:
710 case 33868800:
711 case 4410000:
712 case 8820000:
713 case 17640000:
714 ssm2518->constraints = &ssm2518_constraints_2822000;
715 break;
716 case 3072000:
717 case 6144000:
718 case 38864000:
719 case 4800000:
720 case 9600000:
721 case 19200000:
722 ssm2518->constraints = &ssm2518_constraints_3072000;
723 break;
724 case 12288000:
725 case 16384000:
726 case 24576000:
727 ssm2518->constraints = &ssm2518_constraints_12288000;
728 break;
729 default:
730 return -EINVAL;
731 }
732
733 ssm2518->sysclk = freq;
734
735 return regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER1,
736 SSM2518_POWER1_NO_BCLK, val);
737}
738
739static struct snd_soc_codec_driver ssm2518_codec_driver = {
740 .probe = ssm2518_probe,
741 .remove = ssm2518_remove,
742 .set_bias_level = ssm2518_set_bias_level,
743 .set_sysclk = ssm2518_set_sysclk,
744 .idle_bias_off = true,
745
746 .controls = ssm2518_snd_controls,
747 .num_controls = ARRAY_SIZE(ssm2518_snd_controls),
748 .dapm_widgets = ssm2518_dapm_widgets,
749 .num_dapm_widgets = ARRAY_SIZE(ssm2518_dapm_widgets),
750 .dapm_routes = ssm2518_routes,
751 .num_dapm_routes = ARRAY_SIZE(ssm2518_routes),
752};
753
754static bool ssm2518_register_volatile(struct device *dev, unsigned int reg)
755{
756 return false;
757}
758
759static const struct regmap_config ssm2518_regmap_config = {
760 .val_bits = 8,
761 .reg_bits = 8,
762
763 .max_register = SSM2518_REG_DRC_9,
764 .volatile_reg = ssm2518_register_volatile,
765
766 .cache_type = REGCACHE_RBTREE,
767 .reg_defaults = ssm2518_reg_defaults,
768 .num_reg_defaults = ARRAY_SIZE(ssm2518_reg_defaults),
769};
770
771static int ssm2518_i2c_probe(struct i2c_client *i2c,
772 const struct i2c_device_id *id)
773{
774 struct ssm2518_platform_data *pdata = i2c->dev.platform_data;
775 struct ssm2518 *ssm2518;
776 int ret;
777
778 ssm2518 = devm_kzalloc(&i2c->dev, sizeof(*ssm2518), GFP_KERNEL);
779 if (ssm2518 == NULL)
780 return -ENOMEM;
781
782 if (pdata) {
783 ssm2518->enable_gpio = pdata->enable_gpio;
784 } else if (i2c->dev.of_node) {
785 ssm2518->enable_gpio = of_get_gpio(i2c->dev.of_node, 0);
786 if (ssm2518->enable_gpio < 0 && ssm2518->enable_gpio != -ENOENT)
787 return ssm2518->enable_gpio;
788 } else {
789 ssm2518->enable_gpio = -1;
790 }
791
792 if (gpio_is_valid(ssm2518->enable_gpio)) {
793 ret = devm_gpio_request_one(&i2c->dev, ssm2518->enable_gpio,
794 GPIOF_OUT_INIT_HIGH, "SSM2518 nSD");
795 if (ret)
796 return ret;
797 }
798
799 i2c_set_clientdata(i2c, ssm2518);
800
801 ssm2518->regmap = devm_regmap_init_i2c(i2c, &ssm2518_regmap_config);
802 if (IS_ERR(ssm2518->regmap))
803 return PTR_ERR(ssm2518->regmap);
804
805 /*
806 * The reset bit is obviously volatile, but we need to be able to cache
807 * the other bits in the register, so we can't just mark the whole
808 * register as volatile. Since this is the only place where we'll ever
809 * touch the reset bit just bypass the cache for this operation.
810 */
811 regcache_cache_bypass(ssm2518->regmap, true);
812 ret = regmap_write(ssm2518->regmap, SSM2518_REG_POWER1,
813 SSM2518_POWER1_RESET);
814 regcache_cache_bypass(ssm2518->regmap, false);
815 if (ret)
816 return ret;
817
818 ret = regmap_update_bits(ssm2518->regmap, SSM2518_REG_POWER2,
819 SSM2518_POWER2_APWDN, 0x00);
820 if (ret)
821 return ret;
822
823 ret = ssm2518_set_power(ssm2518, false);
824 if (ret)
825 return ret;
826
827 return snd_soc_register_codec(&i2c->dev, &ssm2518_codec_driver,
828 &ssm2518_dai, 1);
829}
830
831static int ssm2518_i2c_remove(struct i2c_client *client)
832{
833 snd_soc_unregister_codec(&client->dev);
834 return 0;
835}
836
837static const struct i2c_device_id ssm2518_i2c_ids[] = {
838 { "ssm2518", 0 },
839 { }
840};
841MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids);
842
843static struct i2c_driver ssm2518_driver = {
844 .driver = {
845 .name = "ssm2518",
846 .owner = THIS_MODULE,
847 },
848 .probe = ssm2518_i2c_probe,
849 .remove = ssm2518_i2c_remove,
850 .id_table = ssm2518_i2c_ids,
851};
852module_i2c_driver(ssm2518_driver);
853
854MODULE_DESCRIPTION("ASoC SSM2518 driver");
855MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
856MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ssm2518.h b/sound/soc/codecs/ssm2518.h
new file mode 100644
index 000000000000..62511d80518e
--- /dev/null
+++ b/sound/soc/codecs/ssm2518.h
@@ -0,0 +1,20 @@
1/*
2 * SSM2518 amplifier audio driver
3 *
4 * Copyright 2013 Analog Devices Inc.
5 * Author: Lars-Peter Clausen <lars@metafoo.de>
6 *
7 * Licensed under the GPL-2.
8 */
9
10#ifndef __SND_SOC_CODECS_SSM2518_H__
11#define __SND_SOC_CODECS_SSM2518_H__
12
13#define SSM2518_SYSCLK 0
14
15enum ssm2518_sysclk_src {
16 SSM2518_SYSCLK_SRC_MCLK = 0,
17 SSM2518_SYSCLK_SRC_BCLK = 1,
18};
19
20#endif
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
index 370af0cbcc9a..f5e835662cdc 100644
--- a/sound/soc/codecs/wm0010.c
+++ b/sound/soc/codecs/wm0010.c
@@ -14,6 +14,7 @@
14 14
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/moduleparam.h> 16#include <linux/moduleparam.h>
17#include <linux/interrupt.h>
17#include <linux/irqreturn.h> 18#include <linux/irqreturn.h>
18#include <linux/init.h> 19#include <linux/init.h>
19#include <linux/spi/spi.h> 20#include <linux/spi/spi.h>
@@ -972,6 +973,13 @@ static int wm0010_spi_probe(struct spi_device *spi)
972 } 973 }
973 wm0010->irq = irq; 974 wm0010->irq = irq;
974 975
976 ret = irq_set_irq_wake(irq, 1);
977 if (ret) {
978 dev_err(wm0010->dev, "Failed to set IRQ %d as wake source: %d\n",
979 irq, ret);
980 return ret;
981 }
982
975 if (spi->max_speed_hz) 983 if (spi->max_speed_hz)
976 wm0010->board_max_spi_speed = spi->max_speed_hz; 984 wm0010->board_max_spi_speed = spi->max_speed_hz;
977 else 985 else
@@ -995,6 +1003,8 @@ static int wm0010_spi_remove(struct spi_device *spi)
995 gpio_set_value_cansleep(wm0010->gpio_reset, 1003 gpio_set_value_cansleep(wm0010->gpio_reset,
996 wm0010->gpio_reset_value); 1004 wm0010->gpio_reset_value);
997 1005
1006 irq_set_irq_wake(wm0010->irq, 0);
1007
998 if (wm0010->irq) 1008 if (wm0010->irq)
999 free_irq(wm0010->irq, wm0010); 1009 free_irq(wm0010->irq, wm0010);
1000 1010
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 100fdadda56a..282fd232cdf7 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -814,7 +814,20 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L,
814 814
815SOC_VALUE_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]), 815SOC_VALUE_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]),
816SOC_VALUE_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]), 816SOC_VALUE_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]),
817SOC_VALUE_ENUM("HPOUT3 OSR", wm5102_hpout_osr[2]), 817SOC_VALUE_ENUM("EPOUT OSR", wm5102_hpout_osr[2]),
818
819SOC_DOUBLE("HPOUT1 DRE Switch", ARIZONA_DRE_ENABLE,
820 ARIZONA_DRE1L_ENA_SHIFT, ARIZONA_DRE1R_ENA_SHIFT, 1, 0),
821SOC_DOUBLE("HPOUT2 DRE Switch", ARIZONA_DRE_ENABLE,
822 ARIZONA_DRE2L_ENA_SHIFT, ARIZONA_DRE2R_ENA_SHIFT, 1, 0),
823SOC_SINGLE("EPOUT DRE Switch", ARIZONA_DRE_ENABLE,
824 ARIZONA_DRE3L_ENA_SHIFT, 1, 0),
825
826SOC_SINGLE("DRE Threshold", ARIZONA_DRE_CONTROL_2,
827 ARIZONA_DRE_T_LOW_SHIFT, 63, 0),
828
829SOC_SINGLE("DRE Low Level ABS", ARIZONA_DRE_CONTROL_3,
830 ARIZONA_DRE_LOW_LEVEL_ABS_SHIFT, 15, 0),
818 831
819SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), 832SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp),
820SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), 833SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp),
@@ -852,6 +865,15 @@ ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE),
852 865
853ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), 866ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
854ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), 867ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
868
869ARIZONA_MIXER_CONTROLS("SLIMTX1", ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE),
870ARIZONA_MIXER_CONTROLS("SLIMTX2", ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE),
871ARIZONA_MIXER_CONTROLS("SLIMTX3", ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE),
872ARIZONA_MIXER_CONTROLS("SLIMTX4", ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE),
873ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE),
874ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE),
875ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE),
876ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE),
855}; 877};
856 878
857ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); 879ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
@@ -898,6 +920,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
898ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); 920ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
899ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); 921ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
900 922
923ARIZONA_MIXER_ENUMS(SLIMTX1, ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE);
924ARIZONA_MIXER_ENUMS(SLIMTX2, ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE);
925ARIZONA_MIXER_ENUMS(SLIMTX3, ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE);
926ARIZONA_MIXER_ENUMS(SLIMTX4, ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE);
927ARIZONA_MIXER_ENUMS(SLIMTX5, ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE);
928ARIZONA_MIXER_ENUMS(SLIMTX6, ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE);
929ARIZONA_MIXER_ENUMS(SLIMTX7, ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE);
930ARIZONA_MIXER_ENUMS(SLIMTX8, ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE);
931
901ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); 932ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
902ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); 933ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
903ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); 934ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
@@ -1117,6 +1148,56 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
1117SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, 1148SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
1118 ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), 1149 ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
1119 1150
1151SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0,
1152 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
1153 ARIZONA_SLIMTX1_ENA_SHIFT, 0),
1154SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0,
1155 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
1156 ARIZONA_SLIMTX2_ENA_SHIFT, 0),
1157SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0,
1158 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
1159 ARIZONA_SLIMTX3_ENA_SHIFT, 0),
1160SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0,
1161 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
1162 ARIZONA_SLIMTX4_ENA_SHIFT, 0),
1163SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0,
1164 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
1165 ARIZONA_SLIMTX5_ENA_SHIFT, 0),
1166SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0,
1167 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
1168 ARIZONA_SLIMTX6_ENA_SHIFT, 0),
1169SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0,
1170 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
1171 ARIZONA_SLIMTX7_ENA_SHIFT, 0),
1172SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0,
1173 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
1174 ARIZONA_SLIMTX8_ENA_SHIFT, 0),
1175
1176SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0,
1177 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
1178 ARIZONA_SLIMRX1_ENA_SHIFT, 0),
1179SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0,
1180 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
1181 ARIZONA_SLIMRX2_ENA_SHIFT, 0),
1182SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0,
1183 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
1184 ARIZONA_SLIMRX3_ENA_SHIFT, 0),
1185SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0,
1186 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
1187 ARIZONA_SLIMRX4_ENA_SHIFT, 0),
1188SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0,
1189 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
1190 ARIZONA_SLIMRX5_ENA_SHIFT, 0),
1191SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0,
1192 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
1193 ARIZONA_SLIMRX6_ENA_SHIFT, 0),
1194SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0,
1195 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
1196 ARIZONA_SLIMRX7_ENA_SHIFT, 0),
1197SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0,
1198 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
1199 ARIZONA_SLIMRX8_ENA_SHIFT, 0),
1200
1120ARIZONA_DSP_WIDGETS(DSP1, "DSP1"), 1201ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
1121 1202
1122SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, 1203SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
@@ -1189,6 +1270,15 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
1189ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), 1270ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
1190ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), 1271ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
1191 1272
1273ARIZONA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"),
1274ARIZONA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"),
1275ARIZONA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"),
1276ARIZONA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"),
1277ARIZONA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"),
1278ARIZONA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"),
1279ARIZONA_MIXER_WIDGETS(SLIMTX7, "SLIMTX7"),
1280ARIZONA_MIXER_WIDGETS(SLIMTX8, "SLIMTX8"),
1281
1192ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), 1282ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
1193ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), 1283ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
1194ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), 1284ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
@@ -1249,6 +1339,14 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"),
1249 { name, "AIF2RX2", "AIF2RX2" }, \ 1339 { name, "AIF2RX2", "AIF2RX2" }, \
1250 { name, "AIF3RX1", "AIF3RX1" }, \ 1340 { name, "AIF3RX1", "AIF3RX1" }, \
1251 { name, "AIF3RX2", "AIF3RX2" }, \ 1341 { name, "AIF3RX2", "AIF3RX2" }, \
1342 { name, "SLIMRX1", "SLIMRX1" }, \
1343 { name, "SLIMRX2", "SLIMRX2" }, \
1344 { name, "SLIMRX3", "SLIMRX3" }, \
1345 { name, "SLIMRX4", "SLIMRX4" }, \
1346 { name, "SLIMRX5", "SLIMRX5" }, \
1347 { name, "SLIMRX6", "SLIMRX6" }, \
1348 { name, "SLIMRX7", "SLIMRX7" }, \
1349 { name, "SLIMRX8", "SLIMRX8" }, \
1252 { name, "EQ1", "EQ1" }, \ 1350 { name, "EQ1", "EQ1" }, \
1253 { name, "EQ2", "EQ2" }, \ 1351 { name, "EQ2", "EQ2" }, \
1254 { name, "EQ3", "EQ3" }, \ 1352 { name, "EQ3", "EQ3" }, \
@@ -1304,10 +1402,21 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
1304 { "OUT5L", NULL, "SYSCLK" }, 1402 { "OUT5L", NULL, "SYSCLK" },
1305 { "OUT5R", NULL, "SYSCLK" }, 1403 { "OUT5R", NULL, "SYSCLK" },
1306 1404
1405 { "IN1L", NULL, "SYSCLK" },
1406 { "IN1R", NULL, "SYSCLK" },
1407 { "IN2L", NULL, "SYSCLK" },
1408 { "IN2R", NULL, "SYSCLK" },
1409 { "IN3L", NULL, "SYSCLK" },
1410 { "IN3R", NULL, "SYSCLK" },
1411
1307 { "MICBIAS1", NULL, "MICVDD" }, 1412 { "MICBIAS1", NULL, "MICVDD" },
1308 { "MICBIAS2", NULL, "MICVDD" }, 1413 { "MICBIAS2", NULL, "MICVDD" },
1309 { "MICBIAS3", NULL, "MICVDD" }, 1414 { "MICBIAS3", NULL, "MICVDD" },
1310 1415
1416 { "Noise Generator", NULL, "SYSCLK" },
1417 { "Tone Generator 1", NULL, "SYSCLK" },
1418 { "Tone Generator 2", NULL, "SYSCLK" },
1419
1311 { "Noise Generator", NULL, "NOISE" }, 1420 { "Noise Generator", NULL, "NOISE" },
1312 { "Tone Generator 1", NULL, "TONE" }, 1421 { "Tone Generator 1", NULL, "TONE" },
1313 { "Tone Generator 2", NULL, "TONE" }, 1422 { "Tone Generator 2", NULL, "TONE" },
@@ -1345,13 +1454,41 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
1345 { "AIF3RX1", NULL, "AIF3 Playback" }, 1454 { "AIF3RX1", NULL, "AIF3 Playback" },
1346 { "AIF3RX2", NULL, "AIF3 Playback" }, 1455 { "AIF3RX2", NULL, "AIF3 Playback" },
1347 1456
1457 { "Slim1 Capture", NULL, "SLIMTX1" },
1458 { "Slim1 Capture", NULL, "SLIMTX2" },
1459 { "Slim1 Capture", NULL, "SLIMTX3" },
1460 { "Slim1 Capture", NULL, "SLIMTX4" },
1461
1462 { "SLIMRX1", NULL, "Slim1 Playback" },
1463 { "SLIMRX2", NULL, "Slim1 Playback" },
1464 { "SLIMRX3", NULL, "Slim1 Playback" },
1465 { "SLIMRX4", NULL, "Slim1 Playback" },
1466
1467 { "Slim2 Capture", NULL, "SLIMTX5" },
1468 { "Slim2 Capture", NULL, "SLIMTX6" },
1469
1470 { "SLIMRX5", NULL, "Slim2 Playback" },
1471 { "SLIMRX6", NULL, "Slim2 Playback" },
1472
1473 { "Slim3 Capture", NULL, "SLIMTX7" },
1474 { "Slim3 Capture", NULL, "SLIMTX8" },
1475
1476 { "SLIMRX7", NULL, "Slim3 Playback" },
1477 { "SLIMRX8", NULL, "Slim3 Playback" },
1478
1348 { "AIF1 Playback", NULL, "SYSCLK" }, 1479 { "AIF1 Playback", NULL, "SYSCLK" },
1349 { "AIF2 Playback", NULL, "SYSCLK" }, 1480 { "AIF2 Playback", NULL, "SYSCLK" },
1350 { "AIF3 Playback", NULL, "SYSCLK" }, 1481 { "AIF3 Playback", NULL, "SYSCLK" },
1482 { "Slim1 Playback", NULL, "SYSCLK" },
1483 { "Slim2 Playback", NULL, "SYSCLK" },
1484 { "Slim3 Playback", NULL, "SYSCLK" },
1351 1485
1352 { "AIF1 Capture", NULL, "SYSCLK" }, 1486 { "AIF1 Capture", NULL, "SYSCLK" },
1353 { "AIF2 Capture", NULL, "SYSCLK" }, 1487 { "AIF2 Capture", NULL, "SYSCLK" },
1354 { "AIF3 Capture", NULL, "SYSCLK" }, 1488 { "AIF3 Capture", NULL, "SYSCLK" },
1489 { "Slim1 Capture", NULL, "SYSCLK" },
1490 { "Slim2 Capture", NULL, "SYSCLK" },
1491 { "Slim3 Capture", NULL, "SYSCLK" },
1355 1492
1356 { "IN1L PGA", NULL, "IN1L" }, 1493 { "IN1L PGA", NULL, "IN1L" },
1357 { "IN1R PGA", NULL, "IN1R" }, 1494 { "IN1R PGA", NULL, "IN1R" },
@@ -1408,6 +1545,15 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
1408 ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), 1545 ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
1409 ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), 1546 ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
1410 1547
1548 ARIZONA_MIXER_ROUTES("SLIMTX1", "SLIMTX1"),
1549 ARIZONA_MIXER_ROUTES("SLIMTX2", "SLIMTX2"),
1550 ARIZONA_MIXER_ROUTES("SLIMTX3", "SLIMTX3"),
1551 ARIZONA_MIXER_ROUTES("SLIMTX4", "SLIMTX4"),
1552 ARIZONA_MIXER_ROUTES("SLIMTX5", "SLIMTX5"),
1553 ARIZONA_MIXER_ROUTES("SLIMTX6", "SLIMTX6"),
1554 ARIZONA_MIXER_ROUTES("SLIMTX7", "SLIMTX7"),
1555 ARIZONA_MIXER_ROUTES("SLIMTX8", "SLIMTX8"),
1556
1411 ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), 1557 ARIZONA_MIXER_ROUTES("EQ1", "EQ1"),
1412 ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), 1558 ARIZONA_MIXER_ROUTES("EQ2", "EQ2"),
1413 ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), 1559 ARIZONA_MIXER_ROUTES("EQ3", "EQ3"),
@@ -1560,6 +1706,63 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
1560 .ops = &arizona_dai_ops, 1706 .ops = &arizona_dai_ops,
1561 .symmetric_rates = 1, 1707 .symmetric_rates = 1,
1562 }, 1708 },
1709 {
1710 .name = "wm5102-slim1",
1711 .id = 4,
1712 .playback = {
1713 .stream_name = "Slim1 Playback",
1714 .channels_min = 1,
1715 .channels_max = 4,
1716 .rates = WM5102_RATES,
1717 .formats = WM5102_FORMATS,
1718 },
1719 .capture = {
1720 .stream_name = "Slim1 Capture",
1721 .channels_min = 1,
1722 .channels_max = 4,
1723 .rates = WM5102_RATES,
1724 .formats = WM5102_FORMATS,
1725 },
1726 .ops = &arizona_simple_dai_ops,
1727 },
1728 {
1729 .name = "wm5102-slim2",
1730 .id = 5,
1731 .playback = {
1732 .stream_name = "Slim2 Playback",
1733 .channels_min = 1,
1734 .channels_max = 2,
1735 .rates = WM5102_RATES,
1736 .formats = WM5102_FORMATS,
1737 },
1738 .capture = {
1739 .stream_name = "Slim2 Capture",
1740 .channels_min = 1,
1741 .channels_max = 2,
1742 .rates = WM5102_RATES,
1743 .formats = WM5102_FORMATS,
1744 },
1745 .ops = &arizona_simple_dai_ops,
1746 },
1747 {
1748 .name = "wm5102-slim3",
1749 .id = 6,
1750 .playback = {
1751 .stream_name = "Slim3 Playback",
1752 .channels_min = 1,
1753 .channels_max = 2,
1754 .rates = WM5102_RATES,
1755 .formats = WM5102_FORMATS,
1756 },
1757 .capture = {
1758 .stream_name = "Slim3 Capture",
1759 .channels_min = 1,
1760 .channels_max = 2,
1761 .rates = WM5102_RATES,
1762 .formats = WM5102_FORMATS,
1763 },
1764 .ops = &arizona_simple_dai_ops,
1765 },
1563}; 1766};
1564 1767
1565static int wm5102_codec_probe(struct snd_soc_codec *codec) 1768static int wm5102_codec_probe(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index 88ad7db52dde..2e7cb4ba161a 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -309,6 +309,15 @@ ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE),
309 309
310ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), 310ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
311ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), 311ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
312
313ARIZONA_MIXER_CONTROLS("SLIMTX1", ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE),
314ARIZONA_MIXER_CONTROLS("SLIMTX2", ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE),
315ARIZONA_MIXER_CONTROLS("SLIMTX3", ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE),
316ARIZONA_MIXER_CONTROLS("SLIMTX4", ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE),
317ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE),
318ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE),
319ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE),
320ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE),
312}; 321};
313 322
314ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); 323ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
@@ -360,6 +369,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
360ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); 369ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
361ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); 370ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
362 371
372ARIZONA_MIXER_ENUMS(SLIMTX1, ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE);
373ARIZONA_MIXER_ENUMS(SLIMTX2, ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE);
374ARIZONA_MIXER_ENUMS(SLIMTX3, ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE);
375ARIZONA_MIXER_ENUMS(SLIMTX4, ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE);
376ARIZONA_MIXER_ENUMS(SLIMTX5, ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE);
377ARIZONA_MIXER_ENUMS(SLIMTX6, ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE);
378ARIZONA_MIXER_ENUMS(SLIMTX7, ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE);
379ARIZONA_MIXER_ENUMS(SLIMTX8, ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE);
380
363ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); 381ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE);
364ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); 382ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
365ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); 383ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
@@ -550,6 +568,56 @@ SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
550SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, 568SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
551 ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0), 569 ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0),
552 570
571SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0,
572 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
573 ARIZONA_SLIMRX1_ENA_SHIFT, 0),
574SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0,
575 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
576 ARIZONA_SLIMRX2_ENA_SHIFT, 0),
577SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0,
578 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
579 ARIZONA_SLIMRX3_ENA_SHIFT, 0),
580SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0,
581 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
582 ARIZONA_SLIMRX4_ENA_SHIFT, 0),
583SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0,
584 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
585 ARIZONA_SLIMRX5_ENA_SHIFT, 0),
586SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0,
587 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
588 ARIZONA_SLIMRX6_ENA_SHIFT, 0),
589SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0,
590 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
591 ARIZONA_SLIMRX7_ENA_SHIFT, 0),
592SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0,
593 ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
594 ARIZONA_SLIMRX8_ENA_SHIFT, 0),
595
596SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0,
597 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
598 ARIZONA_SLIMTX1_ENA_SHIFT, 0),
599SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0,
600 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
601 ARIZONA_SLIMTX2_ENA_SHIFT, 0),
602SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0,
603 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
604 ARIZONA_SLIMTX3_ENA_SHIFT, 0),
605SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0,
606 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
607 ARIZONA_SLIMTX4_ENA_SHIFT, 0),
608SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0,
609 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
610 ARIZONA_SLIMTX5_ENA_SHIFT, 0),
611SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0,
612 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
613 ARIZONA_SLIMTX6_ENA_SHIFT, 0),
614SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0,
615 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
616 ARIZONA_SLIMTX7_ENA_SHIFT, 0),
617SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0,
618 ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
619 ARIZONA_SLIMTX8_ENA_SHIFT, 0),
620
553SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, 621SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0,
554 ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0), 622 ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0),
555SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, 623SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0,
@@ -640,6 +708,15 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
640ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), 708ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
641ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), 709ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
642 710
711ARIZONA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"),
712ARIZONA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"),
713ARIZONA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"),
714ARIZONA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"),
715ARIZONA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"),
716ARIZONA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"),
717ARIZONA_MIXER_WIDGETS(SLIMTX7, "SLIMTX7"),
718ARIZONA_MIXER_WIDGETS(SLIMTX8, "SLIMTX8"),
719
643ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), 720ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"),
644ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), 721ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
645ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), 722ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
@@ -690,6 +767,14 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"),
690 { name, "AIF2RX2", "AIF2RX2" }, \ 767 { name, "AIF2RX2", "AIF2RX2" }, \
691 { name, "AIF3RX1", "AIF3RX1" }, \ 768 { name, "AIF3RX1", "AIF3RX1" }, \
692 { name, "AIF3RX2", "AIF3RX2" }, \ 769 { name, "AIF3RX2", "AIF3RX2" }, \
770 { name, "SLIMRX1", "SLIMRX1" }, \
771 { name, "SLIMRX2", "SLIMRX2" }, \
772 { name, "SLIMRX3", "SLIMRX3" }, \
773 { name, "SLIMRX4", "SLIMRX4" }, \
774 { name, "SLIMRX5", "SLIMRX5" }, \
775 { name, "SLIMRX6", "SLIMRX6" }, \
776 { name, "SLIMRX7", "SLIMRX7" }, \
777 { name, "SLIMRX8", "SLIMRX8" }, \
693 { name, "EQ1", "EQ1" }, \ 778 { name, "EQ1", "EQ1" }, \
694 { name, "EQ2", "EQ2" }, \ 779 { name, "EQ2", "EQ2" }, \
695 { name, "EQ3", "EQ3" }, \ 780 { name, "EQ3", "EQ3" }, \
@@ -736,10 +821,23 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
736 { "OUT6L", NULL, "SYSCLK" }, 821 { "OUT6L", NULL, "SYSCLK" },
737 { "OUT6R", NULL, "SYSCLK" }, 822 { "OUT6R", NULL, "SYSCLK" },
738 823
824 { "IN1L", NULL, "SYSCLK" },
825 { "IN1R", NULL, "SYSCLK" },
826 { "IN2L", NULL, "SYSCLK" },
827 { "IN2R", NULL, "SYSCLK" },
828 { "IN3L", NULL, "SYSCLK" },
829 { "IN3R", NULL, "SYSCLK" },
830 { "IN4L", NULL, "SYSCLK" },
831 { "IN4R", NULL, "SYSCLK" },
832
739 { "MICBIAS1", NULL, "MICVDD" }, 833 { "MICBIAS1", NULL, "MICVDD" },
740 { "MICBIAS2", NULL, "MICVDD" }, 834 { "MICBIAS2", NULL, "MICVDD" },
741 { "MICBIAS3", NULL, "MICVDD" }, 835 { "MICBIAS3", NULL, "MICVDD" },
742 836
837 { "Noise Generator", NULL, "SYSCLK" },
838 { "Tone Generator 1", NULL, "SYSCLK" },
839 { "Tone Generator 2", NULL, "SYSCLK" },
840
743 { "Noise Generator", NULL, "NOISE" }, 841 { "Noise Generator", NULL, "NOISE" },
744 { "Tone Generator 1", NULL, "TONE" }, 842 { "Tone Generator 1", NULL, "TONE" },
745 { "Tone Generator 2", NULL, "TONE" }, 843 { "Tone Generator 2", NULL, "TONE" },
@@ -777,13 +875,41 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
777 { "AIF3RX1", NULL, "AIF3 Playback" }, 875 { "AIF3RX1", NULL, "AIF3 Playback" },
778 { "AIF3RX2", NULL, "AIF3 Playback" }, 876 { "AIF3RX2", NULL, "AIF3 Playback" },
779 877
878 { "Slim1 Capture", NULL, "SLIMTX1" },
879 { "Slim1 Capture", NULL, "SLIMTX2" },
880 { "Slim1 Capture", NULL, "SLIMTX3" },
881 { "Slim1 Capture", NULL, "SLIMTX4" },
882
883 { "SLIMRX1", NULL, "Slim1 Playback" },
884 { "SLIMRX2", NULL, "Slim1 Playback" },
885 { "SLIMRX3", NULL, "Slim1 Playback" },
886 { "SLIMRX4", NULL, "Slim1 Playback" },
887
888 { "Slim2 Capture", NULL, "SLIMTX5" },
889 { "Slim2 Capture", NULL, "SLIMTX6" },
890
891 { "SLIMRX5", NULL, "Slim2 Playback" },
892 { "SLIMRX6", NULL, "Slim2 Playback" },
893
894 { "Slim3 Capture", NULL, "SLIMTX7" },
895 { "Slim3 Capture", NULL, "SLIMTX8" },
896
897 { "SLIMRX7", NULL, "Slim3 Playback" },
898 { "SLIMRX8", NULL, "Slim3 Playback" },
899
780 { "AIF1 Playback", NULL, "SYSCLK" }, 900 { "AIF1 Playback", NULL, "SYSCLK" },
781 { "AIF2 Playback", NULL, "SYSCLK" }, 901 { "AIF2 Playback", NULL, "SYSCLK" },
782 { "AIF3 Playback", NULL, "SYSCLK" }, 902 { "AIF3 Playback", NULL, "SYSCLK" },
903 { "Slim1 Playback", NULL, "SYSCLK" },
904 { "Slim2 Playback", NULL, "SYSCLK" },
905 { "Slim3 Playback", NULL, "SYSCLK" },
783 906
784 { "AIF1 Capture", NULL, "SYSCLK" }, 907 { "AIF1 Capture", NULL, "SYSCLK" },
785 { "AIF2 Capture", NULL, "SYSCLK" }, 908 { "AIF2 Capture", NULL, "SYSCLK" },
786 { "AIF3 Capture", NULL, "SYSCLK" }, 909 { "AIF3 Capture", NULL, "SYSCLK" },
910 { "Slim1 Capture", NULL, "SYSCLK" },
911 { "Slim2 Capture", NULL, "SYSCLK" },
912 { "Slim3 Capture", NULL, "SYSCLK" },
787 913
788 { "IN1L PGA", NULL, "IN1L" }, 914 { "IN1L PGA", NULL, "IN1L" },
789 { "IN1R PGA", NULL, "IN1R" }, 915 { "IN1R PGA", NULL, "IN1R" },
@@ -829,6 +955,15 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
829 ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), 955 ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
830 ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), 956 ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
831 957
958 ARIZONA_MIXER_ROUTES("SLIMTX1", "SLIMTX1"),
959 ARIZONA_MIXER_ROUTES("SLIMTX2", "SLIMTX2"),
960 ARIZONA_MIXER_ROUTES("SLIMTX3", "SLIMTX3"),
961 ARIZONA_MIXER_ROUTES("SLIMTX4", "SLIMTX4"),
962 ARIZONA_MIXER_ROUTES("SLIMTX5", "SLIMTX5"),
963 ARIZONA_MIXER_ROUTES("SLIMTX6", "SLIMTX6"),
964 ARIZONA_MIXER_ROUTES("SLIMTX7", "SLIMTX7"),
965 ARIZONA_MIXER_ROUTES("SLIMTX8", "SLIMTX8"),
966
832 ARIZONA_MIXER_ROUTES("EQ1", "EQ1"), 967 ARIZONA_MIXER_ROUTES("EQ1", "EQ1"),
833 ARIZONA_MIXER_ROUTES("EQ2", "EQ2"), 968 ARIZONA_MIXER_ROUTES("EQ2", "EQ2"),
834 ARIZONA_MIXER_ROUTES("EQ3", "EQ3"), 969 ARIZONA_MIXER_ROUTES("EQ3", "EQ3"),
@@ -963,6 +1098,63 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
963 .ops = &arizona_dai_ops, 1098 .ops = &arizona_dai_ops,
964 .symmetric_rates = 1, 1099 .symmetric_rates = 1,
965 }, 1100 },
1101 {
1102 .name = "wm5110-slim1",
1103 .id = 4,
1104 .playback = {
1105 .stream_name = "Slim1 Playback",
1106 .channels_min = 1,
1107 .channels_max = 4,
1108 .rates = WM5110_RATES,
1109 .formats = WM5110_FORMATS,
1110 },
1111 .capture = {
1112 .stream_name = "Slim1 Capture",
1113 .channels_min = 1,
1114 .channels_max = 4,
1115 .rates = WM5110_RATES,
1116 .formats = WM5110_FORMATS,
1117 },
1118 .ops = &arizona_simple_dai_ops,
1119 },
1120 {
1121 .name = "wm5110-slim2",
1122 .id = 5,
1123 .playback = {
1124 .stream_name = "Slim2 Playback",
1125 .channels_min = 1,
1126 .channels_max = 2,
1127 .rates = WM5110_RATES,
1128 .formats = WM5110_FORMATS,
1129 },
1130 .capture = {
1131 .stream_name = "Slim2 Capture",
1132 .channels_min = 1,
1133 .channels_max = 2,
1134 .rates = WM5110_RATES,
1135 .formats = WM5110_FORMATS,
1136 },
1137 .ops = &arizona_simple_dai_ops,
1138 },
1139 {
1140 .name = "wm5110-slim3",
1141 .id = 6,
1142 .playback = {
1143 .stream_name = "Slim3 Playback",
1144 .channels_min = 1,
1145 .channels_max = 2,
1146 .rates = WM5110_RATES,
1147 .formats = WM5110_FORMATS,
1148 },
1149 .capture = {
1150 .stream_name = "Slim3 Capture",
1151 .channels_min = 1,
1152 .channels_max = 2,
1153 .rates = WM5110_RATES,
1154 .formats = WM5110_FORMATS,
1155 },
1156 .ops = &arizona_simple_dai_ops,
1157 },
966}; 1158};
967 1159
968static int wm5110_codec_probe(struct snd_soc_codec *codec) 1160static int wm5110_codec_probe(struct snd_soc_codec *codec)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index e9710280e5e1..b1dc7d426438 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -51,6 +51,7 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = {
51 51
52/* codec private data */ 52/* codec private data */
53struct wm8962_priv { 53struct wm8962_priv {
54 struct wm8962_pdata pdata;
54 struct regmap *regmap; 55 struct regmap *regmap;
55 struct snd_soc_codec *codec; 56 struct snd_soc_codec *codec;
56 57
@@ -1600,7 +1601,6 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
1600 struct snd_ctl_elem_value *ucontrol) 1601 struct snd_ctl_elem_value *ucontrol)
1601{ 1602{
1602 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1603 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1603 u16 *reg_cache = codec->reg_cache;
1604 int ret; 1604 int ret;
1605 1605
1606 /* Apply the update (if any) */ 1606 /* Apply the update (if any) */
@@ -1609,16 +1609,19 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
1609 return 0; 1609 return 0;
1610 1610
1611 /* If the left PGA is enabled hit that VU bit... */ 1611 /* If the left PGA is enabled hit that VU bit... */
1612 if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTL_PGA_ENA) 1612 ret = snd_soc_read(codec, WM8962_PWR_MGMT_2);
1613 return snd_soc_write(codec, WM8962_HPOUTL_VOLUME, 1613 if (ret & WM8962_HPOUTL_PGA_ENA) {
1614 reg_cache[WM8962_HPOUTL_VOLUME]); 1614 snd_soc_write(codec, WM8962_HPOUTL_VOLUME,
1615 snd_soc_read(codec, WM8962_HPOUTL_VOLUME));
1616 return 1;
1617 }
1615 1618
1616 /* ...otherwise the right. The VU is stereo. */ 1619 /* ...otherwise the right. The VU is stereo. */
1617 if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTR_PGA_ENA) 1620 if (ret & WM8962_HPOUTR_PGA_ENA)
1618 return snd_soc_write(codec, WM8962_HPOUTR_VOLUME, 1621 snd_soc_write(codec, WM8962_HPOUTR_VOLUME,
1619 reg_cache[WM8962_HPOUTR_VOLUME]); 1622 snd_soc_read(codec, WM8962_HPOUTR_VOLUME));
1620 1623
1621 return 0; 1624 return 1;
1622} 1625}
1623 1626
1624/* The VU bits for the speakers are in a different register to the mute 1627/* The VU bits for the speakers are in a different register to the mute
@@ -2345,12 +2348,13 @@ static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = {
2345 2348
2346static int wm8962_add_widgets(struct snd_soc_codec *codec) 2349static int wm8962_add_widgets(struct snd_soc_codec *codec)
2347{ 2350{
2348 struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); 2351 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
2352 struct wm8962_pdata *pdata = &wm8962->pdata;
2349 struct snd_soc_dapm_context *dapm = &codec->dapm; 2353 struct snd_soc_dapm_context *dapm = &codec->dapm;
2350 2354
2351 snd_soc_add_codec_controls(codec, wm8962_snd_controls, 2355 snd_soc_add_codec_controls(codec, wm8962_snd_controls,
2352 ARRAY_SIZE(wm8962_snd_controls)); 2356 ARRAY_SIZE(wm8962_snd_controls));
2353 if (pdata && pdata->spk_mono) 2357 if (pdata->spk_mono)
2354 snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls, 2358 snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls,
2355 ARRAY_SIZE(wm8962_spk_mono_controls)); 2359 ARRAY_SIZE(wm8962_spk_mono_controls));
2356 else 2360 else
@@ -2360,7 +2364,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
2360 2364
2361 snd_soc_dapm_new_controls(dapm, wm8962_dapm_widgets, 2365 snd_soc_dapm_new_controls(dapm, wm8962_dapm_widgets,
2362 ARRAY_SIZE(wm8962_dapm_widgets)); 2366 ARRAY_SIZE(wm8962_dapm_widgets));
2363 if (pdata && pdata->spk_mono) 2367 if (pdata->spk_mono)
2364 snd_soc_dapm_new_controls(dapm, wm8962_dapm_spk_mono_widgets, 2368 snd_soc_dapm_new_controls(dapm, wm8962_dapm_spk_mono_widgets,
2365 ARRAY_SIZE(wm8962_dapm_spk_mono_widgets)); 2369 ARRAY_SIZE(wm8962_dapm_spk_mono_widgets));
2366 else 2370 else
@@ -2369,7 +2373,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
2369 2373
2370 snd_soc_dapm_add_routes(dapm, wm8962_intercon, 2374 snd_soc_dapm_add_routes(dapm, wm8962_intercon,
2371 ARRAY_SIZE(wm8962_intercon)); 2375 ARRAY_SIZE(wm8962_intercon));
2372 if (pdata && pdata->spk_mono) 2376 if (pdata->spk_mono)
2373 snd_soc_dapm_add_routes(dapm, wm8962_spk_mono_intercon, 2377 snd_soc_dapm_add_routes(dapm, wm8962_spk_mono_intercon,
2374 ARRAY_SIZE(wm8962_spk_mono_intercon)); 2378 ARRAY_SIZE(wm8962_spk_mono_intercon));
2375 else 2379 else
@@ -3333,14 +3337,14 @@ static struct gpio_chip wm8962_template_chip = {
3333static void wm8962_init_gpio(struct snd_soc_codec *codec) 3337static void wm8962_init_gpio(struct snd_soc_codec *codec)
3334{ 3338{
3335 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); 3339 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3336 struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); 3340 struct wm8962_pdata *pdata = &wm8962->pdata;
3337 int ret; 3341 int ret;
3338 3342
3339 wm8962->gpio_chip = wm8962_template_chip; 3343 wm8962->gpio_chip = wm8962_template_chip;
3340 wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO; 3344 wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO;
3341 wm8962->gpio_chip.dev = codec->dev; 3345 wm8962->gpio_chip.dev = codec->dev;
3342 3346
3343 if (pdata && pdata->gpio_base) 3347 if (pdata->gpio_base)
3344 wm8962->gpio_chip.base = pdata->gpio_base; 3348 wm8962->gpio_chip.base = pdata->gpio_base;
3345 else 3349 else
3346 wm8962->gpio_chip.base = -1; 3350 wm8962->gpio_chip.base = -1;
@@ -3374,7 +3378,6 @@ static int wm8962_probe(struct snd_soc_codec *codec)
3374 int ret; 3378 int ret;
3375 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); 3379 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3376 struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); 3380 struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
3377 u16 *reg_cache = codec->reg_cache;
3378 int i, trigger, irq_pol; 3381 int i, trigger, irq_pol;
3379 bool dmicclk, dmicdat; 3382 bool dmicclk, dmicdat;
3380 3383
@@ -3421,30 +3424,29 @@ static int wm8962_probe(struct snd_soc_codec *codec)
3421 WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA, 3424 WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
3422 0); 3425 0);
3423 3426
3424 if (pdata) { 3427 /* Apply static configuration for GPIOs */
3425 /* Apply static configuration for GPIOs */ 3428 for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++)
3426 for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) 3429 if (pdata->gpio_init[i]) {
3427 if (pdata->gpio_init[i]) { 3430 wm8962_set_gpio_mode(codec, i + 1);
3428 wm8962_set_gpio_mode(codec, i + 1); 3431 snd_soc_write(codec, 0x200 + i,
3429 snd_soc_write(codec, 0x200 + i, 3432 pdata->gpio_init[i] & 0xffff);
3430 pdata->gpio_init[i] & 0xffff); 3433 }
3431 }
3432 3434
3433 /* Put the speakers into mono mode? */
3434 if (pdata->spk_mono)
3435 reg_cache[WM8962_CLASS_D_CONTROL_2]
3436 |= WM8962_SPK_MONO;
3437 3435
3438 /* Micbias setup, detection enable and detection 3436 /* Put the speakers into mono mode? */
3439 * threasholds. */ 3437 if (pdata->spk_mono)
3440 if (pdata->mic_cfg) 3438 snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_2,
3441 snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4, 3439 WM8962_SPK_MONO_MASK, WM8962_SPK_MONO);
3442 WM8962_MICDET_ENA | 3440
3443 WM8962_MICDET_THR_MASK | 3441 /* Micbias setup, detection enable and detection
3444 WM8962_MICSHORT_THR_MASK | 3442 * threasholds. */
3445 WM8962_MICBIAS_LVL, 3443 if (pdata->mic_cfg)
3446 pdata->mic_cfg); 3444 snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4,
3447 } 3445 WM8962_MICDET_ENA |
3446 WM8962_MICDET_THR_MASK |
3447 WM8962_MICSHORT_THR_MASK |
3448 WM8962_MICBIAS_LVL,
3449 pdata->mic_cfg);
3448 3450
3449 /* Latch volume update bits */ 3451 /* Latch volume update bits */
3450 snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME, 3452 snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME,
@@ -3506,7 +3508,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
3506 wm8962_init_gpio(codec); 3508 wm8962_init_gpio(codec);
3507 3509
3508 if (wm8962->irq) { 3510 if (wm8962->irq) {
3509 if (pdata && pdata->irq_active_low) { 3511 if (pdata->irq_active_low) {
3510 trigger = IRQF_TRIGGER_LOW; 3512 trigger = IRQF_TRIGGER_LOW;
3511 irq_pol = WM8962_IRQ_POL; 3513 irq_pol = WM8962_IRQ_POL;
3512 } else { 3514 } else {
@@ -3584,6 +3586,34 @@ static const struct regmap_config wm8962_regmap = {
3584 .cache_type = REGCACHE_RBTREE, 3586 .cache_type = REGCACHE_RBTREE,
3585}; 3587};
3586 3588
3589static int wm8962_set_pdata_from_of(struct i2c_client *i2c,
3590 struct wm8962_pdata *pdata)
3591{
3592 const struct device_node *np = i2c->dev.of_node;
3593 u32 val32;
3594 int i;
3595
3596 if (of_property_read_bool(np, "spk-mono"))
3597 pdata->spk_mono = true;
3598
3599 if (of_property_read_u32(np, "mic-cfg", &val32) >= 0)
3600 pdata->mic_cfg = val32;
3601
3602 if (of_property_read_u32_array(np, "gpio-cfg", pdata->gpio_init,
3603 ARRAY_SIZE(pdata->gpio_init)) >= 0)
3604 for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) {
3605 /*
3606 * The range of GPIO register value is [0x0, 0xffff]
3607 * While the default value of each register is 0x0
3608 * Any other value will be regarded as default value
3609 */
3610 if (pdata->gpio_init[i] > 0xffff)
3611 pdata->gpio_init[i] = 0x0;
3612 }
3613
3614 return 0;
3615}
3616
3587static int wm8962_i2c_probe(struct i2c_client *i2c, 3617static int wm8962_i2c_probe(struct i2c_client *i2c,
3588 const struct i2c_device_id *id) 3618 const struct i2c_device_id *id)
3589{ 3619{
@@ -3603,6 +3633,15 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
3603 init_completion(&wm8962->fll_lock); 3633 init_completion(&wm8962->fll_lock);
3604 wm8962->irq = i2c->irq; 3634 wm8962->irq = i2c->irq;
3605 3635
3636 /* If platform data was supplied, update the default data in priv */
3637 if (pdata) {
3638 memcpy(&wm8962->pdata, pdata, sizeof(struct wm8962_pdata));
3639 } else if (i2c->dev.of_node) {
3640 ret = wm8962_set_pdata_from_of(i2c, &wm8962->pdata);
3641 if (ret != 0)
3642 return ret;
3643 }
3644
3606 for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) 3645 for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
3607 wm8962->supplies[i].supply = wm8962_supply_names[i]; 3646 wm8962->supplies[i].supply = wm8962_supply_names[i];
3608 3647
@@ -3666,7 +3705,7 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
3666 goto err_enable; 3705 goto err_enable;
3667 } 3706 }
3668 3707
3669 if (pdata && pdata->in4_dc_measure) { 3708 if (wm8962->pdata.in4_dc_measure) {
3670 ret = regmap_register_patch(wm8962->regmap, 3709 ret = regmap_register_patch(wm8962->regmap,
3671 wm8962_dc_measure, 3710 wm8962_dc_measure,
3672 ARRAY_SIZE(wm8962_dc_measure)); 3711 ARRAY_SIZE(wm8962_dc_measure));
@@ -3719,8 +3758,34 @@ static int wm8962_runtime_resume(struct device *dev)
3719 3758
3720 wm8962_reset(wm8962); 3759 wm8962_reset(wm8962);
3721 3760
3761 /* SYSCLK defaults to on; make sure it is off so we can safely
3762 * write to registers if the device is declocked.
3763 */
3764 regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2,
3765 WM8962_SYSCLK_ENA, 0);
3766
3767 /* Ensure we have soft control over all registers */
3768 regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2,
3769 WM8962_CLKREG_OVD, WM8962_CLKREG_OVD);
3770
3771 /* Ensure that the oscillator and PLLs are disabled */
3772 regmap_update_bits(wm8962->regmap, WM8962_PLL2,
3773 WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
3774 0);
3775
3722 regcache_sync(wm8962->regmap); 3776 regcache_sync(wm8962->regmap);
3723 3777
3778 regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP,
3779 WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA,
3780 WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA);
3781
3782 /* Bias enable at 2*5k (fast start-up) */
3783 regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
3784 WM8962_BIAS_ENA | WM8962_VMID_SEL_MASK,
3785 WM8962_BIAS_ENA | 0x180);
3786
3787 msleep(5);
3788
3724 return 0; 3789 return 0;
3725} 3790}
3726 3791
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 29e95f93d482..25580b5a853f 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -16,6 +16,7 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/pm.h> 18#include <linux/pm.h>
19#include <linux/gcd.h>
19#include <linux/i2c.h> 20#include <linux/i2c.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
21#include <linux/pm_runtime.h> 22#include <linux/pm_runtime.h>
@@ -1498,6 +1499,24 @@ static const char *aif1dac_text[] = {
1498 "AIF1DACDAT", "AIF3DACDAT", 1499 "AIF1DACDAT", "AIF3DACDAT",
1499}; 1500};
1500 1501
1502static const char *loopback_text[] = {
1503 "None", "ADCDAT",
1504};
1505
1506static const struct soc_enum aif1_loopback_enum =
1507 SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, WM8994_AIF1_LOOPBACK_SHIFT, 2,
1508 loopback_text);
1509
1510static const struct snd_kcontrol_new aif1_loopback =
1511 SOC_DAPM_ENUM("AIF1 Loopback", aif1_loopback_enum);
1512
1513static const struct soc_enum aif2_loopback_enum =
1514 SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, WM8994_AIF2_LOOPBACK_SHIFT, 2,
1515 loopback_text);
1516
1517static const struct snd_kcontrol_new aif2_loopback =
1518 SOC_DAPM_ENUM("AIF2 Loopback", aif2_loopback_enum);
1519
1501static const struct soc_enum aif1dac_enum = 1520static const struct soc_enum aif1dac_enum =
1502 SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text); 1521 SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text);
1503 1522
@@ -1744,6 +1763,9 @@ SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8994_POWER_MANAGEMENT_4, 2, 0),
1744SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), 1763SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0),
1745SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), 1764SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0),
1746 1765
1766SND_SOC_DAPM_MUX("AIF1 Loopback", SND_SOC_NOPM, 0, 0, &aif1_loopback),
1767SND_SOC_DAPM_MUX("AIF2 Loopback", SND_SOC_NOPM, 0, 0, &aif2_loopback),
1768
1747SND_SOC_DAPM_POST("Debug log", post_ev), 1769SND_SOC_DAPM_POST("Debug log", post_ev),
1748}; 1770};
1749 1771
@@ -1875,9 +1897,9 @@ static const struct snd_soc_dapm_route intercon[] = {
1875 { "AIF1DAC2L", NULL, "AIF1DAC Mux" }, 1897 { "AIF1DAC2L", NULL, "AIF1DAC Mux" },
1876 { "AIF1DAC2R", NULL, "AIF1DAC Mux" }, 1898 { "AIF1DAC2R", NULL, "AIF1DAC Mux" },
1877 1899
1878 { "AIF1DAC Mux", "AIF1DACDAT", "AIF1DACDAT" }, 1900 { "AIF1DAC Mux", "AIF1DACDAT", "AIF1 Loopback" },
1879 { "AIF1DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, 1901 { "AIF1DAC Mux", "AIF3DACDAT", "AIF3DACDAT" },
1880 { "AIF2DAC Mux", "AIF2DACDAT", "AIF2DACDAT" }, 1902 { "AIF2DAC Mux", "AIF2DACDAT", "AIF2 Loopback" },
1881 { "AIF2DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, 1903 { "AIF2DAC Mux", "AIF3DACDAT", "AIF3DACDAT" },
1882 { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCL" }, 1904 { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCL" },
1883 { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCR" }, 1905 { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCR" },
@@ -1928,6 +1950,12 @@ static const struct snd_soc_dapm_route intercon[] = {
1928 { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACL" }, 1950 { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACL" },
1929 { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACR" }, 1951 { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACR" },
1930 1952
1953 /* Loopback */
1954 { "AIF1 Loopback", "ADCDAT", "AIF1ADCDAT" },
1955 { "AIF1 Loopback", "None", "AIF1DACDAT" },
1956 { "AIF2 Loopback", "ADCDAT", "AIF2ADCDAT" },
1957 { "AIF2 Loopback", "None", "AIF2DACDAT" },
1958
1931 /* Sidetone */ 1959 /* Sidetone */
1932 { "Left Sidetone", "ADC/DMIC1", "ADCL Mux" }, 1960 { "Left Sidetone", "ADC/DMIC1", "ADCL Mux" },
1933 { "Left Sidetone", "DMIC2", "DMIC2L" }, 1961 { "Left Sidetone", "DMIC2", "DMIC2L" },
@@ -2010,15 +2038,16 @@ struct fll_div {
2010 u16 outdiv; 2038 u16 outdiv;
2011 u16 n; 2039 u16 n;
2012 u16 k; 2040 u16 k;
2041 u16 lambda;
2013 u16 clk_ref_div; 2042 u16 clk_ref_div;
2014 u16 fll_fratio; 2043 u16 fll_fratio;
2015}; 2044};
2016 2045
2017static int wm8994_get_fll_config(struct fll_div *fll, 2046static int wm8994_get_fll_config(struct wm8994 *control, struct fll_div *fll,
2018 int freq_in, int freq_out) 2047 int freq_in, int freq_out)
2019{ 2048{
2020 u64 Kpart; 2049 u64 Kpart;
2021 unsigned int K, Ndiv, Nmod; 2050 unsigned int K, Ndiv, Nmod, gcd_fll;
2022 2051
2023 pr_debug("FLL input=%dHz, output=%dHz\n", freq_in, freq_out); 2052 pr_debug("FLL input=%dHz, output=%dHz\n", freq_in, freq_out);
2024 2053
@@ -2067,20 +2096,32 @@ static int wm8994_get_fll_config(struct fll_div *fll,
2067 Nmod = freq_out % freq_in; 2096 Nmod = freq_out % freq_in;
2068 pr_debug("Nmod=%d\n", Nmod); 2097 pr_debug("Nmod=%d\n", Nmod);
2069 2098
2070 /* Calculate fractional part - scale up so we can round. */ 2099 switch (control->type) {
2071 Kpart = FIXED_FLL_SIZE * (long long)Nmod; 2100 case WM8994:
2101 /* Calculate fractional part - scale up so we can round. */
2102 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
2103
2104 do_div(Kpart, freq_in);
2105
2106 K = Kpart & 0xFFFFFFFF;
2072 2107
2073 do_div(Kpart, freq_in); 2108 if ((K % 10) >= 5)
2109 K += 5;
2074 2110
2075 K = Kpart & 0xFFFFFFFF; 2111 /* Move down to proper range now rounding is done */
2112 fll->k = K / 10;
2113 fll->lambda = 0;
2076 2114
2077 if ((K % 10) >= 5) 2115 pr_debug("N=%x K=%x\n", fll->n, fll->k);
2078 K += 5; 2116 break;
2079 2117
2080 /* Move down to proper range now rounding is done */ 2118 default:
2081 fll->k = K / 10; 2119 gcd_fll = gcd(freq_out, freq_in);
2082 2120
2083 pr_debug("N=%x K=%x\n", fll->n, fll->k); 2121 fll->k = (freq_out - (freq_in * fll->n)) / gcd_fll;
2122 fll->lambda = freq_in / gcd_fll;
2123
2124 }
2084 2125
2085 return 0; 2126 return 0;
2086} 2127}
@@ -2144,9 +2185,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
2144 * analysis bugs spewing warnings. 2185 * analysis bugs spewing warnings.
2145 */ 2186 */
2146 if (freq_out) 2187 if (freq_out)
2147 ret = wm8994_get_fll_config(&fll, freq_in, freq_out); 2188 ret = wm8994_get_fll_config(control, &fll, freq_in, freq_out);
2148 else 2189 else
2149 ret = wm8994_get_fll_config(&fll, wm8994->fll[id].in, 2190 ret = wm8994_get_fll_config(control, &fll, wm8994->fll[id].in,
2150 wm8994->fll[id].out); 2191 wm8994->fll[id].out);
2151 if (ret < 0) 2192 if (ret < 0)
2152 return ret; 2193 return ret;
@@ -2191,6 +2232,17 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
2191 WM8994_FLL1_N_MASK, 2232 WM8994_FLL1_N_MASK,
2192 fll.n << WM8994_FLL1_N_SHIFT); 2233 fll.n << WM8994_FLL1_N_SHIFT);
2193 2234
2235 if (fll.lambda) {
2236 snd_soc_update_bits(codec, WM8958_FLL1_EFS_1 + reg_offset,
2237 WM8958_FLL1_LAMBDA_MASK,
2238 fll.lambda);
2239 snd_soc_update_bits(codec, WM8958_FLL1_EFS_2 + reg_offset,
2240 WM8958_FLL1_EFS_ENA, WM8958_FLL1_EFS_ENA);
2241 } else {
2242 snd_soc_update_bits(codec, WM8958_FLL1_EFS_2 + reg_offset,
2243 WM8958_FLL1_EFS_ENA, 0);
2244 }
2245
2194 snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, 2246 snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset,
2195 WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | 2247 WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP |
2196 WM8994_FLL1_REFCLK_DIV_MASK | 2248 WM8994_FLL1_REFCLK_DIV_MASK |
@@ -2555,17 +2607,24 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2555 struct wm8994 *control = wm8994->wm8994; 2607 struct wm8994 *control = wm8994->wm8994;
2556 int ms_reg; 2608 int ms_reg;
2557 int aif1_reg; 2609 int aif1_reg;
2610 int dac_reg;
2611 int adc_reg;
2558 int ms = 0; 2612 int ms = 0;
2559 int aif1 = 0; 2613 int aif1 = 0;
2614 int lrclk = 0;
2560 2615
2561 switch (dai->id) { 2616 switch (dai->id) {
2562 case 1: 2617 case 1:
2563 ms_reg = WM8994_AIF1_MASTER_SLAVE; 2618 ms_reg = WM8994_AIF1_MASTER_SLAVE;
2564 aif1_reg = WM8994_AIF1_CONTROL_1; 2619 aif1_reg = WM8994_AIF1_CONTROL_1;
2620 dac_reg = WM8994_AIF1DAC_LRCLK;
2621 adc_reg = WM8994_AIF1ADC_LRCLK;
2565 break; 2622 break;
2566 case 2: 2623 case 2:
2567 ms_reg = WM8994_AIF2_MASTER_SLAVE; 2624 ms_reg = WM8994_AIF2_MASTER_SLAVE;
2568 aif1_reg = WM8994_AIF2_CONTROL_1; 2625 aif1_reg = WM8994_AIF2_CONTROL_1;
2626 dac_reg = WM8994_AIF1DAC_LRCLK;
2627 adc_reg = WM8994_AIF1ADC_LRCLK;
2569 break; 2628 break;
2570 default: 2629 default:
2571 return -EINVAL; 2630 return -EINVAL;
@@ -2584,6 +2643,7 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2584 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 2643 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
2585 case SND_SOC_DAIFMT_DSP_B: 2644 case SND_SOC_DAIFMT_DSP_B:
2586 aif1 |= WM8994_AIF1_LRCLK_INV; 2645 aif1 |= WM8994_AIF1_LRCLK_INV;
2646 lrclk |= WM8958_AIF1_LRCLK_INV;
2587 case SND_SOC_DAIFMT_DSP_A: 2647 case SND_SOC_DAIFMT_DSP_A:
2588 aif1 |= 0x18; 2648 aif1 |= 0x18;
2589 break; 2649 break;
@@ -2622,12 +2682,14 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2622 break; 2682 break;
2623 case SND_SOC_DAIFMT_IB_IF: 2683 case SND_SOC_DAIFMT_IB_IF:
2624 aif1 |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV; 2684 aif1 |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV;
2685 lrclk |= WM8958_AIF1_LRCLK_INV;
2625 break; 2686 break;
2626 case SND_SOC_DAIFMT_IB_NF: 2687 case SND_SOC_DAIFMT_IB_NF:
2627 aif1 |= WM8994_AIF1_BCLK_INV; 2688 aif1 |= WM8994_AIF1_BCLK_INV;
2628 break; 2689 break;
2629 case SND_SOC_DAIFMT_NB_IF: 2690 case SND_SOC_DAIFMT_NB_IF:
2630 aif1 |= WM8994_AIF1_LRCLK_INV; 2691 aif1 |= WM8994_AIF1_LRCLK_INV;
2692 lrclk |= WM8958_AIF1_LRCLK_INV;
2631 break; 2693 break;
2632 default: 2694 default:
2633 return -EINVAL; 2695 return -EINVAL;
@@ -2658,6 +2720,10 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2658 aif1); 2720 aif1);
2659 snd_soc_update_bits(codec, ms_reg, WM8994_AIF1_MSTR, 2721 snd_soc_update_bits(codec, ms_reg, WM8994_AIF1_MSTR,
2660 ms); 2722 ms);
2723 snd_soc_update_bits(codec, dac_reg,
2724 WM8958_AIF1_LRCLK_INV, lrclk);
2725 snd_soc_update_bits(codec, adc_reg,
2726 WM8958_AIF1_LRCLK_INV, lrclk);
2661 2727
2662 return 0; 2728 return 0;
2663} 2729}
@@ -3096,24 +3162,7 @@ static int wm8994_codec_suspend(struct snd_soc_codec *codec)
3096static int wm8994_codec_resume(struct snd_soc_codec *codec) 3162static int wm8994_codec_resume(struct snd_soc_codec *codec)
3097{ 3163{
3098 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 3164 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
3099 struct wm8994 *control = wm8994->wm8994;
3100 int i, ret; 3165 int i, ret;
3101 unsigned int val, mask;
3102
3103 if (control->revision < 4) {
3104 /* force a HW read */
3105 ret = regmap_read(control->regmap,
3106 WM8994_POWER_MANAGEMENT_5, &val);
3107
3108 /* modify the cache only */
3109 codec->cache_only = 1;
3110 mask = WM8994_DAC1R_ENA | WM8994_DAC1L_ENA |
3111 WM8994_DAC2R_ENA | WM8994_DAC2L_ENA;
3112 val &= mask;
3113 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5,
3114 mask, val);
3115 codec->cache_only = 0;
3116 }
3117 3166
3118 for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { 3167 for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
3119 if (!wm8994->fll_suspend[i].out) 3168 if (!wm8994->fll_suspend[i].out)
@@ -3495,6 +3544,31 @@ static void wm8958_button_det(struct snd_soc_codec *codec, u16 status)
3495 wm8994->btn_mask); 3544 wm8994->btn_mask);
3496} 3545}
3497 3546
3547static void wm8958_open_circuit_work(struct work_struct *work)
3548{
3549 struct wm8994_priv *wm8994 = container_of(work,
3550 struct wm8994_priv,
3551 open_circuit_work.work);
3552 struct device *dev = wm8994->wm8994->dev;
3553
3554 wm1811_micd_stop(wm8994->hubs.codec);
3555
3556 mutex_lock(&wm8994->accdet_lock);
3557
3558 dev_dbg(dev, "Reporting open circuit\n");
3559
3560 wm8994->jack_mic = false;
3561 wm8994->mic_detecting = true;
3562
3563 wm8958_micd_set_rate(wm8994->hubs.codec);
3564
3565 snd_soc_jack_report(wm8994->micdet[0].jack, 0,
3566 wm8994->btn_mask |
3567 SND_JACK_HEADSET);
3568
3569 mutex_unlock(&wm8994->accdet_lock);
3570}
3571
3498static void wm8958_mic_id(void *data, u16 status) 3572static void wm8958_mic_id(void *data, u16 status)
3499{ 3573{
3500 struct snd_soc_codec *codec = data; 3574 struct snd_soc_codec *codec = data;
@@ -3504,16 +3578,9 @@ static void wm8958_mic_id(void *data, u16 status)
3504 if (!(status & WM8958_MICD_STS)) { 3578 if (!(status & WM8958_MICD_STS)) {
3505 /* If nothing present then clear our statuses */ 3579 /* If nothing present then clear our statuses */
3506 dev_dbg(codec->dev, "Detected open circuit\n"); 3580 dev_dbg(codec->dev, "Detected open circuit\n");
3507 wm8994->jack_mic = false;
3508 wm8994->mic_detecting = true;
3509
3510 wm1811_micd_stop(codec);
3511
3512 wm8958_micd_set_rate(codec);
3513 3581
3514 snd_soc_jack_report(wm8994->micdet[0].jack, 0, 3582 schedule_delayed_work(&wm8994->open_circuit_work,
3515 wm8994->btn_mask | 3583 msecs_to_jiffies(2500));
3516 SND_JACK_HEADSET);
3517 return; 3584 return;
3518 } 3585 }
3519 3586
@@ -3598,6 +3665,8 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
3598 3665
3599 pm_runtime_get_sync(codec->dev); 3666 pm_runtime_get_sync(codec->dev);
3600 3667
3668 cancel_delayed_work_sync(&wm8994->mic_complete_work);
3669
3601 mutex_lock(&wm8994->accdet_lock); 3670 mutex_lock(&wm8994->accdet_lock);
3602 3671
3603 reg = snd_soc_read(codec, WM1811_JACKDET_CTRL); 3672 reg = snd_soc_read(codec, WM1811_JACKDET_CTRL);
@@ -3780,11 +3849,33 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
3780} 3849}
3781EXPORT_SYMBOL_GPL(wm8958_mic_detect); 3850EXPORT_SYMBOL_GPL(wm8958_mic_detect);
3782 3851
3852static void wm8958_mic_work(struct work_struct *work)
3853{
3854 struct wm8994_priv *wm8994 = container_of(work,
3855 struct wm8994_priv,
3856 mic_complete_work.work);
3857 struct snd_soc_codec *codec = wm8994->hubs.codec;
3858
3859 dev_crit(codec->dev, "MIC WORK %x\n", wm8994->mic_status);
3860
3861 pm_runtime_get_sync(codec->dev);
3862
3863 mutex_lock(&wm8994->accdet_lock);
3864
3865 wm8994->mic_id_cb(wm8994->mic_id_cb_data, wm8994->mic_status);
3866
3867 mutex_unlock(&wm8994->accdet_lock);
3868
3869 pm_runtime_put(codec->dev);
3870
3871 dev_crit(codec->dev, "MIC WORK %x DONE\n", wm8994->mic_status);
3872}
3873
3783static irqreturn_t wm8958_mic_irq(int irq, void *data) 3874static irqreturn_t wm8958_mic_irq(int irq, void *data)
3784{ 3875{
3785 struct wm8994_priv *wm8994 = data; 3876 struct wm8994_priv *wm8994 = data;
3786 struct snd_soc_codec *codec = wm8994->hubs.codec; 3877 struct snd_soc_codec *codec = wm8994->hubs.codec;
3787 int reg, count, ret; 3878 int reg, count, ret, id_delay;
3788 3879
3789 /* 3880 /*
3790 * Jack detection may have detected a removal simulataneously 3881 * Jack detection may have detected a removal simulataneously
@@ -3794,6 +3885,9 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
3794 if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) 3885 if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA))
3795 return IRQ_HANDLED; 3886 return IRQ_HANDLED;
3796 3887
3888 cancel_delayed_work_sync(&wm8994->mic_complete_work);
3889 cancel_delayed_work_sync(&wm8994->open_circuit_work);
3890
3797 pm_runtime_get_sync(codec->dev); 3891 pm_runtime_get_sync(codec->dev);
3798 3892
3799 /* We may occasionally read a detection without an impedence 3893 /* We may occasionally read a detection without an impedence
@@ -3846,8 +3940,12 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
3846 goto out; 3940 goto out;
3847 } 3941 }
3848 3942
3943 wm8994->mic_status = reg;
3944 id_delay = wm8994->wm8994->pdata.mic_id_delay;
3945
3849 if (wm8994->mic_detecting) 3946 if (wm8994->mic_detecting)
3850 wm8994->mic_id_cb(wm8994->mic_id_cb_data, reg); 3947 schedule_delayed_work(&wm8994->mic_complete_work,
3948 msecs_to_jiffies(id_delay));
3851 else 3949 else
3852 wm8958_button_det(codec, reg); 3950 wm8958_button_det(codec, reg);
3853 3951
@@ -3899,6 +3997,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3899 mutex_init(&wm8994->accdet_lock); 3997 mutex_init(&wm8994->accdet_lock);
3900 INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, 3998 INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap,
3901 wm1811_jackdet_bootstrap); 3999 wm1811_jackdet_bootstrap);
4000 INIT_DELAYED_WORK(&wm8994->open_circuit_work,
4001 wm8958_open_circuit_work);
3902 4002
3903 switch (control->type) { 4003 switch (control->type) {
3904 case WM8994: 4004 case WM8994:
@@ -3911,6 +4011,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3911 break; 4011 break;
3912 } 4012 }
3913 4013
4014 INIT_DELAYED_WORK(&wm8994->mic_complete_work, wm8958_mic_work);
4015
3914 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) 4016 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
3915 init_completion(&wm8994->fll_locked[i]); 4017 init_completion(&wm8994->fll_locked[i]);
3916 4018
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 55ddf4d57d9b..6536f8d45ac6 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -134,6 +134,9 @@ struct wm8994_priv {
134 struct mutex accdet_lock; 134 struct mutex accdet_lock;
135 struct wm8994_micdet micdet[2]; 135 struct wm8994_micdet micdet[2];
136 struct delayed_work mic_work; 136 struct delayed_work mic_work;
137 struct delayed_work open_circuit_work;
138 struct delayed_work mic_complete_work;
139 u16 mic_status;
137 bool mic_detecting; 140 bool mic_detecting;
138 bool jack_mic; 141 bool jack_mic;
139 int btn_mask; 142 int btn_mask;
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 3470b649c0b2..05252ac936a3 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -21,6 +21,7 @@
21#include <linux/regmap.h> 21#include <linux/regmap.h>
22#include <linux/regulator/consumer.h> 22#include <linux/regulator/consumer.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/workqueue.h>
24#include <sound/core.h> 25#include <sound/core.h>
25#include <sound/pcm.h> 26#include <sound/pcm.h>
26#include <sound/pcm_params.h> 27#include <sound/pcm_params.h>
@@ -215,6 +216,36 @@ static struct {
215 [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" }, 216 [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" },
216}; 217};
217 218
219struct wm_coeff_ctl_ops {
220 int (*xget)(struct snd_kcontrol *kcontrol,
221 struct snd_ctl_elem_value *ucontrol);
222 int (*xput)(struct snd_kcontrol *kcontrol,
223 struct snd_ctl_elem_value *ucontrol);
224 int (*xinfo)(struct snd_kcontrol *kcontrol,
225 struct snd_ctl_elem_info *uinfo);
226};
227
228struct wm_coeff {
229 struct device *dev;
230 struct list_head ctl_list;
231 struct regmap *regmap;
232};
233
234struct wm_coeff_ctl {
235 const char *name;
236 struct snd_card *card;
237 struct wm_adsp_alg_region region;
238 struct wm_coeff_ctl_ops ops;
239 struct wm_adsp *adsp;
240 void *private;
241 unsigned int enabled:1;
242 struct list_head list;
243 void *cache;
244 size_t len;
245 unsigned int set:1;
246 struct snd_kcontrol *kcontrol;
247};
248
218static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 249static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
219 struct snd_ctl_elem_value *ucontrol) 250 struct snd_ctl_elem_value *ucontrol)
220{ 251{
@@ -279,7 +310,7 @@ static const struct soc_enum wm_adsp2_rate_enum[] = {
279 ARIZONA_DSP1_RATE_SHIFT, 0xf, 310 ARIZONA_DSP1_RATE_SHIFT, 0xf,
280 ARIZONA_RATE_ENUM_SIZE, 311 ARIZONA_RATE_ENUM_SIZE,
281 arizona_rate_text, arizona_rate_val), 312 arizona_rate_text, arizona_rate_val),
282 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1, 313 SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP4_CONTROL_1,
283 ARIZONA_DSP1_RATE_SHIFT, 0xf, 314 ARIZONA_DSP1_RATE_SHIFT, 0xf,
284 ARIZONA_RATE_ENUM_SIZE, 315 ARIZONA_RATE_ENUM_SIZE,
285 arizona_rate_text, arizona_rate_val), 316 arizona_rate_text, arizona_rate_val),
@@ -334,6 +365,181 @@ static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *region,
334 } 365 }
335} 366}
336 367
368static int wm_coeff_info(struct snd_kcontrol *kcontrol,
369 struct snd_ctl_elem_info *uinfo)
370{
371 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
372
373 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
374 uinfo->count = ctl->len;
375 return 0;
376}
377
378static int wm_coeff_write_control(struct snd_kcontrol *kcontrol,
379 const void *buf, size_t len)
380{
381 struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol);
382 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
383 struct wm_adsp_alg_region *region = &ctl->region;
384 const struct wm_adsp_region *mem;
385 struct wm_adsp *adsp = ctl->adsp;
386 void *scratch;
387 int ret;
388 unsigned int reg;
389
390 mem = wm_adsp_find_region(adsp, region->type);
391 if (!mem) {
392 adsp_err(adsp, "No base for region %x\n",
393 region->type);
394 return -EINVAL;
395 }
396
397 reg = ctl->region.base;
398 reg = wm_adsp_region_to_reg(mem, reg);
399
400 scratch = kmemdup(buf, ctl->len, GFP_KERNEL | GFP_DMA);
401 if (!scratch)
402 return -ENOMEM;
403
404 ret = regmap_raw_write(wm_coeff->regmap, reg, scratch,
405 ctl->len);
406 if (ret) {
407 adsp_err(adsp, "Failed to write %zu bytes to %x\n",
408 ctl->len, reg);
409 kfree(scratch);
410 return ret;
411 }
412
413 kfree(scratch);
414
415 return 0;
416}
417
418static int wm_coeff_put(struct snd_kcontrol *kcontrol,
419 struct snd_ctl_elem_value *ucontrol)
420{
421 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
422 char *p = ucontrol->value.bytes.data;
423
424 memcpy(ctl->cache, p, ctl->len);
425
426 if (!ctl->enabled) {
427 ctl->set = 1;
428 return 0;
429 }
430
431 return wm_coeff_write_control(kcontrol, p, ctl->len);
432}
433
434static int wm_coeff_read_control(struct snd_kcontrol *kcontrol,
435 void *buf, size_t len)
436{
437 struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol);
438 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
439 struct wm_adsp_alg_region *region = &ctl->region;
440 const struct wm_adsp_region *mem;
441 struct wm_adsp *adsp = ctl->adsp;
442 void *scratch;
443 int ret;
444 unsigned int reg;
445
446 mem = wm_adsp_find_region(adsp, region->type);
447 if (!mem) {
448 adsp_err(adsp, "No base for region %x\n",
449 region->type);
450 return -EINVAL;
451 }
452
453 reg = ctl->region.base;
454 reg = wm_adsp_region_to_reg(mem, reg);
455
456 scratch = kmalloc(ctl->len, GFP_KERNEL | GFP_DMA);
457 if (!scratch)
458 return -ENOMEM;
459
460 ret = regmap_raw_read(wm_coeff->regmap, reg, scratch, ctl->len);
461 if (ret) {
462 adsp_err(adsp, "Failed to read %zu bytes from %x\n",
463 ctl->len, reg);
464 kfree(scratch);
465 return ret;
466 }
467
468 memcpy(buf, scratch, ctl->len);
469 kfree(scratch);
470
471 return 0;
472}
473
474static int wm_coeff_get(struct snd_kcontrol *kcontrol,
475 struct snd_ctl_elem_value *ucontrol)
476{
477 struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
478 char *p = ucontrol->value.bytes.data;
479
480 memcpy(p, ctl->cache, ctl->len);
481 return 0;
482}
483
484static int wm_coeff_add_kcontrol(struct wm_coeff *wm_coeff,
485 struct wm_coeff_ctl *ctl,
486 const struct snd_kcontrol_new *kctl)
487{
488 int ret;
489 struct snd_kcontrol *kcontrol;
490
491 kcontrol = snd_ctl_new1(kctl, wm_coeff);
492 ret = snd_ctl_add(ctl->card, kcontrol);
493 if (ret < 0) {
494 dev_err(wm_coeff->dev, "Failed to add %s: %d\n",
495 kctl->name, ret);
496 return ret;
497 }
498 ctl->kcontrol = kcontrol;
499 return 0;
500}
501
502struct wmfw_ctl_work {
503 struct wm_coeff *wm_coeff;
504 struct wm_coeff_ctl *ctl;
505 struct work_struct work;
506};
507
508static int wmfw_add_ctl(struct wm_coeff *wm_coeff,
509 struct wm_coeff_ctl *ctl)
510{
511 struct snd_kcontrol_new *kcontrol;
512 int ret;
513
514 if (!wm_coeff || !ctl || !ctl->name || !ctl->card)
515 return -EINVAL;
516
517 kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
518 if (!kcontrol)
519 return -ENOMEM;
520 kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
521
522 kcontrol->name = ctl->name;
523 kcontrol->info = wm_coeff_info;
524 kcontrol->get = wm_coeff_get;
525 kcontrol->put = wm_coeff_put;
526 kcontrol->private_value = (unsigned long)ctl;
527
528 ret = wm_coeff_add_kcontrol(wm_coeff,
529 ctl, kcontrol);
530 if (ret < 0)
531 goto err_kcontrol;
532
533 kfree(kcontrol);
534
535 list_add(&ctl->list, &wm_coeff->ctl_list);
536 return 0;
537
538err_kcontrol:
539 kfree(kcontrol);
540 return ret;
541}
542
337static int wm_adsp_load(struct wm_adsp *dsp) 543static int wm_adsp_load(struct wm_adsp *dsp)
338{ 544{
339 LIST_HEAD(buf_list); 545 LIST_HEAD(buf_list);
@@ -547,7 +753,157 @@ out:
547 return ret; 753 return ret;
548} 754}
549 755
550static int wm_adsp_setup_algs(struct wm_adsp *dsp) 756static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff)
757{
758 struct wm_coeff_ctl *ctl;
759 int ret;
760
761 list_for_each_entry(ctl, &wm_coeff->ctl_list,
762 list) {
763 if (!ctl->enabled || ctl->set)
764 continue;
765 ret = wm_coeff_read_control(ctl->kcontrol,
766 ctl->cache,
767 ctl->len);
768 if (ret < 0)
769 return ret;
770 }
771
772 return 0;
773}
774
775static int wm_coeff_sync_controls(struct wm_coeff *wm_coeff)
776{
777 struct wm_coeff_ctl *ctl;
778 int ret;
779
780 list_for_each_entry(ctl, &wm_coeff->ctl_list,
781 list) {
782 if (!ctl->enabled)
783 continue;
784 if (ctl->set) {
785 ret = wm_coeff_write_control(ctl->kcontrol,
786 ctl->cache,
787 ctl->len);
788 if (ret < 0)
789 return ret;
790 }
791 }
792
793 return 0;
794}
795
796static void wm_adsp_ctl_work(struct work_struct *work)
797{
798 struct wmfw_ctl_work *ctl_work = container_of(work,
799 struct wmfw_ctl_work,
800 work);
801
802 wmfw_add_ctl(ctl_work->wm_coeff, ctl_work->ctl);
803 kfree(ctl_work);
804}
805
806static int wm_adsp_create_control(struct snd_soc_codec *codec,
807 const struct wm_adsp_alg_region *region)
808
809{
810 struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
811 struct wm_coeff_ctl *ctl;
812 struct wmfw_ctl_work *ctl_work;
813 char *name;
814 char *region_name;
815 int ret;
816
817 name = kmalloc(PAGE_SIZE, GFP_KERNEL);
818 if (!name)
819 return -ENOMEM;
820
821 switch (region->type) {
822 case WMFW_ADSP1_PM:
823 region_name = "PM";
824 break;
825 case WMFW_ADSP1_DM:
826 region_name = "DM";
827 break;
828 case WMFW_ADSP2_XM:
829 region_name = "XM";
830 break;
831 case WMFW_ADSP2_YM:
832 region_name = "YM";
833 break;
834 case WMFW_ADSP1_ZM:
835 region_name = "ZM";
836 break;
837 default:
838 ret = -EINVAL;
839 goto err_name;
840 }
841
842 snprintf(name, PAGE_SIZE, "DSP%d %s %x",
843 dsp->num, region_name, region->alg);
844
845 list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list,
846 list) {
847 if (!strcmp(ctl->name, name)) {
848 if (!ctl->enabled)
849 ctl->enabled = 1;
850 goto found;
851 }
852 }
853
854 ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
855 if (!ctl) {
856 ret = -ENOMEM;
857 goto err_name;
858 }
859 ctl->region = *region;
860 ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL);
861 if (!ctl->name) {
862 ret = -ENOMEM;
863 goto err_ctl;
864 }
865 ctl->enabled = 1;
866 ctl->set = 0;
867 ctl->ops.xget = wm_coeff_get;
868 ctl->ops.xput = wm_coeff_put;
869 ctl->card = codec->card->snd_card;
870 ctl->adsp = dsp;
871
872 ctl->len = region->len;
873 ctl->cache = kzalloc(ctl->len, GFP_KERNEL);
874 if (!ctl->cache) {
875 ret = -ENOMEM;
876 goto err_ctl_name;
877 }
878
879 ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL);
880 if (!ctl_work) {
881 ret = -ENOMEM;
882 goto err_ctl_cache;
883 }
884
885 ctl_work->wm_coeff = dsp->wm_coeff;
886 ctl_work->ctl = ctl;
887 INIT_WORK(&ctl_work->work, wm_adsp_ctl_work);
888 schedule_work(&ctl_work->work);
889
890found:
891 kfree(name);
892
893 return 0;
894
895err_ctl_cache:
896 kfree(ctl->cache);
897err_ctl_name:
898 kfree(ctl->name);
899err_ctl:
900 kfree(ctl);
901err_name:
902 kfree(name);
903 return ret;
904}
905
906static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec)
551{ 907{
552 struct regmap *regmap = dsp->regmap; 908 struct regmap *regmap = dsp->regmap;
553 struct wmfw_adsp1_id_hdr adsp1_id; 909 struct wmfw_adsp1_id_hdr adsp1_id;
@@ -730,7 +1086,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
730 region->type = WMFW_ADSP1_DM; 1086 region->type = WMFW_ADSP1_DM;
731 region->alg = be32_to_cpu(adsp1_alg[i].alg.id); 1087 region->alg = be32_to_cpu(adsp1_alg[i].alg.id);
732 region->base = be32_to_cpu(adsp1_alg[i].dm); 1088 region->base = be32_to_cpu(adsp1_alg[i].dm);
1089 region->len = 0;
733 list_add_tail(&region->list, &dsp->alg_regions); 1090 list_add_tail(&region->list, &dsp->alg_regions);
1091 if (i + 1 < algs) {
1092 region->len = be32_to_cpu(adsp1_alg[i + 1].dm);
1093 region->len -= be32_to_cpu(adsp1_alg[i].dm);
1094 wm_adsp_create_control(codec, region);
1095 } else {
1096 adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
1097 be32_to_cpu(adsp1_alg[i].alg.id));
1098 }
734 1099
735 region = kzalloc(sizeof(*region), GFP_KERNEL); 1100 region = kzalloc(sizeof(*region), GFP_KERNEL);
736 if (!region) 1101 if (!region)
@@ -738,7 +1103,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
738 region->type = WMFW_ADSP1_ZM; 1103 region->type = WMFW_ADSP1_ZM;
739 region->alg = be32_to_cpu(adsp1_alg[i].alg.id); 1104 region->alg = be32_to_cpu(adsp1_alg[i].alg.id);
740 region->base = be32_to_cpu(adsp1_alg[i].zm); 1105 region->base = be32_to_cpu(adsp1_alg[i].zm);
1106 region->len = 0;
741 list_add_tail(&region->list, &dsp->alg_regions); 1107 list_add_tail(&region->list, &dsp->alg_regions);
1108 if (i + 1 < algs) {
1109 region->len = be32_to_cpu(adsp1_alg[i + 1].zm);
1110 region->len -= be32_to_cpu(adsp1_alg[i].zm);
1111 wm_adsp_create_control(codec, region);
1112 } else {
1113 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1114 be32_to_cpu(adsp1_alg[i].alg.id));
1115 }
742 break; 1116 break;
743 1117
744 case WMFW_ADSP2: 1118 case WMFW_ADSP2:
@@ -758,7 +1132,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
758 region->type = WMFW_ADSP2_XM; 1132 region->type = WMFW_ADSP2_XM;
759 region->alg = be32_to_cpu(adsp2_alg[i].alg.id); 1133 region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
760 region->base = be32_to_cpu(adsp2_alg[i].xm); 1134 region->base = be32_to_cpu(adsp2_alg[i].xm);
1135 region->len = 0;
761 list_add_tail(&region->list, &dsp->alg_regions); 1136 list_add_tail(&region->list, &dsp->alg_regions);
1137 if (i + 1 < algs) {
1138 region->len = be32_to_cpu(adsp2_alg[i + 1].xm);
1139 region->len -= be32_to_cpu(adsp2_alg[i].xm);
1140 wm_adsp_create_control(codec, region);
1141 } else {
1142 adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
1143 be32_to_cpu(adsp2_alg[i].alg.id));
1144 }
762 1145
763 region = kzalloc(sizeof(*region), GFP_KERNEL); 1146 region = kzalloc(sizeof(*region), GFP_KERNEL);
764 if (!region) 1147 if (!region)
@@ -766,7 +1149,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
766 region->type = WMFW_ADSP2_YM; 1149 region->type = WMFW_ADSP2_YM;
767 region->alg = be32_to_cpu(adsp2_alg[i].alg.id); 1150 region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
768 region->base = be32_to_cpu(adsp2_alg[i].ym); 1151 region->base = be32_to_cpu(adsp2_alg[i].ym);
1152 region->len = 0;
769 list_add_tail(&region->list, &dsp->alg_regions); 1153 list_add_tail(&region->list, &dsp->alg_regions);
1154 if (i + 1 < algs) {
1155 region->len = be32_to_cpu(adsp2_alg[i + 1].ym);
1156 region->len -= be32_to_cpu(adsp2_alg[i].ym);
1157 wm_adsp_create_control(codec, region);
1158 } else {
1159 adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
1160 be32_to_cpu(adsp2_alg[i].alg.id));
1161 }
770 1162
771 region = kzalloc(sizeof(*region), GFP_KERNEL); 1163 region = kzalloc(sizeof(*region), GFP_KERNEL);
772 if (!region) 1164 if (!region)
@@ -774,7 +1166,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
774 region->type = WMFW_ADSP2_ZM; 1166 region->type = WMFW_ADSP2_ZM;
775 region->alg = be32_to_cpu(adsp2_alg[i].alg.id); 1167 region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
776 region->base = be32_to_cpu(adsp2_alg[i].zm); 1168 region->base = be32_to_cpu(adsp2_alg[i].zm);
1169 region->len = 0;
777 list_add_tail(&region->list, &dsp->alg_regions); 1170 list_add_tail(&region->list, &dsp->alg_regions);
1171 if (i + 1 < algs) {
1172 region->len = be32_to_cpu(adsp2_alg[i + 1].zm);
1173 region->len -= be32_to_cpu(adsp2_alg[i].zm);
1174 wm_adsp_create_control(codec, region);
1175 } else {
1176 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1177 be32_to_cpu(adsp2_alg[i].alg.id));
1178 }
778 break; 1179 break;
779 } 1180 }
780 } 1181 }
@@ -986,6 +1387,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
986 struct snd_soc_codec *codec = w->codec; 1387 struct snd_soc_codec *codec = w->codec;
987 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 1388 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
988 struct wm_adsp *dsp = &dsps[w->shift]; 1389 struct wm_adsp *dsp = &dsps[w->shift];
1390 struct wm_coeff_ctl *ctl;
989 int ret; 1391 int ret;
990 int val; 1392 int val;
991 1393
@@ -1023,7 +1425,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
1023 if (ret != 0) 1425 if (ret != 0)
1024 goto err; 1426 goto err;
1025 1427
1026 ret = wm_adsp_setup_algs(dsp); 1428 ret = wm_adsp_setup_algs(dsp, codec);
1027 if (ret != 0) 1429 if (ret != 0)
1028 goto err; 1430 goto err;
1029 1431
@@ -1031,6 +1433,16 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
1031 if (ret != 0) 1433 if (ret != 0)
1032 goto err; 1434 goto err;
1033 1435
1436 /* Initialize caches for enabled and unset controls */
1437 ret = wm_coeff_init_control_caches(dsp->wm_coeff);
1438 if (ret != 0)
1439 goto err;
1440
1441 /* Sync set controls */
1442 ret = wm_coeff_sync_controls(dsp->wm_coeff);
1443 if (ret != 0)
1444 goto err;
1445
1034 /* Start the core running */ 1446 /* Start the core running */
1035 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 1447 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
1036 ADSP1_CORE_ENA | ADSP1_START, 1448 ADSP1_CORE_ENA | ADSP1_START,
@@ -1047,6 +1459,11 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
1047 1459
1048 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, 1460 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
1049 ADSP1_SYS_ENA, 0); 1461 ADSP1_SYS_ENA, 0);
1462
1463 list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list,
1464 list) {
1465 ctl->enabled = 0;
1466 }
1050 break; 1467 break;
1051 1468
1052 default: 1469 default:
@@ -1099,6 +1516,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1099 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 1516 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
1100 struct wm_adsp *dsp = &dsps[w->shift]; 1517 struct wm_adsp *dsp = &dsps[w->shift];
1101 struct wm_adsp_alg_region *alg_region; 1518 struct wm_adsp_alg_region *alg_region;
1519 struct wm_coeff_ctl *ctl;
1102 unsigned int val; 1520 unsigned int val;
1103 int ret; 1521 int ret;
1104 1522
@@ -1164,7 +1582,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1164 if (ret != 0) 1582 if (ret != 0)
1165 goto err; 1583 goto err;
1166 1584
1167 ret = wm_adsp_setup_algs(dsp); 1585 ret = wm_adsp_setup_algs(dsp, codec);
1168 if (ret != 0) 1586 if (ret != 0)
1169 goto err; 1587 goto err;
1170 1588
@@ -1172,6 +1590,16 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1172 if (ret != 0) 1590 if (ret != 0)
1173 goto err; 1591 goto err;
1174 1592
1593 /* Initialize caches for enabled and unset controls */
1594 ret = wm_coeff_init_control_caches(dsp->wm_coeff);
1595 if (ret != 0)
1596 goto err;
1597
1598 /* Sync set controls */
1599 ret = wm_coeff_sync_controls(dsp->wm_coeff);
1600 if (ret != 0)
1601 goto err;
1602
1175 ret = regmap_update_bits(dsp->regmap, 1603 ret = regmap_update_bits(dsp->regmap,
1176 dsp->base + ADSP2_CONTROL, 1604 dsp->base + ADSP2_CONTROL,
1177 ADSP2_CORE_ENA | ADSP2_START, 1605 ADSP2_CORE_ENA | ADSP2_START,
@@ -1209,6 +1637,11 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1209 ret); 1637 ret);
1210 } 1638 }
1211 1639
1640 list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list,
1641 list) {
1642 ctl->enabled = 0;
1643 }
1644
1212 while (!list_empty(&dsp->alg_regions)) { 1645 while (!list_empty(&dsp->alg_regions)) {
1213 alg_region = list_first_entry(&dsp->alg_regions, 1646 alg_region = list_first_entry(&dsp->alg_regions,
1214 struct wm_adsp_alg_region, 1647 struct wm_adsp_alg_region,
@@ -1247,36 +1680,48 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
1247 1680
1248 INIT_LIST_HEAD(&adsp->alg_regions); 1681 INIT_LIST_HEAD(&adsp->alg_regions);
1249 1682
1683 adsp->wm_coeff = kzalloc(sizeof(*adsp->wm_coeff),
1684 GFP_KERNEL);
1685 if (!adsp->wm_coeff)
1686 return -ENOMEM;
1687 adsp->wm_coeff->regmap = adsp->regmap;
1688 adsp->wm_coeff->dev = adsp->dev;
1689 INIT_LIST_HEAD(&adsp->wm_coeff->ctl_list);
1690
1250 if (dvfs) { 1691 if (dvfs) {
1251 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); 1692 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
1252 if (IS_ERR(adsp->dvfs)) { 1693 if (IS_ERR(adsp->dvfs)) {
1253 ret = PTR_ERR(adsp->dvfs); 1694 ret = PTR_ERR(adsp->dvfs);
1254 dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret); 1695 dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
1255 return ret; 1696 goto out_coeff;
1256 } 1697 }
1257 1698
1258 ret = regulator_enable(adsp->dvfs); 1699 ret = regulator_enable(adsp->dvfs);
1259 if (ret != 0) { 1700 if (ret != 0) {
1260 dev_err(adsp->dev, "Failed to enable DCVDD: %d\n", 1701 dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
1261 ret); 1702 ret);
1262 return ret; 1703 goto out_coeff;
1263 } 1704 }
1264 1705
1265 ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000); 1706 ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
1266 if (ret != 0) { 1707 if (ret != 0) {
1267 dev_err(adsp->dev, "Failed to initialise DVFS: %d\n", 1708 dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
1268 ret); 1709 ret);
1269 return ret; 1710 goto out_coeff;
1270 } 1711 }
1271 1712
1272 ret = regulator_disable(adsp->dvfs); 1713 ret = regulator_disable(adsp->dvfs);
1273 if (ret != 0) { 1714 if (ret != 0) {
1274 dev_err(adsp->dev, "Failed to disable DCVDD: %d\n", 1715 dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
1275 ret); 1716 ret);
1276 return ret; 1717 goto out_coeff;
1277 } 1718 }
1278 } 1719 }
1279 1720
1280 return 0; 1721 return 0;
1722
1723out_coeff:
1724 kfree(adsp->wm_coeff);
1725 return ret;
1281} 1726}
1282EXPORT_SYMBOL_GPL(wm_adsp2_init); 1727EXPORT_SYMBOL_GPL(wm_adsp2_init);
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index fea514627526..6e890b916592 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -30,6 +30,7 @@ struct wm_adsp_alg_region {
30 unsigned int alg; 30 unsigned int alg;
31 int type; 31 int type;
32 unsigned int base; 32 unsigned int base;
33 size_t len;
33}; 34};
34 35
35struct wm_adsp { 36struct wm_adsp {
@@ -55,6 +56,8 @@ struct wm_adsp {
55 bool running; 56 bool running;
56 57
57 struct regulator *dvfs; 58 struct regulator *dvfs;
59
60 struct wm_coeff *wm_coeff;
58}; 61};
59 62
60#define WM_ADSP1(wname, num) \ 63#define WM_ADSP1(wname, num) \
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 9e11a14d1b45..c82f89c9475b 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -54,16 +54,6 @@ config SND_DM6467_SOC_EVM
54 help 54 help
55 Say Y if you want to add support for SoC audio on TI 55 Say Y if you want to add support for SoC audio on TI
56 56
57config SND_DAVINCI_SOC_SFFSDR
58 tristate "SoC Audio support for SFFSDR"
59 depends on SND_DAVINCI_SOC && MACH_SFFSDR
60 select SND_DAVINCI_SOC_I2S
61 select SND_SOC_PCM3008
62 select SFFSDR_FPGA
63 help
64 Say Y if you want to add support for SoC audio on
65 Lyrtech SFFSDR board.
66
67config SND_DA830_SOC_EVM 57config SND_DA830_SOC_EVM
68 tristate "SoC Audio support for DA830/OMAP-L137 EVM" 58 tristate "SoC Audio support for DA830/OMAP-L137 EVM"
69 depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM 59 depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index a93679d618cd..a396ab6d6d5e 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -11,10 +11,8 @@ obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o
11 11
12# DAVINCI Machine Support 12# DAVINCI Machine Support
13snd-soc-evm-objs := davinci-evm.o 13snd-soc-evm-objs := davinci-evm.o
14snd-soc-sffsdr-objs := davinci-sffsdr.o
15 14
16obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o 15obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
17obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o 16obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o
18obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o 17obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o
19obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o 18obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o
20obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 81490febac6d..32ddb7fe5034 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -1024,7 +1024,7 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
1024 struct device_node *np = pdev->dev.of_node; 1024 struct device_node *np = pdev->dev.of_node;
1025 struct snd_platform_data *pdata = NULL; 1025 struct snd_platform_data *pdata = NULL;
1026 const struct of_device_id *match = 1026 const struct of_device_id *match =
1027 of_match_device(of_match_ptr(mcasp_dt_ids), &pdev->dev); 1027 of_match_device(mcasp_dt_ids, &pdev->dev);
1028 1028
1029 const u32 *of_serial_dir32; 1029 const u32 *of_serial_dir32;
1030 u8 *of_serial_dir; 1030 u8 *of_serial_dir;
@@ -1257,7 +1257,7 @@ static struct platform_driver davinci_mcasp_driver = {
1257 .driver = { 1257 .driver = {
1258 .name = "davinci-mcasp", 1258 .name = "davinci-mcasp",
1259 .owner = THIS_MODULE, 1259 .owner = THIS_MODULE,
1260 .of_match_table = of_match_ptr(mcasp_dt_ids), 1260 .of_match_table = mcasp_dt_ids,
1261 }, 1261 },
1262}; 1262};
1263 1263
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c
deleted file mode 100644
index 5be65aae7e0e..000000000000
--- a/sound/soc/davinci/davinci-sffsdr.c
+++ /dev/null
@@ -1,181 +0,0 @@
1/*
2 * ASoC driver for Lyrtech SFFSDR board.
3 *
4 * Author: Hugo Villeneuve
5 * Copyright (C) 2008 Lyrtech inc
6 *
7 * Based on ASoC driver for TI DAVINCI EVM platform, original copyright follow:
8 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/timer.h>
18#include <linux/interrupt.h>
19#include <linux/platform_device.h>
20#include <linux/gpio.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/soc.h>
24
25#include <asm/dma.h>
26#include <asm/mach-types.h>
27#ifdef CONFIG_SFFSDR_FPGA
28#include <asm/plat-sffsdr/sffsdr-fpga.h>
29#endif
30
31#include <mach/edma.h>
32
33#include "../codecs/pcm3008.h"
34#include "davinci-pcm.h"
35#include "davinci-i2s.h"
36
37/*
38 * CLKX and CLKR are the inputs for the Sample Rate Generator.
39 * FSX and FSR are outputs, driven by the sample Rate Generator.
40 */
41#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
42 SND_SOC_DAIFMT_CBM_CFS | \
43 SND_SOC_DAIFMT_IB_NF)
44
45static int sffsdr_hw_params(struct snd_pcm_substream *substream,
46 struct snd_pcm_hw_params *params)
47{
48 struct snd_soc_pcm_runtime *rtd = substream->private_data;
49 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
50 int fs;
51 int ret = 0;
52
53 /* Fsref can be 32000, 44100 or 48000. */
54 fs = params_rate(params);
55
56#ifndef CONFIG_SFFSDR_FPGA
57 /* Without the FPGA module, the Fs is fixed at 44100 Hz */
58 if (fs != 44100) {
59 pr_debug("warning: only 44.1 kHz is supported without SFFSDR FPGA module\n");
60 return -EINVAL;
61 }
62#endif
63
64 /* set cpu DAI configuration */
65 ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
66 if (ret < 0)
67 return ret;
68
69 pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs);
70
71#ifndef CONFIG_SFFSDR_FPGA
72 return 0;
73#else
74 return sffsdr_fpga_set_codec_fs(fs);
75#endif
76}
77
78static struct snd_soc_ops sffsdr_ops = {
79 .hw_params = sffsdr_hw_params,
80};
81
82/* davinci-sffsdr digital audio interface glue - connects codec <--> CPU */
83static struct snd_soc_dai_link sffsdr_dai = {
84 .name = "PCM3008", /* Codec name */
85 .stream_name = "PCM3008 HiFi",
86 .cpu_dai_name = "davinci-mcbsp",
87 .codec_dai_name = "pcm3008-hifi",
88 .codec_name = "pcm3008-codec",
89 .platform_name = "davinci-mcbsp",
90 .ops = &sffsdr_ops,
91};
92
93/* davinci-sffsdr audio machine driver */
94static struct snd_soc_card snd_soc_sffsdr = {
95 .name = "DaVinci SFFSDR",
96 .owner = THIS_MODULE,
97 .dai_link = &sffsdr_dai,
98 .num_links = 1,
99};
100
101/* sffsdr audio private data */
102static struct pcm3008_setup_data sffsdr_pcm3008_setup = {
103 .dem0_pin = GPIO(45),
104 .dem1_pin = GPIO(46),
105 .pdad_pin = GPIO(47),
106 .pdda_pin = GPIO(38),
107};
108
109struct platform_device pcm3008_codec = {
110 .name = "pcm3008-codec",
111 .id = 0,
112 .dev = {
113 .platform_data = &sffsdr_pcm3008_setup,
114 },
115};
116
117static struct resource sffsdr_snd_resources[] = {
118 {
119 .start = DAVINCI_MCBSP_BASE,
120 .end = DAVINCI_MCBSP_BASE + SZ_8K - 1,
121 .flags = IORESOURCE_MEM,
122 },
123};
124
125static struct evm_snd_platform_data sffsdr_snd_data = {
126 .tx_dma_ch = DAVINCI_DMA_MCBSP_TX,
127 .rx_dma_ch = DAVINCI_DMA_MCBSP_RX,
128};
129
130static struct platform_device *sffsdr_snd_device;
131
132static int __init sffsdr_init(void)
133{
134 int ret;
135
136 if (!machine_is_sffsdr())
137 return -EINVAL;
138
139 platform_device_register(&pcm3008_codec);
140
141 sffsdr_snd_device = platform_device_alloc("soc-audio", 0);
142 if (!sffsdr_snd_device) {
143 printk(KERN_ERR "platform device allocation failed\n");
144 return -ENOMEM;
145 }
146
147 platform_set_drvdata(sffsdr_snd_device, &snd_soc_sffsdr);
148 platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data,
149 sizeof(sffsdr_snd_data));
150
151 ret = platform_device_add_resources(sffsdr_snd_device,
152 sffsdr_snd_resources,
153 ARRAY_SIZE(sffsdr_snd_resources));
154 if (ret) {
155 printk(KERN_ERR "platform device add resources failed\n");
156 goto error;
157 }
158
159 ret = platform_device_add(sffsdr_snd_device);
160 if (ret)
161 goto error;
162
163 return ret;
164
165error:
166 platform_device_put(sffsdr_snd_device);
167 return ret;
168}
169
170static void __exit sffsdr_exit(void)
171{
172 platform_device_unregister(sffsdr_snd_device);
173 platform_device_unregister(&pcm3008_codec);
174}
175
176module_init(sffsdr_init);
177module_exit(sffsdr_exit);
178
179MODULE_AUTHOR("Hugo Villeneuve");
180MODULE_DESCRIPTION("Lyrtech SFFSDR ASoC driver");
181MODULE_LICENSE("GPL");
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
index 593a3ea12d4c..70eb37a5dd16 100644
--- a/sound/soc/dwc/designware_i2s.c
+++ b/sound/soc/dwc/designware_i2s.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * ALSA SoC Synopsys I2S Audio Layer 2 * ALSA SoC Synopsys I2S Audio Layer
3 * 3 *
4 * sound/soc/spear/designware_i2s.c 4 * sound/soc/dwc/designware_i2s.c
5 * 5 *
6 * Copyright (C) 2010 ST Microelectronics 6 * Copyright (C) 2010 ST Microelectronics
7 * Rajeev Kumar <rajeev-dlh.kumar@st.com> 7 * Rajeev Kumar <rajeev-dlh.kumar@st.com>
@@ -396,7 +396,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
396 } 396 }
397 397
398 if (cap & DWC_I2S_PLAY) { 398 if (cap & DWC_I2S_PLAY) {
399 dev_dbg(&pdev->dev, " SPEAr: play supported\n"); 399 dev_dbg(&pdev->dev, " designware: play supported\n");
400 dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM; 400 dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM;
401 dw_i2s_dai->playback.channels_max = pdata->channel; 401 dw_i2s_dai->playback.channels_max = pdata->channel;
402 dw_i2s_dai->playback.formats = pdata->snd_fmts; 402 dw_i2s_dai->playback.formats = pdata->snd_fmts;
@@ -404,7 +404,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
404 } 404 }
405 405
406 if (cap & DWC_I2S_RECORD) { 406 if (cap & DWC_I2S_RECORD) {
407 dev_dbg(&pdev->dev, "SPEAr: record supported\n"); 407 dev_dbg(&pdev->dev, "designware: record supported\n");
408 dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; 408 dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM;
409 dw_i2s_dai->capture.channels_max = pdata->channel; 409 dw_i2s_dai->capture.channels_max = pdata->channel;
410 dw_i2s_dai->capture.formats = pdata->snd_fmts; 410 dw_i2s_dai->capture.formats = pdata->snd_fmts;
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 3843a18d4e56..aa438546c912 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -108,18 +108,13 @@ if SND_IMX_SOC
108config SND_SOC_IMX_SSI 108config SND_SOC_IMX_SSI
109 tristate 109 tristate
110 110
111config SND_SOC_IMX_PCM
112 tristate
113
114config SND_SOC_IMX_PCM_FIQ 111config SND_SOC_IMX_PCM_FIQ
115 bool 112 bool
116 select FIQ 113 select FIQ
117 select SND_SOC_IMX_PCM
118 114
119config SND_SOC_IMX_PCM_DMA 115config SND_SOC_IMX_PCM_DMA
120 bool 116 bool
121 select SND_SOC_GENERIC_DMAENGINE_PCM 117 select SND_SOC_GENERIC_DMAENGINE_PCM
122 select SND_SOC_IMX_PCM
123 118
124config SND_SOC_IMX_AUDMUX 119config SND_SOC_IMX_AUDMUX
125 tristate 120 tristate
@@ -173,6 +168,18 @@ config SND_SOC_EUKREA_TLV320
173 Enable I2S based access to the TLV320AIC23B codec attached 168 Enable I2S based access to the TLV320AIC23B codec attached
174 to the SSI interface 169 to the SSI interface
175 170
171config SND_SOC_IMX_WM8962
172 tristate "SoC Audio support for i.MX boards with wm8962"
173 depends on OF && I2C
174 select SND_SOC_WM8962
175 select SND_SOC_IMX_PCM_DMA
176 select SND_SOC_IMX_AUDMUX
177 select SND_SOC_FSL_SSI
178 select SND_SOC_FSL_UTILS
179 help
180 Say Y if you want to add support for SoC audio on an i.MX board with
181 a wm8962 codec.
182
176config SND_SOC_IMX_SGTL5000 183config SND_SOC_IMX_SGTL5000
177 tristate "SoC Audio support for i.MX boards with sgtl5000" 184 tristate "SoC Audio support for i.MX boards with sgtl5000"
178 depends on OF && I2C 185 depends on OF && I2C
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index afd34794db53..d4b4aa8b5649 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -30,18 +30,11 @@ obj-$(CONFIG_SND_MPC52xx_SOC_EFIKA) += efika-audio-fabric.o
30# i.MX Platform Support 30# i.MX Platform Support
31snd-soc-imx-ssi-objs := imx-ssi.o 31snd-soc-imx-ssi-objs := imx-ssi.o
32snd-soc-imx-audmux-objs := imx-audmux.o 32snd-soc-imx-audmux-objs := imx-audmux.o
33snd-soc-imx-pcm-objs := imx-pcm.o
34ifneq ($(CONFIG_SND_SOC_IMX_PCM_FIQ),)
35 snd-soc-imx-pcm-objs += imx-pcm-fiq.o
36endif
37ifneq ($(CONFIG_SND_SOC_IMX_PCM_DMA),)
38 snd-soc-imx-pcm-objs += imx-pcm-dma.o
39endif
40
41obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o 33obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
42obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o 34obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
43 35
44obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o 36obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o
37obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o
45 38
46# i.MX Machine Support 39# i.MX Machine Support
47snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o 40snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
@@ -49,6 +42,7 @@ snd-soc-phycore-ac97-objs := phycore-ac97.o
49snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o 42snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
50snd-soc-wm1133-ev1-objs := wm1133-ev1.o 43snd-soc-wm1133-ev1-objs := wm1133-ev1.o
51snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o 44snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
45snd-soc-imx-wm8962-objs := imx-wm8962.o
52snd-soc-imx-mc13783-objs := imx-mc13783.o 46snd-soc-imx-mc13783-objs := imx-mc13783.o
53 47
54obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o 48obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
@@ -56,4 +50,5 @@ obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
56obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o 50obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o
57obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o 51obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
58obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o 52obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
53obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o
59obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o 54obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o
diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c
index 75ffdf0e2aad..9a4a0ca2c1de 100644
--- a/sound/soc/fsl/eukrea-tlv320.c
+++ b/sound/soc/fsl/eukrea-tlv320.c
@@ -80,7 +80,7 @@ static struct snd_soc_dai_link eukrea_tlv320_dai = {
80 .name = "tlv320aic23", 80 .name = "tlv320aic23",
81 .stream_name = "TLV320AIC23", 81 .stream_name = "TLV320AIC23",
82 .codec_dai_name = "tlv320aic23-hifi", 82 .codec_dai_name = "tlv320aic23-hifi",
83 .platform_name = "imx-fiq-pcm-audio.0", 83 .platform_name = "imx-ssi.0",
84 .codec_name = "tlv320aic23-codec.0-001a", 84 .codec_name = "tlv320aic23-codec.0-001a",
85 .cpu_dai_name = "imx-ssi.0", 85 .cpu_dai_name = "imx-ssi.0",
86 .ops = &eukrea_tlv320_snd_ops, 86 .ops = &eukrea_tlv320_snd_ops,
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 0f0bed6def9e..2f2d837df07f 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -122,7 +122,6 @@ struct fsl_ssi_private {
122 bool new_binding; 122 bool new_binding;
123 bool ssi_on_imx; 123 bool ssi_on_imx;
124 struct clk *clk; 124 struct clk *clk;
125 struct platform_device *imx_pcm_pdev;
126 struct snd_dmaengine_dai_dma_data dma_params_tx; 125 struct snd_dmaengine_dai_dma_data dma_params_tx;
127 struct snd_dmaengine_dai_dma_data dma_params_rx; 126 struct snd_dmaengine_dai_dma_data dma_params_rx;
128 struct imx_dma_data filter_data_tx; 127 struct imx_dma_data filter_data_tx;
@@ -809,13 +808,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
809 } 808 }
810 809
811 if (ssi_private->ssi_on_imx) { 810 if (ssi_private->ssi_on_imx) {
812 ssi_private->imx_pcm_pdev = 811 ret = imx_pcm_dma_init(pdev);
813 platform_device_register_simple("imx-pcm-audio", 812 if (ret)
814 -1, NULL, 0);
815 if (IS_ERR(ssi_private->imx_pcm_pdev)) {
816 ret = PTR_ERR(ssi_private->imx_pcm_pdev);
817 goto error_dev; 813 goto error_dev;
818 }
819 } 814 }
820 815
821 /* 816 /*
@@ -854,7 +849,7 @@ done:
854 849
855error_dai: 850error_dai:
856 if (ssi_private->ssi_on_imx) 851 if (ssi_private->ssi_on_imx)
857 platform_device_unregister(ssi_private->imx_pcm_pdev); 852 imx_pcm_dma_exit(pdev);
858 snd_soc_unregister_component(&pdev->dev); 853 snd_soc_unregister_component(&pdev->dev);
859 854
860error_dev: 855error_dev:
@@ -889,7 +884,7 @@ static int fsl_ssi_remove(struct platform_device *pdev)
889 if (!ssi_private->new_binding) 884 if (!ssi_private->new_binding)
890 platform_device_unregister(ssi_private->pdev); 885 platform_device_unregister(ssi_private->pdev);
891 if (ssi_private->ssi_on_imx) { 886 if (ssi_private->ssi_on_imx) {
892 platform_device_unregister(ssi_private->imx_pcm_pdev); 887 imx_pcm_dma_exit(pdev);
893 clk_disable_unprepare(ssi_private->clk); 888 clk_disable_unprepare(ssi_private->clk);
894 clk_put(ssi_private->clk); 889 clk_put(ssi_private->clk);
895 } 890 }
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index 47f046a8fdab..e260f1f899db 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -26,7 +26,6 @@
26#include <linux/of_device.h> 26#include <linux/of_device.h>
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/slab.h> 28#include <linux/slab.h>
29#include <linux/pinctrl/consumer.h>
30 29
31#include "imx-audmux.h" 30#include "imx-audmux.h"
32 31
@@ -247,7 +246,6 @@ EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
247static int imx_audmux_probe(struct platform_device *pdev) 246static int imx_audmux_probe(struct platform_device *pdev)
248{ 247{
249 struct resource *res; 248 struct resource *res;
250 struct pinctrl *pinctrl;
251 const struct of_device_id *of_id = 249 const struct of_device_id *of_id =
252 of_match_device(imx_audmux_dt_ids, &pdev->dev); 250 of_match_device(imx_audmux_dt_ids, &pdev->dev);
253 251
@@ -256,12 +254,6 @@ static int imx_audmux_probe(struct platform_device *pdev)
256 if (IS_ERR(audmux_base)) 254 if (IS_ERR(audmux_base))
257 return PTR_ERR(audmux_base); 255 return PTR_ERR(audmux_base);
258 256
259 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
260 if (IS_ERR(pinctrl)) {
261 dev_err(&pdev->dev, "setup pinctrl failed!");
262 return PTR_ERR(pinctrl);
263 }
264
265 audmux_clk = devm_clk_get(&pdev->dev, "audmux"); 257 audmux_clk = devm_clk_get(&pdev->dev, "audmux");
266 if (IS_ERR(audmux_clk)) { 258 if (IS_ERR(audmux_clk)) {
267 dev_dbg(&pdev->dev, "cannot get clock: %ld\n", 259 dev_dbg(&pdev->dev, "cannot get clock: %ld\n",
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c
index 4ae30f21fdb5..9df173c091a6 100644
--- a/sound/soc/fsl/imx-mc13783.c
+++ b/sound/soc/fsl/imx-mc13783.c
@@ -64,7 +64,7 @@ static struct snd_soc_dai_link imx_mc13783_dai_mc13783[] = {
64 .codec_dai_name = "mc13783-hifi", 64 .codec_dai_name = "mc13783-hifi",
65 .codec_name = "mc13783-codec", 65 .codec_name = "mc13783-codec",
66 .cpu_dai_name = "imx-ssi.0", 66 .cpu_dai_name = "imx-ssi.0",
67 .platform_name = "imx-pcm-audio.0", 67 .platform_name = "imx-ssi.0",
68 .ops = &imx_mc13783_hifi_ops, 68 .ops = &imx_mc13783_hifi_ops,
69 .symmetric_rates = 1, 69 .symmetric_rates = 1,
70 .dai_fmt = FMT_SSI, 70 .dai_fmt = FMT_SSI,
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index c246fb514930..fde4d2ea68c8 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -67,8 +67,10 @@ int imx_pcm_dma_init(struct platform_device *pdev)
67 SND_DMAENGINE_PCM_FLAG_NO_DT | 67 SND_DMAENGINE_PCM_FLAG_NO_DT |
68 SND_DMAENGINE_PCM_FLAG_COMPAT); 68 SND_DMAENGINE_PCM_FLAG_COMPAT);
69} 69}
70EXPORT_SYMBOL_GPL(imx_pcm_dma_init);
70 71
71void imx_pcm_dma_exit(struct platform_device *pdev) 72void imx_pcm_dma_exit(struct platform_device *pdev)
72{ 73{
73 snd_dmaengine_pcm_unregister(&pdev->dev); 74 snd_dmaengine_pcm_unregister(&pdev->dev);
74} 75}
76EXPORT_SYMBOL_GPL(imx_pcm_dma_exit);
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
index 670b96b0ce2f..310d90290320 100644
--- a/sound/soc/fsl/imx-pcm-fiq.c
+++ b/sound/soc/fsl/imx-pcm-fiq.c
@@ -225,6 +225,22 @@ static int snd_imx_close(struct snd_pcm_substream *substream)
225 return 0; 225 return 0;
226} 226}
227 227
228static int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
229 struct vm_area_struct *vma)
230{
231 struct snd_pcm_runtime *runtime = substream->runtime;
232 int ret;
233
234 ret = dma_mmap_writecombine(substream->pcm->card->dev, vma,
235 runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
236
237 pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret,
238 runtime->dma_area,
239 runtime->dma_addr,
240 runtime->dma_bytes);
241 return ret;
242}
243
228static struct snd_pcm_ops imx_pcm_ops = { 244static struct snd_pcm_ops imx_pcm_ops = {
229 .open = snd_imx_open, 245 .open = snd_imx_open,
230 .close = snd_imx_close, 246 .close = snd_imx_close,
@@ -236,6 +252,54 @@ static struct snd_pcm_ops imx_pcm_ops = {
236 .mmap = snd_imx_pcm_mmap, 252 .mmap = snd_imx_pcm_mmap,
237}; 253};
238 254
255static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
256{
257 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
258 struct snd_dma_buffer *buf = &substream->dma_buffer;
259 size_t size = IMX_SSI_DMABUF_SIZE;
260
261 buf->dev.type = SNDRV_DMA_TYPE_DEV;
262 buf->dev.dev = pcm->card->dev;
263 buf->private_data = NULL;
264 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
265 &buf->addr, GFP_KERNEL);
266 if (!buf->area)
267 return -ENOMEM;
268 buf->bytes = size;
269
270 return 0;
271}
272
273static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
274
275static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
276{
277 struct snd_card *card = rtd->card->snd_card;
278 struct snd_pcm *pcm = rtd->pcm;
279 int ret = 0;
280
281 if (!card->dev->dma_mask)
282 card->dev->dma_mask = &imx_pcm_dmamask;
283 if (!card->dev->coherent_dma_mask)
284 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
285 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
286 ret = imx_pcm_preallocate_dma_buffer(pcm,
287 SNDRV_PCM_STREAM_PLAYBACK);
288 if (ret)
289 goto out;
290 }
291
292 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
293 ret = imx_pcm_preallocate_dma_buffer(pcm,
294 SNDRV_PCM_STREAM_CAPTURE);
295 if (ret)
296 goto out;
297 }
298
299out:
300 return ret;
301}
302
239static int ssi_irq = 0; 303static int ssi_irq = 0;
240 304
241static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd) 305static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd)
@@ -268,6 +332,27 @@ static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd)
268 return 0; 332 return 0;
269} 333}
270 334
335static void imx_pcm_free(struct snd_pcm *pcm)
336{
337 struct snd_pcm_substream *substream;
338 struct snd_dma_buffer *buf;
339 int stream;
340
341 for (stream = 0; stream < 2; stream++) {
342 substream = pcm->streams[stream].substream;
343 if (!substream)
344 continue;
345
346 buf = &substream->dma_buffer;
347 if (!buf->area)
348 continue;
349
350 dma_free_writecombine(pcm->card->dev, buf->bytes,
351 buf->area, buf->addr);
352 buf->area = NULL;
353 }
354}
355
271static void imx_pcm_fiq_free(struct snd_pcm *pcm) 356static void imx_pcm_fiq_free(struct snd_pcm *pcm)
272{ 357{
273 mxc_set_irq_fiq(ssi_irq, 0); 358 mxc_set_irq_fiq(ssi_irq, 0);
@@ -314,3 +399,10 @@ failed_register:
314 399
315 return ret; 400 return ret;
316} 401}
402EXPORT_SYMBOL_GPL(imx_pcm_fiq_init);
403
404void imx_pcm_fiq_exit(struct platform_device *pdev)
405{
406 snd_soc_unregister_platform(&pdev->dev);
407}
408EXPORT_SYMBOL_GPL(imx_pcm_fiq_exit);
diff --git a/sound/soc/fsl/imx-pcm.c b/sound/soc/fsl/imx-pcm.c
deleted file mode 100644
index c49896442d8e..000000000000
--- a/sound/soc/fsl/imx-pcm.c
+++ /dev/null
@@ -1,145 +0,0 @@
1/*
2 * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
3 *
4 * This code is based on code copyrighted by Freescale,
5 * Liam Girdwood, Javier Martin and probably others.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/dma-mapping.h>
14#include <linux/module.h>
15#include <sound/pcm.h>
16#include <sound/soc.h>
17#include "imx-pcm.h"
18
19int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
20 struct vm_area_struct *vma)
21{
22 struct snd_pcm_runtime *runtime = substream->runtime;
23 int ret;
24
25 ret = dma_mmap_writecombine(substream->pcm->card->dev, vma,
26 runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
27
28 pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret,
29 runtime->dma_area,
30 runtime->dma_addr,
31 runtime->dma_bytes);
32 return ret;
33}
34EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
35
36static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
37{
38 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
39 struct snd_dma_buffer *buf = &substream->dma_buffer;
40 size_t size = IMX_SSI_DMABUF_SIZE;
41
42 buf->dev.type = SNDRV_DMA_TYPE_DEV;
43 buf->dev.dev = pcm->card->dev;
44 buf->private_data = NULL;
45 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
46 &buf->addr, GFP_KERNEL);
47 if (!buf->area)
48 return -ENOMEM;
49 buf->bytes = size;
50
51 return 0;
52}
53
54static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
55
56int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
57{
58 struct snd_card *card = rtd->card->snd_card;
59 struct snd_pcm *pcm = rtd->pcm;
60 int ret = 0;
61
62 if (!card->dev->dma_mask)
63 card->dev->dma_mask = &imx_pcm_dmamask;
64 if (!card->dev->coherent_dma_mask)
65 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
66 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
67 ret = imx_pcm_preallocate_dma_buffer(pcm,
68 SNDRV_PCM_STREAM_PLAYBACK);
69 if (ret)
70 goto out;
71 }
72
73 if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
74 ret = imx_pcm_preallocate_dma_buffer(pcm,
75 SNDRV_PCM_STREAM_CAPTURE);
76 if (ret)
77 goto out;
78 }
79
80out:
81 return ret;
82}
83EXPORT_SYMBOL_GPL(imx_pcm_new);
84
85void imx_pcm_free(struct snd_pcm *pcm)
86{
87 struct snd_pcm_substream *substream;
88 struct snd_dma_buffer *buf;
89 int stream;
90
91 for (stream = 0; stream < 2; stream++) {
92 substream = pcm->streams[stream].substream;
93 if (!substream)
94 continue;
95
96 buf = &substream->dma_buffer;
97 if (!buf->area)
98 continue;
99
100 dma_free_writecombine(pcm->card->dev, buf->bytes,
101 buf->area, buf->addr);
102 buf->area = NULL;
103 }
104}
105EXPORT_SYMBOL_GPL(imx_pcm_free);
106
107static int imx_pcm_probe(struct platform_device *pdev)
108{
109 if (strcmp(pdev->id_entry->name, "imx-fiq-pcm-audio") == 0)
110 return imx_pcm_fiq_init(pdev);
111
112 return imx_pcm_dma_init(pdev);
113}
114
115static int imx_pcm_remove(struct platform_device *pdev)
116{
117 if (strcmp(pdev->id_entry->name, "imx-fiq-pcm-audio") == 0)
118 snd_soc_unregister_platform(&pdev->dev);
119 else
120 imx_pcm_dma_exit(pdev);
121
122 return 0;
123}
124
125static struct platform_device_id imx_pcm_devtype[] = {
126 { .name = "imx-pcm-audio", },
127 { .name = "imx-fiq-pcm-audio", },
128 { /* sentinel */ }
129};
130MODULE_DEVICE_TABLE(platform, imx_pcm_devtype);
131
132static struct platform_driver imx_pcm_driver = {
133 .driver = {
134 .name = "imx-pcm",
135 .owner = THIS_MODULE,
136 },
137 .id_table = imx_pcm_devtype,
138 .probe = imx_pcm_probe,
139 .remove = imx_pcm_remove,
140};
141module_platform_driver(imx_pcm_driver);
142
143MODULE_DESCRIPTION("Freescale i.MX PCM driver");
144MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
145MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/imx-pcm.h b/sound/soc/fsl/imx-pcm.h
index b7fa0d75c687..67f656c7c320 100644
--- a/sound/soc/fsl/imx-pcm.h
+++ b/sound/soc/fsl/imx-pcm.h
@@ -32,11 +32,6 @@ imx_pcm_dma_params_init_data(struct imx_dma_data *dma_data,
32 dma_data->peripheral_type = IMX_DMATYPE_SSI; 32 dma_data->peripheral_type = IMX_DMATYPE_SSI;
33} 33}
34 34
35int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
36 struct vm_area_struct *vma);
37int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
38void imx_pcm_free(struct snd_pcm *pcm);
39
40#ifdef CONFIG_SND_SOC_IMX_PCM_DMA 35#ifdef CONFIG_SND_SOC_IMX_PCM_DMA
41int imx_pcm_dma_init(struct platform_device *pdev); 36int imx_pcm_dma_init(struct platform_device *pdev);
42void imx_pcm_dma_exit(struct platform_device *pdev); 37void imx_pcm_dma_exit(struct platform_device *pdev);
@@ -53,11 +48,16 @@ static inline void imx_pcm_dma_exit(struct platform_device *pdev)
53 48
54#ifdef CONFIG_SND_SOC_IMX_PCM_FIQ 49#ifdef CONFIG_SND_SOC_IMX_PCM_FIQ
55int imx_pcm_fiq_init(struct platform_device *pdev); 50int imx_pcm_fiq_init(struct platform_device *pdev);
51void imx_pcm_fiq_exit(struct platform_device *pdev);
56#else 52#else
57static inline int imx_pcm_fiq_init(struct platform_device *pdev) 53static inline int imx_pcm_fiq_init(struct platform_device *pdev)
58{ 54{
59 return -ENODEV; 55 return -ENODEV;
60} 56}
57
58static inline void imx_pcm_fiq_exit(struct platform_device *pdev)
59{
60}
61#endif 61#endif
62 62
63#endif /* _IMX_PCM_H */ 63#endif /* _IMX_PCM_H */
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
index 9584e78858df..3f726e4f88db 100644
--- a/sound/soc/fsl/imx-sgtl5000.c
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -113,13 +113,13 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
113 ssi_pdev = of_find_device_by_node(ssi_np); 113 ssi_pdev = of_find_device_by_node(ssi_np);
114 if (!ssi_pdev) { 114 if (!ssi_pdev) {
115 dev_err(&pdev->dev, "failed to find SSI platform device\n"); 115 dev_err(&pdev->dev, "failed to find SSI platform device\n");
116 ret = -EINVAL; 116 ret = -EPROBE_DEFER;
117 goto fail; 117 goto fail;
118 } 118 }
119 codec_dev = of_find_i2c_device_by_node(codec_np); 119 codec_dev = of_find_i2c_device_by_node(codec_np);
120 if (!codec_dev) { 120 if (!codec_dev) {
121 dev_err(&pdev->dev, "failed to find codec platform device\n"); 121 dev_err(&pdev->dev, "failed to find codec platform device\n");
122 return -EINVAL; 122 return -EPROBE_DEFER;
123 } 123 }
124 124
125 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 125 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
@@ -128,28 +128,18 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
128 goto fail; 128 goto fail;
129 } 129 }
130 130
131 data->codec_clk = clk_get(&codec_dev->dev, NULL); 131 data->codec_clk = devm_clk_get(&codec_dev->dev, NULL);
132 if (IS_ERR(data->codec_clk)) { 132 if (IS_ERR(data->codec_clk))
133 /* assuming clock enabled by default */ 133 goto fail;
134 data->codec_clk = NULL; 134
135 ret = of_property_read_u32(codec_np, "clock-frequency", 135 data->clk_frequency = clk_get_rate(data->codec_clk);
136 &data->clk_frequency);
137 if (ret) {
138 dev_err(&codec_dev->dev,
139 "clock-frequency missing or invalid\n");
140 goto fail;
141 }
142 } else {
143 data->clk_frequency = clk_get_rate(data->codec_clk);
144 clk_prepare_enable(data->codec_clk);
145 }
146 136
147 data->dai.name = "HiFi"; 137 data->dai.name = "HiFi";
148 data->dai.stream_name = "HiFi"; 138 data->dai.stream_name = "HiFi";
149 data->dai.codec_dai_name = "sgtl5000"; 139 data->dai.codec_dai_name = "sgtl5000";
150 data->dai.codec_of_node = codec_np; 140 data->dai.codec_of_node = codec_np;
151 data->dai.cpu_of_node = ssi_np; 141 data->dai.cpu_of_node = ssi_np;
152 data->dai.platform_name = "imx-pcm-audio"; 142 data->dai.platform_of_node = ssi_np;
153 data->dai.init = &imx_sgtl5000_dai_init; 143 data->dai.init = &imx_sgtl5000_dai_init;
154 data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 144 data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
155 SND_SOC_DAIFMT_CBM_CFM; 145 SND_SOC_DAIFMT_CBM_CFM;
@@ -157,10 +147,10 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
157 data->card.dev = &pdev->dev; 147 data->card.dev = &pdev->dev;
158 ret = snd_soc_of_parse_card_name(&data->card, "model"); 148 ret = snd_soc_of_parse_card_name(&data->card, "model");
159 if (ret) 149 if (ret)
160 goto clk_fail; 150 goto fail;
161 ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); 151 ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
162 if (ret) 152 if (ret)
163 goto clk_fail; 153 goto fail;
164 data->card.num_links = 1; 154 data->card.num_links = 1;
165 data->card.owner = THIS_MODULE; 155 data->card.owner = THIS_MODULE;
166 data->card.dai_link = &data->dai; 156 data->card.dai_link = &data->dai;
@@ -170,12 +160,15 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
170 ret = snd_soc_register_card(&data->card); 160 ret = snd_soc_register_card(&data->card);
171 if (ret) { 161 if (ret) {
172 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); 162 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
173 goto clk_fail; 163 goto fail;
174 } 164 }
175 165
176 platform_set_drvdata(pdev, data); 166 platform_set_drvdata(pdev, data);
177clk_fail: 167 of_node_put(ssi_np);
178 clk_put(data->codec_clk); 168 of_node_put(codec_np);
169
170 return 0;
171
179fail: 172fail:
180 if (ssi_np) 173 if (ssi_np)
181 of_node_put(ssi_np); 174 of_node_put(ssi_np);
@@ -189,10 +182,6 @@ static int imx_sgtl5000_remove(struct platform_device *pdev)
189{ 182{
190 struct imx_sgtl5000_data *data = platform_get_drvdata(pdev); 183 struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
191 184
192 if (data->codec_clk) {
193 clk_disable_unprepare(data->codec_clk);
194 clk_put(data->codec_clk);
195 }
196 snd_soc_unregister_card(&data->card); 185 snd_soc_unregister_card(&data->card);
197 186
198 return 0; 187 return 0;
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c
index c6fa03e2114a..a8362be3cd18 100644
--- a/sound/soc/fsl/imx-ssi.c
+++ b/sound/soc/fsl/imx-ssi.c
@@ -590,41 +590,19 @@ static int imx_ssi_probe(struct platform_device *pdev)
590 goto failed_register; 590 goto failed_register;
591 } 591 }
592 592
593 ssi->soc_platform_pdev_fiq = platform_device_alloc("imx-fiq-pcm-audio", pdev->id); 593 ret = imx_pcm_fiq_init(pdev);
594 if (!ssi->soc_platform_pdev_fiq) { 594 if (ret)
595 ret = -ENOMEM; 595 goto failed_pcm_fiq;
596 goto failed_pdev_fiq_alloc;
597 }
598
599 platform_set_drvdata(ssi->soc_platform_pdev_fiq, ssi);
600 ret = platform_device_add(ssi->soc_platform_pdev_fiq);
601 if (ret) {
602 dev_err(&pdev->dev, "failed to add platform device\n");
603 goto failed_pdev_fiq_add;
604 }
605 596
606 ssi->soc_platform_pdev = platform_device_alloc("imx-pcm-audio", pdev->id); 597 ret = imx_pcm_dma_init(pdev);
607 if (!ssi->soc_platform_pdev) { 598 if (ret)
608 ret = -ENOMEM; 599 goto failed_pcm_dma;
609 goto failed_pdev_alloc;
610 }
611
612 platform_set_drvdata(ssi->soc_platform_pdev, ssi);
613 ret = platform_device_add(ssi->soc_platform_pdev);
614 if (ret) {
615 dev_err(&pdev->dev, "failed to add platform device\n");
616 goto failed_pdev_add;
617 }
618 600
619 return 0; 601 return 0;
620 602
621failed_pdev_add: 603failed_pcm_dma:
622 platform_device_put(ssi->soc_platform_pdev); 604 imx_pcm_fiq_exit(pdev);
623failed_pdev_alloc: 605failed_pcm_fiq:
624 platform_device_del(ssi->soc_platform_pdev_fiq);
625failed_pdev_fiq_add:
626 platform_device_put(ssi->soc_platform_pdev_fiq);
627failed_pdev_fiq_alloc:
628 snd_soc_unregister_component(&pdev->dev); 606 snd_soc_unregister_component(&pdev->dev);
629failed_register: 607failed_register:
630 release_mem_region(res->start, resource_size(res)); 608 release_mem_region(res->start, resource_size(res));
@@ -639,8 +617,8 @@ static int imx_ssi_remove(struct platform_device *pdev)
639 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 617 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
640 struct imx_ssi *ssi = platform_get_drvdata(pdev); 618 struct imx_ssi *ssi = platform_get_drvdata(pdev);
641 619
642 platform_device_unregister(ssi->soc_platform_pdev); 620 imx_pcm_dma_exit(pdev);
643 platform_device_unregister(ssi->soc_platform_pdev_fiq); 621 imx_pcm_fiq_exit(pdev);
644 622
645 snd_soc_unregister_component(&pdev->dev); 623 snd_soc_unregister_component(&pdev->dev);
646 624
diff --git a/sound/soc/fsl/imx-ssi.h b/sound/soc/fsl/imx-ssi.h
index bb6b3dbb13fd..d5003cefca8d 100644
--- a/sound/soc/fsl/imx-ssi.h
+++ b/sound/soc/fsl/imx-ssi.h
@@ -211,9 +211,6 @@ struct imx_ssi {
211 struct imx_dma_data filter_data_rx; 211 struct imx_dma_data filter_data_rx;
212 212
213 int enabled; 213 int enabled;
214
215 struct platform_device *soc_platform_pdev;
216 struct platform_device *soc_platform_pdev_fiq;
217}; 214};
218 215
219#endif /* _IMX_SSI_H */ 216#endif /* _IMX_SSI_H */
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c
new file mode 100644
index 000000000000..52a36a90f4f4
--- /dev/null
+++ b/sound/soc/fsl/imx-wm8962.c
@@ -0,0 +1,323 @@
1/*
2 * Copyright 2013 Freescale Semiconductor, Inc.
3 *
4 * Based on imx-sgtl5000.c
5 * Copyright 2012 Freescale Semiconductor, Inc.
6 * Copyright 2012 Linaro Ltd.
7 *
8 * The code contained herein is licensed under the GNU General Public
9 * License. You may obtain a copy of the GNU General Public License
10 * Version 2 or later at the following locations:
11 *
12 * http://www.opensource.org/licenses/gpl-license.html
13 * http://www.gnu.org/copyleft/gpl.html
14 */
15
16#include <linux/module.h>
17#include <linux/of_platform.h>
18#include <linux/of_i2c.h>
19#include <linux/slab.h>
20#include <linux/clk.h>
21#include <sound/soc.h>
22#include <sound/pcm_params.h>
23#include <sound/soc-dapm.h>
24#include <linux/pinctrl/consumer.h>
25
26#include "../codecs/wm8962.h"
27#include "imx-audmux.h"
28
29#define DAI_NAME_SIZE 32
30
31struct imx_wm8962_data {
32 struct snd_soc_dai_link dai;
33 struct snd_soc_card card;
34 char codec_dai_name[DAI_NAME_SIZE];
35 char platform_name[DAI_NAME_SIZE];
36 struct clk *codec_clk;
37 unsigned int clk_frequency;
38};
39
40struct imx_priv {
41 struct platform_device *pdev;
42};
43static struct imx_priv card_priv;
44
45static const struct snd_soc_dapm_widget imx_wm8962_dapm_widgets[] = {
46 SND_SOC_DAPM_HP("Headphone Jack", NULL),
47 SND_SOC_DAPM_SPK("Ext Spk", NULL),
48 SND_SOC_DAPM_MIC("AMIC", NULL),
49 SND_SOC_DAPM_MIC("DMIC", NULL),
50};
51
52static int sample_rate = 44100;
53static snd_pcm_format_t sample_format = SNDRV_PCM_FORMAT_S16_LE;
54
55static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
56 struct snd_pcm_hw_params *params)
57{
58 sample_rate = params_rate(params);
59 sample_format = params_format(params);
60
61 return 0;
62}
63
64static struct snd_soc_ops imx_hifi_ops = {
65 .hw_params = imx_hifi_hw_params,
66};
67
68static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
69 struct snd_soc_dapm_context *dapm,
70 enum snd_soc_bias_level level)
71{
72 struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
73 struct imx_priv *priv = &card_priv;
74 struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev);
75 struct device *dev = &priv->pdev->dev;
76 unsigned int pll_out;
77 int ret;
78
79 if (dapm->dev != codec_dai->dev)
80 return 0;
81
82 switch (level) {
83 case SND_SOC_BIAS_PREPARE:
84 if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
85 if (sample_format == SNDRV_PCM_FORMAT_S24_LE)
86 pll_out = sample_rate * 384;
87 else
88 pll_out = sample_rate * 256;
89
90 ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
91 WM8962_FLL_MCLK, data->clk_frequency,
92 pll_out);
93 if (ret < 0) {
94 dev_err(dev, "failed to start FLL: %d\n", ret);
95 return ret;
96 }
97
98 ret = snd_soc_dai_set_sysclk(codec_dai,
99 WM8962_SYSCLK_FLL, pll_out,
100 SND_SOC_CLOCK_IN);
101 if (ret < 0) {
102 dev_err(dev, "failed to set SYSCLK: %d\n", ret);
103 return ret;
104 }
105 }
106 break;
107
108 case SND_SOC_BIAS_STANDBY:
109 if (dapm->bias_level == SND_SOC_BIAS_PREPARE) {
110 ret = snd_soc_dai_set_sysclk(codec_dai,
111 WM8962_SYSCLK_MCLK, data->clk_frequency,
112 SND_SOC_CLOCK_IN);
113 if (ret < 0) {
114 dev_err(dev,
115 "failed to switch away from FLL: %d\n",
116 ret);
117 return ret;
118 }
119
120 ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
121 0, 0, 0);
122 if (ret < 0) {
123 dev_err(dev, "failed to stop FLL: %d\n", ret);
124 return ret;
125 }
126 }
127 break;
128
129 default:
130 break;
131 }
132
133 dapm->bias_level = level;
134
135 return 0;
136}
137
138static int imx_wm8962_late_probe(struct snd_soc_card *card)
139{
140 struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
141 struct imx_priv *priv = &card_priv;
142 struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev);
143 struct device *dev = &priv->pdev->dev;
144 int ret;
145
146 ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
147 data->clk_frequency, SND_SOC_CLOCK_IN);
148 if (ret < 0)
149 dev_err(dev, "failed to set sysclk in %s\n", __func__);
150
151 return ret;
152}
153
154static int imx_wm8962_probe(struct platform_device *pdev)
155{
156 struct device_node *np = pdev->dev.of_node;
157 struct device_node *ssi_np, *codec_np;
158 struct platform_device *ssi_pdev;
159 struct imx_priv *priv = &card_priv;
160 struct i2c_client *codec_dev;
161 struct imx_wm8962_data *data;
162 int int_port, ext_port;
163 int ret;
164
165 priv->pdev = pdev;
166
167 ret = of_property_read_u32(np, "mux-int-port", &int_port);
168 if (ret) {
169 dev_err(&pdev->dev, "mux-int-port missing or invalid\n");
170 return ret;
171 }
172 ret = of_property_read_u32(np, "mux-ext-port", &ext_port);
173 if (ret) {
174 dev_err(&pdev->dev, "mux-ext-port missing or invalid\n");
175 return ret;
176 }
177
178 /*
179 * The port numbering in the hardware manual starts at 1, while
180 * the audmux API expects it starts at 0.
181 */
182 int_port--;
183 ext_port--;
184 ret = imx_audmux_v2_configure_port(int_port,
185 IMX_AUDMUX_V2_PTCR_SYN |
186 IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
187 IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |
188 IMX_AUDMUX_V2_PTCR_TFSDIR |
189 IMX_AUDMUX_V2_PTCR_TCLKDIR,
190 IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port));
191 if (ret) {
192 dev_err(&pdev->dev, "audmux internal port setup failed\n");
193 return ret;
194 }
195 imx_audmux_v2_configure_port(ext_port,
196 IMX_AUDMUX_V2_PTCR_SYN,
197 IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));
198 if (ret) {
199 dev_err(&pdev->dev, "audmux external port setup failed\n");
200 return ret;
201 }
202
203 ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0);
204 codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
205 if (!ssi_np || !codec_np) {
206 dev_err(&pdev->dev, "phandle missing or invalid\n");
207 ret = -EINVAL;
208 goto fail;
209 }
210
211 ssi_pdev = of_find_device_by_node(ssi_np);
212 if (!ssi_pdev) {
213 dev_err(&pdev->dev, "failed to find SSI platform device\n");
214 ret = -EINVAL;
215 goto fail;
216 }
217 codec_dev = of_find_i2c_device_by_node(codec_np);
218 if (!codec_dev || !codec_dev->driver) {
219 dev_err(&pdev->dev, "failed to find codec platform device\n");
220 return -EINVAL;
221 }
222
223 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
224 if (!data) {
225 ret = -ENOMEM;
226 goto fail;
227 }
228
229 data->codec_clk = devm_clk_get(&codec_dev->dev, NULL);
230 if (IS_ERR(data->codec_clk)) {
231 ret = PTR_ERR(data->codec_clk);
232 dev_err(&codec_dev->dev, "failed to get codec clk: %d\n", ret);
233 goto fail;
234 }
235
236 data->clk_frequency = clk_get_rate(data->codec_clk);
237 ret = clk_prepare_enable(data->codec_clk);
238 if (ret) {
239 dev_err(&codec_dev->dev, "failed to enable codec clk: %d\n", ret);
240 goto fail;
241 }
242
243 data->dai.name = "HiFi";
244 data->dai.stream_name = "HiFi";
245 data->dai.codec_dai_name = "wm8962";
246 data->dai.codec_of_node = codec_np;
247 data->dai.cpu_dai_name = dev_name(&ssi_pdev->dev);
248 data->dai.platform_of_node = ssi_np;
249 data->dai.ops = &imx_hifi_ops;
250 data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
251 SND_SOC_DAIFMT_CBM_CFM;
252
253 data->card.dev = &pdev->dev;
254 ret = snd_soc_of_parse_card_name(&data->card, "model");
255 if (ret)
256 goto clk_fail;
257 ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
258 if (ret)
259 goto clk_fail;
260 data->card.num_links = 1;
261 data->card.dai_link = &data->dai;
262 data->card.dapm_widgets = imx_wm8962_dapm_widgets;
263 data->card.num_dapm_widgets = ARRAY_SIZE(imx_wm8962_dapm_widgets);
264
265 data->card.late_probe = imx_wm8962_late_probe;
266 data->card.set_bias_level = imx_wm8962_set_bias_level;
267
268 ret = snd_soc_register_card(&data->card);
269 if (ret) {
270 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
271 goto clk_fail;
272 }
273
274 platform_set_drvdata(pdev, data);
275 of_node_put(ssi_np);
276 of_node_put(codec_np);
277
278 return 0;
279
280clk_fail:
281 if (!IS_ERR(data->codec_clk))
282 clk_disable_unprepare(data->codec_clk);
283fail:
284 if (ssi_np)
285 of_node_put(ssi_np);
286 if (codec_np)
287 of_node_put(codec_np);
288
289 return ret;
290}
291
292static int imx_wm8962_remove(struct platform_device *pdev)
293{
294 struct imx_wm8962_data *data = platform_get_drvdata(pdev);
295
296 if (!IS_ERR(data->codec_clk))
297 clk_disable_unprepare(data->codec_clk);
298 snd_soc_unregister_card(&data->card);
299
300 return 0;
301}
302
303static const struct of_device_id imx_wm8962_dt_ids[] = {
304 { .compatible = "fsl,imx-audio-wm8962", },
305 { /* sentinel */ }
306};
307MODULE_DEVICE_TABLE(of, imx_wm8962_dt_ids);
308
309static struct platform_driver imx_wm8962_driver = {
310 .driver = {
311 .name = "imx-wm8962",
312 .owner = THIS_MODULE,
313 .of_match_table = imx_wm8962_dt_ids,
314 },
315 .probe = imx_wm8962_probe,
316 .remove = imx_wm8962_remove,
317};
318module_platform_driver(imx_wm8962_driver);
319
320MODULE_AUTHOR("Freescale Semiconductor, Inc.");
321MODULE_DESCRIPTION("Freescale i.MX WM8962 ASoC machine driver");
322MODULE_LICENSE("GPL v2");
323MODULE_ALIAS("platform:imx-wm8962");
diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c
index 3d1074179057..f4c3bda5e69e 100644
--- a/sound/soc/fsl/mx27vis-aic32x4.c
+++ b/sound/soc/fsl/mx27vis-aic32x4.c
@@ -161,7 +161,7 @@ static struct snd_soc_dai_link mx27vis_aic32x4_dai = {
161 .name = "tlv320aic32x4", 161 .name = "tlv320aic32x4",
162 .stream_name = "TLV320AIC32X4", 162 .stream_name = "TLV320AIC32X4",
163 .codec_dai_name = "tlv320aic32x4-hifi", 163 .codec_dai_name = "tlv320aic32x4-hifi",
164 .platform_name = "imx-pcm-audio.0", 164 .platform_name = "imx-ssi.0",
165 .codec_name = "tlv320aic32x4.0-0018", 165 .codec_name = "tlv320aic32x4.0-0018",
166 .cpu_dai_name = "imx-ssi.0", 166 .cpu_dai_name = "imx-ssi.0",
167 .ops = &mx27vis_aic32x4_snd_ops, 167 .ops = &mx27vis_aic32x4_snd_ops,
diff --git a/sound/soc/fsl/phycore-ac97.c b/sound/soc/fsl/phycore-ac97.c
index f8da6dd115ed..ae403c29688f 100644
--- a/sound/soc/fsl/phycore-ac97.c
+++ b/sound/soc/fsl/phycore-ac97.c
@@ -33,7 +33,7 @@ static struct snd_soc_dai_link imx_phycore_dai_ac97[] = {
33 .codec_dai_name = "wm9712-hifi", 33 .codec_dai_name = "wm9712-hifi",
34 .codec_name = "wm9712-codec", 34 .codec_name = "wm9712-codec",
35 .cpu_dai_name = "imx-ssi.0", 35 .cpu_dai_name = "imx-ssi.0",
36 .platform_name = "imx-fiq-pcm-audio.0", 36 .platform_name = "imx-ssi.0",
37 .ops = &imx_phycore_hifi_ops, 37 .ops = &imx_phycore_hifi_ops,
38 }, 38 },
39}; 39};
diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c
index fe54a69073e5..fce63252bdbb 100644
--- a/sound/soc/fsl/wm1133-ev1.c
+++ b/sound/soc/fsl/wm1133-ev1.c
@@ -245,7 +245,7 @@ static struct snd_soc_dai_link wm1133_ev1_dai = {
245 .stream_name = "Audio", 245 .stream_name = "Audio",
246 .cpu_dai_name = "imx-ssi.0", 246 .cpu_dai_name = "imx-ssi.0",
247 .codec_dai_name = "wm8350-hifi", 247 .codec_dai_name = "wm8350-hifi",
248 .platform_name = "imx-fiq-pcm-audio.0", 248 .platform_name = "imx-ssi.0",
249 .codec_name = "wm8350-codec.0-0x1a", 249 .codec_name = "wm8350-codec.0-0x1a",
250 .init = wm1133_ev1_init, 250 .init = wm1133_ev1_init,
251 .ops = &wm1133_ev1_ops, 251 .ops = &wm1133_ev1_ops,
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index 9a126441c5f3..4c849a49c72a 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -118,7 +118,7 @@ static int jz4740_i2s_startup(struct snd_pcm_substream *substream,
118 ctrl |= JZ_AIC_CTRL_FLUSH; 118 ctrl |= JZ_AIC_CTRL_FLUSH;
119 jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); 119 jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
120 120
121 clk_enable(i2s->clk_i2s); 121 clk_prepare_enable(i2s->clk_i2s);
122 122
123 conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); 123 conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
124 conf |= JZ_AIC_CONF_ENABLE; 124 conf |= JZ_AIC_CONF_ENABLE;
@@ -140,7 +140,7 @@ static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream,
140 conf &= ~JZ_AIC_CONF_ENABLE; 140 conf &= ~JZ_AIC_CONF_ENABLE;
141 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); 141 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
142 142
143 clk_disable(i2s->clk_i2s); 143 clk_disable_unprepare(i2s->clk_i2s);
144} 144}
145 145
146static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 146static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -314,10 +314,10 @@ static int jz4740_i2s_suspend(struct snd_soc_dai *dai)
314 conf &= ~JZ_AIC_CONF_ENABLE; 314 conf &= ~JZ_AIC_CONF_ENABLE;
315 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); 315 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf);
316 316
317 clk_disable(i2s->clk_i2s); 317 clk_disable_unprepare(i2s->clk_i2s);
318 } 318 }
319 319
320 clk_disable(i2s->clk_aic); 320 clk_disable_unprepare(i2s->clk_aic);
321 321
322 return 0; 322 return 0;
323} 323}
@@ -327,10 +327,10 @@ static int jz4740_i2s_resume(struct snd_soc_dai *dai)
327 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); 327 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
328 uint32_t conf; 328 uint32_t conf;
329 329
330 clk_enable(i2s->clk_aic); 330 clk_prepare_enable(i2s->clk_aic);
331 331
332 if (dai->active) { 332 if (dai->active) {
333 clk_enable(i2s->clk_i2s); 333 clk_prepare_enable(i2s->clk_i2s);
334 334
335 conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); 335 conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF);
336 conf |= JZ_AIC_CONF_ENABLE; 336 conf |= JZ_AIC_CONF_ENABLE;
@@ -368,7 +368,7 @@ static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai)
368 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); 368 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
369 uint32_t conf; 369 uint32_t conf;
370 370
371 clk_enable(i2s->clk_aic); 371 clk_prepare_enable(i2s->clk_aic);
372 372
373 jz4740_i2c_init_pcm_config(i2s); 373 jz4740_i2c_init_pcm_config(i2s);
374 374
@@ -388,7 +388,7 @@ static int jz4740_i2s_dai_remove(struct snd_soc_dai *dai)
388{ 388{
389 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); 389 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
390 390
391 clk_disable(i2s->clk_aic); 391 clk_disable_unprepare(i2s->clk_aic);
392 return 0; 392 return 0;
393} 393}
394 394
@@ -509,7 +509,6 @@ static int jz4740_i2s_dev_remove(struct platform_device *pdev)
509 iounmap(i2s->base); 509 iounmap(i2s->base);
510 release_mem_region(i2s->mem->start, resource_size(i2s->mem)); 510 release_mem_region(i2s->mem->start, resource_size(i2s->mem));
511 511
512 platform_set_drvdata(pdev, NULL);
513 kfree(i2s); 512 kfree(i2s);
514 513
515 return 0; 514 return 0;
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index d3d4bdca1cc6..a9f14530c3db 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -289,7 +289,7 @@ static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream
289 return count; 289 return count;
290} 290}
291 291
292struct snd_pcm_ops kirkwood_dma_ops = { 292static struct snd_pcm_ops kirkwood_dma_ops = {
293 .open = kirkwood_dma_open, 293 .open = kirkwood_dma_open,
294 .close = kirkwood_dma_close, 294 .close = kirkwood_dma_close,
295 .ioctl = snd_pcm_lib_ioctl, 295 .ioctl = snd_pcm_lib_ioctl,
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
index 4139116c33b5..78d582519891 100644
--- a/sound/soc/mid-x86/mfld_machine.c
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -425,7 +425,6 @@ static int snd_mfld_mc_remove(struct platform_device *pdev)
425 free_irq(platform_get_irq(pdev, 0), mc_drv_ctx); 425 free_irq(platform_get_irq(pdev, 0), mc_drv_ctx);
426 snd_soc_unregister_card(&snd_soc_card_mfld); 426 snd_soc_unregister_card(&snd_soc_card_mfld);
427 kfree(mc_drv_ctx); 427 kfree(mc_drv_ctx);
428 platform_set_drvdata(pdev, NULL);
429 return 0; 428 return 0;
430} 429}
431 430
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index b41fffc056fb..b16abbbf7764 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -49,24 +49,8 @@ static const struct snd_pcm_hardware snd_mxs_hardware = {
49 .fifo_size = 32, 49 .fifo_size = 32,
50}; 50};
51 51
52static bool filter(struct dma_chan *chan, void *param)
53{
54 struct mxs_pcm_dma_params *dma_params = param;
55
56 if (!mxs_dma_is_apbx(chan))
57 return false;
58
59 if (chan->chan_id != dma_params->chan_num)
60 return false;
61
62 chan->private = &dma_params->dma_data;
63
64 return true;
65}
66
67static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = { 52static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = {
68 .pcm_hardware = &snd_mxs_hardware, 53 .pcm_hardware = &snd_mxs_hardware,
69 .compat_filter_fn = filter,
70 .prealloc_buffer_size = 64 * 1024, 54 .prealloc_buffer_size = 64 * 1024,
71}; 55};
72 56
@@ -74,8 +58,6 @@ int mxs_pcm_platform_register(struct device *dev)
74{ 58{
75 return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config, 59 return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config,
76 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | 60 SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
77 SND_DMAENGINE_PCM_FLAG_NO_DT |
78 SND_DMAENGINE_PCM_FLAG_COMPAT |
79 SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX); 61 SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX);
80} 62}
81EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); 63EXPORT_SYMBOL_GPL(mxs_pcm_platform_register);
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h
index 3aa918f9ed3e..bc685b67cac7 100644
--- a/sound/soc/mxs/mxs-pcm.h
+++ b/sound/soc/mxs/mxs-pcm.h
@@ -19,13 +19,6 @@
19#ifndef _MXS_PCM_H 19#ifndef _MXS_PCM_H
20#define _MXS_PCM_H 20#define _MXS_PCM_H
21 21
22#include <linux/fsl/mxs-dma.h>
23
24struct mxs_pcm_dma_params {
25 struct mxs_dma_data dma_data;
26 int chan_num;
27};
28
29int mxs_pcm_platform_register(struct device *dev); 22int mxs_pcm_platform_register(struct device *dev);
30void mxs_pcm_platform_unregister(struct device *dev); 23void mxs_pcm_platform_unregister(struct device *dev);
31 24
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index d31dc52fa862..49d870034bc3 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -26,8 +26,6 @@
26#include <linux/clk.h> 26#include <linux/clk.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include <linux/time.h> 28#include <linux/time.h>
29#include <linux/fsl/mxs-dma.h>
30#include <linux/pinctrl/consumer.h>
31#include <sound/core.h> 29#include <sound/core.h>
32#include <sound/pcm.h> 30#include <sound/pcm.h>
33#include <sound/pcm_params.h> 31#include <sound/pcm_params.h>
@@ -605,8 +603,6 @@ static int mxs_saif_dai_probe(struct snd_soc_dai *dai)
605 struct mxs_saif *saif = dev_get_drvdata(dai->dev); 603 struct mxs_saif *saif = dev_get_drvdata(dai->dev);
606 604
607 snd_soc_dai_set_drvdata(dai, saif); 605 snd_soc_dai_set_drvdata(dai, saif);
608 dai->playback_dma_data = &saif->dma_param;
609 dai->capture_dma_data = &saif->dma_param;
610 606
611 return 0; 607 return 0;
612} 608}
@@ -665,9 +661,8 @@ static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
665static int mxs_saif_probe(struct platform_device *pdev) 661static int mxs_saif_probe(struct platform_device *pdev)
666{ 662{
667 struct device_node *np = pdev->dev.of_node; 663 struct device_node *np = pdev->dev.of_node;
668 struct resource *iores, *dmares; 664 struct resource *iores;
669 struct mxs_saif *saif; 665 struct mxs_saif *saif;
670 struct pinctrl *pinctrl;
671 int ret = 0; 666 int ret = 0;
672 struct device_node *master; 667 struct device_node *master;
673 668
@@ -707,12 +702,6 @@ static int mxs_saif_probe(struct platform_device *pdev)
707 702
708 mxs_saif[saif->id] = saif; 703 mxs_saif[saif->id] = saif;
709 704
710 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
711 if (IS_ERR(pinctrl)) {
712 ret = PTR_ERR(pinctrl);
713 return ret;
714 }
715
716 saif->clk = devm_clk_get(&pdev->dev, NULL); 705 saif->clk = devm_clk_get(&pdev->dev, NULL);
717 if (IS_ERR(saif->clk)) { 706 if (IS_ERR(saif->clk)) {
718 ret = PTR_ERR(saif->clk); 707 ret = PTR_ERR(saif->clk);
@@ -727,22 +716,6 @@ static int mxs_saif_probe(struct platform_device *pdev)
727 if (IS_ERR(saif->base)) 716 if (IS_ERR(saif->base))
728 return PTR_ERR(saif->base); 717 return PTR_ERR(saif->base);
729 718
730 dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
731 if (!dmares) {
732 /*
733 * TODO: This is a temporary solution and should be changed
734 * to use generic DMA binding later when the helplers get in.
735 */
736 ret = of_property_read_u32(np, "fsl,saif-dma-channel",
737 &saif->dma_param.chan_num);
738 if (ret) {
739 dev_err(&pdev->dev, "failed to get dma channel\n");
740 return ret;
741 }
742 } else {
743 saif->dma_param.chan_num = dmares->start;
744 }
745
746 saif->irq = platform_get_irq(pdev, 0); 719 saif->irq = platform_get_irq(pdev, 0);
747 if (saif->irq < 0) { 720 if (saif->irq < 0) {
748 ret = saif->irq; 721 ret = saif->irq;
@@ -759,14 +732,6 @@ static int mxs_saif_probe(struct platform_device *pdev)
759 return ret; 732 return ret;
760 } 733 }
761 734
762 saif->dma_param.dma_data.chan_irq = platform_get_irq(pdev, 1);
763 if (saif->dma_param.dma_data.chan_irq < 0) {
764 ret = saif->dma_param.dma_data.chan_irq;
765 dev_err(&pdev->dev, "failed to get dma irq resource: %d\n",
766 ret);
767 return ret;
768 }
769
770 platform_set_drvdata(pdev, saif); 735 platform_set_drvdata(pdev, saif);
771 736
772 ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component, 737 ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component,
diff --git a/sound/soc/mxs/mxs-saif.h b/sound/soc/mxs/mxs-saif.h
index 3cb342e5bc90..53eaa4bf0e27 100644
--- a/sound/soc/mxs/mxs-saif.h
+++ b/sound/soc/mxs/mxs-saif.h
@@ -117,7 +117,6 @@ struct mxs_saif {
117 unsigned int mclk_in_use; 117 unsigned int mclk_in_use;
118 void __iomem *base; 118 void __iomem *base;
119 int irq; 119 int irq;
120 struct mxs_pcm_dma_params dma_param;
121 unsigned int id; 120 unsigned int id;
122 unsigned int master_id; 121 unsigned int master_id;
123 unsigned int cur_rate; 122 unsigned int cur_rate;
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
index b1d9b5ebeeeb..1b134d72f120 100644
--- a/sound/soc/mxs/mxs-sgtl5000.c
+++ b/sound/soc/mxs/mxs-sgtl5000.c
@@ -90,17 +90,11 @@ static struct snd_soc_dai_link mxs_sgtl5000_dai[] = {
90 .name = "HiFi Tx", 90 .name = "HiFi Tx",
91 .stream_name = "HiFi Playback", 91 .stream_name = "HiFi Playback",
92 .codec_dai_name = "sgtl5000", 92 .codec_dai_name = "sgtl5000",
93 .codec_name = "sgtl5000.0-000a",
94 .cpu_dai_name = "mxs-saif.0",
95 .platform_name = "mxs-saif.0",
96 .ops = &mxs_sgtl5000_hifi_ops, 93 .ops = &mxs_sgtl5000_hifi_ops,
97 }, { 94 }, {
98 .name = "HiFi Rx", 95 .name = "HiFi Rx",
99 .stream_name = "HiFi Capture", 96 .stream_name = "HiFi Capture",
100 .codec_dai_name = "sgtl5000", 97 .codec_dai_name = "sgtl5000",
101 .codec_name = "sgtl5000.0-000a",
102 .cpu_dai_name = "mxs-saif.1",
103 .platform_name = "mxs-saif.1",
104 .ops = &mxs_sgtl5000_hifi_ops, 98 .ops = &mxs_sgtl5000_hifi_ops,
105 }, 99 },
106}; 100};
@@ -116,7 +110,7 @@ static int mxs_sgtl5000_probe_dt(struct platform_device *pdev)
116{ 110{
117 struct device_node *np = pdev->dev.of_node; 111 struct device_node *np = pdev->dev.of_node;
118 struct device_node *saif_np[2], *codec_np; 112 struct device_node *saif_np[2], *codec_np;
119 int i, ret = 0; 113 int i;
120 114
121 if (!np) 115 if (!np)
122 return 1; /* no device tree */ 116 return 1; /* no device tree */
@@ -142,7 +136,7 @@ static int mxs_sgtl5000_probe_dt(struct platform_device *pdev)
142 of_node_put(saif_np[0]); 136 of_node_put(saif_np[0]);
143 of_node_put(saif_np[1]); 137 of_node_put(saif_np[1]);
144 138
145 return ret; 139 return 0;
146} 140}
147 141
148static int mxs_sgtl5000_probe(struct platform_device *pdev) 142static int mxs_sgtl5000_probe(struct platform_device *pdev)
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 2b225945359b..a725905b2c68 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -26,7 +26,6 @@ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
26obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o 26obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o
27obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o 27obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o
28obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o 28obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
29obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o
30obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o 29obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o
31obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o 30obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o
32obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o 31obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o
diff --git a/sound/soc/omap/omap-hdmi-card.c b/sound/soc/omap/omap-hdmi-card.c
index d4eaa92e518e..7e66e9cba5a8 100644
--- a/sound/soc/omap/omap-hdmi-card.c
+++ b/sound/soc/omap/omap-hdmi-card.c
@@ -35,7 +35,7 @@ static struct snd_soc_dai_link omap_hdmi_dai = {
35 .cpu_dai_name = "omap-hdmi-audio-dai", 35 .cpu_dai_name = "omap-hdmi-audio-dai",
36 .platform_name = "omap-pcm-audio", 36 .platform_name = "omap-pcm-audio",
37 .codec_name = "hdmi-audio-codec", 37 .codec_name = "hdmi-audio-codec",
38 .codec_dai_name = "omap-hdmi-hifi", 38 .codec_dai_name = "hdmi-hifi",
39}; 39};
40 40
41static struct snd_soc_card snd_soc_omap_hdmi = { 41static struct snd_soc_card snd_soc_omap_hdmi = {
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index eadbfb6b5000..7483efb6dc67 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -814,8 +814,6 @@ static int asoc_mcbsp_remove(struct platform_device *pdev)
814 814
815 clk_put(mcbsp->fclk); 815 clk_put(mcbsp->fclk);
816 816
817 platform_set_drvdata(pdev, NULL);
818
819 return 0; 817 return 0;
820} 818}
821 819
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 4d2e46fae77c..b35809467547 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -130,26 +130,6 @@ config SND_PXA2XX_SOC_PALM27X
130 Say Y if you want to add support for SoC audio on 130 Say Y if you want to add support for SoC audio on
131 Palm T|X, T5, E2 or LifeDrive handheld computer. 131 Palm T|X, T5, E2 or LifeDrive handheld computer.
132 132
133config SND_SOC_SAARB
134 tristate "SoC Audio support for Marvell Saarb"
135 depends on SND_PXA2XX_SOC && MACH_SAARB
136 select MFD_88PM860X
137 select SND_PXA_SOC_SSP
138 select SND_SOC_88PM860X
139 help
140 Say Y if you want to add support for SoC audio on the
141 Marvell Saarb reference platform.
142
143config SND_SOC_TAVOREVB3
144 tristate "SoC Audio support for Marvell Tavor EVB3"
145 depends on SND_PXA2XX_SOC && MACH_TAVOREVB3
146 select MFD_88PM860X
147 select SND_PXA_SOC_SSP
148 select SND_SOC_88PM860X
149 help
150 Say Y if you want to add support for SoC audio on the
151 Marvell Saarb reference platform.
152
153config SND_PXA910_SOC 133config SND_PXA910_SOC
154 tristate "SoC Audio for Marvell PXA910 chip" 134 tristate "SoC Audio for Marvell PXA910 chip"
155 depends on ARCH_MMP && SND 135 depends on ARCH_MMP && SND
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index d8a265d2d5d7..2cff67b61dc3 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -23,8 +23,6 @@ snd-soc-e800-objs := e800_wm9712.o
23snd-soc-spitz-objs := spitz.o 23snd-soc-spitz-objs := spitz.o
24snd-soc-em-x270-objs := em-x270.o 24snd-soc-em-x270-objs := em-x270.o
25snd-soc-palm27x-objs := palm27x.o 25snd-soc-palm27x-objs := palm27x.o
26snd-soc-saarb-objs := saarb.o
27snd-soc-tavorevb3-objs := tavorevb3.o
28snd-soc-zylonite-objs := zylonite.o 26snd-soc-zylonite-objs := zylonite.o
29snd-soc-hx4700-objs := hx4700.o 27snd-soc-hx4700-objs := hx4700.o
30snd-soc-magician-objs := magician.o 28snd-soc-magician-objs := magician.o
@@ -48,8 +46,6 @@ obj-$(CONFIG_SND_PXA2XX_SOC_HX4700) += snd-soc-hx4700.o
48obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o 46obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o
49obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o 47obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
50obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o 48obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o
51obj-$(CONFIG_SND_SOC_SAARB) += snd-soc-saarb.o
52obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o
53obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o 49obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
54obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o 50obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o
55obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o 51obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
index 349930015264..5d57e071cdf5 100644
--- a/sound/soc/pxa/mmp-pcm.c
+++ b/sound/soc/pxa/mmp-pcm.c
@@ -147,7 +147,7 @@ static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
147 vma->vm_end - vma->vm_start, vma->vm_page_prot); 147 vma->vm_end - vma->vm_start, vma->vm_page_prot);
148} 148}
149 149
150struct snd_pcm_ops mmp_pcm_ops = { 150static struct snd_pcm_ops mmp_pcm_ops = {
151 .open = mmp_pcm_open, 151 .open = mmp_pcm_open,
152 .close = snd_dmaengine_pcm_close_release_chan, 152 .close = snd_dmaengine_pcm_close_release_chan,
153 .ioctl = snd_pcm_lib_ioctl, 153 .ioctl = snd_pcm_lib_ioctl,
@@ -208,7 +208,7 @@ static int mmp_pcm_preallocate_dma_buffer(struct snd_pcm_substream *substream,
208 return 0; 208 return 0;
209} 209}
210 210
211int mmp_pcm_new(struct snd_soc_pcm_runtime *rtd) 211static int mmp_pcm_new(struct snd_soc_pcm_runtime *rtd)
212{ 212{
213 struct snd_pcm_substream *substream; 213 struct snd_pcm_substream *substream;
214 struct snd_pcm *pcm = rtd->pcm; 214 struct snd_pcm *pcm = rtd->pcm;
@@ -229,7 +229,7 @@ err:
229 return ret; 229 return ret;
230} 230}
231 231
232struct snd_soc_platform_driver mmp_soc_platform = { 232static struct snd_soc_platform_driver mmp_soc_platform = {
233 .ops = &mmp_pcm_ops, 233 .ops = &mmp_pcm_ops,
234 .pcm_new = mmp_pcm_new, 234 .pcm_new = mmp_pcm_new,
235 .pcm_free = mmp_pcm_free_dma_buffers, 235 .pcm_free = mmp_pcm_free_dma_buffers,
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index a64779980177..62142ce367c7 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -388,7 +388,7 @@ static struct snd_soc_dai_ops mmp_sspa_dai_ops = {
388 .set_fmt = mmp_sspa_set_dai_fmt, 388 .set_fmt = mmp_sspa_set_dai_fmt,
389}; 389};
390 390
391struct snd_soc_dai_driver mmp_sspa_dai = { 391static struct snd_soc_dai_driver mmp_sspa_dai = {
392 .probe = mmp_sspa_probe, 392 .probe = mmp_sspa_probe,
393 .playback = { 393 .playback = {
394 .channels_min = 1, 394 .channels_min = 1,
diff --git a/sound/soc/pxa/saarb.c b/sound/soc/pxa/saarb.c
deleted file mode 100644
index c34146b776b4..000000000000
--- a/sound/soc/pxa/saarb.c
+++ /dev/null
@@ -1,190 +0,0 @@
1/*
2 * saarb.c -- SoC audio for saarb
3 *
4 * Copyright (C) 2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/device.h>
15#include <linux/clk.h>
16#include <linux/i2c.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h>
21#include <sound/jack.h>
22
23#include <asm/mach-types.h>
24
25#include "../codecs/88pm860x-codec.h"
26#include "pxa-ssp.h"
27
28static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd);
29
30static struct platform_device *saarb_snd_device;
31
32static struct snd_soc_jack hs_jack, mic_jack;
33
34static struct snd_soc_jack_pin hs_jack_pins[] = {
35 { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, },
36};
37
38static struct snd_soc_jack_pin mic_jack_pins[] = {
39 { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, },
40};
41
42/* saarb machine dapm widgets */
43static const struct snd_soc_dapm_widget saarb_dapm_widgets[] = {
44 SND_SOC_DAPM_HP("Headphone Stereophone", NULL),
45 SND_SOC_DAPM_LINE("Lineout Out 1", NULL),
46 SND_SOC_DAPM_LINE("Lineout Out 2", NULL),
47 SND_SOC_DAPM_SPK("Ext Speaker", NULL),
48 SND_SOC_DAPM_MIC("Ext Mic 1", NULL),
49 SND_SOC_DAPM_MIC("Headset Mic", NULL),
50 SND_SOC_DAPM_MIC("Ext Mic 3", NULL),
51};
52
53/* saarb machine audio map */
54static const struct snd_soc_dapm_route saarb_audio_map[] = {
55 {"Headset Stereophone", NULL, "HS1"},
56 {"Headset Stereophone", NULL, "HS2"},
57
58 {"Ext Speaker", NULL, "LSP"},
59 {"Ext Speaker", NULL, "LSN"},
60
61 {"Lineout Out 1", NULL, "LINEOUT1"},
62 {"Lineout Out 2", NULL, "LINEOUT2"},
63
64 {"MIC1P", NULL, "Mic1 Bias"},
65 {"MIC1N", NULL, "Mic1 Bias"},
66 {"Mic1 Bias", NULL, "Ext Mic 1"},
67
68 {"MIC2P", NULL, "Mic1 Bias"},
69 {"MIC2N", NULL, "Mic1 Bias"},
70 {"Mic1 Bias", NULL, "Headset Mic 2"},
71
72 {"MIC3P", NULL, "Mic3 Bias"},
73 {"MIC3N", NULL, "Mic3 Bias"},
74 {"Mic3 Bias", NULL, "Ext Mic 3"},
75};
76
77static int saarb_i2s_hw_params(struct snd_pcm_substream *substream,
78 struct snd_pcm_hw_params *params)
79{
80 struct snd_soc_pcm_runtime *rtd = substream->private_data;
81 struct snd_soc_dai *codec_dai = rtd->codec_dai;
82 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
83 int width = snd_pcm_format_physical_width(params_format(params));
84 int ret;
85
86 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0,
87 PM860X_CLK_DIR_OUT);
88 if (ret < 0)
89 return ret;
90
91 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT);
92 if (ret < 0)
93 return ret;
94
95 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
96
97 return ret;
98}
99
100static struct snd_soc_ops saarb_i2s_ops = {
101 .hw_params = saarb_i2s_hw_params,
102};
103
104static struct snd_soc_dai_link saarb_dai[] = {
105 {
106 .name = "88PM860x I2S",
107 .stream_name = "I2S Audio",
108 .cpu_dai_name = "pxa-ssp-dai.1",
109 .codec_dai_name = "88pm860x-i2s",
110 .platform_name = "pxa-pcm-audio",
111 .codec_name = "88pm860x-codec",
112 .init = saarb_pm860x_init,
113 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
114 SND_SOC_DAIFMT_CBM_CFM,
115 .ops = &saarb_i2s_ops,
116 },
117};
118
119static struct snd_soc_card snd_soc_card_saarb = {
120 .name = "Saarb",
121 .owner = THIS_MODULE,
122 .dai_link = saarb_dai,
123 .num_links = ARRAY_SIZE(saarb_dai),
124
125 .dapm_widgets = saarb_dapm_widgets,
126 .num_dapm_widgets = ARRAY_SIZE(saarb_dapm_widgets),
127 .dapm_routes = saarb_audio_map,
128 .num_dapm_routes = ARRAY_SIZE(saarb_audio_map),
129};
130
131static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd)
132{
133 struct snd_soc_codec *codec = rtd->codec;
134 struct snd_soc_dapm_context *dapm = &codec->dapm;
135
136 /* connected pins */
137 snd_soc_dapm_enable_pin(dapm, "Ext Speaker");
138 snd_soc_dapm_enable_pin(dapm, "Ext Mic 1");
139 snd_soc_dapm_enable_pin(dapm, "Ext Mic 3");
140 snd_soc_dapm_disable_pin(dapm, "Headset Mic 2");
141 snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
142
143 /* Headset jack detection */
144 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
145 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
146 &hs_jack);
147 snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
148 hs_jack_pins);
149 snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE,
150 &mic_jack);
151 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
152 mic_jack_pins);
153
154 /* headphone, microphone detection & headset short detection */
155 pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE,
156 SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2);
157 pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE);
158 return 0;
159}
160
161static int __init saarb_init(void)
162{
163 int ret;
164
165 if (!machine_is_saarb())
166 return -ENODEV;
167 saarb_snd_device = platform_device_alloc("soc-audio", -1);
168 if (!saarb_snd_device)
169 return -ENOMEM;
170
171 platform_set_drvdata(saarb_snd_device, &snd_soc_card_saarb);
172
173 ret = platform_device_add(saarb_snd_device);
174 if (ret)
175 platform_device_put(saarb_snd_device);
176
177 return ret;
178}
179
180static void __exit saarb_exit(void)
181{
182 platform_device_unregister(saarb_snd_device);
183}
184
185module_init(saarb_init);
186module_exit(saarb_exit);
187
188MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
189MODULE_DESCRIPTION("ALSA SoC 88PM860x Saarb");
190MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/tavorevb3.c b/sound/soc/pxa/tavorevb3.c
deleted file mode 100644
index 8b5ab8f72726..000000000000
--- a/sound/soc/pxa/tavorevb3.c
+++ /dev/null
@@ -1,189 +0,0 @@
1/*
2 * tavorevb3.c -- SoC audio for Tavor EVB3
3 *
4 * Copyright (C) 2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/device.h>
15#include <linux/clk.h>
16#include <linux/i2c.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h>
21#include <sound/jack.h>
22
23#include <asm/mach-types.h>
24
25#include "../codecs/88pm860x-codec.h"
26#include "pxa-ssp.h"
27
28static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd);
29
30static struct platform_device *evb3_snd_device;
31
32static struct snd_soc_jack hs_jack, mic_jack;
33
34static struct snd_soc_jack_pin hs_jack_pins[] = {
35 { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, },
36};
37
38static struct snd_soc_jack_pin mic_jack_pins[] = {
39 { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, },
40};
41
42/* tavorevb3 machine dapm widgets */
43static const struct snd_soc_dapm_widget evb3_dapm_widgets[] = {
44 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
45 SND_SOC_DAPM_LINE("Lineout Out 1", NULL),
46 SND_SOC_DAPM_LINE("Lineout Out 2", NULL),
47 SND_SOC_DAPM_SPK("Ext Speaker", NULL),
48 SND_SOC_DAPM_MIC("Ext Mic 1", NULL),
49 SND_SOC_DAPM_MIC("Headset Mic 2", NULL),
50 SND_SOC_DAPM_MIC("Ext Mic 3", NULL),
51};
52
53/* tavorevb3 machine audio map */
54static const struct snd_soc_dapm_route evb3_audio_map[] = {
55 {"Headset Stereophone", NULL, "HS1"},
56 {"Headset Stereophone", NULL, "HS2"},
57
58 {"Ext Speaker", NULL, "LSP"},
59 {"Ext Speaker", NULL, "LSN"},
60
61 {"Lineout Out 1", NULL, "LINEOUT1"},
62 {"Lineout Out 2", NULL, "LINEOUT2"},
63
64 {"MIC1P", NULL, "Mic1 Bias"},
65 {"MIC1N", NULL, "Mic1 Bias"},
66 {"Mic1 Bias", NULL, "Ext Mic 1"},
67
68 {"MIC2P", NULL, "Mic1 Bias"},
69 {"MIC2N", NULL, "Mic1 Bias"},
70 {"Mic1 Bias", NULL, "Headset Mic 2"},
71
72 {"MIC3P", NULL, "Mic3 Bias"},
73 {"MIC3N", NULL, "Mic3 Bias"},
74 {"Mic3 Bias", NULL, "Ext Mic 3"},
75};
76
77static int evb3_i2s_hw_params(struct snd_pcm_substream *substream,
78 struct snd_pcm_hw_params *params)
79{
80 struct snd_soc_pcm_runtime *rtd = substream->private_data;
81 struct snd_soc_dai *codec_dai = rtd->codec_dai;
82 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
83 int width = snd_pcm_format_physical_width(params_format(params));
84 int ret;
85
86 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0,
87 PM860X_CLK_DIR_OUT);
88 if (ret < 0)
89 return ret;
90
91 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT);
92 if (ret < 0)
93 return ret;
94
95 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
96 return ret;
97}
98
99static struct snd_soc_ops evb3_i2s_ops = {
100 .hw_params = evb3_i2s_hw_params,
101};
102
103static struct snd_soc_dai_link evb3_dai[] = {
104 {
105 .name = "88PM860x I2S",
106 .stream_name = "I2S Audio",
107 .cpu_dai_name = "pxa-ssp-dai.1",
108 .codec_dai_name = "88pm860x-i2s",
109 .platform_name = "pxa-pcm-audio",
110 .codec_name = "88pm860x-codec",
111 .init = evb3_pm860x_init,
112 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
113 SND_SOC_DAIFMT_CBM_CFM,
114 .ops = &evb3_i2s_ops,
115 },
116};
117
118static struct snd_soc_card snd_soc_card_evb3 = {
119 .name = "Tavor EVB3",
120 .owner = THIS_MODULE,
121 .dai_link = evb3_dai,
122 .num_links = ARRAY_SIZE(evb3_dai),
123
124 .dapm_widgets = evb3_dapm_widgets,
125 .num_dapm_widgets = ARRAY_SIZE(evb3_dapm_widgets),
126 .dapm_routes = evb3_audio_map,
127 .num_dapm_routes = ARRAY_SIZE(evb3_audio_map),
128};
129
130static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd)
131{
132 struct snd_soc_codec *codec = rtd->codec;
133 struct snd_soc_dapm_context *dapm = &codec->dapm;
134
135 /* connected pins */
136 snd_soc_dapm_enable_pin(dapm, "Ext Speaker");
137 snd_soc_dapm_enable_pin(dapm, "Ext Mic 1");
138 snd_soc_dapm_enable_pin(dapm, "Ext Mic 3");
139 snd_soc_dapm_disable_pin(dapm, "Headset Mic 2");
140 snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
141
142 /* Headset jack detection */
143 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
144 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
145 &hs_jack);
146 snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
147 hs_jack_pins);
148 snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE,
149 &mic_jack);
150 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
151 mic_jack_pins);
152
153 /* headphone, microphone detection & headset short detection */
154 pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE,
155 SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2);
156 pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE);
157 return 0;
158}
159
160static int __init tavorevb3_init(void)
161{
162 int ret;
163
164 if (!machine_is_tavorevb3())
165 return -ENODEV;
166 evb3_snd_device = platform_device_alloc("soc-audio", -1);
167 if (!evb3_snd_device)
168 return -ENOMEM;
169
170 platform_set_drvdata(evb3_snd_device, &snd_soc_card_evb3);
171
172 ret = platform_device_add(evb3_snd_device);
173 if (ret)
174 platform_device_put(evb3_snd_device);
175
176 return ret;
177}
178
179static void __exit tavorevb3_exit(void)
180{
181 platform_device_unregister(evb3_snd_device);
182}
183
184module_init(tavorevb3_init);
185module_exit(tavorevb3_exit);
186
187MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
188MODULE_DESCRIPTION("ALSA SoC 88PM860x Tavor EVB3");
189MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
index ceb656695b0f..db8aadf8932d 100644
--- a/sound/soc/pxa/zylonite.c
+++ b/sound/soc/pxa/zylonite.c
@@ -256,7 +256,6 @@ static struct snd_soc_card zylonite = {
256 .resume_pre = &zylonite_resume_pre, 256 .resume_pre = &zylonite_resume_pre,
257 .dai_link = zylonite_dai, 257 .dai_link = zylonite_dai,
258 .num_links = ARRAY_SIZE(zylonite_dai), 258 .num_links = ARRAY_SIZE(zylonite_dai),
259 .owner = THIS_MODULE,
260}; 259};
261 260
262static struct platform_device *zylonite_snd_ac97_device; 261static struct platform_device *zylonite_snd_ac97_device;
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 475fb0d8b3c6..ae0ea87b7d7b 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -39,7 +39,7 @@ config SND_SOC_SAMSUNG_NEO1973_WM8753
39 depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA02 39 depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA02
40 select SND_S3C24XX_I2S 40 select SND_S3C24XX_I2S
41 select SND_SOC_WM8753 41 select SND_SOC_WM8753
42 select SND_SOC_DFBMCS320 42 select SND_SOC_SCO
43 help 43 help
44 Say Y here to enable audio support for the Openmoko Neo1973 44 Say Y here to enable audio support for the Openmoko Neo1973
45 Smartphones. 45 Smartphones.
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
index ceed466af9ff..29e246803626 100644
--- a/sound/soc/samsung/bells.c
+++ b/sound/soc/samsung/bells.c
@@ -350,8 +350,16 @@ static struct snd_soc_codec_conf bells_codec_conf[] = {
350 }, 350 },
351}; 351};
352 352
353static struct snd_soc_dapm_widget bells_widgets[] = {
354 SND_SOC_DAPM_MIC("DMIC", NULL),
355};
356
353static struct snd_soc_dapm_route bells_routes[] = { 357static struct snd_soc_dapm_route bells_routes[] = {
354 { "Sub CLK_SYS", NULL, "OPCLK" }, 358 { "Sub CLK_SYS", NULL, "OPCLK" },
359
360 { "DMIC", NULL, "MICBIAS2" },
361 { "IN2L", NULL, "DMIC" },
362 { "IN2R", NULL, "DMIC" },
355}; 363};
356 364
357static struct snd_soc_card bells_cards[] = { 365static struct snd_soc_card bells_cards[] = {
@@ -365,6 +373,8 @@ static struct snd_soc_card bells_cards[] = {
365 373
366 .late_probe = bells_late_probe, 374 .late_probe = bells_late_probe,
367 375
376 .dapm_widgets = bells_widgets,
377 .num_dapm_widgets = ARRAY_SIZE(bells_widgets),
368 .dapm_routes = bells_routes, 378 .dapm_routes = bells_routes,
369 .num_dapm_routes = ARRAY_SIZE(bells_routes), 379 .num_dapm_routes = ARRAY_SIZE(bells_routes),
370 380
@@ -383,6 +393,8 @@ static struct snd_soc_card bells_cards[] = {
383 393
384 .late_probe = bells_late_probe, 394 .late_probe = bells_late_probe,
385 395
396 .dapm_widgets = bells_widgets,
397 .num_dapm_widgets = ARRAY_SIZE(bells_widgets),
386 .dapm_routes = bells_routes, 398 .dapm_routes = bells_routes,
387 .num_dapm_routes = ARRAY_SIZE(bells_routes), 399 .num_dapm_routes = ARRAY_SIZE(bells_routes),
388 400
@@ -401,6 +413,8 @@ static struct snd_soc_card bells_cards[] = {
401 413
402 .late_probe = bells_late_probe, 414 .late_probe = bells_late_probe,
403 415
416 .dapm_widgets = bells_widgets,
417 .num_dapm_widgets = ARRAY_SIZE(bells_widgets),
404 .dapm_routes = bells_routes, 418 .dapm_routes = bells_routes,
405 .num_dapm_routes = ARRAY_SIZE(bells_routes), 419 .num_dapm_routes = ARRAY_SIZE(bells_routes),
406 420
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index e591c386917a..807db417d234 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -373,7 +373,7 @@ static struct snd_soc_dai_link neo1973_dai[] = {
373{ /* Voice via BT */ 373{ /* Voice via BT */
374 .name = "Bluetooth", 374 .name = "Bluetooth",
375 .stream_name = "Voice", 375 .stream_name = "Voice",
376 .cpu_dai_name = "dfbmcs320-pcm", 376 .cpu_dai_name = "bt-sco-pcm",
377 .codec_dai_name = "wm8753-voice", 377 .codec_dai_name = "wm8753-voice",
378 .codec_name = "wm8753.0-001a", 378 .codec_name = "wm8753.0-001a",
379 .ops = &neo1973_voice_ops, 379 .ops = &neo1973_voice_ops,
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c
index e43bd4294f99..23a9204b106d 100644
--- a/sound/soc/samsung/smdk_wm8580pcm.c
+++ b/sound/soc/samsung/smdk_wm8580pcm.c
@@ -176,7 +176,6 @@ static int snd_smdk_probe(struct platform_device *pdev)
176static int snd_smdk_remove(struct platform_device *pdev) 176static int snd_smdk_remove(struct platform_device *pdev)
177{ 177{
178 snd_soc_unregister_card(&smdk_pcm); 178 snd_soc_unregister_card(&smdk_pcm);
179 platform_set_drvdata(pdev, NULL);
180 return 0; 179 return 0;
181} 180}
182 181
diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c
index 3688a32000a2..0c84ca099612 100644
--- a/sound/soc/samsung/smdk_wm8994pcm.c
+++ b/sound/soc/samsung/smdk_wm8994pcm.c
@@ -146,7 +146,6 @@ static int snd_smdk_probe(struct platform_device *pdev)
146static int snd_smdk_remove(struct platform_device *pdev) 146static int snd_smdk_remove(struct platform_device *pdev)
147{ 147{
148 snd_soc_unregister_card(&smdk_pcm); 148 snd_soc_unregister_card(&smdk_pcm);
149 platform_set_drvdata(pdev, NULL);
150 return 0; 149 return 0;
151} 150}
152 151
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index f830c41f97dd..30390260bb67 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -276,7 +276,7 @@ struct fsi_stream_handler {
276 int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev); 276 int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev);
277 int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io); 277 int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io);
278 int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io); 278 int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io);
279 void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io, 279 int (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io,
280 int enable); 280 int enable);
281}; 281};
282#define fsi_stream_handler_call(io, func, args...) \ 282#define fsi_stream_handler_call(io, func, args...) \
@@ -1188,7 +1188,7 @@ static int fsi_pio_push(struct fsi_priv *fsi, struct fsi_stream *io)
1188 samples); 1188 samples);
1189} 1189}
1190 1190
1191static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, 1191static int fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
1192 int enable) 1192 int enable)
1193{ 1193{
1194 struct fsi_master *master = fsi_get_master(fsi); 1194 struct fsi_master *master = fsi_get_master(fsi);
@@ -1201,6 +1201,8 @@ static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
1201 1201
1202 if (fsi_is_clk_master(fsi)) 1202 if (fsi_is_clk_master(fsi))
1203 fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); 1203 fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
1204
1205 return 0;
1204} 1206}
1205 1207
1206static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io) 1208static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
@@ -1409,7 +1411,7 @@ static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
1409 return 0; 1411 return 0;
1410} 1412}
1411 1413
1412static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, 1414static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
1413 int start) 1415 int start)
1414{ 1416{
1415 struct fsi_master *master = fsi_get_master(fsi); 1417 struct fsi_master *master = fsi_get_master(fsi);
@@ -1422,6 +1424,8 @@ static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
1422 1424
1423 if (fsi_is_clk_master(fsi)) 1425 if (fsi_is_clk_master(fsi))
1424 fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); 1426 fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
1427
1428 return 0;
1425} 1429}
1426 1430
1427static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev) 1431static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index d56bbea6e75e..4489c5b7b53a 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -272,8 +272,8 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
272 codec->debugfs_codec_root = debugfs_create_dir(codec->name, 272 codec->debugfs_codec_root = debugfs_create_dir(codec->name,
273 debugfs_card_root); 273 debugfs_card_root);
274 if (!codec->debugfs_codec_root) { 274 if (!codec->debugfs_codec_root) {
275 dev_warn(codec->dev, "ASoC: Failed to create codec debugfs" 275 dev_warn(codec->dev,
276 " directory\n"); 276 "ASoC: Failed to create codec debugfs directory\n");
277 return; 277 return;
278 } 278 }
279 279
@@ -286,8 +286,8 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
286 codec->debugfs_codec_root, 286 codec->debugfs_codec_root,
287 codec, &codec_reg_fops); 287 codec, &codec_reg_fops);
288 if (!codec->debugfs_reg) 288 if (!codec->debugfs_reg)
289 dev_warn(codec->dev, "ASoC: Failed to create codec register" 289 dev_warn(codec->dev,
290 " debugfs file\n"); 290 "ASoC: Failed to create codec register debugfs file\n");
291 291
292 snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root); 292 snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root);
293} 293}
@@ -631,8 +631,7 @@ int snd_soc_suspend(struct device *dev)
631 */ 631 */
632 if (codec->dapm.idle_bias_off) { 632 if (codec->dapm.idle_bias_off) {
633 dev_dbg(codec->dev, 633 dev_dbg(codec->dev,
634 "ASoC: idle_bias_off CODEC on" 634 "ASoC: idle_bias_off CODEC on over suspend\n");
635 " over suspend\n");
636 break; 635 break;
637 } 636 }
638 case SND_SOC_BIAS_OFF: 637 case SND_SOC_BIAS_OFF:
@@ -643,8 +642,8 @@ int snd_soc_suspend(struct device *dev)
643 regcache_mark_dirty(codec->control_data); 642 regcache_mark_dirty(codec->control_data);
644 break; 643 break;
645 default: 644 default:
646 dev_dbg(codec->dev, "ASoC: CODEC is on" 645 dev_dbg(codec->dev,
647 " over suspend\n"); 646 "ASoC: CODEC is on over suspend\n");
648 break; 647 break;
649 } 648 }
650 } 649 }
@@ -713,8 +712,8 @@ static void soc_resume_deferred(struct work_struct *work)
713 codec->suspended = 0; 712 codec->suspended = 0;
714 break; 713 break;
715 default: 714 default:
716 dev_dbg(codec->dev, "ASoC: CODEC was on over" 715 dev_dbg(codec->dev,
717 " suspend\n"); 716 "ASoC: CODEC was on over suspend\n");
718 break; 717 break;
719 } 718 }
720 } 719 }
@@ -1110,8 +1109,8 @@ static int soc_probe_codec(struct snd_soc_card *card,
1110 } 1109 }
1111 WARN(codec->dapm.idle_bias_off && 1110 WARN(codec->dapm.idle_bias_off &&
1112 codec->dapm.bias_level != SND_SOC_BIAS_OFF, 1111 codec->dapm.bias_level != SND_SOC_BIAS_OFF,
1113 "codec %s can not start from non-off bias" 1112 "codec %s can not start from non-off bias with idle_bias_off==1\n",
1114 " with idle_bias_off==1\n", codec->name); 1113 codec->name);
1115 } 1114 }
1116 1115
1117 /* If the driver didn't set I/O up try regmap */ 1116 /* If the driver didn't set I/O up try regmap */
@@ -1582,8 +1581,9 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
1582 codec->compress_type = compress_type; 1581 codec->compress_type = compress_type;
1583 ret = snd_soc_cache_init(codec); 1582 ret = snd_soc_cache_init(codec);
1584 if (ret < 0) { 1583 if (ret < 0) {
1585 dev_err(codec->dev, "ASoC: Failed to set cache compression" 1584 dev_err(codec->dev,
1586 " type: %d\n", ret); 1585 "ASoC: Failed to set cache compression type: %d\n",
1586 ret);
1587 return ret; 1587 return ret;
1588 } 1588 }
1589 codec->cache_init = 1; 1589 codec->cache_init = 1;
@@ -1639,8 +1639,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
1639 ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, 1639 ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
1640 card->owner, 0, &card->snd_card); 1640 card->owner, 0, &card->snd_card);
1641 if (ret < 0) { 1641 if (ret < 0) {
1642 dev_err(card->dev, "ASoC: can't create sound card for" 1642 dev_err(card->dev,
1643 " card %s: %d\n", card->name, ret); 1643 "ASoC: can't create sound card for card %s: %d\n",
1644 card->name, ret);
1644 goto base_error; 1645 goto base_error;
1645 } 1646 }
1646 card->snd_card->dev = card->dev; 1647 card->snd_card->dev = card->dev;
@@ -1815,8 +1816,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
1815 for (i = 0; i < card->num_rtd; i++) { 1816 for (i = 0; i < card->num_rtd; i++) {
1816 ret = soc_register_ac97_dai_link(&card->rtd[i]); 1817 ret = soc_register_ac97_dai_link(&card->rtd[i]);
1817 if (ret < 0) { 1818 if (ret < 0) {
1818 dev_err(card->dev, "ASoC: failed to register AC97:" 1819 dev_err(card->dev,
1819 " %d\n", ret); 1820 "ASoC: failed to register AC97: %d\n", ret);
1820 while (--i >= 0) 1821 while (--i >= 0)
1821 soc_unregister_ac97_dai_link(card->rtd[i].codec); 1822 soc_unregister_ac97_dai_link(card->rtd[i].codec);
1822 goto probe_aux_dev_err; 1823 goto probe_aux_dev_err;
@@ -2219,29 +2220,6 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
2219EXPORT_SYMBOL_GPL(snd_soc_test_bits); 2220EXPORT_SYMBOL_GPL(snd_soc_test_bits);
2220 2221
2221/** 2222/**
2222 * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
2223 * @substream: the pcm substream
2224 * @hw: the hardware parameters
2225 *
2226 * Sets the substream runtime hardware parameters.
2227 */
2228int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
2229 const struct snd_pcm_hardware *hw)
2230{
2231 struct snd_pcm_runtime *runtime = substream->runtime;
2232 runtime->hw.info = hw->info;
2233 runtime->hw.formats = hw->formats;
2234 runtime->hw.period_bytes_min = hw->period_bytes_min;
2235 runtime->hw.period_bytes_max = hw->period_bytes_max;
2236 runtime->hw.periods_min = hw->periods_min;
2237 runtime->hw.periods_max = hw->periods_max;
2238 runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
2239 runtime->hw.fifo_size = hw->fifo_size;
2240 return 0;
2241}
2242EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
2243
2244/**
2245 * snd_soc_cnew - create new control 2223 * snd_soc_cnew - create new control
2246 * @_template: control template 2224 * @_template: control template
2247 * @data: control private data 2225 * @data: control private data
@@ -2259,7 +2237,6 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
2259 struct snd_kcontrol_new template; 2237 struct snd_kcontrol_new template;
2260 struct snd_kcontrol *kcontrol; 2238 struct snd_kcontrol *kcontrol;
2261 char *name = NULL; 2239 char *name = NULL;
2262 int name_len;
2263 2240
2264 memcpy(&template, _template, sizeof(template)); 2241 memcpy(&template, _template, sizeof(template));
2265 template.index = 0; 2242 template.index = 0;
@@ -2268,13 +2245,10 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
2268 long_name = template.name; 2245 long_name = template.name;
2269 2246
2270 if (prefix) { 2247 if (prefix) {
2271 name_len = strlen(long_name) + strlen(prefix) + 2; 2248 name = kasprintf(GFP_KERNEL, "%s %s", prefix, long_name);
2272 name = kmalloc(name_len, GFP_KERNEL);
2273 if (!name) 2249 if (!name)
2274 return NULL; 2250 return NULL;
2275 2251
2276 snprintf(name, name_len, "%s %s", prefix, long_name);
2277
2278 template.name = name; 2252 template.name = name;
2279 } else { 2253 } else {
2280 template.name = long_name; 2254 template.name = long_name;
@@ -3586,14 +3560,16 @@ int snd_soc_register_card(struct snd_soc_card *card)
3586 * not both or neither. 3560 * not both or neither.
3587 */ 3561 */
3588 if (!!link->codec_name == !!link->codec_of_node) { 3562 if (!!link->codec_name == !!link->codec_of_node) {
3589 dev_err(card->dev, "ASoC: Neither/both codec" 3563 dev_err(card->dev,
3590 " name/of_node are set for %s\n", link->name); 3564 "ASoC: Neither/both codec name/of_node are set for %s\n",
3565 link->name);
3591 return -EINVAL; 3566 return -EINVAL;
3592 } 3567 }
3593 /* Codec DAI name must be specified */ 3568 /* Codec DAI name must be specified */
3594 if (!link->codec_dai_name) { 3569 if (!link->codec_dai_name) {
3595 dev_err(card->dev, "ASoC: codec_dai_name not" 3570 dev_err(card->dev,
3596 " set for %s\n", link->name); 3571 "ASoC: codec_dai_name not set for %s\n",
3572 link->name);
3597 return -EINVAL; 3573 return -EINVAL;
3598 } 3574 }
3599 3575
@@ -3602,8 +3578,9 @@ int snd_soc_register_card(struct snd_soc_card *card)
3602 * can be left unspecified, and a dummy platform will be used. 3578 * can be left unspecified, and a dummy platform will be used.
3603 */ 3579 */
3604 if (link->platform_name && link->platform_of_node) { 3580 if (link->platform_name && link->platform_of_node) {
3605 dev_err(card->dev, "ASoC: Both platform name/of_node" 3581 dev_err(card->dev,
3606 " are set for %s\n", link->name); 3582 "ASoC: Both platform name/of_node are set for %s\n",
3583 link->name);
3607 return -EINVAL; 3584 return -EINVAL;
3608 } 3585 }
3609 3586
@@ -3613,8 +3590,9 @@ int snd_soc_register_card(struct snd_soc_card *card)
3613 * name alone.. 3590 * name alone..
3614 */ 3591 */
3615 if (link->cpu_name && link->cpu_of_node) { 3592 if (link->cpu_name && link->cpu_of_node) {
3616 dev_err(card->dev, "ASoC: Neither/both " 3593 dev_err(card->dev,
3617 "cpu name/of_node are set for %s\n",link->name); 3594 "ASoC: Neither/both cpu name/of_node are set for %s\n",
3595 link->name);
3618 return -EINVAL; 3596 return -EINVAL;
3619 } 3597 }
3620 /* 3598 /*
@@ -3623,8 +3601,9 @@ int snd_soc_register_card(struct snd_soc_card *card)
3623 */ 3601 */
3624 if (!link->cpu_dai_name && 3602 if (!link->cpu_dai_name &&
3625 !(link->cpu_name || link->cpu_of_node)) { 3603 !(link->cpu_name || link->cpu_of_node)) {
3626 dev_err(card->dev, "ASoC: Neither cpu_dai_name nor " 3604 dev_err(card->dev,
3627 "cpu_name/of_node are set for %s\n", link->name); 3605 "ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
3606 link->name);
3628 return -EINVAL; 3607 return -EINVAL;
3629 } 3608 }
3630 } 3609 }
@@ -3728,8 +3707,9 @@ static inline char *fmt_multiple_name(struct device *dev,
3728 struct snd_soc_dai_driver *dai_drv) 3707 struct snd_soc_dai_driver *dai_drv)
3729{ 3708{
3730 if (dai_drv->name == NULL) { 3709 if (dai_drv->name == NULL) {
3731 dev_err(dev, "ASoC: error - multiple DAI %s registered with" 3710 dev_err(dev,
3732 " no name\n", dev_name(dev)); 3711 "ASoC: error - multiple DAI %s registered with no name\n",
3712 dev_name(dev));
3733 return NULL; 3713 return NULL;
3734 } 3714 }
3735 3715
@@ -3859,8 +3839,9 @@ static int snd_soc_register_dais(struct device *dev,
3859 3839
3860 list_for_each_entry(codec, &codec_list, list) { 3840 list_for_each_entry(codec, &codec_list, list) {
3861 if (codec->dev == dev) { 3841 if (codec->dev == dev) {
3862 dev_dbg(dev, "ASoC: Mapped DAI %s to " 3842 dev_dbg(dev,
3863 "CODEC %s\n", dai->name, codec->name); 3843 "ASoC: Mapped DAI %s to CODEC %s\n",
3844 dai->name, codec->name);
3864 dai->codec = codec; 3845 dai->codec = codec;
3865 break; 3846 break;
3866 } 3847 }
@@ -4296,8 +4277,9 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
4296 4277
4297 num_routes = of_property_count_strings(np, propname); 4278 num_routes = of_property_count_strings(np, propname);
4298 if (num_routes < 0 || num_routes & 1) { 4279 if (num_routes < 0 || num_routes & 1) {
4299 dev_err(card->dev, "ASoC: Property '%s' does not exist or its" 4280 dev_err(card->dev,
4300 " length is not even\n", propname); 4281 "ASoC: Property '%s' does not exist or its length is not even\n",
4282 propname);
4301 return -EINVAL; 4283 return -EINVAL;
4302 } 4284 }
4303 num_routes /= 2; 4285 num_routes /= 2;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index c7051c457b75..b94190820e8c 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -64,6 +64,7 @@ static int dapm_up_seq[] = {
64 [snd_soc_dapm_virt_mux] = 5, 64 [snd_soc_dapm_virt_mux] = 5,
65 [snd_soc_dapm_value_mux] = 5, 65 [snd_soc_dapm_value_mux] = 5,
66 [snd_soc_dapm_dac] = 6, 66 [snd_soc_dapm_dac] = 6,
67 [snd_soc_dapm_switch] = 7,
67 [snd_soc_dapm_mixer] = 7, 68 [snd_soc_dapm_mixer] = 7,
68 [snd_soc_dapm_mixer_named_ctl] = 7, 69 [snd_soc_dapm_mixer_named_ctl] = 7,
69 [snd_soc_dapm_pga] = 8, 70 [snd_soc_dapm_pga] = 8,
@@ -83,6 +84,7 @@ static int dapm_down_seq[] = {
83 [snd_soc_dapm_line] = 2, 84 [snd_soc_dapm_line] = 2,
84 [snd_soc_dapm_out_drv] = 2, 85 [snd_soc_dapm_out_drv] = 2,
85 [snd_soc_dapm_pga] = 4, 86 [snd_soc_dapm_pga] = 4,
87 [snd_soc_dapm_switch] = 5,
86 [snd_soc_dapm_mixer_named_ctl] = 5, 88 [snd_soc_dapm_mixer_named_ctl] = 5,
87 [snd_soc_dapm_mixer] = 5, 89 [snd_soc_dapm_mixer] = 5,
88 [snd_soc_dapm_dac] = 6, 90 [snd_soc_dapm_dac] = 6,
@@ -365,11 +367,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
365 val = soc_widget_read(w, e->reg); 367 val = soc_widget_read(w, e->reg);
366 item = (val >> e->shift_l) & e->mask; 368 item = (val >> e->shift_l) & e->mask;
367 369
368 p->connect = 0; 370 if (item < e->max && !strcmp(p->name, e->texts[item]))
369 for (i = 0; i < e->max; i++) { 371 p->connect = 1;
370 if (!(strcmp(p->name, e->texts[i])) && item == i) 372 else
371 p->connect = 1; 373 p->connect = 0;
372 }
373 } 374 }
374 break; 375 break;
375 case snd_soc_dapm_virt_mux: { 376 case snd_soc_dapm_virt_mux: {
@@ -399,11 +400,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
399 break; 400 break;
400 } 401 }
401 402
402 p->connect = 0; 403 if (item < e->max && !strcmp(p->name, e->texts[item]))
403 for (i = 0; i < e->max; i++) { 404 p->connect = 1;
404 if (!(strcmp(p->name, e->texts[i])) && item == i) 405 else
405 p->connect = 1; 406 p->connect = 0;
406 }
407 } 407 }
408 break; 408 break;
409 /* does not affect routing - always connected */ 409 /* does not affect routing - always connected */
@@ -507,6 +507,11 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
507 return 0; 507 return 0;
508} 508}
509 509
510static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
511{
512 kfree(kctl->private_data);
513}
514
510/* 515/*
511 * Determine if a kcontrol is shared. If it is, look it up. If it isn't, 516 * Determine if a kcontrol is shared. If it is, look it up. If it isn't,
512 * create it. Either way, add the widget into the control's widget list 517 * create it. Either way, add the widget into the control's widget list
@@ -524,7 +529,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
524 int wlistentries; 529 int wlistentries;
525 size_t wlistsize; 530 size_t wlistsize;
526 bool wname_in_long_name, kcname_in_long_name; 531 bool wname_in_long_name, kcname_in_long_name;
527 size_t name_len;
528 char *long_name; 532 char *long_name;
529 const char *name; 533 const char *name;
530 int ret; 534 int ret;
@@ -589,25 +593,19 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
589 } 593 }
590 594
591 if (wname_in_long_name && kcname_in_long_name) { 595 if (wname_in_long_name && kcname_in_long_name) {
592 name_len = strlen(w->name) - prefix_len + 1 +
593 strlen(w->kcontrol_news[kci].name) + 1;
594
595 long_name = kmalloc(name_len, GFP_KERNEL);
596 if (long_name == NULL) {
597 kfree(wlist);
598 return -ENOMEM;
599 }
600
601 /* 596 /*
602 * The control will get a prefix from the control 597 * The control will get a prefix from the control
603 * creation process but we're also using the same 598 * creation process but we're also using the same
604 * prefix for widgets so cut the prefix off the 599 * prefix for widgets so cut the prefix off the
605 * front of the widget name. 600 * front of the widget name.
606 */ 601 */
607 snprintf(long_name, name_len, "%s %s", 602 long_name = kasprintf(GFP_KERNEL, "%s %s",
608 w->name + prefix_len, 603 w->name + prefix_len,
609 w->kcontrol_news[kci].name); 604 w->kcontrol_news[kci].name);
610 long_name[name_len - 1] = '\0'; 605 if (long_name == NULL) {
606 kfree(wlist);
607 return -ENOMEM;
608 }
611 609
612 name = long_name; 610 name = long_name;
613 } else if (wname_in_long_name) { 611 } else if (wname_in_long_name) {
@@ -620,17 +618,16 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
620 618
621 kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name, 619 kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], wlist, name,
622 prefix); 620 prefix);
621 kcontrol->private_free = dapm_kcontrol_free;
622 kfree(long_name);
623 ret = snd_ctl_add(card, kcontrol); 623 ret = snd_ctl_add(card, kcontrol);
624 if (ret < 0) { 624 if (ret < 0) {
625 dev_err(dapm->dev, 625 dev_err(dapm->dev,
626 "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", 626 "ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
627 w->name, name, ret); 627 w->name, name, ret);
628 kfree(wlist); 628 kfree(wlist);
629 kfree(long_name);
630 return ret; 629 return ret;
631 } 630 }
632
633 path->long_name = long_name;
634 } 631 }
635 632
636 kcontrol->private_data = wlist; 633 kcontrol->private_data = wlist;
@@ -1270,6 +1267,14 @@ static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm,
1270 ev_name = "POST_PMD"; 1267 ev_name = "POST_PMD";
1271 power = 0; 1268 power = 0;
1272 break; 1269 break;
1270 case SND_SOC_DAPM_WILL_PMU:
1271 ev_name = "WILL_PMU";
1272 power = 1;
1273 break;
1274 case SND_SOC_DAPM_WILL_PMD:
1275 ev_name = "WILL_PMD";
1276 power = 0;
1277 break;
1273 default: 1278 default:
1274 BUG(); 1279 BUG();
1275 return; 1280 return;
@@ -1730,6 +1735,14 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
1730 &async_domain); 1735 &async_domain);
1731 async_synchronize_full_domain(&async_domain); 1736 async_synchronize_full_domain(&async_domain);
1732 1737
1738 list_for_each_entry(w, &down_list, power_list) {
1739 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMD);
1740 }
1741
1742 list_for_each_entry(w, &up_list, power_list) {
1743 dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMU);
1744 }
1745
1733 /* Power down widgets first; try to avoid amplifying pops. */ 1746 /* Power down widgets first; try to avoid amplifying pops. */
1734 dapm_seq_run(dapm, &down_list, event, false); 1747 dapm_seq_run(dapm, &down_list, event, false);
1735 1748
@@ -2094,6 +2107,14 @@ static void snd_soc_dapm_sys_remove(struct device *dev)
2094 device_remove_file(dev, &dev_attr_dapm_widget); 2107 device_remove_file(dev, &dev_attr_dapm_widget);
2095} 2108}
2096 2109
2110static void dapm_free_path(struct snd_soc_dapm_path *path)
2111{
2112 list_del(&path->list_sink);
2113 list_del(&path->list_source);
2114 list_del(&path->list);
2115 kfree(path);
2116}
2117
2097/* free all dapm widgets and resources */ 2118/* free all dapm widgets and resources */
2098static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) 2119static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
2099{ 2120{
@@ -2109,20 +2130,12 @@ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
2109 * While removing the path, remove reference to it from both 2130 * While removing the path, remove reference to it from both
2110 * source and sink widgets so that path is removed only once. 2131 * source and sink widgets so that path is removed only once.
2111 */ 2132 */
2112 list_for_each_entry_safe(p, next_p, &w->sources, list_sink) { 2133 list_for_each_entry_safe(p, next_p, &w->sources, list_sink)
2113 list_del(&p->list_sink); 2134 dapm_free_path(p);
2114 list_del(&p->list_source); 2135
2115 list_del(&p->list); 2136 list_for_each_entry_safe(p, next_p, &w->sinks, list_source)
2116 kfree(p->long_name); 2137 dapm_free_path(p);
2117 kfree(p); 2138
2118 }
2119 list_for_each_entry_safe(p, next_p, &w->sinks, list_source) {
2120 list_del(&p->list_sink);
2121 list_del(&p->list_source);
2122 list_del(&p->list);
2123 kfree(p->long_name);
2124 kfree(p);
2125 }
2126 kfree(w->kcontrols); 2139 kfree(w->kcontrols);
2127 kfree(w->name); 2140 kfree(w->name);
2128 kfree(w); 2141 kfree(w);
@@ -2398,10 +2411,7 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
2398 dapm_mark_dirty(path->source, "Route removed"); 2411 dapm_mark_dirty(path->source, "Route removed");
2399 dapm_mark_dirty(path->sink, "Route removed"); 2412 dapm_mark_dirty(path->sink, "Route removed");
2400 2413
2401 list_del(&path->list); 2414 dapm_free_path(path);
2402 list_del(&path->list_sink);
2403 list_del(&path->list_source);
2404 kfree(path);
2405 } else { 2415 } else {
2406 dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n", 2416 dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n",
2407 source, sink); 2417 source, sink);
@@ -3055,7 +3065,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3055 const struct snd_soc_dapm_widget *widget) 3065 const struct snd_soc_dapm_widget *widget)
3056{ 3066{
3057 struct snd_soc_dapm_widget *w; 3067 struct snd_soc_dapm_widget *w;
3058 size_t name_len;
3059 int ret; 3068 int ret;
3060 3069
3061 if ((w = dapm_cnew_widget(widget)) == NULL) 3070 if ((w = dapm_cnew_widget(widget)) == NULL)
@@ -3096,19 +3105,16 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
3096 break; 3105 break;
3097 } 3106 }
3098 3107
3099 name_len = strlen(widget->name) + 1;
3100 if (dapm->codec && dapm->codec->name_prefix) 3108 if (dapm->codec && dapm->codec->name_prefix)
3101 name_len += 1 + strlen(dapm->codec->name_prefix); 3109 w->name = kasprintf(GFP_KERNEL, "%s %s",
3102 w->name = kmalloc(name_len, GFP_KERNEL); 3110 dapm->codec->name_prefix, widget->name);
3111 else
3112 w->name = kasprintf(GFP_KERNEL, "%s", widget->name);
3113
3103 if (w->name == NULL) { 3114 if (w->name == NULL) {
3104 kfree(w); 3115 kfree(w);
3105 return NULL; 3116 return NULL;
3106 } 3117 }
3107 if (dapm->codec && dapm->codec->name_prefix)
3108 snprintf((char *)w->name, name_len, "%s %s",
3109 dapm->codec->name_prefix, widget->name);
3110 else
3111 snprintf((char *)w->name, name_len, "%s", widget->name);
3112 3118
3113 switch (w->id) { 3119 switch (w->id) {
3114 case snd_soc_dapm_switch: 3120 case snd_soc_dapm_switch:
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index ccb6be4d658d..b6c640332a17 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -33,6 +33,29 @@
33 33
34#define DPCM_MAX_BE_USERS 8 34#define DPCM_MAX_BE_USERS 8
35 35
36/**
37 * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
38 * @substream: the pcm substream
39 * @hw: the hardware parameters
40 *
41 * Sets the substream runtime hardware parameters.
42 */
43int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
44 const struct snd_pcm_hardware *hw)
45{
46 struct snd_pcm_runtime *runtime = substream->runtime;
47 runtime->hw.info = hw->info;
48 runtime->hw.formats = hw->formats;
49 runtime->hw.period_bytes_min = hw->period_bytes_min;
50 runtime->hw.period_bytes_max = hw->period_bytes_max;
51 runtime->hw.periods_min = hw->periods_min;
52 runtime->hw.periods_max = hw->periods_max;
53 runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
54 runtime->hw.fifo_size = hw->fifo_size;
55 return 0;
56}
57EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
58
36/* DPCM stream event, send event to FE and all active BEs. */ 59/* DPCM stream event, send event to FE and all active BEs. */
37static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, 60static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
38 int event) 61 int event)
@@ -124,6 +147,26 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
124 } 147 }
125} 148}
126 149
150static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw,
151 struct snd_soc_pcm_stream *codec_stream,
152 struct snd_soc_pcm_stream *cpu_stream)
153{
154 hw->rate_min = max(codec_stream->rate_min, cpu_stream->rate_min);
155 hw->rate_max = max(codec_stream->rate_max, cpu_stream->rate_max);
156 hw->channels_min = max(codec_stream->channels_min,
157 cpu_stream->channels_min);
158 hw->channels_max = min(codec_stream->channels_max,
159 cpu_stream->channels_max);
160 hw->formats = codec_stream->formats & cpu_stream->formats;
161 hw->rates = codec_stream->rates & cpu_stream->rates;
162 if (codec_stream->rates
163 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
164 hw->rates |= cpu_stream->rates;
165 if (cpu_stream->rates
166 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
167 hw->rates |= codec_stream->rates;
168}
169
127/* 170/*
128 * Called by ALSA when a PCM substream is opened, the runtime->hw record is 171 * Called by ALSA when a PCM substream is opened, the runtime->hw record is
129 * then initialized and any private data can be allocated. This also calls 172 * then initialized and any private data can be allocated. This also calls
@@ -189,51 +232,11 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
189 232
190 /* Check that the codec and cpu DAIs are compatible */ 233 /* Check that the codec and cpu DAIs are compatible */
191 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 234 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
192 runtime->hw.rate_min = 235 soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->playback,
193 max(codec_dai_drv->playback.rate_min, 236 &cpu_dai_drv->playback);
194 cpu_dai_drv->playback.rate_min);
195 runtime->hw.rate_max =
196 min(codec_dai_drv->playback.rate_max,
197 cpu_dai_drv->playback.rate_max);
198 runtime->hw.channels_min =
199 max(codec_dai_drv->playback.channels_min,
200 cpu_dai_drv->playback.channels_min);
201 runtime->hw.channels_max =
202 min(codec_dai_drv->playback.channels_max,
203 cpu_dai_drv->playback.channels_max);
204 runtime->hw.formats =
205 codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;
206 runtime->hw.rates =
207 codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates;
208 if (codec_dai_drv->playback.rates
209 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
210 runtime->hw.rates |= cpu_dai_drv->playback.rates;
211 if (cpu_dai_drv->playback.rates
212 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
213 runtime->hw.rates |= codec_dai_drv->playback.rates;
214 } else { 237 } else {
215 runtime->hw.rate_min = 238 soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->capture,
216 max(codec_dai_drv->capture.rate_min, 239 &cpu_dai_drv->capture);
217 cpu_dai_drv->capture.rate_min);
218 runtime->hw.rate_max =
219 min(codec_dai_drv->capture.rate_max,
220 cpu_dai_drv->capture.rate_max);
221 runtime->hw.channels_min =
222 max(codec_dai_drv->capture.channels_min,
223 cpu_dai_drv->capture.channels_min);
224 runtime->hw.channels_max =
225 min(codec_dai_drv->capture.channels_max,
226 cpu_dai_drv->capture.channels_max);
227 runtime->hw.formats =
228 codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;
229 runtime->hw.rates =
230 codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates;
231 if (codec_dai_drv->capture.rates
232 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
233 runtime->hw.rates |= cpu_dai_drv->capture.rates;
234 if (cpu_dai_drv->capture.rates
235 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
236 runtime->hw.rates |= codec_dai_drv->capture.rates;
237 } 240 }
238 241
239 ret = -EINVAL; 242 ret = -EINVAL;
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index 4b3be6c3c91e..29b211e9c060 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -159,15 +159,10 @@ int __init snd_soc_util_init(void)
159{ 159{
160 int ret; 160 int ret;
161 161
162 soc_dummy_dev = platform_device_alloc("snd-soc-dummy", -1); 162 soc_dummy_dev =
163 if (!soc_dummy_dev) 163 platform_device_register_simple("snd-soc-dummy", -1, NULL, 0);
164 return -ENOMEM; 164 if (IS_ERR(soc_dummy_dev))
165 165 return PTR_ERR(soc_dummy_dev);
166 ret = platform_device_add(soc_dummy_dev);
167 if (ret != 0) {
168 platform_device_put(soc_dummy_dev);
169 return ret;
170 }
171 166
172 ret = platform_driver_register(&soc_dummy_driver); 167 ret = platform_driver_register(&soc_dummy_driver);
173 if (ret != 0) 168 if (ret != 0)
diff --git a/sound/soc/spear/Kconfig b/sound/soc/spear/Kconfig
new file mode 100644
index 000000000000..3567d73b218e
--- /dev/null
+++ b/sound/soc/spear/Kconfig
@@ -0,0 +1,9 @@
1config SND_SPEAR_SOC
2 tristate
3 select SND_SOC_DMAENGINE_PCM
4
5config SND_SPEAR_SPDIF_OUT
6 tristate
7
8config SND_SPEAR_SPDIF_IN
9 tristate
diff --git a/sound/soc/spear/Makefile b/sound/soc/spear/Makefile
new file mode 100644
index 000000000000..c4ea7161056c
--- /dev/null
+++ b/sound/soc/spear/Makefile
@@ -0,0 +1,8 @@
1# SPEAR Platform Support
2snd-soc-spear-pcm-objs := spear_pcm.o
3snd-soc-spear-spdif-in-objs := spdif_in.o
4snd-soc-spear-spdif-out-objs := spdif_out.o
5
6obj-$(CONFIG_SND_SPEAR_SOC) += snd-soc-spear-pcm.o
7obj-$(CONFIG_SND_SPEAR_SPDIF_IN) += snd-soc-spear-spdif-in.o
8obj-$(CONFIG_SND_SPEAR_SPDIF_OUT) += snd-soc-spear-spdif-out.o
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c
index 14d57e89bcba..63acfeb4b69d 100644
--- a/sound/soc/spear/spdif_in.c
+++ b/sound/soc/spear/spdif_in.c
@@ -49,15 +49,12 @@ static void spdif_in_configure(struct spdif_in_dev *host)
49 writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK); 49 writel(0xF, host->io_base + SPDIF_IN_IRQ_MASK);
50} 50}
51 51
52static int spdif_in_startup(struct snd_pcm_substream *substream, 52static int spdif_in_dai_probe(struct snd_soc_dai *dai)
53 struct snd_soc_dai *cpu_dai)
54{ 53{
55 struct spdif_in_dev *host = snd_soc_dai_get_drvdata(cpu_dai); 54 struct spdif_in_dev *host = snd_soc_dai_get_drvdata(dai);
56 55
57 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) 56 dai->capture_dma_data = &host->dma_params;
58 return -EINVAL;
59 57
60 snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params);
61 return 0; 58 return 0;
62} 59}
63 60
@@ -70,7 +67,6 @@ static void spdif_in_shutdown(struct snd_pcm_substream *substream,
70 return; 67 return;
71 68
72 writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK); 69 writel(0x0, host->io_base + SPDIF_IN_IRQ_MASK);
73 snd_soc_dai_set_dma_data(dai, substream, NULL);
74} 70}
75 71
76static void spdif_in_format(struct spdif_in_dev *host, u32 format) 72static void spdif_in_format(struct spdif_in_dev *host, u32 format)
@@ -151,13 +147,13 @@ static int spdif_in_trigger(struct snd_pcm_substream *substream, int cmd,
151} 147}
152 148
153static struct snd_soc_dai_ops spdif_in_dai_ops = { 149static struct snd_soc_dai_ops spdif_in_dai_ops = {
154 .startup = spdif_in_startup,
155 .shutdown = spdif_in_shutdown, 150 .shutdown = spdif_in_shutdown,
156 .trigger = spdif_in_trigger, 151 .trigger = spdif_in_trigger,
157 .hw_params = spdif_in_hw_params, 152 .hw_params = spdif_in_hw_params,
158}; 153};
159 154
160struct snd_soc_dai_driver spdif_in_dai = { 155static struct snd_soc_dai_driver spdif_in_dai = {
156 .probe = spdif_in_dai_probe,
161 .capture = { 157 .capture = {
162 .channels_min = 2, 158 .channels_min = 2,
163 .channels_max = 2, 159 .channels_max = 2,
@@ -235,7 +231,7 @@ static int spdif_in_probe(struct platform_device *pdev)
235 if (host->irq < 0) 231 if (host->irq < 0)
236 return -EINVAL; 232 return -EINVAL;
237 233
238 host->clk = clk_get(&pdev->dev, NULL); 234 host->clk = devm_clk_get(&pdev->dev, NULL);
239 if (IS_ERR(host->clk)) 235 if (IS_ERR(host->clk))
240 return PTR_ERR(host->clk); 236 return PTR_ERR(host->clk);
241 237
@@ -257,34 +253,21 @@ static int spdif_in_probe(struct platform_device *pdev)
257 ret = devm_request_irq(&pdev->dev, host->irq, spdif_in_irq, 0, 253 ret = devm_request_irq(&pdev->dev, host->irq, spdif_in_irq, 0,
258 "spdif-in", host); 254 "spdif-in", host);
259 if (ret) { 255 if (ret) {
260 clk_put(host->clk);
261 dev_warn(&pdev->dev, "request_irq failed\n"); 256 dev_warn(&pdev->dev, "request_irq failed\n");
262 return ret; 257 return ret;
263 } 258 }
264 259
265 ret = snd_soc_register_component(&pdev->dev, &spdif_in_component, 260 return snd_soc_register_component(&pdev->dev, &spdif_in_component,
266 &spdif_in_dai, 1); 261 &spdif_in_dai, 1);
267 if (ret != 0) {
268 clk_put(host->clk);
269 return ret;
270 }
271
272 return 0;
273} 262}
274 263
275static int spdif_in_remove(struct platform_device *pdev) 264static int spdif_in_remove(struct platform_device *pdev)
276{ 265{
277 struct spdif_in_dev *host = dev_get_drvdata(&pdev->dev);
278
279 snd_soc_unregister_component(&pdev->dev); 266 snd_soc_unregister_component(&pdev->dev);
280 dev_set_drvdata(&pdev->dev, NULL);
281
282 clk_put(host->clk);
283 267
284 return 0; 268 return 0;
285} 269}
286 270
287
288static struct platform_driver spdif_in_driver = { 271static struct platform_driver spdif_in_driver = {
289 .probe = spdif_in_probe, 272 .probe = spdif_in_probe,
290 .remove = spdif_in_remove, 273 .remove = spdif_in_remove,
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c
index 1e3c3dda3598..2fdf68c98d22 100644
--- a/sound/soc/spear/spdif_out.c
+++ b/sound/soc/spear/spdif_out.c
@@ -62,8 +62,6 @@ static int spdif_out_startup(struct snd_pcm_substream *substream,
62 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) 62 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
63 return -EINVAL; 63 return -EINVAL;
64 64
65 snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&host->dma_params);
66
67 ret = clk_enable(host->clk); 65 ret = clk_enable(host->clk);
68 if (ret) 66 if (ret)
69 return ret; 67 return ret;
@@ -84,7 +82,6 @@ static void spdif_out_shutdown(struct snd_pcm_substream *substream,
84 82
85 clk_disable(host->clk); 83 clk_disable(host->clk);
86 host->running = false; 84 host->running = false;
87 snd_soc_dai_set_dma_data(dai, substream, NULL);
88} 85}
89 86
90static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq, 87static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq,
@@ -243,8 +240,12 @@ static const struct snd_kcontrol_new spdif_out_controls[] = {
243 spdif_mute_get, spdif_mute_put), 240 spdif_mute_get, spdif_mute_put),
244}; 241};
245 242
246int spdif_soc_dai_probe(struct snd_soc_dai *dai) 243static int spdif_soc_dai_probe(struct snd_soc_dai *dai)
247{ 244{
245 struct spdif_out_dev *host = snd_soc_dai_get_drvdata(dai);
246
247 dai->playback_dma_data = &host->dma_params;
248
248 return snd_soc_add_dai_controls(dai, spdif_out_controls, 249 return snd_soc_add_dai_controls(dai, spdif_out_controls,
249 ARRAY_SIZE(spdif_out_controls)); 250 ARRAY_SIZE(spdif_out_controls));
250} 251}
@@ -281,30 +282,18 @@ static int spdif_out_probe(struct platform_device *pdev)
281 struct resource *res; 282 struct resource *res;
282 int ret; 283 int ret;
283 284
284 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
285 if (!res)
286 return -EINVAL;
287
288 if (!devm_request_mem_region(&pdev->dev, res->start,
289 resource_size(res), pdev->name)) {
290 dev_warn(&pdev->dev, "Failed to get memory resourse\n");
291 return -ENOENT;
292 }
293
294 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); 285 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
295 if (!host) { 286 if (!host) {
296 dev_warn(&pdev->dev, "kzalloc fail\n"); 287 dev_warn(&pdev->dev, "kzalloc fail\n");
297 return -ENOMEM; 288 return -ENOMEM;
298 } 289 }
299 290
300 host->io_base = devm_ioremap(&pdev->dev, res->start, 291 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
301 resource_size(res)); 292 host->io_base = devm_ioremap_resource(&pdev->dev, res);
302 if (!host->io_base) { 293 if (IS_ERR(host->io_base))
303 dev_warn(&pdev->dev, "ioremap failed\n"); 294 return PTR_ERR(host->io_base);
304 return -ENOMEM;
305 }
306 295
307 host->clk = clk_get(&pdev->dev, NULL); 296 host->clk = devm_clk_get(&pdev->dev, NULL);
308 if (IS_ERR(host->clk)) 297 if (IS_ERR(host->clk))
309 return PTR_ERR(host->clk); 298 return PTR_ERR(host->clk);
310 299
@@ -320,22 +309,12 @@ static int spdif_out_probe(struct platform_device *pdev)
320 309
321 ret = snd_soc_register_component(&pdev->dev, &spdif_out_component, 310 ret = snd_soc_register_component(&pdev->dev, &spdif_out_component,
322 &spdif_out_dai, 1); 311 &spdif_out_dai, 1);
323 if (ret != 0) { 312 return ret;
324 clk_put(host->clk);
325 return ret;
326 }
327
328 return 0;
329} 313}
330 314
331static int spdif_out_remove(struct platform_device *pdev) 315static int spdif_out_remove(struct platform_device *pdev)
332{ 316{
333 struct spdif_out_dev *host = dev_get_drvdata(&pdev->dev);
334
335 snd_soc_unregister_component(&pdev->dev); 317 snd_soc_unregister_component(&pdev->dev);
336 dev_set_drvdata(&pdev->dev, NULL);
337
338 clk_put(host->clk);
339 318
340 return 0; 319 return 0;
341} 320}
diff --git a/sound/soc/spear/spear_pcm.c b/sound/soc/spear/spear_pcm.c
index 2fbd4899d8ef..4707f2b862c3 100644
--- a/sound/soc/spear/spear_pcm.c
+++ b/sound/soc/spear/spear_pcm.c
@@ -13,19 +13,13 @@
13 13
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/dmaengine.h> 15#include <linux/dmaengine.h>
16#include <linux/dma-mapping.h>
17#include <linux/init.h>
18#include <linux/platform_device.h> 16#include <linux/platform_device.h>
19#include <linux/scatterlist.h>
20#include <linux/slab.h>
21#include <sound/core.h>
22#include <sound/dmaengine_pcm.h> 17#include <sound/dmaengine_pcm.h>
23#include <sound/pcm.h> 18#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h> 19#include <sound/soc.h>
26#include <sound/spear_dma.h> 20#include <sound/spear_dma.h>
27 21
28static struct snd_pcm_hardware spear_pcm_hardware = { 22static const struct snd_pcm_hardware spear_pcm_hardware = {
29 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 23 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
30 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 24 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
31 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), 25 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
@@ -37,149 +31,33 @@ static struct snd_pcm_hardware spear_pcm_hardware = {
37 .fifo_size = 0, /* fifo size in bytes */ 31 .fifo_size = 0, /* fifo size in bytes */
38}; 32};
39 33
40static int spear_pcm_hw_params(struct snd_pcm_substream *substream, 34static struct dma_chan *spear_pcm_request_chan(struct snd_soc_pcm_runtime *rtd,
41 struct snd_pcm_hw_params *params) 35 struct snd_pcm_substream *substream)
42{ 36{
43 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 37 struct spear_dma_data *dma_data;
44 38
45 return 0; 39 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
46}
47
48static int spear_pcm_hw_free(struct snd_pcm_substream *substream)
49{
50 snd_pcm_set_runtime_buffer(substream, NULL);
51
52 return 0;
53}
54
55static int spear_pcm_open(struct snd_pcm_substream *substream)
56{
57 struct snd_soc_pcm_runtime *rtd = substream->private_data;
58
59 struct spear_dma_data *dma_data = (struct spear_dma_data *)
60 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
61 int ret;
62
63 ret = snd_soc_set_runtime_hwparams(substream, &spear_pcm_hardware);
64 if (ret)
65 return ret;
66 40
67 return snd_dmaengine_pcm_open_request_chan(substream, dma_data->filter, 41 return snd_dmaengine_pcm_request_channel(dma_data->filter, dma_data);
68 dma_data);
69} 42}
70 43
71static int spear_pcm_mmap(struct snd_pcm_substream *substream, 44static const struct snd_dmaengine_pcm_config spear_dmaengine_pcm_config = {
72 struct vm_area_struct *vma) 45 .pcm_hardware = &spear_pcm_hardware,
73{ 46 .compat_request_channel = spear_pcm_request_chan,
74 struct snd_pcm_runtime *runtime = substream->runtime; 47 .prealloc_buffer_size = 16 * 1024,
75
76 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
77 runtime->dma_area, runtime->dma_addr,
78 runtime->dma_bytes);
79}
80
81static struct snd_pcm_ops spear_pcm_ops = {
82 .open = spear_pcm_open,
83 .close = snd_dmaengine_pcm_close_release_chan,
84 .ioctl = snd_pcm_lib_ioctl,
85 .hw_params = spear_pcm_hw_params,
86 .hw_free = spear_pcm_hw_free,
87 .trigger = snd_dmaengine_pcm_trigger,
88 .pointer = snd_dmaengine_pcm_pointer,
89 .mmap = spear_pcm_mmap,
90};
91
92static int
93spear_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream,
94 size_t size)
95{
96 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
97 struct snd_dma_buffer *buf = &substream->dma_buffer;
98
99 buf->dev.type = SNDRV_DMA_TYPE_DEV;
100 buf->dev.dev = pcm->card->dev;
101 buf->private_data = NULL;
102
103 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
104 &buf->addr, GFP_KERNEL);
105 if (!buf->area)
106 return -ENOMEM;
107
108 dev_info(buf->dev.dev,
109 " preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
110 (void *)buf->area, (void *)buf->addr, size);
111
112 buf->bytes = size;
113 return 0;
114}
115
116static void spear_pcm_free(struct snd_pcm *pcm)
117{
118 struct snd_pcm_substream *substream;
119 struct snd_dma_buffer *buf;
120 int stream;
121
122 for (stream = 0; stream < 2; stream++) {
123 substream = pcm->streams[stream].substream;
124 if (!substream)
125 continue;
126
127 buf = &substream->dma_buffer;
128 if (!buf || !buf->area)
129 continue;
130
131 dma_free_writecombine(pcm->card->dev, buf->bytes,
132 buf->area, buf->addr);
133 buf->area = NULL;
134 }
135}
136
137static u64 spear_pcm_dmamask = DMA_BIT_MASK(32);
138
139static int spear_pcm_new(struct snd_soc_pcm_runtime *rtd)
140{
141 struct snd_card *card = rtd->card->snd_card;
142 int ret;
143
144 if (!card->dev->dma_mask)
145 card->dev->dma_mask = &spear_pcm_dmamask;
146 if (!card->dev->coherent_dma_mask)
147 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
148
149 if (rtd->cpu_dai->driver->playback.channels_min) {
150 ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
151 SNDRV_PCM_STREAM_PLAYBACK,
152 spear_pcm_hardware.buffer_bytes_max);
153 if (ret)
154 return ret;
155 }
156
157 if (rtd->cpu_dai->driver->capture.channels_min) {
158 ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
159 SNDRV_PCM_STREAM_CAPTURE,
160 spear_pcm_hardware.buffer_bytes_max);
161 if (ret)
162 return ret;
163 }
164
165 return 0;
166}
167
168static struct snd_soc_platform_driver spear_soc_platform = {
169 .ops = &spear_pcm_ops,
170 .pcm_new = spear_pcm_new,
171 .pcm_free = spear_pcm_free,
172}; 48};
173 49
174static int spear_soc_platform_probe(struct platform_device *pdev) 50static int spear_soc_platform_probe(struct platform_device *pdev)
175{ 51{
176 return snd_soc_register_platform(&pdev->dev, &spear_soc_platform); 52 return snd_dmaengine_pcm_register(&pdev->dev,
53 &spear_dmaengine_pcm_config,
54 SND_DMAENGINE_PCM_FLAG_NO_DT |
55 SND_DMAENGINE_PCM_FLAG_COMPAT);
177} 56}
178 57
179static int spear_soc_platform_remove(struct platform_device *pdev) 58static int spear_soc_platform_remove(struct platform_device *pdev)
180{ 59{
181 snd_soc_unregister_platform(&pdev->dev); 60 snd_dmaengine_pcm_unregister(&pdev->dev);
182
183 return 0; 61 return 0;
184} 62}
185 63
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index b1c9d573da05..995b120c2cd0 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -59,6 +59,16 @@ config SND_SOC_TEGRA30_I2S
59 Tegra30 I2S interface. You will also need to select the individual 59 Tegra30 I2S interface. You will also need to select the individual
60 machine drivers to support below. 60 machine drivers to support below.
61 61
62config SND_SOC_TEGRA_RT5640
63 tristate "SoC Audio support for Tegra boards using an RT5640 codec"
64 depends on SND_SOC_TEGRA && I2C
65 select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
66 select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
67 select SND_SOC_RT5640
68 help
69 Say Y or M here if you want to add support for SoC audio on Tegra
70 boards using the RT5640 codec, such as Dalmore.
71
62config SND_SOC_TEGRA_WM8753 72config SND_SOC_TEGRA_WM8753
63 tristate "SoC Audio support for Tegra boards using a WM8753 codec" 73 tristate "SoC Audio support for Tegra boards using a WM8753 codec"
64 depends on SND_SOC_TEGRA && I2C 74 depends on SND_SOC_TEGRA && I2C
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 416a14bde41b..21d2550a08a4 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -18,12 +18,14 @@ obj-$(CONFIG_SND_SOC_TEGRA30_AHUB) += snd-soc-tegra30-ahub.o
18obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o 18obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o
19 19
20# Tegra machine Support 20# Tegra machine Support
21snd-soc-tegra-rt5640-objs := tegra_rt5640.o
21snd-soc-tegra-wm8753-objs := tegra_wm8753.o 22snd-soc-tegra-wm8753-objs := tegra_wm8753.o
22snd-soc-tegra-wm8903-objs := tegra_wm8903.o 23snd-soc-tegra-wm8903-objs := tegra_wm8903.o
23snd-soc-tegra-wm9712-objs := tegra_wm9712.o 24snd-soc-tegra-wm9712-objs := tegra_wm9712.o
24snd-soc-tegra-trimslice-objs := trimslice.o 25snd-soc-tegra-trimslice-objs := trimslice.o
25snd-soc-tegra-alc5632-objs := tegra_alc5632.o 26snd-soc-tegra-alc5632-objs := tegra_alc5632.o
26 27
28obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o
27obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o 29obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
28obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o 30obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
29obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o 31obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index 23e592f453fa..d554d46d08b5 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -627,9 +627,34 @@ static int tegra30_ahub_remove(struct platform_device *pdev)
627 return 0; 627 return 0;
628} 628}
629 629
630#ifdef CONFIG_PM_SLEEP
631static int tegra30_ahub_suspend(struct device *dev)
632{
633 regcache_mark_dirty(ahub->regmap_ahub);
634 regcache_mark_dirty(ahub->regmap_apbif);
635
636 return 0;
637}
638
639static int tegra30_ahub_resume(struct device *dev)
640{
641 int ret;
642
643 ret = pm_runtime_get_sync(dev);
644 if (ret < 0)
645 return ret;
646 ret = regcache_sync(ahub->regmap_ahub);
647 ret |= regcache_sync(ahub->regmap_apbif);
648 pm_runtime_put(dev);
649
650 return ret;
651}
652#endif
653
630static const struct dev_pm_ops tegra30_ahub_pm_ops = { 654static const struct dev_pm_ops tegra30_ahub_pm_ops = {
631 SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend, 655 SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend,
632 tegra30_ahub_runtime_resume, NULL) 656 tegra30_ahub_runtime_resume, NULL)
657 SET_SYSTEM_SLEEP_PM_OPS(tegra30_ahub_suspend, tegra30_ahub_resume)
633}; 658};
634 659
635static struct platform_driver tegra30_ahub_driver = { 660static struct platform_driver tegra30_ahub_driver = {
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index 31d092d83c71..d04146cad61f 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -514,6 +514,31 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev)
514 return 0; 514 return 0;
515} 515}
516 516
517#ifdef CONFIG_PM_SLEEP
518static int tegra30_i2s_suspend(struct device *dev)
519{
520 struct tegra30_i2s *i2s = dev_get_drvdata(dev);
521
522 regcache_mark_dirty(i2s->regmap);
523
524 return 0;
525}
526
527static int tegra30_i2s_resume(struct device *dev)
528{
529 struct tegra30_i2s *i2s = dev_get_drvdata(dev);
530 int ret;
531
532 ret = pm_runtime_get_sync(dev);
533 if (ret < 0)
534 return ret;
535 ret = regcache_sync(i2s->regmap);
536 pm_runtime_put(dev);
537
538 return ret;
539}
540#endif
541
517static const struct of_device_id tegra30_i2s_of_match[] = { 542static const struct of_device_id tegra30_i2s_of_match[] = {
518 { .compatible = "nvidia,tegra30-i2s", }, 543 { .compatible = "nvidia,tegra30-i2s", },
519 {}, 544 {},
@@ -522,6 +547,7 @@ static const struct of_device_id tegra30_i2s_of_match[] = {
522static const struct dev_pm_ops tegra30_i2s_pm_ops = { 547static const struct dev_pm_ops tegra30_i2s_pm_ops = {
523 SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend, 548 SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend,
524 tegra30_i2s_runtime_resume, NULL) 549 tegra30_i2s_runtime_resume, NULL)
550 SET_SYSTEM_SLEEP_PM_OPS(tegra30_i2s_suspend, tegra30_i2s_resume)
525}; 551};
526 552
527static struct platform_driver tegra30_i2s_driver = { 553static struct platform_driver tegra30_i2s_driver = {
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index 24fb001be7f4..d173880f290d 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -173,7 +173,6 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
173 struct device *dev) 173 struct device *dev)
174{ 174{
175 int ret; 175 int ret;
176 bool new_clocks = false;
177 176
178 data->dev = dev; 177 data->dev = dev;
179 178
@@ -181,40 +180,28 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
181 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20; 180 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20;
182 else if (of_machine_is_compatible("nvidia,tegra30")) 181 else if (of_machine_is_compatible("nvidia,tegra30"))
183 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30; 182 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30;
184 else if (of_machine_is_compatible("nvidia,tegra114")) { 183 else if (of_machine_is_compatible("nvidia,tegra114"))
185 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114; 184 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114;
186 new_clocks = true; 185 else {
187 } else {
188 dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n"); 186 dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n");
189 return -EINVAL; 187 return -EINVAL;
190 } 188 }
191 189
192 if (new_clocks) 190 data->clk_pll_a = clk_get(dev, "pll_a");
193 data->clk_pll_a = clk_get(dev, "pll_a");
194 else
195 data->clk_pll_a = clk_get_sys(NULL, "pll_a");
196 if (IS_ERR(data->clk_pll_a)) { 191 if (IS_ERR(data->clk_pll_a)) {
197 dev_err(data->dev, "Can't retrieve clk pll_a\n"); 192 dev_err(data->dev, "Can't retrieve clk pll_a\n");
198 ret = PTR_ERR(data->clk_pll_a); 193 ret = PTR_ERR(data->clk_pll_a);
199 goto err; 194 goto err;
200 } 195 }
201 196
202 if (new_clocks) 197 data->clk_pll_a_out0 = clk_get(dev, "pll_a_out0");
203 data->clk_pll_a_out0 = clk_get(dev, "pll_a_out0");
204 else
205 data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0");
206 if (IS_ERR(data->clk_pll_a_out0)) { 198 if (IS_ERR(data->clk_pll_a_out0)) {
207 dev_err(data->dev, "Can't retrieve clk pll_a_out0\n"); 199 dev_err(data->dev, "Can't retrieve clk pll_a_out0\n");
208 ret = PTR_ERR(data->clk_pll_a_out0); 200 ret = PTR_ERR(data->clk_pll_a_out0);
209 goto err_put_pll_a; 201 goto err_put_pll_a;
210 } 202 }
211 203
212 if (new_clocks) 204 data->clk_cdev1 = clk_get(dev, "mclk");
213 data->clk_cdev1 = clk_get(dev, "mclk");
214 else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
215 data->clk_cdev1 = clk_get_sys(NULL, "cdev1");
216 else
217 data->clk_cdev1 = clk_get_sys("extern1", NULL);
218 if (IS_ERR(data->clk_cdev1)) { 205 if (IS_ERR(data->clk_cdev1)) {
219 dev_err(data->dev, "Can't retrieve clk cdev1\n"); 206 dev_err(data->dev, "Can't retrieve clk cdev1\n");
220 ret = PTR_ERR(data->clk_cdev1); 207 ret = PTR_ERR(data->clk_cdev1);
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
new file mode 100644
index 000000000000..08794f915a94
--- /dev/null
+++ b/sound/soc/tegra/tegra_rt5640.c
@@ -0,0 +1,257 @@
1/*
2* tegra_rt5640.c - Tegra machine ASoC driver for boards using WM8903 codec.
3 *
4 * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Based on code copyright/by:
19 *
20 * Copyright (C) 2010-2012 - NVIDIA, Inc.
21 * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
22 * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
23 * Copyright 2007 Wolfson Microelectronics PLC.
24 */
25
26#include <linux/module.h>
27#include <linux/platform_device.h>
28#include <linux/slab.h>
29#include <linux/gpio.h>
30#include <linux/of_gpio.h>
31
32#include <sound/core.h>
33#include <sound/jack.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/soc.h>
37
38#include "../codecs/rt5640.h"
39
40#include "tegra_asoc_utils.h"
41
42#define DRV_NAME "tegra-snd-rt5640"
43
44struct tegra_rt5640 {
45 struct tegra_asoc_utils_data util_data;
46 int gpio_hp_det;
47};
48
49static int tegra_rt5640_asoc_hw_params(struct snd_pcm_substream *substream,
50 struct snd_pcm_hw_params *params)
51{
52 struct snd_soc_pcm_runtime *rtd = substream->private_data;
53 struct snd_soc_dai *codec_dai = rtd->codec_dai;
54 struct snd_soc_codec *codec = codec_dai->codec;
55 struct snd_soc_card *card = codec->card;
56 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
57 int srate, mclk;
58 int err;
59
60 srate = params_rate(params);
61 mclk = 256 * srate;
62
63 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
64 if (err < 0) {
65 dev_err(card->dev, "Can't configure clocks\n");
66 return err;
67 }
68
69 err = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_MCLK, mclk,
70 SND_SOC_CLOCK_IN);
71 if (err < 0) {
72 dev_err(card->dev, "codec_dai clock not set\n");
73 return err;
74 }
75
76 return 0;
77}
78
79static struct snd_soc_ops tegra_rt5640_ops = {
80 .hw_params = tegra_rt5640_asoc_hw_params,
81};
82
83static struct snd_soc_jack tegra_rt5640_hp_jack;
84
85static struct snd_soc_jack_pin tegra_rt5640_hp_jack_pins[] = {
86 {
87 .pin = "Headphones",
88 .mask = SND_JACK_HEADPHONE,
89 },
90};
91
92static struct snd_soc_jack_gpio tegra_rt5640_hp_jack_gpio = {
93 .name = "Headphone detection",
94 .report = SND_JACK_HEADPHONE,
95 .debounce_time = 150,
96 .invert = 1,
97};
98
99static const struct snd_soc_dapm_widget tegra_rt5640_dapm_widgets[] = {
100 SND_SOC_DAPM_HP("Headphones", NULL),
101 SND_SOC_DAPM_SPK("Speakers", NULL),
102};
103
104static const struct snd_kcontrol_new tegra_rt5640_controls[] = {
105 SOC_DAPM_PIN_SWITCH("Speakers"),
106};
107
108static int tegra_rt5640_asoc_init(struct snd_soc_pcm_runtime *rtd)
109{
110 struct snd_soc_dai *codec_dai = rtd->codec_dai;
111 struct snd_soc_codec *codec = codec_dai->codec;
112 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(codec->card);
113
114 snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE,
115 &tegra_rt5640_hp_jack);
116 snd_soc_jack_add_pins(&tegra_rt5640_hp_jack,
117 ARRAY_SIZE(tegra_rt5640_hp_jack_pins),
118 tegra_rt5640_hp_jack_pins);
119
120 if (gpio_is_valid(machine->gpio_hp_det)) {
121 tegra_rt5640_hp_jack_gpio.gpio = machine->gpio_hp_det;
122 snd_soc_jack_add_gpios(&tegra_rt5640_hp_jack,
123 1,
124 &tegra_rt5640_hp_jack_gpio);
125 }
126
127 return 0;
128}
129
130static struct snd_soc_dai_link tegra_rt5640_dai = {
131 .name = "RT5640",
132 .stream_name = "RT5640 PCM",
133 .codec_dai_name = "rt5640-aif1",
134 .init = tegra_rt5640_asoc_init,
135 .ops = &tegra_rt5640_ops,
136 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
137 SND_SOC_DAIFMT_CBS_CFS,
138};
139
140static struct snd_soc_card snd_soc_tegra_rt5640 = {
141 .name = "tegra-rt5640",
142 .owner = THIS_MODULE,
143 .dai_link = &tegra_rt5640_dai,
144 .num_links = 1,
145 .controls = tegra_rt5640_controls,
146 .num_controls = ARRAY_SIZE(tegra_rt5640_controls),
147 .dapm_widgets = tegra_rt5640_dapm_widgets,
148 .num_dapm_widgets = ARRAY_SIZE(tegra_rt5640_dapm_widgets),
149 .fully_routed = true,
150};
151
152static int tegra_rt5640_probe(struct platform_device *pdev)
153{
154 struct device_node *np = pdev->dev.of_node;
155 struct snd_soc_card *card = &snd_soc_tegra_rt5640;
156 struct tegra_rt5640 *machine;
157 int ret;
158
159 machine = devm_kzalloc(&pdev->dev,
160 sizeof(struct tegra_rt5640), GFP_KERNEL);
161 if (!machine) {
162 dev_err(&pdev->dev, "Can't allocate tegra_rt5640\n");
163 return -ENOMEM;
164 }
165
166 card->dev = &pdev->dev;
167 platform_set_drvdata(pdev, card);
168 snd_soc_card_set_drvdata(card, machine);
169
170 machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
171 if (machine->gpio_hp_det == -EPROBE_DEFER)
172 return -EPROBE_DEFER;
173
174 ret = snd_soc_of_parse_card_name(card, "nvidia,model");
175 if (ret)
176 goto err;
177
178 ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
179 if (ret)
180 goto err;
181
182 tegra_rt5640_dai.codec_of_node = of_parse_phandle(np,
183 "nvidia,audio-codec", 0);
184 if (!tegra_rt5640_dai.codec_of_node) {
185 dev_err(&pdev->dev,
186 "Property 'nvidia,audio-codec' missing or invalid\n");
187 ret = -EINVAL;
188 goto err;
189 }
190
191 tegra_rt5640_dai.cpu_of_node = of_parse_phandle(np,
192 "nvidia,i2s-controller", 0);
193 if (!tegra_rt5640_dai.cpu_of_node) {
194 dev_err(&pdev->dev,
195 "Property 'nvidia,i2s-controller' missing or invalid\n");
196 ret = -EINVAL;
197 goto err;
198 }
199
200 tegra_rt5640_dai.platform_of_node = tegra_rt5640_dai.cpu_of_node;
201
202 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
203 if (ret)
204 goto err;
205
206 ret = snd_soc_register_card(card);
207 if (ret) {
208 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
209 ret);
210 goto err_fini_utils;
211 }
212
213 return 0;
214
215err_fini_utils:
216 tegra_asoc_utils_fini(&machine->util_data);
217err:
218 return ret;
219}
220
221static int tegra_rt5640_remove(struct platform_device *pdev)
222{
223 struct snd_soc_card *card = platform_get_drvdata(pdev);
224 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
225
226 snd_soc_jack_free_gpios(&tegra_rt5640_hp_jack, 1,
227 &tegra_rt5640_hp_jack_gpio);
228
229 snd_soc_unregister_card(card);
230
231 tegra_asoc_utils_fini(&machine->util_data);
232
233 return 0;
234}
235
236static const struct of_device_id tegra_rt5640_of_match[] = {
237 { .compatible = "nvidia,tegra-audio-rt5640", },
238 {},
239};
240
241static struct platform_driver tegra_rt5640_driver = {
242 .driver = {
243 .name = DRV_NAME,
244 .owner = THIS_MODULE,
245 .pm = &snd_soc_pm_ops,
246 .of_match_table = tegra_rt5640_of_match,
247 },
248 .probe = tegra_rt5640_probe,
249 .remove = tegra_rt5640_remove,
250};
251module_platform_driver(tegra_rt5640_driver);
252
253MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
254MODULE_DESCRIPTION("Tegra+RT5640 machine ASoC driver");
255MODULE_LICENSE("GPL v2");
256MODULE_ALIAS("platform:" DRV_NAME);
257MODULE_DEVICE_TABLE(of, tegra_rt5640_of_match);
diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c
index 204b899c2311..8f5cd00a6e46 100644
--- a/sound/soc/ux500/mop500.c
+++ b/sound/soc/ux500/mop500.c
@@ -27,7 +27,7 @@
27#include "mop500_ab8500.h" 27#include "mop500_ab8500.h"
28 28
29/* Define the whole MOP500 soundcard, linking platform to the codec-drivers */ 29/* Define the whole MOP500 soundcard, linking platform to the codec-drivers */
30struct snd_soc_dai_link mop500_dai_links[] = { 30static struct snd_soc_dai_link mop500_dai_links[] = {
31 { 31 {
32 .name = "ab8500_0", 32 .name = "ab8500_0",
33 .stream_name = "ab8500_0", 33 .stream_name = "ab8500_0",
diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c
index 892ad9a05c9f..7e923ecf8901 100644
--- a/sound/soc/ux500/mop500_ab8500.c
+++ b/sound/soc/ux500/mop500_ab8500.c
@@ -16,6 +16,7 @@
16#include <linux/device.h> 16#include <linux/device.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/clk.h> 18#include <linux/clk.h>
19#include <linux/mutex.h>
19 20
20#include <sound/soc.h> 21#include <sound/soc.h>
21#include <sound/soc-dapm.h> 22#include <sound/soc-dapm.h>
@@ -24,6 +25,7 @@
24 25
25#include "ux500_pcm.h" 26#include "ux500_pcm.h"
26#include "ux500_msp_dai.h" 27#include "ux500_msp_dai.h"
28#include "mop500_ab8500.h"
27#include "../codecs/ab8500-codec.h" 29#include "../codecs/ab8500-codec.h"
28 30
29#define TX_SLOT_MONO 0x0008 31#define TX_SLOT_MONO 0x0008
@@ -43,6 +45,12 @@
43static unsigned int tx_slots = DEF_TX_SLOTS; 45static unsigned int tx_slots = DEF_TX_SLOTS;
44static unsigned int rx_slots = DEF_RX_SLOTS; 46static unsigned int rx_slots = DEF_RX_SLOTS;
45 47
48/* Configuration consistency parameters */
49static DEFINE_MUTEX(mop500_ab8500_params_lock);
50static unsigned long mop500_ab8500_usage;
51static int mop500_ab8500_rate;
52static int mop500_ab8500_channels;
53
46/* Clocks */ 54/* Clocks */
47static const char * const enum_mclk[] = { 55static const char * const enum_mclk[] = {
48 "SYSCLK", 56 "SYSCLK",
@@ -125,9 +133,9 @@ static int mop500_ab8500_set_mclk(struct device *dev,
125static int mclk_input_control_get(struct snd_kcontrol *kcontrol, 133static int mclk_input_control_get(struct snd_kcontrol *kcontrol,
126 struct snd_ctl_elem_value *ucontrol) 134 struct snd_ctl_elem_value *ucontrol)
127{ 135{
128 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 136 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
129 struct mop500_ab8500_drvdata *drvdata = 137 struct mop500_ab8500_drvdata *drvdata =
130 snd_soc_card_get_drvdata(codec->card); 138 snd_soc_card_get_drvdata(card);
131 139
132 ucontrol->value.enumerated.item[0] = drvdata->mclk_sel; 140 ucontrol->value.enumerated.item[0] = drvdata->mclk_sel;
133 141
@@ -137,9 +145,9 @@ static int mclk_input_control_get(struct snd_kcontrol *kcontrol,
137static int mclk_input_control_put(struct snd_kcontrol *kcontrol, 145static int mclk_input_control_put(struct snd_kcontrol *kcontrol,
138 struct snd_ctl_elem_value *ucontrol) 146 struct snd_ctl_elem_value *ucontrol)
139{ 147{
140 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 148 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
141 struct mop500_ab8500_drvdata *drvdata = 149 struct mop500_ab8500_drvdata *drvdata =
142 snd_soc_card_get_drvdata(codec->card); 150 snd_soc_card_get_drvdata(card);
143 unsigned int val = ucontrol->value.enumerated.item[0]; 151 unsigned int val = ucontrol->value.enumerated.item[0];
144 152
145 if (val > (unsigned int)MCLK_ULPCLK) 153 if (val > (unsigned int)MCLK_ULPCLK)
@@ -160,16 +168,6 @@ static struct snd_kcontrol_new mop500_ab8500_ctrls[] = {
160 SOC_ENUM_EXT("Master Clock Select", 168 SOC_ENUM_EXT("Master Clock Select",
161 soc_enum_mclk, 169 soc_enum_mclk,
162 mclk_input_control_get, mclk_input_control_put), 170 mclk_input_control_get, mclk_input_control_put),
163 /* Digital interface - Clocks */
164 SOC_SINGLE("Digital Interface Master Generator Switch",
165 AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENMASTGEN,
166 1, 0),
167 SOC_SINGLE("Digital Interface 0 Bit-clock Switch",
168 AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK0,
169 1, 0),
170 SOC_SINGLE("Digital Interface 1 Bit-clock Switch",
171 AB8500_DIGIFCONF1, AB8500_DIGIFCONF1_ENFSBITCLK1,
172 1, 0),
173 SOC_DAPM_PIN_SWITCH("Headset Left"), 171 SOC_DAPM_PIN_SWITCH("Headset Left"),
174 SOC_DAPM_PIN_SWITCH("Headset Right"), 172 SOC_DAPM_PIN_SWITCH("Headset Right"),
175 SOC_DAPM_PIN_SWITCH("Earpiece"), 173 SOC_DAPM_PIN_SWITCH("Earpiece"),
@@ -193,7 +191,7 @@ static struct snd_kcontrol_new mop500_ab8500_ctrls[] = {
193 191
194/* ASoC */ 192/* ASoC */
195 193
196int mop500_ab8500_startup(struct snd_pcm_substream *substream) 194static int mop500_ab8500_startup(struct snd_pcm_substream *substream)
197{ 195{
198 struct snd_soc_pcm_runtime *rtd = substream->private_data; 196 struct snd_soc_pcm_runtime *rtd = substream->private_data;
199 197
@@ -202,7 +200,7 @@ int mop500_ab8500_startup(struct snd_pcm_substream *substream)
202 snd_soc_card_get_drvdata(rtd->card)); 200 snd_soc_card_get_drvdata(rtd->card));
203} 201}
204 202
205void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) 203static void mop500_ab8500_shutdown(struct snd_pcm_substream *substream)
206{ 204{
207 struct snd_soc_pcm_runtime *rtd = substream->private_data; 205 struct snd_soc_pcm_runtime *rtd = substream->private_data;
208 struct device *dev = rtd->card->dev; 206 struct device *dev = rtd->card->dev;
@@ -216,7 +214,7 @@ void mop500_ab8500_shutdown(struct snd_pcm_substream *substream)
216 rx_slots = DEF_RX_SLOTS; 214 rx_slots = DEF_RX_SLOTS;
217} 215}
218 216
219int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, 217static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream,
220 struct snd_pcm_hw_params *params) 218 struct snd_pcm_hw_params *params)
221{ 219{
222 struct snd_soc_pcm_runtime *rtd = substream->private_data; 220 struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -240,6 +238,21 @@ int mop500_ab8500_hw_params(struct snd_pcm_substream *substream,
240 substream->name, 238 substream->name,
241 substream->number); 239 substream->number);
242 240
241 /* Ensure configuration consistency between DAIs */
242 mutex_lock(&mop500_ab8500_params_lock);
243 if (mop500_ab8500_usage) {
244 if (mop500_ab8500_rate != params_rate(params) ||
245 mop500_ab8500_channels != params_channels(params)) {
246 mutex_unlock(&mop500_ab8500_params_lock);
247 return -EBUSY;
248 }
249 } else {
250 mop500_ab8500_rate = params_rate(params);
251 mop500_ab8500_channels = params_channels(params);
252 }
253 __set_bit(cpu_dai->id, &mop500_ab8500_usage);
254 mutex_unlock(&mop500_ab8500_params_lock);
255
243 channels = params_channels(params); 256 channels = params_channels(params);
244 257
245 switch (params_format(params)) { 258 switch (params_format(params)) {
@@ -338,9 +351,22 @@ int mop500_ab8500_hw_params(struct snd_pcm_substream *substream,
338 return 0; 351 return 0;
339} 352}
340 353
354static int mop500_ab8500_hw_free(struct snd_pcm_substream *substream)
355{
356 struct snd_soc_pcm_runtime *rtd = substream->private_data;
357 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
358
359 mutex_lock(&mop500_ab8500_params_lock);
360 __clear_bit(cpu_dai->id, &mop500_ab8500_usage);
361 mutex_unlock(&mop500_ab8500_params_lock);
362
363 return 0;
364}
365
341struct snd_soc_ops mop500_ab8500_ops[] = { 366struct snd_soc_ops mop500_ab8500_ops[] = {
342 { 367 {
343 .hw_params = mop500_ab8500_hw_params, 368 .hw_params = mop500_ab8500_hw_params,
369 .hw_free = mop500_ab8500_hw_free,
344 .startup = mop500_ab8500_startup, 370 .startup = mop500_ab8500_startup,
345 .shutdown = mop500_ab8500_shutdown, 371 .shutdown = mop500_ab8500_shutdown,
346 } 372 }
@@ -385,7 +411,7 @@ int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd)
385 drvdata->mclk_sel = MCLK_ULPCLK; 411 drvdata->mclk_sel = MCLK_ULPCLK;
386 412
387 /* Add controls */ 413 /* Add controls */
388 ret = snd_soc_add_codec_controls(codec, mop500_ab8500_ctrls, 414 ret = snd_soc_add_card_controls(codec->card, mop500_ab8500_ctrls,
389 ARRAY_SIZE(mop500_ab8500_ctrls)); 415 ARRAY_SIZE(mop500_ab8500_ctrls));
390 if (ret < 0) { 416 if (ret < 0) {
391 pr_err("%s: Failed to add machine-controls (%d)!\n", 417 pr_err("%s: Failed to add machine-controls (%d)!\n",
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
index 7d5fc1328523..c6fb5cce980e 100644
--- a/sound/soc/ux500/ux500_msp_dai.c
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -658,14 +658,11 @@ static int ux500_msp_dai_probe(struct snd_soc_dai *dai)
658{ 658{
659 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev); 659 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
660 660
661 drvdata->playback_dma_data.dma_cfg = drvdata->msp->dma_cfg_tx; 661 dai->playback_dma_data = &drvdata->msp->playback_dma_data;
662 drvdata->capture_dma_data.dma_cfg = drvdata->msp->dma_cfg_rx; 662 dai->capture_dma_data = &drvdata->msp->capture_dma_data;
663 663
664 dai->playback_dma_data = &drvdata->playback_dma_data; 664 drvdata->msp->playback_dma_data.data_size = drvdata->slot_width;
665 dai->capture_dma_data = &drvdata->capture_dma_data; 665 drvdata->msp->capture_dma_data.data_size = drvdata->slot_width;
666
667 drvdata->playback_dma_data.data_size = drvdata->slot_width;
668 drvdata->capture_dma_data.data_size = drvdata->slot_width;
669 666
670 return 0; 667 return 0;
671} 668}
diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h
index f53104359f15..312ae535e351 100644
--- a/sound/soc/ux500/ux500_msp_dai.h
+++ b/sound/soc/ux500/ux500_msp_dai.h
@@ -51,15 +51,11 @@ enum ux500_msp_clock_id {
51struct ux500_msp_i2s_drvdata { 51struct ux500_msp_i2s_drvdata {
52 struct ux500_msp *msp; 52 struct ux500_msp *msp;
53 struct regulator *reg_vape; 53 struct regulator *reg_vape;
54 struct ux500_msp_dma_params playback_dma_data;
55 struct ux500_msp_dma_params capture_dma_data;
56 unsigned int fmt; 54 unsigned int fmt;
57 unsigned int tx_mask; 55 unsigned int tx_mask;
58 unsigned int rx_mask; 56 unsigned int rx_mask;
59 int slots; 57 int slots;
60 int slot_width; 58 int slot_width;
61 u8 configured;
62 int data_delay;
63 59
64 /* Clocks */ 60 /* Clocks */
65 unsigned int master_clk; 61 unsigned int master_clk;
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c
index f2db6c90a9e2..1ca8b08ae993 100644
--- a/sound/soc/ux500/ux500_msp_i2s.c
+++ b/sound/soc/ux500/ux500_msp_i2s.c
@@ -15,7 +15,6 @@
15 15
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/pinctrl/consumer.h>
19#include <linux/delay.h> 18#include <linux/delay.h>
20#include <linux/slab.h> 19#include <linux/slab.h>
21#include <linux/io.h> 20#include <linux/io.h>
@@ -26,9 +25,6 @@
26 25
27#include "ux500_msp_i2s.h" 26#include "ux500_msp_i2s.h"
28 27
29/* MSP1/3 Tx/Rx usage protection */
30static DEFINE_SPINLOCK(msp_rxtx_lock);
31
32 /* Protocol desciptors */ 28 /* Protocol desciptors */
33static const struct msp_protdesc prot_descs[] = { 29static const struct msp_protdesc prot_descs[] = {
34 { /* I2S */ 30 { /* I2S */
@@ -356,24 +352,8 @@ static int configure_multichannel(struct ux500_msp *msp,
356 352
357static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config) 353static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config)
358{ 354{
359 int status = 0, retval = 0; 355 int status = 0;
360 u32 reg_val_DMACR, reg_val_GCR; 356 u32 reg_val_DMACR, reg_val_GCR;
361 unsigned long flags;
362
363 /* Check msp state whether in RUN or CONFIGURED Mode */
364 if (msp->msp_state == MSP_STATE_IDLE) {
365 spin_lock_irqsave(&msp_rxtx_lock, flags);
366 if (msp->pinctrl_rxtx_ref == 0 &&
367 !(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_def))) {
368 retval = pinctrl_select_state(msp->pinctrl_p,
369 msp->pinctrl_def);
370 if (retval)
371 pr_err("could not set MSP defstate\n");
372 }
373 if (!retval)
374 msp->pinctrl_rxtx_ref++;
375 spin_unlock_irqrestore(&msp_rxtx_lock, flags);
376 }
377 357
378 /* Configure msp with protocol dependent settings */ 358 /* Configure msp with protocol dependent settings */
379 configure_protocol(msp, config); 359 configure_protocol(msp, config);
@@ -387,12 +367,14 @@ static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config)
387 } 367 }
388 368
389 /* Make sure the correct DMA-directions are configured */ 369 /* Make sure the correct DMA-directions are configured */
390 if ((config->direction & MSP_DIR_RX) && (!msp->dma_cfg_rx)) { 370 if ((config->direction & MSP_DIR_RX) &&
371 !msp->capture_dma_data.dma_cfg) {
391 dev_err(msp->dev, "%s: ERROR: MSP RX-mode is not configured!", 372 dev_err(msp->dev, "%s: ERROR: MSP RX-mode is not configured!",
392 __func__); 373 __func__);
393 return -EINVAL; 374 return -EINVAL;
394 } 375 }
395 if ((config->direction == MSP_DIR_TX) && (!msp->dma_cfg_tx)) { 376 if ((config->direction == MSP_DIR_TX) &&
377 !msp->playback_dma_data.dma_cfg) {
396 dev_err(msp->dev, "%s: ERROR: MSP TX-mode is not configured!", 378 dev_err(msp->dev, "%s: ERROR: MSP TX-mode is not configured!",
397 __func__); 379 __func__);
398 return -EINVAL; 380 return -EINVAL;
@@ -630,8 +612,7 @@ int ux500_msp_i2s_trigger(struct ux500_msp *msp, int cmd, int direction)
630 612
631int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir) 613int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)
632{ 614{
633 int status = 0, retval = 0; 615 int status = 0;
634 unsigned long flags;
635 616
636 dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir); 617 dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir);
637 618
@@ -643,18 +624,6 @@ int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)
643 (~(FRAME_GEN_ENABLE | SRG_ENABLE))), 624 (~(FRAME_GEN_ENABLE | SRG_ENABLE))),
644 msp->registers + MSP_GCR); 625 msp->registers + MSP_GCR);
645 626
646 spin_lock_irqsave(&msp_rxtx_lock, flags);
647 WARN_ON(!msp->pinctrl_rxtx_ref);
648 msp->pinctrl_rxtx_ref--;
649 if (msp->pinctrl_rxtx_ref == 0 &&
650 !(IS_ERR(msp->pinctrl_p) || IS_ERR(msp->pinctrl_sleep))) {
651 retval = pinctrl_select_state(msp->pinctrl_p,
652 msp->pinctrl_sleep);
653 if (retval)
654 pr_err("could not set MSP sleepstate\n");
655 }
656 spin_unlock_irqrestore(&msp_rxtx_lock, flags);
657
658 writel(0, msp->registers + MSP_GCR); 627 writel(0, msp->registers + MSP_GCR);
659 writel(0, msp->registers + MSP_TCF); 628 writel(0, msp->registers + MSP_TCF);
660 writel(0, msp->registers + MSP_RCF); 629 writel(0, msp->registers + MSP_RCF);
@@ -682,7 +651,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
682 struct msp_i2s_platform_data *platform_data) 651 struct msp_i2s_platform_data *platform_data)
683{ 652{
684 struct resource *res = NULL; 653 struct resource *res = NULL;
685 struct i2s_controller *i2s_cont;
686 struct device_node *np = pdev->dev.of_node; 654 struct device_node *np = pdev->dev.of_node;
687 struct ux500_msp *msp; 655 struct ux500_msp *msp;
688 656
@@ -707,8 +675,8 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
707 675
708 msp->id = platform_data->id; 676 msp->id = platform_data->id;
709 msp->dev = &pdev->dev; 677 msp->dev = &pdev->dev;
710 msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx; 678 msp->playback_dma_data.dma_cfg = platform_data->msp_i2s_dma_tx;
711 msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx; 679 msp->capture_dma_data.dma_cfg = platform_data->msp_i2s_dma_rx;
712 680
713 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 681 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
714 if (res == NULL) { 682 if (res == NULL) {
@@ -717,6 +685,9 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
717 return -ENOMEM; 685 return -ENOMEM;
718 } 686 }
719 687
688 msp->playback_dma_data.tx_rx_addr = res->start + MSP_DR;
689 msp->capture_dma_data.tx_rx_addr = res->start + MSP_DR;
690
720 msp->registers = devm_ioremap(&pdev->dev, res->start, 691 msp->registers = devm_ioremap(&pdev->dev, res->start,
721 resource_size(res)); 692 resource_size(res));
722 if (msp->registers == NULL) { 693 if (msp->registers == NULL) {
@@ -727,41 +698,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
727 msp->msp_state = MSP_STATE_IDLE; 698 msp->msp_state = MSP_STATE_IDLE;
728 msp->loopback_enable = 0; 699 msp->loopback_enable = 0;
729 700
730 /* I2S-controller is allocated and added in I2S controller class. */
731 i2s_cont = devm_kzalloc(&pdev->dev, sizeof(*i2s_cont), GFP_KERNEL);
732 if (!i2s_cont) {
733 dev_err(&pdev->dev,
734 "%s: ERROR: Failed to allocate I2S-controller!\n",
735 __func__);
736 return -ENOMEM;
737 }
738 i2s_cont->dev.parent = &pdev->dev;
739 i2s_cont->data = (void *)msp;
740 i2s_cont->id = (s16)msp->id;
741 snprintf(i2s_cont->name, sizeof(i2s_cont->name), "ux500-msp-i2s.%04x",
742 msp->id);
743 dev_dbg(&pdev->dev, "I2S device-name: '%s'\n", i2s_cont->name);
744 msp->i2s_cont = i2s_cont;
745
746 msp->pinctrl_p = pinctrl_get(msp->dev);
747 if (IS_ERR(msp->pinctrl_p))
748 dev_err(&pdev->dev, "could not get MSP pinctrl\n");
749 else {
750 msp->pinctrl_def = pinctrl_lookup_state(msp->pinctrl_p,
751 PINCTRL_STATE_DEFAULT);
752 if (IS_ERR(msp->pinctrl_def)) {
753 dev_err(&pdev->dev,
754 "could not get MSP defstate (%li)\n",
755 PTR_ERR(msp->pinctrl_def));
756 }
757 msp->pinctrl_sleep = pinctrl_lookup_state(msp->pinctrl_p,
758 PINCTRL_STATE_SLEEP);
759 if (IS_ERR(msp->pinctrl_sleep))
760 dev_err(&pdev->dev,
761 "could not get MSP idlestate (%li)\n",
762 PTR_ERR(msp->pinctrl_def));
763 }
764
765 return 0; 701 return 0;
766} 702}
767 703
@@ -769,8 +705,6 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,
769 struct ux500_msp *msp) 705 struct ux500_msp *msp)
770{ 706{
771 dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id); 707 dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id);
772
773 device_unregister(&msp->i2s_cont->dev);
774} 708}
775 709
776MODULE_LICENSE("GPL v2"); 710MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h
index e5cd105c90f9..258d0bcee0bd 100644
--- a/sound/soc/ux500/ux500_msp_i2s.h
+++ b/sound/soc/ux500/ux500_msp_i2s.h
@@ -16,6 +16,7 @@
16#define UX500_MSP_I2S_H 16#define UX500_MSP_I2S_H
17 17
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/platform_data/asoc-ux500-msp.h>
19 20
20#define MSP_INPUT_FREQ_APB 48000000 21#define MSP_INPUT_FREQ_APB 48000000
21 22
@@ -341,11 +342,6 @@ enum msp_compress_mode {
341 MSP_COMPRESS_MODE_A_LAW = 3 342 MSP_COMPRESS_MODE_A_LAW = 3
342}; 343};
343 344
344enum msp_spi_burst_mode {
345 MSP_SPI_BURST_MODE_DISABLE = 0,
346 MSP_SPI_BURST_MODE_ENABLE = 1
347};
348
349enum msp_expand_mode { 345enum msp_expand_mode {
350 MSP_EXPAND_MODE_LINEAR = 0, 346 MSP_EXPAND_MODE_LINEAR = 0,
351 MSP_EXPAND_MODE_LINEAR_SIGNED = 1, 347 MSP_EXPAND_MODE_LINEAR_SIGNED = 1,
@@ -370,13 +366,6 @@ enum msp_protocol {
370 */ 366 */
371#define MAX_MSP_BACKUP_REGS 36 367#define MAX_MSP_BACKUP_REGS 36
372 368
373enum enum_i2s_controller {
374 MSP_0_I2S_CONTROLLER = 0,
375 MSP_1_I2S_CONTROLLER,
376 MSP_2_I2S_CONTROLLER,
377 MSP_3_I2S_CONTROLLER,
378};
379
380enum i2s_direction_t { 369enum i2s_direction_t {
381 MSP_DIR_TX = 0x01, 370 MSP_DIR_TX = 0x01,
382 MSP_DIR_RX = 0x02, 371 MSP_DIR_RX = 0x02,
@@ -454,32 +443,6 @@ struct msp_protdesc {
454 u32 clocks_per_frame; 443 u32 clocks_per_frame;
455}; 444};
456 445
457struct i2s_message {
458 enum i2s_direction_t i2s_direction;
459 void *txdata;
460 void *rxdata;
461 size_t txbytes;
462 size_t rxbytes;
463 int dma_flag;
464 int tx_offset;
465 int rx_offset;
466 bool cyclic_dma;
467 dma_addr_t buf_addr;
468 size_t buf_len;
469 size_t period_len;
470};
471
472struct i2s_controller {
473 struct module *owner;
474 unsigned int id;
475 unsigned int class;
476 const struct i2s_algorithm *algo; /* the algorithm to access the bus */
477 void *data;
478 struct mutex bus_lock;
479 struct device dev; /* the controller device */
480 char name[48];
481};
482
483struct ux500_msp_config { 446struct ux500_msp_config {
484 unsigned int f_inputclk; 447 unsigned int f_inputclk;
485 unsigned int rx_clk_sel; 448 unsigned int rx_clk_sel;
@@ -491,8 +454,6 @@ struct ux500_msp_config {
491 unsigned int tx_fsync_sel; 454 unsigned int tx_fsync_sel;
492 unsigned int rx_fifo_config; 455 unsigned int rx_fifo_config;
493 unsigned int tx_fifo_config; 456 unsigned int tx_fifo_config;
494 unsigned int spi_clk_mode;
495 unsigned int spi_burst_mode;
496 unsigned int loopback_enable; 457 unsigned int loopback_enable;
497 unsigned int tx_data_enable; 458 unsigned int tx_data_enable;
498 unsigned int default_protdesc; 459 unsigned int default_protdesc;
@@ -502,43 +463,28 @@ struct ux500_msp_config {
502 unsigned int direction; 463 unsigned int direction;
503 unsigned int protocol; 464 unsigned int protocol;
504 unsigned int frame_freq; 465 unsigned int frame_freq;
505 unsigned int frame_size;
506 enum msp_data_size data_size; 466 enum msp_data_size data_size;
507 unsigned int def_elem_len; 467 unsigned int def_elem_len;
508 unsigned int iodelay; 468 unsigned int iodelay;
509 void (*handler) (void *data); 469};
510 void *tx_callback_data; 470
511 void *rx_callback_data; 471struct ux500_msp_dma_params {
472 unsigned int data_size;
473 dma_addr_t tx_rx_addr;
474 struct stedma40_chan_cfg *dma_cfg;
512}; 475};
513 476
514struct ux500_msp { 477struct ux500_msp {
515 enum enum_i2s_controller id; 478 enum msp_i2s_id id;
516 void __iomem *registers; 479 void __iomem *registers;
517 struct device *dev; 480 struct device *dev;
518 struct i2s_controller *i2s_cont; 481 struct ux500_msp_dma_params playback_dma_data;
519 struct stedma40_chan_cfg *dma_cfg_rx; 482 struct ux500_msp_dma_params capture_dma_data;
520 struct stedma40_chan_cfg *dma_cfg_tx;
521 struct dma_chan *tx_pipeid;
522 struct dma_chan *rx_pipeid;
523 enum msp_state msp_state; 483 enum msp_state msp_state;
524 int (*transfer) (struct ux500_msp *msp, struct i2s_message *message);
525 struct timer_list notify_timer;
526 int def_elem_len; 484 int def_elem_len;
527 unsigned int dir_busy; 485 unsigned int dir_busy;
528 int loopback_enable; 486 int loopback_enable;
529 u32 backup_regs[MAX_MSP_BACKUP_REGS];
530 unsigned int f_bitclk; 487 unsigned int f_bitclk;
531 /* Pin modes */
532 struct pinctrl *pinctrl_p;
533 struct pinctrl_state *pinctrl_def;
534 struct pinctrl_state *pinctrl_sleep;
535 /* Reference Count */
536 int pinctrl_rxtx_ref;
537};
538
539struct ux500_msp_dma_params {
540 unsigned int data_size;
541 struct stedma40_chan_cfg *dma_cfg;
542}; 488};
543 489
544struct msp_i2s_platform_data; 490struct msp_i2s_platform_data;
diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c
index b6e5ae277299..5f01c19776bf 100644
--- a/sound/soc/ux500/ux500_pcm.c
+++ b/sound/soc/ux500/ux500_pcm.c
@@ -103,10 +103,40 @@ static struct dma_chan *ux500_pcm_request_chan(struct snd_soc_pcm_runtime *rtd,
103 return snd_dmaengine_pcm_request_channel(stedma40_filter, dma_cfg); 103 return snd_dmaengine_pcm_request_channel(stedma40_filter, dma_cfg);
104} 104}
105 105
106static int ux500_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
107 struct snd_pcm_hw_params *params,
108 struct dma_slave_config *slave_config)
109{
110 struct snd_soc_pcm_runtime *rtd = substream->private_data;
111 struct ux500_msp_dma_params *dma_params;
112 struct stedma40_chan_cfg *dma_cfg;
113 int ret;
114
115 dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
116 dma_cfg = dma_params->dma_cfg;
117
118 ret = snd_hwparams_to_dma_slave_config(substream, params, slave_config);
119 if (ret)
120 return ret;
121
122 slave_config->dst_maxburst = 4;
123 slave_config->dst_addr_width = dma_cfg->dst_info.data_width;
124 slave_config->src_maxburst = 4;
125 slave_config->src_addr_width = dma_cfg->src_info.data_width;
126
127 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
128 slave_config->dst_addr = dma_params->tx_rx_addr;
129 else
130 slave_config->src_addr = dma_params->tx_rx_addr;
131
132 return 0;
133}
134
106static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = { 135static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = {
107 .pcm_hardware = &ux500_pcm_hw, 136 .pcm_hardware = &ux500_pcm_hw,
108 .compat_request_channel = ux500_pcm_request_chan, 137 .compat_request_channel = ux500_pcm_request_chan,
109 .prealloc_buffer_size = 128 * 1024, 138 .prealloc_buffer_size = 128 * 1024,
139 .prepare_slave_config = ux500_pcm_prepare_slave_config,
110}; 140};
111 141
112int ux500_pcm_register_platform(struct platform_device *pdev) 142int ux500_pcm_register_platform(struct platform_device *pdev)