diff options
Diffstat (limited to 'sound/soc')
95 files changed, 2712 insertions, 4462 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 0e9623368ab0..7d5d6444a837 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -49,7 +49,6 @@ source "sound/soc/mxs/Kconfig" | |||
49 | source "sound/soc/pxa/Kconfig" | 49 | source "sound/soc/pxa/Kconfig" |
50 | source "sound/soc/rockchip/Kconfig" | 50 | source "sound/soc/rockchip/Kconfig" |
51 | source "sound/soc/samsung/Kconfig" | 51 | source "sound/soc/samsung/Kconfig" |
52 | source "sound/soc/s6000/Kconfig" | ||
53 | source "sound/soc/sh/Kconfig" | 52 | source "sound/soc/sh/Kconfig" |
54 | source "sound/soc/sirf/Kconfig" | 53 | source "sound/soc/sirf/Kconfig" |
55 | source "sound/soc/spear/Kconfig" | 54 | source "sound/soc/spear/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 534714a1ca44..865e090c8061 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -1,10 +1,14 @@ | |||
1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o | 1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o |
2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o | 2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o soc-ops.o |
3 | 3 | ||
4 | ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) | 4 | ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) |
5 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o | 5 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o |
6 | endif | 6 | endif |
7 | 7 | ||
8 | ifneq ($(CONFIG_SND_SOC_AC97_BUS),) | ||
9 | snd-soc-core-objs += soc-ac97.o | ||
10 | endif | ||
11 | |||
8 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o | 12 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o |
9 | obj-$(CONFIG_SND_SOC) += codecs/ | 13 | obj-$(CONFIG_SND_SOC) += codecs/ |
10 | obj-$(CONFIG_SND_SOC) += generic/ | 14 | obj-$(CONFIG_SND_SOC) += generic/ |
@@ -26,7 +30,6 @@ obj-$(CONFIG_SND_SOC) += kirkwood/ | |||
26 | obj-$(CONFIG_SND_SOC) += pxa/ | 30 | obj-$(CONFIG_SND_SOC) += pxa/ |
27 | obj-$(CONFIG_SND_SOC) += rockchip/ | 31 | obj-$(CONFIG_SND_SOC) += rockchip/ |
28 | obj-$(CONFIG_SND_SOC) += samsung/ | 32 | obj-$(CONFIG_SND_SOC) += samsung/ |
29 | obj-$(CONFIG_SND_SOC) += s6000/ | ||
30 | obj-$(CONFIG_SND_SOC) += sh/ | 33 | obj-$(CONFIG_SND_SOC) += sh/ |
31 | obj-$(CONFIG_SND_SOC) += sirf/ | 34 | obj-$(CONFIG_SND_SOC) += sirf/ |
32 | obj-$(CONFIG_SND_SOC) += spear/ | 35 | obj-$(CONFIG_SND_SOC) += spear/ |
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index 27e3fc4a536b..fb3878312bf8 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig | |||
@@ -52,12 +52,3 @@ config SND_AT91_SOC_SAM9X5_WM8731 | |||
52 | help | 52 | help |
53 | Say Y if you want to add support for audio SoC on an | 53 | Say Y if you want to add support for audio SoC on an |
54 | at91sam9x5 based board that is using WM8731 codec. | 54 | at91sam9x5 based board that is using WM8731 codec. |
55 | |||
56 | config SND_AT91_SOC_AFEB9260 | ||
57 | tristate "SoC Audio support for AFEB9260 board" | ||
58 | depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC | ||
59 | select SND_ATMEL_SOC_PDC | ||
60 | select SND_ATMEL_SOC_SSC | ||
61 | select SND_SOC_TLV320AIC23_I2C | ||
62 | help | ||
63 | Say Y here to support sound on AFEB9260 board. | ||
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile index 5baabc8bde3a..466a821da98c 100644 --- a/sound/soc/atmel/Makefile +++ b/sound/soc/atmel/Makefile | |||
@@ -17,4 +17,3 @@ snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o | |||
17 | obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o | 17 | obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o |
18 | obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o | 18 | obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o |
19 | obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o | 19 | obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o |
20 | obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o | ||
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index f403f399808a..b1cc2a4a7fc0 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -310,7 +310,10 @@ static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, | |||
310 | * transmit and receive, so if a value has already | 310 | * transmit and receive, so if a value has already |
311 | * been set, it must match this value. | 311 | * been set, it must match this value. |
312 | */ | 312 | */ |
313 | if (ssc_p->cmr_div == 0) | 313 | if (ssc_p->dir_mask != |
314 | (SSC_DIR_MASK_PLAYBACK | SSC_DIR_MASK_CAPTURE)) | ||
315 | ssc_p->cmr_div = div; | ||
316 | else if (ssc_p->cmr_div == 0) | ||
314 | ssc_p->cmr_div = div; | 317 | ssc_p->cmr_div = div; |
315 | else | 318 | else |
316 | if (div != ssc_p->cmr_div) | 319 | if (div != ssc_p->cmr_div) |
diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c deleted file mode 100644 index 9579799ace54..000000000000 --- a/sound/soc/atmel/snd-soc-afeb9260.c +++ /dev/null | |||
@@ -1,151 +0,0 @@ | |||
1 | /* | ||
2 | * afeb9260.c -- SoC audio for AFEB9260 | ||
3 | * | ||
4 | * Copyright (C) 2009 Sergey Lapin <slapin@ossfans.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms 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 that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/clk.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | |||
28 | #include <linux/atmel-ssc.h> | ||
29 | #include <sound/core.h> | ||
30 | #include <sound/pcm.h> | ||
31 | #include <sound/pcm_params.h> | ||
32 | #include <sound/soc.h> | ||
33 | |||
34 | #include <asm/mach-types.h> | ||
35 | #include <mach/hardware.h> | ||
36 | #include <linux/gpio.h> | ||
37 | |||
38 | #include "../codecs/tlv320aic23.h" | ||
39 | #include "atmel-pcm.h" | ||
40 | #include "atmel_ssc_dai.h" | ||
41 | |||
42 | #define CODEC_CLOCK 12000000 | ||
43 | |||
44 | static int afeb9260_hw_params(struct snd_pcm_substream *substream, | ||
45 | struct snd_pcm_hw_params *params) | ||
46 | { | ||
47 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
48 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
49 | int err; | ||
50 | |||
51 | /* Set the codec system clock for DAC and ADC */ | ||
52 | err = | ||
53 | snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN); | ||
54 | |||
55 | if (err < 0) { | ||
56 | printk(KERN_ERR "can't set codec system clock\n"); | ||
57 | return err; | ||
58 | } | ||
59 | |||
60 | return err; | ||
61 | } | ||
62 | |||
63 | static struct snd_soc_ops afeb9260_ops = { | ||
64 | .hw_params = afeb9260_hw_params, | ||
65 | }; | ||
66 | |||
67 | static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { | ||
68 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
69 | SND_SOC_DAPM_LINE("Line In", NULL), | ||
70 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
71 | }; | ||
72 | |||
73 | static const struct snd_soc_dapm_route afeb9260_audio_map[] = { | ||
74 | {"Headphone Jack", NULL, "LHPOUT"}, | ||
75 | {"Headphone Jack", NULL, "RHPOUT"}, | ||
76 | |||
77 | {"LLINEIN", NULL, "Line In"}, | ||
78 | {"RLINEIN", NULL, "Line In"}, | ||
79 | |||
80 | {"MICIN", NULL, "Mic Jack"}, | ||
81 | }; | ||
82 | |||
83 | |||
84 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
85 | static struct snd_soc_dai_link afeb9260_dai = { | ||
86 | .name = "TLV320AIC23", | ||
87 | .stream_name = "AIC23", | ||
88 | .cpu_dai_name = "atmel-ssc-dai.0", | ||
89 | .codec_dai_name = "tlv320aic23-hifi", | ||
90 | .platform_name = "atmel_pcm-audio", | ||
91 | .codec_name = "tlv320aic23-codec.0-001a", | ||
92 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | | ||
93 | SND_SOC_DAIFMT_CBM_CFM, | ||
94 | .ops = &afeb9260_ops, | ||
95 | }; | ||
96 | |||
97 | /* Audio machine driver */ | ||
98 | static struct snd_soc_card snd_soc_machine_afeb9260 = { | ||
99 | .name = "AFEB9260", | ||
100 | .owner = THIS_MODULE, | ||
101 | .dai_link = &afeb9260_dai, | ||
102 | .num_links = 1, | ||
103 | |||
104 | .dapm_widgets = tlv320aic23_dapm_widgets, | ||
105 | .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), | ||
106 | .dapm_routes = afeb9260_audio_map, | ||
107 | .num_dapm_routes = ARRAY_SIZE(afeb9260_audio_map), | ||
108 | }; | ||
109 | |||
110 | static struct platform_device *afeb9260_snd_device; | ||
111 | |||
112 | static int __init afeb9260_soc_init(void) | ||
113 | { | ||
114 | int err; | ||
115 | struct device *dev; | ||
116 | |||
117 | if (!(machine_is_afeb9260())) | ||
118 | return -ENODEV; | ||
119 | |||
120 | |||
121 | afeb9260_snd_device = platform_device_alloc("soc-audio", -1); | ||
122 | if (!afeb9260_snd_device) { | ||
123 | printk(KERN_ERR "ASoC: Platform device allocation failed\n"); | ||
124 | return -ENOMEM; | ||
125 | } | ||
126 | |||
127 | platform_set_drvdata(afeb9260_snd_device, &snd_soc_machine_afeb9260); | ||
128 | err = platform_device_add(afeb9260_snd_device); | ||
129 | if (err) | ||
130 | goto err1; | ||
131 | |||
132 | dev = &afeb9260_snd_device->dev; | ||
133 | |||
134 | return 0; | ||
135 | err1: | ||
136 | platform_device_put(afeb9260_snd_device); | ||
137 | return err; | ||
138 | } | ||
139 | |||
140 | static void __exit afeb9260_soc_exit(void) | ||
141 | { | ||
142 | platform_device_unregister(afeb9260_snd_device); | ||
143 | } | ||
144 | |||
145 | module_init(afeb9260_soc_init); | ||
146 | module_exit(afeb9260_soc_exit); | ||
147 | |||
148 | MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>"); | ||
149 | MODULE_DESCRIPTION("ALSA SoC for AFEB9260"); | ||
150 | MODULE_LICENSE("GPL"); | ||
151 | |||
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c index c8a2de103c5f..5159a50a45a6 100644 --- a/sound/soc/au1x/ac97c.c +++ b/sound/soc/au1x/ac97c.c | |||
@@ -205,7 +205,7 @@ static int au1xac97c_dai_probe(struct snd_soc_dai *dai) | |||
205 | 205 | ||
206 | static struct snd_soc_dai_driver au1xac97c_dai_driver = { | 206 | static struct snd_soc_dai_driver au1xac97c_dai_driver = { |
207 | .name = "alchemy-ac97c", | 207 | .name = "alchemy-ac97c", |
208 | .ac97_control = 1, | 208 | .bus_control = true, |
209 | .probe = au1xac97c_dai_probe, | 209 | .probe = au1xac97c_dai_probe, |
210 | .playback = { | 210 | .playback = { |
211 | .rates = AC97_RATES, | 211 | .rates = AC97_RATES, |
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index 84f31e1f9d24..c6daec98ff89 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c | |||
@@ -343,7 +343,7 @@ static const struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { | |||
343 | }; | 343 | }; |
344 | 344 | ||
345 | static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = { | 345 | static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = { |
346 | .ac97_control = 1, | 346 | .bus_control = true, |
347 | .probe = au1xpsc_ac97_probe, | 347 | .probe = au1xpsc_ac97_probe, |
348 | .playback = { | 348 | .playback = { |
349 | .rates = AC97_RATES, | 349 | .rates = AC97_RATES, |
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index e82eb373a731..6bf21a6c02e4 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c | |||
@@ -260,7 +260,7 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai) | |||
260 | #endif | 260 | #endif |
261 | 261 | ||
262 | static struct snd_soc_dai_driver bfin_ac97_dai = { | 262 | static struct snd_soc_dai_driver bfin_ac97_dai = { |
263 | .ac97_control = 1, | 263 | .bus_control = true, |
264 | .suspend = bf5xx_ac97_suspend, | 264 | .suspend = bf5xx_ac97_suspend, |
265 | .resume = bf5xx_ac97_resume, | 265 | .resume = bf5xx_ac97_resume, |
266 | .playback = { | 266 | .playback = { |
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c index 3450e8f9080d..0fa81a523b8a 100644 --- a/sound/soc/blackfin/bf5xx-ad1980.c +++ b/sound/soc/blackfin/bf5xx-ad1980.c | |||
@@ -46,8 +46,6 @@ | |||
46 | #include <linux/gpio.h> | 46 | #include <linux/gpio.h> |
47 | #include <asm/portmux.h> | 47 | #include <asm/portmux.h> |
48 | 48 | ||
49 | #include "../codecs/ad1980.h" | ||
50 | |||
51 | #include "bf5xx-ac97.h" | 49 | #include "bf5xx-ac97.h" |
52 | 50 | ||
53 | static struct snd_soc_card bf5xx_board; | 51 | static struct snd_soc_card bf5xx_board; |
diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 5477c5475923..7b7fbcd49e5e 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig | |||
@@ -36,7 +36,8 @@ config SND_EP93XX_SOC_EDB93XX | |||
36 | tristate "SoC Audio support for Cirrus Logic EDB93xx boards" | 36 | tristate "SoC Audio support for Cirrus Logic EDB93xx boards" |
37 | depends on SND_EP93XX_SOC && (MACH_EDB9301 || MACH_EDB9302 || MACH_EDB9302A || MACH_EDB9307A || MACH_EDB9315A) | 37 | depends on SND_EP93XX_SOC && (MACH_EDB9301 || MACH_EDB9302 || MACH_EDB9302A || MACH_EDB9307A || MACH_EDB9315A) |
38 | select SND_EP93XX_SOC_I2S | 38 | select SND_EP93XX_SOC_I2S |
39 | select SND_SOC_CS4271 | 39 | select SND_SOC_CS4271_I2C if I2C |
40 | select SND_SOC_CS4271_SPI if SPI_MASTER | ||
40 | help | 41 | help |
41 | Say Y or M here if you want to add support for I2S audio on the | 42 | Say Y or M here if you want to add support for I2S audio on the |
42 | Cirrus Logic EDB93xx boards. | 43 | Cirrus Logic EDB93xx boards. |
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index f30dadf85b99..6b8a366b0211 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
@@ -338,7 +338,7 @@ static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = { | |||
338 | static struct snd_soc_dai_driver ep93xx_ac97_dai = { | 338 | static struct snd_soc_dai_driver ep93xx_ac97_dai = { |
339 | .name = "ep93xx-ac97", | 339 | .name = "ep93xx-ac97", |
340 | .id = 0, | 340 | .id = 0, |
341 | .ac97_control = 1, | 341 | .bus_control = true, |
342 | .probe = ep93xx_ac97_dai_probe, | 342 | .probe = ep93xx_ac97_dai_probe, |
343 | .playback = { | 343 | .playback = { |
344 | .stream_name = "AC97 Playback", | 344 | .stream_name = "AC97 Playback", |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index a68d1731a8fd..1362edd380e5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -50,7 +50,8 @@ config SND_SOC_ALL_CODECS | |||
50 | select SND_SOC_CS42L73 if I2C | 50 | select SND_SOC_CS42L73 if I2C |
51 | select SND_SOC_CS4265 if I2C | 51 | select SND_SOC_CS4265 if I2C |
52 | select SND_SOC_CS4270 if I2C | 52 | select SND_SOC_CS4270 if I2C |
53 | select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI | 53 | select SND_SOC_CS4271_I2C if I2C |
54 | select SND_SOC_CS4271_SPI if SPI_MASTER | ||
54 | select SND_SOC_CS42XX8_I2C if I2C | 55 | select SND_SOC_CS42XX8_I2C if I2C |
55 | select SND_SOC_CX20442 if TTY | 56 | select SND_SOC_CX20442 if TTY |
56 | select SND_SOC_DA7210 if I2C | 57 | select SND_SOC_DA7210 if I2C |
@@ -223,6 +224,7 @@ config SND_SOC_AD193X_I2C | |||
223 | select SND_SOC_AD193X | 224 | select SND_SOC_AD193X |
224 | 225 | ||
225 | config SND_SOC_AD1980 | 226 | config SND_SOC_AD1980 |
227 | select REGMAP_AC97 | ||
226 | tristate | 228 | tristate |
227 | 229 | ||
228 | config SND_SOC_AD73311 | 230 | config SND_SOC_AD73311 |
@@ -336,7 +338,8 @@ config SND_SOC_CS42L51 | |||
336 | tristate | 338 | tristate |
337 | 339 | ||
338 | config SND_SOC_CS42L51_I2C | 340 | config SND_SOC_CS42L51_I2C |
339 | tristate | 341 | tristate "Cirrus Logic CS42L51 CODEC (I2C)" |
342 | depends on I2C | ||
340 | select SND_SOC_CS42L51 | 343 | select SND_SOC_CS42L51 |
341 | 344 | ||
342 | config SND_SOC_CS42L52 | 345 | config SND_SOC_CS42L52 |
@@ -370,8 +373,19 @@ config SND_SOC_CS4270_VD33_ERRATA | |||
370 | depends on SND_SOC_CS4270 | 373 | depends on SND_SOC_CS4270 |
371 | 374 | ||
372 | config SND_SOC_CS4271 | 375 | config SND_SOC_CS4271 |
373 | tristate "Cirrus Logic CS4271 CODEC" | 376 | tristate |
374 | depends on SND_SOC_I2C_AND_SPI | 377 | |
378 | config SND_SOC_CS4271_I2C | ||
379 | tristate "Cirrus Logic CS4271 CODEC (I2C)" | ||
380 | depends on I2C | ||
381 | select SND_SOC_CS4271 | ||
382 | select REGMAP_I2C | ||
383 | |||
384 | config SND_SOC_CS4271_SPI | ||
385 | tristate "Cirrus Logic CS4271 CODEC (SPI)" | ||
386 | depends on SPI_MASTER | ||
387 | select SND_SOC_CS4271 | ||
388 | select REGMAP_SPI | ||
375 | 389 | ||
376 | config SND_SOC_CS42XX8 | 390 | config SND_SOC_CS42XX8 |
377 | tristate | 391 | tristate |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 5dce451661e4..ac7ec31f8cbe 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -41,6 +41,8 @@ snd-soc-cs42l73-objs := cs42l73.o | |||
41 | snd-soc-cs4265-objs := cs4265.o | 41 | snd-soc-cs4265-objs := cs4265.o |
42 | snd-soc-cs4270-objs := cs4270.o | 42 | snd-soc-cs4270-objs := cs4270.o |
43 | snd-soc-cs4271-objs := cs4271.o | 43 | snd-soc-cs4271-objs := cs4271.o |
44 | snd-soc-cs4271-i2c-objs := cs4271-i2c.o | ||
45 | snd-soc-cs4271-spi-objs := cs4271-spi.o | ||
44 | snd-soc-cs42xx8-objs := cs42xx8.o | 46 | snd-soc-cs42xx8-objs := cs42xx8.o |
45 | snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o | 47 | snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o |
46 | snd-soc-cx20442-objs := cx20442.o | 48 | snd-soc-cx20442-objs := cx20442.o |
@@ -217,6 +219,8 @@ obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o | |||
217 | obj-$(CONFIG_SND_SOC_CS4265) += snd-soc-cs4265.o | 219 | obj-$(CONFIG_SND_SOC_CS4265) += snd-soc-cs4265.o |
218 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | 220 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o |
219 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o | 221 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o |
222 | obj-$(CONFIG_SND_SOC_CS4271_I2C) += snd-soc-cs4271-i2c.o | ||
223 | obj-$(CONFIG_SND_SOC_CS4271_SPI) += snd-soc-cs4271-spi.o | ||
220 | obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o | 224 | obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o |
221 | obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o | 225 | obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o |
222 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 226 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index fd43827bb856..7dfbc9921e91 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c | |||
@@ -126,13 +126,13 @@ struct ab8500_codec_drvdata_dbg { | |||
126 | /* Private data for AB8500 device-driver */ | 126 | /* Private data for AB8500 device-driver */ |
127 | struct ab8500_codec_drvdata { | 127 | struct ab8500_codec_drvdata { |
128 | struct regmap *regmap; | 128 | struct regmap *regmap; |
129 | struct mutex ctrl_lock; | ||
129 | 130 | ||
130 | /* Sidetone */ | 131 | /* Sidetone */ |
131 | long *sid_fir_values; | 132 | long *sid_fir_values; |
132 | enum sid_state sid_status; | 133 | enum sid_state sid_status; |
133 | 134 | ||
134 | /* ANC */ | 135 | /* ANC */ |
135 | struct mutex anc_lock; | ||
136 | long *anc_fir_values; | 136 | long *anc_fir_values; |
137 | long *anc_iir_values; | 137 | long *anc_iir_values; |
138 | enum anc_state anc_status; | 138 | enum anc_state anc_status; |
@@ -1129,9 +1129,9 @@ static int sid_status_control_get(struct snd_kcontrol *kcontrol, | |||
1129 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 1129 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
1130 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | 1130 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); |
1131 | 1131 | ||
1132 | mutex_lock(&codec->mutex); | 1132 | mutex_lock(&drvdata->ctrl_lock); |
1133 | ucontrol->value.integer.value[0] = drvdata->sid_status; | 1133 | ucontrol->value.integer.value[0] = drvdata->sid_status; |
1134 | mutex_unlock(&codec->mutex); | 1134 | mutex_unlock(&drvdata->ctrl_lock); |
1135 | 1135 | ||
1136 | return 0; | 1136 | return 0; |
1137 | } | 1137 | } |
@@ -1154,7 +1154,7 @@ static int sid_status_control_put(struct snd_kcontrol *kcontrol, | |||
1154 | return -EIO; | 1154 | return -EIO; |
1155 | } | 1155 | } |
1156 | 1156 | ||
1157 | mutex_lock(&codec->mutex); | 1157 | mutex_lock(&drvdata->ctrl_lock); |
1158 | 1158 | ||
1159 | sidconf = snd_soc_read(codec, AB8500_SIDFIRCONF); | 1159 | sidconf = snd_soc_read(codec, AB8500_SIDFIRCONF); |
1160 | if (((sidconf & BIT(AB8500_SIDFIRCONF_FIRSIDBUSY)) != 0)) { | 1160 | if (((sidconf & BIT(AB8500_SIDFIRCONF_FIRSIDBUSY)) != 0)) { |
@@ -1185,7 +1185,7 @@ static int sid_status_control_put(struct snd_kcontrol *kcontrol, | |||
1185 | drvdata->sid_status = SID_FIR_CONFIGURED; | 1185 | drvdata->sid_status = SID_FIR_CONFIGURED; |
1186 | 1186 | ||
1187 | out: | 1187 | out: |
1188 | mutex_unlock(&codec->mutex); | 1188 | mutex_unlock(&drvdata->ctrl_lock); |
1189 | 1189 | ||
1190 | dev_dbg(codec->dev, "%s: Exit\n", __func__); | 1190 | dev_dbg(codec->dev, "%s: Exit\n", __func__); |
1191 | 1191 | ||
@@ -1198,9 +1198,9 @@ static int anc_status_control_get(struct snd_kcontrol *kcontrol, | |||
1198 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 1198 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
1199 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); | 1199 | struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev); |
1200 | 1200 | ||
1201 | mutex_lock(&codec->mutex); | 1201 | mutex_lock(&drvdata->ctrl_lock); |
1202 | ucontrol->value.integer.value[0] = drvdata->anc_status; | 1202 | ucontrol->value.integer.value[0] = drvdata->anc_status; |
1203 | mutex_unlock(&codec->mutex); | 1203 | mutex_unlock(&drvdata->ctrl_lock); |
1204 | 1204 | ||
1205 | return 0; | 1205 | return 0; |
1206 | } | 1206 | } |
@@ -1217,7 +1217,7 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol, | |||
1217 | 1217 | ||
1218 | dev_dbg(dev, "%s: Enter.\n", __func__); | 1218 | dev_dbg(dev, "%s: Enter.\n", __func__); |
1219 | 1219 | ||
1220 | mutex_lock(&drvdata->anc_lock); | 1220 | mutex_lock(&drvdata->ctrl_lock); |
1221 | 1221 | ||
1222 | req = ucontrol->value.integer.value[0]; | 1222 | req = ucontrol->value.integer.value[0]; |
1223 | if (req >= ARRAY_SIZE(enum_anc_state)) { | 1223 | if (req >= ARRAY_SIZE(enum_anc_state)) { |
@@ -1244,9 +1244,7 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol, | |||
1244 | } | 1244 | } |
1245 | snd_soc_dapm_sync(&codec->dapm); | 1245 | snd_soc_dapm_sync(&codec->dapm); |
1246 | 1246 | ||
1247 | mutex_lock(&codec->mutex); | ||
1248 | anc_configure(codec, apply_fir, apply_iir); | 1247 | anc_configure(codec, apply_fir, apply_iir); |
1249 | mutex_unlock(&codec->mutex); | ||
1250 | 1248 | ||
1251 | if (apply_fir) { | 1249 | if (apply_fir) { |
1252 | if (drvdata->anc_status == ANC_IIR_CONFIGURED) | 1250 | if (drvdata->anc_status == ANC_IIR_CONFIGURED) |
@@ -1265,7 +1263,7 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol, | |||
1265 | snd_soc_dapm_sync(&codec->dapm); | 1263 | snd_soc_dapm_sync(&codec->dapm); |
1266 | 1264 | ||
1267 | cleanup: | 1265 | cleanup: |
1268 | mutex_unlock(&drvdata->anc_lock); | 1266 | mutex_unlock(&drvdata->ctrl_lock); |
1269 | 1267 | ||
1270 | if (status < 0) | 1268 | if (status < 0) |
1271 | dev_err(dev, "%s: Unable to configure ANC! (status = %d)\n", | 1269 | dev_err(dev, "%s: Unable to configure ANC! (status = %d)\n", |
@@ -1294,14 +1292,15 @@ static int filter_control_get(struct snd_kcontrol *kcontrol, | |||
1294 | struct snd_ctl_elem_value *ucontrol) | 1292 | struct snd_ctl_elem_value *ucontrol) |
1295 | { | 1293 | { |
1296 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 1294 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
1295 | struct ab8500_codec_drvdata *drvdata = snd_soc_codec_get_drvdata(codec); | ||
1297 | struct filter_control *fc = | 1296 | struct filter_control *fc = |
1298 | (struct filter_control *)kcontrol->private_value; | 1297 | (struct filter_control *)kcontrol->private_value; |
1299 | unsigned int i; | 1298 | unsigned int i; |
1300 | 1299 | ||
1301 | mutex_lock(&codec->mutex); | 1300 | mutex_lock(&drvdata->ctrl_lock); |
1302 | for (i = 0; i < fc->count; i++) | 1301 | for (i = 0; i < fc->count; i++) |
1303 | ucontrol->value.integer.value[i] = fc->value[i]; | 1302 | ucontrol->value.integer.value[i] = fc->value[i]; |
1304 | mutex_unlock(&codec->mutex); | 1303 | mutex_unlock(&drvdata->ctrl_lock); |
1305 | 1304 | ||
1306 | return 0; | 1305 | return 0; |
1307 | } | 1306 | } |
@@ -1310,14 +1309,15 @@ static int filter_control_put(struct snd_kcontrol *kcontrol, | |||
1310 | struct snd_ctl_elem_value *ucontrol) | 1309 | struct snd_ctl_elem_value *ucontrol) |
1311 | { | 1310 | { |
1312 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 1311 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
1312 | struct ab8500_codec_drvdata *drvdata = snd_soc_codec_get_drvdata(codec); | ||
1313 | struct filter_control *fc = | 1313 | struct filter_control *fc = |
1314 | (struct filter_control *)kcontrol->private_value; | 1314 | (struct filter_control *)kcontrol->private_value; |
1315 | unsigned int i; | 1315 | unsigned int i; |
1316 | 1316 | ||
1317 | mutex_lock(&codec->mutex); | 1317 | mutex_lock(&drvdata->ctrl_lock); |
1318 | for (i = 0; i < fc->count; i++) | 1318 | for (i = 0; i < fc->count; i++) |
1319 | fc->value[i] = ucontrol->value.integer.value[i]; | 1319 | fc->value[i] = ucontrol->value.integer.value[i]; |
1320 | mutex_unlock(&codec->mutex); | 1320 | mutex_unlock(&drvdata->ctrl_lock); |
1321 | 1321 | ||
1322 | return 0; | 1322 | return 0; |
1323 | } | 1323 | } |
@@ -2545,7 +2545,7 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) | |||
2545 | 2545 | ||
2546 | (void)snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input"); | 2546 | (void)snd_soc_dapm_disable_pin(&codec->dapm, "ANC Configure Input"); |
2547 | 2547 | ||
2548 | mutex_init(&drvdata->anc_lock); | 2548 | mutex_init(&drvdata->ctrl_lock); |
2549 | 2549 | ||
2550 | return status; | 2550 | return status; |
2551 | } | 2551 | } |
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index bd9b1839c8b0..c6e5a313ebf4 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -37,10 +37,11 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
37 | struct snd_soc_dai *dai) | 37 | struct snd_soc_dai *dai) |
38 | { | 38 | { |
39 | struct snd_soc_codec *codec = dai->codec; | 39 | struct snd_soc_codec *codec = dai->codec; |
40 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
40 | 41 | ||
41 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | 42 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
42 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; | 43 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; |
43 | return snd_ac97_set_rate(codec->ac97, reg, substream->runtime->rate); | 44 | return snd_ac97_set_rate(ac97, reg, substream->runtime->rate); |
44 | } | 45 | } |
45 | 46 | ||
46 | #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | 47 | #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ |
@@ -53,7 +54,6 @@ static const struct snd_soc_dai_ops ac97_dai_ops = { | |||
53 | 54 | ||
54 | static struct snd_soc_dai_driver ac97_dai = { | 55 | static struct snd_soc_dai_driver ac97_dai = { |
55 | .name = "ac97-hifi", | 56 | .name = "ac97-hifi", |
56 | .ac97_control = 1, | ||
57 | .playback = { | 57 | .playback = { |
58 | .stream_name = "AC97 Playback", | 58 | .stream_name = "AC97 Playback", |
59 | .channels_min = 1, | 59 | .channels_min = 1, |
@@ -71,6 +71,7 @@ static struct snd_soc_dai_driver ac97_dai = { | |||
71 | 71 | ||
72 | static int ac97_soc_probe(struct snd_soc_codec *codec) | 72 | static int ac97_soc_probe(struct snd_soc_codec *codec) |
73 | { | 73 | { |
74 | struct snd_ac97 *ac97; | ||
74 | struct snd_ac97_bus *ac97_bus; | 75 | struct snd_ac97_bus *ac97_bus; |
75 | struct snd_ac97_template ac97_template; | 76 | struct snd_ac97_template ac97_template; |
76 | int ret; | 77 | int ret; |
@@ -82,24 +83,31 @@ static int ac97_soc_probe(struct snd_soc_codec *codec) | |||
82 | return ret; | 83 | return ret; |
83 | 84 | ||
84 | memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); | 85 | memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); |
85 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97); | 86 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97); |
86 | if (ret < 0) | 87 | if (ret < 0) |
87 | return ret; | 88 | return ret; |
88 | 89 | ||
90 | snd_soc_codec_set_drvdata(codec, ac97); | ||
91 | |||
89 | return 0; | 92 | return 0; |
90 | } | 93 | } |
91 | 94 | ||
92 | #ifdef CONFIG_PM | 95 | #ifdef CONFIG_PM |
93 | static int ac97_soc_suspend(struct snd_soc_codec *codec) | 96 | static int ac97_soc_suspend(struct snd_soc_codec *codec) |
94 | { | 97 | { |
95 | snd_ac97_suspend(codec->ac97); | 98 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
99 | |||
100 | snd_ac97_suspend(ac97); | ||
96 | 101 | ||
97 | return 0; | 102 | return 0; |
98 | } | 103 | } |
99 | 104 | ||
100 | static int ac97_soc_resume(struct snd_soc_codec *codec) | 105 | static int ac97_soc_resume(struct snd_soc_codec *codec) |
101 | { | 106 | { |
102 | snd_ac97_resume(codec->ac97); | 107 | |
108 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
109 | |||
110 | snd_ac97_resume(ac97); | ||
103 | 111 | ||
104 | return 0; | 112 | return 0; |
105 | } | 113 | } |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 6844d0b2af68..387530b0b0fd 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -72,11 +72,13 @@ static const struct snd_kcontrol_new ad193x_snd_controls[] = { | |||
72 | }; | 72 | }; |
73 | 73 | ||
74 | static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { | 74 | static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { |
75 | SND_SOC_DAPM_DAC("DAC", "Playback", AD193X_DAC_CTRL0, 0, 1), | 75 | SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), |
76 | SND_SOC_DAPM_PGA("DAC Output", AD193X_DAC_CTRL0, 0, 1, NULL, 0), | ||
76 | SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), | 77 | SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), |
77 | SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0), | 78 | SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0), |
78 | SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), | 79 | SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), |
79 | SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0), | 80 | SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0), |
81 | SND_SOC_DAPM_VMID("VMID"), | ||
80 | SND_SOC_DAPM_OUTPUT("DAC1OUT"), | 82 | SND_SOC_DAPM_OUTPUT("DAC1OUT"), |
81 | SND_SOC_DAPM_OUTPUT("DAC2OUT"), | 83 | SND_SOC_DAPM_OUTPUT("DAC2OUT"), |
82 | SND_SOC_DAPM_OUTPUT("DAC3OUT"), | 84 | SND_SOC_DAPM_OUTPUT("DAC3OUT"), |
@@ -87,13 +89,15 @@ static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { | |||
87 | 89 | ||
88 | static const struct snd_soc_dapm_route audio_paths[] = { | 90 | static const struct snd_soc_dapm_route audio_paths[] = { |
89 | { "DAC", NULL, "SYSCLK" }, | 91 | { "DAC", NULL, "SYSCLK" }, |
92 | { "DAC Output", NULL, "DAC" }, | ||
93 | { "DAC Output", NULL, "VMID" }, | ||
90 | { "ADC", NULL, "SYSCLK" }, | 94 | { "ADC", NULL, "SYSCLK" }, |
91 | { "DAC", NULL, "ADC_PWR" }, | 95 | { "DAC", NULL, "ADC_PWR" }, |
92 | { "ADC", NULL, "ADC_PWR" }, | 96 | { "ADC", NULL, "ADC_PWR" }, |
93 | { "DAC1OUT", NULL, "DAC" }, | 97 | { "DAC1OUT", NULL, "DAC Output" }, |
94 | { "DAC2OUT", NULL, "DAC" }, | 98 | { "DAC2OUT", NULL, "DAC Output" }, |
95 | { "DAC3OUT", NULL, "DAC" }, | 99 | { "DAC3OUT", NULL, "DAC Output" }, |
96 | { "DAC4OUT", NULL, "DAC" }, | 100 | { "DAC4OUT", NULL, "DAC Output" }, |
97 | { "ADC", NULL, "ADC1IN" }, | 101 | { "ADC", NULL, "ADC1IN" }, |
98 | { "ADC", NULL, "ADC2IN" }, | 102 | { "ADC", NULL, "ADC2IN" }, |
99 | { "SYSCLK", NULL, "PLL_PWR" }, | 103 | { "SYSCLK", NULL, "PLL_PWR" }, |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 304d3003339a..2860eef8610c 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -24,34 +24,86 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
27 | #include <linux/regmap.h> | ||
27 | #include <sound/core.h> | 28 | #include <sound/core.h> |
28 | #include <sound/pcm.h> | 29 | #include <sound/pcm.h> |
29 | #include <sound/ac97_codec.h> | 30 | #include <sound/ac97_codec.h> |
30 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
31 | #include <sound/soc.h> | 32 | #include <sound/soc.h> |
32 | 33 | ||
33 | #include "ad1980.h" | 34 | static const struct reg_default ad1980_reg_defaults[] = { |
35 | { 0x02, 0x8000 }, | ||
36 | { 0x04, 0x8000 }, | ||
37 | { 0x06, 0x8000 }, | ||
38 | { 0x0c, 0x8008 }, | ||
39 | { 0x0e, 0x8008 }, | ||
40 | { 0x10, 0x8808 }, | ||
41 | { 0x12, 0x8808 }, | ||
42 | { 0x16, 0x8808 }, | ||
43 | { 0x18, 0x8808 }, | ||
44 | { 0x1a, 0x0000 }, | ||
45 | { 0x1c, 0x8000 }, | ||
46 | { 0x20, 0x0000 }, | ||
47 | { 0x28, 0x03c7 }, | ||
48 | { 0x2c, 0xbb80 }, | ||
49 | { 0x2e, 0xbb80 }, | ||
50 | { 0x30, 0xbb80 }, | ||
51 | { 0x32, 0xbb80 }, | ||
52 | { 0x36, 0x8080 }, | ||
53 | { 0x38, 0x8080 }, | ||
54 | { 0x3a, 0x2000 }, | ||
55 | { 0x60, 0x0000 }, | ||
56 | { 0x62, 0x0000 }, | ||
57 | { 0x72, 0x0000 }, | ||
58 | { 0x74, 0x1001 }, | ||
59 | { 0x76, 0x0000 }, | ||
60 | }; | ||
34 | 61 | ||
35 | /* | 62 | static bool ad1980_readable_reg(struct device *dev, unsigned int reg) |
36 | * AD1980 register cache | 63 | { |
37 | */ | 64 | switch (reg) { |
38 | static const u16 ad1980_reg[] = { | 65 | case AC97_RESET ... AC97_MASTER_MONO: |
39 | 0x0090, 0x8000, 0x8000, 0x8000, /* 0 - 6 */ | 66 | case AC97_PHONE ... AC97_CD: |
40 | 0x0000, 0x0000, 0x8008, 0x8008, /* 8 - e */ | 67 | case AC97_AUX ... AC97_GENERAL_PURPOSE: |
41 | 0x8808, 0x8808, 0x0000, 0x8808, /* 10 - 16 */ | 68 | case AC97_POWERDOWN ... AC97_PCM_LR_ADC_RATE: |
42 | 0x8808, 0x0000, 0x8000, 0x0000, /* 18 - 1e */ | 69 | case AC97_SPDIF: |
43 | 0x0000, 0x0000, 0x0000, 0x0000, /* 20 - 26 */ | 70 | case AC97_CODEC_CLASS_REV: |
44 | 0x03c7, 0x0000, 0xbb80, 0xbb80, /* 28 - 2e */ | 71 | case AC97_PCI_SVID: |
45 | 0xbb80, 0xbb80, 0x0000, 0x8080, /* 30 - 36 */ | 72 | case AC97_AD_CODEC_CFG: |
46 | 0x8080, 0x2000, 0x0000, 0x0000, /* 38 - 3e */ | 73 | case AC97_AD_JACK_SPDIF: |
47 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 74 | case AC97_AD_SERIAL_CFG: |
48 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 75 | case AC97_VENDOR_ID1: |
49 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 76 | case AC97_VENDOR_ID2: |
50 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 77 | return true; |
51 | 0x8080, 0x0000, 0x0000, 0x0000, /* 60 - 66 */ | 78 | default: |
52 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 79 | return false; |
53 | 0x0000, 0x0000, 0x1001, 0x0000, /* 70 - 76 */ | 80 | } |
54 | 0x0000, 0x0000, 0x4144, 0x5370 /* 78 - 7e */ | 81 | } |
82 | |||
83 | static bool ad1980_writeable_reg(struct device *dev, unsigned int reg) | ||
84 | { | ||
85 | switch (reg) { | ||
86 | case AC97_VENDOR_ID1: | ||
87 | case AC97_VENDOR_ID2: | ||
88 | return false; | ||
89 | default: | ||
90 | return ad1980_readable_reg(dev, reg); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | static const struct regmap_config ad1980_regmap_config = { | ||
95 | .reg_bits = 16, | ||
96 | .reg_stride = 2, | ||
97 | .val_bits = 16, | ||
98 | .max_register = 0x7e, | ||
99 | .cache_type = REGCACHE_RBTREE, | ||
100 | |||
101 | .volatile_reg = regmap_ac97_default_volatile, | ||
102 | .readable_reg = ad1980_readable_reg, | ||
103 | .writeable_reg = ad1980_writeable_reg, | ||
104 | |||
105 | .reg_defaults = ad1980_reg_defaults, | ||
106 | .num_reg_defaults = ARRAY_SIZE(ad1980_reg_defaults), | ||
55 | }; | 107 | }; |
56 | 108 | ||
57 | static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line", | 109 | static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line", |
@@ -134,45 +186,8 @@ static const struct snd_soc_dapm_route ad1980_dapm_routes[] = { | |||
134 | { "HP_OUT_R", NULL, "Playback" }, | 186 | { "HP_OUT_R", NULL, "Playback" }, |
135 | }; | 187 | }; |
136 | 188 | ||
137 | static unsigned int ac97_read(struct snd_soc_codec *codec, | ||
138 | unsigned int reg) | ||
139 | { | ||
140 | u16 *cache = codec->reg_cache; | ||
141 | |||
142 | switch (reg) { | ||
143 | case AC97_RESET: | ||
144 | case AC97_INT_PAGING: | ||
145 | case AC97_POWERDOWN: | ||
146 | case AC97_EXTENDED_STATUS: | ||
147 | case AC97_VENDOR_ID1: | ||
148 | case AC97_VENDOR_ID2: | ||
149 | return soc_ac97_ops->read(codec->ac97, reg); | ||
150 | default: | ||
151 | reg = reg >> 1; | ||
152 | |||
153 | if (reg >= ARRAY_SIZE(ad1980_reg)) | ||
154 | return -EINVAL; | ||
155 | |||
156 | return cache[reg]; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | ||
161 | unsigned int val) | ||
162 | { | ||
163 | u16 *cache = codec->reg_cache; | ||
164 | |||
165 | soc_ac97_ops->write(codec->ac97, reg, val); | ||
166 | reg = reg >> 1; | ||
167 | if (reg < ARRAY_SIZE(ad1980_reg)) | ||
168 | cache[reg] = val; | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static struct snd_soc_dai_driver ad1980_dai = { | 189 | static struct snd_soc_dai_driver ad1980_dai = { |
174 | .name = "ad1980-hifi", | 190 | .name = "ad1980-hifi", |
175 | .ac97_control = 1, | ||
176 | .playback = { | 191 | .playback = { |
177 | .stream_name = "Playback", | 192 | .stream_name = "Playback", |
178 | .channels_min = 2, | 193 | .channels_min = 2, |
@@ -189,108 +204,115 @@ static struct snd_soc_dai_driver ad1980_dai = { | |||
189 | 204 | ||
190 | static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) | 205 | static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) |
191 | { | 206 | { |
207 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
192 | unsigned int retry_cnt = 0; | 208 | unsigned int retry_cnt = 0; |
193 | 209 | ||
194 | do { | 210 | do { |
195 | if (try_warm && soc_ac97_ops->warm_reset) { | 211 | if (try_warm && soc_ac97_ops->warm_reset) { |
196 | soc_ac97_ops->warm_reset(codec->ac97); | 212 | soc_ac97_ops->warm_reset(ac97); |
197 | if (ac97_read(codec, AC97_RESET) == 0x0090) | 213 | if (snd_soc_read(codec, AC97_RESET) == 0x0090) |
198 | return 1; | 214 | return 1; |
199 | } | 215 | } |
200 | 216 | ||
201 | soc_ac97_ops->reset(codec->ac97); | 217 | soc_ac97_ops->reset(ac97); |
202 | /* | 218 | /* |
203 | * Set bit 16slot in register 74h, then every slot will has only | 219 | * Set bit 16slot in register 74h, then every slot will has only |
204 | * 16 bits. This command is sent out in 20bit mode, in which | 220 | * 16 bits. This command is sent out in 20bit mode, in which |
205 | * case the first nibble of data is eaten by the addr. (Tag is | 221 | * case the first nibble of data is eaten by the addr. (Tag is |
206 | * always 16 bit) | 222 | * always 16 bit) |
207 | */ | 223 | */ |
208 | ac97_write(codec, AC97_AD_SERIAL_CFG, 0x9900); | 224 | snd_soc_write(codec, AC97_AD_SERIAL_CFG, 0x9900); |
209 | 225 | ||
210 | if (ac97_read(codec, AC97_RESET) == 0x0090) | 226 | if (snd_soc_read(codec, AC97_RESET) == 0x0090) |
211 | return 0; | 227 | return 0; |
212 | } while (retry_cnt++ < 10); | 228 | } while (retry_cnt++ < 10); |
213 | 229 | ||
214 | printk(KERN_ERR "AD1980 AC97 reset failed\n"); | 230 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); |
231 | |||
215 | return -EIO; | 232 | return -EIO; |
216 | } | 233 | } |
217 | 234 | ||
218 | static int ad1980_soc_probe(struct snd_soc_codec *codec) | 235 | static int ad1980_soc_probe(struct snd_soc_codec *codec) |
219 | { | 236 | { |
237 | struct snd_ac97 *ac97; | ||
238 | struct regmap *regmap; | ||
220 | int ret; | 239 | int ret; |
221 | u16 vendor_id2; | 240 | u16 vendor_id2; |
222 | u16 ext_status; | 241 | u16 ext_status; |
223 | 242 | ||
224 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); | 243 | ac97 = snd_soc_new_ac97_codec(codec); |
225 | 244 | if (IS_ERR(ac97)) { | |
226 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | 245 | ret = PTR_ERR(ac97); |
227 | if (ret < 0) { | 246 | dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret); |
228 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); | ||
229 | return ret; | 247 | return ret; |
230 | } | 248 | } |
231 | 249 | ||
250 | regmap = regmap_init_ac97(ac97, &ad1980_regmap_config); | ||
251 | if (IS_ERR(regmap)) { | ||
252 | ret = PTR_ERR(regmap); | ||
253 | goto err_free_ac97; | ||
254 | } | ||
255 | |||
256 | snd_soc_codec_init_regmap(codec, regmap); | ||
257 | snd_soc_codec_set_drvdata(codec, ac97); | ||
258 | |||
232 | ret = ad1980_reset(codec, 0); | 259 | ret = ad1980_reset(codec, 0); |
233 | if (ret < 0) { | 260 | if (ret < 0) |
234 | printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); | ||
235 | goto reset_err; | 261 | goto reset_err; |
236 | } | ||
237 | 262 | ||
238 | /* Read out vendor ID to make sure it is ad1980 */ | 263 | /* Read out vendor ID to make sure it is ad1980 */ |
239 | if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) { | 264 | if (snd_soc_read(codec, AC97_VENDOR_ID1) != 0x4144) { |
240 | ret = -ENODEV; | 265 | ret = -ENODEV; |
241 | goto reset_err; | 266 | goto reset_err; |
242 | } | 267 | } |
243 | 268 | ||
244 | vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2); | 269 | vendor_id2 = snd_soc_read(codec, AC97_VENDOR_ID2); |
245 | 270 | ||
246 | if (vendor_id2 != 0x5370) { | 271 | if (vendor_id2 != 0x5370) { |
247 | if (vendor_id2 != 0x5374) { | 272 | if (vendor_id2 != 0x5374) { |
248 | ret = -ENODEV; | 273 | ret = -ENODEV; |
249 | goto reset_err; | 274 | goto reset_err; |
250 | } else { | 275 | } else { |
251 | printk(KERN_WARNING "ad1980: " | 276 | dev_warn(codec->dev, |
252 | "Found AD1981 - only 2/2 IN/OUT Channels " | 277 | "Found AD1981 - only 2/2 IN/OUT Channels supported\n"); |
253 | "supported\n"); | ||
254 | } | 278 | } |
255 | } | 279 | } |
256 | 280 | ||
257 | /* unmute captures and playbacks volume */ | 281 | /* unmute captures and playbacks volume */ |
258 | ac97_write(codec, AC97_MASTER, 0x0000); | 282 | snd_soc_write(codec, AC97_MASTER, 0x0000); |
259 | ac97_write(codec, AC97_PCM, 0x0000); | 283 | snd_soc_write(codec, AC97_PCM, 0x0000); |
260 | ac97_write(codec, AC97_REC_GAIN, 0x0000); | 284 | snd_soc_write(codec, AC97_REC_GAIN, 0x0000); |
261 | ac97_write(codec, AC97_CENTER_LFE_MASTER, 0x0000); | 285 | snd_soc_write(codec, AC97_CENTER_LFE_MASTER, 0x0000); |
262 | ac97_write(codec, AC97_SURROUND_MASTER, 0x0000); | 286 | snd_soc_write(codec, AC97_SURROUND_MASTER, 0x0000); |
263 | 287 | ||
264 | /*power on LFE/CENTER/Surround DACs*/ | 288 | /*power on LFE/CENTER/Surround DACs*/ |
265 | ext_status = ac97_read(codec, AC97_EXTENDED_STATUS); | 289 | ext_status = snd_soc_read(codec, AC97_EXTENDED_STATUS); |
266 | ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); | 290 | snd_soc_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); |
267 | |||
268 | snd_soc_add_codec_controls(codec, ad1980_snd_ac97_controls, | ||
269 | ARRAY_SIZE(ad1980_snd_ac97_controls)); | ||
270 | 291 | ||
271 | return 0; | 292 | return 0; |
272 | 293 | ||
273 | reset_err: | 294 | reset_err: |
274 | snd_soc_free_ac97_codec(codec); | 295 | snd_soc_codec_exit_regmap(codec); |
296 | err_free_ac97: | ||
297 | snd_soc_free_ac97_codec(ac97); | ||
275 | return ret; | 298 | return ret; |
276 | } | 299 | } |
277 | 300 | ||
278 | static int ad1980_soc_remove(struct snd_soc_codec *codec) | 301 | static int ad1980_soc_remove(struct snd_soc_codec *codec) |
279 | { | 302 | { |
280 | snd_soc_free_ac97_codec(codec); | 303 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
304 | |||
305 | snd_soc_codec_exit_regmap(codec); | ||
306 | snd_soc_free_ac97_codec(ac97); | ||
281 | return 0; | 307 | return 0; |
282 | } | 308 | } |
283 | 309 | ||
284 | static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { | 310 | static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { |
285 | .probe = ad1980_soc_probe, | 311 | .probe = ad1980_soc_probe, |
286 | .remove = ad1980_soc_remove, | 312 | .remove = ad1980_soc_remove, |
287 | .reg_cache_size = ARRAY_SIZE(ad1980_reg), | ||
288 | .reg_word_size = sizeof(u16), | ||
289 | .reg_cache_default = ad1980_reg, | ||
290 | .reg_cache_step = 2, | ||
291 | .write = ac97_write, | ||
292 | .read = ac97_read, | ||
293 | 313 | ||
314 | .controls = ad1980_snd_ac97_controls, | ||
315 | .num_controls = ARRAY_SIZE(ad1980_snd_ac97_controls), | ||
294 | .dapm_widgets = ad1980_dapm_widgets, | 316 | .dapm_widgets = ad1980_dapm_widgets, |
295 | .num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets), | 317 | .num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets), |
296 | .dapm_routes = ad1980_dapm_routes, | 318 | .dapm_routes = ad1980_dapm_routes, |
diff --git a/sound/soc/codecs/ad1980.h b/sound/soc/codecs/ad1980.h deleted file mode 100644 index eb0af44ad3df..000000000000 --- a/sound/soc/codecs/ad1980.h +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * ad1980.h -- ad1980 Soc Audio driver | ||
3 | * | ||
4 | * WARNING: | ||
5 | * | ||
6 | * Because Analog Devices Inc. discontinued the ad1980 sound chip since | ||
7 | * Sep. 2009, this ad1980 driver is not maintained, tested and supported | ||
8 | * by ADI now. | ||
9 | */ | ||
10 | |||
11 | #ifndef _AD1980_H | ||
12 | #define _AD1980_H | ||
13 | /* Bit definition of Power-Down Control/Status Register */ | ||
14 | #define ADC 0x0001 | ||
15 | #define DAC 0x0002 | ||
16 | #define ANL 0x0004 | ||
17 | #define REF 0x0008 | ||
18 | #define PR0 0x0100 | ||
19 | #define PR1 0x0200 | ||
20 | #define PR2 0x0400 | ||
21 | #define PR3 0x0800 | ||
22 | #define PR4 0x1000 | ||
23 | #define PR5 0x2000 | ||
24 | #define PR6 0x4000 | ||
25 | |||
26 | #endif | ||
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 7c784ad3e8b2..783dcb57043a 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
@@ -551,7 +551,7 @@ static const struct snd_kcontrol_new adau1373_drc_controls[] = { | |||
551 | static int adau1373_pll_event(struct snd_soc_dapm_widget *w, | 551 | static int adau1373_pll_event(struct snd_soc_dapm_widget *w, |
552 | struct snd_kcontrol *kcontrol, int event) | 552 | struct snd_kcontrol *kcontrol, int event) |
553 | { | 553 | { |
554 | struct snd_soc_codec *codec = w->codec; | 554 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
555 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | 555 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); |
556 | unsigned int pll_id = w->name[3] - '1'; | 556 | unsigned int pll_id = w->name[3] - '1'; |
557 | unsigned int val; | 557 | unsigned int val; |
@@ -823,7 +823,7 @@ static const struct snd_soc_dapm_widget adau1373_dapm_widgets[] = { | |||
823 | static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, | 823 | static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, |
824 | struct snd_soc_dapm_widget *sink) | 824 | struct snd_soc_dapm_widget *sink) |
825 | { | 825 | { |
826 | struct snd_soc_codec *codec = source->codec; | 826 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
827 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | 827 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); |
828 | unsigned int dai; | 828 | unsigned int dai; |
829 | const char *clk; | 829 | const char *clk; |
@@ -844,7 +844,7 @@ static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, | |||
844 | static int adau1373_check_src(struct snd_soc_dapm_widget *source, | 844 | static int adau1373_check_src(struct snd_soc_dapm_widget *source, |
845 | struct snd_soc_dapm_widget *sink) | 845 | struct snd_soc_dapm_widget *sink) |
846 | { | 846 | { |
847 | struct snd_soc_codec *codec = source->codec; | 847 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
848 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | 848 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); |
849 | unsigned int dai; | 849 | unsigned int dai; |
850 | 850 | ||
diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index 5518ebd6947c..16093dc89441 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c | |||
@@ -255,7 +255,8 @@ static const struct snd_kcontrol_new adau1761_input_mux_control = | |||
255 | static int adau1761_dejitter_fixup(struct snd_soc_dapm_widget *w, | 255 | static int adau1761_dejitter_fixup(struct snd_soc_dapm_widget *w, |
256 | struct snd_kcontrol *kcontrol, int event) | 256 | struct snd_kcontrol *kcontrol, int event) |
257 | { | 257 | { |
258 | struct adau *adau = snd_soc_codec_get_drvdata(w->codec); | 258 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
259 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | ||
259 | 260 | ||
260 | /* After any power changes have been made the dejitter circuit | 261 | /* After any power changes have been made the dejitter circuit |
261 | * has to be reinitialized. */ | 262 | * has to be reinitialized. */ |
@@ -405,6 +406,7 @@ static const struct snd_soc_dapm_widget adau1761_dapm_widgets[] = { | |||
405 | 2, 0, NULL, 0), | 406 | 2, 0, NULL, 0), |
406 | 407 | ||
407 | SND_SOC_DAPM_SUPPLY("Slew Clock", ADAU1761_CLK_ENABLE0, 6, 0, NULL, 0), | 408 | SND_SOC_DAPM_SUPPLY("Slew Clock", ADAU1761_CLK_ENABLE0, 6, 0, NULL, 0), |
409 | SND_SOC_DAPM_SUPPLY("ALC Clock", ADAU1761_CLK_ENABLE0, 5, 0, NULL, 0), | ||
408 | 410 | ||
409 | SND_SOC_DAPM_SUPPLY_S("Digital Clock 0", 1, ADAU1761_CLK_ENABLE1, | 411 | SND_SOC_DAPM_SUPPLY_S("Digital Clock 0", 1, ADAU1761_CLK_ENABLE1, |
410 | 0, 0, NULL, 0), | 412 | 0, 0, NULL, 0), |
@@ -436,6 +438,9 @@ static const struct snd_soc_dapm_route adau1761_dapm_routes[] = { | |||
436 | { "Right Playback Mixer", NULL, "Slew Clock" }, | 438 | { "Right Playback Mixer", NULL, "Slew Clock" }, |
437 | { "Left Playback Mixer", NULL, "Slew Clock" }, | 439 | { "Left Playback Mixer", NULL, "Slew Clock" }, |
438 | 440 | ||
441 | { "Left Input Mixer", NULL, "ALC Clock" }, | ||
442 | { "Right Input Mixer", NULL, "ALC Clock" }, | ||
443 | |||
439 | { "Digital Clock 0", NULL, "SYSCLK" }, | 444 | { "Digital Clock 0", NULL, "SYSCLK" }, |
440 | { "Digital Clock 1", NULL, "SYSCLK" }, | 445 | { "Digital Clock 1", NULL, "SYSCLK" }, |
441 | }; | 446 | }; |
diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c index e9fc00fb13dd..aa6a37cc44b7 100644 --- a/sound/soc/codecs/adau1781.c +++ b/sound/soc/codecs/adau1781.c | |||
@@ -174,7 +174,7 @@ static const struct snd_kcontrol_new adau1781_mono_mixer_controls[] = { | |||
174 | static int adau1781_dejitter_fixup(struct snd_soc_dapm_widget *w, | 174 | static int adau1781_dejitter_fixup(struct snd_soc_dapm_widget *w, |
175 | struct snd_kcontrol *kcontrol, int event) | 175 | struct snd_kcontrol *kcontrol, int event) |
176 | { | 176 | { |
177 | struct snd_soc_codec *codec = w->codec; | 177 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
178 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 178 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
179 | 179 | ||
180 | /* After any power changes have been made the dejitter circuit | 180 | /* After any power changes have been made the dejitter circuit |
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 3e16c1c64115..427ad77bfe56 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c | |||
@@ -61,7 +61,8 @@ static const struct snd_kcontrol_new adau17x1_controls[] = { | |||
61 | static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, | 61 | static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, |
62 | struct snd_kcontrol *kcontrol, int event) | 62 | struct snd_kcontrol *kcontrol, int event) |
63 | { | 63 | { |
64 | struct adau *adau = snd_soc_codec_get_drvdata(w->codec); | 64 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
65 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | ||
65 | int ret; | 66 | int ret; |
66 | 67 | ||
67 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 68 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index ce3cdca9fc62..b67480f1b1aa 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c | |||
@@ -212,7 +212,7 @@ static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = { | |||
212 | static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, | 212 | static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, |
213 | struct snd_soc_dapm_widget *sink) | 213 | struct snd_soc_dapm_widget *sink) |
214 | { | 214 | { |
215 | struct snd_soc_codec *codec = source->codec; | 215 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
216 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 216 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
217 | const char *clk; | 217 | const char *clk; |
218 | 218 | ||
@@ -236,7 +236,7 @@ static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, | |||
236 | static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source, | 236 | static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source, |
237 | struct snd_soc_dapm_widget *sink) | 237 | struct snd_soc_dapm_widget *sink) |
238 | { | 238 | { |
239 | struct snd_soc_codec *codec = source->codec; | 239 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
240 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 240 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
241 | 241 | ||
242 | return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL; | 242 | return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL; |
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 30e297890fec..9130d916f2f4 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -373,33 +373,9 @@ static struct snd_soc_dai_driver ak4535_dai = { | |||
373 | .ops = &ak4535_dai_ops, | 373 | .ops = &ak4535_dai_ops, |
374 | }; | 374 | }; |
375 | 375 | ||
376 | static int ak4535_suspend(struct snd_soc_codec *codec) | ||
377 | { | ||
378 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static int ak4535_resume(struct snd_soc_codec *codec) | 376 | static int ak4535_resume(struct snd_soc_codec *codec) |
383 | { | 377 | { |
384 | snd_soc_cache_sync(codec); | 378 | snd_soc_cache_sync(codec); |
385 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static int ak4535_probe(struct snd_soc_codec *codec) | ||
390 | { | ||
391 | /* power on device */ | ||
392 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
393 | |||
394 | snd_soc_add_codec_controls(codec, ak4535_snd_controls, | ||
395 | ARRAY_SIZE(ak4535_snd_controls)); | ||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | /* power down chip */ | ||
400 | static int ak4535_remove(struct snd_soc_codec *codec) | ||
401 | { | ||
402 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
403 | return 0; | 379 | return 0; |
404 | } | 380 | } |
405 | 381 | ||
@@ -416,11 +392,12 @@ static const struct regmap_config ak4535_regmap = { | |||
416 | }; | 392 | }; |
417 | 393 | ||
418 | static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { | 394 | static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { |
419 | .probe = ak4535_probe, | ||
420 | .remove = ak4535_remove, | ||
421 | .suspend = ak4535_suspend, | ||
422 | .resume = ak4535_resume, | 395 | .resume = ak4535_resume, |
423 | .set_bias_level = ak4535_set_bias_level, | 396 | .set_bias_level = ak4535_set_bias_level, |
397 | .suspend_bias_off = true, | ||
398 | |||
399 | .controls = ak4535_snd_controls, | ||
400 | .num_controls = ARRAY_SIZE(ak4535_snd_controls), | ||
424 | .dapm_widgets = ak4535_dapm_widgets, | 401 | .dapm_widgets = ak4535_dapm_widgets, |
425 | .num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets), | 402 | .num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets), |
426 | .dapm_routes = ak4535_audio_map, | 403 | .dapm_routes = ak4535_audio_map, |
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 7afe8f482088..70861c7b1631 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c | |||
@@ -505,39 +505,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = { | |||
505 | }, | 505 | }, |
506 | }; | 506 | }; |
507 | 507 | ||
508 | static int ak4641_suspend(struct snd_soc_codec *codec) | ||
509 | { | ||
510 | ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static int ak4641_resume(struct snd_soc_codec *codec) | ||
515 | { | ||
516 | ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | static int ak4641_probe(struct snd_soc_codec *codec) | ||
521 | { | ||
522 | /* power on device */ | ||
523 | ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int ak4641_remove(struct snd_soc_codec *codec) | ||
529 | { | ||
530 | ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | |||
536 | static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { | 508 | static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { |
537 | .probe = ak4641_probe, | ||
538 | .remove = ak4641_remove, | ||
539 | .suspend = ak4641_suspend, | ||
540 | .resume = ak4641_resume, | ||
541 | .controls = ak4641_snd_controls, | 509 | .controls = ak4641_snd_controls, |
542 | .num_controls = ARRAY_SIZE(ak4641_snd_controls), | 510 | .num_controls = ARRAY_SIZE(ak4641_snd_controls), |
543 | .dapm_widgets = ak4641_dapm_widgets, | 511 | .dapm_widgets = ak4641_dapm_widgets, |
@@ -545,6 +513,7 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { | |||
545 | .dapm_routes = ak4641_audio_map, | 513 | .dapm_routes = ak4641_audio_map, |
546 | .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), | 514 | .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), |
547 | .set_bias_level = ak4641_set_bias_level, | 515 | .set_bias_level = ak4641_set_bias_level, |
516 | .suspend_bias_off = true, | ||
548 | }; | 517 | }; |
549 | 518 | ||
550 | static const struct regmap_config ak4641_regmap = { | 519 | static const struct regmap_config ak4641_regmap = { |
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 041712592e29..dde8b49c19ad 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -491,23 +491,7 @@ static int ak4642_resume(struct snd_soc_codec *codec) | |||
491 | return 0; | 491 | return 0; |
492 | } | 492 | } |
493 | 493 | ||
494 | |||
495 | static int ak4642_probe(struct snd_soc_codec *codec) | ||
496 | { | ||
497 | ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static int ak4642_remove(struct snd_soc_codec *codec) | ||
503 | { | ||
504 | ak4642_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { | 494 | static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { |
509 | .probe = ak4642_probe, | ||
510 | .remove = ak4642_remove, | ||
511 | .resume = ak4642_resume, | 495 | .resume = ak4642_resume, |
512 | .set_bias_level = ak4642_set_bias_level, | 496 | .set_bias_level = ak4642_set_bias_level, |
513 | .controls = ak4642_snd_controls, | 497 | .controls = ak4642_snd_controls, |
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 998fa0c5a0b9..686cacb0e835 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c | |||
@@ -611,20 +611,7 @@ static struct snd_soc_dai_driver ak4671_dai = { | |||
611 | .ops = &ak4671_dai_ops, | 611 | .ops = &ak4671_dai_ops, |
612 | }; | 612 | }; |
613 | 613 | ||
614 | static int ak4671_probe(struct snd_soc_codec *codec) | ||
615 | { | ||
616 | return ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
617 | } | ||
618 | |||
619 | static int ak4671_remove(struct snd_soc_codec *codec) | ||
620 | { | ||
621 | ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { | 614 | static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { |
626 | .probe = ak4671_probe, | ||
627 | .remove = ak4671_remove, | ||
628 | .set_bias_level = ak4671_set_bias_level, | 615 | .set_bias_level = ak4671_set_bias_level, |
629 | .controls = ak4671_snd_controls, | 616 | .controls = ak4671_snd_controls, |
630 | .num_controls = ARRAY_SIZE(ak4671_snd_controls), | 617 | .num_controls = ARRAY_SIZE(ak4671_snd_controls), |
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index 9d0755aa1d16..bdf8c5ac8ca4 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c | |||
@@ -866,7 +866,6 @@ static int alc5623_suspend(struct snd_soc_codec *codec) | |||
866 | { | 866 | { |
867 | struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); | 867 | struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); |
868 | 868 | ||
869 | alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
870 | regcache_cache_only(alc5623->regmap, true); | 869 | regcache_cache_only(alc5623->regmap, true); |
871 | 870 | ||
872 | return 0; | 871 | return 0; |
@@ -887,15 +886,6 @@ static int alc5623_resume(struct snd_soc_codec *codec) | |||
887 | return ret; | 886 | return ret; |
888 | } | 887 | } |
889 | 888 | ||
890 | alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
891 | |||
892 | /* charge alc5623 caps */ | ||
893 | if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) { | ||
894 | alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
895 | codec->dapm.bias_level = SND_SOC_BIAS_ON; | ||
896 | alc5623_set_bias_level(codec, codec->dapm.bias_level); | ||
897 | } | ||
898 | |||
899 | return 0; | 889 | return 0; |
900 | } | 890 | } |
901 | 891 | ||
@@ -906,9 +896,6 @@ static int alc5623_probe(struct snd_soc_codec *codec) | |||
906 | 896 | ||
907 | alc5623_reset(codec); | 897 | alc5623_reset(codec); |
908 | 898 | ||
909 | /* power on device */ | ||
910 | alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
911 | |||
912 | if (alc5623->add_ctrl) { | 899 | if (alc5623->add_ctrl) { |
913 | snd_soc_write(codec, ALC5623_ADD_CTRL_REG, | 900 | snd_soc_write(codec, ALC5623_ADD_CTRL_REG, |
914 | alc5623->add_ctrl); | 901 | alc5623->add_ctrl); |
@@ -964,19 +951,12 @@ static int alc5623_probe(struct snd_soc_codec *codec) | |||
964 | return 0; | 951 | return 0; |
965 | } | 952 | } |
966 | 953 | ||
967 | /* power down chip */ | ||
968 | static int alc5623_remove(struct snd_soc_codec *codec) | ||
969 | { | ||
970 | alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
971 | return 0; | ||
972 | } | ||
973 | |||
974 | static struct snd_soc_codec_driver soc_codec_device_alc5623 = { | 954 | static struct snd_soc_codec_driver soc_codec_device_alc5623 = { |
975 | .probe = alc5623_probe, | 955 | .probe = alc5623_probe, |
976 | .remove = alc5623_remove, | ||
977 | .suspend = alc5623_suspend, | 956 | .suspend = alc5623_suspend, |
978 | .resume = alc5623_resume, | 957 | .resume = alc5623_resume, |
979 | .set_bias_level = alc5623_set_bias_level, | 958 | .set_bias_level = alc5623_set_bias_level, |
959 | .suspend_bias_off = true, | ||
980 | }; | 960 | }; |
981 | 961 | ||
982 | static const struct regmap_config alc5623_regmap = { | 962 | static const struct regmap_config alc5623_regmap = { |
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index 85942ca36cbf..d1fdbc266631 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c | |||
@@ -1038,23 +1038,15 @@ static struct snd_soc_dai_driver alc5632_dai = { | |||
1038 | }; | 1038 | }; |
1039 | 1039 | ||
1040 | #ifdef CONFIG_PM | 1040 | #ifdef CONFIG_PM |
1041 | static int alc5632_suspend(struct snd_soc_codec *codec) | ||
1042 | { | ||
1043 | alc5632_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | static int alc5632_resume(struct snd_soc_codec *codec) | 1041 | static int alc5632_resume(struct snd_soc_codec *codec) |
1048 | { | 1042 | { |
1049 | struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); | 1043 | struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); |
1050 | 1044 | ||
1051 | regcache_sync(alc5632->regmap); | 1045 | regcache_sync(alc5632->regmap); |
1052 | 1046 | ||
1053 | alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1054 | return 0; | 1047 | return 0; |
1055 | } | 1048 | } |
1056 | #else | 1049 | #else |
1057 | #define alc5632_suspend NULL | ||
1058 | #define alc5632_resume NULL | 1050 | #define alc5632_resume NULL |
1059 | #endif | 1051 | #endif |
1060 | 1052 | ||
@@ -1062,9 +1054,6 @@ static int alc5632_probe(struct snd_soc_codec *codec) | |||
1062 | { | 1054 | { |
1063 | struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); | 1055 | struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); |
1064 | 1056 | ||
1065 | /* power on device */ | ||
1066 | alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1067 | |||
1068 | switch (alc5632->id) { | 1057 | switch (alc5632->id) { |
1069 | case 0x5c: | 1058 | case 0x5c: |
1070 | snd_soc_add_codec_controls(codec, alc5632_vol_snd_controls, | 1059 | snd_soc_add_codec_controls(codec, alc5632_vol_snd_controls, |
@@ -1077,19 +1066,12 @@ static int alc5632_probe(struct snd_soc_codec *codec) | |||
1077 | return 0; | 1066 | return 0; |
1078 | } | 1067 | } |
1079 | 1068 | ||
1080 | /* power down chip */ | ||
1081 | static int alc5632_remove(struct snd_soc_codec *codec) | ||
1082 | { | ||
1083 | alc5632_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1084 | return 0; | ||
1085 | } | ||
1086 | |||
1087 | static struct snd_soc_codec_driver soc_codec_device_alc5632 = { | 1069 | static struct snd_soc_codec_driver soc_codec_device_alc5632 = { |
1088 | .probe = alc5632_probe, | 1070 | .probe = alc5632_probe, |
1089 | .remove = alc5632_remove, | ||
1090 | .suspend = alc5632_suspend, | ||
1091 | .resume = alc5632_resume, | 1071 | .resume = alc5632_resume, |
1092 | .set_bias_level = alc5632_set_bias_level, | 1072 | .set_bias_level = alc5632_set_bias_level, |
1073 | .suspend_bias_off = true, | ||
1074 | |||
1093 | .controls = alc5632_snd_controls, | 1075 | .controls = alc5632_snd_controls, |
1094 | .num_controls = ARRAY_SIZE(alc5632_snd_controls), | 1076 | .num_controls = ARRAY_SIZE(alc5632_snd_controls), |
1095 | .dapm_widgets = alc5632_dapm_widgets, | 1077 | .dapm_widgets = alc5632_dapm_widgets, |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 0c05e7a7945f..9550d7433ad0 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -61,6 +61,11 @@ | |||
61 | #define ARIZONA_FLL_MIN_OUTDIV 2 | 61 | #define ARIZONA_FLL_MIN_OUTDIV 2 |
62 | #define ARIZONA_FLL_MAX_OUTDIV 7 | 62 | #define ARIZONA_FLL_MAX_OUTDIV 7 |
63 | 63 | ||
64 | #define ARIZONA_FMT_DSP_MODE_A 0 | ||
65 | #define ARIZONA_FMT_DSP_MODE_B 1 | ||
66 | #define ARIZONA_FMT_I2S_MODE 2 | ||
67 | #define ARIZONA_FMT_LEFT_JUSTIFIED_MODE 3 | ||
68 | |||
64 | #define arizona_fll_err(_fll, fmt, ...) \ | 69 | #define arizona_fll_err(_fll, fmt, ...) \ |
65 | dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) | 70 | dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) |
66 | #define arizona_fll_warn(_fll, fmt, ...) \ | 71 | #define arizona_fll_warn(_fll, fmt, ...) \ |
@@ -648,7 +653,7 @@ SOC_ENUM_SINGLE_DECL(arizona_in_hpf_cut_enum, | |||
648 | EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); | 653 | EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); |
649 | 654 | ||
650 | static const char * const arizona_in_dmic_osr_text[] = { | 655 | static const char * const arizona_in_dmic_osr_text[] = { |
651 | "1.536MHz", "3.072MHz", "6.144MHz", | 656 | "1.536MHz", "3.072MHz", "6.144MHz", "768kHz", |
652 | }; | 657 | }; |
653 | 658 | ||
654 | const struct soc_enum arizona_in_dmic_osr[] = { | 659 | const struct soc_enum arizona_in_dmic_osr[] = { |
@@ -946,10 +951,26 @@ static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
946 | 951 | ||
947 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 952 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
948 | case SND_SOC_DAIFMT_DSP_A: | 953 | case SND_SOC_DAIFMT_DSP_A: |
949 | mode = 0; | 954 | mode = ARIZONA_FMT_DSP_MODE_A; |
955 | break; | ||
956 | case SND_SOC_DAIFMT_DSP_B: | ||
957 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) | ||
958 | != SND_SOC_DAIFMT_CBM_CFM) { | ||
959 | arizona_aif_err(dai, "DSP_B not valid in slave mode\n"); | ||
960 | return -EINVAL; | ||
961 | } | ||
962 | mode = ARIZONA_FMT_DSP_MODE_B; | ||
950 | break; | 963 | break; |
951 | case SND_SOC_DAIFMT_I2S: | 964 | case SND_SOC_DAIFMT_I2S: |
952 | mode = 2; | 965 | mode = ARIZONA_FMT_I2S_MODE; |
966 | break; | ||
967 | case SND_SOC_DAIFMT_LEFT_J: | ||
968 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) | ||
969 | != SND_SOC_DAIFMT_CBM_CFM) { | ||
970 | arizona_aif_err(dai, "LEFT_J not valid in slave mode\n"); | ||
971 | return -EINVAL; | ||
972 | } | ||
973 | mode = ARIZONA_FMT_LEFT_JUSTIFIED_MODE; | ||
953 | break; | 974 | break; |
954 | default: | 975 | default: |
955 | arizona_aif_err(dai, "Unsupported DAI format %d\n", | 976 | arizona_aif_err(dai, "Unsupported DAI format %d\n", |
@@ -1164,13 +1185,13 @@ static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec, | |||
1164 | { 0x80, 0x0 }, | 1185 | { 0x80, 0x0 }, |
1165 | }; | 1186 | }; |
1166 | 1187 | ||
1167 | mutex_lock(&codec->mutex); | 1188 | mutex_lock(&arizona->dac_comp_lock); |
1168 | 1189 | ||
1169 | dac_comp[1].def = arizona->dac_comp_coeff; | 1190 | dac_comp[1].def = arizona->dac_comp_coeff; |
1170 | if (rate >= 176400) | 1191 | if (rate >= 176400) |
1171 | dac_comp[2].def = arizona->dac_comp_enabled; | 1192 | dac_comp[2].def = arizona->dac_comp_enabled; |
1172 | 1193 | ||
1173 | mutex_unlock(&codec->mutex); | 1194 | mutex_unlock(&arizona->dac_comp_lock); |
1174 | 1195 | ||
1175 | regmap_multi_reg_write(arizona->regmap, | 1196 | regmap_multi_reg_write(arizona->regmap, |
1176 | dac_comp, | 1197 | dac_comp, |
@@ -1298,7 +1319,8 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
1298 | 1319 | ||
1299 | /* Force multiple of 2 channels for I2S mode */ | 1320 | /* Force multiple of 2 channels for I2S mode */ |
1300 | val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT); | 1321 | val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT); |
1301 | if ((channels & 1) && (val & ARIZONA_AIF1_FMT_MASK)) { | 1322 | val &= ARIZONA_AIF1_FMT_MASK; |
1323 | if ((channels & 1) && (val == ARIZONA_FMT_I2S_MODE)) { | ||
1302 | arizona_aif_dbg(dai, "Forcing stereo mode\n"); | 1324 | arizona_aif_dbg(dai, "Forcing stereo mode\n"); |
1303 | bclk_target /= channels; | 1325 | bclk_target /= channels; |
1304 | bclk_target *= channels + 1; | 1326 | bclk_target *= channels + 1; |
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index 537327c7f7f1..8d638e8aa8eb 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c | |||
@@ -62,14 +62,10 @@ static int cq93vc_mute(struct snd_soc_dai *dai, int mute) | |||
62 | static int cq93vc_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 62 | static int cq93vc_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
63 | int clk_id, unsigned int freq, int dir) | 63 | int clk_id, unsigned int freq, int dir) |
64 | { | 64 | { |
65 | struct snd_soc_codec *codec = codec_dai->codec; | ||
66 | struct davinci_vc *davinci_vc = codec->dev->platform_data; | ||
67 | |||
68 | switch (freq) { | 65 | switch (freq) { |
69 | case 22579200: | 66 | case 22579200: |
70 | case 27000000: | 67 | case 27000000: |
71 | case 33868800: | 68 | case 33868800: |
72 | davinci_vc->cq93vc.sysclk = freq; | ||
73 | return 0; | 69 | return 0; |
74 | } | 70 | } |
75 | 71 | ||
@@ -126,32 +122,6 @@ static struct snd_soc_dai_driver cq93vc_dai = { | |||
126 | .ops = &cq93vc_dai_ops, | 122 | .ops = &cq93vc_dai_ops, |
127 | }; | 123 | }; |
128 | 124 | ||
129 | static int cq93vc_resume(struct snd_soc_codec *codec) | ||
130 | { | ||
131 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int cq93vc_probe(struct snd_soc_codec *codec) | ||
137 | { | ||
138 | struct davinci_vc *davinci_vc = codec->dev->platform_data; | ||
139 | |||
140 | davinci_vc->cq93vc.codec = codec; | ||
141 | |||
142 | /* Off, with power on */ | ||
143 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int cq93vc_remove(struct snd_soc_codec *codec) | ||
149 | { | ||
150 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static struct regmap *cq93vc_get_regmap(struct device *dev) | 125 | static struct regmap *cq93vc_get_regmap(struct device *dev) |
156 | { | 126 | { |
157 | struct davinci_vc *davinci_vc = dev->platform_data; | 127 | struct davinci_vc *davinci_vc = dev->platform_data; |
@@ -161,9 +131,6 @@ static struct regmap *cq93vc_get_regmap(struct device *dev) | |||
161 | 131 | ||
162 | static struct snd_soc_codec_driver soc_codec_dev_cq93vc = { | 132 | static struct snd_soc_codec_driver soc_codec_dev_cq93vc = { |
163 | .set_bias_level = cq93vc_set_bias_level, | 133 | .set_bias_level = cq93vc_set_bias_level, |
164 | .probe = cq93vc_probe, | ||
165 | .remove = cq93vc_remove, | ||
166 | .resume = cq93vc_resume, | ||
167 | .get_regmap = cq93vc_get_regmap, | 134 | .get_regmap = cq93vc_get_regmap, |
168 | .controls = cq93vc_snd_controls, | 135 | .controls = cq93vc_snd_controls, |
169 | .num_controls = ARRAY_SIZE(cq93vc_snd_controls), | 136 | .num_controls = ARRAY_SIZE(cq93vc_snd_controls), |
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 4fdd47d700e3..ce6086835ebd 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include "cs4265.h" | 32 | #include "cs4265.h" |
33 | 33 | ||
34 | struct cs4265_private { | 34 | struct cs4265_private { |
35 | struct device *dev; | ||
36 | struct regmap *regmap; | 35 | struct regmap *regmap; |
37 | struct gpio_desc *reset_gpio; | 36 | struct gpio_desc *reset_gpio; |
38 | u8 format; | 37 | u8 format; |
@@ -598,7 +597,6 @@ static int cs4265_i2c_probe(struct i2c_client *i2c_client, | |||
598 | GFP_KERNEL); | 597 | GFP_KERNEL); |
599 | if (cs4265 == NULL) | 598 | if (cs4265 == NULL) |
600 | return -ENOMEM; | 599 | return -ENOMEM; |
601 | cs4265->dev = &i2c_client->dev; | ||
602 | 600 | ||
603 | cs4265->regmap = devm_regmap_init_i2c(i2c_client, &cs4265_regmap); | 601 | cs4265->regmap = devm_regmap_init_i2c(i2c_client, &cs4265_regmap); |
604 | if (IS_ERR(cs4265->regmap)) { | 602 | if (IS_ERR(cs4265->regmap)) { |
diff --git a/sound/soc/codecs/cs4271-i2c.c b/sound/soc/codecs/cs4271-i2c.c new file mode 100644 index 000000000000..b264da030340 --- /dev/null +++ b/sound/soc/codecs/cs4271-i2c.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * CS4271 I2C audio driver | ||
3 | * | ||
4 | * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include "cs4271.h" | ||
22 | |||
23 | static int cs4271_i2c_probe(struct i2c_client *client, | ||
24 | const struct i2c_device_id *id) | ||
25 | { | ||
26 | struct regmap_config config; | ||
27 | |||
28 | config = cs4271_regmap_config; | ||
29 | config.reg_bits = 8; | ||
30 | config.val_bits = 8; | ||
31 | |||
32 | return cs4271_probe(&client->dev, | ||
33 | devm_regmap_init_i2c(client, &config)); | ||
34 | } | ||
35 | |||
36 | static int cs4271_i2c_remove(struct i2c_client *client) | ||
37 | { | ||
38 | snd_soc_unregister_codec(&client->dev); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static const struct i2c_device_id cs4271_i2c_id[] = { | ||
43 | { "cs4271", 0 }, | ||
44 | { } | ||
45 | }; | ||
46 | MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); | ||
47 | |||
48 | static struct i2c_driver cs4271_i2c_driver = { | ||
49 | .driver = { | ||
50 | .name = "cs4271", | ||
51 | .owner = THIS_MODULE, | ||
52 | .of_match_table = of_match_ptr(cs4271_dt_ids), | ||
53 | }, | ||
54 | .probe = cs4271_i2c_probe, | ||
55 | .remove = cs4271_i2c_remove, | ||
56 | .id_table = cs4271_i2c_id, | ||
57 | }; | ||
58 | module_i2c_driver(cs4271_i2c_driver); | ||
59 | |||
60 | MODULE_DESCRIPTION("ASoC CS4271 I2C Driver"); | ||
61 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); | ||
62 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/cs4271-spi.c b/sound/soc/codecs/cs4271-spi.c new file mode 100644 index 000000000000..acd49d86e706 --- /dev/null +++ b/sound/soc/codecs/cs4271-spi.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * CS4271 SPI audio driver | ||
3 | * | ||
4 | * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/spi/spi.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include "cs4271.h" | ||
22 | |||
23 | static int cs4271_spi_probe(struct spi_device *spi) | ||
24 | { | ||
25 | struct regmap_config config; | ||
26 | |||
27 | config = cs4271_regmap_config; | ||
28 | config.reg_bits = 16; | ||
29 | config.val_bits = 8; | ||
30 | config.read_flag_mask = 0x21; | ||
31 | config.write_flag_mask = 0x20; | ||
32 | |||
33 | return cs4271_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); | ||
34 | } | ||
35 | |||
36 | static int cs4271_spi_remove(struct spi_device *spi) | ||
37 | { | ||
38 | snd_soc_unregister_codec(&spi->dev); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static struct spi_driver cs4271_spi_driver = { | ||
43 | .driver = { | ||
44 | .name = "cs4271", | ||
45 | .owner = THIS_MODULE, | ||
46 | .of_match_table = of_match_ptr(cs4271_dt_ids), | ||
47 | }, | ||
48 | .probe = cs4271_spi_probe, | ||
49 | .remove = cs4271_spi_remove, | ||
50 | }; | ||
51 | module_spi_driver(cs4271_spi_driver); | ||
52 | |||
53 | MODULE_DESCRIPTION("ASoC CS4271 SPI Driver"); | ||
54 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); | ||
55 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 93cec52f4733..79a4efcb894c 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c | |||
@@ -23,8 +23,6 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
26 | #include <linux/i2c.h> | ||
27 | #include <linux/spi/spi.h> | ||
28 | #include <linux/of.h> | 26 | #include <linux/of.h> |
29 | #include <linux/of_device.h> | 27 | #include <linux/of_device.h> |
30 | #include <linux/of_gpio.h> | 28 | #include <linux/of_gpio.h> |
@@ -32,6 +30,7 @@ | |||
32 | #include <sound/soc.h> | 30 | #include <sound/soc.h> |
33 | #include <sound/tlv.h> | 31 | #include <sound/tlv.h> |
34 | #include <sound/cs4271.h> | 32 | #include <sound/cs4271.h> |
33 | #include "cs4271.h" | ||
35 | 34 | ||
36 | #define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | 35 | #define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
37 | SNDRV_PCM_FMTBIT_S24_LE | \ | 36 | SNDRV_PCM_FMTBIT_S24_LE | \ |
@@ -527,14 +526,15 @@ static int cs4271_soc_resume(struct snd_soc_codec *codec) | |||
527 | #endif /* CONFIG_PM */ | 526 | #endif /* CONFIG_PM */ |
528 | 527 | ||
529 | #ifdef CONFIG_OF | 528 | #ifdef CONFIG_OF |
530 | static const struct of_device_id cs4271_dt_ids[] = { | 529 | const struct of_device_id cs4271_dt_ids[] = { |
531 | { .compatible = "cirrus,cs4271", }, | 530 | { .compatible = "cirrus,cs4271", }, |
532 | { } | 531 | { } |
533 | }; | 532 | }; |
534 | MODULE_DEVICE_TABLE(of, cs4271_dt_ids); | 533 | MODULE_DEVICE_TABLE(of, cs4271_dt_ids); |
534 | EXPORT_SYMBOL_GPL(cs4271_dt_ids); | ||
535 | #endif | 535 | #endif |
536 | 536 | ||
537 | static int cs4271_probe(struct snd_soc_codec *codec) | 537 | static int cs4271_codec_probe(struct snd_soc_codec *codec) |
538 | { | 538 | { |
539 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | 539 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); |
540 | struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; | 540 | struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; |
@@ -587,7 +587,7 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
587 | return 0; | 587 | return 0; |
588 | } | 588 | } |
589 | 589 | ||
590 | static int cs4271_remove(struct snd_soc_codec *codec) | 590 | static int cs4271_codec_remove(struct snd_soc_codec *codec) |
591 | { | 591 | { |
592 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | 592 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); |
593 | 593 | ||
@@ -599,8 +599,8 @@ static int cs4271_remove(struct snd_soc_codec *codec) | |||
599 | }; | 599 | }; |
600 | 600 | ||
601 | static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { | 601 | static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { |
602 | .probe = cs4271_probe, | 602 | .probe = cs4271_codec_probe, |
603 | .remove = cs4271_remove, | 603 | .remove = cs4271_codec_remove, |
604 | .suspend = cs4271_soc_suspend, | 604 | .suspend = cs4271_soc_suspend, |
605 | .resume = cs4271_soc_resume, | 605 | .resume = cs4271_soc_resume, |
606 | 606 | ||
@@ -642,14 +642,8 @@ static int cs4271_common_probe(struct device *dev, | |||
642 | return 0; | 642 | return 0; |
643 | } | 643 | } |
644 | 644 | ||
645 | #if defined(CONFIG_SPI_MASTER) | 645 | const struct regmap_config cs4271_regmap_config = { |
646 | |||
647 | static const struct regmap_config cs4271_spi_regmap = { | ||
648 | .reg_bits = 16, | ||
649 | .val_bits = 8, | ||
650 | .max_register = CS4271_LASTREG, | 646 | .max_register = CS4271_LASTREG, |
651 | .read_flag_mask = 0x21, | ||
652 | .write_flag_mask = 0x20, | ||
653 | 647 | ||
654 | .reg_defaults = cs4271_reg_defaults, | 648 | .reg_defaults = cs4271_reg_defaults, |
655 | .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), | 649 | .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), |
@@ -657,140 +651,27 @@ static const struct regmap_config cs4271_spi_regmap = { | |||
657 | 651 | ||
658 | .volatile_reg = cs4271_volatile_reg, | 652 | .volatile_reg = cs4271_volatile_reg, |
659 | }; | 653 | }; |
654 | EXPORT_SYMBOL_GPL(cs4271_regmap_config); | ||
660 | 655 | ||
661 | static int cs4271_spi_probe(struct spi_device *spi) | 656 | int cs4271_probe(struct device *dev, struct regmap *regmap) |
662 | { | 657 | { |
663 | struct cs4271_private *cs4271; | 658 | struct cs4271_private *cs4271; |
664 | int ret; | 659 | int ret; |
665 | 660 | ||
666 | ret = cs4271_common_probe(&spi->dev, &cs4271); | 661 | if (IS_ERR(regmap)) |
667 | if (ret < 0) | 662 | return PTR_ERR(regmap); |
668 | return ret; | ||
669 | |||
670 | spi_set_drvdata(spi, cs4271); | ||
671 | cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap); | ||
672 | if (IS_ERR(cs4271->regmap)) | ||
673 | return PTR_ERR(cs4271->regmap); | ||
674 | |||
675 | return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271, | ||
676 | &cs4271_dai, 1); | ||
677 | } | ||
678 | |||
679 | static int cs4271_spi_remove(struct spi_device *spi) | ||
680 | { | ||
681 | snd_soc_unregister_codec(&spi->dev); | ||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | static struct spi_driver cs4271_spi_driver = { | ||
686 | .driver = { | ||
687 | .name = "cs4271", | ||
688 | .owner = THIS_MODULE, | ||
689 | .of_match_table = of_match_ptr(cs4271_dt_ids), | ||
690 | }, | ||
691 | .probe = cs4271_spi_probe, | ||
692 | .remove = cs4271_spi_remove, | ||
693 | }; | ||
694 | #endif /* defined(CONFIG_SPI_MASTER) */ | ||
695 | |||
696 | #if IS_ENABLED(CONFIG_I2C) | ||
697 | static const struct i2c_device_id cs4271_i2c_id[] = { | ||
698 | {"cs4271", 0}, | ||
699 | {} | ||
700 | }; | ||
701 | MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); | ||
702 | 663 | ||
703 | static const struct regmap_config cs4271_i2c_regmap = { | 664 | ret = cs4271_common_probe(dev, &cs4271); |
704 | .reg_bits = 8, | ||
705 | .val_bits = 8, | ||
706 | .max_register = CS4271_LASTREG, | ||
707 | |||
708 | .reg_defaults = cs4271_reg_defaults, | ||
709 | .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), | ||
710 | .cache_type = REGCACHE_RBTREE, | ||
711 | |||
712 | .volatile_reg = cs4271_volatile_reg, | ||
713 | }; | ||
714 | |||
715 | static int cs4271_i2c_probe(struct i2c_client *client, | ||
716 | const struct i2c_device_id *id) | ||
717 | { | ||
718 | struct cs4271_private *cs4271; | ||
719 | int ret; | ||
720 | |||
721 | ret = cs4271_common_probe(&client->dev, &cs4271); | ||
722 | if (ret < 0) | 665 | if (ret < 0) |
723 | return ret; | 666 | return ret; |
724 | 667 | ||
725 | i2c_set_clientdata(client, cs4271); | 668 | dev_set_drvdata(dev, cs4271); |
726 | cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap); | 669 | cs4271->regmap = regmap; |
727 | if (IS_ERR(cs4271->regmap)) | ||
728 | return PTR_ERR(cs4271->regmap); | ||
729 | 670 | ||
730 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271, | 671 | return snd_soc_register_codec(dev, &soc_codec_dev_cs4271, &cs4271_dai, |
731 | &cs4271_dai, 1); | 672 | 1); |
732 | } | ||
733 | |||
734 | static int cs4271_i2c_remove(struct i2c_client *client) | ||
735 | { | ||
736 | snd_soc_unregister_codec(&client->dev); | ||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | static struct i2c_driver cs4271_i2c_driver = { | ||
741 | .driver = { | ||
742 | .name = "cs4271", | ||
743 | .owner = THIS_MODULE, | ||
744 | .of_match_table = of_match_ptr(cs4271_dt_ids), | ||
745 | }, | ||
746 | .id_table = cs4271_i2c_id, | ||
747 | .probe = cs4271_i2c_probe, | ||
748 | .remove = cs4271_i2c_remove, | ||
749 | }; | ||
750 | #endif /* IS_ENABLED(CONFIG_I2C) */ | ||
751 | |||
752 | /* | ||
753 | * We only register our serial bus driver here without | ||
754 | * assignment to particular chip. So if any of the below | ||
755 | * fails, there is some problem with I2C or SPI subsystem. | ||
756 | * In most cases this module will be compiled with support | ||
757 | * of only one serial bus. | ||
758 | */ | ||
759 | static int __init cs4271_modinit(void) | ||
760 | { | ||
761 | int ret; | ||
762 | |||
763 | #if IS_ENABLED(CONFIG_I2C) | ||
764 | ret = i2c_add_driver(&cs4271_i2c_driver); | ||
765 | if (ret) { | ||
766 | pr_err("Failed to register CS4271 I2C driver: %d\n", ret); | ||
767 | return ret; | ||
768 | } | ||
769 | #endif | ||
770 | |||
771 | #if defined(CONFIG_SPI_MASTER) | ||
772 | ret = spi_register_driver(&cs4271_spi_driver); | ||
773 | if (ret) { | ||
774 | pr_err("Failed to register CS4271 SPI driver: %d\n", ret); | ||
775 | return ret; | ||
776 | } | ||
777 | #endif | ||
778 | |||
779 | return 0; | ||
780 | } | ||
781 | module_init(cs4271_modinit); | ||
782 | |||
783 | static void __exit cs4271_modexit(void) | ||
784 | { | ||
785 | #if defined(CONFIG_SPI_MASTER) | ||
786 | spi_unregister_driver(&cs4271_spi_driver); | ||
787 | #endif | ||
788 | |||
789 | #if IS_ENABLED(CONFIG_I2C) | ||
790 | i2c_del_driver(&cs4271_i2c_driver); | ||
791 | #endif | ||
792 | } | 673 | } |
793 | module_exit(cs4271_modexit); | 674 | EXPORT_SYMBOL_GPL(cs4271_probe); |
794 | 675 | ||
795 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); | 676 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); |
796 | MODULE_DESCRIPTION("Cirrus Logic CS4271 ALSA SoC Codec Driver"); | 677 | MODULE_DESCRIPTION("Cirrus Logic CS4271 ALSA SoC Codec Driver"); |
diff --git a/sound/soc/codecs/cs4271.h b/sound/soc/codecs/cs4271.h new file mode 100644 index 000000000000..9adad8eefdc9 --- /dev/null +++ b/sound/soc/codecs/cs4271.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef _CS4271_PRIV_H | ||
2 | #define _CS4271_PRIV_H | ||
3 | |||
4 | #include <linux/regmap.h> | ||
5 | |||
6 | extern const struct of_device_id cs4271_dt_ids[]; | ||
7 | extern const struct regmap_config cs4271_regmap_config; | ||
8 | |||
9 | int cs4271_probe(struct device *dev, struct regmap *regmap); | ||
10 | |||
11 | #endif | ||
diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c index cee51ae177c1..c40428f25ba5 100644 --- a/sound/soc/codecs/cs42l51-i2c.c +++ b/sound/soc/codecs/cs42l51-i2c.c | |||
@@ -46,6 +46,7 @@ static struct i2c_driver cs42l51_i2c_driver = { | |||
46 | .driver = { | 46 | .driver = { |
47 | .name = "cs42l51", | 47 | .name = "cs42l51", |
48 | .owner = THIS_MODULE, | 48 | .owner = THIS_MODULE, |
49 | .of_match_table = cs42l51_of_match, | ||
49 | }, | 50 | }, |
50 | .probe = cs42l51_i2c_probe, | 51 | .probe = cs42l51_i2c_probe, |
51 | .remove = cs42l51_i2c_remove, | 52 | .remove = cs42l51_i2c_remove, |
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 09488d97de60..b3951524339f 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c | |||
@@ -153,15 +153,17 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = { | |||
153 | static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w, | 153 | static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w, |
154 | struct snd_kcontrol *kcontrol, int event) | 154 | struct snd_kcontrol *kcontrol, int event) |
155 | { | 155 | { |
156 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
157 | |||
156 | switch (event) { | 158 | switch (event) { |
157 | case SND_SOC_DAPM_PRE_PMD: | 159 | case SND_SOC_DAPM_PRE_PMD: |
158 | snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1, | 160 | snd_soc_update_bits(codec, CS42L51_POWER_CTL1, |
159 | CS42L51_POWER_CTL1_PDN, | 161 | CS42L51_POWER_CTL1_PDN, |
160 | CS42L51_POWER_CTL1_PDN); | 162 | CS42L51_POWER_CTL1_PDN); |
161 | break; | 163 | break; |
162 | default: | 164 | default: |
163 | case SND_SOC_DAPM_POST_PMD: | 165 | case SND_SOC_DAPM_POST_PMD: |
164 | snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1, | 166 | snd_soc_update_bits(codec, CS42L51_POWER_CTL1, |
165 | CS42L51_POWER_CTL1_PDN, 0); | 167 | CS42L51_POWER_CTL1_PDN, 0); |
166 | break; | 168 | break; |
167 | } | 169 | } |
@@ -558,11 +560,13 @@ error: | |||
558 | } | 560 | } |
559 | EXPORT_SYMBOL_GPL(cs42l51_probe); | 561 | EXPORT_SYMBOL_GPL(cs42l51_probe); |
560 | 562 | ||
561 | static const struct of_device_id cs42l51_of_match[] = { | 563 | const struct of_device_id cs42l51_of_match[] = { |
562 | { .compatible = "cirrus,cs42l51", }, | 564 | { .compatible = "cirrus,cs42l51", }, |
563 | { } | 565 | { } |
564 | }; | 566 | }; |
565 | MODULE_DEVICE_TABLE(of, cs42l51_of_match); | 567 | MODULE_DEVICE_TABLE(of, cs42l51_of_match); |
568 | EXPORT_SYMBOL_GPL(cs42l51_of_match); | ||
569 | |||
566 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); | 570 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); |
567 | MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); | 571 | MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); |
568 | MODULE_LICENSE("GPL"); | 572 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h index 8c55bf384bc6..0ca805492ac4 100644 --- a/sound/soc/codecs/cs42l51.h +++ b/sound/soc/codecs/cs42l51.h | |||
@@ -22,6 +22,7 @@ struct device; | |||
22 | 22 | ||
23 | extern const struct regmap_config cs42l51_regmap; | 23 | extern const struct regmap_config cs42l51_regmap; |
24 | int cs42l51_probe(struct device *dev, struct regmap *regmap); | 24 | int cs42l51_probe(struct device *dev, struct regmap *regmap); |
25 | extern const struct of_device_id cs42l51_of_match[]; | ||
25 | 26 | ||
26 | #define CS42L51_CHIP_ID 0x1B | 27 | #define CS42L51_CHIP_ID 0x1B |
27 | #define CS42L51_CHIP_REV_A 0x00 | 28 | #define CS42L51_CHIP_REV_A 0x00 |
diff --git a/sound/soc/codecs/es8328-i2c.c b/sound/soc/codecs/es8328-i2c.c index aae410d122ee..2d05b5d3a6ce 100644 --- a/sound/soc/codecs/es8328-i2c.c +++ b/sound/soc/codecs/es8328-i2c.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include "es8328.h" | 19 | #include "es8328.h" |
20 | 20 | ||
21 | static const struct i2c_device_id es8328_id[] = { | 21 | static const struct i2c_device_id es8328_id[] = { |
22 | { "everest,es8328", 0 }, | 22 | { "es8328", 0 }, |
23 | { } | 23 | { } |
24 | }; | 24 | }; |
25 | MODULE_DEVICE_TABLE(i2c, es8328_id); | 25 | MODULE_DEVICE_TABLE(i2c, es8328_id); |
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index d519294f57c7..34ed9a91f392 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c | |||
@@ -1311,6 +1311,10 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | |||
1311 | {"MIC1 Input", NULL, "MIC1"}, | 1311 | {"MIC1 Input", NULL, "MIC1"}, |
1312 | {"MIC2 Input", NULL, "MIC2"}, | 1312 | {"MIC2 Input", NULL, "MIC2"}, |
1313 | 1313 | ||
1314 | {"DMICL", NULL, "DMICL_ENA"}, | ||
1315 | {"DMICL", NULL, "DMICR_ENA"}, | ||
1316 | {"DMICR", NULL, "DMICL_ENA"}, | ||
1317 | {"DMICR", NULL, "DMICR_ENA"}, | ||
1314 | {"DMICL", NULL, "AHPF"}, | 1318 | {"DMICL", NULL, "AHPF"}, |
1315 | {"DMICR", NULL, "AHPF"}, | 1319 | {"DMICR", NULL, "AHPF"}, |
1316 | 1320 | ||
@@ -1368,8 +1372,6 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | |||
1368 | {"DMIC Mux", "ADC", "ADCR"}, | 1372 | {"DMIC Mux", "ADC", "ADCR"}, |
1369 | {"DMIC Mux", "DMIC", "DMICL"}, | 1373 | {"DMIC Mux", "DMIC", "DMICL"}, |
1370 | {"DMIC Mux", "DMIC", "DMICR"}, | 1374 | {"DMIC Mux", "DMIC", "DMICR"}, |
1371 | {"DMIC Mux", "DMIC", "DMICL_ENA"}, | ||
1372 | {"DMIC Mux", "DMIC", "DMICR_ENA"}, | ||
1373 | 1375 | ||
1374 | {"LBENL Mux", "Normal", "DMIC Mux"}, | 1376 | {"LBENL Mux", "Normal", "DMIC Mux"}, |
1375 | {"LBENL Mux", "Loopback", "LTENL Mux"}, | 1377 | {"LBENL Mux", "Loopback", "LTENL Mux"}, |
@@ -1395,8 +1397,8 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { | |||
1395 | {"STENL Mux", "Sidetone Left", "DMICL"}, | 1397 | {"STENL Mux", "Sidetone Left", "DMICL"}, |
1396 | {"STENR Mux", "Sidetone Right", "ADCR"}, | 1398 | {"STENR Mux", "Sidetone Right", "ADCR"}, |
1397 | {"STENR Mux", "Sidetone Right", "DMICR"}, | 1399 | {"STENR Mux", "Sidetone Right", "DMICR"}, |
1398 | {"DACL", "NULL", "STENL Mux"}, | 1400 | {"DACL", NULL, "STENL Mux"}, |
1399 | {"DACR", "NULL", "STENL Mux"}, | 1401 | {"DACR", NULL, "STENR Mux"}, |
1400 | 1402 | ||
1401 | {"AIFINL", NULL, "SHDN"}, | 1403 | {"AIFINL", NULL, "SHDN"}, |
1402 | {"AIFINR", NULL, "SHDN"}, | 1404 | {"AIFINR", NULL, "SHDN"}, |
@@ -1941,13 +1943,13 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai, | |||
1941 | * 0x02 (when master clk is 20MHz to 40MHz).. | 1943 | * 0x02 (when master clk is 20MHz to 40MHz).. |
1942 | * 0x03 (when master clk is 40MHz to 60MHz).. | 1944 | * 0x03 (when master clk is 40MHz to 60MHz).. |
1943 | */ | 1945 | */ |
1944 | if ((freq >= 10000000) && (freq < 20000000)) { | 1946 | if ((freq >= 10000000) && (freq <= 20000000)) { |
1945 | snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, | 1947 | snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, |
1946 | M98090_PSCLK_DIV1); | 1948 | M98090_PSCLK_DIV1); |
1947 | } else if ((freq >= 20000000) && (freq < 40000000)) { | 1949 | } else if ((freq > 20000000) && (freq <= 40000000)) { |
1948 | snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, | 1950 | snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, |
1949 | M98090_PSCLK_DIV2); | 1951 | M98090_PSCLK_DIV2); |
1950 | } else if ((freq >= 40000000) && (freq < 60000000)) { | 1952 | } else if ((freq > 40000000) && (freq <= 60000000)) { |
1951 | snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, | 1953 | snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK, |
1952 | M98090_PSCLK_DIV4); | 1954 | M98090_PSCLK_DIV4); |
1953 | } else { | 1955 | } else { |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 0ee6797d5083..01f3cc9c780f 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.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/mutex.h> | ||
19 | #include <sound/core.h> | 20 | #include <sound/core.h> |
20 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
21 | #include <sound/pcm_params.h> | 22 | #include <sound/pcm_params.h> |
@@ -57,6 +58,7 @@ struct max98095_priv { | |||
57 | unsigned int mic2pre; | 58 | unsigned int mic2pre; |
58 | struct snd_soc_jack *headphone_jack; | 59 | struct snd_soc_jack *headphone_jack; |
59 | struct snd_soc_jack *mic_jack; | 60 | struct snd_soc_jack *mic_jack; |
61 | struct mutex lock; | ||
60 | }; | 62 | }; |
61 | 63 | ||
62 | static const struct reg_default max98095_reg_def[] = { | 64 | static const struct reg_default max98095_reg_def[] = { |
@@ -1803,7 +1805,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol, | |||
1803 | regsave = snd_soc_read(codec, M98095_088_CFG_LEVEL); | 1805 | regsave = snd_soc_read(codec, M98095_088_CFG_LEVEL); |
1804 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, 0); | 1806 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, 0); |
1805 | 1807 | ||
1806 | mutex_lock(&codec->mutex); | 1808 | mutex_lock(&max98095->lock); |
1807 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG); | 1809 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG); |
1808 | m98095_eq_band(codec, channel, 0, coef_set->band1); | 1810 | m98095_eq_band(codec, channel, 0, coef_set->band1); |
1809 | m98095_eq_band(codec, channel, 1, coef_set->band2); | 1811 | m98095_eq_band(codec, channel, 1, coef_set->band2); |
@@ -1811,7 +1813,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol, | |||
1811 | m98095_eq_band(codec, channel, 3, coef_set->band4); | 1813 | m98095_eq_band(codec, channel, 3, coef_set->band4); |
1812 | m98095_eq_band(codec, channel, 4, coef_set->band5); | 1814 | m98095_eq_band(codec, channel, 4, coef_set->band5); |
1813 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, 0); | 1815 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, 0); |
1814 | mutex_unlock(&codec->mutex); | 1816 | mutex_unlock(&max98095->lock); |
1815 | 1817 | ||
1816 | /* Restore the original on/off state */ | 1818 | /* Restore the original on/off state */ |
1817 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, regsave); | 1819 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, regsave); |
@@ -1957,12 +1959,12 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol, | |||
1957 | regsave = snd_soc_read(codec, M98095_088_CFG_LEVEL); | 1959 | regsave = snd_soc_read(codec, M98095_088_CFG_LEVEL); |
1958 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, 0); | 1960 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, 0); |
1959 | 1961 | ||
1960 | mutex_lock(&codec->mutex); | 1962 | mutex_lock(&max98095->lock); |
1961 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG); | 1963 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG); |
1962 | m98095_biquad_band(codec, channel, 0, coef_set->band1); | 1964 | m98095_biquad_band(codec, channel, 0, coef_set->band1); |
1963 | m98095_biquad_band(codec, channel, 1, coef_set->band2); | 1965 | m98095_biquad_band(codec, channel, 1, coef_set->band2); |
1964 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, 0); | 1966 | snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, 0); |
1965 | mutex_unlock(&codec->mutex); | 1967 | mutex_unlock(&max98095->lock); |
1966 | 1968 | ||
1967 | /* Restore the original on/off state */ | 1969 | /* Restore the original on/off state */ |
1968 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, regsave); | 1970 | snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, regsave); |
@@ -2395,6 +2397,8 @@ static int max98095_i2c_probe(struct i2c_client *i2c, | |||
2395 | if (max98095 == NULL) | 2397 | if (max98095 == NULL) |
2396 | return -ENOMEM; | 2398 | return -ENOMEM; |
2397 | 2399 | ||
2400 | mutex_init(&max98095->lock); | ||
2401 | |||
2398 | max98095->regmap = devm_regmap_init_i2c(i2c, &max98095_regmap); | 2402 | max98095->regmap = devm_regmap_init_i2c(i2c, &max98095_regmap); |
2399 | if (IS_ERR(max98095->regmap)) { | 2403 | if (IS_ERR(max98095->regmap)) { |
2400 | ret = PTR_ERR(max98095->regmap); | 2404 | ret = PTR_ERR(max98095->regmap); |
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 3fb83bf09768..d16331e0b64d 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -139,6 +139,7 @@ static const struct reg_default rt5645_reg[] = { | |||
139 | { 0x76, 0x000a }, | 139 | { 0x76, 0x000a }, |
140 | { 0x77, 0x0c00 }, | 140 | { 0x77, 0x0c00 }, |
141 | { 0x78, 0x0000 }, | 141 | { 0x78, 0x0000 }, |
142 | { 0x79, 0x0123 }, | ||
142 | { 0x80, 0x0000 }, | 143 | { 0x80, 0x0000 }, |
143 | { 0x81, 0x0000 }, | 144 | { 0x81, 0x0000 }, |
144 | { 0x82, 0x0000 }, | 145 | { 0x82, 0x0000 }, |
@@ -334,6 +335,7 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg) | |||
334 | case RT5645_DMIC_CTRL2: | 335 | case RT5645_DMIC_CTRL2: |
335 | case RT5645_TDM_CTRL_1: | 336 | case RT5645_TDM_CTRL_1: |
336 | case RT5645_TDM_CTRL_2: | 337 | case RT5645_TDM_CTRL_2: |
338 | case RT5645_TDM_CTRL_3: | ||
337 | case RT5645_GLB_CLK: | 339 | case RT5645_GLB_CLK: |
338 | case RT5645_PLL_CTRL1: | 340 | case RT5645_PLL_CTRL1: |
339 | case RT5645_PLL_CTRL2: | 341 | case RT5645_PLL_CTRL2: |
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index ba9d9b4d4857..9bd8b4f63303 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c | |||
@@ -100,18 +100,18 @@ static const struct reg_default rt5670_reg[] = { | |||
100 | { 0x4c, 0x5380 }, | 100 | { 0x4c, 0x5380 }, |
101 | { 0x4f, 0x0073 }, | 101 | { 0x4f, 0x0073 }, |
102 | { 0x52, 0x00d3 }, | 102 | { 0x52, 0x00d3 }, |
103 | { 0x53, 0xf0f0 }, | 103 | { 0x53, 0xf000 }, |
104 | { 0x61, 0x0000 }, | 104 | { 0x61, 0x0000 }, |
105 | { 0x62, 0x0001 }, | 105 | { 0x62, 0x0001 }, |
106 | { 0x63, 0x00c3 }, | 106 | { 0x63, 0x00c3 }, |
107 | { 0x64, 0x0000 }, | 107 | { 0x64, 0x0000 }, |
108 | { 0x65, 0x0000 }, | 108 | { 0x65, 0x0001 }, |
109 | { 0x66, 0x0000 }, | 109 | { 0x66, 0x0000 }, |
110 | { 0x6f, 0x8000 }, | 110 | { 0x6f, 0x8000 }, |
111 | { 0x70, 0x8000 }, | 111 | { 0x70, 0x8000 }, |
112 | { 0x71, 0x8000 }, | 112 | { 0x71, 0x8000 }, |
113 | { 0x72, 0x8000 }, | 113 | { 0x72, 0x8000 }, |
114 | { 0x73, 0x1110 }, | 114 | { 0x73, 0x7770 }, |
115 | { 0x74, 0x0e00 }, | 115 | { 0x74, 0x0e00 }, |
116 | { 0x75, 0x1505 }, | 116 | { 0x75, 0x1505 }, |
117 | { 0x76, 0x0015 }, | 117 | { 0x76, 0x0015 }, |
@@ -125,21 +125,21 @@ static const struct reg_default rt5670_reg[] = { | |||
125 | { 0x83, 0x0000 }, | 125 | { 0x83, 0x0000 }, |
126 | { 0x84, 0x0000 }, | 126 | { 0x84, 0x0000 }, |
127 | { 0x85, 0x0000 }, | 127 | { 0x85, 0x0000 }, |
128 | { 0x86, 0x0008 }, | 128 | { 0x86, 0x0004 }, |
129 | { 0x87, 0x0000 }, | 129 | { 0x87, 0x0000 }, |
130 | { 0x88, 0x0000 }, | 130 | { 0x88, 0x0000 }, |
131 | { 0x89, 0x0000 }, | 131 | { 0x89, 0x0000 }, |
132 | { 0x8a, 0x0000 }, | 132 | { 0x8a, 0x0000 }, |
133 | { 0x8b, 0x0000 }, | 133 | { 0x8b, 0x0000 }, |
134 | { 0x8c, 0x0007 }, | 134 | { 0x8c, 0x0003 }, |
135 | { 0x8d, 0x0000 }, | 135 | { 0x8d, 0x0000 }, |
136 | { 0x8e, 0x0004 }, | 136 | { 0x8e, 0x0004 }, |
137 | { 0x8f, 0x1100 }, | 137 | { 0x8f, 0x1100 }, |
138 | { 0x90, 0x0646 }, | 138 | { 0x90, 0x0646 }, |
139 | { 0x91, 0x0c06 }, | 139 | { 0x91, 0x0c06 }, |
140 | { 0x93, 0x0000 }, | 140 | { 0x93, 0x0000 }, |
141 | { 0x94, 0x0000 }, | 141 | { 0x94, 0x1270 }, |
142 | { 0x95, 0x0000 }, | 142 | { 0x95, 0x1000 }, |
143 | { 0x97, 0x0000 }, | 143 | { 0x97, 0x0000 }, |
144 | { 0x98, 0x0000 }, | 144 | { 0x98, 0x0000 }, |
145 | { 0x99, 0x0000 }, | 145 | { 0x99, 0x0000 }, |
@@ -150,11 +150,11 @@ static const struct reg_default rt5670_reg[] = { | |||
150 | { 0x9e, 0x0400 }, | 150 | { 0x9e, 0x0400 }, |
151 | { 0xae, 0x7000 }, | 151 | { 0xae, 0x7000 }, |
152 | { 0xaf, 0x0000 }, | 152 | { 0xaf, 0x0000 }, |
153 | { 0xb0, 0x6000 }, | 153 | { 0xb0, 0x7000 }, |
154 | { 0xb1, 0x0000 }, | 154 | { 0xb1, 0x0000 }, |
155 | { 0xb2, 0x0000 }, | 155 | { 0xb2, 0x0000 }, |
156 | { 0xb3, 0x001f }, | 156 | { 0xb3, 0x001f }, |
157 | { 0xb4, 0x2206 }, | 157 | { 0xb4, 0x220c }, |
158 | { 0xb5, 0x1f00 }, | 158 | { 0xb5, 0x1f00 }, |
159 | { 0xb6, 0x0000 }, | 159 | { 0xb6, 0x0000 }, |
160 | { 0xb7, 0x0000 }, | 160 | { 0xb7, 0x0000 }, |
@@ -171,25 +171,25 @@ static const struct reg_default rt5670_reg[] = { | |||
171 | { 0xcf, 0x1813 }, | 171 | { 0xcf, 0x1813 }, |
172 | { 0xd0, 0x0690 }, | 172 | { 0xd0, 0x0690 }, |
173 | { 0xd1, 0x1c17 }, | 173 | { 0xd1, 0x1c17 }, |
174 | { 0xd3, 0xb320 }, | 174 | { 0xd3, 0xa220 }, |
175 | { 0xd4, 0x0000 }, | 175 | { 0xd4, 0x0000 }, |
176 | { 0xd6, 0x0400 }, | 176 | { 0xd6, 0x0400 }, |
177 | { 0xd9, 0x0809 }, | 177 | { 0xd9, 0x0809 }, |
178 | { 0xda, 0x0000 }, | 178 | { 0xda, 0x0000 }, |
179 | { 0xdb, 0x0001 }, | 179 | { 0xdb, 0x0001 }, |
180 | { 0xdc, 0x0049 }, | 180 | { 0xdc, 0x0049 }, |
181 | { 0xdd, 0x0009 }, | 181 | { 0xdd, 0x0024 }, |
182 | { 0xe6, 0x8000 }, | 182 | { 0xe6, 0x8000 }, |
183 | { 0xe7, 0x0000 }, | 183 | { 0xe7, 0x0000 }, |
184 | { 0xec, 0xb300 }, | 184 | { 0xec, 0xa200 }, |
185 | { 0xed, 0x0000 }, | 185 | { 0xed, 0x0000 }, |
186 | { 0xee, 0xb300 }, | 186 | { 0xee, 0xa200 }, |
187 | { 0xef, 0x0000 }, | 187 | { 0xef, 0x0000 }, |
188 | { 0xf8, 0x0000 }, | 188 | { 0xf8, 0x0000 }, |
189 | { 0xf9, 0x0000 }, | 189 | { 0xf9, 0x0000 }, |
190 | { 0xfa, 0x8010 }, | 190 | { 0xfa, 0x8010 }, |
191 | { 0xfb, 0x0033 }, | 191 | { 0xfb, 0x0033 }, |
192 | { 0xfc, 0x0080 }, | 192 | { 0xfc, 0x0100 }, |
193 | }; | 193 | }; |
194 | 194 | ||
195 | static bool rt5670_volatile_register(struct device *dev, unsigned int reg) | 195 | static bool rt5670_volatile_register(struct device *dev, unsigned int reg) |
@@ -1877,6 +1877,10 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { | |||
1877 | { "DAC1 MIXR", "DAC1 Switch", "DAC1 R Mux" }, | 1877 | { "DAC1 MIXR", "DAC1 Switch", "DAC1 R Mux" }, |
1878 | { "DAC1 MIXR", NULL, "DAC Stereo1 Filter" }, | 1878 | { "DAC1 MIXR", NULL, "DAC Stereo1 Filter" }, |
1879 | 1879 | ||
1880 | { "DAC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1881 | { "DAC Mono Left Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1882 | { "DAC Mono Right Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1883 | |||
1880 | { "DAC MIX", NULL, "DAC1 MIXL" }, | 1884 | { "DAC MIX", NULL, "DAC1 MIXL" }, |
1881 | { "DAC MIX", NULL, "DAC1 MIXR" }, | 1885 | { "DAC MIX", NULL, "DAC1 MIXR" }, |
1882 | 1886 | ||
@@ -1926,14 +1930,10 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { | |||
1926 | 1930 | ||
1927 | { "DAC L1", NULL, "DAC L1 Power" }, | 1931 | { "DAC L1", NULL, "DAC L1 Power" }, |
1928 | { "DAC L1", NULL, "Stereo DAC MIXL" }, | 1932 | { "DAC L1", NULL, "Stereo DAC MIXL" }, |
1929 | { "DAC L1", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1930 | { "DAC R1", NULL, "DAC R1 Power" }, | 1933 | { "DAC R1", NULL, "DAC R1 Power" }, |
1931 | { "DAC R1", NULL, "Stereo DAC MIXR" }, | 1934 | { "DAC R1", NULL, "Stereo DAC MIXR" }, |
1932 | { "DAC R1", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1933 | { "DAC L2", NULL, "Mono DAC MIXL" }, | 1935 | { "DAC L2", NULL, "Mono DAC MIXL" }, |
1934 | { "DAC L2", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1935 | { "DAC R2", NULL, "Mono DAC MIXR" }, | 1936 | { "DAC R2", NULL, "Mono DAC MIXR" }, |
1936 | { "DAC R2", NULL, "PLL1", is_sys_clk_from_pll }, | ||
1937 | 1937 | ||
1938 | { "OUT MIXL", "BST1 Switch", "BST1" }, | 1938 | { "OUT MIXL", "BST1 Switch", "BST1" }, |
1939 | { "OUT MIXL", "INL Switch", "INL VOL" }, | 1939 | { "OUT MIXL", "INL Switch", "INL VOL" }, |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 6bb77d76561b..dab9b15304af 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -1299,8 +1299,7 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) | |||
1299 | 1299 | ||
1300 | /* enable small pop, introduce 400ms delay in turning off */ | 1300 | /* enable small pop, introduce 400ms delay in turning off */ |
1301 | snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL, | 1301 | snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL, |
1302 | SGTL5000_SMALL_POP, | 1302 | SGTL5000_SMALL_POP, 1); |
1303 | SGTL5000_SMALL_POP); | ||
1304 | 1303 | ||
1305 | /* disable short cut detector */ | 1304 | /* disable short cut detector */ |
1306 | snd_soc_write(codec, SGTL5000_CHIP_SHORT_CTRL, 0); | 1305 | snd_soc_write(codec, SGTL5000_CHIP_SHORT_CTRL, 0); |
diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index 2f8c88931f69..bd7a344bf8c5 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h | |||
@@ -275,7 +275,7 @@ | |||
275 | #define SGTL5000_BIAS_CTRL_MASK 0x000e | 275 | #define SGTL5000_BIAS_CTRL_MASK 0x000e |
276 | #define SGTL5000_BIAS_CTRL_SHIFT 1 | 276 | #define SGTL5000_BIAS_CTRL_SHIFT 1 |
277 | #define SGTL5000_BIAS_CTRL_WIDTH 3 | 277 | #define SGTL5000_BIAS_CTRL_WIDTH 3 |
278 | #define SGTL5000_SMALL_POP 0x0001 | 278 | #define SGTL5000_SMALL_POP 0 |
279 | 279 | ||
280 | /* | 280 | /* |
281 | * SGTL5000_CHIP_MIC_CTRL | 281 | * SGTL5000_CHIP_MIC_CTRL |
diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c index f2de7e049bc6..81a38dd9af1f 100644 --- a/sound/soc/codecs/sigmadsp.c +++ b/sound/soc/codecs/sigmadsp.c | |||
@@ -159,6 +159,13 @@ int _process_sigma_firmware(struct device *dev, | |||
159 | goto done; | 159 | goto done; |
160 | } | 160 | } |
161 | 161 | ||
162 | if (ssfw_head->version != 1) { | ||
163 | dev_err(dev, | ||
164 | "Failed to load firmware: Invalid version %d. Supported firmware versions: 1\n", | ||
165 | ssfw_head->version); | ||
166 | goto done; | ||
167 | } | ||
168 | |||
162 | crc = crc32(0, fw->data + sizeof(*ssfw_head), | 169 | crc = crc32(0, fw->data + sizeof(*ssfw_head), |
163 | fw->size - sizeof(*ssfw_head)); | 170 | fw->size - sizeof(*ssfw_head)); |
164 | pr_debug("%s: crc=%x\n", __func__, crc); | 171 | pr_debug("%s: crc=%x\n", __func__, crc); |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 53b810d23fea..f37a79ec45e6 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
@@ -139,18 +139,19 @@ static const struct snd_kcontrol_new stac9766_snd_ac97_controls[] = { | |||
139 | static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 139 | static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
140 | unsigned int val) | 140 | unsigned int val) |
141 | { | 141 | { |
142 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
142 | u16 *cache = codec->reg_cache; | 143 | u16 *cache = codec->reg_cache; |
143 | 144 | ||
144 | if (reg > AC97_STAC_PAGE0) { | 145 | if (reg > AC97_STAC_PAGE0) { |
145 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); | 146 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
146 | soc_ac97_ops->write(codec->ac97, reg, val); | 147 | soc_ac97_ops->write(ac97, reg, val); |
147 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); | 148 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
148 | return 0; | 149 | return 0; |
149 | } | 150 | } |
150 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) | 151 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) |
151 | return -EIO; | 152 | return -EIO; |
152 | 153 | ||
153 | soc_ac97_ops->write(codec->ac97, reg, val); | 154 | soc_ac97_ops->write(ac97, reg, val); |
154 | cache[reg / 2] = val; | 155 | cache[reg / 2] = val; |
155 | return 0; | 156 | return 0; |
156 | } | 157 | } |
@@ -158,11 +159,12 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
158 | static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, | 159 | static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, |
159 | unsigned int reg) | 160 | unsigned int reg) |
160 | { | 161 | { |
162 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
161 | u16 val = 0, *cache = codec->reg_cache; | 163 | u16 val = 0, *cache = codec->reg_cache; |
162 | 164 | ||
163 | if (reg > AC97_STAC_PAGE0) { | 165 | if (reg > AC97_STAC_PAGE0) { |
164 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); | 166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
165 | val = soc_ac97_ops->read(codec->ac97, reg - AC97_STAC_PAGE0); | 167 | val = soc_ac97_ops->read(ac97, reg - AC97_STAC_PAGE0); |
166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); | 168 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
167 | return val; | 169 | return val; |
168 | } | 170 | } |
@@ -173,7 +175,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, | |||
173 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || | 175 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || |
174 | reg == AC97_VENDOR_ID2) { | 176 | reg == AC97_VENDOR_ID2) { |
175 | 177 | ||
176 | val = soc_ac97_ops->read(codec->ac97, reg); | 178 | val = soc_ac97_ops->read(ac97, reg); |
177 | return val; | 179 | return val; |
178 | } | 180 | } |
179 | return cache[reg / 2]; | 181 | return cache[reg / 2]; |
@@ -240,15 +242,17 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec, | |||
240 | 242 | ||
241 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) | 243 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) |
242 | { | 244 | { |
245 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
246 | |||
243 | if (try_warm && soc_ac97_ops->warm_reset) { | 247 | if (try_warm && soc_ac97_ops->warm_reset) { |
244 | soc_ac97_ops->warm_reset(codec->ac97); | 248 | soc_ac97_ops->warm_reset(ac97); |
245 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) | 249 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) |
246 | return 1; | 250 | return 1; |
247 | } | 251 | } |
248 | 252 | ||
249 | soc_ac97_ops->reset(codec->ac97); | 253 | soc_ac97_ops->reset(ac97); |
250 | if (soc_ac97_ops->warm_reset) | 254 | if (soc_ac97_ops->warm_reset) |
251 | soc_ac97_ops->warm_reset(codec->ac97); | 255 | soc_ac97_ops->warm_reset(ac97); |
252 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) | 256 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) |
253 | return -EIO; | 257 | return -EIO; |
254 | return 0; | 258 | return 0; |
@@ -262,6 +266,7 @@ static int stac9766_codec_suspend(struct snd_soc_codec *codec) | |||
262 | 266 | ||
263 | static int stac9766_codec_resume(struct snd_soc_codec *codec) | 267 | static int stac9766_codec_resume(struct snd_soc_codec *codec) |
264 | { | 268 | { |
269 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
265 | u16 id, reset; | 270 | u16 id, reset; |
266 | 271 | ||
267 | reset = 0; | 272 | reset = 0; |
@@ -271,8 +276,8 @@ reset: | |||
271 | printk(KERN_ERR "stac9766 failed to resume"); | 276 | printk(KERN_ERR "stac9766 failed to resume"); |
272 | return -EIO; | 277 | return -EIO; |
273 | } | 278 | } |
274 | codec->ac97->bus->ops->warm_reset(codec->ac97); | 279 | ac97->bus->ops->warm_reset(ac97); |
275 | id = soc_ac97_ops->read(codec->ac97, AC97_VENDOR_ID2); | 280 | id = soc_ac97_ops->read(ac97, AC97_VENDOR_ID2); |
276 | if (id != 0x4c13) { | 281 | if (id != 0x4c13) { |
277 | stac9766_reset(codec, 0); | 282 | stac9766_reset(codec, 0); |
278 | reset++; | 283 | reset++; |
@@ -294,7 +299,6 @@ static const struct snd_soc_dai_ops stac9766_dai_ops_digital = { | |||
294 | static struct snd_soc_dai_driver stac9766_dai[] = { | 299 | static struct snd_soc_dai_driver stac9766_dai[] = { |
295 | { | 300 | { |
296 | .name = "stac9766-hifi-analog", | 301 | .name = "stac9766-hifi-analog", |
297 | .ac97_control = 1, | ||
298 | 302 | ||
299 | /* stream cababilities */ | 303 | /* stream cababilities */ |
300 | .playback = { | 304 | .playback = { |
@@ -316,7 +320,6 @@ static struct snd_soc_dai_driver stac9766_dai[] = { | |||
316 | }, | 320 | }, |
317 | { | 321 | { |
318 | .name = "stac9766-hifi-IEC958", | 322 | .name = "stac9766-hifi-IEC958", |
319 | .ac97_control = 1, | ||
320 | 323 | ||
321 | /* stream cababilities */ | 324 | /* stream cababilities */ |
322 | .playback = { | 325 | .playback = { |
@@ -334,11 +337,14 @@ static struct snd_soc_dai_driver stac9766_dai[] = { | |||
334 | 337 | ||
335 | static int stac9766_codec_probe(struct snd_soc_codec *codec) | 338 | static int stac9766_codec_probe(struct snd_soc_codec *codec) |
336 | { | 339 | { |
340 | struct snd_ac97 *ac97; | ||
337 | int ret = 0; | 341 | int ret = 0; |
338 | 342 | ||
339 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | 343 | ac97 = snd_soc_new_ac97_codec(codec); |
340 | if (ret < 0) | 344 | if (IS_ERR(ac97)) |
341 | goto codec_err; | 345 | return PTR_ERR(ac97); |
346 | |||
347 | snd_soc_codec_set_drvdata(codec, ac97); | ||
342 | 348 | ||
343 | /* do a cold reset for the controller and then try | 349 | /* do a cold reset for the controller and then try |
344 | * a warm reset followed by an optional cold reset for codec */ | 350 | * a warm reset followed by an optional cold reset for codec */ |
@@ -357,13 +363,15 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) | |||
357 | return 0; | 363 | return 0; |
358 | 364 | ||
359 | codec_err: | 365 | codec_err: |
360 | snd_soc_free_ac97_codec(codec); | 366 | snd_soc_free_ac97_codec(ac97); |
361 | return ret; | 367 | return ret; |
362 | } | 368 | } |
363 | 369 | ||
364 | static int stac9766_codec_remove(struct snd_soc_codec *codec) | 370 | static int stac9766_codec_remove(struct snd_soc_codec *codec) |
365 | { | 371 | { |
366 | snd_soc_free_ac97_codec(codec); | 372 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
373 | |||
374 | snd_soc_free_ac97_codec(ac97); | ||
367 | return 0; | 375 | return 0; |
368 | } | 376 | } |
369 | 377 | ||
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 145fe5b253d4..93de5dd0a7b9 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -911,12 +911,13 @@ static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
911 | } | 911 | } |
912 | aic31xx->p_div = i; | 912 | aic31xx->p_div = i; |
913 | 913 | ||
914 | for (i = 0; aic31xx_divs[i].mclk_p != freq/aic31xx->p_div; i++) { | 914 | for (i = 0; i < ARRAY_SIZE(aic31xx_divs) && |
915 | if (i == ARRAY_SIZE(aic31xx_divs)) { | 915 | aic31xx_divs[i].mclk_p != freq/aic31xx->p_div; i++) |
916 | dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n", | 916 | ; |
917 | __func__, freq); | 917 | if (i == ARRAY_SIZE(aic31xx_divs)) { |
918 | return -EINVAL; | 918 | dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n", |
919 | } | 919 | __func__, freq); |
920 | return -EINVAL; | ||
920 | } | 921 | } |
921 | 922 | ||
922 | /* set clock on MCLK, BCLK, or GPIO1 as PLL input */ | 923 | /* set clock on MCLK, BCLK, or GPIO1 as PLL input */ |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index f60234962527..d78fb8dffc8c 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -619,10 +619,10 @@ static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, | |||
619 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 619 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
620 | uint16_t data; | 620 | uint16_t data; |
621 | 621 | ||
622 | mutex_lock(&codec->mutex); | 622 | mutex_lock(&arizona->dac_comp_lock); |
623 | data = cpu_to_be16(arizona->dac_comp_coeff); | 623 | data = cpu_to_be16(arizona->dac_comp_coeff); |
624 | memcpy(ucontrol->value.bytes.data, &data, sizeof(data)); | 624 | memcpy(ucontrol->value.bytes.data, &data, sizeof(data)); |
625 | mutex_unlock(&codec->mutex); | 625 | mutex_unlock(&arizona->dac_comp_lock); |
626 | 626 | ||
627 | return 0; | 627 | return 0; |
628 | } | 628 | } |
@@ -633,11 +633,11 @@ static int wm5102_out_comp_coeff_put(struct snd_kcontrol *kcontrol, | |||
633 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 633 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
634 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 634 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
635 | 635 | ||
636 | mutex_lock(&codec->mutex); | 636 | mutex_lock(&arizona->dac_comp_lock); |
637 | memcpy(&arizona->dac_comp_coeff, ucontrol->value.bytes.data, | 637 | memcpy(&arizona->dac_comp_coeff, ucontrol->value.bytes.data, |
638 | sizeof(arizona->dac_comp_coeff)); | 638 | sizeof(arizona->dac_comp_coeff)); |
639 | arizona->dac_comp_coeff = be16_to_cpu(arizona->dac_comp_coeff); | 639 | arizona->dac_comp_coeff = be16_to_cpu(arizona->dac_comp_coeff); |
640 | mutex_unlock(&codec->mutex); | 640 | mutex_unlock(&arizona->dac_comp_lock); |
641 | 641 | ||
642 | return 0; | 642 | return 0; |
643 | } | 643 | } |
@@ -648,9 +648,9 @@ static int wm5102_out_comp_switch_get(struct snd_kcontrol *kcontrol, | |||
648 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 648 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
649 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 649 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
650 | 650 | ||
651 | mutex_lock(&codec->mutex); | 651 | mutex_lock(&arizona->dac_comp_lock); |
652 | ucontrol->value.integer.value[0] = arizona->dac_comp_enabled; | 652 | ucontrol->value.integer.value[0] = arizona->dac_comp_enabled; |
653 | mutex_unlock(&codec->mutex); | 653 | mutex_unlock(&arizona->dac_comp_lock); |
654 | 654 | ||
655 | return 0; | 655 | return 0; |
656 | } | 656 | } |
@@ -661,9 +661,9 @@ static int wm5102_out_comp_switch_put(struct snd_kcontrol *kcontrol, | |||
661 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); | 661 | struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); |
662 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); | 662 | struct arizona *arizona = dev_get_drvdata(codec->dev->parent); |
663 | 663 | ||
664 | mutex_lock(&codec->mutex); | 664 | mutex_lock(&arizona->dac_comp_lock); |
665 | arizona->dac_comp_enabled = ucontrol->value.integer.value[0]; | 665 | arizona->dac_comp_enabled = ucontrol->value.integer.value[0]; |
666 | mutex_unlock(&codec->mutex); | 666 | mutex_unlock(&arizona->dac_comp_lock); |
667 | 667 | ||
668 | return 0; | 668 | return 0; |
669 | } | 669 | } |
@@ -1900,6 +1900,8 @@ static int wm5102_probe(struct platform_device *pdev) | |||
1900 | return -ENOMEM; | 1900 | return -ENOMEM; |
1901 | platform_set_drvdata(pdev, wm5102); | 1901 | platform_set_drvdata(pdev, wm5102); |
1902 | 1902 | ||
1903 | mutex_init(&arizona->dac_comp_lock); | ||
1904 | |||
1903 | wm5102->core.arizona = arizona; | 1905 | wm5102->core.arizona = arizona; |
1904 | wm5102->core.num_inputs = 6; | 1906 | wm5102->core.num_inputs = 6; |
1905 | 1907 | ||
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index eebb3280bfad..5dae9a6f8076 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/regulator/consumer.h> | 24 | #include <linux/regulator/consumer.h> |
25 | #include <linux/spi/spi.h> | 25 | #include <linux/spi/spi.h> |
26 | #include <linux/of_device.h> | 26 | #include <linux/of_device.h> |
27 | #include <linux/mutex.h> | ||
27 | #include <sound/core.h> | 28 | #include <sound/core.h> |
28 | #include <sound/pcm.h> | 29 | #include <sound/pcm.h> |
29 | #include <sound/pcm_params.h> | 30 | #include <sound/pcm_params.h> |
@@ -50,6 +51,8 @@ struct wm8731_priv { | |||
50 | int sysclk_type; | 51 | int sysclk_type; |
51 | int playback_fs; | 52 | int playback_fs; |
52 | bool deemph; | 53 | bool deemph; |
54 | |||
55 | struct mutex lock; | ||
53 | }; | 56 | }; |
54 | 57 | ||
55 | 58 | ||
@@ -138,7 +141,7 @@ static int wm8731_put_deemph(struct snd_kcontrol *kcontrol, | |||
138 | if (deemph > 1) | 141 | if (deemph > 1) |
139 | return -EINVAL; | 142 | return -EINVAL; |
140 | 143 | ||
141 | mutex_lock(&codec->mutex); | 144 | mutex_lock(&wm8731->lock); |
142 | if (wm8731->deemph != deemph) { | 145 | if (wm8731->deemph != deemph) { |
143 | wm8731->deemph = deemph; | 146 | wm8731->deemph = deemph; |
144 | 147 | ||
@@ -146,7 +149,7 @@ static int wm8731_put_deemph(struct snd_kcontrol *kcontrol, | |||
146 | 149 | ||
147 | ret = 1; | 150 | ret = 1; |
148 | } | 151 | } |
149 | mutex_unlock(&codec->mutex); | 152 | mutex_unlock(&wm8731->lock); |
150 | 153 | ||
151 | return ret; | 154 | return ret; |
152 | } | 155 | } |
@@ -685,6 +688,8 @@ static int wm8731_spi_probe(struct spi_device *spi) | |||
685 | if (wm8731 == NULL) | 688 | if (wm8731 == NULL) |
686 | return -ENOMEM; | 689 | return -ENOMEM; |
687 | 690 | ||
691 | mutex_init(&wm8731->lock); | ||
692 | |||
688 | wm8731->regmap = devm_regmap_init_spi(spi, &wm8731_regmap); | 693 | wm8731->regmap = devm_regmap_init_spi(spi, &wm8731_regmap); |
689 | if (IS_ERR(wm8731->regmap)) { | 694 | if (IS_ERR(wm8731->regmap)) { |
690 | ret = PTR_ERR(wm8731->regmap); | 695 | ret = PTR_ERR(wm8731->regmap); |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index c038b3e04398..ffbe6df3453a 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/regmap.h> | 26 | #include <linux/regmap.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/irq.h> | 28 | #include <linux/irq.h> |
29 | #include <linux/mutex.h> | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/jack.h> | 31 | #include <sound/jack.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
@@ -123,6 +124,7 @@ struct wm8903_priv { | |||
123 | int sysclk; | 124 | int sysclk; |
124 | int irq; | 125 | int irq; |
125 | 126 | ||
127 | struct mutex lock; | ||
126 | int fs; | 128 | int fs; |
127 | int deemph; | 129 | int deemph; |
128 | 130 | ||
@@ -457,7 +459,7 @@ static int wm8903_put_deemph(struct snd_kcontrol *kcontrol, | |||
457 | if (deemph > 1) | 459 | if (deemph > 1) |
458 | return -EINVAL; | 460 | return -EINVAL; |
459 | 461 | ||
460 | mutex_lock(&codec->mutex); | 462 | mutex_lock(&wm8903->lock); |
461 | if (wm8903->deemph != deemph) { | 463 | if (wm8903->deemph != deemph) { |
462 | wm8903->deemph = deemph; | 464 | wm8903->deemph = deemph; |
463 | 465 | ||
@@ -465,7 +467,7 @@ static int wm8903_put_deemph(struct snd_kcontrol *kcontrol, | |||
465 | 467 | ||
466 | ret = 1; | 468 | ret = 1; |
467 | } | 469 | } |
468 | mutex_unlock(&codec->mutex); | 470 | mutex_unlock(&wm8903->lock); |
469 | 471 | ||
470 | return ret; | 472 | return ret; |
471 | } | 473 | } |
@@ -2023,6 +2025,8 @@ static int wm8903_i2c_probe(struct i2c_client *i2c, | |||
2023 | GFP_KERNEL); | 2025 | GFP_KERNEL); |
2024 | if (wm8903 == NULL) | 2026 | if (wm8903 == NULL) |
2025 | return -ENOMEM; | 2027 | return -ENOMEM; |
2028 | |||
2029 | mutex_init(&wm8903->lock); | ||
2026 | wm8903->dev = &i2c->dev; | 2030 | wm8903->dev = &i2c->dev; |
2027 | 2031 | ||
2028 | wm8903->regmap = devm_regmap_init_i2c(i2c, &wm8903_regmap); | 2032 | wm8903->regmap = devm_regmap_init_i2c(i2c, &wm8903_regmap); |
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 0dada7f0105e..3cbc82b33292 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c | |||
@@ -867,9 +867,9 @@ static void wm8958_enh_eq_loaded(const struct firmware *fw, void *context) | |||
867 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 867 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
868 | 868 | ||
869 | if (fw && (wm8958_dsp2_fw(codec, "ENH_EQ", fw, true) == 0)) { | 869 | if (fw && (wm8958_dsp2_fw(codec, "ENH_EQ", fw, true) == 0)) { |
870 | mutex_lock(&codec->mutex); | 870 | mutex_lock(&wm8994->fw_lock); |
871 | wm8994->enh_eq = fw; | 871 | wm8994->enh_eq = fw; |
872 | mutex_unlock(&codec->mutex); | 872 | mutex_unlock(&wm8994->fw_lock); |
873 | } | 873 | } |
874 | } | 874 | } |
875 | 875 | ||
@@ -879,9 +879,9 @@ static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context) | |||
879 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 879 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
880 | 880 | ||
881 | if (fw && (wm8958_dsp2_fw(codec, "MBC+VSS", fw, true) == 0)) { | 881 | if (fw && (wm8958_dsp2_fw(codec, "MBC+VSS", fw, true) == 0)) { |
882 | mutex_lock(&codec->mutex); | 882 | mutex_lock(&wm8994->fw_lock); |
883 | wm8994->mbc_vss = fw; | 883 | wm8994->mbc_vss = fw; |
884 | mutex_unlock(&codec->mutex); | 884 | mutex_unlock(&wm8994->fw_lock); |
885 | } | 885 | } |
886 | } | 886 | } |
887 | 887 | ||
@@ -891,9 +891,9 @@ static void wm8958_mbc_loaded(const struct firmware *fw, void *context) | |||
891 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 891 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
892 | 892 | ||
893 | if (fw && (wm8958_dsp2_fw(codec, "MBC", fw, true) == 0)) { | 893 | if (fw && (wm8958_dsp2_fw(codec, "MBC", fw, true) == 0)) { |
894 | mutex_lock(&codec->mutex); | 894 | mutex_lock(&wm8994->fw_lock); |
895 | wm8994->mbc = fw; | 895 | wm8994->mbc = fw; |
896 | mutex_unlock(&codec->mutex); | 896 | mutex_unlock(&wm8994->fw_lock); |
897 | } | 897 | } |
898 | } | 898 | } |
899 | 899 | ||
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 9077411e62ce..61ca4a7cb6ea 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/regulator/consumer.h> | 26 | #include <linux/regulator/consumer.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
29 | #include <linux/mutex.h> | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/jack.h> | 31 | #include <sound/jack.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
@@ -67,6 +68,7 @@ struct wm8962_priv { | |||
67 | int fll_fref; | 68 | int fll_fref; |
68 | int fll_fout; | 69 | int fll_fout; |
69 | 70 | ||
71 | struct mutex dsp2_ena_lock; | ||
70 | u16 dsp2_ena; | 72 | u16 dsp2_ena; |
71 | 73 | ||
72 | struct delayed_work mic_work; | 74 | struct delayed_work mic_work; |
@@ -1570,7 +1572,7 @@ static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol, | |||
1570 | int dsp2_running = snd_soc_read(codec, WM8962_DSP2_POWER_MANAGEMENT) & | 1572 | int dsp2_running = snd_soc_read(codec, WM8962_DSP2_POWER_MANAGEMENT) & |
1571 | WM8962_DSP2_ENA; | 1573 | WM8962_DSP2_ENA; |
1572 | 1574 | ||
1573 | mutex_lock(&codec->mutex); | 1575 | mutex_lock(&wm8962->dsp2_ena_lock); |
1574 | 1576 | ||
1575 | if (ucontrol->value.integer.value[0]) | 1577 | if (ucontrol->value.integer.value[0]) |
1576 | wm8962->dsp2_ena |= 1 << shift; | 1578 | wm8962->dsp2_ena |= 1 << shift; |
@@ -1590,7 +1592,7 @@ static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol, | |||
1590 | } | 1592 | } |
1591 | 1593 | ||
1592 | out: | 1594 | out: |
1593 | mutex_unlock(&codec->mutex); | 1595 | mutex_unlock(&wm8962->dsp2_ena_lock); |
1594 | 1596 | ||
1595 | return ret; | 1597 | return ret; |
1596 | } | 1598 | } |
@@ -3557,6 +3559,8 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3557 | if (wm8962 == NULL) | 3559 | if (wm8962 == NULL) |
3558 | return -ENOMEM; | 3560 | return -ENOMEM; |
3559 | 3561 | ||
3562 | mutex_init(&wm8962->dsp2_ena_lock); | ||
3563 | |||
3560 | i2c_set_clientdata(i2c, wm8962); | 3564 | i2c_set_clientdata(i2c, wm8962); |
3561 | 3565 | ||
3562 | INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work); | 3566 | INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work); |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 1fcb9f3f3097..dbca6e0cc93a 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -4457,6 +4457,8 @@ static int wm8994_probe(struct platform_device *pdev) | |||
4457 | return -ENOMEM; | 4457 | return -ENOMEM; |
4458 | platform_set_drvdata(pdev, wm8994); | 4458 | platform_set_drvdata(pdev, wm8994); |
4459 | 4459 | ||
4460 | mutex_init(&wm8994->fw_lock); | ||
4461 | |||
4460 | wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent); | 4462 | wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent); |
4461 | 4463 | ||
4462 | pm_runtime_enable(&pdev->dev); | 4464 | pm_runtime_enable(&pdev->dev); |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 6536f8d45ac6..dd73387b1cc4 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/firmware.h> | 13 | #include <linux/firmware.h> |
14 | #include <linux/completion.h> | 14 | #include <linux/completion.h> |
15 | #include <linux/workqueue.h> | 15 | #include <linux/workqueue.h> |
16 | #include <linux/mutex.h> | ||
16 | 17 | ||
17 | #include "wm_hubs.h" | 18 | #include "wm_hubs.h" |
18 | 19 | ||
@@ -156,6 +157,7 @@ struct wm8994_priv { | |||
156 | unsigned int aif1clk_disable:1; | 157 | unsigned int aif1clk_disable:1; |
157 | unsigned int aif2clk_disable:1; | 158 | unsigned int aif2clk_disable:1; |
158 | 159 | ||
160 | struct mutex fw_lock; | ||
159 | int dsp_active; | 161 | int dsp_active; |
160 | const struct firmware *cur_fw; | 162 | const struct firmware *cur_fw; |
161 | const struct firmware *mbc; | 163 | const struct firmware *mbc; |
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index c0b7f45dfa37..d3a800fa6f06 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
@@ -203,13 +203,14 @@ static const struct snd_soc_dapm_route wm9705_audio_map[] = { | |||
203 | /* We use a register cache to enhance read performance. */ | 203 | /* We use a register cache to enhance read performance. */ |
204 | static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) | 204 | static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) |
205 | { | 205 | { |
206 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
206 | u16 *cache = codec->reg_cache; | 207 | u16 *cache = codec->reg_cache; |
207 | 208 | ||
208 | switch (reg) { | 209 | switch (reg) { |
209 | case AC97_RESET: | 210 | case AC97_RESET: |
210 | case AC97_VENDOR_ID1: | 211 | case AC97_VENDOR_ID1: |
211 | case AC97_VENDOR_ID2: | 212 | case AC97_VENDOR_ID2: |
212 | return soc_ac97_ops->read(codec->ac97, reg); | 213 | return soc_ac97_ops->read(ac97, reg); |
213 | default: | 214 | default: |
214 | reg = reg >> 1; | 215 | reg = reg >> 1; |
215 | 216 | ||
@@ -223,9 +224,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) | |||
223 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 224 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
224 | unsigned int val) | 225 | unsigned int val) |
225 | { | 226 | { |
227 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
226 | u16 *cache = codec->reg_cache; | 228 | u16 *cache = codec->reg_cache; |
227 | 229 | ||
228 | soc_ac97_ops->write(codec->ac97, reg, val); | 230 | soc_ac97_ops->write(ac97, reg, val); |
229 | reg = reg >> 1; | 231 | reg = reg >> 1; |
230 | if (reg < (ARRAY_SIZE(wm9705_reg))) | 232 | if (reg < (ARRAY_SIZE(wm9705_reg))) |
231 | cache[reg] = val; | 233 | cache[reg] = val; |
@@ -263,7 +265,6 @@ static const struct snd_soc_dai_ops wm9705_dai_ops = { | |||
263 | static struct snd_soc_dai_driver wm9705_dai[] = { | 265 | static struct snd_soc_dai_driver wm9705_dai[] = { |
264 | { | 266 | { |
265 | .name = "wm9705-hifi", | 267 | .name = "wm9705-hifi", |
266 | .ac97_control = 1, | ||
267 | .playback = { | 268 | .playback = { |
268 | .stream_name = "HiFi Playback", | 269 | .stream_name = "HiFi Playback", |
269 | .channels_min = 1, | 270 | .channels_min = 1, |
@@ -294,36 +295,41 @@ static struct snd_soc_dai_driver wm9705_dai[] = { | |||
294 | 295 | ||
295 | static int wm9705_reset(struct snd_soc_codec *codec) | 296 | static int wm9705_reset(struct snd_soc_codec *codec) |
296 | { | 297 | { |
298 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
299 | |||
297 | if (soc_ac97_ops->reset) { | 300 | if (soc_ac97_ops->reset) { |
298 | soc_ac97_ops->reset(codec->ac97); | 301 | soc_ac97_ops->reset(ac97); |
299 | if (ac97_read(codec, 0) == wm9705_reg[0]) | 302 | if (ac97_read(codec, 0) == wm9705_reg[0]) |
300 | return 0; /* Success */ | 303 | return 0; /* Success */ |
301 | } | 304 | } |
302 | 305 | ||
306 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); | ||
307 | |||
303 | return -EIO; | 308 | return -EIO; |
304 | } | 309 | } |
305 | 310 | ||
306 | #ifdef CONFIG_PM | 311 | #ifdef CONFIG_PM |
307 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) | 312 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) |
308 | { | 313 | { |
309 | soc_ac97_ops->write(codec->ac97, AC97_POWERDOWN, 0xffff); | 314 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
315 | |||
316 | soc_ac97_ops->write(ac97, AC97_POWERDOWN, 0xffff); | ||
310 | 317 | ||
311 | return 0; | 318 | return 0; |
312 | } | 319 | } |
313 | 320 | ||
314 | static int wm9705_soc_resume(struct snd_soc_codec *codec) | 321 | static int wm9705_soc_resume(struct snd_soc_codec *codec) |
315 | { | 322 | { |
323 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
316 | int i, ret; | 324 | int i, ret; |
317 | u16 *cache = codec->reg_cache; | 325 | u16 *cache = codec->reg_cache; |
318 | 326 | ||
319 | ret = wm9705_reset(codec); | 327 | ret = wm9705_reset(codec); |
320 | if (ret < 0) { | 328 | if (ret < 0) |
321 | printk(KERN_ERR "could not reset AC97 codec\n"); | ||
322 | return ret; | 329 | return ret; |
323 | } | ||
324 | 330 | ||
325 | for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { | 331 | for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { |
326 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); | 332 | soc_ac97_ops->write(ac97, i, cache[i>>1]); |
327 | } | 333 | } |
328 | 334 | ||
329 | return 0; | 335 | return 0; |
@@ -335,31 +341,34 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec) | |||
335 | 341 | ||
336 | static int wm9705_soc_probe(struct snd_soc_codec *codec) | 342 | static int wm9705_soc_probe(struct snd_soc_codec *codec) |
337 | { | 343 | { |
344 | struct snd_ac97 *ac97; | ||
338 | int ret = 0; | 345 | int ret = 0; |
339 | 346 | ||
340 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | 347 | ac97 = snd_soc_new_ac97_codec(codec); |
341 | if (ret < 0) { | 348 | if (IS_ERR(ac97)) { |
342 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); | 349 | ret = PTR_ERR(ac97); |
350 | dev_err(codec->dev, "Failed to register AC97 codec\n"); | ||
343 | return ret; | 351 | return ret; |
344 | } | 352 | } |
345 | 353 | ||
354 | snd_soc_codec_set_drvdata(codec, ac97); | ||
355 | |||
346 | ret = wm9705_reset(codec); | 356 | ret = wm9705_reset(codec); |
347 | if (ret) | 357 | if (ret) |
348 | goto reset_err; | 358 | goto reset_err; |
349 | 359 | ||
350 | snd_soc_add_codec_controls(codec, wm9705_snd_ac97_controls, | ||
351 | ARRAY_SIZE(wm9705_snd_ac97_controls)); | ||
352 | |||
353 | return 0; | 360 | return 0; |
354 | 361 | ||
355 | reset_err: | 362 | reset_err: |
356 | snd_soc_free_ac97_codec(codec); | 363 | snd_soc_free_ac97_codec(ac97); |
357 | return ret; | 364 | return ret; |
358 | } | 365 | } |
359 | 366 | ||
360 | static int wm9705_soc_remove(struct snd_soc_codec *codec) | 367 | static int wm9705_soc_remove(struct snd_soc_codec *codec) |
361 | { | 368 | { |
362 | snd_soc_free_ac97_codec(codec); | 369 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
370 | |||
371 | snd_soc_free_ac97_codec(ac97); | ||
363 | return 0; | 372 | return 0; |
364 | } | 373 | } |
365 | 374 | ||
@@ -374,6 +383,9 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { | |||
374 | .reg_word_size = sizeof(u16), | 383 | .reg_word_size = sizeof(u16), |
375 | .reg_cache_step = 2, | 384 | .reg_cache_step = 2, |
376 | .reg_cache_default = wm9705_reg, | 385 | .reg_cache_default = wm9705_reg, |
386 | |||
387 | .controls = wm9705_snd_ac97_controls, | ||
388 | .num_controls = ARRAY_SIZE(wm9705_snd_ac97_controls), | ||
377 | .dapm_widgets = wm9705_dapm_widgets, | 389 | .dapm_widgets = wm9705_dapm_widgets, |
378 | .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), | 390 | .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), |
379 | .dapm_routes = wm9705_audio_map, | 391 | .dapm_routes = wm9705_audio_map, |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index c5eb746087b4..52a211be5b47 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -23,6 +23,12 @@ | |||
23 | #include <sound/tlv.h> | 23 | #include <sound/tlv.h> |
24 | #include "wm9712.h" | 24 | #include "wm9712.h" |
25 | 25 | ||
26 | struct wm9712_priv { | ||
27 | struct snd_ac97 *ac97; | ||
28 | unsigned int hp_mixer[2]; | ||
29 | struct mutex lock; | ||
30 | }; | ||
31 | |||
26 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 32 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
27 | unsigned int reg); | 33 | unsigned int reg); |
28 | static int ac97_write(struct snd_soc_codec *codec, | 34 | static int ac97_write(struct snd_soc_codec *codec, |
@@ -48,12 +54,10 @@ static const u16 wm9712_reg[] = { | |||
48 | 0x0000, 0x0000, 0x0000, 0x0000, /* 6e */ | 54 | 0x0000, 0x0000, 0x0000, 0x0000, /* 6e */ |
49 | 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */ | 55 | 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */ |
50 | 0x0001, 0x0000, 0x574d, 0x4c12, /* 7e */ | 56 | 0x0001, 0x0000, 0x574d, 0x4c12, /* 7e */ |
51 | 0x0000, 0x0000 /* virtual hp mixers */ | ||
52 | }; | 57 | }; |
53 | 58 | ||
54 | /* virtual HP mixers regs */ | 59 | #define HPL_MIXER 0x0 |
55 | #define HPL_MIXER 0x80 | 60 | #define HPR_MIXER 0x1 |
56 | #define HPR_MIXER 0x82 | ||
57 | 61 | ||
58 | static const char *wm9712_alc_select[] = {"None", "Left", "Right", "Stereo"}; | 62 | static const char *wm9712_alc_select[] = {"None", "Left", "Right", "Stereo"}; |
59 | static const char *wm9712_alc_mux[] = {"Stereo", "Left", "Right", "None"}; | 63 | static const char *wm9712_alc_mux[] = {"Stereo", "Left", "Right", "None"}; |
@@ -157,75 +161,108 @@ SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC, 0, 31, 1, main_tlv), | |||
157 | SOC_SINGLE_TLV("Mic Boost Volume", AC97_MIC, 7, 1, 0, boost_tlv), | 161 | SOC_SINGLE_TLV("Mic Boost Volume", AC97_MIC, 7, 1, 0, boost_tlv), |
158 | }; | 162 | }; |
159 | 163 | ||
164 | static const unsigned int wm9712_mixer_mute_regs[] = { | ||
165 | AC97_VIDEO, | ||
166 | AC97_PCM, | ||
167 | AC97_LINE, | ||
168 | AC97_PHONE, | ||
169 | AC97_CD, | ||
170 | AC97_PC_BEEP, | ||
171 | }; | ||
172 | |||
160 | /* We have to create a fake left and right HP mixers because | 173 | /* We have to create a fake left and right HP mixers because |
161 | * the codec only has a single control that is shared by both channels. | 174 | * the codec only has a single control that is shared by both channels. |
162 | * This makes it impossible to determine the audio path. | 175 | * This makes it impossible to determine the audio path. |
163 | */ | 176 | */ |
164 | static int mixer_event(struct snd_soc_dapm_widget *w, | 177 | static int wm9712_hp_mixer_put(struct snd_kcontrol *kcontrol, |
165 | struct snd_kcontrol *k, int event) | 178 | struct snd_ctl_elem_value *ucontrol) |
166 | { | 179 | { |
167 | u16 l, r, beep, line, phone, mic, pcm, aux; | 180 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
168 | 181 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | |
169 | l = ac97_read(w->codec, HPL_MIXER); | 182 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); |
170 | r = ac97_read(w->codec, HPR_MIXER); | 183 | unsigned int val = ucontrol->value.enumerated.item[0]; |
171 | beep = ac97_read(w->codec, AC97_PC_BEEP); | 184 | struct soc_mixer_control *mc = |
172 | mic = ac97_read(w->codec, AC97_VIDEO); | 185 | (struct soc_mixer_control *)kcontrol->private_value; |
173 | phone = ac97_read(w->codec, AC97_PHONE); | 186 | unsigned int mixer, mask, shift, old; |
174 | line = ac97_read(w->codec, AC97_LINE); | 187 | struct snd_soc_dapm_update update; |
175 | pcm = ac97_read(w->codec, AC97_PCM); | 188 | bool change; |
176 | aux = ac97_read(w->codec, AC97_CD); | 189 | |
177 | 190 | mixer = mc->shift >> 8; | |
178 | if (l & 0x1 || r & 0x1) | 191 | shift = mc->shift & 0xff; |
179 | ac97_write(w->codec, AC97_VIDEO, mic & 0x7fff); | 192 | mask = 1 << shift; |
193 | |||
194 | mutex_lock(&wm9712->lock); | ||
195 | old = wm9712->hp_mixer[mixer]; | ||
196 | if (ucontrol->value.enumerated.item[0]) | ||
197 | wm9712->hp_mixer[mixer] |= mask; | ||
180 | else | 198 | else |
181 | ac97_write(w->codec, AC97_VIDEO, mic | 0x8000); | 199 | wm9712->hp_mixer[mixer] &= ~mask; |
200 | |||
201 | change = old != wm9712->hp_mixer[mixer]; | ||
202 | if (change) { | ||
203 | update.kcontrol = kcontrol; | ||
204 | update.reg = wm9712_mixer_mute_regs[shift]; | ||
205 | update.mask = 0x8000; | ||
206 | if ((wm9712->hp_mixer[0] & mask) || | ||
207 | (wm9712->hp_mixer[1] & mask)) | ||
208 | update.val = 0x0; | ||
209 | else | ||
210 | update.val = 0x8000; | ||
211 | |||
212 | snd_soc_dapm_mixer_update_power(dapm, kcontrol, val, | ||
213 | &update); | ||
214 | } | ||
182 | 215 | ||
183 | if (l & 0x2 || r & 0x2) | 216 | mutex_unlock(&wm9712->lock); |
184 | ac97_write(w->codec, AC97_PCM, pcm & 0x7fff); | ||
185 | else | ||
186 | ac97_write(w->codec, AC97_PCM, pcm | 0x8000); | ||
187 | 217 | ||
188 | if (l & 0x4 || r & 0x4) | 218 | return change; |
189 | ac97_write(w->codec, AC97_LINE, line & 0x7fff); | 219 | } |
190 | else | ||
191 | ac97_write(w->codec, AC97_LINE, line | 0x8000); | ||
192 | 220 | ||
193 | if (l & 0x8 || r & 0x8) | 221 | static int wm9712_hp_mixer_get(struct snd_kcontrol *kcontrol, |
194 | ac97_write(w->codec, AC97_PHONE, phone & 0x7fff); | 222 | struct snd_ctl_elem_value *ucontrol) |
195 | else | 223 | { |
196 | ac97_write(w->codec, AC97_PHONE, phone | 0x8000); | 224 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
225 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
226 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
227 | struct soc_mixer_control *mc = | ||
228 | (struct soc_mixer_control *)kcontrol->private_value; | ||
229 | unsigned int shift, mixer; | ||
197 | 230 | ||
198 | if (l & 0x10 || r & 0x10) | 231 | mixer = mc->shift >> 8; |
199 | ac97_write(w->codec, AC97_CD, aux & 0x7fff); | 232 | shift = mc->shift & 0xff; |
200 | else | ||
201 | ac97_write(w->codec, AC97_CD, aux | 0x8000); | ||
202 | 233 | ||
203 | if (l & 0x20 || r & 0x20) | 234 | ucontrol->value.enumerated.item[0] = |
204 | ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff); | 235 | (wm9712->hp_mixer[mixer] >> shift) & 1; |
205 | else | ||
206 | ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000); | ||
207 | 236 | ||
208 | return 0; | 237 | return 0; |
209 | } | 238 | } |
210 | 239 | ||
240 | #define WM9712_HP_MIXER_CTRL(xname, xmixer, xshift) { \ | ||
241 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
242 | .info = snd_soc_info_volsw, \ | ||
243 | .get = wm9712_hp_mixer_get, .put = wm9712_hp_mixer_put, \ | ||
244 | .private_value = SOC_SINGLE_VALUE(SND_SOC_NOPM, \ | ||
245 | (xmixer << 8) | xshift, 1, 0, 0) \ | ||
246 | } | ||
247 | |||
211 | /* Left Headphone Mixers */ | 248 | /* Left Headphone Mixers */ |
212 | static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = { | 249 | static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = { |
213 | SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPL_MIXER, 5, 1, 0), | 250 | WM9712_HP_MIXER_CTRL("PCBeep Bypass Switch", HPL_MIXER, 5), |
214 | SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 4, 1, 0), | 251 | WM9712_HP_MIXER_CTRL("Aux Playback Switch", HPL_MIXER, 4), |
215 | SOC_DAPM_SINGLE("Phone Bypass Switch", HPL_MIXER, 3, 1, 0), | 252 | WM9712_HP_MIXER_CTRL("Phone Bypass Switch", HPL_MIXER, 3), |
216 | SOC_DAPM_SINGLE("Line Bypass Switch", HPL_MIXER, 2, 1, 0), | 253 | WM9712_HP_MIXER_CTRL("Line Bypass Switch", HPL_MIXER, 2), |
217 | SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 1, 1, 0), | 254 | WM9712_HP_MIXER_CTRL("PCM Playback Switch", HPL_MIXER, 1), |
218 | SOC_DAPM_SINGLE("Mic Sidetone Switch", HPL_MIXER, 0, 1, 0), | 255 | WM9712_HP_MIXER_CTRL("Mic Sidetone Switch", HPL_MIXER, 0), |
219 | }; | 256 | }; |
220 | 257 | ||
221 | /* Right Headphone Mixers */ | 258 | /* Right Headphone Mixers */ |
222 | static const struct snd_kcontrol_new wm9712_hpr_mixer_controls[] = { | 259 | static const struct snd_kcontrol_new wm9712_hpr_mixer_controls[] = { |
223 | SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPR_MIXER, 5, 1, 0), | 260 | WM9712_HP_MIXER_CTRL("PCBeep Bypass Switch", HPR_MIXER, 5), |
224 | SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 4, 1, 0), | 261 | WM9712_HP_MIXER_CTRL("Aux Playback Switch", HPR_MIXER, 4), |
225 | SOC_DAPM_SINGLE("Phone Bypass Switch", HPR_MIXER, 3, 1, 0), | 262 | WM9712_HP_MIXER_CTRL("Phone Bypass Switch", HPR_MIXER, 3), |
226 | SOC_DAPM_SINGLE("Line Bypass Switch", HPR_MIXER, 2, 1, 0), | 263 | WM9712_HP_MIXER_CTRL("Line Bypass Switch", HPR_MIXER, 2), |
227 | SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 1, 1, 0), | 264 | WM9712_HP_MIXER_CTRL("PCM Playback Switch", HPR_MIXER, 1), |
228 | SOC_DAPM_SINGLE("Mic Sidetone Switch", HPR_MIXER, 0, 1, 0), | 265 | WM9712_HP_MIXER_CTRL("Mic Sidetone Switch", HPR_MIXER, 0), |
229 | }; | 266 | }; |
230 | 267 | ||
231 | /* Speaker Mixer */ | 268 | /* Speaker Mixer */ |
@@ -299,12 +336,10 @@ SND_SOC_DAPM_MUX("Right Mic Select Source", SND_SOC_NOPM, 0, 0, | |||
299 | SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0, | 336 | SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0, |
300 | &wm9712_diff_sel_controls), | 337 | &wm9712_diff_sel_controls), |
301 | SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), | 338 | SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), |
302 | SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_INT_PAGING, 9, 1, | 339 | SND_SOC_DAPM_MIXER("Left HP Mixer", AC97_INT_PAGING, 9, 1, |
303 | &wm9712_hpl_mixer_controls[0], ARRAY_SIZE(wm9712_hpl_mixer_controls), | 340 | &wm9712_hpl_mixer_controls[0], ARRAY_SIZE(wm9712_hpl_mixer_controls)), |
304 | mixer_event, SND_SOC_DAPM_POST_REG), | 341 | SND_SOC_DAPM_MIXER("Right HP Mixer", AC97_INT_PAGING, 8, 1, |
305 | SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_INT_PAGING, 8, 1, | 342 | &wm9712_hpr_mixer_controls[0], ARRAY_SIZE(wm9712_hpr_mixer_controls)), |
306 | &wm9712_hpr_mixer_controls[0], ARRAY_SIZE(wm9712_hpr_mixer_controls), | ||
307 | mixer_event, SND_SOC_DAPM_POST_REG), | ||
308 | SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAGING, 6, 1, | 343 | SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAGING, 6, 1, |
309 | &wm9712_phone_mixer_controls[0], ARRAY_SIZE(wm9712_phone_mixer_controls)), | 344 | &wm9712_phone_mixer_controls[0], ARRAY_SIZE(wm9712_phone_mixer_controls)), |
310 | SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_PAGING, 7, 1, | 345 | SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_PAGING, 7, 1, |
@@ -450,12 +485,13 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = { | |||
450 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 485 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
451 | unsigned int reg) | 486 | unsigned int reg) |
452 | { | 487 | { |
488 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
453 | u16 *cache = codec->reg_cache; | 489 | u16 *cache = codec->reg_cache; |
454 | 490 | ||
455 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || | 491 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
456 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || | 492 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
457 | reg == AC97_REC_GAIN) | 493 | reg == AC97_REC_GAIN) |
458 | return soc_ac97_ops->read(codec->ac97, reg); | 494 | return soc_ac97_ops->read(wm9712->ac97, reg); |
459 | else { | 495 | else { |
460 | reg = reg >> 1; | 496 | reg = reg >> 1; |
461 | 497 | ||
@@ -469,10 +505,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
469 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 505 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
470 | unsigned int val) | 506 | unsigned int val) |
471 | { | 507 | { |
508 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
472 | u16 *cache = codec->reg_cache; | 509 | u16 *cache = codec->reg_cache; |
473 | 510 | ||
474 | if (reg < 0x7c) | 511 | soc_ac97_ops->write(wm9712->ac97, reg, val); |
475 | soc_ac97_ops->write(codec->ac97, reg, val); | ||
476 | reg = reg >> 1; | 512 | reg = reg >> 1; |
477 | if (reg < (ARRAY_SIZE(wm9712_reg))) | 513 | if (reg < (ARRAY_SIZE(wm9712_reg))) |
478 | cache[reg] = val; | 514 | cache[reg] = val; |
@@ -532,7 +568,6 @@ static const struct snd_soc_dai_ops wm9712_dai_ops_aux = { | |||
532 | static struct snd_soc_dai_driver wm9712_dai[] = { | 568 | static struct snd_soc_dai_driver wm9712_dai[] = { |
533 | { | 569 | { |
534 | .name = "wm9712-hifi", | 570 | .name = "wm9712-hifi", |
535 | .ac97_control = 1, | ||
536 | .playback = { | 571 | .playback = { |
537 | .stream_name = "HiFi Playback", | 572 | .stream_name = "HiFi Playback", |
538 | .channels_min = 1, | 573 | .channels_min = 1, |
@@ -581,21 +616,23 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec, | |||
581 | 616 | ||
582 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) | 617 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) |
583 | { | 618 | { |
619 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
620 | |||
584 | if (try_warm && soc_ac97_ops->warm_reset) { | 621 | if (try_warm && soc_ac97_ops->warm_reset) { |
585 | soc_ac97_ops->warm_reset(codec->ac97); | 622 | soc_ac97_ops->warm_reset(wm9712->ac97); |
586 | if (ac97_read(codec, 0) == wm9712_reg[0]) | 623 | if (ac97_read(codec, 0) == wm9712_reg[0]) |
587 | return 1; | 624 | return 1; |
588 | } | 625 | } |
589 | 626 | ||
590 | soc_ac97_ops->reset(codec->ac97); | 627 | soc_ac97_ops->reset(wm9712->ac97); |
591 | if (soc_ac97_ops->warm_reset) | 628 | if (soc_ac97_ops->warm_reset) |
592 | soc_ac97_ops->warm_reset(codec->ac97); | 629 | soc_ac97_ops->warm_reset(wm9712->ac97); |
593 | if (ac97_read(codec, 0) != wm9712_reg[0]) | 630 | if (ac97_read(codec, 0) != wm9712_reg[0]) |
594 | goto err; | 631 | goto err; |
595 | return 0; | 632 | return 0; |
596 | 633 | ||
597 | err: | 634 | err: |
598 | printk(KERN_ERR "WM9712 AC97 reset failed\n"); | 635 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); |
599 | return -EIO; | 636 | return -EIO; |
600 | } | 637 | } |
601 | 638 | ||
@@ -607,14 +644,13 @@ static int wm9712_soc_suspend(struct snd_soc_codec *codec) | |||
607 | 644 | ||
608 | static int wm9712_soc_resume(struct snd_soc_codec *codec) | 645 | static int wm9712_soc_resume(struct snd_soc_codec *codec) |
609 | { | 646 | { |
647 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
610 | int i, ret; | 648 | int i, ret; |
611 | u16 *cache = codec->reg_cache; | 649 | u16 *cache = codec->reg_cache; |
612 | 650 | ||
613 | ret = wm9712_reset(codec, 1); | 651 | ret = wm9712_reset(codec, 1); |
614 | if (ret < 0) { | 652 | if (ret < 0) |
615 | printk(KERN_ERR "could not reset AC97 codec\n"); | ||
616 | return ret; | 653 | return ret; |
617 | } | ||
618 | 654 | ||
619 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 655 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
620 | 656 | ||
@@ -624,7 +660,7 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) | |||
624 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || | 660 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || |
625 | (i > 0x58 && i != 0x5c)) | 661 | (i > 0x58 && i != 0x5c)) |
626 | continue; | 662 | continue; |
627 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); | 663 | soc_ac97_ops->write(wm9712->ac97, i, cache[i>>1]); |
628 | } | 664 | } |
629 | } | 665 | } |
630 | 666 | ||
@@ -633,37 +669,37 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) | |||
633 | 669 | ||
634 | static int wm9712_soc_probe(struct snd_soc_codec *codec) | 670 | static int wm9712_soc_probe(struct snd_soc_codec *codec) |
635 | { | 671 | { |
672 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
636 | int ret = 0; | 673 | int ret = 0; |
637 | 674 | ||
638 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | 675 | wm9712->ac97 = snd_soc_new_ac97_codec(codec); |
639 | if (ret < 0) { | 676 | if (IS_ERR(wm9712->ac97)) { |
640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); | 677 | ret = PTR_ERR(wm9712->ac97); |
678 | dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret); | ||
641 | return ret; | 679 | return ret; |
642 | } | 680 | } |
643 | 681 | ||
644 | ret = wm9712_reset(codec, 0); | 682 | ret = wm9712_reset(codec, 0); |
645 | if (ret < 0) { | 683 | if (ret < 0) |
646 | printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); | ||
647 | goto reset_err; | 684 | goto reset_err; |
648 | } | ||
649 | 685 | ||
650 | /* set alc mux to none */ | 686 | /* set alc mux to none */ |
651 | ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); | 687 | ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); |
652 | 688 | ||
653 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 689 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
654 | snd_soc_add_codec_controls(codec, wm9712_snd_ac97_controls, | ||
655 | ARRAY_SIZE(wm9712_snd_ac97_controls)); | ||
656 | 690 | ||
657 | return 0; | 691 | return 0; |
658 | 692 | ||
659 | reset_err: | 693 | reset_err: |
660 | snd_soc_free_ac97_codec(codec); | 694 | snd_soc_free_ac97_codec(wm9712->ac97); |
661 | return ret; | 695 | return ret; |
662 | } | 696 | } |
663 | 697 | ||
664 | static int wm9712_soc_remove(struct snd_soc_codec *codec) | 698 | static int wm9712_soc_remove(struct snd_soc_codec *codec) |
665 | { | 699 | { |
666 | snd_soc_free_ac97_codec(codec); | 700 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); |
701 | |||
702 | snd_soc_free_ac97_codec(wm9712->ac97); | ||
667 | return 0; | 703 | return 0; |
668 | } | 704 | } |
669 | 705 | ||
@@ -679,6 +715,9 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { | |||
679 | .reg_word_size = sizeof(u16), | 715 | .reg_word_size = sizeof(u16), |
680 | .reg_cache_step = 2, | 716 | .reg_cache_step = 2, |
681 | .reg_cache_default = wm9712_reg, | 717 | .reg_cache_default = wm9712_reg, |
718 | |||
719 | .controls = wm9712_snd_ac97_controls, | ||
720 | .num_controls = ARRAY_SIZE(wm9712_snd_ac97_controls), | ||
682 | .dapm_widgets = wm9712_dapm_widgets, | 721 | .dapm_widgets = wm9712_dapm_widgets, |
683 | .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets), | 722 | .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets), |
684 | .dapm_routes = wm9712_audio_map, | 723 | .dapm_routes = wm9712_audio_map, |
@@ -687,6 +726,16 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { | |||
687 | 726 | ||
688 | static int wm9712_probe(struct platform_device *pdev) | 727 | static int wm9712_probe(struct platform_device *pdev) |
689 | { | 728 | { |
729 | struct wm9712_priv *wm9712; | ||
730 | |||
731 | wm9712 = devm_kzalloc(&pdev->dev, sizeof(*wm9712), GFP_KERNEL); | ||
732 | if (wm9712 == NULL) | ||
733 | return -ENOMEM; | ||
734 | |||
735 | mutex_init(&wm9712->lock); | ||
736 | |||
737 | platform_set_drvdata(pdev, wm9712); | ||
738 | |||
690 | return snd_soc_register_codec(&pdev->dev, | 739 | return snd_soc_register_codec(&pdev->dev, |
691 | &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai)); | 740 | &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai)); |
692 | } | 741 | } |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index bddee30a4bc7..6c95d98b0eb1 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -30,7 +30,10 @@ | |||
30 | #include "wm9713.h" | 30 | #include "wm9713.h" |
31 | 31 | ||
32 | struct wm9713_priv { | 32 | struct wm9713_priv { |
33 | struct snd_ac97 *ac97; | ||
33 | u32 pll_in; /* PLL input frequency */ | 34 | u32 pll_in; /* PLL input frequency */ |
35 | unsigned int hp_mixer[2]; | ||
36 | struct mutex lock; | ||
34 | }; | 37 | }; |
35 | 38 | ||
36 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 39 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
@@ -59,13 +62,10 @@ static const u16 wm9713_reg[] = { | |||
59 | 0x0000, 0x0000, 0x0000, 0x0000, | 62 | 0x0000, 0x0000, 0x0000, 0x0000, |
60 | 0x0000, 0x0000, 0x0000, 0x0006, | 63 | 0x0000, 0x0000, 0x0000, 0x0006, |
61 | 0x0001, 0x0000, 0x574d, 0x4c13, | 64 | 0x0001, 0x0000, 0x574d, 0x4c13, |
62 | 0x0000, 0x0000, 0x0000 | ||
63 | }; | 65 | }; |
64 | 66 | ||
65 | /* virtual HP mixers regs */ | 67 | #define HPL_MIXER 0 |
66 | #define HPL_MIXER 0x80 | 68 | #define HPR_MIXER 1 |
67 | #define HPR_MIXER 0x82 | ||
68 | #define MICB_MUX 0x82 | ||
69 | 69 | ||
70 | static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"}; | 70 | static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"}; |
71 | static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"}; | 71 | static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"}; |
@@ -110,7 +110,7 @@ SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 10, 8, wm9713_dac_inv), /* dac invert 2 15 */ | |||
110 | SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */ | 110 | SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */ |
111 | SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */ | 111 | SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */ |
112 | SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */ | 112 | SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */ |
113 | SOC_ENUM_SINGLE(MICB_MUX, 0, 2, wm9713_micb_select), /* mic selection 19 */ | 113 | SOC_ENUM_SINGLE_VIRT(2, wm9713_micb_select), /* mic selection 19 */ |
114 | }; | 114 | }; |
115 | 115 | ||
116 | static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0); | 116 | static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0); |
@@ -234,6 +234,14 @@ static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w, | |||
234 | return 0; | 234 | return 0; |
235 | } | 235 | } |
236 | 236 | ||
237 | static const unsigned int wm9713_mixer_mute_regs[] = { | ||
238 | AC97_PC_BEEP, | ||
239 | AC97_MASTER_TONE, | ||
240 | AC97_PHONE, | ||
241 | AC97_REC_SEL, | ||
242 | AC97_PCM, | ||
243 | AC97_AUX, | ||
244 | }; | ||
237 | 245 | ||
238 | /* We have to create a fake left and right HP mixers because | 246 | /* We have to create a fake left and right HP mixers because |
239 | * the codec only has a single control that is shared by both channels. | 247 | * the codec only has a single control that is shared by both channels. |
@@ -241,73 +249,95 @@ static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w, | |||
241 | * register map, thus we add a new (virtual) register to help determine the | 249 | * register map, thus we add a new (virtual) register to help determine the |
242 | * audio route within the device. | 250 | * audio route within the device. |
243 | */ | 251 | */ |
244 | static int mixer_event(struct snd_soc_dapm_widget *w, | 252 | static int wm9713_hp_mixer_put(struct snd_kcontrol *kcontrol, |
245 | struct snd_kcontrol *kcontrol, int event) | 253 | struct snd_ctl_elem_value *ucontrol) |
246 | { | 254 | { |
247 | u16 l, r, beep, tone, phone, rec, pcm, aux; | 255 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
248 | 256 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | |
249 | l = ac97_read(w->codec, HPL_MIXER); | 257 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
250 | r = ac97_read(w->codec, HPR_MIXER); | 258 | unsigned int val = ucontrol->value.enumerated.item[0]; |
251 | beep = ac97_read(w->codec, AC97_PC_BEEP); | 259 | struct soc_mixer_control *mc = |
252 | tone = ac97_read(w->codec, AC97_MASTER_TONE); | 260 | (struct soc_mixer_control *)kcontrol->private_value; |
253 | phone = ac97_read(w->codec, AC97_PHONE); | 261 | unsigned int mixer, mask, shift, old; |
254 | rec = ac97_read(w->codec, AC97_REC_SEL); | 262 | struct snd_soc_dapm_update update; |
255 | pcm = ac97_read(w->codec, AC97_PCM); | 263 | bool change; |
256 | aux = ac97_read(w->codec, AC97_AUX); | 264 | |
257 | 265 | mixer = mc->shift >> 8; | |
258 | if (event & SND_SOC_DAPM_PRE_REG) | 266 | shift = mc->shift & 0xff; |
259 | return 0; | 267 | mask = (1 << shift); |
260 | if ((l & 0x1) || (r & 0x1)) | 268 | |
261 | ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff); | 269 | mutex_lock(&wm9713->lock); |
270 | old = wm9713->hp_mixer[mixer]; | ||
271 | if (ucontrol->value.enumerated.item[0]) | ||
272 | wm9713->hp_mixer[mixer] |= mask; | ||
262 | else | 273 | else |
263 | ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000); | 274 | wm9713->hp_mixer[mixer] &= ~mask; |
275 | |||
276 | change = old != wm9713->hp_mixer[mixer]; | ||
277 | if (change) { | ||
278 | update.kcontrol = kcontrol; | ||
279 | update.reg = wm9713_mixer_mute_regs[shift]; | ||
280 | update.mask = 0x8000; | ||
281 | if ((wm9713->hp_mixer[0] & mask) || | ||
282 | (wm9713->hp_mixer[1] & mask)) | ||
283 | update.val = 0x0; | ||
284 | else | ||
285 | update.val = 0x8000; | ||
286 | |||
287 | snd_soc_dapm_mixer_update_power(dapm, kcontrol, val, | ||
288 | &update); | ||
289 | } | ||
264 | 290 | ||
265 | if ((l & 0x2) || (r & 0x2)) | 291 | mutex_unlock(&wm9713->lock); |
266 | ac97_write(w->codec, AC97_MASTER_TONE, tone & 0x7fff); | ||
267 | else | ||
268 | ac97_write(w->codec, AC97_MASTER_TONE, tone | 0x8000); | ||
269 | 292 | ||
270 | if ((l & 0x4) || (r & 0x4)) | 293 | return change; |
271 | ac97_write(w->codec, AC97_PHONE, phone & 0x7fff); | 294 | } |
272 | else | ||
273 | ac97_write(w->codec, AC97_PHONE, phone | 0x8000); | ||
274 | 295 | ||
275 | if ((l & 0x8) || (r & 0x8)) | 296 | static int wm9713_hp_mixer_get(struct snd_kcontrol *kcontrol, |
276 | ac97_write(w->codec, AC97_REC_SEL, rec & 0x7fff); | 297 | struct snd_ctl_elem_value *ucontrol) |
277 | else | 298 | { |
278 | ac97_write(w->codec, AC97_REC_SEL, rec | 0x8000); | 299 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
300 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
301 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
302 | struct soc_mixer_control *mc = | ||
303 | (struct soc_mixer_control *)kcontrol->private_value; | ||
304 | unsigned int mixer, shift; | ||
279 | 305 | ||
280 | if ((l & 0x10) || (r & 0x10)) | 306 | mixer = mc->shift >> 8; |
281 | ac97_write(w->codec, AC97_PCM, pcm & 0x7fff); | 307 | shift = mc->shift & 0xff; |
282 | else | ||
283 | ac97_write(w->codec, AC97_PCM, pcm | 0x8000); | ||
284 | 308 | ||
285 | if ((l & 0x20) || (r & 0x20)) | 309 | ucontrol->value.enumerated.item[0] = |
286 | ac97_write(w->codec, AC97_AUX, aux & 0x7fff); | 310 | (wm9713->hp_mixer[mixer] >> shift) & 1; |
287 | else | ||
288 | ac97_write(w->codec, AC97_AUX, aux | 0x8000); | ||
289 | 311 | ||
290 | return 0; | 312 | return 0; |
291 | } | 313 | } |
292 | 314 | ||
315 | #define WM9713_HP_MIXER_CTRL(xname, xmixer, xshift) { \ | ||
316 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
317 | .info = snd_soc_info_volsw, \ | ||
318 | .get = wm9713_hp_mixer_get, .put = wm9713_hp_mixer_put, \ | ||
319 | .private_value = SOC_DOUBLE_VALUE(SND_SOC_NOPM, \ | ||
320 | xshift, xmixer, 1, 0, 0) \ | ||
321 | } | ||
322 | |||
293 | /* Left Headphone Mixers */ | 323 | /* Left Headphone Mixers */ |
294 | static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = { | 324 | static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = { |
295 | SOC_DAPM_SINGLE("Beep Playback Switch", HPL_MIXER, 5, 1, 0), | 325 | WM9713_HP_MIXER_CTRL("Beep Playback Switch", HPL_MIXER, 5), |
296 | SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0), | 326 | WM9713_HP_MIXER_CTRL("Voice Playback Switch", HPL_MIXER, 4), |
297 | SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0), | 327 | WM9713_HP_MIXER_CTRL("Aux Playback Switch", HPL_MIXER, 3), |
298 | SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0), | 328 | WM9713_HP_MIXER_CTRL("PCM Playback Switch", HPL_MIXER, 2), |
299 | SOC_DAPM_SINGLE("MonoIn Playback Switch", HPL_MIXER, 1, 1, 0), | 329 | WM9713_HP_MIXER_CTRL("MonoIn Playback Switch", HPL_MIXER, 1), |
300 | SOC_DAPM_SINGLE("Bypass Playback Switch", HPL_MIXER, 0, 1, 0), | 330 | WM9713_HP_MIXER_CTRL("Bypass Playback Switch", HPL_MIXER, 0), |
301 | }; | 331 | }; |
302 | 332 | ||
303 | /* Right Headphone Mixers */ | 333 | /* Right Headphone Mixers */ |
304 | static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = { | 334 | static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = { |
305 | SOC_DAPM_SINGLE("Beep Playback Switch", HPR_MIXER, 5, 1, 0), | 335 | WM9713_HP_MIXER_CTRL("Beep Playback Switch", HPR_MIXER, 5), |
306 | SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0), | 336 | WM9713_HP_MIXER_CTRL("Voice Playback Switch", HPR_MIXER, 4), |
307 | SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0), | 337 | WM9713_HP_MIXER_CTRL("Aux Playback Switch", HPR_MIXER, 3), |
308 | SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0), | 338 | WM9713_HP_MIXER_CTRL("PCM Playback Switch", HPR_MIXER, 2), |
309 | SOC_DAPM_SINGLE("MonoIn Playback Switch", HPR_MIXER, 1, 1, 0), | 339 | WM9713_HP_MIXER_CTRL("MonoIn Playback Switch", HPR_MIXER, 1), |
310 | SOC_DAPM_SINGLE("Bypass Playback Switch", HPR_MIXER, 0, 1, 0), | 340 | WM9713_HP_MIXER_CTRL("Bypass Playback Switch", HPR_MIXER, 0), |
311 | }; | 341 | }; |
312 | 342 | ||
313 | /* headphone capture mux */ | 343 | /* headphone capture mux */ |
@@ -429,12 +459,10 @@ SND_SOC_DAPM_MUX("Mic A Source", SND_SOC_NOPM, 0, 0, | |||
429 | &wm9713_mic_sel_mux_controls), | 459 | &wm9713_mic_sel_mux_controls), |
430 | SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0, | 460 | SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0, |
431 | &wm9713_micb_sel_mux_controls), | 461 | &wm9713_micb_sel_mux_controls), |
432 | SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_EXTENDED_MID, 3, 1, | 462 | SND_SOC_DAPM_MIXER("Left HP Mixer", AC97_EXTENDED_MID, 3, 1, |
433 | &wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls), | 463 | &wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls)), |
434 | mixer_event, SND_SOC_DAPM_POST_REG), | 464 | SND_SOC_DAPM_MIXER("Right HP Mixer", AC97_EXTENDED_MID, 2, 1, |
435 | SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_EXTENDED_MID, 2, 1, | 465 | &wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls)), |
436 | &wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls), | ||
437 | mixer_event, SND_SOC_DAPM_POST_REG), | ||
438 | SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1, | 466 | SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1, |
439 | &wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)), | 467 | &wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)), |
440 | SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1, | 468 | SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1, |
@@ -647,12 +675,13 @@ static const struct snd_soc_dapm_route wm9713_audio_map[] = { | |||
647 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 675 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
648 | unsigned int reg) | 676 | unsigned int reg) |
649 | { | 677 | { |
678 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
650 | u16 *cache = codec->reg_cache; | 679 | u16 *cache = codec->reg_cache; |
651 | 680 | ||
652 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || | 681 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
653 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || | 682 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
654 | reg == AC97_CD) | 683 | reg == AC97_CD) |
655 | return soc_ac97_ops->read(codec->ac97, reg); | 684 | return soc_ac97_ops->read(wm9713->ac97, reg); |
656 | else { | 685 | else { |
657 | reg = reg >> 1; | 686 | reg = reg >> 1; |
658 | 687 | ||
@@ -666,9 +695,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
666 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 695 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
667 | unsigned int val) | 696 | unsigned int val) |
668 | { | 697 | { |
698 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
699 | |||
669 | u16 *cache = codec->reg_cache; | 700 | u16 *cache = codec->reg_cache; |
670 | if (reg < 0x7c) | 701 | soc_ac97_ops->write(wm9713->ac97, reg, val); |
671 | soc_ac97_ops->write(codec->ac97, reg, val); | ||
672 | reg = reg >> 1; | 702 | reg = reg >> 1; |
673 | if (reg < (ARRAY_SIZE(wm9713_reg))) | 703 | if (reg < (ARRAY_SIZE(wm9713_reg))) |
674 | cache[reg] = val; | 704 | cache[reg] = val; |
@@ -689,7 +719,8 @@ struct _pll_div { | |||
689 | * to allow rounding later */ | 719 | * to allow rounding later */ |
690 | #define FIXED_PLL_SIZE ((1 << 22) * 10) | 720 | #define FIXED_PLL_SIZE ((1 << 22) * 10) |
691 | 721 | ||
692 | static void pll_factors(struct _pll_div *pll_div, unsigned int source) | 722 | static void pll_factors(struct snd_soc_codec *codec, |
723 | struct _pll_div *pll_div, unsigned int source) | ||
693 | { | 724 | { |
694 | u64 Kpart; | 725 | u64 Kpart; |
695 | unsigned int K, Ndiv, Nmod, target; | 726 | unsigned int K, Ndiv, Nmod, target; |
@@ -724,7 +755,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int source) | |||
724 | 755 | ||
725 | Ndiv = target / source; | 756 | Ndiv = target / source; |
726 | if ((Ndiv < 5) || (Ndiv > 12)) | 757 | if ((Ndiv < 5) || (Ndiv > 12)) |
727 | printk(KERN_WARNING | 758 | dev_warn(codec->dev, |
728 | "WM9713 PLL N value %u out of recommended range!\n", | 759 | "WM9713 PLL N value %u out of recommended range!\n", |
729 | Ndiv); | 760 | Ndiv); |
730 | 761 | ||
@@ -768,7 +799,7 @@ static int wm9713_set_pll(struct snd_soc_codec *codec, | |||
768 | return 0; | 799 | return 0; |
769 | } | 800 | } |
770 | 801 | ||
771 | pll_factors(&pll_div, freq_in); | 802 | pll_factors(codec, &pll_div, freq_in); |
772 | 803 | ||
773 | if (pll_div.k == 0) { | 804 | if (pll_div.k == 0) { |
774 | reg = (pll_div.n << 12) | (pll_div.lf << 11) | | 805 | reg = (pll_div.n << 12) | (pll_div.lf << 11) | |
@@ -1049,7 +1080,6 @@ static const struct snd_soc_dai_ops wm9713_dai_ops_voice = { | |||
1049 | static struct snd_soc_dai_driver wm9713_dai[] = { | 1080 | static struct snd_soc_dai_driver wm9713_dai[] = { |
1050 | { | 1081 | { |
1051 | .name = "wm9713-hifi", | 1082 | .name = "wm9713-hifi", |
1052 | .ac97_control = 1, | ||
1053 | .playback = { | 1083 | .playback = { |
1054 | .stream_name = "HiFi Playback", | 1084 | .stream_name = "HiFi Playback", |
1055 | .channels_min = 1, | 1085 | .channels_min = 1, |
@@ -1095,17 +1125,22 @@ static struct snd_soc_dai_driver wm9713_dai[] = { | |||
1095 | 1125 | ||
1096 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) | 1126 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) |
1097 | { | 1127 | { |
1128 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
1129 | |||
1098 | if (try_warm && soc_ac97_ops->warm_reset) { | 1130 | if (try_warm && soc_ac97_ops->warm_reset) { |
1099 | soc_ac97_ops->warm_reset(codec->ac97); | 1131 | soc_ac97_ops->warm_reset(wm9713->ac97); |
1100 | if (ac97_read(codec, 0) == wm9713_reg[0]) | 1132 | if (ac97_read(codec, 0) == wm9713_reg[0]) |
1101 | return 1; | 1133 | return 1; |
1102 | } | 1134 | } |
1103 | 1135 | ||
1104 | soc_ac97_ops->reset(codec->ac97); | 1136 | soc_ac97_ops->reset(wm9713->ac97); |
1105 | if (soc_ac97_ops->warm_reset) | 1137 | if (soc_ac97_ops->warm_reset) |
1106 | soc_ac97_ops->warm_reset(codec->ac97); | 1138 | soc_ac97_ops->warm_reset(wm9713->ac97); |
1107 | if (ac97_read(codec, 0) != wm9713_reg[0]) | 1139 | if (ac97_read(codec, 0) != wm9713_reg[0]) { |
1140 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); | ||
1108 | return -EIO; | 1141 | return -EIO; |
1142 | } | ||
1143 | |||
1109 | return 0; | 1144 | return 0; |
1110 | } | 1145 | } |
1111 | EXPORT_SYMBOL_GPL(wm9713_reset); | 1146 | EXPORT_SYMBOL_GPL(wm9713_reset); |
@@ -1163,10 +1198,8 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1163 | u16 *cache = codec->reg_cache; | 1198 | u16 *cache = codec->reg_cache; |
1164 | 1199 | ||
1165 | ret = wm9713_reset(codec, 1); | 1200 | ret = wm9713_reset(codec, 1); |
1166 | if (ret < 0) { | 1201 | if (ret < 0) |
1167 | printk(KERN_ERR "could not reset AC97 codec\n"); | ||
1168 | return ret; | 1202 | return ret; |
1169 | } | ||
1170 | 1203 | ||
1171 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1204 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1172 | 1205 | ||
@@ -1180,7 +1213,7 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1180 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || | 1213 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || |
1181 | i == AC97_EXTENDED_MSTATUS || i > 0x66) | 1214 | i == AC97_EXTENDED_MSTATUS || i > 0x66) |
1182 | continue; | 1215 | continue; |
1183 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); | 1216 | soc_ac97_ops->write(wm9713->ac97, i, cache[i>>1]); |
1184 | } | 1217 | } |
1185 | } | 1218 | } |
1186 | 1219 | ||
@@ -1189,26 +1222,19 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1189 | 1222 | ||
1190 | static int wm9713_soc_probe(struct snd_soc_codec *codec) | 1223 | static int wm9713_soc_probe(struct snd_soc_codec *codec) |
1191 | { | 1224 | { |
1192 | struct wm9713_priv *wm9713; | 1225 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
1193 | int ret = 0, reg; | 1226 | int ret = 0, reg; |
1194 | 1227 | ||
1195 | wm9713 = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL); | 1228 | wm9713->ac97 = snd_soc_new_ac97_codec(codec); |
1196 | if (wm9713 == NULL) | 1229 | if (IS_ERR(wm9713->ac97)) |
1197 | return -ENOMEM; | 1230 | return PTR_ERR(wm9713->ac97); |
1198 | snd_soc_codec_set_drvdata(codec, wm9713); | ||
1199 | |||
1200 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | ||
1201 | if (ret < 0) | ||
1202 | goto codec_err; | ||
1203 | 1231 | ||
1204 | /* do a cold reset for the controller and then try | 1232 | /* do a cold reset for the controller and then try |
1205 | * a warm reset followed by an optional cold reset for codec */ | 1233 | * a warm reset followed by an optional cold reset for codec */ |
1206 | wm9713_reset(codec, 0); | 1234 | wm9713_reset(codec, 0); |
1207 | ret = wm9713_reset(codec, 1); | 1235 | ret = wm9713_reset(codec, 1); |
1208 | if (ret < 0) { | 1236 | if (ret < 0) |
1209 | printk(KERN_ERR "Failed to reset WM9713: AC97 link error\n"); | ||
1210 | goto reset_err; | 1237 | goto reset_err; |
1211 | } | ||
1212 | 1238 | ||
1213 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1239 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1214 | 1240 | ||
@@ -1216,23 +1242,18 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) | |||
1216 | reg = ac97_read(codec, AC97_CD) & 0x7fff; | 1242 | reg = ac97_read(codec, AC97_CD) & 0x7fff; |
1217 | ac97_write(codec, AC97_CD, reg); | 1243 | ac97_write(codec, AC97_CD, reg); |
1218 | 1244 | ||
1219 | snd_soc_add_codec_controls(codec, wm9713_snd_ac97_controls, | ||
1220 | ARRAY_SIZE(wm9713_snd_ac97_controls)); | ||
1221 | |||
1222 | return 0; | 1245 | return 0; |
1223 | 1246 | ||
1224 | reset_err: | 1247 | reset_err: |
1225 | snd_soc_free_ac97_codec(codec); | 1248 | snd_soc_free_ac97_codec(wm9713->ac97); |
1226 | codec_err: | ||
1227 | kfree(wm9713); | ||
1228 | return ret; | 1249 | return ret; |
1229 | } | 1250 | } |
1230 | 1251 | ||
1231 | static int wm9713_soc_remove(struct snd_soc_codec *codec) | 1252 | static int wm9713_soc_remove(struct snd_soc_codec *codec) |
1232 | { | 1253 | { |
1233 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | 1254 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
1234 | snd_soc_free_ac97_codec(codec); | 1255 | |
1235 | kfree(wm9713); | 1256 | snd_soc_free_ac97_codec(wm9713->ac97); |
1236 | return 0; | 1257 | return 0; |
1237 | } | 1258 | } |
1238 | 1259 | ||
@@ -1248,6 +1269,9 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { | |||
1248 | .reg_word_size = sizeof(u16), | 1269 | .reg_word_size = sizeof(u16), |
1249 | .reg_cache_step = 2, | 1270 | .reg_cache_step = 2, |
1250 | .reg_cache_default = wm9713_reg, | 1271 | .reg_cache_default = wm9713_reg, |
1272 | |||
1273 | .controls = wm9713_snd_ac97_controls, | ||
1274 | .num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls), | ||
1251 | .dapm_widgets = wm9713_dapm_widgets, | 1275 | .dapm_widgets = wm9713_dapm_widgets, |
1252 | .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), | 1276 | .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), |
1253 | .dapm_routes = wm9713_audio_map, | 1277 | .dapm_routes = wm9713_audio_map, |
@@ -1256,6 +1280,16 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { | |||
1256 | 1280 | ||
1257 | static int wm9713_probe(struct platform_device *pdev) | 1281 | static int wm9713_probe(struct platform_device *pdev) |
1258 | { | 1282 | { |
1283 | struct wm9713_priv *wm9713; | ||
1284 | |||
1285 | wm9713 = devm_kzalloc(&pdev->dev, sizeof(*wm9713), GFP_KERNEL); | ||
1286 | if (wm9713 == NULL) | ||
1287 | return -ENOMEM; | ||
1288 | |||
1289 | mutex_init(&wm9713->lock); | ||
1290 | |||
1291 | platform_set_drvdata(pdev, wm9713); | ||
1292 | |||
1259 | return snd_soc_register_codec(&pdev->dev, | 1293 | return snd_soc_register_codec(&pdev->dev, |
1260 | &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai)); | 1294 | &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai)); |
1261 | } | 1295 | } |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index f412a9911a75..720d6e852986 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/vmalloc.h> | ||
24 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
25 | #include <sound/core.h> | 26 | #include <sound/core.h> |
26 | #include <sound/pcm.h> | 27 | #include <sound/pcm.h> |
@@ -169,11 +170,12 @@ static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len, | |||
169 | if (buf == NULL) | 170 | if (buf == NULL) |
170 | return NULL; | 171 | return NULL; |
171 | 172 | ||
172 | buf->buf = kmemdup(src, len, GFP_KERNEL | GFP_DMA); | 173 | buf->buf = vmalloc(len); |
173 | if (!buf->buf) { | 174 | if (!buf->buf) { |
174 | kfree(buf); | 175 | vfree(buf); |
175 | return NULL; | 176 | return NULL; |
176 | } | 177 | } |
178 | memcpy(buf->buf, src, len); | ||
177 | 179 | ||
178 | if (list) | 180 | if (list) |
179 | list_add_tail(&buf->list, list); | 181 | list_add_tail(&buf->list, list); |
@@ -188,7 +190,7 @@ static void wm_adsp_buf_free(struct list_head *list) | |||
188 | struct wm_adsp_buf, | 190 | struct wm_adsp_buf, |
189 | list); | 191 | list); |
190 | list_del(&buf->list); | 192 | list_del(&buf->list); |
191 | kfree(buf->buf); | 193 | vfree(buf->buf); |
192 | kfree(buf); | 194 | kfree(buf); |
193 | } | 195 | } |
194 | } | 196 | } |
@@ -684,38 +686,24 @@ static int wm_adsp_load(struct wm_adsp *dsp) | |||
684 | } | 686 | } |
685 | 687 | ||
686 | if (reg) { | 688 | if (reg) { |
687 | size_t to_write = PAGE_SIZE; | 689 | buf = wm_adsp_buf_alloc(region->data, |
688 | size_t remain = le32_to_cpu(region->len); | 690 | le32_to_cpu(region->len), |
689 | const u8 *data = region->data; | 691 | &buf_list); |
690 | 692 | if (!buf) { | |
691 | while (remain > 0) { | 693 | adsp_err(dsp, "Out of memory\n"); |
692 | if (remain < PAGE_SIZE) | 694 | ret = -ENOMEM; |
693 | to_write = remain; | 695 | goto out_fw; |
694 | 696 | } | |
695 | buf = wm_adsp_buf_alloc(data, | ||
696 | to_write, | ||
697 | &buf_list); | ||
698 | if (!buf) { | ||
699 | adsp_err(dsp, "Out of memory\n"); | ||
700 | ret = -ENOMEM; | ||
701 | goto out_fw; | ||
702 | } | ||
703 | |||
704 | ret = regmap_raw_write_async(regmap, reg, | ||
705 | buf->buf, | ||
706 | to_write); | ||
707 | if (ret != 0) { | ||
708 | adsp_err(dsp, | ||
709 | "%s.%d: Failed to write %zd bytes at %d in %s: %d\n", | ||
710 | file, regions, | ||
711 | to_write, offset, | ||
712 | region_name, ret); | ||
713 | goto out_fw; | ||
714 | } | ||
715 | 697 | ||
716 | data += to_write; | 698 | ret = regmap_raw_write_async(regmap, reg, buf->buf, |
717 | reg += to_write / 2; | 699 | le32_to_cpu(region->len)); |
718 | remain -= to_write; | 700 | if (ret != 0) { |
701 | adsp_err(dsp, | ||
702 | "%s.%d: Failed to write %d bytes at %d in %s: %d\n", | ||
703 | file, regions, | ||
704 | le32_to_cpu(region->len), offset, | ||
705 | region_name, ret); | ||
706 | goto out_fw; | ||
719 | } | 707 | } |
720 | } | 708 | } |
721 | 709 | ||
@@ -1065,8 +1053,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
1065 | be32_to_cpu(adsp1_alg[i].zm)); | 1053 | be32_to_cpu(adsp1_alg[i].zm)); |
1066 | 1054 | ||
1067 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1055 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
1068 | if (!region) | 1056 | if (!region) { |
1069 | return -ENOMEM; | 1057 | ret = -ENOMEM; |
1058 | goto out; | ||
1059 | } | ||
1070 | region->type = WMFW_ADSP1_DM; | 1060 | region->type = WMFW_ADSP1_DM; |
1071 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); | 1061 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); |
1072 | region->base = be32_to_cpu(adsp1_alg[i].dm); | 1062 | region->base = be32_to_cpu(adsp1_alg[i].dm); |
@@ -1083,8 +1073,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
1083 | } | 1073 | } |
1084 | 1074 | ||
1085 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1075 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
1086 | if (!region) | 1076 | if (!region) { |
1087 | return -ENOMEM; | 1077 | ret = -ENOMEM; |
1078 | goto out; | ||
1079 | } | ||
1088 | region->type = WMFW_ADSP1_ZM; | 1080 | region->type = WMFW_ADSP1_ZM; |
1089 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); | 1081 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); |
1090 | region->base = be32_to_cpu(adsp1_alg[i].zm); | 1082 | region->base = be32_to_cpu(adsp1_alg[i].zm); |
@@ -1113,8 +1105,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
1113 | be32_to_cpu(adsp2_alg[i].zm)); | 1105 | be32_to_cpu(adsp2_alg[i].zm)); |
1114 | 1106 | ||
1115 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1107 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
1116 | if (!region) | 1108 | if (!region) { |
1117 | return -ENOMEM; | 1109 | ret = -ENOMEM; |
1110 | goto out; | ||
1111 | } | ||
1118 | region->type = WMFW_ADSP2_XM; | 1112 | region->type = WMFW_ADSP2_XM; |
1119 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1113 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); |
1120 | region->base = be32_to_cpu(adsp2_alg[i].xm); | 1114 | region->base = be32_to_cpu(adsp2_alg[i].xm); |
@@ -1131,8 +1125,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
1131 | } | 1125 | } |
1132 | 1126 | ||
1133 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1127 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
1134 | if (!region) | 1128 | if (!region) { |
1135 | return -ENOMEM; | 1129 | ret = -ENOMEM; |
1130 | goto out; | ||
1131 | } | ||
1136 | region->type = WMFW_ADSP2_YM; | 1132 | region->type = WMFW_ADSP2_YM; |
1137 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1133 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); |
1138 | region->base = be32_to_cpu(adsp2_alg[i].ym); | 1134 | region->base = be32_to_cpu(adsp2_alg[i].ym); |
@@ -1149,8 +1145,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
1149 | } | 1145 | } |
1150 | 1146 | ||
1151 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1147 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
1152 | if (!region) | 1148 | if (!region) { |
1153 | return -ENOMEM; | 1149 | ret = -ENOMEM; |
1150 | goto out; | ||
1151 | } | ||
1154 | region->type = WMFW_ADSP2_ZM; | 1152 | region->type = WMFW_ADSP2_ZM; |
1155 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1153 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); |
1156 | region->base = be32_to_cpu(adsp2_alg[i].zm); | 1154 | region->base = be32_to_cpu(adsp2_alg[i].zm); |
@@ -1355,6 +1353,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) | |||
1355 | file, blocks, pos - firmware->size); | 1353 | file, blocks, pos - firmware->size); |
1356 | 1354 | ||
1357 | out_fw: | 1355 | out_fw: |
1356 | regmap_async_complete(regmap); | ||
1358 | release_firmware(firmware); | 1357 | release_firmware(firmware); |
1359 | wm_adsp_buf_free(&buf_list); | 1358 | wm_adsp_buf_free(&buf_list); |
1360 | out: | 1359 | out: |
@@ -1594,13 +1593,6 @@ static void wm_adsp2_boot_work(struct work_struct *work) | |||
1594 | if (ret != 0) | 1593 | if (ret != 0) |
1595 | goto err; | 1594 | goto err; |
1596 | 1595 | ||
1597 | ret = regmap_update_bits_async(dsp->regmap, | ||
1598 | dsp->base + ADSP2_CONTROL, | ||
1599 | ADSP2_CORE_ENA, | ||
1600 | ADSP2_CORE_ENA); | ||
1601 | if (ret != 0) | ||
1602 | goto err; | ||
1603 | |||
1604 | dsp->running = true; | 1596 | dsp->running = true; |
1605 | 1597 | ||
1606 | return; | 1598 | return; |
@@ -1650,8 +1642,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
1650 | 1642 | ||
1651 | ret = regmap_update_bits(dsp->regmap, | 1643 | ret = regmap_update_bits(dsp->regmap, |
1652 | dsp->base + ADSP2_CONTROL, | 1644 | dsp->base + ADSP2_CONTROL, |
1653 | ADSP2_START, | 1645 | ADSP2_CORE_ENA | ADSP2_START, |
1654 | ADSP2_START); | 1646 | ADSP2_CORE_ENA | ADSP2_START); |
1655 | if (ret != 0) | 1647 | if (ret != 0) |
1656 | goto err; | 1648 | goto err; |
1657 | break; | 1649 | break; |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 0eed9b1b24e1..ea3ad747d092 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -154,9 +154,9 @@ static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp) | |||
154 | 154 | ||
155 | static void mcasp_start_rx(struct davinci_mcasp *mcasp) | 155 | static void mcasp_start_rx(struct davinci_mcasp *mcasp) |
156 | { | 156 | { |
157 | /* Start clocks */ | ||
157 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); | 158 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); |
158 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); | 159 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); |
159 | |||
160 | /* | 160 | /* |
161 | * When ASYNC == 0 the transmit and receive sections operate | 161 | * When ASYNC == 0 the transmit and receive sections operate |
162 | * synchronously from the transmit clock and frame sync. We need to make | 162 | * synchronously from the transmit clock and frame sync. We need to make |
@@ -167,47 +167,36 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp) | |||
167 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); | 167 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); |
168 | } | 168 | } |
169 | 169 | ||
170 | /* Activate serializer(s) */ | ||
170 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); | 171 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); |
171 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXBUF_REG, 0); | 172 | /* Release RX state machine */ |
172 | |||
173 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); | ||
174 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); | ||
175 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXBUF_REG, 0); | ||
176 | |||
177 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); | 173 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); |
174 | /* Release Frame Sync generator */ | ||
178 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); | 175 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); |
179 | |||
180 | if (mcasp_is_synchronous(mcasp)) | 176 | if (mcasp_is_synchronous(mcasp)) |
181 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); | 177 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); |
182 | } | 178 | } |
183 | 179 | ||
184 | static void mcasp_start_tx(struct davinci_mcasp *mcasp) | 180 | static void mcasp_start_tx(struct davinci_mcasp *mcasp) |
185 | { | 181 | { |
186 | u8 offset = 0, i; | ||
187 | u32 cnt; | 182 | u32 cnt; |
188 | 183 | ||
184 | /* Start clocks */ | ||
189 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); | 185 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); |
190 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); | 186 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); |
187 | /* Activate serializer(s) */ | ||
191 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); | 188 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); |
192 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0); | ||
193 | 189 | ||
194 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); | 190 | /* wait for XDATA to be cleared */ |
195 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); | ||
196 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0); | ||
197 | for (i = 0; i < mcasp->num_serializer; i++) { | ||
198 | if (mcasp->serial_dir[i] == TX_MODE) { | ||
199 | offset = i; | ||
200 | break; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | /* wait for TX ready */ | ||
205 | cnt = 0; | 191 | cnt = 0; |
206 | while (!(mcasp_get_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(offset)) & | 192 | while (!(mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG) & |
207 | TXSTATE) && (cnt < 100000)) | 193 | ~XRDATA) && (cnt < 100000)) |
208 | cnt++; | 194 | cnt++; |
209 | 195 | ||
210 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0); | 196 | /* Release TX state machine */ |
197 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); | ||
198 | /* Release Frame Sync generator */ | ||
199 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); | ||
211 | } | 200 | } |
212 | 201 | ||
213 | static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream) | 202 | static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream) |
@@ -244,6 +233,12 @@ static void mcasp_stop_rx(struct davinci_mcasp *mcasp) | |||
244 | 233 | ||
245 | mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0); | 234 | mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0); |
246 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); | 235 | mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); |
236 | |||
237 | if (mcasp->rxnumevt) { /* disable FIFO */ | ||
238 | u32 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; | ||
239 | |||
240 | mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); | ||
241 | } | ||
247 | } | 242 | } |
248 | 243 | ||
249 | static void mcasp_stop_tx(struct davinci_mcasp *mcasp) | 244 | static void mcasp_stop_tx(struct davinci_mcasp *mcasp) |
@@ -259,27 +254,22 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp) | |||
259 | 254 | ||
260 | mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val); | 255 | mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val); |
261 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); | 256 | mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); |
257 | |||
258 | if (mcasp->txnumevt) { /* disable FIFO */ | ||
259 | u32 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; | ||
260 | |||
261 | mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); | ||
262 | } | ||
262 | } | 263 | } |
263 | 264 | ||
264 | static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream) | 265 | static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream) |
265 | { | 266 | { |
266 | u32 reg; | ||
267 | |||
268 | mcasp->streams--; | 267 | mcasp->streams--; |
269 | 268 | ||
270 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 269 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) |
271 | if (mcasp->txnumevt) { /* disable FIFO */ | ||
272 | reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; | ||
273 | mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); | ||
274 | } | ||
275 | mcasp_stop_tx(mcasp); | 270 | mcasp_stop_tx(mcasp); |
276 | } else { | 271 | else |
277 | if (mcasp->rxnumevt) { /* disable FIFO */ | ||
278 | reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; | ||
279 | mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); | ||
280 | } | ||
281 | mcasp_stop_rx(mcasp); | 272 | mcasp_stop_rx(mcasp); |
282 | } | ||
283 | } | 273 | } |
284 | 274 | ||
285 | static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 275 | static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
@@ -500,8 +490,17 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, | |||
500 | * both left and right channels), so it has to be divided by number of | 490 | * both left and right channels), so it has to be divided by number of |
501 | * tdm-slots (for I2S - divided by 2). | 491 | * tdm-slots (for I2S - divided by 2). |
502 | */ | 492 | */ |
503 | if (mcasp->bclk_lrclk_ratio) | 493 | if (mcasp->bclk_lrclk_ratio) { |
504 | word_length = mcasp->bclk_lrclk_ratio / mcasp->tdm_slots; | 494 | u32 slot_length = mcasp->bclk_lrclk_ratio / mcasp->tdm_slots; |
495 | |||
496 | /* | ||
497 | * When we have more bclk then it is needed for the data, we | ||
498 | * need to use the rotation to move the received samples to have | ||
499 | * correct alignment. | ||
500 | */ | ||
501 | rx_rotate = (slot_length - word_length) / 4; | ||
502 | word_length = slot_length; | ||
503 | } | ||
505 | 504 | ||
506 | /* mapping of the XSSZ bit-field as described in the datasheet */ | 505 | /* mapping of the XSSZ bit-field as described in the datasheet */ |
507 | fmt = (word_length >> 1) - 1; | 506 | fmt = (word_length >> 1) - 1; |
@@ -971,6 +970,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | |||
971 | }, | 970 | }, |
972 | .ops = &davinci_mcasp_dai_ops, | 971 | .ops = &davinci_mcasp_dai_ops, |
973 | 972 | ||
973 | .symmetric_samplebits = 1, | ||
974 | }, | 974 | }, |
975 | { | 975 | { |
976 | .name = "davinci-mcasp.1", | 976 | .name = "davinci-mcasp.1", |
@@ -1235,6 +1235,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1235 | ret = pm_runtime_get_sync(&pdev->dev); | 1235 | ret = pm_runtime_get_sync(&pdev->dev); |
1236 | if (IS_ERR_VALUE(ret)) { | 1236 | if (IS_ERR_VALUE(ret)) { |
1237 | dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); | 1237 | dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); |
1238 | pm_runtime_disable(&pdev->dev); | ||
1238 | return ret; | 1239 | return ret; |
1239 | } | 1240 | } |
1240 | 1241 | ||
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 98fbc451892a..9737108f0305 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h | |||
@@ -253,6 +253,12 @@ | |||
253 | #define TXFSRST BIT(12) /* Frame Sync Generator Reset */ | 253 | #define TXFSRST BIT(12) /* Frame Sync Generator Reset */ |
254 | 254 | ||
255 | /* | 255 | /* |
256 | * DAVINCI_MCASP_TXSTAT_REG - Transmitter Status Register Bits | ||
257 | * DAVINCI_MCASP_RXSTAT_REG - Receiver Status Register Bits | ||
258 | */ | ||
259 | #define XRDATA BIT(5) /* Transmit/Receive data ready */ | ||
260 | |||
261 | /* | ||
256 | * DAVINCI_MCASP_AMUTE_REG - Mute Control Register Bits | 262 | * DAVINCI_MCASP_AMUTE_REG - Mute Control Register Bits |
257 | */ | 263 | */ |
258 | #define MUTENA(val) (val) | 264 | #define MUTENA(val) (val) |
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 3b145313f93e..9deabdd2b1a2 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c | |||
@@ -684,12 +684,38 @@ static bool fsl_asrc_writeable_reg(struct device *dev, unsigned int reg) | |||
684 | } | 684 | } |
685 | } | 685 | } |
686 | 686 | ||
687 | static struct reg_default fsl_asrc_reg[] = { | ||
688 | { REG_ASRCTR, 0x0000 }, { REG_ASRIER, 0x0000 }, | ||
689 | { REG_ASRCNCR, 0x0000 }, { REG_ASRCFG, 0x0000 }, | ||
690 | { REG_ASRCSR, 0x0000 }, { REG_ASRCDR1, 0x0000 }, | ||
691 | { REG_ASRCDR2, 0x0000 }, { REG_ASRSTR, 0x0000 }, | ||
692 | { REG_ASRRA, 0x0000 }, { REG_ASRRB, 0x0000 }, | ||
693 | { REG_ASRRC, 0x0000 }, { REG_ASRPM1, 0x0000 }, | ||
694 | { REG_ASRPM2, 0x0000 }, { REG_ASRPM3, 0x0000 }, | ||
695 | { REG_ASRPM4, 0x0000 }, { REG_ASRPM5, 0x0000 }, | ||
696 | { REG_ASRTFR1, 0x0000 }, { REG_ASRCCR, 0x0000 }, | ||
697 | { REG_ASRDIA, 0x0000 }, { REG_ASRDOA, 0x0000 }, | ||
698 | { REG_ASRDIB, 0x0000 }, { REG_ASRDOB, 0x0000 }, | ||
699 | { REG_ASRDIC, 0x0000 }, { REG_ASRDOC, 0x0000 }, | ||
700 | { REG_ASRIDRHA, 0x0000 }, { REG_ASRIDRLA, 0x0000 }, | ||
701 | { REG_ASRIDRHB, 0x0000 }, { REG_ASRIDRLB, 0x0000 }, | ||
702 | { REG_ASRIDRHC, 0x0000 }, { REG_ASRIDRLC, 0x0000 }, | ||
703 | { REG_ASR76K, 0x0A47 }, { REG_ASR56K, 0x0DF3 }, | ||
704 | { REG_ASRMCRA, 0x0000 }, { REG_ASRFSTA, 0x0000 }, | ||
705 | { REG_ASRMCRB, 0x0000 }, { REG_ASRFSTB, 0x0000 }, | ||
706 | { REG_ASRMCRC, 0x0000 }, { REG_ASRFSTC, 0x0000 }, | ||
707 | { REG_ASRMCR1A, 0x0000 }, { REG_ASRMCR1B, 0x0000 }, | ||
708 | { REG_ASRMCR1C, 0x0000 }, | ||
709 | }; | ||
710 | |||
687 | static const struct regmap_config fsl_asrc_regmap_config = { | 711 | static const struct regmap_config fsl_asrc_regmap_config = { |
688 | .reg_bits = 32, | 712 | .reg_bits = 32, |
689 | .reg_stride = 4, | 713 | .reg_stride = 4, |
690 | .val_bits = 32, | 714 | .val_bits = 32, |
691 | 715 | ||
692 | .max_register = REG_ASRMCR1C, | 716 | .max_register = REG_ASRMCR1C, |
717 | .reg_defaults = fsl_asrc_reg, | ||
718 | .num_reg_defaults = ARRAY_SIZE(fsl_asrc_reg), | ||
693 | .readable_reg = fsl_asrc_readable_reg, | 719 | .readable_reg = fsl_asrc_readable_reg, |
694 | .volatile_reg = fsl_asrc_volatile_reg, | 720 | .volatile_reg = fsl_asrc_volatile_reg, |
695 | .writeable_reg = fsl_asrc_writeable_reg, | 721 | .writeable_reg = fsl_asrc_writeable_reg, |
@@ -792,7 +818,7 @@ static int fsl_asrc_probe(struct platform_device *pdev) | |||
792 | return -ENOMEM; | 818 | return -ENOMEM; |
793 | 819 | ||
794 | asrc_priv->pdev = pdev; | 820 | asrc_priv->pdev = pdev; |
795 | strcpy(asrc_priv->name, np->name); | 821 | strncpy(asrc_priv->name, np->name, sizeof(asrc_priv->name) - 1); |
796 | 822 | ||
797 | /* Get the addresses and IRQ */ | 823 | /* Get the addresses and IRQ */ |
798 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 824 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 8bcdfda09d7a..ca319d59f843 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c | |||
@@ -513,10 +513,15 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, | |||
513 | u32 width = snd_pcm_format_width(params_format(params)); | 513 | u32 width = snd_pcm_format_width(params_format(params)); |
514 | u32 channels = params_channels(params); | 514 | u32 channels = params_channels(params); |
515 | u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); | 515 | u32 pins = DIV_ROUND_UP(channels, esai_priv->slots); |
516 | u32 slot_width = width; | ||
516 | u32 bclk, mask, val; | 517 | u32 bclk, mask, val; |
517 | int ret; | 518 | int ret; |
518 | 519 | ||
519 | bclk = params_rate(params) * esai_priv->slot_width * esai_priv->slots; | 520 | /* Override slot_width if being specifially set */ |
521 | if (esai_priv->slot_width) | ||
522 | slot_width = esai_priv->slot_width; | ||
523 | |||
524 | bclk = params_rate(params) * slot_width * esai_priv->slots; | ||
520 | 525 | ||
521 | ret = fsl_esai_set_bclk(dai, tx, bclk); | 526 | ret = fsl_esai_set_bclk(dai, tx, bclk); |
522 | if (ret) | 527 | if (ret) |
@@ -538,7 +543,7 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, | |||
538 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val); | 543 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val); |
539 | 544 | ||
540 | mask = ESAI_xCR_xSWS_MASK | (tx ? ESAI_xCR_PADC : 0); | 545 | mask = ESAI_xCR_xSWS_MASK | (tx ? ESAI_xCR_PADC : 0); |
541 | val = ESAI_xCR_xSWS(esai_priv->slot_width, width) | (tx ? ESAI_xCR_PADC : 0); | 546 | val = ESAI_xCR_xSWS(slot_width, width) | (tx ? ESAI_xCR_PADC : 0); |
542 | 547 | ||
543 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val); | 548 | regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val); |
544 | 549 | ||
@@ -734,7 +739,7 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
734 | return -ENOMEM; | 739 | return -ENOMEM; |
735 | 740 | ||
736 | esai_priv->pdev = pdev; | 741 | esai_priv->pdev = pdev; |
737 | strcpy(esai_priv->name, np->name); | 742 | strncpy(esai_priv->name, np->name, sizeof(esai_priv->name) - 1); |
738 | 743 | ||
739 | /* Get the addresses and IRQ */ | 744 | /* Get the addresses and IRQ */ |
740 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 745 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -780,9 +785,6 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
780 | return ret; | 785 | return ret; |
781 | } | 786 | } |
782 | 787 | ||
783 | /* Set a default slot size */ | ||
784 | esai_priv->slot_width = 32; | ||
785 | |||
786 | /* Set a default slot number */ | 788 | /* Set a default slot number */ |
787 | esai_priv->slots = 2; | 789 | esai_priv->slots = 2; |
788 | 790 | ||
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index e6955170dc42..7fd3cbcd74c0 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -1099,7 +1099,7 @@ static const struct snd_soc_component_driver fsl_ssi_component = { | |||
1099 | }; | 1099 | }; |
1100 | 1100 | ||
1101 | static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { | 1101 | static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { |
1102 | .ac97_control = 1, | 1102 | .bus_control = true, |
1103 | .playback = { | 1103 | .playback = { |
1104 | .stream_name = "AC97 Playback", | 1104 | .stream_name = "AC97 Playback", |
1105 | .channels_min = 2, | 1105 | .channels_min = 2, |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index ab2fdd76b693..60b0a5b1f1f1 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
@@ -382,7 +382,7 @@ static struct snd_soc_dai_driver imx_ssi_dai = { | |||
382 | 382 | ||
383 | static struct snd_soc_dai_driver imx_ac97_dai = { | 383 | static struct snd_soc_dai_driver imx_ac97_dai = { |
384 | .probe = imx_ssi_dai_probe, | 384 | .probe = imx_ssi_dai_probe, |
385 | .ac97_control = 1, | 385 | .bus_control = true, |
386 | .playback = { | 386 | .playback = { |
387 | .stream_name = "AC97 Playback", | 387 | .stream_name = "AC97 Playback", |
388 | .channels_min = 2, | 388 | .channels_min = 2, |
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index f2b5d756b1f3..0b82e209b6e3 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c | |||
@@ -327,9 +327,6 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd) | |||
327 | goto capture_alloc_err; | 327 | goto capture_alloc_err; |
328 | } | 328 | } |
329 | 329 | ||
330 | if (rtd->codec->ac97) | ||
331 | rtd->codec->ac97->private_data = psc_dma; | ||
332 | |||
333 | return 0; | 330 | return 0; |
334 | 331 | ||
335 | capture_alloc_err: | 332 | capture_alloc_err: |
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index 24eafa2cfbf4..c6ed6ba965a9 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c | |||
@@ -237,7 +237,7 @@ static const struct snd_soc_dai_ops psc_ac97_digital_ops = { | |||
237 | static struct snd_soc_dai_driver psc_ac97_dai[] = { | 237 | static struct snd_soc_dai_driver psc_ac97_dai[] = { |
238 | { | 238 | { |
239 | .name = "mpc5200-psc-ac97.0", | 239 | .name = "mpc5200-psc-ac97.0", |
240 | .ac97_control = 1, | 240 | .bus_control = true, |
241 | .probe = psc_ac97_probe, | 241 | .probe = psc_ac97_probe, |
242 | .playback = { | 242 | .playback = { |
243 | .stream_name = "AC97 Playback", | 243 | .stream_name = "AC97 Playback", |
@@ -257,7 +257,7 @@ static struct snd_soc_dai_driver psc_ac97_dai[] = { | |||
257 | }, | 257 | }, |
258 | { | 258 | { |
259 | .name = "mpc5200-psc-ac97.1", | 259 | .name = "mpc5200-psc-ac97.1", |
260 | .ac97_control = 1, | 260 | .bus_control = true, |
261 | .playback = { | 261 | .playback = { |
262 | .stream_name = "AC97 SPDIF", | 262 | .stream_name = "AC97 SPDIF", |
263 | .channels_min = 1, | 263 | .channels_min = 1, |
@@ -282,7 +282,6 @@ static const struct snd_soc_component_driver psc_ac97_component = { | |||
282 | static int psc_ac97_of_probe(struct platform_device *op) | 282 | static int psc_ac97_of_probe(struct platform_device *op) |
283 | { | 283 | { |
284 | int rc; | 284 | int rc; |
285 | struct snd_ac97 ac97; | ||
286 | struct mpc52xx_psc __iomem *regs; | 285 | struct mpc52xx_psc __iomem *regs; |
287 | 286 | ||
288 | rc = mpc5200_audio_dma_create(op); | 287 | rc = mpc5200_audio_dma_create(op); |
@@ -304,7 +303,6 @@ static int psc_ac97_of_probe(struct platform_device *op) | |||
304 | 303 | ||
305 | psc_dma = dev_get_drvdata(&op->dev); | 304 | psc_dma = dev_get_drvdata(&op->dev); |
306 | regs = psc_dma->psc_regs; | 305 | regs = psc_dma->psc_regs; |
307 | ac97.private_data = psc_dma; | ||
308 | 306 | ||
309 | psc_dma->imr = 0; | 307 | psc_dma->imr = 0; |
310 | out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); | 308 | out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); |
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c index 33fc5c3abf55..4df867cbb92a 100644 --- a/sound/soc/intel/sst-haswell-pcm.c +++ b/sound/soc/intel/sst-haswell-pcm.c | |||
@@ -691,9 +691,7 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
691 | } | 691 | } |
692 | 692 | ||
693 | #define HSW_FORMATS \ | 693 | #define HSW_FORMATS \ |
694 | (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \ | 694 | (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) |
695 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
696 | SNDRV_PCM_FMTBIT_S8) | ||
697 | 695 | ||
698 | static struct snd_soc_dai_driver hsw_dais[] = { | 696 | static struct snd_soc_dai_driver hsw_dais[] = { |
699 | { | 697 | { |
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index f2f67942b229..dff443e4b657 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c | |||
@@ -298,7 +298,7 @@ static const struct snd_soc_dai_ops nuc900_ac97_dai_ops = { | |||
298 | static struct snd_soc_dai_driver nuc900_ac97_dai = { | 298 | static struct snd_soc_dai_driver nuc900_ac97_dai = { |
299 | .probe = nuc900_ac97_probe, | 299 | .probe = nuc900_ac97_probe, |
300 | .remove = nuc900_ac97_remove, | 300 | .remove = nuc900_ac97_remove, |
301 | .ac97_control = 1, | 301 | .bus_control = true, |
302 | .playback = { | 302 | .playback = { |
303 | .rates = SNDRV_PCM_RATE_8000_48000, | 303 | .rates = SNDRV_PCM_RATE_8000_48000, |
304 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 304 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index ae956e3f4b9d..73ca2820c08c 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c | |||
@@ -157,7 +157,7 @@ static const struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = { | |||
157 | static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = { | 157 | static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = { |
158 | { | 158 | { |
159 | .name = "pxa2xx-ac97", | 159 | .name = "pxa2xx-ac97", |
160 | .ac97_control = 1, | 160 | .bus_control = true, |
161 | .playback = { | 161 | .playback = { |
162 | .stream_name = "AC97 Playback", | 162 | .stream_name = "AC97 Playback", |
163 | .channels_min = 2, | 163 | .channels_min = 2, |
@@ -174,7 +174,7 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = { | |||
174 | }, | 174 | }, |
175 | { | 175 | { |
176 | .name = "pxa2xx-ac97-aux", | 176 | .name = "pxa2xx-ac97-aux", |
177 | .ac97_control = 1, | 177 | .bus_control = true, |
178 | .playback = { | 178 | .playback = { |
179 | .stream_name = "AC97 Aux Playback", | 179 | .stream_name = "AC97 Aux Playback", |
180 | .channels_min = 1, | 180 | .channels_min = 1, |
@@ -191,7 +191,7 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = { | |||
191 | }, | 191 | }, |
192 | { | 192 | { |
193 | .name = "pxa2xx-ac97-mic", | 193 | .name = "pxa2xx-ac97-mic", |
194 | .ac97_control = 1, | 194 | .bus_control = true, |
195 | .capture = { | 195 | .capture = { |
196 | .stream_name = "AC97 Mic Capture", | 196 | .stream_name = "AC97 Mic Capture", |
197 | .channels_min = 1, | 197 | .channels_min = 1, |
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index f373e37f8305..c74ba37f862c 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c | |||
@@ -154,8 +154,10 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) | |||
154 | while (val) { | 154 | while (val) { |
155 | regmap_read(i2s->regmap, I2S_CLR, &val); | 155 | regmap_read(i2s->regmap, I2S_CLR, &val); |
156 | retry--; | 156 | retry--; |
157 | if (!retry) | 157 | if (!retry) { |
158 | dev_warn(i2s->dev, "fail to clear\n"); | 158 | dev_warn(i2s->dev, "fail to clear\n"); |
159 | break; | ||
160 | } | ||
159 | } | 161 | } |
160 | } | 162 | } |
161 | } | 163 | } |
diff --git a/sound/soc/s6000/Kconfig b/sound/soc/s6000/Kconfig deleted file mode 100644 index f244a2566f20..000000000000 --- a/sound/soc/s6000/Kconfig +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | config SND_S6000_SOC | ||
2 | tristate "SoC Audio for the Stretch s6000 family" | ||
3 | depends on XTENSA_VARIANT_S6000 || COMPILE_TEST | ||
4 | depends on HAS_IOMEM | ||
5 | select SND_S6000_SOC_PCM if XTENSA_VARIANT_S6000 | ||
6 | help | ||
7 | Say Y or M if you want to add support for codecs attached to | ||
8 | s6000 family chips. You will also need to select the platform | ||
9 | to support below. | ||
10 | |||
11 | config SND_S6000_SOC_PCM | ||
12 | tristate | ||
13 | |||
14 | config SND_S6000_SOC_I2S | ||
15 | tristate | ||
16 | |||
17 | config SND_S6000_SOC_S6IPCAM | ||
18 | bool "SoC Audio support for Stretch 6105 IP Camera" | ||
19 | depends on SND_S6000_SOC=y | ||
20 | depends on I2C=y | ||
21 | depends on XTENSA_PLATFORM_S6105 || COMPILE_TEST | ||
22 | select SND_S6000_SOC_I2S | ||
23 | select SND_SOC_TLV320AIC3X | ||
24 | help | ||
25 | Say Y if you want to add support for SoC audio on the | ||
26 | Stretch s6105 IP Camera Reference Design. | ||
diff --git a/sound/soc/s6000/Makefile b/sound/soc/s6000/Makefile deleted file mode 100644 index 0f0ae2a012aa..000000000000 --- a/sound/soc/s6000/Makefile +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | # s6000 Platform Support | ||
2 | snd-soc-s6000-objs := s6000-pcm.o | ||
3 | snd-soc-s6000-i2s-objs := s6000-i2s.o | ||
4 | |||
5 | obj-$(CONFIG_SND_S6000_SOC_PCM) += snd-soc-s6000.o | ||
6 | obj-$(CONFIG_SND_S6000_SOC_I2S) += snd-soc-s6000-i2s.o | ||
7 | |||
8 | # s6105 Machine Support | ||
9 | snd-soc-s6ipcam-objs := s6105-ipcam.o | ||
10 | |||
11 | obj-$(CONFIG_SND_S6000_SOC_S6IPCAM) += snd-soc-s6ipcam.o | ||
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c deleted file mode 100644 index 1c8d01166e5b..000000000000 --- a/sound/soc/s6000/s6000-i2s.c +++ /dev/null | |||
@@ -1,617 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA SoC I2S Audio Layer for the Stretch S6000 family | ||
3 | * | ||
4 | * Author: Daniel Gloeckner, <dg@emlix.com> | ||
5 | * Copyright: (C) 2009 emlix GmbH <info@emlix.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/init.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/clk.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/slab.h> | ||
20 | |||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/initval.h> | ||
25 | #include <sound/soc.h> | ||
26 | |||
27 | #include "s6000-i2s.h" | ||
28 | #include "s6000-pcm.h" | ||
29 | |||
30 | struct s6000_i2s_dev { | ||
31 | dma_addr_t sifbase; | ||
32 | u8 __iomem *scbbase; | ||
33 | unsigned int wide; | ||
34 | unsigned int channel_in; | ||
35 | unsigned int channel_out; | ||
36 | unsigned int lines_in; | ||
37 | unsigned int lines_out; | ||
38 | struct s6000_pcm_dma_params dma_params; | ||
39 | }; | ||
40 | |||
41 | #define S6_I2S_INTERRUPT_STATUS 0x00 | ||
42 | #define S6_I2S_INT_OVERRUN 1 | ||
43 | #define S6_I2S_INT_UNDERRUN 2 | ||
44 | #define S6_I2S_INT_ALIGNMENT 4 | ||
45 | #define S6_I2S_INTERRUPT_ENABLE 0x04 | ||
46 | #define S6_I2S_INTERRUPT_RAW 0x08 | ||
47 | #define S6_I2S_INTERRUPT_CLEAR 0x0C | ||
48 | #define S6_I2S_INTERRUPT_SET 0x10 | ||
49 | #define S6_I2S_MODE 0x20 | ||
50 | #define S6_I2S_DUAL 0 | ||
51 | #define S6_I2S_WIDE 1 | ||
52 | #define S6_I2S_TX_DEFAULT 0x24 | ||
53 | #define S6_I2S_DATA_CFG(c) (0x40 + 0x10 * (c)) | ||
54 | #define S6_I2S_IN 0 | ||
55 | #define S6_I2S_OUT 1 | ||
56 | #define S6_I2S_UNUSED 2 | ||
57 | #define S6_I2S_INTERFACE_CFG(c) (0x44 + 0x10 * (c)) | ||
58 | #define S6_I2S_DIV_MASK 0x001fff | ||
59 | #define S6_I2S_16BIT 0x000000 | ||
60 | #define S6_I2S_20BIT 0x002000 | ||
61 | #define S6_I2S_24BIT 0x004000 | ||
62 | #define S6_I2S_32BIT 0x006000 | ||
63 | #define S6_I2S_BITS_MASK 0x006000 | ||
64 | #define S6_I2S_MEM_16BIT 0x000000 | ||
65 | #define S6_I2S_MEM_32BIT 0x008000 | ||
66 | #define S6_I2S_MEM_MASK 0x008000 | ||
67 | #define S6_I2S_CHANNELS_SHIFT 16 | ||
68 | #define S6_I2S_CHANNELS_MASK 0x030000 | ||
69 | #define S6_I2S_SCK_IN 0x000000 | ||
70 | #define S6_I2S_SCK_OUT 0x040000 | ||
71 | #define S6_I2S_SCK_DIR 0x040000 | ||
72 | #define S6_I2S_WS_IN 0x000000 | ||
73 | #define S6_I2S_WS_OUT 0x080000 | ||
74 | #define S6_I2S_WS_DIR 0x080000 | ||
75 | #define S6_I2S_LEFT_FIRST 0x000000 | ||
76 | #define S6_I2S_RIGHT_FIRST 0x100000 | ||
77 | #define S6_I2S_FIRST 0x100000 | ||
78 | #define S6_I2S_CUR_SCK 0x200000 | ||
79 | #define S6_I2S_CUR_WS 0x400000 | ||
80 | #define S6_I2S_ENABLE(c) (0x48 + 0x10 * (c)) | ||
81 | #define S6_I2S_DISABLE_IF 0x02 | ||
82 | #define S6_I2S_ENABLE_IF 0x03 | ||
83 | #define S6_I2S_IS_BUSY 0x04 | ||
84 | #define S6_I2S_DMA_ACTIVE 0x08 | ||
85 | #define S6_I2S_IS_ENABLED 0x10 | ||
86 | |||
87 | #define S6_I2S_NUM_LINES 4 | ||
88 | |||
89 | #define S6_I2S_SIF_PORT0 0x0000000 | ||
90 | #define S6_I2S_SIF_PORT1 0x0000080 /* docs say 0x0000010 */ | ||
91 | |||
92 | static inline void s6_i2s_write_reg(struct s6000_i2s_dev *dev, int reg, u32 val) | ||
93 | { | ||
94 | writel(val, dev->scbbase + reg); | ||
95 | } | ||
96 | |||
97 | static inline u32 s6_i2s_read_reg(struct s6000_i2s_dev *dev, int reg) | ||
98 | { | ||
99 | return readl(dev->scbbase + reg); | ||
100 | } | ||
101 | |||
102 | static inline void s6_i2s_mod_reg(struct s6000_i2s_dev *dev, int reg, | ||
103 | u32 mask, u32 val) | ||
104 | { | ||
105 | val ^= s6_i2s_read_reg(dev, reg) & ~mask; | ||
106 | s6_i2s_write_reg(dev, reg, val); | ||
107 | } | ||
108 | |||
109 | static void s6000_i2s_start_channel(struct s6000_i2s_dev *dev, int channel) | ||
110 | { | ||
111 | int i, j, cur, prev; | ||
112 | |||
113 | /* | ||
114 | * Wait for WCLK to toggle 5 times before enabling the channel | ||
115 | * s6000 Family Datasheet 3.6.4: | ||
116 | * "At least two cycles of WS must occur between commands | ||
117 | * to disable or enable the interface" | ||
118 | */ | ||
119 | j = 0; | ||
120 | prev = ~S6_I2S_CUR_WS; | ||
121 | for (i = 1000000; --i && j < 6; ) { | ||
122 | cur = s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(channel)) | ||
123 | & S6_I2S_CUR_WS; | ||
124 | if (prev != cur) { | ||
125 | prev = cur; | ||
126 | j++; | ||
127 | } | ||
128 | } | ||
129 | if (j < 6) | ||
130 | printk(KERN_WARNING "s6000-i2s: timeout waiting for WCLK\n"); | ||
131 | |||
132 | s6_i2s_write_reg(dev, S6_I2S_ENABLE(channel), S6_I2S_ENABLE_IF); | ||
133 | } | ||
134 | |||
135 | static void s6000_i2s_stop_channel(struct s6000_i2s_dev *dev, int channel) | ||
136 | { | ||
137 | s6_i2s_write_reg(dev, S6_I2S_ENABLE(channel), S6_I2S_DISABLE_IF); | ||
138 | } | ||
139 | |||
140 | static void s6000_i2s_start(struct snd_pcm_substream *substream) | ||
141 | { | ||
142 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
143 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
144 | int channel; | ||
145 | |||
146 | channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
147 | dev->channel_out : dev->channel_in; | ||
148 | |||
149 | s6000_i2s_start_channel(dev, channel); | ||
150 | } | ||
151 | |||
152 | static void s6000_i2s_stop(struct snd_pcm_substream *substream) | ||
153 | { | ||
154 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
155 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
156 | int channel; | ||
157 | |||
158 | channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
159 | dev->channel_out : dev->channel_in; | ||
160 | |||
161 | s6000_i2s_stop_channel(dev, channel); | ||
162 | } | ||
163 | |||
164 | static int s6000_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | ||
165 | int after) | ||
166 | { | ||
167 | switch (cmd) { | ||
168 | case SNDRV_PCM_TRIGGER_START: | ||
169 | case SNDRV_PCM_TRIGGER_RESUME: | ||
170 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
171 | if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) ^ !after) | ||
172 | s6000_i2s_start(substream); | ||
173 | break; | ||
174 | case SNDRV_PCM_TRIGGER_STOP: | ||
175 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
176 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
177 | if (!after) | ||
178 | s6000_i2s_stop(substream); | ||
179 | } | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static unsigned int s6000_i2s_int_sources(struct s6000_i2s_dev *dev) | ||
184 | { | ||
185 | unsigned int pending; | ||
186 | pending = s6_i2s_read_reg(dev, S6_I2S_INTERRUPT_RAW); | ||
187 | pending &= S6_I2S_INT_ALIGNMENT | | ||
188 | S6_I2S_INT_UNDERRUN | | ||
189 | S6_I2S_INT_OVERRUN; | ||
190 | s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_CLEAR, pending); | ||
191 | |||
192 | return pending; | ||
193 | } | ||
194 | |||
195 | static unsigned int s6000_i2s_check_xrun(struct snd_soc_dai *cpu_dai) | ||
196 | { | ||
197 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); | ||
198 | unsigned int errors; | ||
199 | unsigned int ret; | ||
200 | |||
201 | errors = s6000_i2s_int_sources(dev); | ||
202 | if (likely(!errors)) | ||
203 | return 0; | ||
204 | |||
205 | ret = 0; | ||
206 | if (errors & S6_I2S_INT_ALIGNMENT) | ||
207 | printk(KERN_ERR "s6000-i2s: WCLK misaligned\n"); | ||
208 | if (errors & S6_I2S_INT_UNDERRUN) | ||
209 | ret |= 1 << SNDRV_PCM_STREAM_PLAYBACK; | ||
210 | if (errors & S6_I2S_INT_OVERRUN) | ||
211 | ret |= 1 << SNDRV_PCM_STREAM_CAPTURE; | ||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | static void s6000_i2s_wait_disabled(struct s6000_i2s_dev *dev) | ||
216 | { | ||
217 | int channel; | ||
218 | int n = 50; | ||
219 | for (channel = 0; channel < 2; channel++) { | ||
220 | while (--n >= 0) { | ||
221 | int v = s6_i2s_read_reg(dev, S6_I2S_ENABLE(channel)); | ||
222 | if ((v & S6_I2S_IS_ENABLED) | ||
223 | || !(v & (S6_I2S_DMA_ACTIVE | S6_I2S_IS_BUSY))) | ||
224 | break; | ||
225 | udelay(20); | ||
226 | } | ||
227 | } | ||
228 | if (n < 0) | ||
229 | printk(KERN_WARNING "s6000-i2s: timeout disabling interfaces"); | ||
230 | } | ||
231 | |||
232 | static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | ||
233 | unsigned int fmt) | ||
234 | { | ||
235 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); | ||
236 | u32 w; | ||
237 | |||
238 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
239 | case SND_SOC_DAIFMT_CBM_CFM: | ||
240 | w = S6_I2S_SCK_IN | S6_I2S_WS_IN; | ||
241 | break; | ||
242 | case SND_SOC_DAIFMT_CBS_CFM: | ||
243 | w = S6_I2S_SCK_OUT | S6_I2S_WS_IN; | ||
244 | break; | ||
245 | case SND_SOC_DAIFMT_CBM_CFS: | ||
246 | w = S6_I2S_SCK_IN | S6_I2S_WS_OUT; | ||
247 | break; | ||
248 | case SND_SOC_DAIFMT_CBS_CFS: | ||
249 | w = S6_I2S_SCK_OUT | S6_I2S_WS_OUT; | ||
250 | break; | ||
251 | default: | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | |||
255 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
256 | case SND_SOC_DAIFMT_NB_NF: | ||
257 | w |= S6_I2S_LEFT_FIRST; | ||
258 | break; | ||
259 | case SND_SOC_DAIFMT_NB_IF: | ||
260 | w |= S6_I2S_RIGHT_FIRST; | ||
261 | break; | ||
262 | default: | ||
263 | return -EINVAL; | ||
264 | } | ||
265 | |||
266 | s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(0), | ||
267 | S6_I2S_FIRST | S6_I2S_WS_DIR | S6_I2S_SCK_DIR, w); | ||
268 | s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(1), | ||
269 | S6_I2S_FIRST | S6_I2S_WS_DIR | S6_I2S_SCK_DIR, w); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int s6000_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) | ||
275 | { | ||
276 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
277 | |||
278 | if (!div || (div & 1) || div > (S6_I2S_DIV_MASK + 1) * 2) | ||
279 | return -EINVAL; | ||
280 | |||
281 | s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(div_id), | ||
282 | S6_I2S_DIV_MASK, div / 2 - 1); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static int s6000_i2s_hw_params(struct snd_pcm_substream *substream, | ||
287 | struct snd_pcm_hw_params *params, | ||
288 | struct snd_soc_dai *dai) | ||
289 | { | ||
290 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
291 | int interf; | ||
292 | u32 w = 0; | ||
293 | |||
294 | if (dev->wide) | ||
295 | interf = 0; | ||
296 | else { | ||
297 | w |= (((params_channels(params) - 2) / 2) | ||
298 | << S6_I2S_CHANNELS_SHIFT) & S6_I2S_CHANNELS_MASK; | ||
299 | interf = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
300 | ? dev->channel_out : dev->channel_in; | ||
301 | } | ||
302 | |||
303 | switch (params_format(params)) { | ||
304 | case SNDRV_PCM_FORMAT_S16_LE: | ||
305 | w |= S6_I2S_16BIT | S6_I2S_MEM_16BIT; | ||
306 | break; | ||
307 | case SNDRV_PCM_FORMAT_S32_LE: | ||
308 | w |= S6_I2S_32BIT | S6_I2S_MEM_32BIT; | ||
309 | break; | ||
310 | default: | ||
311 | printk(KERN_WARNING "s6000-i2s: unsupported PCM format %x\n", | ||
312 | params_format(params)); | ||
313 | return -EINVAL; | ||
314 | } | ||
315 | |||
316 | if (s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(interf)) | ||
317 | & S6_I2S_IS_ENABLED) { | ||
318 | printk(KERN_ERR "s6000-i2s: interface already enabled\n"); | ||
319 | return -EBUSY; | ||
320 | } | ||
321 | |||
322 | s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(interf), | ||
323 | S6_I2S_CHANNELS_MASK|S6_I2S_MEM_MASK|S6_I2S_BITS_MASK, | ||
324 | w); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static int s6000_i2s_dai_probe(struct snd_soc_dai *dai) | ||
330 | { | ||
331 | struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
332 | struct s6000_snd_platform_data *pdata = dai->dev->platform_data; | ||
333 | |||
334 | if (!pdata) | ||
335 | return -EINVAL; | ||
336 | |||
337 | dai->capture_dma_data = &dev->dma_params; | ||
338 | dai->playback_dma_data = &dev->dma_params; | ||
339 | |||
340 | dev->wide = pdata->wide; | ||
341 | dev->channel_in = pdata->channel_in; | ||
342 | dev->channel_out = pdata->channel_out; | ||
343 | dev->lines_in = pdata->lines_in; | ||
344 | dev->lines_out = pdata->lines_out; | ||
345 | |||
346 | s6_i2s_write_reg(dev, S6_I2S_MODE, | ||
347 | dev->wide ? S6_I2S_WIDE : S6_I2S_DUAL); | ||
348 | |||
349 | if (dev->wide) { | ||
350 | int i; | ||
351 | |||
352 | if (dev->lines_in + dev->lines_out > S6_I2S_NUM_LINES) | ||
353 | return -EINVAL; | ||
354 | |||
355 | dev->channel_in = 0; | ||
356 | dev->channel_out = 1; | ||
357 | dai->driver->capture.channels_min = 2 * dev->lines_in; | ||
358 | dai->driver->capture.channels_max = dai->driver->capture.channels_min; | ||
359 | dai->driver->playback.channels_min = 2 * dev->lines_out; | ||
360 | dai->driver->playback.channels_max = dai->driver->playback.channels_min; | ||
361 | |||
362 | for (i = 0; i < dev->lines_out; i++) | ||
363 | s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_OUT); | ||
364 | |||
365 | for (; i < S6_I2S_NUM_LINES - dev->lines_in; i++) | ||
366 | s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), | ||
367 | S6_I2S_UNUSED); | ||
368 | |||
369 | for (; i < S6_I2S_NUM_LINES; i++) | ||
370 | s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_IN); | ||
371 | } else { | ||
372 | unsigned int cfg[2] = {S6_I2S_UNUSED, S6_I2S_UNUSED}; | ||
373 | |||
374 | if (dev->lines_in > 1 || dev->lines_out > 1) | ||
375 | return -EINVAL; | ||
376 | |||
377 | dai->driver->capture.channels_min = 2 * dev->lines_in; | ||
378 | dai->driver->capture.channels_max = 8 * dev->lines_in; | ||
379 | dai->driver->playback.channels_min = 2 * dev->lines_out; | ||
380 | dai->driver->playback.channels_max = 8 * dev->lines_out; | ||
381 | |||
382 | if (dev->lines_in) | ||
383 | cfg[dev->channel_in] = S6_I2S_IN; | ||
384 | if (dev->lines_out) | ||
385 | cfg[dev->channel_out] = S6_I2S_OUT; | ||
386 | |||
387 | s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(0), cfg[0]); | ||
388 | s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(1), cfg[1]); | ||
389 | } | ||
390 | |||
391 | if (dev->lines_out) { | ||
392 | if (dev->lines_in) { | ||
393 | if (!dev->dma_params.dma_out) | ||
394 | return -ENODEV; | ||
395 | } else { | ||
396 | dev->dma_params.dma_out = dev->dma_params.dma_in; | ||
397 | dev->dma_params.dma_in = 0; | ||
398 | } | ||
399 | } | ||
400 | dev->dma_params.sif_in = dev->sifbase + (dev->channel_in ? | ||
401 | S6_I2S_SIF_PORT1 : S6_I2S_SIF_PORT0); | ||
402 | dev->dma_params.sif_out = dev->sifbase + (dev->channel_out ? | ||
403 | S6_I2S_SIF_PORT1 : S6_I2S_SIF_PORT0); | ||
404 | dev->dma_params.same_rate = pdata->same_rate | pdata->wide; | ||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | #define S6000_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS | ||
409 | #define S6000_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
410 | |||
411 | static const struct snd_soc_dai_ops s6000_i2s_dai_ops = { | ||
412 | .set_fmt = s6000_i2s_set_dai_fmt, | ||
413 | .set_clkdiv = s6000_i2s_set_clkdiv, | ||
414 | .hw_params = s6000_i2s_hw_params, | ||
415 | }; | ||
416 | |||
417 | static struct snd_soc_dai_driver s6000_i2s_dai = { | ||
418 | .probe = s6000_i2s_dai_probe, | ||
419 | .playback = { | ||
420 | .channels_min = 2, | ||
421 | .channels_max = 8, | ||
422 | .formats = S6000_I2S_FORMATS, | ||
423 | .rates = S6000_I2S_RATES, | ||
424 | .rate_min = 0, | ||
425 | .rate_max = 1562500, | ||
426 | }, | ||
427 | .capture = { | ||
428 | .channels_min = 2, | ||
429 | .channels_max = 8, | ||
430 | .formats = S6000_I2S_FORMATS, | ||
431 | .rates = S6000_I2S_RATES, | ||
432 | .rate_min = 0, | ||
433 | .rate_max = 1562500, | ||
434 | }, | ||
435 | .ops = &s6000_i2s_dai_ops, | ||
436 | }; | ||
437 | |||
438 | static const struct snd_soc_component_driver s6000_i2s_component = { | ||
439 | .name = "s6000-i2s", | ||
440 | }; | ||
441 | |||
442 | static int s6000_i2s_probe(struct platform_device *pdev) | ||
443 | { | ||
444 | struct s6000_i2s_dev *dev; | ||
445 | struct resource *scbmem, *sifmem, *region, *dma1, *dma2; | ||
446 | u8 __iomem *mmio; | ||
447 | int ret; | ||
448 | |||
449 | scbmem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
450 | if (!scbmem) { | ||
451 | dev_err(&pdev->dev, "no mem resource?\n"); | ||
452 | ret = -ENODEV; | ||
453 | goto err_release_none; | ||
454 | } | ||
455 | |||
456 | region = request_mem_region(scbmem->start, resource_size(scbmem), | ||
457 | pdev->name); | ||
458 | if (!region) { | ||
459 | dev_err(&pdev->dev, "I2S SCB region already claimed\n"); | ||
460 | ret = -EBUSY; | ||
461 | goto err_release_none; | ||
462 | } | ||
463 | |||
464 | mmio = ioremap(scbmem->start, resource_size(scbmem)); | ||
465 | if (!mmio) { | ||
466 | dev_err(&pdev->dev, "can't ioremap SCB region\n"); | ||
467 | ret = -ENOMEM; | ||
468 | goto err_release_scb; | ||
469 | } | ||
470 | |||
471 | sifmem = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
472 | if (!sifmem) { | ||
473 | dev_err(&pdev->dev, "no second mem resource?\n"); | ||
474 | ret = -ENODEV; | ||
475 | goto err_release_map; | ||
476 | } | ||
477 | |||
478 | region = request_mem_region(sifmem->start, resource_size(sifmem), | ||
479 | pdev->name); | ||
480 | if (!region) { | ||
481 | dev_err(&pdev->dev, "I2S SIF region already claimed\n"); | ||
482 | ret = -EBUSY; | ||
483 | goto err_release_map; | ||
484 | } | ||
485 | |||
486 | dma1 = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
487 | if (!dma1) { | ||
488 | dev_err(&pdev->dev, "no dma resource?\n"); | ||
489 | ret = -ENODEV; | ||
490 | goto err_release_sif; | ||
491 | } | ||
492 | |||
493 | region = request_mem_region(dma1->start, resource_size(dma1), | ||
494 | pdev->name); | ||
495 | if (!region) { | ||
496 | dev_err(&pdev->dev, "I2S DMA region already claimed\n"); | ||
497 | ret = -EBUSY; | ||
498 | goto err_release_sif; | ||
499 | } | ||
500 | |||
501 | dma2 = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
502 | if (dma2) { | ||
503 | region = request_mem_region(dma2->start, resource_size(dma2), | ||
504 | pdev->name); | ||
505 | if (!region) { | ||
506 | dev_err(&pdev->dev, | ||
507 | "I2S DMA region already claimed\n"); | ||
508 | ret = -EBUSY; | ||
509 | goto err_release_dma1; | ||
510 | } | ||
511 | } | ||
512 | |||
513 | dev = kzalloc(sizeof(struct s6000_i2s_dev), GFP_KERNEL); | ||
514 | if (!dev) { | ||
515 | ret = -ENOMEM; | ||
516 | goto err_release_dma2; | ||
517 | } | ||
518 | dev_set_drvdata(&pdev->dev, dev); | ||
519 | |||
520 | dev->sifbase = sifmem->start; | ||
521 | dev->scbbase = mmio; | ||
522 | |||
523 | s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0); | ||
524 | s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_CLEAR, | ||
525 | S6_I2S_INT_ALIGNMENT | | ||
526 | S6_I2S_INT_UNDERRUN | | ||
527 | S6_I2S_INT_OVERRUN); | ||
528 | |||
529 | s6000_i2s_stop_channel(dev, 0); | ||
530 | s6000_i2s_stop_channel(dev, 1); | ||
531 | s6000_i2s_wait_disabled(dev); | ||
532 | |||
533 | dev->dma_params.check_xrun = s6000_i2s_check_xrun; | ||
534 | dev->dma_params.trigger = s6000_i2s_trigger; | ||
535 | dev->dma_params.dma_in = dma1->start; | ||
536 | dev->dma_params.dma_out = dma2 ? dma2->start : 0; | ||
537 | dev->dma_params.irq = platform_get_irq(pdev, 0); | ||
538 | if (dev->dma_params.irq < 0) { | ||
539 | dev_err(&pdev->dev, "no irq resource?\n"); | ||
540 | ret = -ENODEV; | ||
541 | goto err_release_dev; | ||
542 | } | ||
543 | |||
544 | s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, | ||
545 | S6_I2S_INT_ALIGNMENT | | ||
546 | S6_I2S_INT_UNDERRUN | | ||
547 | S6_I2S_INT_OVERRUN); | ||
548 | |||
549 | ret = snd_soc_register_component(&pdev->dev, &s6000_i2s_component, | ||
550 | &s6000_i2s_dai, 1); | ||
551 | if (ret) | ||
552 | goto err_release_dev; | ||
553 | |||
554 | return 0; | ||
555 | |||
556 | err_release_dev: | ||
557 | kfree(dev); | ||
558 | err_release_dma2: | ||
559 | if (dma2) | ||
560 | release_mem_region(dma2->start, resource_size(dma2)); | ||
561 | err_release_dma1: | ||
562 | release_mem_region(dma1->start, resource_size(dma1)); | ||
563 | err_release_sif: | ||
564 | release_mem_region(sifmem->start, resource_size(sifmem)); | ||
565 | err_release_map: | ||
566 | iounmap(mmio); | ||
567 | err_release_scb: | ||
568 | release_mem_region(scbmem->start, resource_size(scbmem)); | ||
569 | err_release_none: | ||
570 | return ret; | ||
571 | } | ||
572 | |||
573 | static int s6000_i2s_remove(struct platform_device *pdev) | ||
574 | { | ||
575 | struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev); | ||
576 | struct resource *region; | ||
577 | void __iomem *mmio = dev->scbbase; | ||
578 | |||
579 | snd_soc_unregister_component(&pdev->dev); | ||
580 | |||
581 | s6000_i2s_stop_channel(dev, 0); | ||
582 | s6000_i2s_stop_channel(dev, 1); | ||
583 | |||
584 | s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0); | ||
585 | kfree(dev); | ||
586 | |||
587 | region = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
588 | release_mem_region(region->start, resource_size(region)); | ||
589 | |||
590 | region = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
591 | if (region) | ||
592 | release_mem_region(region->start, resource_size(region)); | ||
593 | |||
594 | region = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
595 | release_mem_region(region->start, resource_size(region)); | ||
596 | |||
597 | iounmap(mmio); | ||
598 | region = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
599 | release_mem_region(region->start, resource_size(region)); | ||
600 | |||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static struct platform_driver s6000_i2s_driver = { | ||
605 | .probe = s6000_i2s_probe, | ||
606 | .remove = s6000_i2s_remove, | ||
607 | .driver = { | ||
608 | .name = "s6000-i2s", | ||
609 | .owner = THIS_MODULE, | ||
610 | }, | ||
611 | }; | ||
612 | |||
613 | module_platform_driver(s6000_i2s_driver); | ||
614 | |||
615 | MODULE_AUTHOR("Daniel Gloeckner"); | ||
616 | MODULE_DESCRIPTION("Stretch s6000 family I2S SoC Interface"); | ||
617 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s6000/s6000-i2s.h b/sound/soc/s6000/s6000-i2s.h deleted file mode 100644 index 86aa1921c89e..000000000000 --- a/sound/soc/s6000/s6000-i2s.h +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA SoC I2S Audio Layer for the Stretch s6000 family | ||
3 | * | ||
4 | * Author: Daniel Gloeckner, <dg@emlix.com> | ||
5 | * Copyright: (C) 2009 emlix GmbH <info@emlix.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 _S6000_I2S_H | ||
13 | #define _S6000_I2S_H | ||
14 | |||
15 | struct s6000_snd_platform_data { | ||
16 | int lines_in; | ||
17 | int lines_out; | ||
18 | int channel_in; | ||
19 | int channel_out; | ||
20 | int wide; | ||
21 | int same_rate; | ||
22 | }; | ||
23 | #endif | ||
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c deleted file mode 100644 index fb8461e1b1f6..000000000000 --- a/sound/soc/s6000/s6000-pcm.c +++ /dev/null | |||
@@ -1,521 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA PCM interface for the Stetch s6000 family | ||
3 | * | ||
4 | * Author: Daniel Gloeckner, <dg@emlix.com> | ||
5 | * Copyright: (C) 2009 emlix GmbH <info@emlix.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/init.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | |||
19 | #include <sound/core.h> | ||
20 | #include <sound/pcm.h> | ||
21 | #include <sound/pcm_params.h> | ||
22 | #include <sound/soc.h> | ||
23 | |||
24 | #include <asm/dma.h> | ||
25 | #include <variant/dmac.h> | ||
26 | |||
27 | #include "s6000-pcm.h" | ||
28 | |||
29 | #define S6_PCM_PREALLOCATE_SIZE (96 * 1024) | ||
30 | #define S6_PCM_PREALLOCATE_MAX (2048 * 1024) | ||
31 | |||
32 | static struct snd_pcm_hardware s6000_pcm_hardware = { | ||
33 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
34 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | ||
35 | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_JOINT_DUPLEX), | ||
36 | .buffer_bytes_max = 0x7ffffff0, | ||
37 | .period_bytes_min = 16, | ||
38 | .period_bytes_max = 0xfffff0, | ||
39 | .periods_min = 2, | ||
40 | .periods_max = 1024, /* no limit */ | ||
41 | .fifo_size = 0, | ||
42 | }; | ||
43 | |||
44 | struct s6000_runtime_data { | ||
45 | spinlock_t lock; | ||
46 | int period; /* current DMA period */ | ||
47 | }; | ||
48 | |||
49 | static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream) | ||
50 | { | ||
51 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
52 | struct s6000_runtime_data *prtd = runtime->private_data; | ||
53 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | ||
54 | struct s6000_pcm_dma_params *par; | ||
55 | int channel; | ||
56 | unsigned int period_size; | ||
57 | unsigned int dma_offset; | ||
58 | dma_addr_t dma_pos; | ||
59 | dma_addr_t src, dst; | ||
60 | |||
61 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); | ||
62 | |||
63 | period_size = snd_pcm_lib_period_bytes(substream); | ||
64 | dma_offset = prtd->period * period_size; | ||
65 | dma_pos = runtime->dma_addr + dma_offset; | ||
66 | |||
67 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
68 | src = dma_pos; | ||
69 | dst = par->sif_out; | ||
70 | channel = par->dma_out; | ||
71 | } else { | ||
72 | src = par->sif_in; | ||
73 | dst = dma_pos; | ||
74 | channel = par->dma_in; | ||
75 | } | ||
76 | |||
77 | if (!s6dmac_channel_enabled(DMA_MASK_DMAC(channel), | ||
78 | DMA_INDEX_CHNL(channel))) | ||
79 | return; | ||
80 | |||
81 | if (s6dmac_fifo_full(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel))) { | ||
82 | printk(KERN_ERR "s6000-pcm: fifo full\n"); | ||
83 | return; | ||
84 | } | ||
85 | |||
86 | if (WARN_ON(period_size & 15)) | ||
87 | return; | ||
88 | s6dmac_put_fifo(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel), | ||
89 | src, dst, period_size); | ||
90 | |||
91 | prtd->period++; | ||
92 | if (unlikely(prtd->period >= runtime->periods)) | ||
93 | prtd->period = 0; | ||
94 | } | ||
95 | |||
96 | static irqreturn_t s6000_pcm_irq(int irq, void *data) | ||
97 | { | ||
98 | struct snd_pcm *pcm = data; | ||
99 | struct snd_soc_pcm_runtime *runtime = pcm->private_data; | ||
100 | struct s6000_runtime_data *prtd; | ||
101 | unsigned int has_xrun; | ||
102 | int i, ret = IRQ_NONE; | ||
103 | |||
104 | for (i = 0; i < 2; ++i) { | ||
105 | struct snd_pcm_substream *substream = pcm->streams[i].substream; | ||
106 | struct s6000_pcm_dma_params *params = | ||
107 | snd_soc_dai_get_dma_data(runtime->cpu_dai, substream); | ||
108 | u32 channel; | ||
109 | unsigned int pending; | ||
110 | |||
111 | if (substream == SNDRV_PCM_STREAM_PLAYBACK) | ||
112 | channel = params->dma_out; | ||
113 | else | ||
114 | channel = params->dma_in; | ||
115 | |||
116 | has_xrun = params->check_xrun(runtime->cpu_dai); | ||
117 | |||
118 | if (!channel) | ||
119 | continue; | ||
120 | |||
121 | if (unlikely(has_xrun & (1 << i)) && | ||
122 | substream->runtime && | ||
123 | snd_pcm_running(substream)) { | ||
124 | dev_dbg(pcm->dev, "xrun\n"); | ||
125 | snd_pcm_stream_lock(substream); | ||
126 | snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); | ||
127 | snd_pcm_stream_unlock(substream); | ||
128 | ret = IRQ_HANDLED; | ||
129 | } | ||
130 | |||
131 | pending = s6dmac_int_sources(DMA_MASK_DMAC(channel), | ||
132 | DMA_INDEX_CHNL(channel)); | ||
133 | |||
134 | if (pending & 1) { | ||
135 | ret = IRQ_HANDLED; | ||
136 | if (likely(substream->runtime && | ||
137 | snd_pcm_running(substream))) { | ||
138 | snd_pcm_period_elapsed(substream); | ||
139 | dev_dbg(pcm->dev, "period elapsed %x %x\n", | ||
140 | s6dmac_cur_src(DMA_MASK_DMAC(channel), | ||
141 | DMA_INDEX_CHNL(channel)), | ||
142 | s6dmac_cur_dst(DMA_MASK_DMAC(channel), | ||
143 | DMA_INDEX_CHNL(channel))); | ||
144 | prtd = substream->runtime->private_data; | ||
145 | spin_lock(&prtd->lock); | ||
146 | s6000_pcm_enqueue_dma(substream); | ||
147 | spin_unlock(&prtd->lock); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | if (unlikely(pending & ~7)) { | ||
152 | if (pending & (1 << 3)) | ||
153 | printk(KERN_WARNING | ||
154 | "s6000-pcm: DMA %x Underflow\n", | ||
155 | channel); | ||
156 | if (pending & (1 << 4)) | ||
157 | printk(KERN_WARNING | ||
158 | "s6000-pcm: DMA %x Overflow\n", | ||
159 | channel); | ||
160 | if (pending & 0x1e0) | ||
161 | printk(KERN_WARNING | ||
162 | "s6000-pcm: DMA %x Master Error " | ||
163 | "(mask %x)\n", | ||
164 | channel, pending >> 5); | ||
165 | |||
166 | } | ||
167 | } | ||
168 | |||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | static int s6000_pcm_start(struct snd_pcm_substream *substream) | ||
173 | { | ||
174 | struct s6000_runtime_data *prtd = substream->runtime->private_data; | ||
175 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | ||
176 | struct s6000_pcm_dma_params *par; | ||
177 | unsigned long flags; | ||
178 | int srcinc; | ||
179 | u32 dma; | ||
180 | |||
181 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); | ||
182 | |||
183 | spin_lock_irqsave(&prtd->lock, flags); | ||
184 | |||
185 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
186 | srcinc = 1; | ||
187 | dma = par->dma_out; | ||
188 | } else { | ||
189 | srcinc = 0; | ||
190 | dma = par->dma_in; | ||
191 | } | ||
192 | s6dmac_enable_chan(DMA_MASK_DMAC(dma), DMA_INDEX_CHNL(dma), | ||
193 | 1 /* priority 1 (0 is max) */, | ||
194 | 0 /* peripheral requests w/o xfer length mode */, | ||
195 | srcinc /* source address increment */, | ||
196 | srcinc^1 /* destination address increment */, | ||
197 | 0 /* chunksize 0 (skip impossible on this dma) */, | ||
198 | 0 /* source skip after chunk (impossible) */, | ||
199 | 0 /* destination skip after chunk (impossible) */, | ||
200 | 4 /* 16 byte burst size */, | ||
201 | -1 /* don't conserve bandwidth */, | ||
202 | 0 /* low watermark irq descriptor threshold */, | ||
203 | 0 /* disable hardware timestamps */, | ||
204 | 1 /* enable channel */); | ||
205 | |||
206 | s6000_pcm_enqueue_dma(substream); | ||
207 | s6000_pcm_enqueue_dma(substream); | ||
208 | |||
209 | spin_unlock_irqrestore(&prtd->lock, flags); | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int s6000_pcm_stop(struct snd_pcm_substream *substream) | ||
215 | { | ||
216 | struct s6000_runtime_data *prtd = substream->runtime->private_data; | ||
217 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | ||
218 | struct s6000_pcm_dma_params *par; | ||
219 | unsigned long flags; | ||
220 | u32 channel; | ||
221 | |||
222 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); | ||
223 | |||
224 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
225 | channel = par->dma_out; | ||
226 | else | ||
227 | channel = par->dma_in; | ||
228 | |||
229 | s6dmac_set_terminal_count(DMA_MASK_DMAC(channel), | ||
230 | DMA_INDEX_CHNL(channel), 0); | ||
231 | |||
232 | spin_lock_irqsave(&prtd->lock, flags); | ||
233 | |||
234 | s6dmac_disable_chan(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel)); | ||
235 | |||
236 | spin_unlock_irqrestore(&prtd->lock, flags); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
242 | { | ||
243 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | ||
244 | struct s6000_pcm_dma_params *par; | ||
245 | int ret; | ||
246 | |||
247 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); | ||
248 | |||
249 | ret = par->trigger(substream, cmd, 0); | ||
250 | if (ret < 0) | ||
251 | return ret; | ||
252 | |||
253 | switch (cmd) { | ||
254 | case SNDRV_PCM_TRIGGER_START: | ||
255 | case SNDRV_PCM_TRIGGER_RESUME: | ||
256 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
257 | ret = s6000_pcm_start(substream); | ||
258 | break; | ||
259 | case SNDRV_PCM_TRIGGER_STOP: | ||
260 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
261 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
262 | ret = s6000_pcm_stop(substream); | ||
263 | break; | ||
264 | default: | ||
265 | ret = -EINVAL; | ||
266 | } | ||
267 | if (ret < 0) | ||
268 | return ret; | ||
269 | |||
270 | return par->trigger(substream, cmd, 1); | ||
271 | } | ||
272 | |||
273 | static int s6000_pcm_prepare(struct snd_pcm_substream *substream) | ||
274 | { | ||
275 | struct s6000_runtime_data *prtd = substream->runtime->private_data; | ||
276 | |||
277 | prtd->period = 0; | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream) | ||
283 | { | ||
284 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | ||
285 | struct s6000_pcm_dma_params *par; | ||
286 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
287 | struct s6000_runtime_data *prtd = runtime->private_data; | ||
288 | unsigned long flags; | ||
289 | unsigned int offset; | ||
290 | dma_addr_t count; | ||
291 | |||
292 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); | ||
293 | |||
294 | spin_lock_irqsave(&prtd->lock, flags); | ||
295 | |||
296 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
297 | count = s6dmac_cur_src(DMA_MASK_DMAC(par->dma_out), | ||
298 | DMA_INDEX_CHNL(par->dma_out)); | ||
299 | else | ||
300 | count = s6dmac_cur_dst(DMA_MASK_DMAC(par->dma_in), | ||
301 | DMA_INDEX_CHNL(par->dma_in)); | ||
302 | |||
303 | count -= runtime->dma_addr; | ||
304 | |||
305 | spin_unlock_irqrestore(&prtd->lock, flags); | ||
306 | |||
307 | offset = bytes_to_frames(runtime, count); | ||
308 | if (unlikely(offset >= runtime->buffer_size)) | ||
309 | offset = 0; | ||
310 | |||
311 | return offset; | ||
312 | } | ||
313 | |||
314 | static int s6000_pcm_open(struct snd_pcm_substream *substream) | ||
315 | { | ||
316 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | ||
317 | struct s6000_pcm_dma_params *par; | ||
318 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
319 | struct s6000_runtime_data *prtd; | ||
320 | int ret; | ||
321 | |||
322 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); | ||
323 | snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware); | ||
324 | |||
325 | ret = snd_pcm_hw_constraint_step(runtime, 0, | ||
326 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16); | ||
327 | if (ret < 0) | ||
328 | return ret; | ||
329 | ret = snd_pcm_hw_constraint_step(runtime, 0, | ||
330 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16); | ||
331 | if (ret < 0) | ||
332 | return ret; | ||
333 | ret = snd_pcm_hw_constraint_integer(runtime, | ||
334 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
335 | if (ret < 0) | ||
336 | return ret; | ||
337 | |||
338 | if (par->same_rate) { | ||
339 | int rate; | ||
340 | spin_lock(&par->lock); /* needed? */ | ||
341 | rate = par->rate; | ||
342 | spin_unlock(&par->lock); | ||
343 | if (rate != -1) { | ||
344 | ret = snd_pcm_hw_constraint_minmax(runtime, | ||
345 | SNDRV_PCM_HW_PARAM_RATE, | ||
346 | rate, rate); | ||
347 | if (ret < 0) | ||
348 | return ret; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | prtd = kzalloc(sizeof(struct s6000_runtime_data), GFP_KERNEL); | ||
353 | if (prtd == NULL) | ||
354 | return -ENOMEM; | ||
355 | |||
356 | spin_lock_init(&prtd->lock); | ||
357 | |||
358 | runtime->private_data = prtd; | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int s6000_pcm_close(struct snd_pcm_substream *substream) | ||
364 | { | ||
365 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
366 | struct s6000_runtime_data *prtd = runtime->private_data; | ||
367 | |||
368 | kfree(prtd); | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int s6000_pcm_hw_params(struct snd_pcm_substream *substream, | ||
374 | struct snd_pcm_hw_params *hw_params) | ||
375 | { | ||
376 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | ||
377 | struct s6000_pcm_dma_params *par; | ||
378 | int ret; | ||
379 | ret = snd_pcm_lib_malloc_pages(substream, | ||
380 | params_buffer_bytes(hw_params)); | ||
381 | if (ret < 0) { | ||
382 | printk(KERN_WARNING "s6000-pcm: allocation of memory failed\n"); | ||
383 | return ret; | ||
384 | } | ||
385 | |||
386 | par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); | ||
387 | |||
388 | if (par->same_rate) { | ||
389 | spin_lock(&par->lock); | ||
390 | if (par->rate == -1 || | ||
391 | !(par->in_use & ~(1 << substream->stream))) { | ||
392 | par->rate = params_rate(hw_params); | ||
393 | par->in_use |= 1 << substream->stream; | ||
394 | } else if (params_rate(hw_params) != par->rate) { | ||
395 | snd_pcm_lib_free_pages(substream); | ||
396 | par->in_use &= ~(1 << substream->stream); | ||
397 | ret = -EBUSY; | ||
398 | } | ||
399 | spin_unlock(&par->lock); | ||
400 | } | ||
401 | return ret; | ||
402 | } | ||
403 | |||
404 | static int s6000_pcm_hw_free(struct snd_pcm_substream *substream) | ||
405 | { | ||
406 | struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; | ||
407 | struct s6000_pcm_dma_params *par = | ||
408 | snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); | ||
409 | |||
410 | spin_lock(&par->lock); | ||
411 | par->in_use &= ~(1 << substream->stream); | ||
412 | if (!par->in_use) | ||
413 | par->rate = -1; | ||
414 | spin_unlock(&par->lock); | ||
415 | |||
416 | return snd_pcm_lib_free_pages(substream); | ||
417 | } | ||
418 | |||
419 | static struct snd_pcm_ops s6000_pcm_ops = { | ||
420 | .open = s6000_pcm_open, | ||
421 | .close = s6000_pcm_close, | ||
422 | .ioctl = snd_pcm_lib_ioctl, | ||
423 | .hw_params = s6000_pcm_hw_params, | ||
424 | .hw_free = s6000_pcm_hw_free, | ||
425 | .trigger = s6000_pcm_trigger, | ||
426 | .prepare = s6000_pcm_prepare, | ||
427 | .pointer = s6000_pcm_pointer, | ||
428 | }; | ||
429 | |||
430 | static void s6000_pcm_free(struct snd_pcm *pcm) | ||
431 | { | ||
432 | struct snd_soc_pcm_runtime *runtime = pcm->private_data; | ||
433 | struct s6000_pcm_dma_params *params = | ||
434 | snd_soc_dai_get_dma_data(runtime->cpu_dai, | ||
435 | pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream); | ||
436 | |||
437 | free_irq(params->irq, pcm); | ||
438 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
439 | } | ||
440 | |||
441 | static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime) | ||
442 | { | ||
443 | struct snd_card *card = runtime->card->snd_card; | ||
444 | struct snd_pcm *pcm = runtime->pcm; | ||
445 | struct s6000_pcm_dma_params *params; | ||
446 | int res; | ||
447 | |||
448 | params = snd_soc_dai_get_dma_data(runtime->cpu_dai, | ||
449 | pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream); | ||
450 | |||
451 | res = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); | ||
452 | if (res) | ||
453 | return res; | ||
454 | |||
455 | if (params->dma_in) { | ||
456 | s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_in), | ||
457 | DMA_INDEX_CHNL(params->dma_in)); | ||
458 | s6dmac_int_sources(DMA_MASK_DMAC(params->dma_in), | ||
459 | DMA_INDEX_CHNL(params->dma_in)); | ||
460 | } | ||
461 | |||
462 | if (params->dma_out) { | ||
463 | s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_out), | ||
464 | DMA_INDEX_CHNL(params->dma_out)); | ||
465 | s6dmac_int_sources(DMA_MASK_DMAC(params->dma_out), | ||
466 | DMA_INDEX_CHNL(params->dma_out)); | ||
467 | } | ||
468 | |||
469 | res = request_irq(params->irq, s6000_pcm_irq, IRQF_SHARED, | ||
470 | "s6000-audio", pcm); | ||
471 | if (res) { | ||
472 | printk(KERN_ERR "s6000-pcm couldn't get IRQ\n"); | ||
473 | return res; | ||
474 | } | ||
475 | |||
476 | res = snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
477 | SNDRV_DMA_TYPE_DEV, | ||
478 | card->dev, | ||
479 | S6_PCM_PREALLOCATE_SIZE, | ||
480 | S6_PCM_PREALLOCATE_MAX); | ||
481 | if (res) | ||
482 | printk(KERN_WARNING "s6000-pcm: preallocation failed\n"); | ||
483 | |||
484 | spin_lock_init(¶ms->lock); | ||
485 | params->in_use = 0; | ||
486 | params->rate = -1; | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static struct snd_soc_platform_driver s6000_soc_platform = { | ||
491 | .ops = &s6000_pcm_ops, | ||
492 | .pcm_new = s6000_pcm_new, | ||
493 | .pcm_free = s6000_pcm_free, | ||
494 | }; | ||
495 | |||
496 | static int s6000_soc_platform_probe(struct platform_device *pdev) | ||
497 | { | ||
498 | return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform); | ||
499 | } | ||
500 | |||
501 | static int s6000_soc_platform_remove(struct platform_device *pdev) | ||
502 | { | ||
503 | snd_soc_unregister_platform(&pdev->dev); | ||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | static struct platform_driver s6000_pcm_driver = { | ||
508 | .driver = { | ||
509 | .name = "s6000-pcm-audio", | ||
510 | .owner = THIS_MODULE, | ||
511 | }, | ||
512 | |||
513 | .probe = s6000_soc_platform_probe, | ||
514 | .remove = s6000_soc_platform_remove, | ||
515 | }; | ||
516 | |||
517 | module_platform_driver(s6000_pcm_driver); | ||
518 | |||
519 | MODULE_AUTHOR("Daniel Gloeckner"); | ||
520 | MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module"); | ||
521 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s6000/s6000-pcm.h b/sound/soc/s6000/s6000-pcm.h deleted file mode 100644 index 09d9b883e58b..000000000000 --- a/sound/soc/s6000/s6000-pcm.h +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA PCM interface for the Stretch s6000 family | ||
3 | * | ||
4 | * Author: Daniel Gloeckner, <dg@emlix.com> | ||
5 | * Copyright: (C) 2009 emlix GmbH <info@emlix.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 _S6000_PCM_H | ||
13 | #define _S6000_PCM_H | ||
14 | |||
15 | struct snd_soc_dai; | ||
16 | struct snd_pcm_substream; | ||
17 | |||
18 | struct s6000_pcm_dma_params { | ||
19 | unsigned int (*check_xrun)(struct snd_soc_dai *cpu_dai); | ||
20 | int (*trigger)(struct snd_pcm_substream *substream, int cmd, int after); | ||
21 | dma_addr_t sif_in; | ||
22 | dma_addr_t sif_out; | ||
23 | u32 dma_in; | ||
24 | u32 dma_out; | ||
25 | int irq; | ||
26 | int same_rate; | ||
27 | |||
28 | spinlock_t lock; | ||
29 | int in_use; | ||
30 | int rate; | ||
31 | }; | ||
32 | |||
33 | #endif | ||
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c deleted file mode 100644 index 3510c01f8a6a..000000000000 --- a/sound/soc/s6000/s6105-ipcam.c +++ /dev/null | |||
@@ -1,221 +0,0 @@ | |||
1 | /* | ||
2 | * ASoC driver for Stretch s6105 IP camera platform | ||
3 | * | ||
4 | * Author: Daniel Gloeckner, <dg@emlix.com> | ||
5 | * Copyright: (C) 2009 emlix GmbH <info@emlix.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/timer.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <sound/core.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/soc.h> | ||
21 | |||
22 | #include "s6000-pcm.h" | ||
23 | #include "s6000-i2s.h" | ||
24 | |||
25 | #define S6105_CAM_CODEC_CLOCK 12288000 | ||
26 | |||
27 | static int s6105_hw_params(struct snd_pcm_substream *substream, | ||
28 | struct snd_pcm_hw_params *params) | ||
29 | { | ||
30 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
31 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
32 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
33 | int ret = 0; | ||
34 | |||
35 | /* set codec DAI configuration */ | ||
36 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
37 | SND_SOC_DAIFMT_CBM_CFM); | ||
38 | if (ret < 0) | ||
39 | return ret; | ||
40 | |||
41 | /* set cpu DAI configuration */ | ||
42 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM | | ||
43 | SND_SOC_DAIFMT_NB_NF); | ||
44 | if (ret < 0) | ||
45 | return ret; | ||
46 | |||
47 | /* set the codec system clock */ | ||
48 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, S6105_CAM_CODEC_CLOCK, | ||
49 | SND_SOC_CLOCK_OUT); | ||
50 | if (ret < 0) | ||
51 | return ret; | ||
52 | |||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static struct snd_soc_ops s6105_ops = { | ||
57 | .hw_params = s6105_hw_params, | ||
58 | }; | ||
59 | |||
60 | /* s6105 machine dapm widgets */ | ||
61 | static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | ||
62 | SND_SOC_DAPM_LINE("Audio Out Differential", NULL), | ||
63 | SND_SOC_DAPM_LINE("Audio Out Stereo", NULL), | ||
64 | SND_SOC_DAPM_LINE("Audio In", NULL), | ||
65 | }; | ||
66 | |||
67 | /* s6105 machine audio_mapnections to the codec pins */ | ||
68 | static const struct snd_soc_dapm_route audio_map[] = { | ||
69 | /* Audio Out connected to HPLOUT, HPLCOM, HPROUT */ | ||
70 | {"Audio Out Differential", NULL, "HPLOUT"}, | ||
71 | {"Audio Out Differential", NULL, "HPLCOM"}, | ||
72 | {"Audio Out Stereo", NULL, "HPLOUT"}, | ||
73 | {"Audio Out Stereo", NULL, "HPROUT"}, | ||
74 | |||
75 | /* Audio In connected to LINE1L, LINE1R */ | ||
76 | {"LINE1L", NULL, "Audio In"}, | ||
77 | {"LINE1R", NULL, "Audio In"}, | ||
78 | }; | ||
79 | |||
80 | static int output_type_info(struct snd_kcontrol *kcontrol, | ||
81 | struct snd_ctl_elem_info *uinfo) | ||
82 | { | ||
83 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
84 | uinfo->count = 1; | ||
85 | uinfo->value.enumerated.items = 2; | ||
86 | if (uinfo->value.enumerated.item) { | ||
87 | uinfo->value.enumerated.item = 1; | ||
88 | strcpy(uinfo->value.enumerated.name, "HPLOUT/HPROUT"); | ||
89 | } else { | ||
90 | strcpy(uinfo->value.enumerated.name, "HPLOUT/HPLCOM"); | ||
91 | } | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static int output_type_get(struct snd_kcontrol *kcontrol, | ||
96 | struct snd_ctl_elem_value *ucontrol) | ||
97 | { | ||
98 | ucontrol->value.enumerated.item[0] = kcontrol->private_value; | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static int output_type_put(struct snd_kcontrol *kcontrol, | ||
103 | struct snd_ctl_elem_value *ucontrol) | ||
104 | { | ||
105 | struct snd_soc_card *card = kcontrol->private_data; | ||
106 | struct snd_soc_dapm_context *dapm = &card->dapm; | ||
107 | unsigned int val = (ucontrol->value.enumerated.item[0] != 0); | ||
108 | char *differential = "Audio Out Differential"; | ||
109 | char *stereo = "Audio Out Stereo"; | ||
110 | |||
111 | if (kcontrol->private_value == val) | ||
112 | return 0; | ||
113 | kcontrol->private_value = val; | ||
114 | snd_soc_dapm_disable_pin(dapm, val ? differential : stereo); | ||
115 | snd_soc_dapm_sync(dapm); | ||
116 | snd_soc_dapm_enable_pin(dapm, val ? stereo : differential); | ||
117 | snd_soc_dapm_sync(dapm); | ||
118 | |||
119 | return 1; | ||
120 | } | ||
121 | |||
122 | static const struct snd_kcontrol_new audio_out_mux = { | ||
123 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
124 | .name = "Master Output Mux", | ||
125 | .index = 0, | ||
126 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
127 | .info = output_type_info, | ||
128 | .get = output_type_get, | ||
129 | .put = output_type_put, | ||
130 | .private_value = 1 /* default to stereo */ | ||
131 | }; | ||
132 | |||
133 | /* Logic for a aic3x as connected on the s6105 ip camera ref design */ | ||
134 | static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) | ||
135 | { | ||
136 | struct snd_soc_card *card = rtd->card; | ||
137 | |||
138 | /* must correspond to audio_out_mux.private_value initializer */ | ||
139 | snd_soc_dapm_disable_pin(&card->dapm, "Audio Out Differential"); | ||
140 | |||
141 | snd_ctl_add(card->snd_card, snd_ctl_new1(&audio_out_mux, card)); | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | /* s6105 digital audio interface glue - connects codec <--> CPU */ | ||
147 | static struct snd_soc_dai_link s6105_dai = { | ||
148 | .name = "TLV320AIC31", | ||
149 | .stream_name = "AIC31", | ||
150 | .cpu_dai_name = "s6000-i2s", | ||
151 | .codec_dai_name = "tlv320aic3x-hifi", | ||
152 | .platform_name = "s6000-pcm-audio", | ||
153 | .codec_name = "tlv320aic3x-codec.0-001a", | ||
154 | .init = s6105_aic3x_init, | ||
155 | .ops = &s6105_ops, | ||
156 | }; | ||
157 | |||
158 | /* s6105 audio machine driver */ | ||
159 | static struct snd_soc_card snd_soc_card_s6105 = { | ||
160 | .name = "Stretch IP Camera", | ||
161 | .owner = THIS_MODULE, | ||
162 | .dai_link = &s6105_dai, | ||
163 | .num_links = 1, | ||
164 | |||
165 | .dapm_widgets = aic3x_dapm_widgets, | ||
166 | .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), | ||
167 | .dapm_routes = audio_map, | ||
168 | .num_dapm_routes = ARRAY_SIZE(audio_map), | ||
169 | .fully_routed = true, | ||
170 | }; | ||
171 | |||
172 | static struct s6000_snd_platform_data s6105_snd_data __initdata = { | ||
173 | .wide = 0, | ||
174 | .channel_in = 0, | ||
175 | .channel_out = 1, | ||
176 | .lines_in = 1, | ||
177 | .lines_out = 1, | ||
178 | .same_rate = 1, | ||
179 | }; | ||
180 | |||
181 | static struct platform_device *s6105_snd_device; | ||
182 | |||
183 | /* temporary i2c device creation until this can be moved into the machine | ||
184 | * support file. | ||
185 | */ | ||
186 | static struct i2c_board_info i2c_device[] = { | ||
187 | { I2C_BOARD_INFO("tlv320aic33", 0x18), } | ||
188 | }; | ||
189 | |||
190 | static int __init s6105_init(void) | ||
191 | { | ||
192 | int ret; | ||
193 | |||
194 | i2c_register_board_info(0, i2c_device, ARRAY_SIZE(i2c_device)); | ||
195 | |||
196 | s6105_snd_device = platform_device_alloc("soc-audio", -1); | ||
197 | if (!s6105_snd_device) | ||
198 | return -ENOMEM; | ||
199 | |||
200 | platform_set_drvdata(s6105_snd_device, &snd_soc_card_s6105); | ||
201 | platform_device_add_data(s6105_snd_device, &s6105_snd_data, | ||
202 | sizeof(s6105_snd_data)); | ||
203 | |||
204 | ret = platform_device_add(s6105_snd_device); | ||
205 | if (ret) | ||
206 | platform_device_put(s6105_snd_device); | ||
207 | |||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | static void __exit s6105_exit(void) | ||
212 | { | ||
213 | platform_device_unregister(s6105_snd_device); | ||
214 | } | ||
215 | |||
216 | module_init(s6105_init); | ||
217 | module_exit(s6105_exit); | ||
218 | |||
219 | MODULE_AUTHOR("Daniel Gloeckner"); | ||
220 | MODULE_DESCRIPTION("Stretch s6105 IP camera ASoC driver"); | ||
221 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index e1615113fd84..7952a625669d 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c | |||
@@ -288,7 +288,7 @@ static int s3c_ac97_mic_dai_probe(struct snd_soc_dai *dai) | |||
288 | static struct snd_soc_dai_driver s3c_ac97_dai[] = { | 288 | static struct snd_soc_dai_driver s3c_ac97_dai[] = { |
289 | [S3C_AC97_DAI_PCM] = { | 289 | [S3C_AC97_DAI_PCM] = { |
290 | .name = "samsung-ac97", | 290 | .name = "samsung-ac97", |
291 | .ac97_control = 1, | 291 | .bus_control = true, |
292 | .playback = { | 292 | .playback = { |
293 | .stream_name = "AC97 Playback", | 293 | .stream_name = "AC97 Playback", |
294 | .channels_min = 2, | 294 | .channels_min = 2, |
@@ -306,7 +306,7 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = { | |||
306 | }, | 306 | }, |
307 | [S3C_AC97_DAI_MIC] = { | 307 | [S3C_AC97_DAI_MIC] = { |
308 | .name = "samsung-ac97-mic", | 308 | .name = "samsung-ac97-mic", |
309 | .ac97_control = 1, | 309 | .bus_control = true, |
310 | .capture = { | 310 | .capture = { |
311 | .stream_name = "AC97 Mic Capture", | 311 | .stream_name = "AC97 Mic Capture", |
312 | .channels_min = 1, | 312 | .channels_min = 1, |
diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 0acf5d0eed53..72118a77dd5b 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c | |||
@@ -110,6 +110,7 @@ static const struct of_device_id snow_of_match[] = { | |||
110 | { .compatible = "google,snow-audio-max98095", }, | 110 | { .compatible = "google,snow-audio-max98095", }, |
111 | {}, | 111 | {}, |
112 | }; | 112 | }; |
113 | MODULE_DEVICE_TABLE(of, snow_of_match); | ||
113 | 114 | ||
114 | static struct platform_driver snow_driver = { | 115 | static struct platform_driver snow_driver = { |
115 | .driver = { | 116 | .driver = { |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 66fddec9543d..88e5df474ccf 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -1711,8 +1711,7 @@ static const struct snd_soc_dai_ops fsi_dai_ops = { | |||
1711 | static struct snd_pcm_hardware fsi_pcm_hardware = { | 1711 | static struct snd_pcm_hardware fsi_pcm_hardware = { |
1712 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 1712 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
1713 | SNDRV_PCM_INFO_MMAP | | 1713 | SNDRV_PCM_INFO_MMAP | |
1714 | SNDRV_PCM_INFO_MMAP_VALID | | 1714 | SNDRV_PCM_INFO_MMAP_VALID, |
1715 | SNDRV_PCM_INFO_PAUSE, | ||
1716 | .buffer_bytes_max = 64 * 1024, | 1715 | .buffer_bytes_max = 64 * 1024, |
1717 | .period_bytes_min = 32, | 1716 | .period_bytes_min = 32, |
1718 | .period_bytes_max = 8192, | 1717 | .period_bytes_max = 8192, |
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index 0af2e4dfd139..d5f567e085ff 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c | |||
@@ -272,7 +272,7 @@ static const struct snd_soc_dai_ops hac_dai_ops = { | |||
272 | static struct snd_soc_dai_driver sh4_hac_dai[] = { | 272 | static struct snd_soc_dai_driver sh4_hac_dai[] = { |
273 | { | 273 | { |
274 | .name = "hac-dai.0", | 274 | .name = "hac-dai.0", |
275 | .ac97_control = 1, | 275 | .bus_control = true, |
276 | .playback = { | 276 | .playback = { |
277 | .rates = AC97_RATES, | 277 | .rates = AC97_RATES, |
278 | .formats = AC97_FMTS, | 278 | .formats = AC97_FMTS, |
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1922ec57d10a..70042197f9e2 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -886,8 +886,7 @@ static int rsnd_dai_probe(struct platform_device *pdev, | |||
886 | static struct snd_pcm_hardware rsnd_pcm_hardware = { | 886 | static struct snd_pcm_hardware rsnd_pcm_hardware = { |
887 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 887 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
888 | SNDRV_PCM_INFO_MMAP | | 888 | SNDRV_PCM_INFO_MMAP | |
889 | SNDRV_PCM_INFO_MMAP_VALID | | 889 | SNDRV_PCM_INFO_MMAP_VALID, |
890 | SNDRV_PCM_INFO_PAUSE, | ||
891 | .buffer_bytes_max = 64 * 1024, | 890 | .buffer_bytes_max = 64 * 1024, |
892 | .period_bytes_min = 32, | 891 | .period_bytes_min = 32, |
893 | .period_bytes_max = 8192, | 892 | .period_bytes_max = 8192, |
diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c new file mode 100644 index 000000000000..2e10e9a38376 --- /dev/null +++ b/sound/soc/soc-ac97.c | |||
@@ -0,0 +1,256 @@ | |||
1 | /* | ||
2 | * soc-ac97.c -- ALSA SoC Audio Layer AC97 support | ||
3 | * | ||
4 | * Copyright 2005 Wolfson Microelectronics PLC. | ||
5 | * Copyright 2005 Openedhand Ltd. | ||
6 | * Copyright (C) 2010 Slimlogic Ltd. | ||
7 | * Copyright (C) 2010 Texas Instruments Inc. | ||
8 | * | ||
9 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> | ||
10 | * with code, comments and ideas from :- | ||
11 | * Richard Purdie <richard@openedhand.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | */ | ||
18 | |||
19 | #include <linux/ctype.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/export.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/of_gpio.h> | ||
25 | #include <linux/of.h> | ||
26 | #include <linux/pinctrl/consumer.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <sound/ac97_codec.h> | ||
29 | #include <sound/soc.h> | ||
30 | |||
31 | struct snd_ac97_reset_cfg { | ||
32 | struct pinctrl *pctl; | ||
33 | struct pinctrl_state *pstate_reset; | ||
34 | struct pinctrl_state *pstate_warm_reset; | ||
35 | struct pinctrl_state *pstate_run; | ||
36 | int gpio_sdata; | ||
37 | int gpio_sync; | ||
38 | int gpio_reset; | ||
39 | }; | ||
40 | |||
41 | static struct snd_ac97_bus soc_ac97_bus = { | ||
42 | .ops = NULL, /* Gets initialized in snd_soc_set_ac97_ops() */ | ||
43 | }; | ||
44 | |||
45 | static void soc_ac97_device_release(struct device *dev) | ||
46 | { | ||
47 | kfree(to_ac97_t(dev)); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * snd_soc_new_ac97_codec - initailise AC97 device | ||
52 | * @codec: audio codec | ||
53 | * | ||
54 | * Initialises AC97 codec resources for use by ad-hoc devices only. | ||
55 | */ | ||
56 | struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec) | ||
57 | { | ||
58 | struct snd_ac97 *ac97; | ||
59 | int ret; | ||
60 | |||
61 | ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); | ||
62 | if (ac97 == NULL) | ||
63 | return ERR_PTR(-ENOMEM); | ||
64 | |||
65 | ac97->bus = &soc_ac97_bus; | ||
66 | ac97->num = 0; | ||
67 | |||
68 | ac97->dev.bus = &ac97_bus_type; | ||
69 | ac97->dev.parent = codec->component.card->dev; | ||
70 | ac97->dev.release = soc_ac97_device_release; | ||
71 | |||
72 | dev_set_name(&ac97->dev, "%d-%d:%s", | ||
73 | codec->component.card->snd_card->number, 0, | ||
74 | codec->component.name); | ||
75 | |||
76 | ret = device_register(&ac97->dev); | ||
77 | if (ret) { | ||
78 | put_device(&ac97->dev); | ||
79 | return ERR_PTR(ret); | ||
80 | } | ||
81 | |||
82 | return ac97; | ||
83 | } | ||
84 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | ||
85 | |||
86 | /** | ||
87 | * snd_soc_free_ac97_codec - free AC97 codec device | ||
88 | * @codec: audio codec | ||
89 | * | ||
90 | * Frees AC97 codec device resources. | ||
91 | */ | ||
92 | void snd_soc_free_ac97_codec(struct snd_ac97 *ac97) | ||
93 | { | ||
94 | device_del(&ac97->dev); | ||
95 | ac97->bus = NULL; | ||
96 | put_device(&ac97->dev); | ||
97 | } | ||
98 | EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); | ||
99 | |||
100 | static struct snd_ac97_reset_cfg snd_ac97_rst_cfg; | ||
101 | |||
102 | static void snd_soc_ac97_warm_reset(struct snd_ac97 *ac97) | ||
103 | { | ||
104 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
105 | |||
106 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_warm_reset); | ||
107 | |||
108 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 1); | ||
109 | |||
110 | udelay(10); | ||
111 | |||
112 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
113 | |||
114 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
115 | msleep(2); | ||
116 | } | ||
117 | |||
118 | static void snd_soc_ac97_reset(struct snd_ac97 *ac97) | ||
119 | { | ||
120 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
121 | |||
122 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_reset); | ||
123 | |||
124 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
125 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sdata, 0); | ||
126 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 0); | ||
127 | |||
128 | udelay(10); | ||
129 | |||
130 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 1); | ||
131 | |||
132 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
133 | msleep(2); | ||
134 | } | ||
135 | |||
136 | static int snd_soc_ac97_parse_pinctl(struct device *dev, | ||
137 | struct snd_ac97_reset_cfg *cfg) | ||
138 | { | ||
139 | struct pinctrl *p; | ||
140 | struct pinctrl_state *state; | ||
141 | int gpio; | ||
142 | int ret; | ||
143 | |||
144 | p = devm_pinctrl_get(dev); | ||
145 | if (IS_ERR(p)) { | ||
146 | dev_err(dev, "Failed to get pinctrl\n"); | ||
147 | return PTR_ERR(p); | ||
148 | } | ||
149 | cfg->pctl = p; | ||
150 | |||
151 | state = pinctrl_lookup_state(p, "ac97-reset"); | ||
152 | if (IS_ERR(state)) { | ||
153 | dev_err(dev, "Can't find pinctrl state ac97-reset\n"); | ||
154 | return PTR_ERR(state); | ||
155 | } | ||
156 | cfg->pstate_reset = state; | ||
157 | |||
158 | state = pinctrl_lookup_state(p, "ac97-warm-reset"); | ||
159 | if (IS_ERR(state)) { | ||
160 | dev_err(dev, "Can't find pinctrl state ac97-warm-reset\n"); | ||
161 | return PTR_ERR(state); | ||
162 | } | ||
163 | cfg->pstate_warm_reset = state; | ||
164 | |||
165 | state = pinctrl_lookup_state(p, "ac97-running"); | ||
166 | if (IS_ERR(state)) { | ||
167 | dev_err(dev, "Can't find pinctrl state ac97-running\n"); | ||
168 | return PTR_ERR(state); | ||
169 | } | ||
170 | cfg->pstate_run = state; | ||
171 | |||
172 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 0); | ||
173 | if (gpio < 0) { | ||
174 | dev_err(dev, "Can't find ac97-sync gpio\n"); | ||
175 | return gpio; | ||
176 | } | ||
177 | ret = devm_gpio_request(dev, gpio, "AC97 link sync"); | ||
178 | if (ret) { | ||
179 | dev_err(dev, "Failed requesting ac97-sync gpio\n"); | ||
180 | return ret; | ||
181 | } | ||
182 | cfg->gpio_sync = gpio; | ||
183 | |||
184 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 1); | ||
185 | if (gpio < 0) { | ||
186 | dev_err(dev, "Can't find ac97-sdata gpio %d\n", gpio); | ||
187 | return gpio; | ||
188 | } | ||
189 | ret = devm_gpio_request(dev, gpio, "AC97 link sdata"); | ||
190 | if (ret) { | ||
191 | dev_err(dev, "Failed requesting ac97-sdata gpio\n"); | ||
192 | return ret; | ||
193 | } | ||
194 | cfg->gpio_sdata = gpio; | ||
195 | |||
196 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 2); | ||
197 | if (gpio < 0) { | ||
198 | dev_err(dev, "Can't find ac97-reset gpio\n"); | ||
199 | return gpio; | ||
200 | } | ||
201 | ret = devm_gpio_request(dev, gpio, "AC97 link reset"); | ||
202 | if (ret) { | ||
203 | dev_err(dev, "Failed requesting ac97-reset gpio\n"); | ||
204 | return ret; | ||
205 | } | ||
206 | cfg->gpio_reset = gpio; | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | struct snd_ac97_bus_ops *soc_ac97_ops; | ||
212 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
213 | |||
214 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | ||
215 | { | ||
216 | if (ops == soc_ac97_ops) | ||
217 | return 0; | ||
218 | |||
219 | if (soc_ac97_ops && ops) | ||
220 | return -EBUSY; | ||
221 | |||
222 | soc_ac97_ops = ops; | ||
223 | soc_ac97_bus.ops = ops; | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); | ||
228 | |||
229 | /** | ||
230 | * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions | ||
231 | * | ||
232 | * This function sets the reset and warm_reset properties of ops and parses | ||
233 | * the device node of pdev to get pinctrl states and gpio numbers to use. | ||
234 | */ | ||
235 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | ||
236 | struct platform_device *pdev) | ||
237 | { | ||
238 | struct device *dev = &pdev->dev; | ||
239 | struct snd_ac97_reset_cfg cfg; | ||
240 | int ret; | ||
241 | |||
242 | ret = snd_soc_ac97_parse_pinctl(dev, &cfg); | ||
243 | if (ret) | ||
244 | return ret; | ||
245 | |||
246 | ret = snd_soc_set_ac97_ops(ops); | ||
247 | if (ret) | ||
248 | return ret; | ||
249 | |||
250 | ops->warm_reset = snd_soc_ac97_warm_reset; | ||
251 | ops->reset = snd_soc_ac97_reset; | ||
252 | |||
253 | snd_ac97_rst_cfg = cfg; | ||
254 | return 0; | ||
255 | } | ||
256 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset); | ||
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index a9f82b5aba9d..07f43356f963 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -15,56 +15,6 @@ | |||
15 | #include <linux/export.h> | 15 | #include <linux/export.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | 17 | ||
18 | #include <trace/events/asoc.h> | ||
19 | |||
20 | static bool snd_soc_set_cache_val(void *base, unsigned int idx, | ||
21 | unsigned int val, unsigned int word_size) | ||
22 | { | ||
23 | switch (word_size) { | ||
24 | case 1: { | ||
25 | u8 *cache = base; | ||
26 | if (cache[idx] == val) | ||
27 | return true; | ||
28 | cache[idx] = val; | ||
29 | break; | ||
30 | } | ||
31 | case 2: { | ||
32 | u16 *cache = base; | ||
33 | if (cache[idx] == val) | ||
34 | return true; | ||
35 | cache[idx] = val; | ||
36 | break; | ||
37 | } | ||
38 | default: | ||
39 | WARN(1, "Invalid word_size %d\n", word_size); | ||
40 | break; | ||
41 | } | ||
42 | return false; | ||
43 | } | ||
44 | |||
45 | static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx, | ||
46 | unsigned int word_size) | ||
47 | { | ||
48 | if (!base) | ||
49 | return -1; | ||
50 | |||
51 | switch (word_size) { | ||
52 | case 1: { | ||
53 | const u8 *cache = base; | ||
54 | return cache[idx]; | ||
55 | } | ||
56 | case 2: { | ||
57 | const u16 *cache = base; | ||
58 | return cache[idx]; | ||
59 | } | ||
60 | default: | ||
61 | WARN(1, "Invalid word_size %d\n", word_size); | ||
62 | break; | ||
63 | } | ||
64 | /* unreachable */ | ||
65 | return -1; | ||
66 | } | ||
67 | |||
68 | int snd_soc_cache_init(struct snd_soc_codec *codec) | 18 | int snd_soc_cache_init(struct snd_soc_codec *codec) |
69 | { | 19 | { |
70 | const struct snd_soc_codec_driver *codec_drv = codec->driver; | 20 | const struct snd_soc_codec_driver *codec_drv = codec->driver; |
@@ -75,8 +25,6 @@ int snd_soc_cache_init(struct snd_soc_codec *codec) | |||
75 | if (!reg_size) | 25 | if (!reg_size) |
76 | return 0; | 26 | return 0; |
77 | 27 | ||
78 | mutex_init(&codec->cache_rw_mutex); | ||
79 | |||
80 | dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n", | 28 | dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n", |
81 | codec->component.name); | 29 | codec->component.name); |
82 | 30 | ||
@@ -103,100 +51,3 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec) | |||
103 | codec->reg_cache = NULL; | 51 | codec->reg_cache = NULL; |
104 | return 0; | 52 | return 0; |
105 | } | 53 | } |
106 | |||
107 | /** | ||
108 | * snd_soc_cache_read: Fetch the value of a given register from the cache. | ||
109 | * | ||
110 | * @codec: CODEC to configure. | ||
111 | * @reg: The register index. | ||
112 | * @value: The value to be returned. | ||
113 | */ | ||
114 | int snd_soc_cache_read(struct snd_soc_codec *codec, | ||
115 | unsigned int reg, unsigned int *value) | ||
116 | { | ||
117 | if (!value) | ||
118 | return -EINVAL; | ||
119 | |||
120 | mutex_lock(&codec->cache_rw_mutex); | ||
121 | if (!ZERO_OR_NULL_PTR(codec->reg_cache)) | ||
122 | *value = snd_soc_get_cache_val(codec->reg_cache, reg, | ||
123 | codec->driver->reg_word_size); | ||
124 | mutex_unlock(&codec->cache_rw_mutex); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | EXPORT_SYMBOL_GPL(snd_soc_cache_read); | ||
129 | |||
130 | /** | ||
131 | * snd_soc_cache_write: Set the value of a given register in the cache. | ||
132 | * | ||
133 | * @codec: CODEC to configure. | ||
134 | * @reg: The register index. | ||
135 | * @value: The new register value. | ||
136 | */ | ||
137 | int snd_soc_cache_write(struct snd_soc_codec *codec, | ||
138 | unsigned int reg, unsigned int value) | ||
139 | { | ||
140 | mutex_lock(&codec->cache_rw_mutex); | ||
141 | if (!ZERO_OR_NULL_PTR(codec->reg_cache)) | ||
142 | snd_soc_set_cache_val(codec->reg_cache, reg, value, | ||
143 | codec->driver->reg_word_size); | ||
144 | mutex_unlock(&codec->cache_rw_mutex); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | EXPORT_SYMBOL_GPL(snd_soc_cache_write); | ||
149 | |||
150 | static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec) | ||
151 | { | ||
152 | int i; | ||
153 | int ret; | ||
154 | const struct snd_soc_codec_driver *codec_drv; | ||
155 | unsigned int val; | ||
156 | |||
157 | codec_drv = codec->driver; | ||
158 | for (i = 0; i < codec_drv->reg_cache_size; ++i) { | ||
159 | ret = snd_soc_cache_read(codec, i, &val); | ||
160 | if (ret) | ||
161 | return ret; | ||
162 | if (codec_drv->reg_cache_default) | ||
163 | if (snd_soc_get_cache_val(codec_drv->reg_cache_default, | ||
164 | i, codec_drv->reg_word_size) == val) | ||
165 | continue; | ||
166 | |||
167 | ret = snd_soc_write(codec, i, val); | ||
168 | if (ret) | ||
169 | return ret; | ||
170 | dev_dbg(codec->dev, "ASoC: Synced register %#x, value = %#x\n", | ||
171 | i, val); | ||
172 | } | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * snd_soc_cache_sync: Sync the register cache with the hardware. | ||
178 | * | ||
179 | * @codec: CODEC to configure. | ||
180 | * | ||
181 | * Any registers that should not be synced should be marked as | ||
182 | * volatile. In general drivers can choose not to use the provided | ||
183 | * syncing functionality if they so require. | ||
184 | */ | ||
185 | int snd_soc_cache_sync(struct snd_soc_codec *codec) | ||
186 | { | ||
187 | const char *name = "flat"; | ||
188 | int ret; | ||
189 | |||
190 | if (!codec->cache_sync) | ||
191 | return 0; | ||
192 | |||
193 | dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n", | ||
194 | codec->component.name); | ||
195 | trace_snd_soc_cache_sync(codec, name, "start"); | ||
196 | ret = snd_soc_flat_cache_sync(codec); | ||
197 | if (!ret) | ||
198 | codec->cache_sync = 0; | ||
199 | trace_snd_soc_cache_sync(codec, name, "end"); | ||
200 | return ret; | ||
201 | } | ||
202 | EXPORT_SYMBOL_GPL(snd_soc_cache_sync); | ||
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index cecfab3cc948..590a82f01d0b 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c | |||
@@ -258,10 +258,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) | |||
258 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) | 258 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) |
259 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; | 259 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; |
260 | 260 | ||
261 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | 261 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); |
262 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); | ||
263 | else | ||
264 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); | ||
265 | 262 | ||
266 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; | 263 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; |
267 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | 264 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; |
@@ -456,11 +453,7 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, | |||
456 | if (ret < 0) | 453 | if (ret < 0) |
457 | goto out; | 454 | goto out; |
458 | 455 | ||
459 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | 456 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); |
460 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); | ||
461 | else | ||
462 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); | ||
463 | |||
464 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; | 457 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; |
465 | 458 | ||
466 | out: | 459 | out: |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4c8f8a23a0e9..11d01e5a2f70 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -34,9 +34,6 @@ | |||
34 | #include <linux/ctype.h> | 34 | #include <linux/ctype.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/of.h> | 36 | #include <linux/of.h> |
37 | #include <linux/gpio.h> | ||
38 | #include <linux/of_gpio.h> | ||
39 | #include <sound/ac97_codec.h> | ||
40 | #include <sound/core.h> | 37 | #include <sound/core.h> |
41 | #include <sound/jack.h> | 38 | #include <sound/jack.h> |
42 | #include <sound/pcm.h> | 39 | #include <sound/pcm.h> |
@@ -69,16 +66,6 @@ static int pmdown_time = 5000; | |||
69 | module_param(pmdown_time, int, 0); | 66 | module_param(pmdown_time, int, 0); |
70 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 67 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
71 | 68 | ||
72 | struct snd_ac97_reset_cfg { | ||
73 | struct pinctrl *pctl; | ||
74 | struct pinctrl_state *pstate_reset; | ||
75 | struct pinctrl_state *pstate_warm_reset; | ||
76 | struct pinctrl_state *pstate_run; | ||
77 | int gpio_sdata; | ||
78 | int gpio_sync; | ||
79 | int gpio_reset; | ||
80 | }; | ||
81 | |||
82 | /* returns the minimum number of bytes needed to represent | 69 | /* returns the minimum number of bytes needed to represent |
83 | * a particular given value */ | 70 | * a particular given value */ |
84 | static int min_bytes_needed(unsigned long val) | 71 | static int min_bytes_needed(unsigned long val) |
@@ -309,9 +296,6 @@ static void soc_init_codec_debugfs(struct snd_soc_component *component) | |||
309 | { | 296 | { |
310 | struct snd_soc_codec *codec = snd_soc_component_to_codec(component); | 297 | struct snd_soc_codec *codec = snd_soc_component_to_codec(component); |
311 | 298 | ||
312 | debugfs_create_bool("cache_sync", 0444, codec->component.debugfs_root, | ||
313 | &codec->cache_sync); | ||
314 | |||
315 | codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, | 299 | codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, |
316 | codec->component.debugfs_root, | 300 | codec->component.debugfs_root, |
317 | codec, &codec_reg_fops); | 301 | codec, &codec_reg_fops); |
@@ -499,40 +483,6 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, | |||
499 | } | 483 | } |
500 | EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime); | 484 | EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime); |
501 | 485 | ||
502 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
503 | /* unregister ac97 codec */ | ||
504 | static int soc_ac97_dev_unregister(struct snd_soc_codec *codec) | ||
505 | { | ||
506 | if (codec->ac97->dev.bus) | ||
507 | device_unregister(&codec->ac97->dev); | ||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | /* stop no dev release warning */ | ||
512 | static void soc_ac97_device_release(struct device *dev){} | ||
513 | |||
514 | /* register ac97 codec to bus */ | ||
515 | static int soc_ac97_dev_register(struct snd_soc_codec *codec) | ||
516 | { | ||
517 | int err; | ||
518 | |||
519 | codec->ac97->dev.bus = &ac97_bus_type; | ||
520 | codec->ac97->dev.parent = codec->component.card->dev; | ||
521 | codec->ac97->dev.release = soc_ac97_device_release; | ||
522 | |||
523 | dev_set_name(&codec->ac97->dev, "%d-%d:%s", | ||
524 | codec->component.card->snd_card->number, 0, | ||
525 | codec->component.name); | ||
526 | err = device_register(&codec->ac97->dev); | ||
527 | if (err < 0) { | ||
528 | dev_err(codec->dev, "ASoC: Can't register ac97 bus\n"); | ||
529 | codec->ac97->dev.bus = NULL; | ||
530 | return err; | ||
531 | } | ||
532 | return 0; | ||
533 | } | ||
534 | #endif | ||
535 | |||
536 | static void codec2codec_close_delayed_work(struct work_struct *work) | 486 | static void codec2codec_close_delayed_work(struct work_struct *work) |
537 | { | 487 | { |
538 | /* Currently nothing to do for c2c links | 488 | /* Currently nothing to do for c2c links |
@@ -592,17 +542,12 @@ int snd_soc_suspend(struct device *dev) | |||
592 | 542 | ||
593 | for (i = 0; i < card->num_rtd; i++) { | 543 | for (i = 0; i < card->num_rtd; i++) { |
594 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 544 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
595 | struct snd_soc_platform *platform = card->rtd[i].platform; | ||
596 | 545 | ||
597 | if (card->rtd[i].dai_link->ignore_suspend) | 546 | if (card->rtd[i].dai_link->ignore_suspend) |
598 | continue; | 547 | continue; |
599 | 548 | ||
600 | if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control) | 549 | if (cpu_dai->driver->suspend && !cpu_dai->driver->bus_control) |
601 | cpu_dai->driver->suspend(cpu_dai); | 550 | cpu_dai->driver->suspend(cpu_dai); |
602 | if (platform->driver->suspend && !platform->suspended) { | ||
603 | platform->driver->suspend(cpu_dai); | ||
604 | platform->suspended = 1; | ||
605 | } | ||
606 | } | 551 | } |
607 | 552 | ||
608 | /* close any waiting streams and save state */ | 553 | /* close any waiting streams and save state */ |
@@ -629,8 +574,8 @@ int snd_soc_suspend(struct device *dev) | |||
629 | SND_SOC_DAPM_STREAM_SUSPEND); | 574 | SND_SOC_DAPM_STREAM_SUSPEND); |
630 | } | 575 | } |
631 | 576 | ||
632 | /* Recheck all analogue paths too */ | 577 | /* Recheck all endpoints too, their state is affected by suspend */ |
633 | dapm_mark_io_dirty(&card->dapm); | 578 | dapm_mark_endpoints_dirty(card); |
634 | snd_soc_dapm_sync(&card->dapm); | 579 | snd_soc_dapm_sync(&card->dapm); |
635 | 580 | ||
636 | /* suspend all CODECs */ | 581 | /* suspend all CODECs */ |
@@ -656,7 +601,6 @@ int snd_soc_suspend(struct device *dev) | |||
656 | if (codec->driver->suspend) | 601 | if (codec->driver->suspend) |
657 | codec->driver->suspend(codec); | 602 | codec->driver->suspend(codec); |
658 | codec->suspended = 1; | 603 | codec->suspended = 1; |
659 | codec->cache_sync = 1; | ||
660 | if (codec->component.regmap) | 604 | if (codec->component.regmap) |
661 | regcache_mark_dirty(codec->component.regmap); | 605 | regcache_mark_dirty(codec->component.regmap); |
662 | /* deactivate pins to sleep state */ | 606 | /* deactivate pins to sleep state */ |
@@ -676,7 +620,7 @@ int snd_soc_suspend(struct device *dev) | |||
676 | if (card->rtd[i].dai_link->ignore_suspend) | 620 | if (card->rtd[i].dai_link->ignore_suspend) |
677 | continue; | 621 | continue; |
678 | 622 | ||
679 | if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control) | 623 | if (cpu_dai->driver->suspend && cpu_dai->driver->bus_control) |
680 | cpu_dai->driver->suspend(cpu_dai); | 624 | cpu_dai->driver->suspend(cpu_dai); |
681 | 625 | ||
682 | /* deactivate pins to sleep state */ | 626 | /* deactivate pins to sleep state */ |
@@ -712,14 +656,14 @@ static void soc_resume_deferred(struct work_struct *work) | |||
712 | if (card->resume_pre) | 656 | if (card->resume_pre) |
713 | card->resume_pre(card); | 657 | card->resume_pre(card); |
714 | 658 | ||
715 | /* resume AC97 DAIs */ | 659 | /* resume control bus DAIs */ |
716 | for (i = 0; i < card->num_rtd; i++) { | 660 | for (i = 0; i < card->num_rtd; i++) { |
717 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 661 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
718 | 662 | ||
719 | if (card->rtd[i].dai_link->ignore_suspend) | 663 | if (card->rtd[i].dai_link->ignore_suspend) |
720 | continue; | 664 | continue; |
721 | 665 | ||
722 | if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control) | 666 | if (cpu_dai->driver->resume && cpu_dai->driver->bus_control) |
723 | cpu_dai->driver->resume(cpu_dai); | 667 | cpu_dai->driver->resume(cpu_dai); |
724 | } | 668 | } |
725 | 669 | ||
@@ -775,17 +719,12 @@ static void soc_resume_deferred(struct work_struct *work) | |||
775 | 719 | ||
776 | for (i = 0; i < card->num_rtd; i++) { | 720 | for (i = 0; i < card->num_rtd; i++) { |
777 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 721 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
778 | struct snd_soc_platform *platform = card->rtd[i].platform; | ||
779 | 722 | ||
780 | if (card->rtd[i].dai_link->ignore_suspend) | 723 | if (card->rtd[i].dai_link->ignore_suspend) |
781 | continue; | 724 | continue; |
782 | 725 | ||
783 | if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control) | 726 | if (cpu_dai->driver->resume && !cpu_dai->driver->bus_control) |
784 | cpu_dai->driver->resume(cpu_dai); | 727 | cpu_dai->driver->resume(cpu_dai); |
785 | if (platform->driver->resume && platform->suspended) { | ||
786 | platform->driver->resume(cpu_dai); | ||
787 | platform->suspended = 0; | ||
788 | } | ||
789 | } | 728 | } |
790 | 729 | ||
791 | if (card->resume_post) | 730 | if (card->resume_post) |
@@ -796,8 +735,8 @@ static void soc_resume_deferred(struct work_struct *work) | |||
796 | /* userspace can access us now we are back as we were before */ | 735 | /* userspace can access us now we are back as we were before */ |
797 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); | 736 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); |
798 | 737 | ||
799 | /* Recheck all analogue paths too */ | 738 | /* Recheck all endpoints too, their state is affected by suspend */ |
800 | dapm_mark_io_dirty(&card->dapm); | 739 | dapm_mark_endpoints_dirty(card); |
801 | snd_soc_dapm_sync(&card->dapm); | 740 | snd_soc_dapm_sync(&card->dapm); |
802 | } | 741 | } |
803 | 742 | ||
@@ -805,7 +744,8 @@ static void soc_resume_deferred(struct work_struct *work) | |||
805 | int snd_soc_resume(struct device *dev) | 744 | int snd_soc_resume(struct device *dev) |
806 | { | 745 | { |
807 | struct snd_soc_card *card = dev_get_drvdata(dev); | 746 | struct snd_soc_card *card = dev_get_drvdata(dev); |
808 | int i, ac97_control = 0; | 747 | bool bus_control = false; |
748 | int i; | ||
809 | 749 | ||
810 | /* If the card is not initialized yet there is nothing to do */ | 750 | /* If the card is not initialized yet there is nothing to do */ |
811 | if (!card->instantiated) | 751 | if (!card->instantiated) |
@@ -828,17 +768,18 @@ int snd_soc_resume(struct device *dev) | |||
828 | } | 768 | } |
829 | } | 769 | } |
830 | 770 | ||
831 | /* AC97 devices might have other drivers hanging off them so | 771 | /* |
832 | * need to resume immediately. Other drivers don't have that | 772 | * DAIs that also act as the control bus master might have other drivers |
833 | * problem and may take a substantial amount of time to resume | 773 | * hanging off them so need to resume immediately. Other drivers don't |
774 | * have that problem and may take a substantial amount of time to resume | ||
834 | * due to I/O costs and anti-pop so handle them out of line. | 775 | * due to I/O costs and anti-pop so handle them out of line. |
835 | */ | 776 | */ |
836 | for (i = 0; i < card->num_rtd; i++) { | 777 | for (i = 0; i < card->num_rtd; i++) { |
837 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 778 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
838 | ac97_control |= cpu_dai->driver->ac97_control; | 779 | bus_control |= cpu_dai->driver->bus_control; |
839 | } | 780 | } |
840 | if (ac97_control) { | 781 | if (bus_control) { |
841 | dev_dbg(dev, "ASoC: Resuming AC97 immediately\n"); | 782 | dev_dbg(dev, "ASoC: Resuming control bus master immediately\n"); |
842 | soc_resume_deferred(&card->deferred_resume_work); | 783 | soc_resume_deferred(&card->deferred_resume_work); |
843 | } else { | 784 | } else { |
844 | dev_dbg(dev, "ASoC: Scheduling resume work\n"); | 785 | dev_dbg(dev, "ASoC: Scheduling resume work\n"); |
@@ -884,7 +825,7 @@ static struct snd_soc_dai *snd_soc_find_dai( | |||
884 | list_for_each_entry(component, &component_list, list) { | 825 | list_for_each_entry(component, &component_list, list) { |
885 | if (dlc->of_node && component->dev->of_node != dlc->of_node) | 826 | if (dlc->of_node && component->dev->of_node != dlc->of_node) |
886 | continue; | 827 | continue; |
887 | if (dlc->name && strcmp(dev_name(component->dev), dlc->name)) | 828 | if (dlc->name && strcmp(component->name, dlc->name)) |
888 | continue; | 829 | continue; |
889 | list_for_each_entry(dai, &component->dai_list, list) { | 830 | list_for_each_entry(dai, &component->dai_list, list) { |
890 | if (dlc->dai_name && strcmp(dai->name, dlc->dai_name)) | 831 | if (dlc->dai_name && strcmp(dai->name, dlc->dai_name)) |
@@ -1251,25 +1192,22 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num, | |||
1251 | return 0; | 1192 | return 0; |
1252 | } | 1193 | } |
1253 | 1194 | ||
1254 | static int soc_probe_codec_dai(struct snd_soc_card *card, | 1195 | static int soc_probe_dai(struct snd_soc_dai *dai, int order) |
1255 | struct snd_soc_dai *codec_dai, | ||
1256 | int order) | ||
1257 | { | 1196 | { |
1258 | int ret; | 1197 | int ret; |
1259 | 1198 | ||
1260 | if (!codec_dai->probed && codec_dai->driver->probe_order == order) { | 1199 | if (!dai->probed && dai->driver->probe_order == order) { |
1261 | if (codec_dai->driver->probe) { | 1200 | if (dai->driver->probe) { |
1262 | ret = codec_dai->driver->probe(codec_dai); | 1201 | ret = dai->driver->probe(dai); |
1263 | if (ret < 0) { | 1202 | if (ret < 0) { |
1264 | dev_err(codec_dai->dev, | 1203 | dev_err(dai->dev, |
1265 | "ASoC: failed to probe CODEC DAI %s: %d\n", | 1204 | "ASoC: failed to probe DAI %s: %d\n", |
1266 | codec_dai->name, ret); | 1205 | dai->name, ret); |
1267 | return ret; | 1206 | return ret; |
1268 | } | 1207 | } |
1269 | } | 1208 | } |
1270 | 1209 | ||
1271 | /* mark codec_dai as probed and add to card dai list */ | 1210 | dai->probed = 1; |
1272 | codec_dai->probed = 1; | ||
1273 | } | 1211 | } |
1274 | 1212 | ||
1275 | return 0; | 1213 | return 0; |
@@ -1319,40 +1257,22 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1319 | { | 1257 | { |
1320 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 1258 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
1321 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1259 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1322 | struct snd_soc_platform *platform = rtd->platform; | ||
1323 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1260 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1324 | int i, ret; | 1261 | int i, ret; |
1325 | 1262 | ||
1326 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", | 1263 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", |
1327 | card->name, num, order); | 1264 | card->name, num, order); |
1328 | 1265 | ||
1329 | /* config components */ | ||
1330 | cpu_dai->platform = platform; | ||
1331 | cpu_dai->card = card; | ||
1332 | for (i = 0; i < rtd->num_codecs; i++) | ||
1333 | rtd->codec_dais[i]->card = card; | ||
1334 | |||
1335 | /* set default power off timeout */ | 1266 | /* set default power off timeout */ |
1336 | rtd->pmdown_time = pmdown_time; | 1267 | rtd->pmdown_time = pmdown_time; |
1337 | 1268 | ||
1338 | /* probe the cpu_dai */ | 1269 | ret = soc_probe_dai(cpu_dai, order); |
1339 | if (!cpu_dai->probed && | 1270 | if (ret) |
1340 | cpu_dai->driver->probe_order == order) { | 1271 | return ret; |
1341 | if (cpu_dai->driver->probe) { | ||
1342 | ret = cpu_dai->driver->probe(cpu_dai); | ||
1343 | if (ret < 0) { | ||
1344 | dev_err(cpu_dai->dev, | ||
1345 | "ASoC: failed to probe CPU DAI %s: %d\n", | ||
1346 | cpu_dai->name, ret); | ||
1347 | return ret; | ||
1348 | } | ||
1349 | } | ||
1350 | cpu_dai->probed = 1; | ||
1351 | } | ||
1352 | 1272 | ||
1353 | /* probe the CODEC DAI */ | 1273 | /* probe the CODEC DAI */ |
1354 | for (i = 0; i < rtd->num_codecs; i++) { | 1274 | for (i = 0; i < rtd->num_codecs; i++) { |
1355 | ret = soc_probe_codec_dai(card, rtd->codec_dais[i], order); | 1275 | ret = soc_probe_dai(rtd->codec_dais[i], order); |
1356 | if (ret) | 1276 | if (ret) |
1357 | return ret; | 1277 | return ret; |
1358 | } | 1278 | } |
@@ -1422,84 +1342,9 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1422 | } | 1342 | } |
1423 | } | 1343 | } |
1424 | 1344 | ||
1425 | /* add platform data for AC97 devices */ | ||
1426 | for (i = 0; i < rtd->num_codecs; i++) { | ||
1427 | if (rtd->codec_dais[i]->driver->ac97_control) | ||
1428 | snd_ac97_dev_add_pdata(rtd->codec_dais[i]->codec->ac97, | ||
1429 | rtd->cpu_dai->ac97_pdata); | ||
1430 | } | ||
1431 | |||
1432 | return 0; | 1345 | return 0; |
1433 | } | 1346 | } |
1434 | 1347 | ||
1435 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
1436 | static int soc_register_ac97_codec(struct snd_soc_codec *codec, | ||
1437 | struct snd_soc_dai *codec_dai) | ||
1438 | { | ||
1439 | int ret; | ||
1440 | |||
1441 | /* Only instantiate AC97 if not already done by the adaptor | ||
1442 | * for the generic AC97 subsystem. | ||
1443 | */ | ||
1444 | if (codec_dai->driver->ac97_control && !codec->ac97_registered) { | ||
1445 | /* | ||
1446 | * It is possible that the AC97 device is already registered to | ||
1447 | * the device subsystem. This happens when the device is created | ||
1448 | * via snd_ac97_mixer(). Currently only SoC codec that does so | ||
1449 | * is the generic AC97 glue but others migh emerge. | ||
1450 | * | ||
1451 | * In those cases we don't try to register the device again. | ||
1452 | */ | ||
1453 | if (!codec->ac97_created) | ||
1454 | return 0; | ||
1455 | |||
1456 | ret = soc_ac97_dev_register(codec); | ||
1457 | if (ret < 0) { | ||
1458 | dev_err(codec->dev, | ||
1459 | "ASoC: AC97 device register failed: %d\n", ret); | ||
1460 | return ret; | ||
1461 | } | ||
1462 | |||
1463 | codec->ac97_registered = 1; | ||
1464 | } | ||
1465 | return 0; | ||
1466 | } | ||
1467 | |||
1468 | static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) | ||
1469 | { | ||
1470 | if (codec->ac97_registered) { | ||
1471 | soc_ac97_dev_unregister(codec); | ||
1472 | codec->ac97_registered = 0; | ||
1473 | } | ||
1474 | } | ||
1475 | |||
1476 | static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | ||
1477 | { | ||
1478 | int i, ret; | ||
1479 | |||
1480 | for (i = 0; i < rtd->num_codecs; i++) { | ||
1481 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
1482 | |||
1483 | ret = soc_register_ac97_codec(codec_dai->codec, codec_dai); | ||
1484 | if (ret) { | ||
1485 | while (--i >= 0) | ||
1486 | soc_unregister_ac97_codec(codec_dai->codec); | ||
1487 | return ret; | ||
1488 | } | ||
1489 | } | ||
1490 | |||
1491 | return 0; | ||
1492 | } | ||
1493 | |||
1494 | static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | ||
1495 | { | ||
1496 | int i; | ||
1497 | |||
1498 | for (i = 0; i < rtd->num_codecs; i++) | ||
1499 | soc_unregister_ac97_codec(rtd->codec_dais[i]->codec); | ||
1500 | } | ||
1501 | #endif | ||
1502 | |||
1503 | static int soc_bind_aux_dev(struct snd_soc_card *card, int num) | 1348 | static int soc_bind_aux_dev(struct snd_soc_card *card, int num) |
1504 | { | 1349 | { |
1505 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | 1350 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; |
@@ -1793,20 +1638,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1793 | goto probe_aux_dev_err; | 1638 | goto probe_aux_dev_err; |
1794 | } | 1639 | } |
1795 | 1640 | ||
1796 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
1797 | /* register any AC97 codecs */ | ||
1798 | for (i = 0; i < card->num_rtd; i++) { | ||
1799 | ret = soc_register_ac97_dai_link(&card->rtd[i]); | ||
1800 | if (ret < 0) { | ||
1801 | dev_err(card->dev, | ||
1802 | "ASoC: failed to register AC97: %d\n", ret); | ||
1803 | while (--i >= 0) | ||
1804 | soc_unregister_ac97_dai_link(&card->rtd[i]); | ||
1805 | goto probe_aux_dev_err; | ||
1806 | } | ||
1807 | } | ||
1808 | #endif | ||
1809 | |||
1810 | card->instantiated = 1; | 1641 | card->instantiated = 1; |
1811 | snd_soc_dapm_sync(&card->dapm); | 1642 | snd_soc_dapm_sync(&card->dapm); |
1812 | mutex_unlock(&card->mutex); | 1643 | mutex_unlock(&card->mutex); |
@@ -1949,216 +1780,6 @@ static struct platform_driver soc_driver = { | |||
1949 | }; | 1780 | }; |
1950 | 1781 | ||
1951 | /** | 1782 | /** |
1952 | * snd_soc_new_ac97_codec - initailise AC97 device | ||
1953 | * @codec: audio codec | ||
1954 | * @ops: AC97 bus operations | ||
1955 | * @num: AC97 codec number | ||
1956 | * | ||
1957 | * Initialises AC97 codec resources for use by ad-hoc devices only. | ||
1958 | */ | ||
1959 | int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | ||
1960 | struct snd_ac97_bus_ops *ops, int num) | ||
1961 | { | ||
1962 | codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); | ||
1963 | if (codec->ac97 == NULL) | ||
1964 | return -ENOMEM; | ||
1965 | |||
1966 | codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL); | ||
1967 | if (codec->ac97->bus == NULL) { | ||
1968 | kfree(codec->ac97); | ||
1969 | codec->ac97 = NULL; | ||
1970 | return -ENOMEM; | ||
1971 | } | ||
1972 | |||
1973 | codec->ac97->bus->ops = ops; | ||
1974 | codec->ac97->num = num; | ||
1975 | |||
1976 | /* | ||
1977 | * Mark the AC97 device to be created by us. This way we ensure that the | ||
1978 | * device will be registered with the device subsystem later on. | ||
1979 | */ | ||
1980 | codec->ac97_created = 1; | ||
1981 | |||
1982 | return 0; | ||
1983 | } | ||
1984 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | ||
1985 | |||
1986 | static struct snd_ac97_reset_cfg snd_ac97_rst_cfg; | ||
1987 | |||
1988 | static void snd_soc_ac97_warm_reset(struct snd_ac97 *ac97) | ||
1989 | { | ||
1990 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
1991 | |||
1992 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_warm_reset); | ||
1993 | |||
1994 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 1); | ||
1995 | |||
1996 | udelay(10); | ||
1997 | |||
1998 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
1999 | |||
2000 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
2001 | msleep(2); | ||
2002 | } | ||
2003 | |||
2004 | static void snd_soc_ac97_reset(struct snd_ac97 *ac97) | ||
2005 | { | ||
2006 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
2007 | |||
2008 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_reset); | ||
2009 | |||
2010 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
2011 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sdata, 0); | ||
2012 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 0); | ||
2013 | |||
2014 | udelay(10); | ||
2015 | |||
2016 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 1); | ||
2017 | |||
2018 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
2019 | msleep(2); | ||
2020 | } | ||
2021 | |||
2022 | static int snd_soc_ac97_parse_pinctl(struct device *dev, | ||
2023 | struct snd_ac97_reset_cfg *cfg) | ||
2024 | { | ||
2025 | struct pinctrl *p; | ||
2026 | struct pinctrl_state *state; | ||
2027 | int gpio; | ||
2028 | int ret; | ||
2029 | |||
2030 | p = devm_pinctrl_get(dev); | ||
2031 | if (IS_ERR(p)) { | ||
2032 | dev_err(dev, "Failed to get pinctrl\n"); | ||
2033 | return PTR_ERR(p); | ||
2034 | } | ||
2035 | cfg->pctl = p; | ||
2036 | |||
2037 | state = pinctrl_lookup_state(p, "ac97-reset"); | ||
2038 | if (IS_ERR(state)) { | ||
2039 | dev_err(dev, "Can't find pinctrl state ac97-reset\n"); | ||
2040 | return PTR_ERR(state); | ||
2041 | } | ||
2042 | cfg->pstate_reset = state; | ||
2043 | |||
2044 | state = pinctrl_lookup_state(p, "ac97-warm-reset"); | ||
2045 | if (IS_ERR(state)) { | ||
2046 | dev_err(dev, "Can't find pinctrl state ac97-warm-reset\n"); | ||
2047 | return PTR_ERR(state); | ||
2048 | } | ||
2049 | cfg->pstate_warm_reset = state; | ||
2050 | |||
2051 | state = pinctrl_lookup_state(p, "ac97-running"); | ||
2052 | if (IS_ERR(state)) { | ||
2053 | dev_err(dev, "Can't find pinctrl state ac97-running\n"); | ||
2054 | return PTR_ERR(state); | ||
2055 | } | ||
2056 | cfg->pstate_run = state; | ||
2057 | |||
2058 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 0); | ||
2059 | if (gpio < 0) { | ||
2060 | dev_err(dev, "Can't find ac97-sync gpio\n"); | ||
2061 | return gpio; | ||
2062 | } | ||
2063 | ret = devm_gpio_request(dev, gpio, "AC97 link sync"); | ||
2064 | if (ret) { | ||
2065 | dev_err(dev, "Failed requesting ac97-sync gpio\n"); | ||
2066 | return ret; | ||
2067 | } | ||
2068 | cfg->gpio_sync = gpio; | ||
2069 | |||
2070 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 1); | ||
2071 | if (gpio < 0) { | ||
2072 | dev_err(dev, "Can't find ac97-sdata gpio %d\n", gpio); | ||
2073 | return gpio; | ||
2074 | } | ||
2075 | ret = devm_gpio_request(dev, gpio, "AC97 link sdata"); | ||
2076 | if (ret) { | ||
2077 | dev_err(dev, "Failed requesting ac97-sdata gpio\n"); | ||
2078 | return ret; | ||
2079 | } | ||
2080 | cfg->gpio_sdata = gpio; | ||
2081 | |||
2082 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 2); | ||
2083 | if (gpio < 0) { | ||
2084 | dev_err(dev, "Can't find ac97-reset gpio\n"); | ||
2085 | return gpio; | ||
2086 | } | ||
2087 | ret = devm_gpio_request(dev, gpio, "AC97 link reset"); | ||
2088 | if (ret) { | ||
2089 | dev_err(dev, "Failed requesting ac97-reset gpio\n"); | ||
2090 | return ret; | ||
2091 | } | ||
2092 | cfg->gpio_reset = gpio; | ||
2093 | |||
2094 | return 0; | ||
2095 | } | ||
2096 | |||
2097 | struct snd_ac97_bus_ops *soc_ac97_ops; | ||
2098 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
2099 | |||
2100 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | ||
2101 | { | ||
2102 | if (ops == soc_ac97_ops) | ||
2103 | return 0; | ||
2104 | |||
2105 | if (soc_ac97_ops && ops) | ||
2106 | return -EBUSY; | ||
2107 | |||
2108 | soc_ac97_ops = ops; | ||
2109 | |||
2110 | return 0; | ||
2111 | } | ||
2112 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); | ||
2113 | |||
2114 | /** | ||
2115 | * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions | ||
2116 | * | ||
2117 | * This function sets the reset and warm_reset properties of ops and parses | ||
2118 | * the device node of pdev to get pinctrl states and gpio numbers to use. | ||
2119 | */ | ||
2120 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | ||
2121 | struct platform_device *pdev) | ||
2122 | { | ||
2123 | struct device *dev = &pdev->dev; | ||
2124 | struct snd_ac97_reset_cfg cfg; | ||
2125 | int ret; | ||
2126 | |||
2127 | ret = snd_soc_ac97_parse_pinctl(dev, &cfg); | ||
2128 | if (ret) | ||
2129 | return ret; | ||
2130 | |||
2131 | ret = snd_soc_set_ac97_ops(ops); | ||
2132 | if (ret) | ||
2133 | return ret; | ||
2134 | |||
2135 | ops->warm_reset = snd_soc_ac97_warm_reset; | ||
2136 | ops->reset = snd_soc_ac97_reset; | ||
2137 | |||
2138 | snd_ac97_rst_cfg = cfg; | ||
2139 | return 0; | ||
2140 | } | ||
2141 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset); | ||
2142 | |||
2143 | /** | ||
2144 | * snd_soc_free_ac97_codec - free AC97 codec device | ||
2145 | * @codec: audio codec | ||
2146 | * | ||
2147 | * Frees AC97 codec device resources. | ||
2148 | */ | ||
2149 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) | ||
2150 | { | ||
2151 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
2152 | soc_unregister_ac97_codec(codec); | ||
2153 | #endif | ||
2154 | kfree(codec->ac97->bus); | ||
2155 | kfree(codec->ac97); | ||
2156 | codec->ac97 = NULL; | ||
2157 | codec->ac97_created = 0; | ||
2158 | } | ||
2159 | EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); | ||
2160 | |||
2161 | /** | ||
2162 | * snd_soc_cnew - create new control | 1783 | * snd_soc_cnew - create new control |
2163 | * @_template: control template | 1784 | * @_template: control template |
2164 | * @data: control private data | 1785 | * @data: control private data |
@@ -2326,7 +1947,7 @@ EXPORT_SYMBOL_GPL(snd_soc_add_card_controls); | |||
2326 | int snd_soc_add_dai_controls(struct snd_soc_dai *dai, | 1947 | int snd_soc_add_dai_controls(struct snd_soc_dai *dai, |
2327 | const struct snd_kcontrol_new *controls, int num_controls) | 1948 | const struct snd_kcontrol_new *controls, int num_controls) |
2328 | { | 1949 | { |
2329 | struct snd_card *card = dai->card->snd_card; | 1950 | struct snd_card *card = dai->component->card->snd_card; |
2330 | 1951 | ||
2331 | return snd_soc_add_controls(card, dai->dev, controls, num_controls, | 1952 | return snd_soc_add_controls(card, dai->dev, controls, num_controls, |
2332 | NULL, dai); | 1953 | NULL, dai); |
@@ -2334,1020 +1955,6 @@ int snd_soc_add_dai_controls(struct snd_soc_dai *dai, | |||
2334 | EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); | 1955 | EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); |
2335 | 1956 | ||
2336 | /** | 1957 | /** |
2337 | * snd_soc_info_enum_double - enumerated double mixer info callback | ||
2338 | * @kcontrol: mixer control | ||
2339 | * @uinfo: control element information | ||
2340 | * | ||
2341 | * Callback to provide information about a double enumerated | ||
2342 | * mixer control. | ||
2343 | * | ||
2344 | * Returns 0 for success. | ||
2345 | */ | ||
2346 | int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, | ||
2347 | struct snd_ctl_elem_info *uinfo) | ||
2348 | { | ||
2349 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
2350 | |||
2351 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2352 | uinfo->count = e->shift_l == e->shift_r ? 1 : 2; | ||
2353 | uinfo->value.enumerated.items = e->items; | ||
2354 | |||
2355 | if (uinfo->value.enumerated.item >= e->items) | ||
2356 | uinfo->value.enumerated.item = e->items - 1; | ||
2357 | strlcpy(uinfo->value.enumerated.name, | ||
2358 | e->texts[uinfo->value.enumerated.item], | ||
2359 | sizeof(uinfo->value.enumerated.name)); | ||
2360 | return 0; | ||
2361 | } | ||
2362 | EXPORT_SYMBOL_GPL(snd_soc_info_enum_double); | ||
2363 | |||
2364 | /** | ||
2365 | * snd_soc_get_enum_double - enumerated double mixer get callback | ||
2366 | * @kcontrol: mixer control | ||
2367 | * @ucontrol: control element information | ||
2368 | * | ||
2369 | * Callback to get the value of a double enumerated mixer. | ||
2370 | * | ||
2371 | * Returns 0 for success. | ||
2372 | */ | ||
2373 | int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, | ||
2374 | struct snd_ctl_elem_value *ucontrol) | ||
2375 | { | ||
2376 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2377 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
2378 | unsigned int val, item; | ||
2379 | unsigned int reg_val; | ||
2380 | int ret; | ||
2381 | |||
2382 | ret = snd_soc_component_read(component, e->reg, ®_val); | ||
2383 | if (ret) | ||
2384 | return ret; | ||
2385 | val = (reg_val >> e->shift_l) & e->mask; | ||
2386 | item = snd_soc_enum_val_to_item(e, val); | ||
2387 | ucontrol->value.enumerated.item[0] = item; | ||
2388 | if (e->shift_l != e->shift_r) { | ||
2389 | val = (reg_val >> e->shift_l) & e->mask; | ||
2390 | item = snd_soc_enum_val_to_item(e, val); | ||
2391 | ucontrol->value.enumerated.item[1] = item; | ||
2392 | } | ||
2393 | |||
2394 | return 0; | ||
2395 | } | ||
2396 | EXPORT_SYMBOL_GPL(snd_soc_get_enum_double); | ||
2397 | |||
2398 | /** | ||
2399 | * snd_soc_put_enum_double - enumerated double mixer put callback | ||
2400 | * @kcontrol: mixer control | ||
2401 | * @ucontrol: control element information | ||
2402 | * | ||
2403 | * Callback to set the value of a double enumerated mixer. | ||
2404 | * | ||
2405 | * Returns 0 for success. | ||
2406 | */ | ||
2407 | int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | ||
2408 | struct snd_ctl_elem_value *ucontrol) | ||
2409 | { | ||
2410 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2411 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
2412 | unsigned int *item = ucontrol->value.enumerated.item; | ||
2413 | unsigned int val; | ||
2414 | unsigned int mask; | ||
2415 | |||
2416 | if (item[0] >= e->items) | ||
2417 | return -EINVAL; | ||
2418 | val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; | ||
2419 | mask = e->mask << e->shift_l; | ||
2420 | if (e->shift_l != e->shift_r) { | ||
2421 | if (item[1] >= e->items) | ||
2422 | return -EINVAL; | ||
2423 | val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; | ||
2424 | mask |= e->mask << e->shift_r; | ||
2425 | } | ||
2426 | |||
2427 | return snd_soc_component_update_bits(component, e->reg, mask, val); | ||
2428 | } | ||
2429 | EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); | ||
2430 | |||
2431 | /** | ||
2432 | * snd_soc_read_signed - Read a codec register and interprete as signed value | ||
2433 | * @component: component | ||
2434 | * @reg: Register to read | ||
2435 | * @mask: Mask to use after shifting the register value | ||
2436 | * @shift: Right shift of register value | ||
2437 | * @sign_bit: Bit that describes if a number is negative or not. | ||
2438 | * @signed_val: Pointer to where the read value should be stored | ||
2439 | * | ||
2440 | * This functions reads a codec register. The register value is shifted right | ||
2441 | * by 'shift' bits and masked with the given 'mask'. Afterwards it translates | ||
2442 | * the given registervalue into a signed integer if sign_bit is non-zero. | ||
2443 | * | ||
2444 | * Returns 0 on sucess, otherwise an error value | ||
2445 | */ | ||
2446 | static int snd_soc_read_signed(struct snd_soc_component *component, | ||
2447 | unsigned int reg, unsigned int mask, unsigned int shift, | ||
2448 | unsigned int sign_bit, int *signed_val) | ||
2449 | { | ||
2450 | int ret; | ||
2451 | unsigned int val; | ||
2452 | |||
2453 | ret = snd_soc_component_read(component, reg, &val); | ||
2454 | if (ret < 0) | ||
2455 | return ret; | ||
2456 | |||
2457 | val = (val >> shift) & mask; | ||
2458 | |||
2459 | if (!sign_bit) { | ||
2460 | *signed_val = val; | ||
2461 | return 0; | ||
2462 | } | ||
2463 | |||
2464 | /* non-negative number */ | ||
2465 | if (!(val & BIT(sign_bit))) { | ||
2466 | *signed_val = val; | ||
2467 | return 0; | ||
2468 | } | ||
2469 | |||
2470 | ret = val; | ||
2471 | |||
2472 | /* | ||
2473 | * The register most probably does not contain a full-sized int. | ||
2474 | * Instead we have an arbitrary number of bits in a signed | ||
2475 | * representation which has to be translated into a full-sized int. | ||
2476 | * This is done by filling up all bits above the sign-bit. | ||
2477 | */ | ||
2478 | ret |= ~((int)(BIT(sign_bit) - 1)); | ||
2479 | |||
2480 | *signed_val = ret; | ||
2481 | |||
2482 | return 0; | ||
2483 | } | ||
2484 | |||
2485 | /** | ||
2486 | * snd_soc_info_volsw - single mixer info callback | ||
2487 | * @kcontrol: mixer control | ||
2488 | * @uinfo: control element information | ||
2489 | * | ||
2490 | * Callback to provide information about a single mixer control, or a double | ||
2491 | * mixer control that spans 2 registers. | ||
2492 | * | ||
2493 | * Returns 0 for success. | ||
2494 | */ | ||
2495 | int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, | ||
2496 | struct snd_ctl_elem_info *uinfo) | ||
2497 | { | ||
2498 | struct soc_mixer_control *mc = | ||
2499 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2500 | int platform_max; | ||
2501 | |||
2502 | if (!mc->platform_max) | ||
2503 | mc->platform_max = mc->max; | ||
2504 | platform_max = mc->platform_max; | ||
2505 | |||
2506 | if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume")) | ||
2507 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2508 | else | ||
2509 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2510 | |||
2511 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; | ||
2512 | uinfo->value.integer.min = 0; | ||
2513 | uinfo->value.integer.max = platform_max - mc->min; | ||
2514 | return 0; | ||
2515 | } | ||
2516 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); | ||
2517 | |||
2518 | /** | ||
2519 | * snd_soc_get_volsw - single mixer get callback | ||
2520 | * @kcontrol: mixer control | ||
2521 | * @ucontrol: control element information | ||
2522 | * | ||
2523 | * Callback to get the value of a single mixer control, or a double mixer | ||
2524 | * control that spans 2 registers. | ||
2525 | * | ||
2526 | * Returns 0 for success. | ||
2527 | */ | ||
2528 | int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | ||
2529 | struct snd_ctl_elem_value *ucontrol) | ||
2530 | { | ||
2531 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2532 | struct soc_mixer_control *mc = | ||
2533 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2534 | unsigned int reg = mc->reg; | ||
2535 | unsigned int reg2 = mc->rreg; | ||
2536 | unsigned int shift = mc->shift; | ||
2537 | unsigned int rshift = mc->rshift; | ||
2538 | int max = mc->max; | ||
2539 | int min = mc->min; | ||
2540 | int sign_bit = mc->sign_bit; | ||
2541 | unsigned int mask = (1 << fls(max)) - 1; | ||
2542 | unsigned int invert = mc->invert; | ||
2543 | int val; | ||
2544 | int ret; | ||
2545 | |||
2546 | if (sign_bit) | ||
2547 | mask = BIT(sign_bit + 1) - 1; | ||
2548 | |||
2549 | ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val); | ||
2550 | if (ret) | ||
2551 | return ret; | ||
2552 | |||
2553 | ucontrol->value.integer.value[0] = val - min; | ||
2554 | if (invert) | ||
2555 | ucontrol->value.integer.value[0] = | ||
2556 | max - ucontrol->value.integer.value[0]; | ||
2557 | |||
2558 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2559 | if (reg == reg2) | ||
2560 | ret = snd_soc_read_signed(component, reg, mask, rshift, | ||
2561 | sign_bit, &val); | ||
2562 | else | ||
2563 | ret = snd_soc_read_signed(component, reg2, mask, shift, | ||
2564 | sign_bit, &val); | ||
2565 | if (ret) | ||
2566 | return ret; | ||
2567 | |||
2568 | ucontrol->value.integer.value[1] = val - min; | ||
2569 | if (invert) | ||
2570 | ucontrol->value.integer.value[1] = | ||
2571 | max - ucontrol->value.integer.value[1]; | ||
2572 | } | ||
2573 | |||
2574 | return 0; | ||
2575 | } | ||
2576 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw); | ||
2577 | |||
2578 | /** | ||
2579 | * snd_soc_put_volsw - single mixer put callback | ||
2580 | * @kcontrol: mixer control | ||
2581 | * @ucontrol: control element information | ||
2582 | * | ||
2583 | * Callback to set the value of a single mixer control, or a double mixer | ||
2584 | * control that spans 2 registers. | ||
2585 | * | ||
2586 | * Returns 0 for success. | ||
2587 | */ | ||
2588 | int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | ||
2589 | struct snd_ctl_elem_value *ucontrol) | ||
2590 | { | ||
2591 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2592 | struct soc_mixer_control *mc = | ||
2593 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2594 | unsigned int reg = mc->reg; | ||
2595 | unsigned int reg2 = mc->rreg; | ||
2596 | unsigned int shift = mc->shift; | ||
2597 | unsigned int rshift = mc->rshift; | ||
2598 | int max = mc->max; | ||
2599 | int min = mc->min; | ||
2600 | unsigned int sign_bit = mc->sign_bit; | ||
2601 | unsigned int mask = (1 << fls(max)) - 1; | ||
2602 | unsigned int invert = mc->invert; | ||
2603 | int err; | ||
2604 | bool type_2r = false; | ||
2605 | unsigned int val2 = 0; | ||
2606 | unsigned int val, val_mask; | ||
2607 | |||
2608 | if (sign_bit) | ||
2609 | mask = BIT(sign_bit + 1) - 1; | ||
2610 | |||
2611 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
2612 | if (invert) | ||
2613 | val = max - val; | ||
2614 | val_mask = mask << shift; | ||
2615 | val = val << shift; | ||
2616 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2617 | val2 = ((ucontrol->value.integer.value[1] + min) & mask); | ||
2618 | if (invert) | ||
2619 | val2 = max - val2; | ||
2620 | if (reg == reg2) { | ||
2621 | val_mask |= mask << rshift; | ||
2622 | val |= val2 << rshift; | ||
2623 | } else { | ||
2624 | val2 = val2 << shift; | ||
2625 | type_2r = true; | ||
2626 | } | ||
2627 | } | ||
2628 | err = snd_soc_component_update_bits(component, reg, val_mask, val); | ||
2629 | if (err < 0) | ||
2630 | return err; | ||
2631 | |||
2632 | if (type_2r) | ||
2633 | err = snd_soc_component_update_bits(component, reg2, val_mask, | ||
2634 | val2); | ||
2635 | |||
2636 | return err; | ||
2637 | } | ||
2638 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw); | ||
2639 | |||
2640 | /** | ||
2641 | * snd_soc_get_volsw_sx - single mixer get callback | ||
2642 | * @kcontrol: mixer control | ||
2643 | * @ucontrol: control element information | ||
2644 | * | ||
2645 | * Callback to get the value of a single mixer control, or a double mixer | ||
2646 | * control that spans 2 registers. | ||
2647 | * | ||
2648 | * Returns 0 for success. | ||
2649 | */ | ||
2650 | int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, | ||
2651 | struct snd_ctl_elem_value *ucontrol) | ||
2652 | { | ||
2653 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2654 | struct soc_mixer_control *mc = | ||
2655 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2656 | unsigned int reg = mc->reg; | ||
2657 | unsigned int reg2 = mc->rreg; | ||
2658 | unsigned int shift = mc->shift; | ||
2659 | unsigned int rshift = mc->rshift; | ||
2660 | int max = mc->max; | ||
2661 | int min = mc->min; | ||
2662 | int mask = (1 << (fls(min + max) - 1)) - 1; | ||
2663 | unsigned int val; | ||
2664 | int ret; | ||
2665 | |||
2666 | ret = snd_soc_component_read(component, reg, &val); | ||
2667 | if (ret < 0) | ||
2668 | return ret; | ||
2669 | |||
2670 | ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask; | ||
2671 | |||
2672 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2673 | ret = snd_soc_component_read(component, reg2, &val); | ||
2674 | if (ret < 0) | ||
2675 | return ret; | ||
2676 | |||
2677 | val = ((val >> rshift) - min) & mask; | ||
2678 | ucontrol->value.integer.value[1] = val; | ||
2679 | } | ||
2680 | |||
2681 | return 0; | ||
2682 | } | ||
2683 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx); | ||
2684 | |||
2685 | /** | ||
2686 | * snd_soc_put_volsw_sx - double mixer set callback | ||
2687 | * @kcontrol: mixer control | ||
2688 | * @uinfo: control element information | ||
2689 | * | ||
2690 | * Callback to set the value of a double mixer control that spans 2 registers. | ||
2691 | * | ||
2692 | * Returns 0 for success. | ||
2693 | */ | ||
2694 | int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, | ||
2695 | struct snd_ctl_elem_value *ucontrol) | ||
2696 | { | ||
2697 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2698 | struct soc_mixer_control *mc = | ||
2699 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2700 | |||
2701 | unsigned int reg = mc->reg; | ||
2702 | unsigned int reg2 = mc->rreg; | ||
2703 | unsigned int shift = mc->shift; | ||
2704 | unsigned int rshift = mc->rshift; | ||
2705 | int max = mc->max; | ||
2706 | int min = mc->min; | ||
2707 | int mask = (1 << (fls(min + max) - 1)) - 1; | ||
2708 | int err = 0; | ||
2709 | unsigned int val, val_mask, val2 = 0; | ||
2710 | |||
2711 | val_mask = mask << shift; | ||
2712 | val = (ucontrol->value.integer.value[0] + min) & mask; | ||
2713 | val = val << shift; | ||
2714 | |||
2715 | err = snd_soc_component_update_bits(component, reg, val_mask, val); | ||
2716 | if (err < 0) | ||
2717 | return err; | ||
2718 | |||
2719 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2720 | val_mask = mask << rshift; | ||
2721 | val2 = (ucontrol->value.integer.value[1] + min) & mask; | ||
2722 | val2 = val2 << rshift; | ||
2723 | |||
2724 | err = snd_soc_component_update_bits(component, reg2, val_mask, | ||
2725 | val2); | ||
2726 | } | ||
2727 | return err; | ||
2728 | } | ||
2729 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); | ||
2730 | |||
2731 | /** | ||
2732 | * snd_soc_info_volsw_s8 - signed mixer info callback | ||
2733 | * @kcontrol: mixer control | ||
2734 | * @uinfo: control element information | ||
2735 | * | ||
2736 | * Callback to provide information about a signed mixer control. | ||
2737 | * | ||
2738 | * Returns 0 for success. | ||
2739 | */ | ||
2740 | int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, | ||
2741 | struct snd_ctl_elem_info *uinfo) | ||
2742 | { | ||
2743 | struct soc_mixer_control *mc = | ||
2744 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2745 | int platform_max; | ||
2746 | int min = mc->min; | ||
2747 | |||
2748 | if (!mc->platform_max) | ||
2749 | mc->platform_max = mc->max; | ||
2750 | platform_max = mc->platform_max; | ||
2751 | |||
2752 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2753 | uinfo->count = 2; | ||
2754 | uinfo->value.integer.min = 0; | ||
2755 | uinfo->value.integer.max = platform_max - min; | ||
2756 | return 0; | ||
2757 | } | ||
2758 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8); | ||
2759 | |||
2760 | /** | ||
2761 | * snd_soc_get_volsw_s8 - signed mixer get callback | ||
2762 | * @kcontrol: mixer control | ||
2763 | * @ucontrol: control element information | ||
2764 | * | ||
2765 | * Callback to get the value of a signed mixer control. | ||
2766 | * | ||
2767 | * Returns 0 for success. | ||
2768 | */ | ||
2769 | int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, | ||
2770 | struct snd_ctl_elem_value *ucontrol) | ||
2771 | { | ||
2772 | struct soc_mixer_control *mc = | ||
2773 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2774 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2775 | unsigned int reg = mc->reg; | ||
2776 | unsigned int val; | ||
2777 | int min = mc->min; | ||
2778 | int ret; | ||
2779 | |||
2780 | ret = snd_soc_component_read(component, reg, &val); | ||
2781 | if (ret) | ||
2782 | return ret; | ||
2783 | |||
2784 | ucontrol->value.integer.value[0] = | ||
2785 | ((signed char)(val & 0xff))-min; | ||
2786 | ucontrol->value.integer.value[1] = | ||
2787 | ((signed char)((val >> 8) & 0xff))-min; | ||
2788 | return 0; | ||
2789 | } | ||
2790 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_s8); | ||
2791 | |||
2792 | /** | ||
2793 | * snd_soc_put_volsw_sgn - signed mixer put callback | ||
2794 | * @kcontrol: mixer control | ||
2795 | * @ucontrol: control element information | ||
2796 | * | ||
2797 | * Callback to set the value of a signed mixer control. | ||
2798 | * | ||
2799 | * Returns 0 for success. | ||
2800 | */ | ||
2801 | int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, | ||
2802 | struct snd_ctl_elem_value *ucontrol) | ||
2803 | { | ||
2804 | struct soc_mixer_control *mc = | ||
2805 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2806 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2807 | unsigned int reg = mc->reg; | ||
2808 | int min = mc->min; | ||
2809 | unsigned int val; | ||
2810 | |||
2811 | val = (ucontrol->value.integer.value[0]+min) & 0xff; | ||
2812 | val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8; | ||
2813 | |||
2814 | return snd_soc_component_update_bits(component, reg, 0xffff, val); | ||
2815 | } | ||
2816 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); | ||
2817 | |||
2818 | /** | ||
2819 | * snd_soc_info_volsw_range - single mixer info callback with range. | ||
2820 | * @kcontrol: mixer control | ||
2821 | * @uinfo: control element information | ||
2822 | * | ||
2823 | * Callback to provide information, within a range, about a single | ||
2824 | * mixer control. | ||
2825 | * | ||
2826 | * returns 0 for success. | ||
2827 | */ | ||
2828 | int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, | ||
2829 | struct snd_ctl_elem_info *uinfo) | ||
2830 | { | ||
2831 | struct soc_mixer_control *mc = | ||
2832 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2833 | int platform_max; | ||
2834 | int min = mc->min; | ||
2835 | |||
2836 | if (!mc->platform_max) | ||
2837 | mc->platform_max = mc->max; | ||
2838 | platform_max = mc->platform_max; | ||
2839 | |||
2840 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2841 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; | ||
2842 | uinfo->value.integer.min = 0; | ||
2843 | uinfo->value.integer.max = platform_max - min; | ||
2844 | |||
2845 | return 0; | ||
2846 | } | ||
2847 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); | ||
2848 | |||
2849 | /** | ||
2850 | * snd_soc_put_volsw_range - single mixer put value callback with range. | ||
2851 | * @kcontrol: mixer control | ||
2852 | * @ucontrol: control element information | ||
2853 | * | ||
2854 | * Callback to set the value, within a range, for a single mixer control. | ||
2855 | * | ||
2856 | * Returns 0 for success. | ||
2857 | */ | ||
2858 | int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | ||
2859 | struct snd_ctl_elem_value *ucontrol) | ||
2860 | { | ||
2861 | struct soc_mixer_control *mc = | ||
2862 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2863 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2864 | unsigned int reg = mc->reg; | ||
2865 | unsigned int rreg = mc->rreg; | ||
2866 | unsigned int shift = mc->shift; | ||
2867 | int min = mc->min; | ||
2868 | int max = mc->max; | ||
2869 | unsigned int mask = (1 << fls(max)) - 1; | ||
2870 | unsigned int invert = mc->invert; | ||
2871 | unsigned int val, val_mask; | ||
2872 | int ret; | ||
2873 | |||
2874 | if (invert) | ||
2875 | val = (max - ucontrol->value.integer.value[0]) & mask; | ||
2876 | else | ||
2877 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
2878 | val_mask = mask << shift; | ||
2879 | val = val << shift; | ||
2880 | |||
2881 | ret = snd_soc_component_update_bits(component, reg, val_mask, val); | ||
2882 | if (ret < 0) | ||
2883 | return ret; | ||
2884 | |||
2885 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2886 | if (invert) | ||
2887 | val = (max - ucontrol->value.integer.value[1]) & mask; | ||
2888 | else | ||
2889 | val = ((ucontrol->value.integer.value[1] + min) & mask); | ||
2890 | val_mask = mask << shift; | ||
2891 | val = val << shift; | ||
2892 | |||
2893 | ret = snd_soc_component_update_bits(component, rreg, val_mask, | ||
2894 | val); | ||
2895 | } | ||
2896 | |||
2897 | return ret; | ||
2898 | } | ||
2899 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); | ||
2900 | |||
2901 | /** | ||
2902 | * snd_soc_get_volsw_range - single mixer get callback with range | ||
2903 | * @kcontrol: mixer control | ||
2904 | * @ucontrol: control element information | ||
2905 | * | ||
2906 | * Callback to get the value, within a range, of a single mixer control. | ||
2907 | * | ||
2908 | * Returns 0 for success. | ||
2909 | */ | ||
2910 | int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, | ||
2911 | struct snd_ctl_elem_value *ucontrol) | ||
2912 | { | ||
2913 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2914 | struct soc_mixer_control *mc = | ||
2915 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2916 | unsigned int reg = mc->reg; | ||
2917 | unsigned int rreg = mc->rreg; | ||
2918 | unsigned int shift = mc->shift; | ||
2919 | int min = mc->min; | ||
2920 | int max = mc->max; | ||
2921 | unsigned int mask = (1 << fls(max)) - 1; | ||
2922 | unsigned int invert = mc->invert; | ||
2923 | unsigned int val; | ||
2924 | int ret; | ||
2925 | |||
2926 | ret = snd_soc_component_read(component, reg, &val); | ||
2927 | if (ret) | ||
2928 | return ret; | ||
2929 | |||
2930 | ucontrol->value.integer.value[0] = (val >> shift) & mask; | ||
2931 | if (invert) | ||
2932 | ucontrol->value.integer.value[0] = | ||
2933 | max - ucontrol->value.integer.value[0]; | ||
2934 | else | ||
2935 | ucontrol->value.integer.value[0] = | ||
2936 | ucontrol->value.integer.value[0] - min; | ||
2937 | |||
2938 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2939 | ret = snd_soc_component_read(component, rreg, &val); | ||
2940 | if (ret) | ||
2941 | return ret; | ||
2942 | |||
2943 | ucontrol->value.integer.value[1] = (val >> shift) & mask; | ||
2944 | if (invert) | ||
2945 | ucontrol->value.integer.value[1] = | ||
2946 | max - ucontrol->value.integer.value[1]; | ||
2947 | else | ||
2948 | ucontrol->value.integer.value[1] = | ||
2949 | ucontrol->value.integer.value[1] - min; | ||
2950 | } | ||
2951 | |||
2952 | return 0; | ||
2953 | } | ||
2954 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); | ||
2955 | |||
2956 | /** | ||
2957 | * snd_soc_limit_volume - Set new limit to an existing volume control. | ||
2958 | * | ||
2959 | * @codec: where to look for the control | ||
2960 | * @name: Name of the control | ||
2961 | * @max: new maximum limit | ||
2962 | * | ||
2963 | * Return 0 for success, else error. | ||
2964 | */ | ||
2965 | int snd_soc_limit_volume(struct snd_soc_codec *codec, | ||
2966 | const char *name, int max) | ||
2967 | { | ||
2968 | struct snd_card *card = codec->component.card->snd_card; | ||
2969 | struct snd_kcontrol *kctl; | ||
2970 | struct soc_mixer_control *mc; | ||
2971 | int found = 0; | ||
2972 | int ret = -EINVAL; | ||
2973 | |||
2974 | /* Sanity check for name and max */ | ||
2975 | if (unlikely(!name || max <= 0)) | ||
2976 | return -EINVAL; | ||
2977 | |||
2978 | list_for_each_entry(kctl, &card->controls, list) { | ||
2979 | if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) { | ||
2980 | found = 1; | ||
2981 | break; | ||
2982 | } | ||
2983 | } | ||
2984 | if (found) { | ||
2985 | mc = (struct soc_mixer_control *)kctl->private_value; | ||
2986 | if (max <= mc->max) { | ||
2987 | mc->platform_max = max; | ||
2988 | ret = 0; | ||
2989 | } | ||
2990 | } | ||
2991 | return ret; | ||
2992 | } | ||
2993 | EXPORT_SYMBOL_GPL(snd_soc_limit_volume); | ||
2994 | |||
2995 | int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, | ||
2996 | struct snd_ctl_elem_info *uinfo) | ||
2997 | { | ||
2998 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
2999 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
3000 | |||
3001 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
3002 | uinfo->count = params->num_regs * component->val_bytes; | ||
3003 | |||
3004 | return 0; | ||
3005 | } | ||
3006 | EXPORT_SYMBOL_GPL(snd_soc_bytes_info); | ||
3007 | |||
3008 | int snd_soc_bytes_get(struct snd_kcontrol *kcontrol, | ||
3009 | struct snd_ctl_elem_value *ucontrol) | ||
3010 | { | ||
3011 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
3012 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
3013 | int ret; | ||
3014 | |||
3015 | if (component->regmap) | ||
3016 | ret = regmap_raw_read(component->regmap, params->base, | ||
3017 | ucontrol->value.bytes.data, | ||
3018 | params->num_regs * component->val_bytes); | ||
3019 | else | ||
3020 | ret = -EINVAL; | ||
3021 | |||
3022 | /* Hide any masked bytes to ensure consistent data reporting */ | ||
3023 | if (ret == 0 && params->mask) { | ||
3024 | switch (component->val_bytes) { | ||
3025 | case 1: | ||
3026 | ucontrol->value.bytes.data[0] &= ~params->mask; | ||
3027 | break; | ||
3028 | case 2: | ||
3029 | ((u16 *)(&ucontrol->value.bytes.data))[0] | ||
3030 | &= cpu_to_be16(~params->mask); | ||
3031 | break; | ||
3032 | case 4: | ||
3033 | ((u32 *)(&ucontrol->value.bytes.data))[0] | ||
3034 | &= cpu_to_be32(~params->mask); | ||
3035 | break; | ||
3036 | default: | ||
3037 | return -EINVAL; | ||
3038 | } | ||
3039 | } | ||
3040 | |||
3041 | return ret; | ||
3042 | } | ||
3043 | EXPORT_SYMBOL_GPL(snd_soc_bytes_get); | ||
3044 | |||
3045 | int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, | ||
3046 | struct snd_ctl_elem_value *ucontrol) | ||
3047 | { | ||
3048 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
3049 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
3050 | int ret, len; | ||
3051 | unsigned int val, mask; | ||
3052 | void *data; | ||
3053 | |||
3054 | if (!component->regmap || !params->num_regs) | ||
3055 | return -EINVAL; | ||
3056 | |||
3057 | len = params->num_regs * component->val_bytes; | ||
3058 | |||
3059 | data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA); | ||
3060 | if (!data) | ||
3061 | return -ENOMEM; | ||
3062 | |||
3063 | /* | ||
3064 | * If we've got a mask then we need to preserve the register | ||
3065 | * bits. We shouldn't modify the incoming data so take a | ||
3066 | * copy. | ||
3067 | */ | ||
3068 | if (params->mask) { | ||
3069 | ret = regmap_read(component->regmap, params->base, &val); | ||
3070 | if (ret != 0) | ||
3071 | goto out; | ||
3072 | |||
3073 | val &= params->mask; | ||
3074 | |||
3075 | switch (component->val_bytes) { | ||
3076 | case 1: | ||
3077 | ((u8 *)data)[0] &= ~params->mask; | ||
3078 | ((u8 *)data)[0] |= val; | ||
3079 | break; | ||
3080 | case 2: | ||
3081 | mask = ~params->mask; | ||
3082 | ret = regmap_parse_val(component->regmap, | ||
3083 | &mask, &mask); | ||
3084 | if (ret != 0) | ||
3085 | goto out; | ||
3086 | |||
3087 | ((u16 *)data)[0] &= mask; | ||
3088 | |||
3089 | ret = regmap_parse_val(component->regmap, | ||
3090 | &val, &val); | ||
3091 | if (ret != 0) | ||
3092 | goto out; | ||
3093 | |||
3094 | ((u16 *)data)[0] |= val; | ||
3095 | break; | ||
3096 | case 4: | ||
3097 | mask = ~params->mask; | ||
3098 | ret = regmap_parse_val(component->regmap, | ||
3099 | &mask, &mask); | ||
3100 | if (ret != 0) | ||
3101 | goto out; | ||
3102 | |||
3103 | ((u32 *)data)[0] &= mask; | ||
3104 | |||
3105 | ret = regmap_parse_val(component->regmap, | ||
3106 | &val, &val); | ||
3107 | if (ret != 0) | ||
3108 | goto out; | ||
3109 | |||
3110 | ((u32 *)data)[0] |= val; | ||
3111 | break; | ||
3112 | default: | ||
3113 | ret = -EINVAL; | ||
3114 | goto out; | ||
3115 | } | ||
3116 | } | ||
3117 | |||
3118 | ret = regmap_raw_write(component->regmap, params->base, | ||
3119 | data, len); | ||
3120 | |||
3121 | out: | ||
3122 | kfree(data); | ||
3123 | |||
3124 | return ret; | ||
3125 | } | ||
3126 | EXPORT_SYMBOL_GPL(snd_soc_bytes_put); | ||
3127 | |||
3128 | int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, | ||
3129 | struct snd_ctl_elem_info *ucontrol) | ||
3130 | { | ||
3131 | struct soc_bytes_ext *params = (void *)kcontrol->private_value; | ||
3132 | |||
3133 | ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
3134 | ucontrol->count = params->max; | ||
3135 | |||
3136 | return 0; | ||
3137 | } | ||
3138 | EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); | ||
3139 | |||
3140 | int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, | ||
3141 | unsigned int size, unsigned int __user *tlv) | ||
3142 | { | ||
3143 | struct soc_bytes_ext *params = (void *)kcontrol->private_value; | ||
3144 | unsigned int count = size < params->max ? size : params->max; | ||
3145 | int ret = -ENXIO; | ||
3146 | |||
3147 | switch (op_flag) { | ||
3148 | case SNDRV_CTL_TLV_OP_READ: | ||
3149 | if (params->get) | ||
3150 | ret = params->get(tlv, count); | ||
3151 | break; | ||
3152 | case SNDRV_CTL_TLV_OP_WRITE: | ||
3153 | if (params->put) | ||
3154 | ret = params->put(tlv, count); | ||
3155 | break; | ||
3156 | } | ||
3157 | return ret; | ||
3158 | } | ||
3159 | EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); | ||
3160 | |||
3161 | /** | ||
3162 | * snd_soc_info_xr_sx - signed multi register info callback | ||
3163 | * @kcontrol: mreg control | ||
3164 | * @uinfo: control element information | ||
3165 | * | ||
3166 | * Callback to provide information of a control that can | ||
3167 | * span multiple codec registers which together | ||
3168 | * forms a single signed value in a MSB/LSB manner. | ||
3169 | * | ||
3170 | * Returns 0 for success. | ||
3171 | */ | ||
3172 | int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, | ||
3173 | struct snd_ctl_elem_info *uinfo) | ||
3174 | { | ||
3175 | struct soc_mreg_control *mc = | ||
3176 | (struct soc_mreg_control *)kcontrol->private_value; | ||
3177 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
3178 | uinfo->count = 1; | ||
3179 | uinfo->value.integer.min = mc->min; | ||
3180 | uinfo->value.integer.max = mc->max; | ||
3181 | |||
3182 | return 0; | ||
3183 | } | ||
3184 | EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx); | ||
3185 | |||
3186 | /** | ||
3187 | * snd_soc_get_xr_sx - signed multi register get callback | ||
3188 | * @kcontrol: mreg control | ||
3189 | * @ucontrol: control element information | ||
3190 | * | ||
3191 | * Callback to get the value of a control that can span | ||
3192 | * multiple codec registers which together forms a single | ||
3193 | * signed value in a MSB/LSB manner. The control supports | ||
3194 | * specifying total no of bits used to allow for bitfields | ||
3195 | * across the multiple codec registers. | ||
3196 | * | ||
3197 | * Returns 0 for success. | ||
3198 | */ | ||
3199 | int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, | ||
3200 | struct snd_ctl_elem_value *ucontrol) | ||
3201 | { | ||
3202 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
3203 | struct soc_mreg_control *mc = | ||
3204 | (struct soc_mreg_control *)kcontrol->private_value; | ||
3205 | unsigned int regbase = mc->regbase; | ||
3206 | unsigned int regcount = mc->regcount; | ||
3207 | unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; | ||
3208 | unsigned int regwmask = (1<<regwshift)-1; | ||
3209 | unsigned int invert = mc->invert; | ||
3210 | unsigned long mask = (1UL<<mc->nbits)-1; | ||
3211 | long min = mc->min; | ||
3212 | long max = mc->max; | ||
3213 | long val = 0; | ||
3214 | unsigned int regval; | ||
3215 | unsigned int i; | ||
3216 | int ret; | ||
3217 | |||
3218 | for (i = 0; i < regcount; i++) { | ||
3219 | ret = snd_soc_component_read(component, regbase+i, ®val); | ||
3220 | if (ret) | ||
3221 | return ret; | ||
3222 | val |= (regval & regwmask) << (regwshift*(regcount-i-1)); | ||
3223 | } | ||
3224 | val &= mask; | ||
3225 | if (min < 0 && val > max) | ||
3226 | val |= ~mask; | ||
3227 | if (invert) | ||
3228 | val = max - val; | ||
3229 | ucontrol->value.integer.value[0] = val; | ||
3230 | |||
3231 | return 0; | ||
3232 | } | ||
3233 | EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx); | ||
3234 | |||
3235 | /** | ||
3236 | * snd_soc_put_xr_sx - signed multi register get callback | ||
3237 | * @kcontrol: mreg control | ||
3238 | * @ucontrol: control element information | ||
3239 | * | ||
3240 | * Callback to set the value of a control that can span | ||
3241 | * multiple codec registers which together forms a single | ||
3242 | * signed value in a MSB/LSB manner. The control supports | ||
3243 | * specifying total no of bits used to allow for bitfields | ||
3244 | * across the multiple codec registers. | ||
3245 | * | ||
3246 | * Returns 0 for success. | ||
3247 | */ | ||
3248 | int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, | ||
3249 | struct snd_ctl_elem_value *ucontrol) | ||
3250 | { | ||
3251 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
3252 | struct soc_mreg_control *mc = | ||
3253 | (struct soc_mreg_control *)kcontrol->private_value; | ||
3254 | unsigned int regbase = mc->regbase; | ||
3255 | unsigned int regcount = mc->regcount; | ||
3256 | unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; | ||
3257 | unsigned int regwmask = (1<<regwshift)-1; | ||
3258 | unsigned int invert = mc->invert; | ||
3259 | unsigned long mask = (1UL<<mc->nbits)-1; | ||
3260 | long max = mc->max; | ||
3261 | long val = ucontrol->value.integer.value[0]; | ||
3262 | unsigned int i, regval, regmask; | ||
3263 | int err; | ||
3264 | |||
3265 | if (invert) | ||
3266 | val = max - val; | ||
3267 | val &= mask; | ||
3268 | for (i = 0; i < regcount; i++) { | ||
3269 | regval = (val >> (regwshift*(regcount-i-1))) & regwmask; | ||
3270 | regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask; | ||
3271 | err = snd_soc_component_update_bits(component, regbase+i, | ||
3272 | regmask, regval); | ||
3273 | if (err < 0) | ||
3274 | return err; | ||
3275 | } | ||
3276 | |||
3277 | return 0; | ||
3278 | } | ||
3279 | EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx); | ||
3280 | |||
3281 | /** | ||
3282 | * snd_soc_get_strobe - strobe get callback | ||
3283 | * @kcontrol: mixer control | ||
3284 | * @ucontrol: control element information | ||
3285 | * | ||
3286 | * Callback get the value of a strobe mixer control. | ||
3287 | * | ||
3288 | * Returns 0 for success. | ||
3289 | */ | ||
3290 | int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, | ||
3291 | struct snd_ctl_elem_value *ucontrol) | ||
3292 | { | ||
3293 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
3294 | struct soc_mixer_control *mc = | ||
3295 | (struct soc_mixer_control *)kcontrol->private_value; | ||
3296 | unsigned int reg = mc->reg; | ||
3297 | unsigned int shift = mc->shift; | ||
3298 | unsigned int mask = 1 << shift; | ||
3299 | unsigned int invert = mc->invert != 0; | ||
3300 | unsigned int val; | ||
3301 | int ret; | ||
3302 | |||
3303 | ret = snd_soc_component_read(component, reg, &val); | ||
3304 | if (ret) | ||
3305 | return ret; | ||
3306 | |||
3307 | val &= mask; | ||
3308 | |||
3309 | if (shift != 0 && val != 0) | ||
3310 | val = val >> shift; | ||
3311 | ucontrol->value.enumerated.item[0] = val ^ invert; | ||
3312 | |||
3313 | return 0; | ||
3314 | } | ||
3315 | EXPORT_SYMBOL_GPL(snd_soc_get_strobe); | ||
3316 | |||
3317 | /** | ||
3318 | * snd_soc_put_strobe - strobe put callback | ||
3319 | * @kcontrol: mixer control | ||
3320 | * @ucontrol: control element information | ||
3321 | * | ||
3322 | * Callback strobe a register bit to high then low (or the inverse) | ||
3323 | * in one pass of a single mixer enum control. | ||
3324 | * | ||
3325 | * Returns 1 for success. | ||
3326 | */ | ||
3327 | int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, | ||
3328 | struct snd_ctl_elem_value *ucontrol) | ||
3329 | { | ||
3330 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
3331 | struct soc_mixer_control *mc = | ||
3332 | (struct soc_mixer_control *)kcontrol->private_value; | ||
3333 | unsigned int reg = mc->reg; | ||
3334 | unsigned int shift = mc->shift; | ||
3335 | unsigned int mask = 1 << shift; | ||
3336 | unsigned int invert = mc->invert != 0; | ||
3337 | unsigned int strobe = ucontrol->value.enumerated.item[0] != 0; | ||
3338 | unsigned int val1 = (strobe ^ invert) ? mask : 0; | ||
3339 | unsigned int val2 = (strobe ^ invert) ? 0 : mask; | ||
3340 | int err; | ||
3341 | |||
3342 | err = snd_soc_component_update_bits(component, reg, mask, val1); | ||
3343 | if (err < 0) | ||
3344 | return err; | ||
3345 | |||
3346 | return snd_soc_component_update_bits(component, reg, mask, val2); | ||
3347 | } | ||
3348 | EXPORT_SYMBOL_GPL(snd_soc_put_strobe); | ||
3349 | |||
3350 | /** | ||
3351 | * snd_soc_dai_set_sysclk - configure DAI system or master clock. | 1958 | * snd_soc_dai_set_sysclk - configure DAI system or master clock. |
3352 | * @dai: DAI | 1959 | * @dai: DAI |
3353 | * @clk_id: DAI specific clock ID | 1960 | * @clk_id: DAI specific clock ID |
@@ -3996,22 +2603,62 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, | |||
3996 | return 0; | 2603 | return 0; |
3997 | } | 2604 | } |
3998 | 2605 | ||
3999 | static void snd_soc_component_init_regmap(struct snd_soc_component *component) | 2606 | static void snd_soc_component_setup_regmap(struct snd_soc_component *component) |
4000 | { | 2607 | { |
4001 | if (!component->regmap) | 2608 | int val_bytes = regmap_get_val_bytes(component->regmap); |
4002 | component->regmap = dev_get_regmap(component->dev, NULL); | 2609 | |
4003 | if (component->regmap) { | 2610 | /* Errors are legitimate for non-integer byte multiples */ |
4004 | int val_bytes = regmap_get_val_bytes(component->regmap); | 2611 | if (val_bytes > 0) |
4005 | /* Errors are legitimate for non-integer byte multiples */ | 2612 | component->val_bytes = val_bytes; |
4006 | if (val_bytes > 0) | ||
4007 | component->val_bytes = val_bytes; | ||
4008 | } | ||
4009 | } | 2613 | } |
4010 | 2614 | ||
2615 | #ifdef CONFIG_REGMAP | ||
2616 | |||
2617 | /** | ||
2618 | * snd_soc_component_init_regmap() - Initialize regmap instance for the component | ||
2619 | * @component: The component for which to initialize the regmap instance | ||
2620 | * @regmap: The regmap instance that should be used by the component | ||
2621 | * | ||
2622 | * This function allows deferred assignment of the regmap instance that is | ||
2623 | * associated with the component. Only use this if the regmap instance is not | ||
2624 | * yet ready when the component is registered. The function must also be called | ||
2625 | * before the first IO attempt of the component. | ||
2626 | */ | ||
2627 | void snd_soc_component_init_regmap(struct snd_soc_component *component, | ||
2628 | struct regmap *regmap) | ||
2629 | { | ||
2630 | component->regmap = regmap; | ||
2631 | snd_soc_component_setup_regmap(component); | ||
2632 | } | ||
2633 | EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); | ||
2634 | |||
2635 | /** | ||
2636 | * snd_soc_component_exit_regmap() - De-initialize regmap instance for the component | ||
2637 | * @component: The component for which to de-initialize the regmap instance | ||
2638 | * | ||
2639 | * Calls regmap_exit() on the regmap instance associated to the component and | ||
2640 | * removes the regmap instance from the component. | ||
2641 | * | ||
2642 | * This function should only be used if snd_soc_component_init_regmap() was used | ||
2643 | * to initialize the regmap instance. | ||
2644 | */ | ||
2645 | void snd_soc_component_exit_regmap(struct snd_soc_component *component) | ||
2646 | { | ||
2647 | regmap_exit(component->regmap); | ||
2648 | component->regmap = NULL; | ||
2649 | } | ||
2650 | EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap); | ||
2651 | |||
2652 | #endif | ||
2653 | |||
4011 | static void snd_soc_component_add_unlocked(struct snd_soc_component *component) | 2654 | static void snd_soc_component_add_unlocked(struct snd_soc_component *component) |
4012 | { | 2655 | { |
4013 | if (!component->write && !component->read) | 2656 | if (!component->write && !component->read) { |
4014 | snd_soc_component_init_regmap(component); | 2657 | if (!component->regmap) |
2658 | component->regmap = dev_get_regmap(component->dev, NULL); | ||
2659 | if (component->regmap) | ||
2660 | snd_soc_component_setup_regmap(component); | ||
2661 | } | ||
4015 | 2662 | ||
4016 | list_add(&component->list, &component_list); | 2663 | list_add(&component->list, &component_list); |
4017 | } | 2664 | } |
@@ -4362,7 +3009,6 @@ int snd_soc_register_codec(struct device *dev, | |||
4362 | codec->dev = dev; | 3009 | codec->dev = dev; |
4363 | codec->driver = codec_drv; | 3010 | codec->driver = codec_drv; |
4364 | codec->component.val_bytes = codec_drv->reg_word_size; | 3011 | codec->component.val_bytes = codec_drv->reg_word_size; |
4365 | mutex_init(&codec->mutex); | ||
4366 | 3012 | ||
4367 | #ifdef CONFIG_DEBUG_FS | 3013 | #ifdef CONFIG_DEBUG_FS |
4368 | codec->component.init_debugfs = soc_init_codec_debugfs; | 3014 | codec->component.init_debugfs = soc_init_codec_debugfs; |
@@ -4585,7 +3231,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
4585 | const char *propname) | 3231 | const char *propname) |
4586 | { | 3232 | { |
4587 | struct device_node *np = card->dev->of_node; | 3233 | struct device_node *np = card->dev->of_node; |
4588 | int num_routes; | 3234 | int num_routes, old_routes; |
4589 | struct snd_soc_dapm_route *routes; | 3235 | struct snd_soc_dapm_route *routes; |
4590 | int i, ret; | 3236 | int i, ret; |
4591 | 3237 | ||
@@ -4603,7 +3249,9 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
4603 | return -EINVAL; | 3249 | return -EINVAL; |
4604 | } | 3250 | } |
4605 | 3251 | ||
4606 | routes = devm_kzalloc(card->dev, num_routes * sizeof(*routes), | 3252 | old_routes = card->num_dapm_routes; |
3253 | routes = devm_kzalloc(card->dev, | ||
3254 | (old_routes + num_routes) * sizeof(*routes), | ||
4607 | GFP_KERNEL); | 3255 | GFP_KERNEL); |
4608 | if (!routes) { | 3256 | if (!routes) { |
4609 | dev_err(card->dev, | 3257 | dev_err(card->dev, |
@@ -4611,9 +3259,11 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
4611 | return -EINVAL; | 3259 | return -EINVAL; |
4612 | } | 3260 | } |
4613 | 3261 | ||
3262 | memcpy(routes, card->dapm_routes, old_routes * sizeof(*routes)); | ||
3263 | |||
4614 | for (i = 0; i < num_routes; i++) { | 3264 | for (i = 0; i < num_routes; i++) { |
4615 | ret = of_property_read_string_index(np, propname, | 3265 | ret = of_property_read_string_index(np, propname, |
4616 | 2 * i, &routes[i].sink); | 3266 | 2 * i, &routes[old_routes + i].sink); |
4617 | if (ret) { | 3267 | if (ret) { |
4618 | dev_err(card->dev, | 3268 | dev_err(card->dev, |
4619 | "ASoC: Property '%s' index %d could not be read: %d\n", | 3269 | "ASoC: Property '%s' index %d could not be read: %d\n", |
@@ -4621,7 +3271,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
4621 | return -EINVAL; | 3271 | return -EINVAL; |
4622 | } | 3272 | } |
4623 | ret = of_property_read_string_index(np, propname, | 3273 | ret = of_property_read_string_index(np, propname, |
4624 | (2 * i) + 1, &routes[i].source); | 3274 | (2 * i) + 1, &routes[old_routes + i].source); |
4625 | if (ret) { | 3275 | if (ret) { |
4626 | dev_err(card->dev, | 3276 | dev_err(card->dev, |
4627 | "ASoC: Property '%s' index %d could not be read: %d\n", | 3277 | "ASoC: Property '%s' index %d could not be read: %d\n", |
@@ -4630,7 +3280,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
4630 | } | 3280 | } |
4631 | } | 3281 | } |
4632 | 3282 | ||
4633 | card->num_dapm_routes = num_routes; | 3283 | card->num_dapm_routes += num_routes; |
4634 | card->dapm_routes = routes; | 3284 | card->dapm_routes = routes; |
4635 | 3285 | ||
4636 | return 0; | 3286 | return 0; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c61cb9cedbcd..c5136bb1f982 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -159,27 +159,135 @@ static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) | |||
159 | } | 159 | } |
160 | } | 160 | } |
161 | 161 | ||
162 | void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm) | 162 | /* |
163 | * dapm_widget_invalidate_input_paths() - Invalidate the cached number of input | ||
164 | * paths | ||
165 | * @w: The widget for which to invalidate the cached number of input paths | ||
166 | * | ||
167 | * The function resets the cached number of inputs for the specified widget and | ||
168 | * all widgets that can be reached via outgoing paths from the widget. | ||
169 | * | ||
170 | * This function must be called if the number of input paths for a widget might | ||
171 | * have changed. E.g. if the source state of a widget changes or a path is added | ||
172 | * or activated with the widget as the sink. | ||
173 | */ | ||
174 | static void dapm_widget_invalidate_input_paths(struct snd_soc_dapm_widget *w) | ||
175 | { | ||
176 | struct snd_soc_dapm_widget *sink; | ||
177 | struct snd_soc_dapm_path *p; | ||
178 | LIST_HEAD(list); | ||
179 | |||
180 | dapm_assert_locked(w->dapm); | ||
181 | |||
182 | if (w->inputs == -1) | ||
183 | return; | ||
184 | |||
185 | w->inputs = -1; | ||
186 | list_add_tail(&w->work_list, &list); | ||
187 | |||
188 | list_for_each_entry(w, &list, work_list) { | ||
189 | list_for_each_entry(p, &w->sinks, list_source) { | ||
190 | if (p->is_supply || p->weak || !p->connect) | ||
191 | continue; | ||
192 | sink = p->sink; | ||
193 | if (sink->inputs != -1) { | ||
194 | sink->inputs = -1; | ||
195 | list_add_tail(&sink->work_list, &list); | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * dapm_widget_invalidate_output_paths() - Invalidate the cached number of | ||
203 | * output paths | ||
204 | * @w: The widget for which to invalidate the cached number of output paths | ||
205 | * | ||
206 | * Resets the cached number of outputs for the specified widget and all widgets | ||
207 | * that can be reached via incoming paths from the widget. | ||
208 | * | ||
209 | * This function must be called if the number of output paths for a widget might | ||
210 | * have changed. E.g. if the sink state of a widget changes or a path is added | ||
211 | * or activated with the widget as the source. | ||
212 | */ | ||
213 | static void dapm_widget_invalidate_output_paths(struct snd_soc_dapm_widget *w) | ||
214 | { | ||
215 | struct snd_soc_dapm_widget *source; | ||
216 | struct snd_soc_dapm_path *p; | ||
217 | LIST_HEAD(list); | ||
218 | |||
219 | dapm_assert_locked(w->dapm); | ||
220 | |||
221 | if (w->outputs == -1) | ||
222 | return; | ||
223 | |||
224 | w->outputs = -1; | ||
225 | list_add_tail(&w->work_list, &list); | ||
226 | |||
227 | list_for_each_entry(w, &list, work_list) { | ||
228 | list_for_each_entry(p, &w->sources, list_sink) { | ||
229 | if (p->is_supply || p->weak || !p->connect) | ||
230 | continue; | ||
231 | source = p->source; | ||
232 | if (source->outputs != -1) { | ||
233 | source->outputs = -1; | ||
234 | list_add_tail(&source->work_list, &list); | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | |||
240 | /* | ||
241 | * dapm_path_invalidate() - Invalidates the cached number of inputs and outputs | ||
242 | * for the widgets connected to a path | ||
243 | * @p: The path to invalidate | ||
244 | * | ||
245 | * Resets the cached number of inputs for the sink of the path and the cached | ||
246 | * number of outputs for the source of the path. | ||
247 | * | ||
248 | * This function must be called when a path is added, removed or the connected | ||
249 | * state changes. | ||
250 | */ | ||
251 | static void dapm_path_invalidate(struct snd_soc_dapm_path *p) | ||
252 | { | ||
253 | /* | ||
254 | * Weak paths or supply paths do not influence the number of input or | ||
255 | * output paths of their neighbors. | ||
256 | */ | ||
257 | if (p->weak || p->is_supply) | ||
258 | return; | ||
259 | |||
260 | /* | ||
261 | * The number of connected endpoints is the sum of the number of | ||
262 | * connected endpoints of all neighbors. If a node with 0 connected | ||
263 | * endpoints is either connected or disconnected that sum won't change, | ||
264 | * so there is no need to re-check the path. | ||
265 | */ | ||
266 | if (p->source->inputs != 0) | ||
267 | dapm_widget_invalidate_input_paths(p->sink); | ||
268 | if (p->sink->outputs != 0) | ||
269 | dapm_widget_invalidate_output_paths(p->source); | ||
270 | } | ||
271 | |||
272 | void dapm_mark_endpoints_dirty(struct snd_soc_card *card) | ||
163 | { | 273 | { |
164 | struct snd_soc_card *card = dapm->card; | ||
165 | struct snd_soc_dapm_widget *w; | 274 | struct snd_soc_dapm_widget *w; |
166 | 275 | ||
167 | mutex_lock(&card->dapm_mutex); | 276 | mutex_lock(&card->dapm_mutex); |
168 | 277 | ||
169 | list_for_each_entry(w, &card->widgets, list) { | 278 | list_for_each_entry(w, &card->widgets, list) { |
170 | switch (w->id) { | 279 | if (w->is_sink || w->is_source) { |
171 | case snd_soc_dapm_input: | 280 | dapm_mark_dirty(w, "Rechecking endpoints"); |
172 | case snd_soc_dapm_output: | 281 | if (w->is_sink) |
173 | dapm_mark_dirty(w, "Rechecking inputs and outputs"); | 282 | dapm_widget_invalidate_output_paths(w); |
174 | break; | 283 | if (w->is_source) |
175 | default: | 284 | dapm_widget_invalidate_input_paths(w); |
176 | break; | ||
177 | } | 285 | } |
178 | } | 286 | } |
179 | 287 | ||
180 | mutex_unlock(&card->dapm_mutex); | 288 | mutex_unlock(&card->dapm_mutex); |
181 | } | 289 | } |
182 | EXPORT_SYMBOL_GPL(dapm_mark_io_dirty); | 290 | EXPORT_SYMBOL_GPL(dapm_mark_endpoints_dirty); |
183 | 291 | ||
184 | /* create a new dapm widget */ | 292 | /* create a new dapm widget */ |
185 | static inline struct snd_soc_dapm_widget *dapm_cnew_widget( | 293 | static inline struct snd_soc_dapm_widget *dapm_cnew_widget( |
@@ -386,8 +494,6 @@ static void dapm_reset(struct snd_soc_card *card) | |||
386 | list_for_each_entry(w, &card->widgets, list) { | 494 | list_for_each_entry(w, &card->widgets, list) { |
387 | w->new_power = w->power; | 495 | w->new_power = w->power; |
388 | w->power_checked = false; | 496 | w->power_checked = false; |
389 | w->inputs = -1; | ||
390 | w->outputs = -1; | ||
391 | } | 497 | } |
392 | } | 498 | } |
393 | 499 | ||
@@ -469,10 +575,9 @@ out: | |||
469 | 575 | ||
470 | /* connect mux widget to its interconnecting audio paths */ | 576 | /* connect mux widget to its interconnecting audio paths */ |
471 | static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, | 577 | static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, |
472 | struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, | 578 | struct snd_soc_dapm_path *path, const char *control_name) |
473 | struct snd_soc_dapm_path *path, const char *control_name, | ||
474 | const struct snd_kcontrol_new *kcontrol) | ||
475 | { | 579 | { |
580 | const struct snd_kcontrol_new *kcontrol = &path->sink->kcontrol_news[0]; | ||
476 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 581 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
477 | unsigned int val, item; | 582 | unsigned int val, item; |
478 | int i; | 583 | int i; |
@@ -493,10 +598,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, | |||
493 | 598 | ||
494 | for (i = 0; i < e->items; i++) { | 599 | for (i = 0; i < e->items; i++) { |
495 | if (!(strcmp(control_name, e->texts[i]))) { | 600 | if (!(strcmp(control_name, e->texts[i]))) { |
496 | list_add(&path->list, &dapm->card->paths); | 601 | path->name = e->texts[i]; |
497 | list_add(&path->list_sink, &dest->sources); | ||
498 | list_add(&path->list_source, &src->sinks); | ||
499 | path->name = (char*)e->texts[i]; | ||
500 | if (i == item) | 602 | if (i == item) |
501 | path->connect = 1; | 603 | path->connect = 1; |
502 | else | 604 | else |
@@ -509,11 +611,10 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, | |||
509 | } | 611 | } |
510 | 612 | ||
511 | /* set up initial codec paths */ | 613 | /* set up initial codec paths */ |
512 | static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, | 614 | static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i) |
513 | struct snd_soc_dapm_path *p, int i) | ||
514 | { | 615 | { |
515 | struct soc_mixer_control *mc = (struct soc_mixer_control *) | 616 | struct soc_mixer_control *mc = (struct soc_mixer_control *) |
516 | w->kcontrol_news[i].private_value; | 617 | p->sink->kcontrol_news[i].private_value; |
517 | unsigned int reg = mc->reg; | 618 | unsigned int reg = mc->reg; |
518 | unsigned int shift = mc->shift; | 619 | unsigned int shift = mc->shift; |
519 | unsigned int max = mc->max; | 620 | unsigned int max = mc->max; |
@@ -522,7 +623,7 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, | |||
522 | unsigned int val; | 623 | unsigned int val; |
523 | 624 | ||
524 | if (reg != SND_SOC_NOPM) { | 625 | if (reg != SND_SOC_NOPM) { |
525 | soc_dapm_read(w->dapm, reg, &val); | 626 | soc_dapm_read(p->sink->dapm, reg, &val); |
526 | val = (val >> shift) & mask; | 627 | val = (val >> shift) & mask; |
527 | if (invert) | 628 | if (invert) |
528 | val = max - val; | 629 | val = max - val; |
@@ -534,19 +635,15 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, | |||
534 | 635 | ||
535 | /* connect mixer widget to its interconnecting audio paths */ | 636 | /* connect mixer widget to its interconnecting audio paths */ |
536 | static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, | 637 | static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, |
537 | struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, | ||
538 | struct snd_soc_dapm_path *path, const char *control_name) | 638 | struct snd_soc_dapm_path *path, const char *control_name) |
539 | { | 639 | { |
540 | int i; | 640 | int i; |
541 | 641 | ||
542 | /* search for mixer kcontrol */ | 642 | /* search for mixer kcontrol */ |
543 | for (i = 0; i < dest->num_kcontrols; i++) { | 643 | for (i = 0; i < path->sink->num_kcontrols; i++) { |
544 | if (!strcmp(control_name, dest->kcontrol_news[i].name)) { | 644 | if (!strcmp(control_name, path->sink->kcontrol_news[i].name)) { |
545 | list_add(&path->list, &dapm->card->paths); | 645 | path->name = path->sink->kcontrol_news[i].name; |
546 | list_add(&path->list_sink, &dest->sources); | 646 | dapm_set_mixer_path_status(path, i); |
547 | list_add(&path->list_source, &src->sinks); | ||
548 | path->name = dest->kcontrol_news[i].name; | ||
549 | dapm_set_mixer_path_status(dest, path, i); | ||
550 | return 0; | 647 | return 0; |
551 | } | 648 | } |
552 | } | 649 | } |
@@ -738,8 +835,10 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w) | |||
738 | if (ret < 0) | 835 | if (ret < 0) |
739 | return ret; | 836 | return ret; |
740 | 837 | ||
741 | list_for_each_entry(path, &w->sources, list_sink) | 838 | list_for_each_entry(path, &w->sources, list_sink) { |
742 | dapm_kcontrol_add_path(w->kcontrols[0], path); | 839 | if (path->name) |
840 | dapm_kcontrol_add_path(w->kcontrols[0], path); | ||
841 | } | ||
743 | 842 | ||
744 | return 0; | 843 | return 0; |
745 | } | 844 | } |
@@ -754,34 +853,6 @@ static int dapm_new_pga(struct snd_soc_dapm_widget *w) | |||
754 | return 0; | 853 | return 0; |
755 | } | 854 | } |
756 | 855 | ||
757 | /* reset 'walked' bit for each dapm path */ | ||
758 | static void dapm_clear_walk_output(struct snd_soc_dapm_context *dapm, | ||
759 | struct list_head *sink) | ||
760 | { | ||
761 | struct snd_soc_dapm_path *p; | ||
762 | |||
763 | list_for_each_entry(p, sink, list_source) { | ||
764 | if (p->walked) { | ||
765 | p->walked = 0; | ||
766 | dapm_clear_walk_output(dapm, &p->sink->sinks); | ||
767 | } | ||
768 | } | ||
769 | } | ||
770 | |||
771 | static void dapm_clear_walk_input(struct snd_soc_dapm_context *dapm, | ||
772 | struct list_head *source) | ||
773 | { | ||
774 | struct snd_soc_dapm_path *p; | ||
775 | |||
776 | list_for_each_entry(p, source, list_sink) { | ||
777 | if (p->walked) { | ||
778 | p->walked = 0; | ||
779 | dapm_clear_walk_input(dapm, &p->source->sources); | ||
780 | } | ||
781 | } | ||
782 | } | ||
783 | |||
784 | |||
785 | /* We implement power down on suspend by checking the power state of | 856 | /* We implement power down on suspend by checking the power state of |
786 | * the ALSA card - when we are suspending the ALSA state for the card | 857 | * the ALSA card - when we are suspending the ALSA state for the card |
787 | * is set to D3. | 858 | * is set to D3. |
@@ -856,61 +927,23 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget, | |||
856 | 927 | ||
857 | DAPM_UPDATE_STAT(widget, path_checks); | 928 | DAPM_UPDATE_STAT(widget, path_checks); |
858 | 929 | ||
859 | switch (widget->id) { | 930 | if (widget->is_sink && widget->connected) { |
860 | case snd_soc_dapm_supply: | 931 | widget->outputs = snd_soc_dapm_suspend_check(widget); |
861 | case snd_soc_dapm_regulator_supply: | 932 | return widget->outputs; |
862 | case snd_soc_dapm_clock_supply: | ||
863 | case snd_soc_dapm_kcontrol: | ||
864 | return 0; | ||
865 | default: | ||
866 | break; | ||
867 | } | ||
868 | |||
869 | switch (widget->id) { | ||
870 | case snd_soc_dapm_adc: | ||
871 | case snd_soc_dapm_aif_out: | ||
872 | case snd_soc_dapm_dai_out: | ||
873 | if (widget->active) { | ||
874 | widget->outputs = snd_soc_dapm_suspend_check(widget); | ||
875 | return widget->outputs; | ||
876 | } | ||
877 | default: | ||
878 | break; | ||
879 | } | ||
880 | |||
881 | if (widget->connected) { | ||
882 | /* connected pin ? */ | ||
883 | if (widget->id == snd_soc_dapm_output && !widget->ext) { | ||
884 | widget->outputs = snd_soc_dapm_suspend_check(widget); | ||
885 | return widget->outputs; | ||
886 | } | ||
887 | |||
888 | /* connected jack or spk ? */ | ||
889 | if (widget->id == snd_soc_dapm_hp || | ||
890 | widget->id == snd_soc_dapm_spk || | ||
891 | (widget->id == snd_soc_dapm_line && | ||
892 | !list_empty(&widget->sources))) { | ||
893 | widget->outputs = snd_soc_dapm_suspend_check(widget); | ||
894 | return widget->outputs; | ||
895 | } | ||
896 | } | 933 | } |
897 | 934 | ||
898 | list_for_each_entry(path, &widget->sinks, list_source) { | 935 | list_for_each_entry(path, &widget->sinks, list_source) { |
899 | DAPM_UPDATE_STAT(widget, neighbour_checks); | 936 | DAPM_UPDATE_STAT(widget, neighbour_checks); |
900 | 937 | ||
901 | if (path->weak) | 938 | if (path->weak || path->is_supply) |
902 | continue; | 939 | continue; |
903 | 940 | ||
904 | if (path->walking) | 941 | if (path->walking) |
905 | return 1; | 942 | return 1; |
906 | 943 | ||
907 | if (path->walked) | ||
908 | continue; | ||
909 | |||
910 | trace_snd_soc_dapm_output_path(widget, path); | 944 | trace_snd_soc_dapm_output_path(widget, path); |
911 | 945 | ||
912 | if (path->sink && path->connect) { | 946 | if (path->connect) { |
913 | path->walked = 1; | ||
914 | path->walking = 1; | 947 | path->walking = 1; |
915 | 948 | ||
916 | /* do we need to add this widget to the list ? */ | 949 | /* do we need to add this widget to the list ? */ |
@@ -952,73 +985,23 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, | |||
952 | 985 | ||
953 | DAPM_UPDATE_STAT(widget, path_checks); | 986 | DAPM_UPDATE_STAT(widget, path_checks); |
954 | 987 | ||
955 | switch (widget->id) { | 988 | if (widget->is_source && widget->connected) { |
956 | case snd_soc_dapm_supply: | 989 | widget->inputs = snd_soc_dapm_suspend_check(widget); |
957 | case snd_soc_dapm_regulator_supply: | 990 | return widget->inputs; |
958 | case snd_soc_dapm_clock_supply: | ||
959 | case snd_soc_dapm_kcontrol: | ||
960 | return 0; | ||
961 | default: | ||
962 | break; | ||
963 | } | ||
964 | |||
965 | /* active stream ? */ | ||
966 | switch (widget->id) { | ||
967 | case snd_soc_dapm_dac: | ||
968 | case snd_soc_dapm_aif_in: | ||
969 | case snd_soc_dapm_dai_in: | ||
970 | if (widget->active) { | ||
971 | widget->inputs = snd_soc_dapm_suspend_check(widget); | ||
972 | return widget->inputs; | ||
973 | } | ||
974 | default: | ||
975 | break; | ||
976 | } | ||
977 | |||
978 | if (widget->connected) { | ||
979 | /* connected pin ? */ | ||
980 | if (widget->id == snd_soc_dapm_input && !widget->ext) { | ||
981 | widget->inputs = snd_soc_dapm_suspend_check(widget); | ||
982 | return widget->inputs; | ||
983 | } | ||
984 | |||
985 | /* connected VMID/Bias for lower pops */ | ||
986 | if (widget->id == snd_soc_dapm_vmid) { | ||
987 | widget->inputs = snd_soc_dapm_suspend_check(widget); | ||
988 | return widget->inputs; | ||
989 | } | ||
990 | |||
991 | /* connected jack ? */ | ||
992 | if (widget->id == snd_soc_dapm_mic || | ||
993 | (widget->id == snd_soc_dapm_line && | ||
994 | !list_empty(&widget->sinks))) { | ||
995 | widget->inputs = snd_soc_dapm_suspend_check(widget); | ||
996 | return widget->inputs; | ||
997 | } | ||
998 | |||
999 | /* signal generator */ | ||
1000 | if (widget->id == snd_soc_dapm_siggen) { | ||
1001 | widget->inputs = snd_soc_dapm_suspend_check(widget); | ||
1002 | return widget->inputs; | ||
1003 | } | ||
1004 | } | 991 | } |
1005 | 992 | ||
1006 | list_for_each_entry(path, &widget->sources, list_sink) { | 993 | list_for_each_entry(path, &widget->sources, list_sink) { |
1007 | DAPM_UPDATE_STAT(widget, neighbour_checks); | 994 | DAPM_UPDATE_STAT(widget, neighbour_checks); |
1008 | 995 | ||
1009 | if (path->weak) | 996 | if (path->weak || path->is_supply) |
1010 | continue; | 997 | continue; |
1011 | 998 | ||
1012 | if (path->walking) | 999 | if (path->walking) |
1013 | return 1; | 1000 | return 1; |
1014 | 1001 | ||
1015 | if (path->walked) | ||
1016 | continue; | ||
1017 | |||
1018 | trace_snd_soc_dapm_input_path(widget, path); | 1002 | trace_snd_soc_dapm_input_path(widget, path); |
1019 | 1003 | ||
1020 | if (path->source && path->connect) { | 1004 | if (path->connect) { |
1021 | path->walked = 1; | ||
1022 | path->walking = 1; | 1005 | path->walking = 1; |
1023 | 1006 | ||
1024 | /* do we need to add this widget to the list ? */ | 1007 | /* do we need to add this widget to the list ? */ |
@@ -1060,21 +1043,25 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, | |||
1060 | int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, | 1043 | int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, |
1061 | struct snd_soc_dapm_widget_list **list) | 1044 | struct snd_soc_dapm_widget_list **list) |
1062 | { | 1045 | { |
1063 | struct snd_soc_card *card = dai->card; | 1046 | struct snd_soc_card *card = dai->component->card; |
1047 | struct snd_soc_dapm_widget *w; | ||
1064 | int paths; | 1048 | int paths; |
1065 | 1049 | ||
1066 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 1050 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
1067 | dapm_reset(card); | ||
1068 | 1051 | ||
1069 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 1052 | /* |
1053 | * For is_connected_{output,input}_ep fully discover the graph we need | ||
1054 | * to reset the cached number of inputs and outputs. | ||
1055 | */ | ||
1056 | list_for_each_entry(w, &card->widgets, list) { | ||
1057 | w->inputs = -1; | ||
1058 | w->outputs = -1; | ||
1059 | } | ||
1060 | |||
1061 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
1070 | paths = is_connected_output_ep(dai->playback_widget, list); | 1062 | paths = is_connected_output_ep(dai->playback_widget, list); |
1071 | dapm_clear_walk_output(&card->dapm, | 1063 | else |
1072 | &dai->playback_widget->sinks); | ||
1073 | } else { | ||
1074 | paths = is_connected_input_ep(dai->capture_widget, list); | 1064 | paths = is_connected_input_ep(dai->capture_widget, list); |
1075 | dapm_clear_walk_input(&card->dapm, | ||
1076 | &dai->capture_widget->sources); | ||
1077 | } | ||
1078 | 1065 | ||
1079 | trace_snd_soc_dapm_connected(paths, stream); | 1066 | trace_snd_soc_dapm_connected(paths, stream); |
1080 | mutex_unlock(&card->dapm_mutex); | 1067 | mutex_unlock(&card->dapm_mutex); |
@@ -1163,44 +1150,10 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w) | |||
1163 | DAPM_UPDATE_STAT(w, power_checks); | 1150 | DAPM_UPDATE_STAT(w, power_checks); |
1164 | 1151 | ||
1165 | in = is_connected_input_ep(w, NULL); | 1152 | in = is_connected_input_ep(w, NULL); |
1166 | dapm_clear_walk_input(w->dapm, &w->sources); | ||
1167 | out = is_connected_output_ep(w, NULL); | 1153 | out = is_connected_output_ep(w, NULL); |
1168 | dapm_clear_walk_output(w->dapm, &w->sinks); | ||
1169 | return out != 0 && in != 0; | 1154 | return out != 0 && in != 0; |
1170 | } | 1155 | } |
1171 | 1156 | ||
1172 | /* Check to see if an ADC has power */ | ||
1173 | static int dapm_adc_check_power(struct snd_soc_dapm_widget *w) | ||
1174 | { | ||
1175 | int in; | ||
1176 | |||
1177 | DAPM_UPDATE_STAT(w, power_checks); | ||
1178 | |||
1179 | if (w->active) { | ||
1180 | in = is_connected_input_ep(w, NULL); | ||
1181 | dapm_clear_walk_input(w->dapm, &w->sources); | ||
1182 | return in != 0; | ||
1183 | } else { | ||
1184 | return dapm_generic_check_power(w); | ||
1185 | } | ||
1186 | } | ||
1187 | |||
1188 | /* Check to see if a DAC has power */ | ||
1189 | static int dapm_dac_check_power(struct snd_soc_dapm_widget *w) | ||
1190 | { | ||
1191 | int out; | ||
1192 | |||
1193 | DAPM_UPDATE_STAT(w, power_checks); | ||
1194 | |||
1195 | if (w->active) { | ||
1196 | out = is_connected_output_ep(w, NULL); | ||
1197 | dapm_clear_walk_output(w->dapm, &w->sinks); | ||
1198 | return out != 0; | ||
1199 | } else { | ||
1200 | return dapm_generic_check_power(w); | ||
1201 | } | ||
1202 | } | ||
1203 | |||
1204 | /* Check to see if a power supply is needed */ | 1157 | /* Check to see if a power supply is needed */ |
1205 | static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) | 1158 | static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) |
1206 | { | 1159 | { |
@@ -1219,9 +1172,6 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) | |||
1219 | !path->connected(path->source, path->sink)) | 1172 | !path->connected(path->source, path->sink)) |
1220 | continue; | 1173 | continue; |
1221 | 1174 | ||
1222 | if (!path->sink) | ||
1223 | continue; | ||
1224 | |||
1225 | if (dapm_widget_power_check(path->sink)) | 1175 | if (dapm_widget_power_check(path->sink)) |
1226 | return 1; | 1176 | return 1; |
1227 | } | 1177 | } |
@@ -1636,27 +1586,14 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power, | |||
1636 | /* If we changed our power state perhaps our neigbours changed | 1586 | /* If we changed our power state perhaps our neigbours changed |
1637 | * also. | 1587 | * also. |
1638 | */ | 1588 | */ |
1639 | list_for_each_entry(path, &w->sources, list_sink) { | 1589 | list_for_each_entry(path, &w->sources, list_sink) |
1640 | if (path->source) { | 1590 | dapm_widget_set_peer_power(path->source, power, path->connect); |
1641 | dapm_widget_set_peer_power(path->source, power, | 1591 | |
1592 | /* Supplies can't affect their outputs, only their inputs */ | ||
1593 | if (!w->is_supply) { | ||
1594 | list_for_each_entry(path, &w->sinks, list_source) | ||
1595 | dapm_widget_set_peer_power(path->sink, power, | ||
1642 | path->connect); | 1596 | path->connect); |
1643 | } | ||
1644 | } | ||
1645 | switch (w->id) { | ||
1646 | case snd_soc_dapm_supply: | ||
1647 | case snd_soc_dapm_regulator_supply: | ||
1648 | case snd_soc_dapm_clock_supply: | ||
1649 | case snd_soc_dapm_kcontrol: | ||
1650 | /* Supplies can't affect their outputs, only their inputs */ | ||
1651 | break; | ||
1652 | default: | ||
1653 | list_for_each_entry(path, &w->sinks, list_source) { | ||
1654 | if (path->sink) { | ||
1655 | dapm_widget_set_peer_power(path->sink, power, | ||
1656 | path->connect); | ||
1657 | } | ||
1658 | } | ||
1659 | break; | ||
1660 | } | 1597 | } |
1661 | 1598 | ||
1662 | if (power) | 1599 | if (power) |
@@ -1863,10 +1800,14 @@ static ssize_t dapm_widget_power_read_file(struct file *file, | |||
1863 | if (!buf) | 1800 | if (!buf) |
1864 | return -ENOMEM; | 1801 | return -ENOMEM; |
1865 | 1802 | ||
1866 | in = is_connected_input_ep(w, NULL); | 1803 | /* Supply widgets are not handled by is_connected_{input,output}_ep() */ |
1867 | dapm_clear_walk_input(w->dapm, &w->sources); | 1804 | if (w->is_supply) { |
1868 | out = is_connected_output_ep(w, NULL); | 1805 | in = 0; |
1869 | dapm_clear_walk_output(w->dapm, &w->sinks); | 1806 | out = 0; |
1807 | } else { | ||
1808 | in = is_connected_input_ep(w, NULL); | ||
1809 | out = is_connected_output_ep(w, NULL); | ||
1810 | } | ||
1870 | 1811 | ||
1871 | ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d", | 1812 | ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d", |
1872 | w->name, w->power ? "On" : "Off", | 1813 | w->name, w->power ? "On" : "Off", |
@@ -2011,32 +1952,45 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) | |||
2011 | 1952 | ||
2012 | #endif | 1953 | #endif |
2013 | 1954 | ||
1955 | /* | ||
1956 | * soc_dapm_connect_path() - Connects or disconnects a path | ||
1957 | * @path: The path to update | ||
1958 | * @connect: The new connect state of the path. True if the path is connected, | ||
1959 | * false if it is disconneted. | ||
1960 | * @reason: The reason why the path changed (for debugging only) | ||
1961 | */ | ||
1962 | static void soc_dapm_connect_path(struct snd_soc_dapm_path *path, | ||
1963 | bool connect, const char *reason) | ||
1964 | { | ||
1965 | if (path->connect == connect) | ||
1966 | return; | ||
1967 | |||
1968 | path->connect = connect; | ||
1969 | dapm_mark_dirty(path->source, reason); | ||
1970 | dapm_mark_dirty(path->sink, reason); | ||
1971 | dapm_path_invalidate(path); | ||
1972 | } | ||
1973 | |||
2014 | /* test and update the power status of a mux widget */ | 1974 | /* test and update the power status of a mux widget */ |
2015 | static int soc_dapm_mux_update_power(struct snd_soc_card *card, | 1975 | static int soc_dapm_mux_update_power(struct snd_soc_card *card, |
2016 | struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) | 1976 | struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e) |
2017 | { | 1977 | { |
2018 | struct snd_soc_dapm_path *path; | 1978 | struct snd_soc_dapm_path *path; |
2019 | int found = 0; | 1979 | int found = 0; |
1980 | bool connect; | ||
2020 | 1981 | ||
2021 | lockdep_assert_held(&card->dapm_mutex); | 1982 | lockdep_assert_held(&card->dapm_mutex); |
2022 | 1983 | ||
2023 | /* find dapm widget path assoc with kcontrol */ | 1984 | /* find dapm widget path assoc with kcontrol */ |
2024 | dapm_kcontrol_for_each_path(path, kcontrol) { | 1985 | dapm_kcontrol_for_each_path(path, kcontrol) { |
2025 | if (!path->name || !e->texts[mux]) | ||
2026 | continue; | ||
2027 | |||
2028 | found = 1; | 1986 | found = 1; |
2029 | /* we now need to match the string in the enum to the path */ | 1987 | /* we now need to match the string in the enum to the path */ |
2030 | if (!(strcmp(path->name, e->texts[mux]))) { | 1988 | if (!(strcmp(path->name, e->texts[mux]))) |
2031 | path->connect = 1; /* new connection */ | 1989 | connect = true; |
2032 | dapm_mark_dirty(path->source, "mux connection"); | 1990 | else |
2033 | } else { | 1991 | connect = false; |
2034 | if (path->connect) | 1992 | |
2035 | dapm_mark_dirty(path->source, | 1993 | soc_dapm_connect_path(path, connect, "mux update"); |
2036 | "mux disconnection"); | ||
2037 | path->connect = 0; /* old connection must be powered down */ | ||
2038 | } | ||
2039 | dapm_mark_dirty(path->sink, "mux change"); | ||
2040 | } | 1994 | } |
2041 | 1995 | ||
2042 | if (found) | 1996 | if (found) |
@@ -2075,9 +2029,7 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card, | |||
2075 | /* find dapm widget path assoc with kcontrol */ | 2029 | /* find dapm widget path assoc with kcontrol */ |
2076 | dapm_kcontrol_for_each_path(path, kcontrol) { | 2030 | dapm_kcontrol_for_each_path(path, kcontrol) { |
2077 | found = 1; | 2031 | found = 1; |
2078 | path->connect = connect; | 2032 | soc_dapm_connect_path(path, connect, "mixer update"); |
2079 | dapm_mark_dirty(path->source, "mixer connection"); | ||
2080 | dapm_mark_dirty(path->sink, "mixer update"); | ||
2081 | } | 2033 | } |
2082 | 2034 | ||
2083 | if (found) | 2035 | if (found) |
@@ -2255,8 +2207,11 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, | |||
2255 | return -EINVAL; | 2207 | return -EINVAL; |
2256 | } | 2208 | } |
2257 | 2209 | ||
2258 | if (w->connected != status) | 2210 | if (w->connected != status) { |
2259 | dapm_mark_dirty(w, "pin configuration"); | 2211 | dapm_mark_dirty(w, "pin configuration"); |
2212 | dapm_widget_invalidate_input_paths(w); | ||
2213 | dapm_widget_invalidate_output_paths(w); | ||
2214 | } | ||
2260 | 2215 | ||
2261 | w->connected = status; | 2216 | w->connected = status; |
2262 | if (status == 0) | 2217 | if (status == 0) |
@@ -2309,6 +2264,53 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) | |||
2309 | } | 2264 | } |
2310 | EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); | 2265 | EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); |
2311 | 2266 | ||
2267 | /* | ||
2268 | * dapm_update_widget_flags() - Re-compute widget sink and source flags | ||
2269 | * @w: The widget for which to update the flags | ||
2270 | * | ||
2271 | * Some widgets have a dynamic category which depends on which neighbors they | ||
2272 | * are connected to. This function update the category for these widgets. | ||
2273 | * | ||
2274 | * This function must be called whenever a path is added or removed to a widget. | ||
2275 | */ | ||
2276 | static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w) | ||
2277 | { | ||
2278 | struct snd_soc_dapm_path *p; | ||
2279 | |||
2280 | switch (w->id) { | ||
2281 | case snd_soc_dapm_input: | ||
2282 | w->is_source = 1; | ||
2283 | list_for_each_entry(p, &w->sources, list_sink) { | ||
2284 | if (p->source->id == snd_soc_dapm_micbias || | ||
2285 | p->source->id == snd_soc_dapm_mic || | ||
2286 | p->source->id == snd_soc_dapm_line || | ||
2287 | p->source->id == snd_soc_dapm_output) { | ||
2288 | w->is_source = 0; | ||
2289 | break; | ||
2290 | } | ||
2291 | } | ||
2292 | break; | ||
2293 | case snd_soc_dapm_output: | ||
2294 | w->is_sink = 1; | ||
2295 | list_for_each_entry(p, &w->sinks, list_source) { | ||
2296 | if (p->sink->id == snd_soc_dapm_spk || | ||
2297 | p->sink->id == snd_soc_dapm_hp || | ||
2298 | p->sink->id == snd_soc_dapm_line || | ||
2299 | p->sink->id == snd_soc_dapm_input) { | ||
2300 | w->is_sink = 0; | ||
2301 | break; | ||
2302 | } | ||
2303 | } | ||
2304 | break; | ||
2305 | case snd_soc_dapm_line: | ||
2306 | w->is_sink = !list_empty(&w->sources); | ||
2307 | w->is_source = !list_empty(&w->sinks); | ||
2308 | break; | ||
2309 | default: | ||
2310 | break; | ||
2311 | } | ||
2312 | } | ||
2313 | |||
2312 | static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | 2314 | static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, |
2313 | struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink, | 2315 | struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink, |
2314 | const char *control, | 2316 | const char *control, |
@@ -2318,6 +2320,27 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | |||
2318 | struct snd_soc_dapm_path *path; | 2320 | struct snd_soc_dapm_path *path; |
2319 | int ret; | 2321 | int ret; |
2320 | 2322 | ||
2323 | if (wsink->is_supply && !wsource->is_supply) { | ||
2324 | dev_err(dapm->dev, | ||
2325 | "Connecting non-supply widget to supply widget is not supported (%s -> %s)\n", | ||
2326 | wsource->name, wsink->name); | ||
2327 | return -EINVAL; | ||
2328 | } | ||
2329 | |||
2330 | if (connected && !wsource->is_supply) { | ||
2331 | dev_err(dapm->dev, | ||
2332 | "connected() callback only supported for supply widgets (%s -> %s)\n", | ||
2333 | wsource->name, wsink->name); | ||
2334 | return -EINVAL; | ||
2335 | } | ||
2336 | |||
2337 | if (wsource->is_supply && control) { | ||
2338 | dev_err(dapm->dev, | ||
2339 | "Conditional paths are not supported for supply widgets (%s -> [%s] -> %s)\n", | ||
2340 | wsource->name, control, wsink->name); | ||
2341 | return -EINVAL; | ||
2342 | } | ||
2343 | |||
2321 | path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); | 2344 | path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); |
2322 | if (!path) | 2345 | if (!path) |
2323 | return -ENOMEM; | 2346 | return -ENOMEM; |
@@ -2330,85 +2353,49 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, | |||
2330 | INIT_LIST_HEAD(&path->list_source); | 2353 | INIT_LIST_HEAD(&path->list_source); |
2331 | INIT_LIST_HEAD(&path->list_sink); | 2354 | INIT_LIST_HEAD(&path->list_sink); |
2332 | 2355 | ||
2333 | /* check for external widgets */ | 2356 | if (wsource->is_supply || wsink->is_supply) |
2334 | if (wsink->id == snd_soc_dapm_input) { | 2357 | path->is_supply = 1; |
2335 | if (wsource->id == snd_soc_dapm_micbias || | ||
2336 | wsource->id == snd_soc_dapm_mic || | ||
2337 | wsource->id == snd_soc_dapm_line || | ||
2338 | wsource->id == snd_soc_dapm_output) | ||
2339 | wsink->ext = 1; | ||
2340 | } | ||
2341 | if (wsource->id == snd_soc_dapm_output) { | ||
2342 | if (wsink->id == snd_soc_dapm_spk || | ||
2343 | wsink->id == snd_soc_dapm_hp || | ||
2344 | wsink->id == snd_soc_dapm_line || | ||
2345 | wsink->id == snd_soc_dapm_input) | ||
2346 | wsource->ext = 1; | ||
2347 | } | ||
2348 | |||
2349 | dapm_mark_dirty(wsource, "Route added"); | ||
2350 | dapm_mark_dirty(wsink, "Route added"); | ||
2351 | 2358 | ||
2352 | /* connect static paths */ | 2359 | /* connect static paths */ |
2353 | if (control == NULL) { | 2360 | if (control == NULL) { |
2354 | list_add(&path->list, &dapm->card->paths); | ||
2355 | list_add(&path->list_sink, &wsink->sources); | ||
2356 | list_add(&path->list_source, &wsource->sinks); | ||
2357 | path->connect = 1; | 2361 | path->connect = 1; |
2358 | return 0; | 2362 | } else { |
2359 | } | 2363 | /* connect dynamic paths */ |
2360 | 2364 | switch (wsink->id) { | |
2361 | /* connect dynamic paths */ | 2365 | case snd_soc_dapm_mux: |
2362 | switch (wsink->id) { | 2366 | ret = dapm_connect_mux(dapm, path, control); |
2363 | case snd_soc_dapm_adc: | 2367 | if (ret != 0) |
2364 | case snd_soc_dapm_dac: | 2368 | goto err; |
2365 | case snd_soc_dapm_pga: | 2369 | break; |
2366 | case snd_soc_dapm_out_drv: | 2370 | case snd_soc_dapm_switch: |
2367 | case snd_soc_dapm_input: | 2371 | case snd_soc_dapm_mixer: |
2368 | case snd_soc_dapm_output: | 2372 | case snd_soc_dapm_mixer_named_ctl: |
2369 | case snd_soc_dapm_siggen: | 2373 | ret = dapm_connect_mixer(dapm, path, control); |
2370 | case snd_soc_dapm_micbias: | 2374 | if (ret != 0) |
2371 | case snd_soc_dapm_vmid: | 2375 | goto err; |
2372 | case snd_soc_dapm_pre: | 2376 | break; |
2373 | case snd_soc_dapm_post: | 2377 | default: |
2374 | case snd_soc_dapm_supply: | 2378 | dev_err(dapm->dev, |
2375 | case snd_soc_dapm_regulator_supply: | 2379 | "Control not supported for path %s -> [%s] -> %s\n", |
2376 | case snd_soc_dapm_clock_supply: | 2380 | wsource->name, control, wsink->name); |
2377 | case snd_soc_dapm_aif_in: | 2381 | ret = -EINVAL; |
2378 | case snd_soc_dapm_aif_out: | ||
2379 | case snd_soc_dapm_dai_in: | ||
2380 | case snd_soc_dapm_dai_out: | ||
2381 | case snd_soc_dapm_dai_link: | ||
2382 | case snd_soc_dapm_kcontrol: | ||
2383 | list_add(&path->list, &dapm->card->paths); | ||
2384 | list_add(&path->list_sink, &wsink->sources); | ||
2385 | list_add(&path->list_source, &wsource->sinks); | ||
2386 | path->connect = 1; | ||
2387 | return 0; | ||
2388 | case snd_soc_dapm_mux: | ||
2389 | ret = dapm_connect_mux(dapm, wsource, wsink, path, control, | ||
2390 | &wsink->kcontrol_news[0]); | ||
2391 | if (ret != 0) | ||
2392 | goto err; | ||
2393 | break; | ||
2394 | case snd_soc_dapm_switch: | ||
2395 | case snd_soc_dapm_mixer: | ||
2396 | case snd_soc_dapm_mixer_named_ctl: | ||
2397 | ret = dapm_connect_mixer(dapm, wsource, wsink, path, control); | ||
2398 | if (ret != 0) | ||
2399 | goto err; | 2382 | goto err; |
2400 | break; | 2383 | } |
2401 | case snd_soc_dapm_hp: | ||
2402 | case snd_soc_dapm_mic: | ||
2403 | case snd_soc_dapm_line: | ||
2404 | case snd_soc_dapm_spk: | ||
2405 | list_add(&path->list, &dapm->card->paths); | ||
2406 | list_add(&path->list_sink, &wsink->sources); | ||
2407 | list_add(&path->list_source, &wsource->sinks); | ||
2408 | path->connect = 0; | ||
2409 | return 0; | ||
2410 | } | 2384 | } |
2411 | 2385 | ||
2386 | list_add(&path->list, &dapm->card->paths); | ||
2387 | list_add(&path->list_sink, &wsink->sources); | ||
2388 | list_add(&path->list_source, &wsource->sinks); | ||
2389 | |||
2390 | dapm_update_widget_flags(wsource); | ||
2391 | dapm_update_widget_flags(wsink); | ||
2392 | |||
2393 | dapm_mark_dirty(wsource, "Route added"); | ||
2394 | dapm_mark_dirty(wsink, "Route added"); | ||
2395 | |||
2396 | if (dapm->card->instantiated && path->connect) | ||
2397 | dapm_path_invalidate(path); | ||
2398 | |||
2412 | return 0; | 2399 | return 0; |
2413 | err: | 2400 | err: |
2414 | kfree(path); | 2401 | kfree(path); |
@@ -2489,6 +2476,7 @@ err: | |||
2489 | static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, | 2476 | static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, |
2490 | const struct snd_soc_dapm_route *route) | 2477 | const struct snd_soc_dapm_route *route) |
2491 | { | 2478 | { |
2479 | struct snd_soc_dapm_widget *wsource, *wsink; | ||
2492 | struct snd_soc_dapm_path *path, *p; | 2480 | struct snd_soc_dapm_path *path, *p; |
2493 | const char *sink; | 2481 | const char *sink; |
2494 | const char *source; | 2482 | const char *source; |
@@ -2526,10 +2514,19 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, | |||
2526 | } | 2514 | } |
2527 | 2515 | ||
2528 | if (path) { | 2516 | if (path) { |
2529 | dapm_mark_dirty(path->source, "Route removed"); | 2517 | wsource = path->source; |
2530 | dapm_mark_dirty(path->sink, "Route removed"); | 2518 | wsink = path->sink; |
2519 | |||
2520 | dapm_mark_dirty(wsource, "Route removed"); | ||
2521 | dapm_mark_dirty(wsink, "Route removed"); | ||
2522 | if (path->connect) | ||
2523 | dapm_path_invalidate(path); | ||
2531 | 2524 | ||
2532 | dapm_free_path(path); | 2525 | dapm_free_path(path); |
2526 | |||
2527 | /* Update any path related flags */ | ||
2528 | dapm_update_widget_flags(wsource); | ||
2529 | dapm_update_widget_flags(wsink); | ||
2533 | } else { | 2530 | } else { |
2534 | dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n", | 2531 | dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n", |
2535 | source, sink); | 2532 | source, sink); |
@@ -3087,40 +3084,44 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3087 | } | 3084 | } |
3088 | 3085 | ||
3089 | switch (w->id) { | 3086 | switch (w->id) { |
3090 | case snd_soc_dapm_switch: | 3087 | case snd_soc_dapm_mic: |
3091 | case snd_soc_dapm_mixer: | 3088 | case snd_soc_dapm_input: |
3092 | case snd_soc_dapm_mixer_named_ctl: | 3089 | w->is_source = 1; |
3093 | w->power_check = dapm_generic_check_power; | 3090 | w->power_check = dapm_generic_check_power; |
3094 | break; | 3091 | break; |
3095 | case snd_soc_dapm_mux: | 3092 | case snd_soc_dapm_spk: |
3093 | case snd_soc_dapm_hp: | ||
3094 | case snd_soc_dapm_output: | ||
3095 | w->is_sink = 1; | ||
3096 | w->power_check = dapm_generic_check_power; | 3096 | w->power_check = dapm_generic_check_power; |
3097 | break; | 3097 | break; |
3098 | case snd_soc_dapm_dai_out: | 3098 | case snd_soc_dapm_vmid: |
3099 | w->power_check = dapm_adc_check_power; | 3099 | case snd_soc_dapm_siggen: |
3100 | break; | 3100 | w->is_source = 1; |
3101 | case snd_soc_dapm_dai_in: | 3101 | w->power_check = dapm_always_on_check_power; |
3102 | w->power_check = dapm_dac_check_power; | ||
3103 | break; | 3102 | break; |
3103 | case snd_soc_dapm_mux: | ||
3104 | case snd_soc_dapm_switch: | ||
3105 | case snd_soc_dapm_mixer: | ||
3106 | case snd_soc_dapm_mixer_named_ctl: | ||
3104 | case snd_soc_dapm_adc: | 3107 | case snd_soc_dapm_adc: |
3105 | case snd_soc_dapm_aif_out: | 3108 | case snd_soc_dapm_aif_out: |
3106 | case snd_soc_dapm_dac: | 3109 | case snd_soc_dapm_dac: |
3107 | case snd_soc_dapm_aif_in: | 3110 | case snd_soc_dapm_aif_in: |
3108 | case snd_soc_dapm_pga: | 3111 | case snd_soc_dapm_pga: |
3109 | case snd_soc_dapm_out_drv: | 3112 | case snd_soc_dapm_out_drv: |
3110 | case snd_soc_dapm_input: | ||
3111 | case snd_soc_dapm_output: | ||
3112 | case snd_soc_dapm_micbias: | 3113 | case snd_soc_dapm_micbias: |
3113 | case snd_soc_dapm_spk: | ||
3114 | case snd_soc_dapm_hp: | ||
3115 | case snd_soc_dapm_mic: | ||
3116 | case snd_soc_dapm_line: | 3114 | case snd_soc_dapm_line: |
3117 | case snd_soc_dapm_dai_link: | 3115 | case snd_soc_dapm_dai_link: |
3116 | case snd_soc_dapm_dai_out: | ||
3117 | case snd_soc_dapm_dai_in: | ||
3118 | w->power_check = dapm_generic_check_power; | 3118 | w->power_check = dapm_generic_check_power; |
3119 | break; | 3119 | break; |
3120 | case snd_soc_dapm_supply: | 3120 | case snd_soc_dapm_supply: |
3121 | case snd_soc_dapm_regulator_supply: | 3121 | case snd_soc_dapm_regulator_supply: |
3122 | case snd_soc_dapm_clock_supply: | 3122 | case snd_soc_dapm_clock_supply: |
3123 | case snd_soc_dapm_kcontrol: | 3123 | case snd_soc_dapm_kcontrol: |
3124 | w->is_supply = 1; | ||
3124 | w->power_check = dapm_supply_check_power; | 3125 | w->power_check = dapm_supply_check_power; |
3125 | break; | 3126 | break; |
3126 | default: | 3127 | default: |
@@ -3137,6 +3138,9 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3137 | INIT_LIST_HEAD(&w->dirty); | 3138 | INIT_LIST_HEAD(&w->dirty); |
3138 | list_add(&w->list, &dapm->card->widgets); | 3139 | list_add(&w->list, &dapm->card->widgets); |
3139 | 3140 | ||
3141 | w->inputs = -1; | ||
3142 | w->outputs = -1; | ||
3143 | |||
3140 | /* machine layer set ups unconnected pins and insertions */ | 3144 | /* machine layer set ups unconnected pins and insertions */ |
3141 | w->connected = 1; | 3145 | w->connected = 1; |
3142 | return w; | 3146 | return w; |
@@ -3484,6 +3488,14 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, | |||
3484 | case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: | 3488 | case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: |
3485 | break; | 3489 | break; |
3486 | } | 3490 | } |
3491 | |||
3492 | if (w->id == snd_soc_dapm_dai_in) { | ||
3493 | w->is_source = w->active; | ||
3494 | dapm_widget_invalidate_input_paths(w); | ||
3495 | } else { | ||
3496 | w->is_sink = w->active; | ||
3497 | dapm_widget_invalidate_output_paths(w); | ||
3498 | } | ||
3487 | } | 3499 | } |
3488 | } | 3500 | } |
3489 | 3501 | ||
@@ -3610,7 +3622,15 @@ int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, | |||
3610 | } | 3622 | } |
3611 | 3623 | ||
3612 | dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin); | 3624 | dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin); |
3613 | w->connected = 1; | 3625 | if (!w->connected) { |
3626 | /* | ||
3627 | * w->force does not affect the number of input or output paths, | ||
3628 | * so we only have to recheck if w->connected is changed | ||
3629 | */ | ||
3630 | dapm_widget_invalidate_input_paths(w); | ||
3631 | dapm_widget_invalidate_output_paths(w); | ||
3632 | w->connected = 1; | ||
3633 | } | ||
3614 | w->force = 1; | 3634 | w->force = 1; |
3615 | dapm_mark_dirty(w, "force enable"); | 3635 | dapm_mark_dirty(w, "force enable"); |
3616 | 3636 | ||
@@ -3788,35 +3808,54 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, | |||
3788 | } | 3808 | } |
3789 | EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); | 3809 | EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); |
3790 | 3810 | ||
3811 | /** | ||
3812 | * dapm_is_external_path() - Checks if a path is a external path | ||
3813 | * @card: The card the path belongs to | ||
3814 | * @path: The path to check | ||
3815 | * | ||
3816 | * Returns true if the path is either between two different DAPM contexts or | ||
3817 | * between two external pins of the same DAPM context. Otherwise returns | ||
3818 | * false. | ||
3819 | */ | ||
3820 | static bool dapm_is_external_path(struct snd_soc_card *card, | ||
3821 | struct snd_soc_dapm_path *path) | ||
3822 | { | ||
3823 | dev_dbg(card->dev, | ||
3824 | "... Path %s(id:%d dapm:%p) - %s(id:%d dapm:%p)\n", | ||
3825 | path->source->name, path->source->id, path->source->dapm, | ||
3826 | path->sink->name, path->sink->id, path->sink->dapm); | ||
3827 | |||
3828 | /* Connection between two different DAPM contexts */ | ||
3829 | if (path->source->dapm != path->sink->dapm) | ||
3830 | return true; | ||
3831 | |||
3832 | /* Loopback connection from external pin to external pin */ | ||
3833 | if (path->sink->id == snd_soc_dapm_input) { | ||
3834 | switch (path->source->id) { | ||
3835 | case snd_soc_dapm_output: | ||
3836 | case snd_soc_dapm_micbias: | ||
3837 | return true; | ||
3838 | default: | ||
3839 | break; | ||
3840 | } | ||
3841 | } | ||
3842 | |||
3843 | return false; | ||
3844 | } | ||
3845 | |||
3791 | static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card, | 3846 | static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card, |
3792 | struct snd_soc_dapm_widget *w) | 3847 | struct snd_soc_dapm_widget *w) |
3793 | { | 3848 | { |
3794 | struct snd_soc_dapm_path *p; | 3849 | struct snd_soc_dapm_path *p; |
3795 | 3850 | ||
3796 | list_for_each_entry(p, &card->paths, list) { | 3851 | list_for_each_entry(p, &w->sources, list_sink) { |
3797 | if ((p->source == w) || (p->sink == w)) { | 3852 | if (dapm_is_external_path(card, p)) |
3798 | dev_dbg(card->dev, | 3853 | return true; |
3799 | "... Path %s(id:%d dapm:%p) - %s(id:%d dapm:%p)\n", | 3854 | } |
3800 | p->source->name, p->source->id, p->source->dapm, | ||
3801 | p->sink->name, p->sink->id, p->sink->dapm); | ||
3802 | 3855 | ||
3803 | /* Connected to something other than the codec */ | 3856 | list_for_each_entry(p, &w->sinks, list_source) { |
3804 | if (p->source->dapm != p->sink->dapm) | 3857 | if (dapm_is_external_path(card, p)) |
3805 | return true; | 3858 | return true; |
3806 | /* | ||
3807 | * Loopback connection from codec external pin to | ||
3808 | * codec external pin | ||
3809 | */ | ||
3810 | if (p->sink->id == snd_soc_dapm_input) { | ||
3811 | switch (p->source->id) { | ||
3812 | case snd_soc_dapm_output: | ||
3813 | case snd_soc_dapm_micbias: | ||
3814 | return true; | ||
3815 | default: | ||
3816 | break; | ||
3817 | } | ||
3818 | } | ||
3819 | } | ||
3820 | } | 3859 | } |
3821 | 3860 | ||
3822 | return false; | 3861 | return false; |
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c new file mode 100644 index 000000000000..100d92b5b77e --- /dev/null +++ b/sound/soc/soc-ops.c | |||
@@ -0,0 +1,952 @@ | |||
1 | /* | ||
2 | * soc-ops.c -- Generic ASoC operations | ||
3 | * | ||
4 | * Copyright 2005 Wolfson Microelectronics PLC. | ||
5 | * Copyright 2005 Openedhand Ltd. | ||
6 | * Copyright (C) 2010 Slimlogic Ltd. | ||
7 | * Copyright (C) 2010 Texas Instruments Inc. | ||
8 | * | ||
9 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> | ||
10 | * with code, comments and ideas from :- | ||
11 | * Richard Purdie <richard@openedhand.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/moduleparam.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/pm.h> | ||
24 | #include <linux/bitops.h> | ||
25 | #include <linux/ctype.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <sound/core.h> | ||
28 | #include <sound/jack.h> | ||
29 | #include <sound/pcm.h> | ||
30 | #include <sound/pcm_params.h> | ||
31 | #include <sound/soc.h> | ||
32 | #include <sound/soc-dpcm.h> | ||
33 | #include <sound/initval.h> | ||
34 | |||
35 | /** | ||
36 | * snd_soc_info_enum_double - enumerated double mixer info callback | ||
37 | * @kcontrol: mixer control | ||
38 | * @uinfo: control element information | ||
39 | * | ||
40 | * Callback to provide information about a double enumerated | ||
41 | * mixer control. | ||
42 | * | ||
43 | * Returns 0 for success. | ||
44 | */ | ||
45 | int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, | ||
46 | struct snd_ctl_elem_info *uinfo) | ||
47 | { | ||
48 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
49 | |||
50 | return snd_ctl_enum_info(uinfo, e->shift_l == e->shift_r ? 1 : 2, | ||
51 | e->items, e->texts); | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(snd_soc_info_enum_double); | ||
54 | |||
55 | /** | ||
56 | * snd_soc_get_enum_double - enumerated double mixer get callback | ||
57 | * @kcontrol: mixer control | ||
58 | * @ucontrol: control element information | ||
59 | * | ||
60 | * Callback to get the value of a double enumerated mixer. | ||
61 | * | ||
62 | * Returns 0 for success. | ||
63 | */ | ||
64 | int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, | ||
65 | struct snd_ctl_elem_value *ucontrol) | ||
66 | { | ||
67 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
68 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
69 | unsigned int val, item; | ||
70 | unsigned int reg_val; | ||
71 | int ret; | ||
72 | |||
73 | ret = snd_soc_component_read(component, e->reg, ®_val); | ||
74 | if (ret) | ||
75 | return ret; | ||
76 | val = (reg_val >> e->shift_l) & e->mask; | ||
77 | item = snd_soc_enum_val_to_item(e, val); | ||
78 | ucontrol->value.enumerated.item[0] = item; | ||
79 | if (e->shift_l != e->shift_r) { | ||
80 | val = (reg_val >> e->shift_l) & e->mask; | ||
81 | item = snd_soc_enum_val_to_item(e, val); | ||
82 | ucontrol->value.enumerated.item[1] = item; | ||
83 | } | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | EXPORT_SYMBOL_GPL(snd_soc_get_enum_double); | ||
88 | |||
89 | /** | ||
90 | * snd_soc_put_enum_double - enumerated double mixer put callback | ||
91 | * @kcontrol: mixer control | ||
92 | * @ucontrol: control element information | ||
93 | * | ||
94 | * Callback to set the value of a double enumerated mixer. | ||
95 | * | ||
96 | * Returns 0 for success. | ||
97 | */ | ||
98 | int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | ||
99 | struct snd_ctl_elem_value *ucontrol) | ||
100 | { | ||
101 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
102 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
103 | unsigned int *item = ucontrol->value.enumerated.item; | ||
104 | unsigned int val; | ||
105 | unsigned int mask; | ||
106 | |||
107 | if (item[0] >= e->items) | ||
108 | return -EINVAL; | ||
109 | val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; | ||
110 | mask = e->mask << e->shift_l; | ||
111 | if (e->shift_l != e->shift_r) { | ||
112 | if (item[1] >= e->items) | ||
113 | return -EINVAL; | ||
114 | val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; | ||
115 | mask |= e->mask << e->shift_r; | ||
116 | } | ||
117 | |||
118 | return snd_soc_component_update_bits(component, e->reg, mask, val); | ||
119 | } | ||
120 | EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); | ||
121 | |||
122 | /** | ||
123 | * snd_soc_read_signed - Read a codec register and interprete as signed value | ||
124 | * @component: component | ||
125 | * @reg: Register to read | ||
126 | * @mask: Mask to use after shifting the register value | ||
127 | * @shift: Right shift of register value | ||
128 | * @sign_bit: Bit that describes if a number is negative or not. | ||
129 | * @signed_val: Pointer to where the read value should be stored | ||
130 | * | ||
131 | * This functions reads a codec register. The register value is shifted right | ||
132 | * by 'shift' bits and masked with the given 'mask'. Afterwards it translates | ||
133 | * the given registervalue into a signed integer if sign_bit is non-zero. | ||
134 | * | ||
135 | * Returns 0 on sucess, otherwise an error value | ||
136 | */ | ||
137 | static int snd_soc_read_signed(struct snd_soc_component *component, | ||
138 | unsigned int reg, unsigned int mask, unsigned int shift, | ||
139 | unsigned int sign_bit, int *signed_val) | ||
140 | { | ||
141 | int ret; | ||
142 | unsigned int val; | ||
143 | |||
144 | ret = snd_soc_component_read(component, reg, &val); | ||
145 | if (ret < 0) | ||
146 | return ret; | ||
147 | |||
148 | val = (val >> shift) & mask; | ||
149 | |||
150 | if (!sign_bit) { | ||
151 | *signed_val = val; | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | /* non-negative number */ | ||
156 | if (!(val & BIT(sign_bit))) { | ||
157 | *signed_val = val; | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | ret = val; | ||
162 | |||
163 | /* | ||
164 | * The register most probably does not contain a full-sized int. | ||
165 | * Instead we have an arbitrary number of bits in a signed | ||
166 | * representation which has to be translated into a full-sized int. | ||
167 | * This is done by filling up all bits above the sign-bit. | ||
168 | */ | ||
169 | ret |= ~((int)(BIT(sign_bit) - 1)); | ||
170 | |||
171 | *signed_val = ret; | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * snd_soc_info_volsw - single mixer info callback | ||
178 | * @kcontrol: mixer control | ||
179 | * @uinfo: control element information | ||
180 | * | ||
181 | * Callback to provide information about a single mixer control, or a double | ||
182 | * mixer control that spans 2 registers. | ||
183 | * | ||
184 | * Returns 0 for success. | ||
185 | */ | ||
186 | int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, | ||
187 | struct snd_ctl_elem_info *uinfo) | ||
188 | { | ||
189 | struct soc_mixer_control *mc = | ||
190 | (struct soc_mixer_control *)kcontrol->private_value; | ||
191 | int platform_max; | ||
192 | |||
193 | if (!mc->platform_max) | ||
194 | mc->platform_max = mc->max; | ||
195 | platform_max = mc->platform_max; | ||
196 | |||
197 | if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume")) | ||
198 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
199 | else | ||
200 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
201 | |||
202 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; | ||
203 | uinfo->value.integer.min = 0; | ||
204 | uinfo->value.integer.max = platform_max - mc->min; | ||
205 | return 0; | ||
206 | } | ||
207 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); | ||
208 | |||
209 | /** | ||
210 | * snd_soc_get_volsw - single mixer get callback | ||
211 | * @kcontrol: mixer control | ||
212 | * @ucontrol: control element information | ||
213 | * | ||
214 | * Callback to get the value of a single mixer control, or a double mixer | ||
215 | * control that spans 2 registers. | ||
216 | * | ||
217 | * Returns 0 for success. | ||
218 | */ | ||
219 | int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | ||
220 | struct snd_ctl_elem_value *ucontrol) | ||
221 | { | ||
222 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
223 | struct soc_mixer_control *mc = | ||
224 | (struct soc_mixer_control *)kcontrol->private_value; | ||
225 | unsigned int reg = mc->reg; | ||
226 | unsigned int reg2 = mc->rreg; | ||
227 | unsigned int shift = mc->shift; | ||
228 | unsigned int rshift = mc->rshift; | ||
229 | int max = mc->max; | ||
230 | int min = mc->min; | ||
231 | int sign_bit = mc->sign_bit; | ||
232 | unsigned int mask = (1 << fls(max)) - 1; | ||
233 | unsigned int invert = mc->invert; | ||
234 | int val; | ||
235 | int ret; | ||
236 | |||
237 | if (sign_bit) | ||
238 | mask = BIT(sign_bit + 1) - 1; | ||
239 | |||
240 | ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val); | ||
241 | if (ret) | ||
242 | return ret; | ||
243 | |||
244 | ucontrol->value.integer.value[0] = val - min; | ||
245 | if (invert) | ||
246 | ucontrol->value.integer.value[0] = | ||
247 | max - ucontrol->value.integer.value[0]; | ||
248 | |||
249 | if (snd_soc_volsw_is_stereo(mc)) { | ||
250 | if (reg == reg2) | ||
251 | ret = snd_soc_read_signed(component, reg, mask, rshift, | ||
252 | sign_bit, &val); | ||
253 | else | ||
254 | ret = snd_soc_read_signed(component, reg2, mask, shift, | ||
255 | sign_bit, &val); | ||
256 | if (ret) | ||
257 | return ret; | ||
258 | |||
259 | ucontrol->value.integer.value[1] = val - min; | ||
260 | if (invert) | ||
261 | ucontrol->value.integer.value[1] = | ||
262 | max - ucontrol->value.integer.value[1]; | ||
263 | } | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw); | ||
268 | |||
269 | /** | ||
270 | * snd_soc_put_volsw - single mixer put callback | ||
271 | * @kcontrol: mixer control | ||
272 | * @ucontrol: control element information | ||
273 | * | ||
274 | * Callback to set the value of a single mixer control, or a double mixer | ||
275 | * control that spans 2 registers. | ||
276 | * | ||
277 | * Returns 0 for success. | ||
278 | */ | ||
279 | int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | ||
280 | struct snd_ctl_elem_value *ucontrol) | ||
281 | { | ||
282 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
283 | struct soc_mixer_control *mc = | ||
284 | (struct soc_mixer_control *)kcontrol->private_value; | ||
285 | unsigned int reg = mc->reg; | ||
286 | unsigned int reg2 = mc->rreg; | ||
287 | unsigned int shift = mc->shift; | ||
288 | unsigned int rshift = mc->rshift; | ||
289 | int max = mc->max; | ||
290 | int min = mc->min; | ||
291 | unsigned int sign_bit = mc->sign_bit; | ||
292 | unsigned int mask = (1 << fls(max)) - 1; | ||
293 | unsigned int invert = mc->invert; | ||
294 | int err; | ||
295 | bool type_2r = false; | ||
296 | unsigned int val2 = 0; | ||
297 | unsigned int val, val_mask; | ||
298 | |||
299 | if (sign_bit) | ||
300 | mask = BIT(sign_bit + 1) - 1; | ||
301 | |||
302 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
303 | if (invert) | ||
304 | val = max - val; | ||
305 | val_mask = mask << shift; | ||
306 | val = val << shift; | ||
307 | if (snd_soc_volsw_is_stereo(mc)) { | ||
308 | val2 = ((ucontrol->value.integer.value[1] + min) & mask); | ||
309 | if (invert) | ||
310 | val2 = max - val2; | ||
311 | if (reg == reg2) { | ||
312 | val_mask |= mask << rshift; | ||
313 | val |= val2 << rshift; | ||
314 | } else { | ||
315 | val2 = val2 << shift; | ||
316 | type_2r = true; | ||
317 | } | ||
318 | } | ||
319 | err = snd_soc_component_update_bits(component, reg, val_mask, val); | ||
320 | if (err < 0) | ||
321 | return err; | ||
322 | |||
323 | if (type_2r) | ||
324 | err = snd_soc_component_update_bits(component, reg2, val_mask, | ||
325 | val2); | ||
326 | |||
327 | return err; | ||
328 | } | ||
329 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw); | ||
330 | |||
331 | /** | ||
332 | * snd_soc_get_volsw_sx - single mixer get callback | ||
333 | * @kcontrol: mixer control | ||
334 | * @ucontrol: control element information | ||
335 | * | ||
336 | * Callback to get the value of a single mixer control, or a double mixer | ||
337 | * control that spans 2 registers. | ||
338 | * | ||
339 | * Returns 0 for success. | ||
340 | */ | ||
341 | int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, | ||
342 | struct snd_ctl_elem_value *ucontrol) | ||
343 | { | ||
344 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
345 | struct soc_mixer_control *mc = | ||
346 | (struct soc_mixer_control *)kcontrol->private_value; | ||
347 | unsigned int reg = mc->reg; | ||
348 | unsigned int reg2 = mc->rreg; | ||
349 | unsigned int shift = mc->shift; | ||
350 | unsigned int rshift = mc->rshift; | ||
351 | int max = mc->max; | ||
352 | int min = mc->min; | ||
353 | int mask = (1 << (fls(min + max) - 1)) - 1; | ||
354 | unsigned int val; | ||
355 | int ret; | ||
356 | |||
357 | ret = snd_soc_component_read(component, reg, &val); | ||
358 | if (ret < 0) | ||
359 | return ret; | ||
360 | |||
361 | ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask; | ||
362 | |||
363 | if (snd_soc_volsw_is_stereo(mc)) { | ||
364 | ret = snd_soc_component_read(component, reg2, &val); | ||
365 | if (ret < 0) | ||
366 | return ret; | ||
367 | |||
368 | val = ((val >> rshift) - min) & mask; | ||
369 | ucontrol->value.integer.value[1] = val; | ||
370 | } | ||
371 | |||
372 | return 0; | ||
373 | } | ||
374 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx); | ||
375 | |||
376 | /** | ||
377 | * snd_soc_put_volsw_sx - double mixer set callback | ||
378 | * @kcontrol: mixer control | ||
379 | * @uinfo: control element information | ||
380 | * | ||
381 | * Callback to set the value of a double mixer control that spans 2 registers. | ||
382 | * | ||
383 | * Returns 0 for success. | ||
384 | */ | ||
385 | int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, | ||
386 | struct snd_ctl_elem_value *ucontrol) | ||
387 | { | ||
388 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
389 | struct soc_mixer_control *mc = | ||
390 | (struct soc_mixer_control *)kcontrol->private_value; | ||
391 | |||
392 | unsigned int reg = mc->reg; | ||
393 | unsigned int reg2 = mc->rreg; | ||
394 | unsigned int shift = mc->shift; | ||
395 | unsigned int rshift = mc->rshift; | ||
396 | int max = mc->max; | ||
397 | int min = mc->min; | ||
398 | int mask = (1 << (fls(min + max) - 1)) - 1; | ||
399 | int err = 0; | ||
400 | unsigned int val, val_mask, val2 = 0; | ||
401 | |||
402 | val_mask = mask << shift; | ||
403 | val = (ucontrol->value.integer.value[0] + min) & mask; | ||
404 | val = val << shift; | ||
405 | |||
406 | err = snd_soc_component_update_bits(component, reg, val_mask, val); | ||
407 | if (err < 0) | ||
408 | return err; | ||
409 | |||
410 | if (snd_soc_volsw_is_stereo(mc)) { | ||
411 | val_mask = mask << rshift; | ||
412 | val2 = (ucontrol->value.integer.value[1] + min) & mask; | ||
413 | val2 = val2 << rshift; | ||
414 | |||
415 | err = snd_soc_component_update_bits(component, reg2, val_mask, | ||
416 | val2); | ||
417 | } | ||
418 | return err; | ||
419 | } | ||
420 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); | ||
421 | |||
422 | /** | ||
423 | * snd_soc_info_volsw_range - single mixer info callback with range. | ||
424 | * @kcontrol: mixer control | ||
425 | * @uinfo: control element information | ||
426 | * | ||
427 | * Callback to provide information, within a range, about a single | ||
428 | * mixer control. | ||
429 | * | ||
430 | * returns 0 for success. | ||
431 | */ | ||
432 | int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, | ||
433 | struct snd_ctl_elem_info *uinfo) | ||
434 | { | ||
435 | struct soc_mixer_control *mc = | ||
436 | (struct soc_mixer_control *)kcontrol->private_value; | ||
437 | int platform_max; | ||
438 | int min = mc->min; | ||
439 | |||
440 | if (!mc->platform_max) | ||
441 | mc->platform_max = mc->max; | ||
442 | platform_max = mc->platform_max; | ||
443 | |||
444 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
445 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; | ||
446 | uinfo->value.integer.min = 0; | ||
447 | uinfo->value.integer.max = platform_max - min; | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); | ||
452 | |||
453 | /** | ||
454 | * snd_soc_put_volsw_range - single mixer put value callback with range. | ||
455 | * @kcontrol: mixer control | ||
456 | * @ucontrol: control element information | ||
457 | * | ||
458 | * Callback to set the value, within a range, for a single mixer control. | ||
459 | * | ||
460 | * Returns 0 for success. | ||
461 | */ | ||
462 | int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | ||
463 | struct snd_ctl_elem_value *ucontrol) | ||
464 | { | ||
465 | struct soc_mixer_control *mc = | ||
466 | (struct soc_mixer_control *)kcontrol->private_value; | ||
467 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
468 | unsigned int reg = mc->reg; | ||
469 | unsigned int rreg = mc->rreg; | ||
470 | unsigned int shift = mc->shift; | ||
471 | int min = mc->min; | ||
472 | int max = mc->max; | ||
473 | unsigned int mask = (1 << fls(max)) - 1; | ||
474 | unsigned int invert = mc->invert; | ||
475 | unsigned int val, val_mask; | ||
476 | int ret; | ||
477 | |||
478 | if (invert) | ||
479 | val = (max - ucontrol->value.integer.value[0]) & mask; | ||
480 | else | ||
481 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
482 | val_mask = mask << shift; | ||
483 | val = val << shift; | ||
484 | |||
485 | ret = snd_soc_component_update_bits(component, reg, val_mask, val); | ||
486 | if (ret < 0) | ||
487 | return ret; | ||
488 | |||
489 | if (snd_soc_volsw_is_stereo(mc)) { | ||
490 | if (invert) | ||
491 | val = (max - ucontrol->value.integer.value[1]) & mask; | ||
492 | else | ||
493 | val = ((ucontrol->value.integer.value[1] + min) & mask); | ||
494 | val_mask = mask << shift; | ||
495 | val = val << shift; | ||
496 | |||
497 | ret = snd_soc_component_update_bits(component, rreg, val_mask, | ||
498 | val); | ||
499 | } | ||
500 | |||
501 | return ret; | ||
502 | } | ||
503 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); | ||
504 | |||
505 | /** | ||
506 | * snd_soc_get_volsw_range - single mixer get callback with range | ||
507 | * @kcontrol: mixer control | ||
508 | * @ucontrol: control element information | ||
509 | * | ||
510 | * Callback to get the value, within a range, of a single mixer control. | ||
511 | * | ||
512 | * Returns 0 for success. | ||
513 | */ | ||
514 | int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, | ||
515 | struct snd_ctl_elem_value *ucontrol) | ||
516 | { | ||
517 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
518 | struct soc_mixer_control *mc = | ||
519 | (struct soc_mixer_control *)kcontrol->private_value; | ||
520 | unsigned int reg = mc->reg; | ||
521 | unsigned int rreg = mc->rreg; | ||
522 | unsigned int shift = mc->shift; | ||
523 | int min = mc->min; | ||
524 | int max = mc->max; | ||
525 | unsigned int mask = (1 << fls(max)) - 1; | ||
526 | unsigned int invert = mc->invert; | ||
527 | unsigned int val; | ||
528 | int ret; | ||
529 | |||
530 | ret = snd_soc_component_read(component, reg, &val); | ||
531 | if (ret) | ||
532 | return ret; | ||
533 | |||
534 | ucontrol->value.integer.value[0] = (val >> shift) & mask; | ||
535 | if (invert) | ||
536 | ucontrol->value.integer.value[0] = | ||
537 | max - ucontrol->value.integer.value[0]; | ||
538 | else | ||
539 | ucontrol->value.integer.value[0] = | ||
540 | ucontrol->value.integer.value[0] - min; | ||
541 | |||
542 | if (snd_soc_volsw_is_stereo(mc)) { | ||
543 | ret = snd_soc_component_read(component, rreg, &val); | ||
544 | if (ret) | ||
545 | return ret; | ||
546 | |||
547 | ucontrol->value.integer.value[1] = (val >> shift) & mask; | ||
548 | if (invert) | ||
549 | ucontrol->value.integer.value[1] = | ||
550 | max - ucontrol->value.integer.value[1]; | ||
551 | else | ||
552 | ucontrol->value.integer.value[1] = | ||
553 | ucontrol->value.integer.value[1] - min; | ||
554 | } | ||
555 | |||
556 | return 0; | ||
557 | } | ||
558 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); | ||
559 | |||
560 | /** | ||
561 | * snd_soc_limit_volume - Set new limit to an existing volume control. | ||
562 | * | ||
563 | * @codec: where to look for the control | ||
564 | * @name: Name of the control | ||
565 | * @max: new maximum limit | ||
566 | * | ||
567 | * Return 0 for success, else error. | ||
568 | */ | ||
569 | int snd_soc_limit_volume(struct snd_soc_codec *codec, | ||
570 | const char *name, int max) | ||
571 | { | ||
572 | struct snd_card *card = codec->component.card->snd_card; | ||
573 | struct snd_kcontrol *kctl; | ||
574 | struct soc_mixer_control *mc; | ||
575 | int found = 0; | ||
576 | int ret = -EINVAL; | ||
577 | |||
578 | /* Sanity check for name and max */ | ||
579 | if (unlikely(!name || max <= 0)) | ||
580 | return -EINVAL; | ||
581 | |||
582 | list_for_each_entry(kctl, &card->controls, list) { | ||
583 | if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) { | ||
584 | found = 1; | ||
585 | break; | ||
586 | } | ||
587 | } | ||
588 | if (found) { | ||
589 | mc = (struct soc_mixer_control *)kctl->private_value; | ||
590 | if (max <= mc->max) { | ||
591 | mc->platform_max = max; | ||
592 | ret = 0; | ||
593 | } | ||
594 | } | ||
595 | return ret; | ||
596 | } | ||
597 | EXPORT_SYMBOL_GPL(snd_soc_limit_volume); | ||
598 | |||
599 | int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, | ||
600 | struct snd_ctl_elem_info *uinfo) | ||
601 | { | ||
602 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
603 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
604 | |||
605 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
606 | uinfo->count = params->num_regs * component->val_bytes; | ||
607 | |||
608 | return 0; | ||
609 | } | ||
610 | EXPORT_SYMBOL_GPL(snd_soc_bytes_info); | ||
611 | |||
612 | int snd_soc_bytes_get(struct snd_kcontrol *kcontrol, | ||
613 | struct snd_ctl_elem_value *ucontrol) | ||
614 | { | ||
615 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
616 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
617 | int ret; | ||
618 | |||
619 | if (component->regmap) | ||
620 | ret = regmap_raw_read(component->regmap, params->base, | ||
621 | ucontrol->value.bytes.data, | ||
622 | params->num_regs * component->val_bytes); | ||
623 | else | ||
624 | ret = -EINVAL; | ||
625 | |||
626 | /* Hide any masked bytes to ensure consistent data reporting */ | ||
627 | if (ret == 0 && params->mask) { | ||
628 | switch (component->val_bytes) { | ||
629 | case 1: | ||
630 | ucontrol->value.bytes.data[0] &= ~params->mask; | ||
631 | break; | ||
632 | case 2: | ||
633 | ((u16 *)(&ucontrol->value.bytes.data))[0] | ||
634 | &= cpu_to_be16(~params->mask); | ||
635 | break; | ||
636 | case 4: | ||
637 | ((u32 *)(&ucontrol->value.bytes.data))[0] | ||
638 | &= cpu_to_be32(~params->mask); | ||
639 | break; | ||
640 | default: | ||
641 | return -EINVAL; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | return ret; | ||
646 | } | ||
647 | EXPORT_SYMBOL_GPL(snd_soc_bytes_get); | ||
648 | |||
649 | int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, | ||
650 | struct snd_ctl_elem_value *ucontrol) | ||
651 | { | ||
652 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
653 | struct soc_bytes *params = (void *)kcontrol->private_value; | ||
654 | int ret, len; | ||
655 | unsigned int val, mask; | ||
656 | void *data; | ||
657 | |||
658 | if (!component->regmap || !params->num_regs) | ||
659 | return -EINVAL; | ||
660 | |||
661 | len = params->num_regs * component->val_bytes; | ||
662 | |||
663 | data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA); | ||
664 | if (!data) | ||
665 | return -ENOMEM; | ||
666 | |||
667 | /* | ||
668 | * If we've got a mask then we need to preserve the register | ||
669 | * bits. We shouldn't modify the incoming data so take a | ||
670 | * copy. | ||
671 | */ | ||
672 | if (params->mask) { | ||
673 | ret = regmap_read(component->regmap, params->base, &val); | ||
674 | if (ret != 0) | ||
675 | goto out; | ||
676 | |||
677 | val &= params->mask; | ||
678 | |||
679 | switch (component->val_bytes) { | ||
680 | case 1: | ||
681 | ((u8 *)data)[0] &= ~params->mask; | ||
682 | ((u8 *)data)[0] |= val; | ||
683 | break; | ||
684 | case 2: | ||
685 | mask = ~params->mask; | ||
686 | ret = regmap_parse_val(component->regmap, | ||
687 | &mask, &mask); | ||
688 | if (ret != 0) | ||
689 | goto out; | ||
690 | |||
691 | ((u16 *)data)[0] &= mask; | ||
692 | |||
693 | ret = regmap_parse_val(component->regmap, | ||
694 | &val, &val); | ||
695 | if (ret != 0) | ||
696 | goto out; | ||
697 | |||
698 | ((u16 *)data)[0] |= val; | ||
699 | break; | ||
700 | case 4: | ||
701 | mask = ~params->mask; | ||
702 | ret = regmap_parse_val(component->regmap, | ||
703 | &mask, &mask); | ||
704 | if (ret != 0) | ||
705 | goto out; | ||
706 | |||
707 | ((u32 *)data)[0] &= mask; | ||
708 | |||
709 | ret = regmap_parse_val(component->regmap, | ||
710 | &val, &val); | ||
711 | if (ret != 0) | ||
712 | goto out; | ||
713 | |||
714 | ((u32 *)data)[0] |= val; | ||
715 | break; | ||
716 | default: | ||
717 | ret = -EINVAL; | ||
718 | goto out; | ||
719 | } | ||
720 | } | ||
721 | |||
722 | ret = regmap_raw_write(component->regmap, params->base, | ||
723 | data, len); | ||
724 | |||
725 | out: | ||
726 | kfree(data); | ||
727 | |||
728 | return ret; | ||
729 | } | ||
730 | EXPORT_SYMBOL_GPL(snd_soc_bytes_put); | ||
731 | |||
732 | int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, | ||
733 | struct snd_ctl_elem_info *ucontrol) | ||
734 | { | ||
735 | struct soc_bytes_ext *params = (void *)kcontrol->private_value; | ||
736 | |||
737 | ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
738 | ucontrol->count = params->max; | ||
739 | |||
740 | return 0; | ||
741 | } | ||
742 | EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); | ||
743 | |||
744 | int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, | ||
745 | unsigned int size, unsigned int __user *tlv) | ||
746 | { | ||
747 | struct soc_bytes_ext *params = (void *)kcontrol->private_value; | ||
748 | unsigned int count = size < params->max ? size : params->max; | ||
749 | int ret = -ENXIO; | ||
750 | |||
751 | switch (op_flag) { | ||
752 | case SNDRV_CTL_TLV_OP_READ: | ||
753 | if (params->get) | ||
754 | ret = params->get(tlv, count); | ||
755 | break; | ||
756 | case SNDRV_CTL_TLV_OP_WRITE: | ||
757 | if (params->put) | ||
758 | ret = params->put(tlv, count); | ||
759 | break; | ||
760 | } | ||
761 | return ret; | ||
762 | } | ||
763 | EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); | ||
764 | |||
765 | /** | ||
766 | * snd_soc_info_xr_sx - signed multi register info callback | ||
767 | * @kcontrol: mreg control | ||
768 | * @uinfo: control element information | ||
769 | * | ||
770 | * Callback to provide information of a control that can | ||
771 | * span multiple codec registers which together | ||
772 | * forms a single signed value in a MSB/LSB manner. | ||
773 | * | ||
774 | * Returns 0 for success. | ||
775 | */ | ||
776 | int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, | ||
777 | struct snd_ctl_elem_info *uinfo) | ||
778 | { | ||
779 | struct soc_mreg_control *mc = | ||
780 | (struct soc_mreg_control *)kcontrol->private_value; | ||
781 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
782 | uinfo->count = 1; | ||
783 | uinfo->value.integer.min = mc->min; | ||
784 | uinfo->value.integer.max = mc->max; | ||
785 | |||
786 | return 0; | ||
787 | } | ||
788 | EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx); | ||
789 | |||
790 | /** | ||
791 | * snd_soc_get_xr_sx - signed multi register get callback | ||
792 | * @kcontrol: mreg control | ||
793 | * @ucontrol: control element information | ||
794 | * | ||
795 | * Callback to get the value of a control that can span | ||
796 | * multiple codec registers which together forms a single | ||
797 | * signed value in a MSB/LSB manner. The control supports | ||
798 | * specifying total no of bits used to allow for bitfields | ||
799 | * across the multiple codec registers. | ||
800 | * | ||
801 | * Returns 0 for success. | ||
802 | */ | ||
803 | int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, | ||
804 | struct snd_ctl_elem_value *ucontrol) | ||
805 | { | ||
806 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
807 | struct soc_mreg_control *mc = | ||
808 | (struct soc_mreg_control *)kcontrol->private_value; | ||
809 | unsigned int regbase = mc->regbase; | ||
810 | unsigned int regcount = mc->regcount; | ||
811 | unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; | ||
812 | unsigned int regwmask = (1<<regwshift)-1; | ||
813 | unsigned int invert = mc->invert; | ||
814 | unsigned long mask = (1UL<<mc->nbits)-1; | ||
815 | long min = mc->min; | ||
816 | long max = mc->max; | ||
817 | long val = 0; | ||
818 | unsigned int regval; | ||
819 | unsigned int i; | ||
820 | int ret; | ||
821 | |||
822 | for (i = 0; i < regcount; i++) { | ||
823 | ret = snd_soc_component_read(component, regbase+i, ®val); | ||
824 | if (ret) | ||
825 | return ret; | ||
826 | val |= (regval & regwmask) << (regwshift*(regcount-i-1)); | ||
827 | } | ||
828 | val &= mask; | ||
829 | if (min < 0 && val > max) | ||
830 | val |= ~mask; | ||
831 | if (invert) | ||
832 | val = max - val; | ||
833 | ucontrol->value.integer.value[0] = val; | ||
834 | |||
835 | return 0; | ||
836 | } | ||
837 | EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx); | ||
838 | |||
839 | /** | ||
840 | * snd_soc_put_xr_sx - signed multi register get callback | ||
841 | * @kcontrol: mreg control | ||
842 | * @ucontrol: control element information | ||
843 | * | ||
844 | * Callback to set the value of a control that can span | ||
845 | * multiple codec registers which together forms a single | ||
846 | * signed value in a MSB/LSB manner. The control supports | ||
847 | * specifying total no of bits used to allow for bitfields | ||
848 | * across the multiple codec registers. | ||
849 | * | ||
850 | * Returns 0 for success. | ||
851 | */ | ||
852 | int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, | ||
853 | struct snd_ctl_elem_value *ucontrol) | ||
854 | { | ||
855 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
856 | struct soc_mreg_control *mc = | ||
857 | (struct soc_mreg_control *)kcontrol->private_value; | ||
858 | unsigned int regbase = mc->regbase; | ||
859 | unsigned int regcount = mc->regcount; | ||
860 | unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; | ||
861 | unsigned int regwmask = (1<<regwshift)-1; | ||
862 | unsigned int invert = mc->invert; | ||
863 | unsigned long mask = (1UL<<mc->nbits)-1; | ||
864 | long max = mc->max; | ||
865 | long val = ucontrol->value.integer.value[0]; | ||
866 | unsigned int i, regval, regmask; | ||
867 | int err; | ||
868 | |||
869 | if (invert) | ||
870 | val = max - val; | ||
871 | val &= mask; | ||
872 | for (i = 0; i < regcount; i++) { | ||
873 | regval = (val >> (regwshift*(regcount-i-1))) & regwmask; | ||
874 | regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask; | ||
875 | err = snd_soc_component_update_bits(component, regbase+i, | ||
876 | regmask, regval); | ||
877 | if (err < 0) | ||
878 | return err; | ||
879 | } | ||
880 | |||
881 | return 0; | ||
882 | } | ||
883 | EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx); | ||
884 | |||
885 | /** | ||
886 | * snd_soc_get_strobe - strobe get callback | ||
887 | * @kcontrol: mixer control | ||
888 | * @ucontrol: control element information | ||
889 | * | ||
890 | * Callback get the value of a strobe mixer control. | ||
891 | * | ||
892 | * Returns 0 for success. | ||
893 | */ | ||
894 | int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, | ||
895 | struct snd_ctl_elem_value *ucontrol) | ||
896 | { | ||
897 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
898 | struct soc_mixer_control *mc = | ||
899 | (struct soc_mixer_control *)kcontrol->private_value; | ||
900 | unsigned int reg = mc->reg; | ||
901 | unsigned int shift = mc->shift; | ||
902 | unsigned int mask = 1 << shift; | ||
903 | unsigned int invert = mc->invert != 0; | ||
904 | unsigned int val; | ||
905 | int ret; | ||
906 | |||
907 | ret = snd_soc_component_read(component, reg, &val); | ||
908 | if (ret) | ||
909 | return ret; | ||
910 | |||
911 | val &= mask; | ||
912 | |||
913 | if (shift != 0 && val != 0) | ||
914 | val = val >> shift; | ||
915 | ucontrol->value.enumerated.item[0] = val ^ invert; | ||
916 | |||
917 | return 0; | ||
918 | } | ||
919 | EXPORT_SYMBOL_GPL(snd_soc_get_strobe); | ||
920 | |||
921 | /** | ||
922 | * snd_soc_put_strobe - strobe put callback | ||
923 | * @kcontrol: mixer control | ||
924 | * @ucontrol: control element information | ||
925 | * | ||
926 | * Callback strobe a register bit to high then low (or the inverse) | ||
927 | * in one pass of a single mixer enum control. | ||
928 | * | ||
929 | * Returns 1 for success. | ||
930 | */ | ||
931 | int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, | ||
932 | struct snd_ctl_elem_value *ucontrol) | ||
933 | { | ||
934 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
935 | struct soc_mixer_control *mc = | ||
936 | (struct soc_mixer_control *)kcontrol->private_value; | ||
937 | unsigned int reg = mc->reg; | ||
938 | unsigned int shift = mc->shift; | ||
939 | unsigned int mask = 1 << shift; | ||
940 | unsigned int invert = mc->invert != 0; | ||
941 | unsigned int strobe = ucontrol->value.enumerated.item[0] != 0; | ||
942 | unsigned int val1 = (strobe ^ invert) ? mask : 0; | ||
943 | unsigned int val2 = (strobe ^ invert) ? 0 : mask; | ||
944 | int err; | ||
945 | |||
946 | err = snd_soc_component_update_bits(component, reg, mask, val1); | ||
947 | if (err < 0) | ||
948 | return err; | ||
949 | |||
950 | return snd_soc_component_update_bits(component, reg, mask, val2); | ||
951 | } | ||
952 | EXPORT_SYMBOL_GPL(snd_soc_put_strobe); | ||
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 002311afdeaa..5de2440ff25c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -654,6 +654,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
654 | codec_dai->rate = 0; | 654 | codec_dai->rate = 0; |
655 | } | 655 | } |
656 | 656 | ||
657 | snd_soc_dai_digital_mute(cpu_dai, 1, substream->stream); | ||
658 | |||
657 | if (cpu_dai->driver->ops->shutdown) | 659 | if (cpu_dai->driver->ops->shutdown) |
658 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | 660 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); |
659 | 661 | ||
@@ -772,6 +774,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
772 | for (i = 0; i < rtd->num_codecs; i++) | 774 | for (i = 0; i < rtd->num_codecs; i++) |
773 | snd_soc_dai_digital_mute(rtd->codec_dais[i], 0, | 775 | snd_soc_dai_digital_mute(rtd->codec_dais[i], 0, |
774 | substream->stream); | 776 | substream->stream); |
777 | snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); | ||
775 | 778 | ||
776 | out: | 779 | out: |
777 | mutex_unlock(&rtd->pcm_mutex); | 780 | mutex_unlock(&rtd->pcm_mutex); |
@@ -1522,13 +1525,36 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) | |||
1522 | dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture); | 1525 | dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture); |
1523 | } | 1526 | } |
1524 | 1527 | ||
1528 | static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd); | ||
1529 | |||
1530 | /* Set FE's runtime_update state; the state is protected via PCM stream lock | ||
1531 | * for avoiding the race with trigger callback. | ||
1532 | * If the state is unset and a trigger is pending while the previous operation, | ||
1533 | * process the pending trigger action here. | ||
1534 | */ | ||
1535 | static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe, | ||
1536 | int stream, enum snd_soc_dpcm_update state) | ||
1537 | { | ||
1538 | struct snd_pcm_substream *substream = | ||
1539 | snd_soc_dpcm_get_substream(fe, stream); | ||
1540 | |||
1541 | snd_pcm_stream_lock_irq(substream); | ||
1542 | if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) { | ||
1543 | dpcm_fe_dai_do_trigger(substream, | ||
1544 | fe->dpcm[stream].trigger_pending - 1); | ||
1545 | fe->dpcm[stream].trigger_pending = 0; | ||
1546 | } | ||
1547 | fe->dpcm[stream].runtime_update = state; | ||
1548 | snd_pcm_stream_unlock_irq(substream); | ||
1549 | } | ||
1550 | |||
1525 | static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) | 1551 | static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) |
1526 | { | 1552 | { |
1527 | struct snd_soc_pcm_runtime *fe = fe_substream->private_data; | 1553 | struct snd_soc_pcm_runtime *fe = fe_substream->private_data; |
1528 | struct snd_pcm_runtime *runtime = fe_substream->runtime; | 1554 | struct snd_pcm_runtime *runtime = fe_substream->runtime; |
1529 | int stream = fe_substream->stream, ret = 0; | 1555 | int stream = fe_substream->stream, ret = 0; |
1530 | 1556 | ||
1531 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; | 1557 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); |
1532 | 1558 | ||
1533 | ret = dpcm_be_dai_startup(fe, fe_substream->stream); | 1559 | ret = dpcm_be_dai_startup(fe, fe_substream->stream); |
1534 | if (ret < 0) { | 1560 | if (ret < 0) { |
@@ -1550,13 +1576,13 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) | |||
1550 | dpcm_set_fe_runtime(fe_substream); | 1576 | dpcm_set_fe_runtime(fe_substream); |
1551 | snd_pcm_limit_hw_rates(runtime); | 1577 | snd_pcm_limit_hw_rates(runtime); |
1552 | 1578 | ||
1553 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | 1579 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); |
1554 | return 0; | 1580 | return 0; |
1555 | 1581 | ||
1556 | unwind: | 1582 | unwind: |
1557 | dpcm_be_dai_startup_unwind(fe, fe_substream->stream); | 1583 | dpcm_be_dai_startup_unwind(fe, fe_substream->stream); |
1558 | be_err: | 1584 | be_err: |
1559 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | 1585 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); |
1560 | return ret; | 1586 | return ret; |
1561 | } | 1587 | } |
1562 | 1588 | ||
@@ -1603,7 +1629,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) | |||
1603 | struct snd_soc_pcm_runtime *fe = substream->private_data; | 1629 | struct snd_soc_pcm_runtime *fe = substream->private_data; |
1604 | int stream = substream->stream; | 1630 | int stream = substream->stream; |
1605 | 1631 | ||
1606 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; | 1632 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); |
1607 | 1633 | ||
1608 | /* shutdown the BEs */ | 1634 | /* shutdown the BEs */ |
1609 | dpcm_be_dai_shutdown(fe, substream->stream); | 1635 | dpcm_be_dai_shutdown(fe, substream->stream); |
@@ -1617,7 +1643,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) | |||
1617 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); | 1643 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); |
1618 | 1644 | ||
1619 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; | 1645 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; |
1620 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | 1646 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); |
1621 | return 0; | 1647 | return 0; |
1622 | } | 1648 | } |
1623 | 1649 | ||
@@ -1641,6 +1667,10 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) | |||
1641 | if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) | 1667 | if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream)) |
1642 | continue; | 1668 | continue; |
1643 | 1669 | ||
1670 | /* do not free hw if this BE is used by other FE */ | ||
1671 | if (be->dpcm[stream].users > 1) | ||
1672 | continue; | ||
1673 | |||
1644 | if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && | 1674 | if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && |
1645 | (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) && | 1675 | (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) && |
1646 | (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) && | 1676 | (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) && |
@@ -1665,7 +1695,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) | |||
1665 | int err, stream = substream->stream; | 1695 | int err, stream = substream->stream; |
1666 | 1696 | ||
1667 | mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); | 1697 | mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); |
1668 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; | 1698 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); |
1669 | 1699 | ||
1670 | dev_dbg(fe->dev, "ASoC: hw_free FE %s\n", fe->dai_link->name); | 1700 | dev_dbg(fe->dev, "ASoC: hw_free FE %s\n", fe->dai_link->name); |
1671 | 1701 | ||
@@ -1680,7 +1710,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) | |||
1680 | err = dpcm_be_dai_hw_free(fe, stream); | 1710 | err = dpcm_be_dai_hw_free(fe, stream); |
1681 | 1711 | ||
1682 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE; | 1712 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE; |
1683 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | 1713 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); |
1684 | 1714 | ||
1685 | mutex_unlock(&fe->card->mutex); | 1715 | mutex_unlock(&fe->card->mutex); |
1686 | return 0; | 1716 | return 0; |
@@ -1773,7 +1803,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, | |||
1773 | int ret, stream = substream->stream; | 1803 | int ret, stream = substream->stream; |
1774 | 1804 | ||
1775 | mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); | 1805 | mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); |
1776 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; | 1806 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); |
1777 | 1807 | ||
1778 | memcpy(&fe->dpcm[substream->stream].hw_params, params, | 1808 | memcpy(&fe->dpcm[substream->stream].hw_params, params, |
1779 | sizeof(struct snd_pcm_hw_params)); | 1809 | sizeof(struct snd_pcm_hw_params)); |
@@ -1796,7 +1826,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, | |||
1796 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS; | 1826 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS; |
1797 | 1827 | ||
1798 | out: | 1828 | out: |
1799 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | 1829 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); |
1800 | mutex_unlock(&fe->card->mutex); | 1830 | mutex_unlock(&fe->card->mutex); |
1801 | return ret; | 1831 | return ret; |
1802 | } | 1832 | } |
@@ -1910,7 +1940,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, | |||
1910 | } | 1940 | } |
1911 | EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger); | 1941 | EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger); |
1912 | 1942 | ||
1913 | static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd) | 1943 | static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) |
1914 | { | 1944 | { |
1915 | struct snd_soc_pcm_runtime *fe = substream->private_data; | 1945 | struct snd_soc_pcm_runtime *fe = substream->private_data; |
1916 | int stream = substream->stream, ret; | 1946 | int stream = substream->stream, ret; |
@@ -1984,6 +2014,23 @@ out: | |||
1984 | return ret; | 2014 | return ret; |
1985 | } | 2015 | } |
1986 | 2016 | ||
2017 | static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd) | ||
2018 | { | ||
2019 | struct snd_soc_pcm_runtime *fe = substream->private_data; | ||
2020 | int stream = substream->stream; | ||
2021 | |||
2022 | /* if FE's runtime_update is already set, we're in race; | ||
2023 | * process this trigger later at exit | ||
2024 | */ | ||
2025 | if (fe->dpcm[stream].runtime_update != SND_SOC_DPCM_UPDATE_NO) { | ||
2026 | fe->dpcm[stream].trigger_pending = cmd + 1; | ||
2027 | return 0; /* delayed, assuming it's successful */ | ||
2028 | } | ||
2029 | |||
2030 | /* we're alone, let's trigger */ | ||
2031 | return dpcm_fe_dai_do_trigger(substream, cmd); | ||
2032 | } | ||
2033 | |||
1987 | int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) | 2034 | int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) |
1988 | { | 2035 | { |
1989 | struct snd_soc_dpcm *dpcm; | 2036 | struct snd_soc_dpcm *dpcm; |
@@ -2027,7 +2074,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) | |||
2027 | 2074 | ||
2028 | dev_dbg(fe->dev, "ASoC: prepare FE %s\n", fe->dai_link->name); | 2075 | dev_dbg(fe->dev, "ASoC: prepare FE %s\n", fe->dai_link->name); |
2029 | 2076 | ||
2030 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; | 2077 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); |
2031 | 2078 | ||
2032 | /* there is no point preparing this FE if there are no BEs */ | 2079 | /* there is no point preparing this FE if there are no BEs */ |
2033 | if (list_empty(&fe->dpcm[stream].be_clients)) { | 2080 | if (list_empty(&fe->dpcm[stream].be_clients)) { |
@@ -2054,7 +2101,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) | |||
2054 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; | 2101 | fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; |
2055 | 2102 | ||
2056 | out: | 2103 | out: |
2057 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | 2104 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); |
2058 | mutex_unlock(&fe->card->mutex); | 2105 | mutex_unlock(&fe->card->mutex); |
2059 | 2106 | ||
2060 | return ret; | 2107 | return ret; |
@@ -2201,11 +2248,11 @@ static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream) | |||
2201 | { | 2248 | { |
2202 | int ret; | 2249 | int ret; |
2203 | 2250 | ||
2204 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE; | 2251 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE); |
2205 | ret = dpcm_run_update_startup(fe, stream); | 2252 | ret = dpcm_run_update_startup(fe, stream); |
2206 | if (ret < 0) | 2253 | if (ret < 0) |
2207 | dev_err(fe->dev, "ASoC: failed to startup some BEs\n"); | 2254 | dev_err(fe->dev, "ASoC: failed to startup some BEs\n"); |
2208 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | 2255 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); |
2209 | 2256 | ||
2210 | return ret; | 2257 | return ret; |
2211 | } | 2258 | } |
@@ -2214,11 +2261,11 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream) | |||
2214 | { | 2261 | { |
2215 | int ret; | 2262 | int ret; |
2216 | 2263 | ||
2217 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE; | 2264 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE); |
2218 | ret = dpcm_run_update_shutdown(fe, stream); | 2265 | ret = dpcm_run_update_shutdown(fe, stream); |
2219 | if (ret < 0) | 2266 | if (ret < 0) |
2220 | dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n"); | 2267 | dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n"); |
2221 | fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; | 2268 | dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); |
2222 | 2269 | ||
2223 | return ret; | 2270 | return ret; |
2224 | } | 2271 | } |
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index 3b0fa12dbff7..29a9957d335a 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c | |||
@@ -228,7 +228,7 @@ static int tegra20_ac97_probe(struct snd_soc_dai *dai) | |||
228 | 228 | ||
229 | static struct snd_soc_dai_driver tegra20_ac97_dai = { | 229 | static struct snd_soc_dai_driver tegra20_ac97_dai = { |
230 | .name = "tegra-ac97-pcm", | 230 | .name = "tegra-ac97-pcm", |
231 | .ac97_control = 1, | 231 | .bus_control = true, |
232 | .probe = tegra20_ac97_probe, | 232 | .probe = tegra20_ac97_probe, |
233 | .playback = { | 233 | .playback = { |
234 | .stream_name = "PCM Playback", | 234 | .stream_name = "PCM Playback", |
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index 9edd68db9f48..f7135cdaa2ca 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c | |||
@@ -152,7 +152,7 @@ static int txx9aclc_ac97_remove(struct snd_soc_dai *dai) | |||
152 | } | 152 | } |
153 | 153 | ||
154 | static struct snd_soc_dai_driver txx9aclc_ac97_dai = { | 154 | static struct snd_soc_dai_driver txx9aclc_ac97_dai = { |
155 | .ac97_control = 1, | 155 | .bus_control = true, |
156 | .probe = txx9aclc_ac97_probe, | 156 | .probe = txx9aclc_ac97_probe, |
157 | .remove = txx9aclc_ac97_remove, | 157 | .remove = txx9aclc_ac97_remove, |
158 | .playback = { | 158 | .playback = { |
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index cd71fd889d8b..00b7e2d02690 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c | |||
@@ -292,7 +292,7 @@ static int txx9aclc_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
292 | struct snd_card *card = rtd->card->snd_card; | 292 | struct snd_card *card = rtd->card->snd_card; |
293 | struct snd_soc_dai *dai = rtd->cpu_dai; | 293 | struct snd_soc_dai *dai = rtd->cpu_dai; |
294 | struct snd_pcm *pcm = rtd->pcm; | 294 | struct snd_pcm *pcm = rtd->pcm; |
295 | struct platform_device *pdev = to_platform_device(dai->platform->dev); | 295 | struct platform_device *pdev = to_platform_device(rtd->platform->dev); |
296 | struct txx9aclc_soc_device *dev; | 296 | struct txx9aclc_soc_device *dev; |
297 | struct resource *r; | 297 | struct resource *r; |
298 | int i; | 298 | int i; |