diff options
author | Mark Brown <broonie@linaro.org> | 2013-07-04 13:30:01 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-07-04 13:30:01 -0400 |
commit | 986a622df307644af14618bee54c901aa74816da (patch) | |
tree | 6da87812b9120634381e3e3987e115f90bd562e0 /sound | |
parent | 8bb495e3f02401ee6f76d1b1d77f3ac9f079e376 (diff) | |
parent | 28e5ca73ef9072ed58dbb81cfff6f908be8e3cd4 (diff) |
Merge remote-tracking branch 'asoc/fix/fsl' into asoc-linus
Diffstat (limited to 'sound')
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" | |||
51 | source "sound/soc/samsung/Kconfig" | 51 | source "sound/soc/samsung/Kconfig" |
52 | source "sound/soc/s6000/Kconfig" | 52 | source "sound/soc/s6000/Kconfig" |
53 | source "sound/soc/sh/Kconfig" | 53 | source "sound/soc/sh/Kconfig" |
54 | source "sound/soc/spear/Kconfig" | ||
54 | source "sound/soc/tegra/Kconfig" | 55 | source "sound/soc/tegra/Kconfig" |
55 | source "sound/soc/txx9/Kconfig" | 56 | source "sound/soc/txx9/Kconfig" |
56 | source "sound/soc/ux500/Kconfig" | 57 | source "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/ | |||
29 | obj-$(CONFIG_SND_SOC) += samsung/ | 29 | obj-$(CONFIG_SND_SOC) += samsung/ |
30 | obj-$(CONFIG_SND_SOC) += s6000/ | 30 | obj-$(CONFIG_SND_SOC) += s6000/ |
31 | obj-$(CONFIG_SND_SOC) += sh/ | 31 | obj-$(CONFIG_SND_SOC) += sh/ |
32 | obj-$(CONFIG_SND_SOC) += spear/ | ||
32 | obj-$(CONFIG_SND_SOC) += tegra/ | 33 | obj-$(CONFIG_SND_SOC) += tegra/ |
33 | obj-$(CONFIG_SND_SOC) += txx9/ | 34 | obj-$(CONFIG_SND_SOC) += txx9/ |
34 | obj-$(CONFIG_SND_SOC) += ux500/ | 35 | obj-$(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 | ||
59 | config 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 | |||
67 | config 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 | |||
59 | config SND_BF5XX_SOC_AD73311 | 76 | config 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 | ||
75 | config 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 | |||
85 | config 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 | |||
93 | config 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 | |||
102 | config SND_BF5XX_AC97 | 92 | config 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 | |||
174 | config SND_BF6XX_SOC_I2S | 164 | config SND_BF6XX_SOC_I2S |
175 | tristate | 165 | tristate |
176 | 166 | ||
177 | config SND_BF5XX_SOC_TDM | ||
178 | tristate | ||
179 | |||
180 | config SND_BF5XX_SOC_AC97 | 167 | config 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 |
2 | snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o | 2 | snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o |
3 | snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o | 3 | snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o |
4 | snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o | ||
5 | snd-soc-bf5xx-sport-objs := bf5xx-sport.o | 4 | snd-soc-bf5xx-sport-objs := bf5xx-sport.o |
6 | snd-soc-bf6xx-sport-objs := bf6xx-sport.o | 5 | snd-soc-bf6xx-sport-objs := bf6xx-sport.o |
7 | snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o | 6 | snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o |
8 | snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o | 7 | snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o |
9 | snd-soc-bf6xx-i2s-objs := bf6xx-i2s.o | 8 | snd-soc-bf6xx-i2s-objs := bf6xx-i2s.o |
10 | snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o | ||
11 | 9 | ||
12 | obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o | 10 | obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o |
13 | obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o | 11 | obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o |
14 | obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o | ||
15 | obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o | 12 | obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o |
16 | obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o | 13 | obj-$(CONFIG_SND_BF6XX_SOC_SPORT) += snd-soc-bf6xx-sport.o |
17 | obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o | 14 | obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o |
18 | obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o | 15 | obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o |
19 | obj-$(CONFIG_SND_BF6XX_SOC_I2S) += snd-soc-bf6xx-i2s.o | 16 | obj-$(CONFIG_SND_BF6XX_SOC_I2S) += snd-soc-bf6xx-i2s.o |
20 | obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o | ||
21 | 17 | ||
22 | # Blackfin Machine Support | 18 | # Blackfin Machine Support |
23 | snd-ad1836-objs := bf5xx-ad1836.o | 19 | snd-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 | |||
14 | struct bf5xx_pcm_dma_params { | ||
15 | char *name; /* stream identifier */ | ||
16 | }; | ||
17 | |||
18 | struct 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 | |||
36 | static struct snd_soc_card bf5xx_ad1836; | 33 | static struct snd_soc_card bf5xx_ad1836; |
37 | 34 | ||
38 | static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, | 35 | static 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 | ||
55 | static 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 | ||
71 | static struct snd_soc_card bf5xx_ad1836 = { | 66 | static 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 | |||
45 | static struct snd_soc_card bf5xx_ad193x; | 42 | static struct snd_soc_card bf5xx_ad193x; |
46 | 43 | ||
47 | static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, | 44 | static 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 | ||
86 | static struct snd_soc_ops bf5xx_ad193x_ops = { | ||
87 | .hw_params = bf5xx_ad193x_hw_params, | ||
88 | }; | ||
89 | |||
90 | static struct snd_soc_dai_link bf5xx_ad193x_dai[] = { | 70 | static 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 | ||
54 | static struct snd_soc_card bf5xx_board; | 53 | static 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 | ||
45 | static void bf5xx_dma_irq(void *data) | 45 | static void bf5xx_dma_irq(void *data) |
46 | { | 46 | { |
@@ -50,7 +50,6 @@ static void bf5xx_dma_irq(void *data) | |||
50 | 50 | ||
51 | static const struct snd_pcm_hardware bf5xx_pcm_hardware = { | 51 | static 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 = { | |||
67 | static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, | 66 | static 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 | ||
76 | static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) | 81 | static 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 | ||
83 | static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) | 88 | static 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 | ||
132 | static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | 144 | static 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 | ||
231 | static 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 | |||
288 | static 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 | |||
205 | static struct snd_pcm_ops bf5xx_pcm_i2s_ops = { | 313 | static 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 | ||
216 | static 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 | |||
239 | static 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 | |||
258 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | 326 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); |
259 | 327 | ||
260 | static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd) | 328 | static 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 | ||
289 | static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = { | 343 | static 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 | ||
295 | static int bfin_i2s_soc_platform_probe(struct platform_device *pdev) | 348 | static 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 | ||
14 | struct bf5xx_pcm_dma_params { | 10 | #define BFIN_TDM_DAI_MAX_SLOTS 8 |
15 | char *name; /* stream identifier */ | ||
16 | }; | ||
17 | 11 | ||
18 | struct bf5xx_gpio { | 12 | struct 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 | ||
46 | struct bf5xx_i2s_port { | 47 | struct 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 | ||
54 | static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 62 | static 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 | ||
181 | static 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 | |||
217 | static 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 |
172 | static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) | 240 | static 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 | ||
284 | static 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 | ||
226 | static const struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { | 312 | static 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 | ||
232 | static struct snd_soc_dai_driver bf5xx_i2s_dai = { | 320 | static 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 ! */ |
48 | int sport_set_multichannel(struct sport_device *sport, | 48 | int 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 */ |
130 | int sport_set_multichannel(struct sport_device *sport, int tdm_count, | 130 | int 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 | ||
133 | int sport_config_rx(struct sport_device *sport, | 133 | int 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 | ||
45 | static struct snd_soc_card bf5xx_ssm2602; | 44 | static 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 | |||
51 | static void bf5xx_dma_irq(void *data) | ||
52 | { | ||
53 | struct snd_pcm_substream *pcm = data; | ||
54 | snd_pcm_period_elapsed(pcm); | ||
55 | } | ||
56 | |||
57 | static 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 | |||
71 | static 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 | |||
80 | static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) | ||
81 | { | ||
82 | snd_pcm_lib_free_pages(substream); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static 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 | |||
110 | static 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 | |||
138 | static 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 | |||
155 | static 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 | } | ||
183 | out: | ||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | static 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 | |||
222 | static 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 | |||
233 | struct 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 | |||
245 | static 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 | |||
265 | static 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 | |||
284 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | ||
285 | |||
286 | static 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 | } | ||
310 | out: | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | static 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 | |||
320 | static int bf5xx_soc_platform_probe(struct platform_device *pdev) | ||
321 | { | ||
322 | return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform); | ||
323 | } | ||
324 | |||
325 | static int bf5xx_soc_platform_remove(struct platform_device *pdev) | ||
326 | { | ||
327 | snd_soc_unregister_platform(&pdev->dev); | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static 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 | |||
341 | module_platform_driver(bfin_tdm_driver); | ||
342 | |||
343 | MODULE_AUTHOR("Barry Song"); | ||
344 | MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module"); | ||
345 | MODULE_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 | |||
14 | struct 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 | |||
49 | static 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 | |||
81 | static 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 | |||
133 | static 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 | |||
144 | static 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 | ||
181 | static 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 | |||
196 | static 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 | |||
229 | static 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 | |||
236 | static 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 | |||
252 | static const struct snd_soc_component_driver bf5xx_tdm_component = { | ||
253 | .name = "bf5xx-tdm", | ||
254 | }; | ||
255 | |||
256 | static 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 | |||
298 | sport_config_err: | ||
299 | sport_done(sport_handle); | ||
300 | return ret; | ||
301 | } | ||
302 | |||
303 | static 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 | |||
313 | static 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 | |||
322 | module_platform_driver(bfin_tdm_driver); | ||
323 | |||
324 | /* Module information */ | ||
325 | MODULE_AUTHOR("Barry Song"); | ||
326 | MODULE_DESCRIPTION("TDM driver for ADI Blackfin"); | ||
327 | MODULE_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 | ||
13 | struct 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 @@ | |||
1 | config SND_EP93XX_SOC | 1 | config 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 | ||
317 | static int ep93xx_ac97_startup(struct snd_pcm_substream *substream, | 317 | static 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 | ||
331 | static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = { | 325 | static 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 | ||
405 | fail: | 399 | fail: |
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 | ||
67 | struct ep93xx_dma_data ep93xx_i2s_dma_data[] = { | 66 | static 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 | ||
142 | static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, | 141 | static 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 | ||
340 | static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { | 335 | static 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 | ||
350 | static struct snd_soc_dai_driver ep93xx_i2s_dai = { | 344 | static 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 | ||
32 | static const struct snd_pcm_hardware ep93xx_pcm_hardware = { | 26 | static 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 | ||
66 | static int ep93xx_pcm_open(struct snd_pcm_substream *substream) | 60 | static 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 | |||
77 | static 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 | |||
85 | static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream) | ||
86 | { | ||
87 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static 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 | |||
102 | static 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 | |||
113 | static 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 | |||
129 | static 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 | |||
150 | static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32); | ||
151 | |||
152 | static 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 | |||
180 | static 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 | ||
186 | static int ep93xx_soc_platform_probe(struct platform_device *pdev) | 66 | static 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 | ||
191 | static int ep93xx_soc_platform_remove(struct platform_device *pdev) | 75 | static 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 | |||
1461 | out: | ||
1462 | platform_set_drvdata(pdev, NULL); | ||
1463 | return -EINVAL; | ||
1464 | } | 1460 | } |
1465 | 1461 | ||
1466 | static int pm860x_codec_remove(struct platform_device *pdev) | 1462 | static 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 | |||
263 | config SND_SOC_DA9055 | 265 | config SND_SOC_DA9055 |
264 | tristate | 266 | tristate |
265 | 267 | ||
266 | config SND_SOC_DFBMCS320 | 268 | config SND_SOC_BT_SCO |
267 | tristate | 269 | tristate |
268 | 270 | ||
269 | config SND_SOC_DMIC | 271 | config SND_SOC_DMIC |
@@ -287,7 +289,7 @@ config SND_SOC_MAX98095 | |||
287 | config SND_SOC_MAX9850 | 289 | config SND_SOC_MAX9850 |
288 | tristate | 290 | tristate |
289 | 291 | ||
290 | config SND_SOC_OMAP_HDMI_CODEC | 292 | config SND_SOC_HDMI_CODEC |
291 | tristate | 293 | tristate |
292 | 294 | ||
293 | config SND_SOC_PCM3008 | 295 | config SND_SOC_PCM3008 |
@@ -296,6 +298,9 @@ config SND_SOC_PCM3008 | |||
296 | config SND_SOC_RT5631 | 298 | config SND_SOC_RT5631 |
297 | tristate | 299 | tristate |
298 | 300 | ||
301 | config SND_SOC_RT5640 | ||
302 | tristate | ||
303 | |||
299 | #Freescale sgtl5000 codec | 304 | #Freescale sgtl5000 codec |
300 | config SND_SOC_SGTL5000 | 305 | config SND_SOC_SGTL5000 |
301 | tristate | 306 | tristate |
@@ -313,6 +318,9 @@ config SND_SOC_SN95031 | |||
313 | config SND_SOC_SPDIF | 318 | config SND_SOC_SPDIF |
314 | tristate | 319 | tristate |
315 | 320 | ||
321 | config SND_SOC_SSM2518 | ||
322 | tristate | ||
323 | |||
316 | config SND_SOC_SSM2602 | 324 | config 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 | |||
27 | snd-soc-da7213-objs := da7213.o | 27 | snd-soc-da7213-objs := da7213.o |
28 | snd-soc-da732x-objs := da732x.o | 28 | snd-soc-da732x-objs := da732x.o |
29 | snd-soc-da9055-objs := da9055.o | 29 | snd-soc-da9055-objs := da9055.o |
30 | snd-soc-dfbmcs320-objs := dfbmcs320.o | 30 | snd-soc-bt-sco-objs := bt-sco.o |
31 | snd-soc-dmic-objs := dmic.o | 31 | snd-soc-dmic-objs := dmic.o |
32 | snd-soc-isabelle-objs := isabelle.o | 32 | snd-soc-isabelle-objs := isabelle.o |
33 | snd-soc-jz4740-codec-objs := jz4740.o | 33 | snd-soc-jz4740-codec-objs := jz4740.o |
@@ -41,17 +41,19 @@ snd-soc-max98095-objs := max98095.o | |||
41 | snd-soc-max9850-objs := max9850.o | 41 | snd-soc-max9850-objs := max9850.o |
42 | snd-soc-mc13783-objs := mc13783.o | 42 | snd-soc-mc13783-objs := mc13783.o |
43 | snd-soc-ml26124-objs := ml26124.o | 43 | snd-soc-ml26124-objs := ml26124.o |
44 | snd-soc-omap-hdmi-codec-objs := omap-hdmi.o | 44 | snd-soc-hdmi-codec-objs := hdmi.o |
45 | snd-soc-pcm3008-objs := pcm3008.o | 45 | snd-soc-pcm3008-objs := pcm3008.o |
46 | snd-soc-rt5631-objs := rt5631.o | 46 | snd-soc-rt5631-objs := rt5631.o |
47 | snd-soc-rt5640-objs := rt5640.o | ||
47 | snd-soc-sgtl5000-objs := sgtl5000.o | 48 | snd-soc-sgtl5000-objs := sgtl5000.o |
48 | snd-soc-alc5623-objs := alc5623.o | 49 | snd-soc-alc5623-objs := alc5623.o |
49 | snd-soc-alc5632-objs := alc5632.o | 50 | snd-soc-alc5632-objs := alc5632.o |
50 | snd-soc-sigmadsp-objs := sigmadsp.o | 51 | snd-soc-sigmadsp-objs := sigmadsp.o |
51 | snd-soc-si476x-objs := si476x.o | 52 | snd-soc-si476x-objs := si476x.o |
52 | snd-soc-sn95031-objs := sn95031.o | 53 | snd-soc-sn95031-objs := sn95031.o |
53 | snd-soc-spdif-tx-objs := spdif_transciever.o | 54 | snd-soc-spdif-tx-objs := spdif_transmitter.o |
54 | snd-soc-spdif-rx-objs := spdif_receiver.o | 55 | snd-soc-spdif-rx-objs := spdif_receiver.o |
56 | snd-soc-ssm2518-objs := ssm2518.o | ||
55 | snd-soc-ssm2602-objs := ssm2602.o | 57 | snd-soc-ssm2602-objs := ssm2602.o |
56 | snd-soc-sta32x-objs := sta32x.o | 58 | snd-soc-sta32x-objs := sta32x.o |
57 | snd-soc-sta529-objs := sta529.o | 59 | snd-soc-sta529-objs := sta529.o |
@@ -154,7 +156,7 @@ obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o | |||
154 | obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o | 156 | obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o |
155 | obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o | 157 | obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o |
156 | obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o | 158 | obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o |
157 | obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o | 159 | obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o |
158 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o | 160 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o |
159 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o | 161 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o |
160 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o | 162 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o |
@@ -168,14 +170,16 @@ obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o | |||
168 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o | 170 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o |
169 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o | 171 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o |
170 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o | 172 | obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o |
171 | obj-$(CONFIG_SND_SOC_OMAP_HDMI_CODEC) += snd-soc-omap-hdmi-codec.o | 173 | obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o |
172 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o | 174 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o |
173 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o | 175 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o |
176 | obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o | ||
174 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o | 177 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o |
175 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o | 178 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o |
176 | obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o | 179 | obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o |
177 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o | 180 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o |
178 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o | 181 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o |
182 | obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o | ||
179 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | 183 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
180 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o | 184 | obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o |
181 | obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o | 185 | obj-$(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"}; |
1500 | static SOC_ENUM_SINGLE_DECL(soc_enum_adslot0map, | 1506 | static 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 | ||
2383 | static 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 | |||
2359 | static struct snd_soc_dai_driver ab8500_codec_dai[] = { | 2388 | static 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 | ||
89 | struct adau1701 { | 92 | struct 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 | ||
183 | static int adau1701_load_firmware(struct snd_soc_codec *codec) | 187 | static 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 | |||
202 | static 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 | ||
188 | static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, | 220 | static 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 | ||
488 | static const struct of_device_id adau1701_dt_ids[] = { | ||
489 | { .compatible = "adi,adau1701", }, | ||
490 | { } | ||
491 | }; | ||
492 | MODULE_DEVICE_TABLE(of, adau1701_dt_ids); | ||
493 | #endif | ||
494 | |||
455 | static int adau1701_probe(struct snd_soc_codec *codec) | 495 | static 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 | }; |
1199 | EXPORT_SYMBOL_GPL(arizona_dai_ops); | 1199 | EXPORT_SYMBOL_GPL(arizona_dai_ops); |
1200 | 1200 | ||
1201 | const 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 | }; | ||
1206 | EXPORT_SYMBOL_GPL(arizona_simple_dai_ops); | ||
1207 | |||
1201 | int arizona_init_dai(struct arizona_priv *priv, int id) | 1208 | int 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 | ||
63 | struct arizona; | 63 | struct 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 | ||
215 | extern const struct snd_soc_dai_ops arizona_dai_ops; | 215 | extern const struct snd_soc_dai_ops arizona_dai_ops; |
216 | extern 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 | ||
18 | static struct snd_soc_dai_driver dfbmcs320_dai = { | 18 | static 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 | ||
34 | static struct snd_soc_codec_driver soc_codec_dev_dfbmcs320; | 34 | static struct snd_soc_codec_driver soc_codec_dev_bt_sco; |
35 | 35 | ||
36 | static int dfbmcs320_probe(struct platform_device *pdev) | 36 | static 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 | ||
42 | static int dfbmcs320_remove(struct platform_device *pdev) | 42 | static 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 | ||
49 | static struct platform_driver dfmcs320_driver = { | 49 | static struct platform_device_id bt_sco_driver_ids[] = { |
50 | { | ||
51 | .name = "dfbmcs320", | ||
52 | }, | ||
53 | {}, | ||
54 | }; | ||
55 | MODULE_DEVICE_TABLE(platform, bt_sco_driver_ids); | ||
56 | |||
57 | static 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 | ||
58 | module_platform_driver(dfmcs320_driver); | 67 | module_platform_driver(bt_sco_driver); |
59 | 68 | ||
60 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 69 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
61 | MODULE_DESCRIPTION("ASoC DFBM-CS320 bluethooth module driver"); | 70 | MODULE_DESCRIPTION("ASoC generic bluethooth sco link driver"); |
62 | MODULE_LICENSE("GPL"); | 71 | MODULE_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 | ||
26 | static struct snd_soc_codec_driver omap_hdmi_codec; | 26 | static struct snd_soc_codec_driver hdmi_codec; |
27 | 27 | ||
28 | static struct snd_soc_dai_driver omap_hdmi_codec_dai = { | 28 | static 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 | ||
42 | static int omap_hdmi_codec_probe(struct platform_device *pdev) | 42 | static 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 | ||
48 | static int omap_hdmi_codec_remove(struct platform_device *pdev) | 48 | static 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 | ||
54 | static struct platform_driver omap_hdmi_codec_driver = { | 54 | static 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 | ||
64 | module_platform_driver(omap_hdmi_codec_driver); | 64 | module_platform_driver(hdmi_codec_driver); |
65 | 65 | ||
66 | MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>"); | 66 | MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>"); |
67 | MODULE_DESCRIPTION("ASoC OMAP HDMI codec driver"); | 67 | MODULE_DESCRIPTION("ASoC generic HDMI codec driver"); |
68 | MODULE_LICENSE("GPL"); | 68 | MODULE_LICENSE("GPL"); |
69 | MODULE_ALIAS("platform:" DRV_NAME); | 69 | MODULE_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 = | |||
857 | static const struct snd_kcontrol_new max98090_mic2_mux = | 857 | static 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 | ||
860 | static const char *dmic_mux_text[] = { "ADC", "DMIC" }; | ||
861 | |||
862 | static const struct soc_enum dmic_mux_enum = | ||
863 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dmic_mux_text), dmic_mux_text); | ||
864 | |||
865 | static const struct snd_kcontrol_new max98090_dmic_mux = | ||
866 | SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum); | ||
867 | |||
860 | static const char *max98090_micpre_text[] = { "Off", "On" }; | 868 | static const char *max98090_micpre_text[] = { "Off", "On" }; |
861 | 869 | ||
862 | static const struct soc_enum max98090_pa1en_enum = | 870 | static 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 | ||
2339 | static int max98090_runtime_resume(struct device *dev) | 2354 | static 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 | ||
2359 | static const struct dev_pm_ops max98090_pm = { | 2375 | static 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 | |||
41 | static 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 | |||
51 | static 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 | |||
63 | static 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 | |||
169 | static int rt5640_reset(struct snd_soc_codec *codec) | ||
170 | { | ||
171 | return snd_soc_write(codec, RT5640_RESET, 0); | ||
172 | } | ||
173 | |||
174 | static 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 | |||
209 | static 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 | |||
343 | static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); | ||
344 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); | ||
345 | static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); | ||
346 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); | ||
347 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | ||
348 | |||
349 | /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ | ||
350 | static 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 */ | ||
362 | static const char * const rt5640_data_select[] = { | ||
363 | "Normal", "left copy to right", "right copy to left", "Swap"}; | ||
364 | |||
365 | static const SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA, | ||
366 | RT5640_IF1_DAC_SEL_SFT, rt5640_data_select); | ||
367 | |||
368 | static const SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA, | ||
369 | RT5640_IF1_ADC_SEL_SFT, rt5640_data_select); | ||
370 | |||
371 | static const SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA, | ||
372 | RT5640_IF2_DAC_SEL_SFT, rt5640_data_select); | ||
373 | |||
374 | static 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 */ | ||
378 | static 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 | |||
381 | static 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 | |||
385 | static 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 | */ | ||
460 | static 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 | |||
489 | static 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 */ | ||
503 | static 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 | |||
510 | static 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 | |||
517 | static 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 | |||
524 | static 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 | |||
531 | static 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 | |||
538 | static 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 | |||
545 | static 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 | |||
554 | static 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 | |||
563 | static 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 | |||
572 | static 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 | |||
581 | static 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 | |||
588 | static 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 */ | ||
596 | static 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 | |||
609 | static 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 */ | ||
623 | static 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 | |||
636 | static 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 | |||
649 | static 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 | |||
666 | static 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 | |||
685 | static 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 | |||
698 | static 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 | |||
707 | static 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 | |||
716 | static 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 | |||
727 | static 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 */ | ||
741 | static const char * const rt5640_inl_src[] = { | ||
742 | "IN2P", "MONOP" | ||
743 | }; | ||
744 | |||
745 | static const SOC_ENUM_SINGLE_DECL( | ||
746 | rt5640_inl_enum, RT5640_INL_INR_VOL, | ||
747 | RT5640_INL_SEL_SFT, rt5640_inl_src); | ||
748 | |||
749 | static const struct snd_kcontrol_new rt5640_inl_mux = | ||
750 | SOC_DAPM_ENUM("INL source", rt5640_inl_enum); | ||
751 | |||
752 | static const char * const rt5640_inr_src[] = { | ||
753 | "IN2N", "MONON" | ||
754 | }; | ||
755 | |||
756 | static const SOC_ENUM_SINGLE_DECL( | ||
757 | rt5640_inr_enum, RT5640_INL_INR_VOL, | ||
758 | RT5640_INR_SEL_SFT, rt5640_inr_src); | ||
759 | |||
760 | static const struct snd_kcontrol_new rt5640_inr_mux = | ||
761 | SOC_DAPM_ENUM("INR source", rt5640_inr_enum); | ||
762 | |||
763 | /* Stereo ADC source */ | ||
764 | static const char * const rt5640_stereo_adc1_src[] = { | ||
765 | "DIG MIX", "ADC" | ||
766 | }; | ||
767 | |||
768 | static 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 | |||
772 | static const struct snd_kcontrol_new rt5640_sto_adc_1_mux = | ||
773 | SOC_DAPM_ENUM("Stereo ADC1 Mux", rt5640_stereo_adc1_enum); | ||
774 | |||
775 | static const char * const rt5640_stereo_adc2_src[] = { | ||
776 | "DMIC1", "DMIC2", "DIG MIX" | ||
777 | }; | ||
778 | |||
779 | static 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 | |||
783 | static 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 */ | ||
787 | static const char * const rt5640_mono_adc_l1_src[] = { | ||
788 | "Mono DAC MIXL", "ADCL" | ||
789 | }; | ||
790 | |||
791 | static 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 | |||
795 | static const struct snd_kcontrol_new rt5640_mono_adc_l1_mux = | ||
796 | SOC_DAPM_ENUM("Mono ADC1 left source", rt5640_mono_adc_l1_enum); | ||
797 | |||
798 | static const char * const rt5640_mono_adc_l2_src[] = { | ||
799 | "DMIC L1", "DMIC L2", "Mono DAC MIXL" | ||
800 | }; | ||
801 | |||
802 | static 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 | |||
806 | static const struct snd_kcontrol_new rt5640_mono_adc_l2_mux = | ||
807 | SOC_DAPM_ENUM("Mono ADC2 left source", rt5640_mono_adc_l2_enum); | ||
808 | |||
809 | static const char * const rt5640_mono_adc_r1_src[] = { | ||
810 | "Mono DAC MIXR", "ADCR" | ||
811 | }; | ||
812 | |||
813 | static 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 | |||
817 | static const struct snd_kcontrol_new rt5640_mono_adc_r1_mux = | ||
818 | SOC_DAPM_ENUM("Mono ADC1 right source", rt5640_mono_adc_r1_enum); | ||
819 | |||
820 | static const char * const rt5640_mono_adc_r2_src[] = { | ||
821 | "DMIC R1", "DMIC R2", "Mono DAC MIXR" | ||
822 | }; | ||
823 | |||
824 | static 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 | |||
828 | static 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 */ | ||
832 | static const char * const rt5640_dac_l2_src[] = { | ||
833 | "IF2", "Base L/R" | ||
834 | }; | ||
835 | |||
836 | static int rt5640_dac_l2_values[] = { | ||
837 | 0, | ||
838 | 3, | ||
839 | }; | ||
840 | |||
841 | static 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 | |||
845 | static const struct snd_kcontrol_new rt5640_dac_l2_mux = | ||
846 | SOC_DAPM_VALUE_ENUM("DAC2 left channel source", rt5640_dac_l2_enum); | ||
847 | |||
848 | static const char * const rt5640_dac_r2_src[] = { | ||
849 | "IF2", | ||
850 | }; | ||
851 | |||
852 | static int rt5640_dac_r2_values[] = { | ||
853 | 0, | ||
854 | }; | ||
855 | |||
856 | static 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 | |||
860 | static 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 */ | ||
864 | static 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 | |||
868 | static int rt5640_dai_iis_map_values[] = { | ||
869 | 0, | ||
870 | 5, | ||
871 | 6, | ||
872 | 7, | ||
873 | }; | ||
874 | |||
875 | static 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 | |||
879 | static const struct snd_kcontrol_new rt5640_dai_mux = | ||
880 | SOC_DAPM_VALUE_ENUM("DAI select", rt5640_dai_iis_map_enum); | ||
881 | |||
882 | /* SDI select */ | ||
883 | static const char * const rt5640_sdi_sel[] = { | ||
884 | "IF1", "IF2" | ||
885 | }; | ||
886 | |||
887 | static const SOC_ENUM_SINGLE_DECL( | ||
888 | rt5640_sdi_sel_enum, RT5640_I2S2_SDP, | ||
889 | RT5640_I2S2_SDI_SFT, rt5640_sdi_sel); | ||
890 | |||
891 | static const struct snd_kcontrol_new rt5640_sdi_mux = | ||
892 | SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum); | ||
893 | |||
894 | static 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 | |||
921 | static 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 | |||
945 | static 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 | |||
969 | static 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 | |||
1183 | static 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 | |||
1450 | static 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 | |||
1498 | static 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 | |||
1513 | static 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 | |||
1585 | static 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 | |||
1648 | static 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 | */ | ||
1695 | static 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 | |||
1729 | code_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 | |||
1737 | static 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 | |||
1808 | static 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 | |||
1857 | static 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 | |||
1883 | static int rt5640_remove(struct snd_soc_codec *codec) | ||
1884 | { | ||
1885 | rt5640_reset(codec); | ||
1886 | |||
1887 | return 0; | ||
1888 | } | ||
1889 | |||
1890 | #ifdef CONFIG_PM | ||
1891 | static 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 | |||
1903 | static 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 | |||
1918 | static 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 | |||
1925 | static 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 | |||
1966 | static 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 | |||
1980 | static 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 | |||
1996 | static const struct i2c_device_id rt5640_i2c_id[] = { | ||
1997 | { "rt5640", 0 }, | ||
1998 | { } | ||
1999 | }; | ||
2000 | MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id); | ||
2001 | |||
2002 | static 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 | |||
2024 | static 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; | ||
2104 | err: | ||
2105 | return ret; | ||
2106 | } | ||
2107 | |||
2108 | static int rt5640_i2c_remove(struct i2c_client *i2c) | ||
2109 | { | ||
2110 | snd_soc_unregister_codec(&i2c->dev); | ||
2111 | |||
2112 | return 0; | ||
2113 | } | ||
2114 | |||
2115 | static 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 | }; | ||
2124 | module_i2c_driver(rt5640_i2c_driver); | ||
2125 | |||
2126 | MODULE_DESCRIPTION("ASoC RT5640 driver"); | ||
2127 | MODULE_AUTHOR("Johnny Hsu <johnnyhsu@realtek.com>"); | ||
2128 | MODULE_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 | ||
1996 | enum { | ||
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 | |||
2035 | enum { | ||
2036 | RT5640_AIF1, | ||
2037 | RT5640_AIF2, | ||
2038 | RT5640_AIF3, | ||
2039 | RT5640_AIFS, | ||
2040 | }; | ||
2041 | |||
2042 | enum { | ||
2043 | RT5640_U_IF1 = 0x1, | ||
2044 | RT5640_U_IF2 = 0x2, | ||
2045 | RT5640_U_IF3 = 0x4, | ||
2046 | }; | ||
2047 | |||
2048 | enum { | ||
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 | |||
2060 | enum { | ||
2061 | RT5640_DMIC_DIS, | ||
2062 | RT5640_DMIC1, | ||
2063 | RT5640_DMIC2, | ||
2064 | }; | ||
2065 | |||
2066 | struct 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 | |||
2073 | struct 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 */ |
37 | static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET] = { | 38 | static 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 | ||
961 | static int sgtl5000_volatile_register(struct snd_soc_codec *codec, | 975 | static 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 | |||
987 | static 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 | ||
1215 | static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | 1288 | static 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, ®); | ||
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 | ||
1470 | static 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 | */ | ||
1493 | static 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 | |||
1407 | static int sgtl5000_i2c_probe(struct i2c_client *client, | 1508 | static 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, ®); | ||
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 | |||
1567 | disable_clk: | ||
1568 | clk_disable_unprepare(sgtl5000->mclk); | ||
1422 | return ret; | 1569 | return ret; |
1423 | } | 1570 | } |
1424 | 1571 | ||
1425 | static int sgtl5000_i2c_remove(struct i2c_client *client) | 1572 | static 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 | ||
886 | struct snd_soc_codec_driver sn95031_codec = { | 886 | static 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 | ||
56 | static const struct of_device_id spdif_dir_dt_ids[] = { | ||
57 | { .compatible = "linux,spdif-dir", }, | ||
58 | { } | ||
59 | }; | ||
60 | MODULE_DEVICE_TABLE(of, spdif_dir_dt_ids); | ||
61 | #endif | ||
62 | |||
54 | static struct platform_driver spdif_dir_driver = { | 63 | static 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 | ||
57 | static const struct of_device_id spdif_dit_dt_ids[] = { | ||
58 | { .compatible = "linux,spdif-dit", }, | ||
59 | { } | ||
60 | }; | ||
61 | MODULE_DEVICE_TABLE(of, spdif_dit_dt_ids); | ||
62 | #endif | ||
63 | |||
55 | static struct platform_driver spdif_dit_driver = { | 64 | static 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 | |||
111 | struct 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 | |||
121 | static 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 | |||
143 | static const DECLARE_TLV_DB_MINMAX_MUTE(ssm2518_vol_tlv, -7125, 2400); | ||
144 | static const DECLARE_TLV_DB_SCALE(ssm2518_compressor_tlv, -3400, 200, 0); | ||
145 | static const DECLARE_TLV_DB_SCALE(ssm2518_expander_tlv, -8100, 300, 0); | ||
146 | static const DECLARE_TLV_DB_SCALE(ssm2518_noise_gate_tlv, -9600, 300, 0); | ||
147 | static const DECLARE_TLV_DB_SCALE(ssm2518_post_drc_tlv, -2400, 300, 0); | ||
148 | |||
149 | static 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 | |||
154 | static 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 | |||
160 | static 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 | |||
166 | static 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 | |||
172 | static 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); | ||
174 | static 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); | ||
176 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum, | ||
177 | SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text); | ||
178 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum, | ||
179 | SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text); | ||
180 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum, | ||
181 | SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text); | ||
182 | static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum, | ||
183 | SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text); | ||
184 | static 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 | |||
187 | static 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 | |||
230 | static 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 | |||
238 | static const struct snd_soc_dapm_route ssm2518_routes[] = { | ||
239 | { "OUTL", NULL, "DACL" }, | ||
240 | { "OUTR", NULL, "DACR" }, | ||
241 | }; | ||
242 | |||
243 | struct ssm2518_mcs_lut { | ||
244 | unsigned int rate; | ||
245 | const unsigned int *sysclks; | ||
246 | }; | ||
247 | |||
248 | static const unsigned int ssm2518_sysclks_2048000[] = { | ||
249 | 2048000, 4096000, 8192000, 12288000, 16384000, 24576000, | ||
250 | 3200000, 6400000, 12800000, 0 | ||
251 | }; | ||
252 | |||
253 | static const unsigned int ssm2518_sysclks_2822000[] = { | ||
254 | 2822000, 5644800, 11289600, 16934400, 22579200, 33868800, | ||
255 | 4410000, 8820000, 17640000, 0 | ||
256 | }; | ||
257 | |||
258 | static const unsigned int ssm2518_sysclks_3072000[] = { | ||
259 | 3072000, 6144000, 12288000, 16384000, 24576000, 38864000, | ||
260 | 4800000, 9600000, 19200000, 0 | ||
261 | }; | ||
262 | |||
263 | static 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 | |||
276 | static const unsigned int ssm2518_rates_2048000[] = { | ||
277 | 8000, 16000, 32000, | ||
278 | }; | ||
279 | |||
280 | static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2048000 = { | ||
281 | .list = ssm2518_rates_2048000, | ||
282 | .count = ARRAY_SIZE(ssm2518_rates_2048000), | ||
283 | }; | ||
284 | |||
285 | static const unsigned int ssm2518_rates_2822000[] = { | ||
286 | 11025, 22050, 44100, | ||
287 | }; | ||
288 | |||
289 | static const struct snd_pcm_hw_constraint_list ssm2518_constraints_2822000 = { | ||
290 | .list = ssm2518_rates_2822000, | ||
291 | .count = ARRAY_SIZE(ssm2518_rates_2822000), | ||
292 | }; | ||
293 | |||
294 | static const unsigned int ssm2518_rates_3072000[] = { | ||
295 | 12000, 24000, 48000, 96000, | ||
296 | }; | ||
297 | |||
298 | static const struct snd_pcm_hw_constraint_list ssm2518_constraints_3072000 = { | ||
299 | .list = ssm2518_rates_3072000, | ||
300 | .count = ARRAY_SIZE(ssm2518_rates_3072000), | ||
301 | }; | ||
302 | |||
303 | static const unsigned int ssm2518_rates_12288000[] = { | ||
304 | 8000, 12000, 16000, 24000, 32000, 48000, 96000, | ||
305 | }; | ||
306 | |||
307 | static const struct snd_pcm_hw_constraint_list ssm2518_constraints_12288000 = { | ||
308 | .list = ssm2518_rates_12288000, | ||
309 | .count = ARRAY_SIZE(ssm2518_rates_12288000), | ||
310 | }; | ||
311 | |||
312 | static 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 | |||
336 | static 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 | |||
392 | static 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 | |||
406 | static 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 | |||
477 | static 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 | |||
501 | static 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 | |||
529 | static 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 | |||
614 | static 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 | |||
629 | static 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 | |||
637 | static 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 | |||
649 | static 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 | |||
664 | static int ssm2518_remove(struct snd_soc_codec *codec) | ||
665 | { | ||
666 | ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
667 | return 0; | ||
668 | } | ||
669 | |||
670 | static 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 | |||
739 | static 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 | |||
754 | static bool ssm2518_register_volatile(struct device *dev, unsigned int reg) | ||
755 | { | ||
756 | return false; | ||
757 | } | ||
758 | |||
759 | static 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 | |||
771 | static 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 | |||
831 | static int ssm2518_i2c_remove(struct i2c_client *client) | ||
832 | { | ||
833 | snd_soc_unregister_codec(&client->dev); | ||
834 | return 0; | ||
835 | } | ||
836 | |||
837 | static const struct i2c_device_id ssm2518_i2c_ids[] = { | ||
838 | { "ssm2518", 0 }, | ||
839 | { } | ||
840 | }; | ||
841 | MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids); | ||
842 | |||
843 | static 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 | }; | ||
852 | module_i2c_driver(ssm2518_driver); | ||
853 | |||
854 | MODULE_DESCRIPTION("ASoC SSM2518 driver"); | ||
855 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
856 | MODULE_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 | |||
15 | enum 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 | ||
815 | SOC_VALUE_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]), | 815 | SOC_VALUE_ENUM("HPOUT1 OSR", wm5102_hpout_osr[0]), |
816 | SOC_VALUE_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]), | 816 | SOC_VALUE_ENUM("HPOUT2 OSR", wm5102_hpout_osr[1]), |
817 | SOC_VALUE_ENUM("HPOUT3 OSR", wm5102_hpout_osr[2]), | 817 | SOC_VALUE_ENUM("EPOUT OSR", wm5102_hpout_osr[2]), |
818 | |||
819 | SOC_DOUBLE("HPOUT1 DRE Switch", ARIZONA_DRE_ENABLE, | ||
820 | ARIZONA_DRE1L_ENA_SHIFT, ARIZONA_DRE1R_ENA_SHIFT, 1, 0), | ||
821 | SOC_DOUBLE("HPOUT2 DRE Switch", ARIZONA_DRE_ENABLE, | ||
822 | ARIZONA_DRE2L_ENA_SHIFT, ARIZONA_DRE2R_ENA_SHIFT, 1, 0), | ||
823 | SOC_SINGLE("EPOUT DRE Switch", ARIZONA_DRE_ENABLE, | ||
824 | ARIZONA_DRE3L_ENA_SHIFT, 1, 0), | ||
825 | |||
826 | SOC_SINGLE("DRE Threshold", ARIZONA_DRE_CONTROL_2, | ||
827 | ARIZONA_DRE_T_LOW_SHIFT, 63, 0), | ||
828 | |||
829 | SOC_SINGLE("DRE Low Level ABS", ARIZONA_DRE_CONTROL_3, | ||
830 | ARIZONA_DRE_LOW_LEVEL_ABS_SHIFT, 15, 0), | ||
818 | 831 | ||
819 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), | 832 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), |
820 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), | 833 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), |
@@ -852,6 +865,15 @@ ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE), | |||
852 | 865 | ||
853 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), | 866 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), |
854 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), | 867 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), |
868 | |||
869 | ARIZONA_MIXER_CONTROLS("SLIMTX1", ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE), | ||
870 | ARIZONA_MIXER_CONTROLS("SLIMTX2", ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE), | ||
871 | ARIZONA_MIXER_CONTROLS("SLIMTX3", ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE), | ||
872 | ARIZONA_MIXER_CONTROLS("SLIMTX4", ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE), | ||
873 | ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE), | ||
874 | ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE), | ||
875 | ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE), | ||
876 | ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE), | ||
855 | }; | 877 | }; |
856 | 878 | ||
857 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); | 879 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); |
@@ -898,6 +920,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | |||
898 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); | 920 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); |
899 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); | 921 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); |
900 | 922 | ||
923 | ARIZONA_MIXER_ENUMS(SLIMTX1, ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE); | ||
924 | ARIZONA_MIXER_ENUMS(SLIMTX2, ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE); | ||
925 | ARIZONA_MIXER_ENUMS(SLIMTX3, ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE); | ||
926 | ARIZONA_MIXER_ENUMS(SLIMTX4, ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE); | ||
927 | ARIZONA_MIXER_ENUMS(SLIMTX5, ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE); | ||
928 | ARIZONA_MIXER_ENUMS(SLIMTX6, ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE); | ||
929 | ARIZONA_MIXER_ENUMS(SLIMTX7, ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE); | ||
930 | ARIZONA_MIXER_ENUMS(SLIMTX8, ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE); | ||
931 | |||
901 | ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); | 932 | ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); |
902 | ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | 933 | ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); |
903 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 934 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
@@ -1117,6 +1148,56 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, | |||
1117 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | 1148 | SND_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 | ||
1151 | SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, | ||
1152 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1153 | ARIZONA_SLIMTX1_ENA_SHIFT, 0), | ||
1154 | SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, | ||
1155 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1156 | ARIZONA_SLIMTX2_ENA_SHIFT, 0), | ||
1157 | SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, | ||
1158 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1159 | ARIZONA_SLIMTX3_ENA_SHIFT, 0), | ||
1160 | SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, | ||
1161 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1162 | ARIZONA_SLIMTX4_ENA_SHIFT, 0), | ||
1163 | SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, | ||
1164 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1165 | ARIZONA_SLIMTX5_ENA_SHIFT, 0), | ||
1166 | SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, | ||
1167 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1168 | ARIZONA_SLIMTX6_ENA_SHIFT, 0), | ||
1169 | SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, | ||
1170 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1171 | ARIZONA_SLIMTX7_ENA_SHIFT, 0), | ||
1172 | SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, | ||
1173 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
1174 | ARIZONA_SLIMTX8_ENA_SHIFT, 0), | ||
1175 | |||
1176 | SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, | ||
1177 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1178 | ARIZONA_SLIMRX1_ENA_SHIFT, 0), | ||
1179 | SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, | ||
1180 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1181 | ARIZONA_SLIMRX2_ENA_SHIFT, 0), | ||
1182 | SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, | ||
1183 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1184 | ARIZONA_SLIMRX3_ENA_SHIFT, 0), | ||
1185 | SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, | ||
1186 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1187 | ARIZONA_SLIMRX4_ENA_SHIFT, 0), | ||
1188 | SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, | ||
1189 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1190 | ARIZONA_SLIMRX5_ENA_SHIFT, 0), | ||
1191 | SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, | ||
1192 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1193 | ARIZONA_SLIMRX6_ENA_SHIFT, 0), | ||
1194 | SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, | ||
1195 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1196 | ARIZONA_SLIMRX7_ENA_SHIFT, 0), | ||
1197 | SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, | ||
1198 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
1199 | ARIZONA_SLIMRX8_ENA_SHIFT, 0), | ||
1200 | |||
1120 | ARIZONA_DSP_WIDGETS(DSP1, "DSP1"), | 1201 | ARIZONA_DSP_WIDGETS(DSP1, "DSP1"), |
1121 | 1202 | ||
1122 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | 1203 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, |
@@ -1189,6 +1270,15 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | |||
1189 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | 1270 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), |
1190 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | 1271 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), |
1191 | 1272 | ||
1273 | ARIZONA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"), | ||
1274 | ARIZONA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"), | ||
1275 | ARIZONA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"), | ||
1276 | ARIZONA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"), | ||
1277 | ARIZONA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"), | ||
1278 | ARIZONA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"), | ||
1279 | ARIZONA_MIXER_WIDGETS(SLIMTX7, "SLIMTX7"), | ||
1280 | ARIZONA_MIXER_WIDGETS(SLIMTX8, "SLIMTX8"), | ||
1281 | |||
1192 | ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), | 1282 | ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), |
1193 | ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), | 1283 | ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), |
1194 | ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), | 1284 | ARIZONA_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 | ||
1565 | static int wm5102_codec_probe(struct snd_soc_codec *codec) | 1768 | static 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 | ||
310 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), | 310 | ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE), |
311 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), | 311 | ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE), |
312 | |||
313 | ARIZONA_MIXER_CONTROLS("SLIMTX1", ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE), | ||
314 | ARIZONA_MIXER_CONTROLS("SLIMTX2", ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE), | ||
315 | ARIZONA_MIXER_CONTROLS("SLIMTX3", ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE), | ||
316 | ARIZONA_MIXER_CONTROLS("SLIMTX4", ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE), | ||
317 | ARIZONA_MIXER_CONTROLS("SLIMTX5", ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE), | ||
318 | ARIZONA_MIXER_CONTROLS("SLIMTX6", ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE), | ||
319 | ARIZONA_MIXER_CONTROLS("SLIMTX7", ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE), | ||
320 | ARIZONA_MIXER_CONTROLS("SLIMTX8", ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE), | ||
312 | }; | 321 | }; |
313 | 322 | ||
314 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); | 323 | ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE); |
@@ -360,6 +369,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | |||
360 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); | 369 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); |
361 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); | 370 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); |
362 | 371 | ||
372 | ARIZONA_MIXER_ENUMS(SLIMTX1, ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE); | ||
373 | ARIZONA_MIXER_ENUMS(SLIMTX2, ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE); | ||
374 | ARIZONA_MIXER_ENUMS(SLIMTX3, ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE); | ||
375 | ARIZONA_MIXER_ENUMS(SLIMTX4, ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE); | ||
376 | ARIZONA_MIXER_ENUMS(SLIMTX5, ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE); | ||
377 | ARIZONA_MIXER_ENUMS(SLIMTX6, ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE); | ||
378 | ARIZONA_MIXER_ENUMS(SLIMTX7, ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE); | ||
379 | ARIZONA_MIXER_ENUMS(SLIMTX8, ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE); | ||
380 | |||
363 | ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); | 381 | ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); |
364 | ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | 382 | ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); |
365 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 383 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
@@ -550,6 +568,56 @@ SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, | |||
550 | SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0, | 568 | SND_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 | ||
571 | SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0, | ||
572 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
573 | ARIZONA_SLIMRX1_ENA_SHIFT, 0), | ||
574 | SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0, | ||
575 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
576 | ARIZONA_SLIMRX2_ENA_SHIFT, 0), | ||
577 | SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0, | ||
578 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
579 | ARIZONA_SLIMRX3_ENA_SHIFT, 0), | ||
580 | SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0, | ||
581 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
582 | ARIZONA_SLIMRX4_ENA_SHIFT, 0), | ||
583 | SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0, | ||
584 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
585 | ARIZONA_SLIMRX5_ENA_SHIFT, 0), | ||
586 | SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0, | ||
587 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
588 | ARIZONA_SLIMRX6_ENA_SHIFT, 0), | ||
589 | SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0, | ||
590 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
591 | ARIZONA_SLIMRX7_ENA_SHIFT, 0), | ||
592 | SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0, | ||
593 | ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE, | ||
594 | ARIZONA_SLIMRX8_ENA_SHIFT, 0), | ||
595 | |||
596 | SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0, | ||
597 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
598 | ARIZONA_SLIMTX1_ENA_SHIFT, 0), | ||
599 | SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0, | ||
600 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
601 | ARIZONA_SLIMTX2_ENA_SHIFT, 0), | ||
602 | SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0, | ||
603 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
604 | ARIZONA_SLIMTX3_ENA_SHIFT, 0), | ||
605 | SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0, | ||
606 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
607 | ARIZONA_SLIMTX4_ENA_SHIFT, 0), | ||
608 | SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0, | ||
609 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
610 | ARIZONA_SLIMTX5_ENA_SHIFT, 0), | ||
611 | SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0, | ||
612 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
613 | ARIZONA_SLIMTX6_ENA_SHIFT, 0), | ||
614 | SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0, | ||
615 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
616 | ARIZONA_SLIMTX7_ENA_SHIFT, 0), | ||
617 | SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0, | ||
618 | ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE, | ||
619 | ARIZONA_SLIMTX8_ENA_SHIFT, 0), | ||
620 | |||
553 | SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0, | 621 | SND_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), |
555 | SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, | 623 | SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0, |
@@ -640,6 +708,15 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | |||
640 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | 708 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), |
641 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | 709 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), |
642 | 710 | ||
711 | ARIZONA_MIXER_WIDGETS(SLIMTX1, "SLIMTX1"), | ||
712 | ARIZONA_MIXER_WIDGETS(SLIMTX2, "SLIMTX2"), | ||
713 | ARIZONA_MIXER_WIDGETS(SLIMTX3, "SLIMTX3"), | ||
714 | ARIZONA_MIXER_WIDGETS(SLIMTX4, "SLIMTX4"), | ||
715 | ARIZONA_MIXER_WIDGETS(SLIMTX5, "SLIMTX5"), | ||
716 | ARIZONA_MIXER_WIDGETS(SLIMTX6, "SLIMTX6"), | ||
717 | ARIZONA_MIXER_WIDGETS(SLIMTX7, "SLIMTX7"), | ||
718 | ARIZONA_MIXER_WIDGETS(SLIMTX8, "SLIMTX8"), | ||
719 | |||
643 | ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), | 720 | ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), |
644 | ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), | 721 | ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), |
645 | ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), | 722 | ARIZONA_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 | ||
968 | static int wm5110_codec_probe(struct snd_soc_codec *codec) | 1160 | static 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 */ |
53 | struct wm8962_priv { | 53 | struct 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 | ||
2346 | static int wm8962_add_widgets(struct snd_soc_codec *codec) | 2349 | static 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 = { | |||
3333 | static void wm8962_init_gpio(struct snd_soc_codec *codec) | 3337 | static 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 | ||
3589 | static 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 | |||
3587 | static int wm8962_i2c_probe(struct i2c_client *i2c, | 3617 | static 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 | ||
1502 | static const char *loopback_text[] = { | ||
1503 | "None", "ADCDAT", | ||
1504 | }; | ||
1505 | |||
1506 | static const struct soc_enum aif1_loopback_enum = | ||
1507 | SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, WM8994_AIF1_LOOPBACK_SHIFT, 2, | ||
1508 | loopback_text); | ||
1509 | |||
1510 | static const struct snd_kcontrol_new aif1_loopback = | ||
1511 | SOC_DAPM_ENUM("AIF1 Loopback", aif1_loopback_enum); | ||
1512 | |||
1513 | static const struct soc_enum aif2_loopback_enum = | ||
1514 | SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, WM8994_AIF2_LOOPBACK_SHIFT, 2, | ||
1515 | loopback_text); | ||
1516 | |||
1517 | static const struct snd_kcontrol_new aif2_loopback = | ||
1518 | SOC_DAPM_ENUM("AIF2 Loopback", aif2_loopback_enum); | ||
1519 | |||
1501 | static const struct soc_enum aif1dac_enum = | 1520 | static 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), | |||
1744 | SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), | 1763 | SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), |
1745 | SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), | 1764 | SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), |
1746 | 1765 | ||
1766 | SND_SOC_DAPM_MUX("AIF1 Loopback", SND_SOC_NOPM, 0, 0, &aif1_loopback), | ||
1767 | SND_SOC_DAPM_MUX("AIF2 Loopback", SND_SOC_NOPM, 0, 0, &aif2_loopback), | ||
1768 | |||
1747 | SND_SOC_DAPM_POST("Debug log", post_ev), | 1769 | SND_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 | ||
2017 | static int wm8994_get_fll_config(struct fll_div *fll, | 2046 | static 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) | |||
3096 | static int wm8994_codec_resume(struct snd_soc_codec *codec) | 3162 | static 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 | ||
3547 | static 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 | |||
3498 | static void wm8958_mic_id(void *data, u16 status) | 3572 | static 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 | } |
3781 | EXPORT_SYMBOL_GPL(wm8958_mic_detect); | 3850 | EXPORT_SYMBOL_GPL(wm8958_mic_detect); |
3782 | 3851 | ||
3852 | static 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 | |||
3783 | static irqreturn_t wm8958_mic_irq(int irq, void *data) | 3874 | static 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 | ||
219 | struct 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 | |||
228 | struct wm_coeff { | ||
229 | struct device *dev; | ||
230 | struct list_head ctl_list; | ||
231 | struct regmap *regmap; | ||
232 | }; | ||
233 | |||
234 | struct 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 | |||
218 | static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, | 249 | static 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 | ||
368 | static 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 | |||
378 | static 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 | |||
418 | static 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 | |||
434 | static 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 | |||
474 | static 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 | |||
484 | static 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 | |||
502 | struct wmfw_ctl_work { | ||
503 | struct wm_coeff *wm_coeff; | ||
504 | struct wm_coeff_ctl *ctl; | ||
505 | struct work_struct work; | ||
506 | }; | ||
507 | |||
508 | static 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 | |||
538 | err_kcontrol: | ||
539 | kfree(kcontrol); | ||
540 | return ret; | ||
541 | } | ||
542 | |||
337 | static int wm_adsp_load(struct wm_adsp *dsp) | 543 | static 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 | ||
550 | static int wm_adsp_setup_algs(struct wm_adsp *dsp) | 756 | static 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 | |||
775 | static 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 | |||
796 | static 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 | |||
806 | static 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 | |||
890 | found: | ||
891 | kfree(name); | ||
892 | |||
893 | return 0; | ||
894 | |||
895 | err_ctl_cache: | ||
896 | kfree(ctl->cache); | ||
897 | err_ctl_name: | ||
898 | kfree(ctl->name); | ||
899 | err_ctl: | ||
900 | kfree(ctl); | ||
901 | err_name: | ||
902 | kfree(name); | ||
903 | return ret; | ||
904 | } | ||
905 | |||
906 | static 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(®ion->list, &dsp->alg_regions); | 1090 | list_add_tail(®ion->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(®ion->list, &dsp->alg_regions); | 1107 | list_add_tail(®ion->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(®ion->list, &dsp->alg_regions); | 1136 | list_add_tail(®ion->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(®ion->list, &dsp->alg_regions); | 1153 | list_add_tail(®ion->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(®ion->list, &dsp->alg_regions); | 1170 | list_add_tail(®ion->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 | |||
1723 | out_coeff: | ||
1724 | kfree(adsp->wm_coeff); | ||
1725 | return ret; | ||
1281 | } | 1726 | } |
1282 | EXPORT_SYMBOL_GPL(wm_adsp2_init); | 1727 | EXPORT_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 | ||
35 | struct wm_adsp { | 36 | struct 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 | ||
57 | config 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 | |||
67 | config SND_DA830_SOC_EVM | 57 | config 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 |
13 | snd-soc-evm-objs := davinci-evm.o | 13 | snd-soc-evm-objs := davinci-evm.o |
14 | snd-soc-sffsdr-objs := davinci-sffsdr.o | ||
15 | 14 | ||
16 | obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o | 15 | obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o |
17 | obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o | 16 | obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o |
18 | obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o | 17 | obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o |
19 | obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o | 18 | obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o |
20 | obj-$(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 | |||
45 | static 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 | |||
78 | static struct snd_soc_ops sffsdr_ops = { | ||
79 | .hw_params = sffsdr_hw_params, | ||
80 | }; | ||
81 | |||
82 | /* davinci-sffsdr digital audio interface glue - connects codec <--> CPU */ | ||
83 | static 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 */ | ||
94 | static 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 */ | ||
102 | static 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 | |||
109 | struct platform_device pcm3008_codec = { | ||
110 | .name = "pcm3008-codec", | ||
111 | .id = 0, | ||
112 | .dev = { | ||
113 | .platform_data = &sffsdr_pcm3008_setup, | ||
114 | }, | ||
115 | }; | ||
116 | |||
117 | static 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 | |||
125 | static 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 | |||
130 | static struct platform_device *sffsdr_snd_device; | ||
131 | |||
132 | static 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 | |||
165 | error: | ||
166 | platform_device_put(sffsdr_snd_device); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static void __exit sffsdr_exit(void) | ||
171 | { | ||
172 | platform_device_unregister(sffsdr_snd_device); | ||
173 | platform_device_unregister(&pcm3008_codec); | ||
174 | } | ||
175 | |||
176 | module_init(sffsdr_init); | ||
177 | module_exit(sffsdr_exit); | ||
178 | |||
179 | MODULE_AUTHOR("Hugo Villeneuve"); | ||
180 | MODULE_DESCRIPTION("Lyrtech SFFSDR ASoC driver"); | ||
181 | MODULE_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 | |||
108 | config SND_SOC_IMX_SSI | 108 | config SND_SOC_IMX_SSI |
109 | tristate | 109 | tristate |
110 | 110 | ||
111 | config SND_SOC_IMX_PCM | ||
112 | tristate | ||
113 | |||
114 | config SND_SOC_IMX_PCM_FIQ | 111 | config SND_SOC_IMX_PCM_FIQ |
115 | bool | 112 | bool |
116 | select FIQ | 113 | select FIQ |
117 | select SND_SOC_IMX_PCM | ||
118 | 114 | ||
119 | config SND_SOC_IMX_PCM_DMA | 115 | config 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 | ||
124 | config SND_SOC_IMX_AUDMUX | 119 | config 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 | ||
171 | config 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 | |||
176 | config SND_SOC_IMX_SGTL5000 | 183 | config 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 |
31 | snd-soc-imx-ssi-objs := imx-ssi.o | 31 | snd-soc-imx-ssi-objs := imx-ssi.o |
32 | snd-soc-imx-audmux-objs := imx-audmux.o | 32 | snd-soc-imx-audmux-objs := imx-audmux.o |
33 | snd-soc-imx-pcm-objs := imx-pcm.o | ||
34 | ifneq ($(CONFIG_SND_SOC_IMX_PCM_FIQ),) | ||
35 | snd-soc-imx-pcm-objs += imx-pcm-fiq.o | ||
36 | endif | ||
37 | ifneq ($(CONFIG_SND_SOC_IMX_PCM_DMA),) | ||
38 | snd-soc-imx-pcm-objs += imx-pcm-dma.o | ||
39 | endif | ||
40 | |||
41 | obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o | 33 | obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o |
42 | obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o | 34 | obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o |
43 | 35 | ||
44 | obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o | 36 | obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o |
37 | obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o | ||
45 | 38 | ||
46 | # i.MX Machine Support | 39 | # i.MX Machine Support |
47 | snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o | 40 | snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o |
@@ -49,6 +42,7 @@ snd-soc-phycore-ac97-objs := phycore-ac97.o | |||
49 | snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o | 42 | snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o |
50 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o | 43 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o |
51 | snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o | 44 | snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o |
45 | snd-soc-imx-wm8962-objs := imx-wm8962.o | ||
52 | snd-soc-imx-mc13783-objs := imx-mc13783.o | 46 | snd-soc-imx-mc13783-objs := imx-mc13783.o |
53 | 47 | ||
54 | obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o | 48 | obj-$(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 | |||
56 | obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o | 50 | obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o |
57 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o | 51 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o |
58 | obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o | 52 | obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o |
53 | obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o | ||
59 | obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o | 54 | obj-$(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 | ||
855 | error_dai: | 850 | error_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 | ||
860 | error_dev: | 855 | error_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); | |||
247 | static int imx_audmux_probe(struct platform_device *pdev) | 246 | static 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 | } |
70 | EXPORT_SYMBOL_GPL(imx_pcm_dma_init); | ||
70 | 71 | ||
71 | void imx_pcm_dma_exit(struct platform_device *pdev) | 72 | void 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 | } |
76 | EXPORT_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 | ||
228 | static 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 | |||
228 | static struct snd_pcm_ops imx_pcm_ops = { | 244 | static 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 | ||
255 | static 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 | |||
273 | static u64 imx_pcm_dmamask = DMA_BIT_MASK(32); | ||
274 | |||
275 | static 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 | |||
299 | out: | ||
300 | return ret; | ||
301 | } | ||
302 | |||
239 | static int ssi_irq = 0; | 303 | static int ssi_irq = 0; |
240 | 304 | ||
241 | static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd) | 305 | static 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 | ||
335 | static 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 | |||
271 | static void imx_pcm_fiq_free(struct snd_pcm *pcm) | 356 | static 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 | } |
402 | EXPORT_SYMBOL_GPL(imx_pcm_fiq_init); | ||
403 | |||
404 | void imx_pcm_fiq_exit(struct platform_device *pdev) | ||
405 | { | ||
406 | snd_soc_unregister_platform(&pdev->dev); | ||
407 | } | ||
408 | EXPORT_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 | |||
19 | int 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 | } | ||
34 | EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap); | ||
35 | |||
36 | static 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 | |||
54 | static u64 imx_pcm_dmamask = DMA_BIT_MASK(32); | ||
55 | |||
56 | int 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 | |||
80 | out: | ||
81 | return ret; | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(imx_pcm_new); | ||
84 | |||
85 | void 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 | } | ||
105 | EXPORT_SYMBOL_GPL(imx_pcm_free); | ||
106 | |||
107 | static 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 | |||
115 | static 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 | |||
125 | static struct platform_device_id imx_pcm_devtype[] = { | ||
126 | { .name = "imx-pcm-audio", }, | ||
127 | { .name = "imx-fiq-pcm-audio", }, | ||
128 | { /* sentinel */ } | ||
129 | }; | ||
130 | MODULE_DEVICE_TABLE(platform, imx_pcm_devtype); | ||
131 | |||
132 | static 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 | }; | ||
141 | module_platform_driver(imx_pcm_driver); | ||
142 | |||
143 | MODULE_DESCRIPTION("Freescale i.MX PCM driver"); | ||
144 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
145 | MODULE_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 | ||
35 | int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, | ||
36 | struct vm_area_struct *vma); | ||
37 | int imx_pcm_new(struct snd_soc_pcm_runtime *rtd); | ||
38 | void imx_pcm_free(struct snd_pcm *pcm); | ||
39 | |||
40 | #ifdef CONFIG_SND_SOC_IMX_PCM_DMA | 35 | #ifdef CONFIG_SND_SOC_IMX_PCM_DMA |
41 | int imx_pcm_dma_init(struct platform_device *pdev); | 36 | int imx_pcm_dma_init(struct platform_device *pdev); |
42 | void imx_pcm_dma_exit(struct platform_device *pdev); | 37 | void 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 |
55 | int imx_pcm_fiq_init(struct platform_device *pdev); | 50 | int imx_pcm_fiq_init(struct platform_device *pdev); |
51 | void imx_pcm_fiq_exit(struct platform_device *pdev); | ||
56 | #else | 52 | #else |
57 | static inline int imx_pcm_fiq_init(struct platform_device *pdev) | 53 | static inline int imx_pcm_fiq_init(struct platform_device *pdev) |
58 | { | 54 | { |
59 | return -ENODEV; | 55 | return -ENODEV; |
60 | } | 56 | } |
57 | |||
58 | static 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); |
177 | clk_fail: | 167 | of_node_put(ssi_np); |
178 | clk_put(data->codec_clk); | 168 | of_node_put(codec_np); |
169 | |||
170 | return 0; | ||
171 | |||
179 | fail: | 172 | fail: |
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 | ||
621 | failed_pdev_add: | 603 | failed_pcm_dma: |
622 | platform_device_put(ssi->soc_platform_pdev); | 604 | imx_pcm_fiq_exit(pdev); |
623 | failed_pdev_alloc: | 605 | failed_pcm_fiq: |
624 | platform_device_del(ssi->soc_platform_pdev_fiq); | ||
625 | failed_pdev_fiq_add: | ||
626 | platform_device_put(ssi->soc_platform_pdev_fiq); | ||
627 | failed_pdev_fiq_alloc: | ||
628 | snd_soc_unregister_component(&pdev->dev); | 606 | snd_soc_unregister_component(&pdev->dev); |
629 | failed_register: | 607 | failed_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 | |||
31 | struct 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 | |||
40 | struct imx_priv { | ||
41 | struct platform_device *pdev; | ||
42 | }; | ||
43 | static struct imx_priv card_priv; | ||
44 | |||
45 | static 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 | |||
52 | static int sample_rate = 44100; | ||
53 | static snd_pcm_format_t sample_format = SNDRV_PCM_FORMAT_S16_LE; | ||
54 | |||
55 | static 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 | |||
64 | static struct snd_soc_ops imx_hifi_ops = { | ||
65 | .hw_params = imx_hifi_hw_params, | ||
66 | }; | ||
67 | |||
68 | static 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 | |||
138 | static 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 | |||
154 | static 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 | |||
280 | clk_fail: | ||
281 | if (!IS_ERR(data->codec_clk)) | ||
282 | clk_disable_unprepare(data->codec_clk); | ||
283 | fail: | ||
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 | |||
292 | static 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 | |||
303 | static const struct of_device_id imx_wm8962_dt_ids[] = { | ||
304 | { .compatible = "fsl,imx-audio-wm8962", }, | ||
305 | { /* sentinel */ } | ||
306 | }; | ||
307 | MODULE_DEVICE_TABLE(of, imx_wm8962_dt_ids); | ||
308 | |||
309 | static 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 | }; | ||
318 | module_platform_driver(imx_wm8962_driver); | ||
319 | |||
320 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
321 | MODULE_DESCRIPTION("Freescale i.MX WM8962 ASoC machine driver"); | ||
322 | MODULE_LICENSE("GPL v2"); | ||
323 | MODULE_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 | ||
146 | static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | 146 | static 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 | ||
292 | struct snd_pcm_ops kirkwood_dma_ops = { | 292 | static 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 | ||
52 | static 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 | |||
67 | static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = { | 52 | static 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 | } |
81 | EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); | 63 | EXPORT_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 | |||
24 | struct mxs_pcm_dma_params { | ||
25 | struct mxs_dma_data dma_data; | ||
26 | int chan_num; | ||
27 | }; | ||
28 | |||
29 | int mxs_pcm_platform_register(struct device *dev); | 22 | int mxs_pcm_platform_register(struct device *dev); |
30 | void mxs_pcm_platform_unregister(struct device *dev); | 23 | void 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) | |||
665 | static int mxs_saif_probe(struct platform_device *pdev) | 661 | static 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 | ||
148 | static int mxs_sgtl5000_probe(struct platform_device *pdev) | 142 | static 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 | |||
26 | obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o | 26 | obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o |
27 | obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o | 27 | obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o |
28 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o | 28 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o |
29 | obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o | ||
30 | obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o | 29 | obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o |
31 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o | 30 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o |
32 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o | 31 | obj-$(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 | ||
41 | static struct snd_soc_card snd_soc_omap_hdmi = { | 41 | static 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 | ||
133 | config 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 | |||
143 | config 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 | |||
153 | config SND_PXA910_SOC | 133 | config 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 | |||
23 | snd-soc-spitz-objs := spitz.o | 23 | snd-soc-spitz-objs := spitz.o |
24 | snd-soc-em-x270-objs := em-x270.o | 24 | snd-soc-em-x270-objs := em-x270.o |
25 | snd-soc-palm27x-objs := palm27x.o | 25 | snd-soc-palm27x-objs := palm27x.o |
26 | snd-soc-saarb-objs := saarb.o | ||
27 | snd-soc-tavorevb3-objs := tavorevb3.o | ||
28 | snd-soc-zylonite-objs := zylonite.o | 26 | snd-soc-zylonite-objs := zylonite.o |
29 | snd-soc-hx4700-objs := hx4700.o | 27 | snd-soc-hx4700-objs := hx4700.o |
30 | snd-soc-magician-objs := magician.o | 28 | snd-soc-magician-objs := magician.o |
@@ -48,8 +46,6 @@ obj-$(CONFIG_SND_PXA2XX_SOC_HX4700) += snd-soc-hx4700.o | |||
48 | obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o | 46 | obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o |
49 | obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o | 47 | obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o |
50 | obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o | 48 | obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o |
51 | obj-$(CONFIG_SND_SOC_SAARB) += snd-soc-saarb.o | ||
52 | obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o | ||
53 | obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o | 49 | obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o |
54 | obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o | 50 | obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o |
55 | obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o | 51 | obj-$(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 | ||
150 | struct snd_pcm_ops mmp_pcm_ops = { | 150 | static 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 | ||
211 | int mmp_pcm_new(struct snd_soc_pcm_runtime *rtd) | 211 | static 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 | ||
232 | struct snd_soc_platform_driver mmp_soc_platform = { | 232 | static 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 | ||
391 | struct snd_soc_dai_driver mmp_sspa_dai = { | 391 | static 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 | |||
28 | static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd); | ||
29 | |||
30 | static struct platform_device *saarb_snd_device; | ||
31 | |||
32 | static struct snd_soc_jack hs_jack, mic_jack; | ||
33 | |||
34 | static struct snd_soc_jack_pin hs_jack_pins[] = { | ||
35 | { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, }, | ||
36 | }; | ||
37 | |||
38 | static struct snd_soc_jack_pin mic_jack_pins[] = { | ||
39 | { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, }, | ||
40 | }; | ||
41 | |||
42 | /* saarb machine dapm widgets */ | ||
43 | static 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 */ | ||
54 | static 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 | |||
77 | static 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 | |||
100 | static struct snd_soc_ops saarb_i2s_ops = { | ||
101 | .hw_params = saarb_i2s_hw_params, | ||
102 | }; | ||
103 | |||
104 | static 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 | |||
119 | static 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 | |||
131 | static 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 | |||
161 | static 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 | |||
180 | static void __exit saarb_exit(void) | ||
181 | { | ||
182 | platform_device_unregister(saarb_snd_device); | ||
183 | } | ||
184 | |||
185 | module_init(saarb_init); | ||
186 | module_exit(saarb_exit); | ||
187 | |||
188 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | ||
189 | MODULE_DESCRIPTION("ALSA SoC 88PM860x Saarb"); | ||
190 | MODULE_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 | |||
28 | static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd); | ||
29 | |||
30 | static struct platform_device *evb3_snd_device; | ||
31 | |||
32 | static struct snd_soc_jack hs_jack, mic_jack; | ||
33 | |||
34 | static struct snd_soc_jack_pin hs_jack_pins[] = { | ||
35 | { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, }, | ||
36 | }; | ||
37 | |||
38 | static struct snd_soc_jack_pin mic_jack_pins[] = { | ||
39 | { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, }, | ||
40 | }; | ||
41 | |||
42 | /* tavorevb3 machine dapm widgets */ | ||
43 | static 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 */ | ||
54 | static 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 | |||
77 | static 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 | |||
99 | static struct snd_soc_ops evb3_i2s_ops = { | ||
100 | .hw_params = evb3_i2s_hw_params, | ||
101 | }; | ||
102 | |||
103 | static 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 | |||
118 | static 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 | |||
130 | static 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 | |||
160 | static 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 | |||
179 | static void __exit tavorevb3_exit(void) | ||
180 | { | ||
181 | platform_device_unregister(evb3_snd_device); | ||
182 | } | ||
183 | |||
184 | module_init(tavorevb3_init); | ||
185 | module_exit(tavorevb3_exit); | ||
186 | |||
187 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | ||
188 | MODULE_DESCRIPTION("ALSA SoC 88PM860x Tavor EVB3"); | ||
189 | MODULE_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 | ||
262 | static struct platform_device *zylonite_snd_ac97_device; | 261 | static 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 | ||
353 | static struct snd_soc_dapm_widget bells_widgets[] = { | ||
354 | SND_SOC_DAPM_MIC("DMIC", NULL), | ||
355 | }; | ||
356 | |||
353 | static struct snd_soc_dapm_route bells_routes[] = { | 357 | static 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 | ||
357 | static struct snd_soc_card bells_cards[] = { | 365 | static 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) | |||
176 | static int snd_smdk_remove(struct platform_device *pdev) | 176 | static 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) | |||
146 | static int snd_smdk_remove(struct platform_device *pdev) | 146 | static 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 | ||
1191 | static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | 1191 | static 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 | ||
1206 | static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io) | 1208 | static 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 | ||
1412 | static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | 1414 | static 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 | ||
1427 | static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev) | 1431 | static 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, | |||
2219 | EXPORT_SYMBOL_GPL(snd_soc_test_bits); | 2220 | EXPORT_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 | */ | ||
2228 | int 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 | } | ||
2242 | EXPORT_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 | ||
510 | static 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 | ||
2110 | static 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 */ |
2098 | static void dapm_free_widgets(struct snd_soc_dapm_context *dapm) | 2119 | static 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 | */ | ||
43 | int 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 | } | ||
57 | EXPORT_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. */ |
37 | static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, | 60 | static 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 | ||
150 | static 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 @@ | |||
1 | config SND_SPEAR_SOC | ||
2 | tristate | ||
3 | select SND_SOC_DMAENGINE_PCM | ||
4 | |||
5 | config SND_SPEAR_SPDIF_OUT | ||
6 | tristate | ||
7 | |||
8 | config 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 | ||
2 | snd-soc-spear-pcm-objs := spear_pcm.o | ||
3 | snd-soc-spear-spdif-in-objs := spdif_in.o | ||
4 | snd-soc-spear-spdif-out-objs := spdif_out.o | ||
5 | |||
6 | obj-$(CONFIG_SND_SPEAR_SOC) += snd-soc-spear-pcm.o | ||
7 | obj-$(CONFIG_SND_SPEAR_SPDIF_IN) += snd-soc-spear-spdif-in.o | ||
8 | obj-$(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 | ||
52 | static int spdif_in_startup(struct snd_pcm_substream *substream, | 52 | static 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 | ||
76 | static void spdif_in_format(struct spdif_in_dev *host, u32 format) | 72 | static 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 | ||
153 | static struct snd_soc_dai_ops spdif_in_dai_ops = { | 149 | static 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 | ||
160 | struct snd_soc_dai_driver spdif_in_dai = { | 155 | static 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 | ||
275 | static int spdif_in_remove(struct platform_device *pdev) | 264 | static 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 | |||
288 | static struct platform_driver spdif_in_driver = { | 271 | static 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 | ||
90 | static void spdif_out_clock(struct spdif_out_dev *host, u32 core_freq, | 87 | static 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 | ||
246 | int spdif_soc_dai_probe(struct snd_soc_dai *dai) | 243 | static 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 | ||
331 | static int spdif_out_remove(struct platform_device *pdev) | 315 | static 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 | ||
28 | static struct snd_pcm_hardware spear_pcm_hardware = { | 22 | static 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 | ||
40 | static int spear_pcm_hw_params(struct snd_pcm_substream *substream, | 34 | static 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 | |||
48 | static 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 | |||
55 | static 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 | ||
71 | static int spear_pcm_mmap(struct snd_pcm_substream *substream, | 44 | static 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 | |||
81 | static 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 | |||
92 | static int | ||
93 | spear_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 | |||
116 | static 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 | |||
137 | static u64 spear_pcm_dmamask = DMA_BIT_MASK(32); | ||
138 | |||
139 | static 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 | |||
168 | static 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 | ||
174 | static int spear_soc_platform_probe(struct platform_device *pdev) | 50 | static 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 | ||
179 | static int spear_soc_platform_remove(struct platform_device *pdev) | 58 | static 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 | ||
62 | config 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 | |||
62 | config SND_SOC_TEGRA_WM8753 | 72 | config 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 | |||
18 | obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o | 18 | obj-$(CONFIG_SND_SOC_TEGRA30_I2S) += snd-soc-tegra30-i2s.o |
19 | 19 | ||
20 | # Tegra machine Support | 20 | # Tegra machine Support |
21 | snd-soc-tegra-rt5640-objs := tegra_rt5640.o | ||
21 | snd-soc-tegra-wm8753-objs := tegra_wm8753.o | 22 | snd-soc-tegra-wm8753-objs := tegra_wm8753.o |
22 | snd-soc-tegra-wm8903-objs := tegra_wm8903.o | 23 | snd-soc-tegra-wm8903-objs := tegra_wm8903.o |
23 | snd-soc-tegra-wm9712-objs := tegra_wm9712.o | 24 | snd-soc-tegra-wm9712-objs := tegra_wm9712.o |
24 | snd-soc-tegra-trimslice-objs := trimslice.o | 25 | snd-soc-tegra-trimslice-objs := trimslice.o |
25 | snd-soc-tegra-alc5632-objs := tegra_alc5632.o | 26 | snd-soc-tegra-alc5632-objs := tegra_alc5632.o |
26 | 27 | ||
28 | obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o | ||
27 | obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o | 29 | obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o |
28 | obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o | 30 | obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o |
29 | obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o | 31 | obj-$(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 | ||
631 | static 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 | |||
639 | static 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 | |||
630 | static const struct dev_pm_ops tegra30_ahub_pm_ops = { | 654 | static 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 | ||
635 | static struct platform_driver tegra30_ahub_driver = { | 660 | static 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 | ||
518 | static 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 | |||
527 | static 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 | |||
517 | static const struct of_device_id tegra30_i2s_of_match[] = { | 542 | static 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[] = { | |||
522 | static const struct dev_pm_ops tegra30_i2s_pm_ops = { | 547 | static 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 | ||
527 | static struct platform_driver tegra30_i2s_driver = { | 553 | static 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 | |||
44 | struct tegra_rt5640 { | ||
45 | struct tegra_asoc_utils_data util_data; | ||
46 | int gpio_hp_det; | ||
47 | }; | ||
48 | |||
49 | static 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 | |||
79 | static struct snd_soc_ops tegra_rt5640_ops = { | ||
80 | .hw_params = tegra_rt5640_asoc_hw_params, | ||
81 | }; | ||
82 | |||
83 | static struct snd_soc_jack tegra_rt5640_hp_jack; | ||
84 | |||
85 | static struct snd_soc_jack_pin tegra_rt5640_hp_jack_pins[] = { | ||
86 | { | ||
87 | .pin = "Headphones", | ||
88 | .mask = SND_JACK_HEADPHONE, | ||
89 | }, | ||
90 | }; | ||
91 | |||
92 | static 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 | |||
99 | static 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 | |||
104 | static const struct snd_kcontrol_new tegra_rt5640_controls[] = { | ||
105 | SOC_DAPM_PIN_SWITCH("Speakers"), | ||
106 | }; | ||
107 | |||
108 | static 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 | |||
130 | static 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 | |||
140 | static 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 | |||
152 | static 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 | |||
215 | err_fini_utils: | ||
216 | tegra_asoc_utils_fini(&machine->util_data); | ||
217 | err: | ||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | static 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 | |||
236 | static const struct of_device_id tegra_rt5640_of_match[] = { | ||
237 | { .compatible = "nvidia,tegra-audio-rt5640", }, | ||
238 | {}, | ||
239 | }; | ||
240 | |||
241 | static 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 | }; | ||
251 | module_platform_driver(tegra_rt5640_driver); | ||
252 | |||
253 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
254 | MODULE_DESCRIPTION("Tegra+RT5640 machine ASoC driver"); | ||
255 | MODULE_LICENSE("GPL v2"); | ||
256 | MODULE_ALIAS("platform:" DRV_NAME); | ||
257 | MODULE_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 */ |
30 | struct snd_soc_dai_link mop500_dai_links[] = { | 30 | static 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 @@ | |||
43 | static unsigned int tx_slots = DEF_TX_SLOTS; | 45 | static unsigned int tx_slots = DEF_TX_SLOTS; |
44 | static unsigned int rx_slots = DEF_RX_SLOTS; | 46 | static unsigned int rx_slots = DEF_RX_SLOTS; |
45 | 47 | ||
48 | /* Configuration consistency parameters */ | ||
49 | static DEFINE_MUTEX(mop500_ab8500_params_lock); | ||
50 | static unsigned long mop500_ab8500_usage; | ||
51 | static int mop500_ab8500_rate; | ||
52 | static int mop500_ab8500_channels; | ||
53 | |||
46 | /* Clocks */ | 54 | /* Clocks */ |
47 | static const char * const enum_mclk[] = { | 55 | static const char * const enum_mclk[] = { |
48 | "SYSCLK", | 56 | "SYSCLK", |
@@ -125,9 +133,9 @@ static int mop500_ab8500_set_mclk(struct device *dev, | |||
125 | static int mclk_input_control_get(struct snd_kcontrol *kcontrol, | 133 | static 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, | |||
137 | static int mclk_input_control_put(struct snd_kcontrol *kcontrol, | 145 | static 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 | ||
196 | int mop500_ab8500_startup(struct snd_pcm_substream *substream) | 194 | static 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 | ||
205 | void mop500_ab8500_shutdown(struct snd_pcm_substream *substream) | 203 | static 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 | ||
219 | int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, | 217 | static 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 | ||
354 | static 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 | |||
341 | struct snd_soc_ops mop500_ab8500_ops[] = { | 366 | struct 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 { | |||
51 | struct ux500_msp_i2s_drvdata { | 51 | struct 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 */ | ||
30 | static DEFINE_SPINLOCK(msp_rxtx_lock); | ||
31 | |||
32 | /* Protocol desciptors */ | 28 | /* Protocol desciptors */ |
33 | static const struct msp_protdesc prot_descs[] = { | 29 | static const struct msp_protdesc prot_descs[] = { |
34 | { /* I2S */ | 30 | { /* I2S */ |
@@ -356,24 +352,8 @@ static int configure_multichannel(struct ux500_msp *msp, | |||
356 | 352 | ||
357 | static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config) | 353 | static 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 | ||
631 | int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir) | 613 | int 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 | ||
776 | MODULE_LICENSE("GPL v2"); | 710 | MODULE_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 | ||
344 | enum msp_spi_burst_mode { | ||
345 | MSP_SPI_BURST_MODE_DISABLE = 0, | ||
346 | MSP_SPI_BURST_MODE_ENABLE = 1 | ||
347 | }; | ||
348 | |||
349 | enum msp_expand_mode { | 345 | enum 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 | ||
373 | enum 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 | |||
380 | enum i2s_direction_t { | 369 | enum 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 | ||
457 | struct 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 | |||
472 | struct 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 | |||
483 | struct ux500_msp_config { | 446 | struct 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; | 471 | struct 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 | ||
514 | struct ux500_msp { | 477 | struct 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 | |||
539 | struct ux500_msp_dma_params { | ||
540 | unsigned int data_size; | ||
541 | struct stedma40_chan_cfg *dma_cfg; | ||
542 | }; | 488 | }; |
543 | 489 | ||
544 | struct msp_i2s_platform_data; | 490 | struct 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 | ||
106 | static 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 | |||
106 | static const struct snd_dmaengine_pcm_config ux500_dmaengine_pcm_config = { | 135 | static 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 | ||
112 | int ux500_pcm_register_platform(struct platform_device *pdev) | 142 | int ux500_pcm_register_platform(struct platform_device *pdev) |