diff options
Diffstat (limited to 'sound')
138 files changed, 5110 insertions, 2981 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index c5de0a84566f..5da8ca7aee05 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -9,6 +9,7 @@ menuconfig SND_SOC | |||
9 | select SND_JACK if INPUT=y || INPUT=SND | 9 | select SND_JACK if INPUT=y || INPUT=SND |
10 | select REGMAP_I2C if I2C | 10 | select REGMAP_I2C if I2C |
11 | select REGMAP_SPI if SPI_MASTER | 11 | select REGMAP_SPI if SPI_MASTER |
12 | select SND_COMPRESS_OFFLOAD | ||
12 | ---help--- | 13 | ---help--- |
13 | 14 | ||
14 | If you want ASoC support, you should say Y here and also to the | 15 | If you want ASoC support, you should say Y here and also to the |
@@ -32,9 +33,9 @@ config SND_SOC_DMAENGINE_PCM | |||
32 | source "sound/soc/atmel/Kconfig" | 33 | source "sound/soc/atmel/Kconfig" |
33 | source "sound/soc/au1x/Kconfig" | 34 | source "sound/soc/au1x/Kconfig" |
34 | source "sound/soc/blackfin/Kconfig" | 35 | source "sound/soc/blackfin/Kconfig" |
36 | source "sound/soc/cirrus/Kconfig" | ||
35 | source "sound/soc/davinci/Kconfig" | 37 | source "sound/soc/davinci/Kconfig" |
36 | source "sound/soc/dwc/Kconfig" | 38 | source "sound/soc/dwc/Kconfig" |
37 | source "sound/soc/ep93xx/Kconfig" | ||
38 | source "sound/soc/fsl/Kconfig" | 39 | source "sound/soc/fsl/Kconfig" |
39 | source "sound/soc/jz4740/Kconfig" | 40 | source "sound/soc/jz4740/Kconfig" |
40 | source "sound/soc/nuc900/Kconfig" | 41 | source "sound/soc/nuc900/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 00a555a743b6..bcbf1d00aa85 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -1,5 +1,5 @@ | |||
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-io.o | 2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o |
3 | 3 | ||
4 | snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o | 4 | snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o |
5 | obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o | 5 | obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o |
@@ -10,9 +10,9 @@ obj-$(CONFIG_SND_SOC) += generic/ | |||
10 | obj-$(CONFIG_SND_SOC) += atmel/ | 10 | obj-$(CONFIG_SND_SOC) += atmel/ |
11 | obj-$(CONFIG_SND_SOC) += au1x/ | 11 | obj-$(CONFIG_SND_SOC) += au1x/ |
12 | obj-$(CONFIG_SND_SOC) += blackfin/ | 12 | obj-$(CONFIG_SND_SOC) += blackfin/ |
13 | obj-$(CONFIG_SND_SOC) += cirrus/ | ||
13 | obj-$(CONFIG_SND_SOC) += davinci/ | 14 | obj-$(CONFIG_SND_SOC) += davinci/ |
14 | obj-$(CONFIG_SND_SOC) += dwc/ | 15 | obj-$(CONFIG_SND_SOC) += dwc/ |
15 | obj-$(CONFIG_SND_SOC) += ep93xx/ | ||
16 | obj-$(CONFIG_SND_SOC) += fsl/ | 16 | obj-$(CONFIG_SND_SOC) += fsl/ |
17 | obj-$(CONFIG_SND_SOC) += jz4740/ | 17 | obj-$(CONFIG_SND_SOC) += jz4740/ |
18 | obj-$(CONFIG_SND_SOC) += mid-x86/ | 18 | obj-$(CONFIG_SND_SOC) += mid-x86/ |
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index d542d4063771..16b9c9efd19a 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c | |||
@@ -59,62 +59,63 @@ static struct snd_soc_ops bf5xx_ad1836_ops = { | |||
59 | #define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ | 59 | #define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ |
60 | SND_SOC_DAIFMT_CBM_CFM) | 60 | SND_SOC_DAIFMT_CBM_CFM) |
61 | 61 | ||
62 | static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { | 62 | static struct snd_soc_dai_link bf5xx_ad1836_dai = { |
63 | { | 63 | .name = "ad1836", |
64 | .name = "ad1836", | 64 | .stream_name = "AD1836", |
65 | .stream_name = "AD1836", | 65 | .codec_dai_name = "ad1836-hifi", |
66 | .cpu_dai_name = "bfin-tdm.0", | 66 | .platform_name = "bfin-tdm-pcm-audio", |
67 | .codec_dai_name = "ad1836-hifi", | 67 | .ops = &bf5xx_ad1836_ops, |
68 | .platform_name = "bfin-tdm-pcm-audio", | 68 | .dai_fmt = BF5XX_AD1836_DAIFMT, |
69 | .codec_name = "spi0.4", | ||
70 | .ops = &bf5xx_ad1836_ops, | ||
71 | .dai_fmt = BF5XX_AD1836_DAIFMT, | ||
72 | }, | ||
73 | { | ||
74 | .name = "ad1836", | ||
75 | .stream_name = "AD1836", | ||
76 | .cpu_dai_name = "bfin-tdm.1", | ||
77 | .codec_dai_name = "ad1836-hifi", | ||
78 | .platform_name = "bfin-tdm-pcm-audio", | ||
79 | .codec_name = "spi0.4", | ||
80 | .ops = &bf5xx_ad1836_ops, | ||
81 | .dai_fmt = BF5XX_AD1836_DAIFMT, | ||
82 | }, | ||
83 | }; | 69 | }; |
84 | 70 | ||
85 | static struct snd_soc_card bf5xx_ad1836 = { | 71 | static struct snd_soc_card bf5xx_ad1836 = { |
86 | .name = "bfin-ad1836", | 72 | .name = "bfin-ad1836", |
87 | .owner = THIS_MODULE, | 73 | .owner = THIS_MODULE, |
88 | .dai_link = &bf5xx_ad1836_dai[CONFIG_SND_BF5XX_SPORT_NUM], | 74 | .dai_link = &bf5xx_ad1836_dai, |
89 | .num_links = 1, | 75 | .num_links = 1, |
90 | }; | 76 | }; |
91 | 77 | ||
92 | static struct platform_device *bfxx_ad1836_snd_device; | 78 | static __devinit int bf5xx_ad1836_driver_probe(struct platform_device *pdev) |
93 | |||
94 | static int __init bf5xx_ad1836_init(void) | ||
95 | { | 79 | { |
80 | struct snd_soc_card *card = &bf5xx_ad1836; | ||
81 | const char **link_name; | ||
96 | int ret; | 82 | int ret; |
97 | 83 | ||
98 | bfxx_ad1836_snd_device = platform_device_alloc("soc-audio", -1); | 84 | link_name = pdev->dev.platform_data; |
99 | if (!bfxx_ad1836_snd_device) | 85 | if (!link_name) { |
100 | return -ENOMEM; | 86 | dev_err(&pdev->dev, "No platform data supplied\n"); |
87 | return -EINVAL; | ||
88 | } | ||
89 | bf5xx_ad1836_dai.cpu_dai_name = link_name[0]; | ||
90 | bf5xx_ad1836_dai.codec_name = link_name[1]; | ||
101 | 91 | ||
102 | platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836); | 92 | card->dev = &pdev->dev; |
103 | ret = platform_device_add(bfxx_ad1836_snd_device); | 93 | platform_set_drvdata(pdev, card); |
104 | 94 | ||
95 | ret = snd_soc_register_card(card); | ||
105 | if (ret) | 96 | if (ret) |
106 | platform_device_put(bfxx_ad1836_snd_device); | 97 | dev_err(&pdev->dev, "Failed to register card\n"); |
107 | |||
108 | return ret; | 98 | return ret; |
109 | } | 99 | } |
110 | 100 | ||
111 | static void __exit bf5xx_ad1836_exit(void) | 101 | static int __devexit bf5xx_ad1836_driver_remove(struct platform_device *pdev) |
112 | { | 102 | { |
113 | platform_device_unregister(bfxx_ad1836_snd_device); | 103 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
104 | |||
105 | snd_soc_unregister_card(card); | ||
106 | return 0; | ||
114 | } | 107 | } |
115 | 108 | ||
116 | module_init(bf5xx_ad1836_init); | 109 | static struct platform_driver bf5xx_ad1836_driver = { |
117 | module_exit(bf5xx_ad1836_exit); | 110 | .driver = { |
111 | .name = "bfin-snd-ad1836", | ||
112 | .owner = THIS_MODULE, | ||
113 | .pm = &snd_soc_pm_ops, | ||
114 | }, | ||
115 | .probe = bf5xx_ad1836_driver_probe, | ||
116 | .remove = __devexit_p(bf5xx_ad1836_driver_remove), | ||
117 | }; | ||
118 | module_platform_driver(bf5xx_ad1836_driver); | ||
118 | 119 | ||
119 | /* Module information */ | 120 | /* Module information */ |
120 | MODULE_AUTHOR("Barry Song"); | 121 | MODULE_AUTHOR("Barry Song"); |
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/cirrus/Kconfig index 88143db7e753..88143db7e753 100644 --- a/sound/soc/ep93xx/Kconfig +++ b/sound/soc/cirrus/Kconfig | |||
diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/cirrus/Makefile index 5514146cbdf0..5514146cbdf0 100644 --- a/sound/soc/ep93xx/Makefile +++ b/sound/soc/cirrus/Makefile | |||
diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/cirrus/edb93xx.c index e01cb02abd3a..e01cb02abd3a 100644 --- a/sound/soc/ep93xx/edb93xx.c +++ b/sound/soc/cirrus/edb93xx.c | |||
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index bdffab33e160..bdffab33e160 100644 --- a/sound/soc/ep93xx/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 8df8f6dc474f..8df8f6dc474f 100644 --- a/sound/soc/ep93xx/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c | |||
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c index 4eea98b42bc8..4eea98b42bc8 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/cirrus/ep93xx-pcm.c | |||
diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/cirrus/ep93xx-pcm.h index 111e1121ecb8..111e1121ecb8 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.h +++ b/sound/soc/cirrus/ep93xx-pcm.h | |||
diff --git a/sound/soc/ep93xx/simone.c b/sound/soc/cirrus/simone.c index dd997094eb30..dd997094eb30 100644 --- a/sound/soc/ep93xx/simone.c +++ b/sound/soc/cirrus/simone.c | |||
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/cirrus/snappercl15.c index a193cea3cf3c..a193cea3cf3c 100644 --- a/sound/soc/ep93xx/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c | |||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9f8e8594aeb9..3684255e5fba 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -70,6 +70,7 @@ config SND_SOC_ALL_CODECS | |||
70 | select SND_SOC_UDA134X | 70 | select SND_SOC_UDA134X |
71 | select SND_SOC_UDA1380 if I2C | 71 | select SND_SOC_UDA1380 if I2C |
72 | select SND_SOC_WL1273 if MFD_WL1273_CORE | 72 | select SND_SOC_WL1273 if MFD_WL1273_CORE |
73 | select SND_SOC_WM0010 if SPI_MASTER | ||
73 | select SND_SOC_WM1250_EV1 if I2C | 74 | select SND_SOC_WM1250_EV1 if I2C |
74 | select SND_SOC_WM2000 if I2C | 75 | select SND_SOC_WM2000 if I2C |
75 | select SND_SOC_WM2200 if I2C | 76 | select SND_SOC_WM2200 if I2C |
@@ -326,6 +327,9 @@ config SND_SOC_UDA1380 | |||
326 | config SND_SOC_WL1273 | 327 | config SND_SOC_WL1273 |
327 | tristate | 328 | tristate |
328 | 329 | ||
330 | config SND_SOC_WM0010 | ||
331 | tristate | ||
332 | |||
329 | config SND_SOC_WM1250_EV1 | 333 | config SND_SOC_WM1250_EV1 |
330 | tristate | 334 | tristate |
331 | 335 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 34148bb59c68..ca508b251df7 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -61,6 +61,7 @@ snd-soc-twl6040-objs := twl6040.o | |||
61 | snd-soc-uda134x-objs := uda134x.o | 61 | snd-soc-uda134x-objs := uda134x.o |
62 | snd-soc-uda1380-objs := uda1380.o | 62 | snd-soc-uda1380-objs := uda1380.o |
63 | snd-soc-wl1273-objs := wl1273.o | 63 | snd-soc-wl1273-objs := wl1273.o |
64 | snd-soc-wm0010-objs := wm0010.o | ||
64 | snd-soc-wm1250-ev1-objs := wm1250-ev1.o | 65 | snd-soc-wm1250-ev1-objs := wm1250-ev1.o |
65 | snd-soc-wm2000-objs := wm2000.o | 66 | snd-soc-wm2000-objs := wm2000.o |
66 | snd-soc-wm2200-objs := wm2200.o | 67 | snd-soc-wm2200-objs := wm2200.o |
@@ -177,6 +178,7 @@ obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o | |||
177 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o | 178 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o |
178 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o | 179 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o |
179 | obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o | 180 | obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o |
181 | obj-$(CONFIG_SND_SOC_WM0010) += snd-soc-wm0010.o | ||
180 | obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o | 182 | obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o |
181 | obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o | 183 | obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o |
182 | obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o | 184 | obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o |
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 07abd09e0b1d..af547490b4f7 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c | |||
@@ -391,10 +391,10 @@ static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = { | |||
391 | SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"), | 391 | SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"), |
392 | 392 | ||
393 | /* Regulators */ | 393 | /* Regulators */ |
394 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0), | 394 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0, 0), |
395 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0), | 395 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0, 0), |
396 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0), | 396 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0, 0), |
397 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0), | 397 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0, 0), |
398 | 398 | ||
399 | /* Power */ | 399 | /* Power */ |
400 | SND_SOC_DAPM_SUPPLY("Audio Power", | 400 | SND_SOC_DAPM_SUPPLY("Audio Power", |
@@ -2462,10 +2462,7 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) | |||
2462 | dev_dbg(dev, "%s: Enter.\n", __func__); | 2462 | dev_dbg(dev, "%s: Enter.\n", __func__); |
2463 | 2463 | ||
2464 | /* Setup AB8500 according to board-settings */ | 2464 | /* Setup AB8500 according to board-settings */ |
2465 | pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent); | 2465 | pdata = dev_get_platdata(dev->parent); |
2466 | |||
2467 | /* Inform SoC Core that we have our own I/O arrangements. */ | ||
2468 | codec->control_data = (void *)true; | ||
2469 | 2466 | ||
2470 | if (np) { | 2467 | if (np) { |
2471 | if (!pdata) | 2468 | if (!pdata) |
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index c67b50d8b317..dce6ebeef452 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
20 | #include <sound/tlv.h> | 20 | #include <sound/tlv.h> |
21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/regmap.h> | ||
23 | |||
22 | #include "ad1836.h" | 24 | #include "ad1836.h" |
23 | 25 | ||
24 | enum ad1836_type { | 26 | enum ad1836_type { |
@@ -30,6 +32,7 @@ enum ad1836_type { | |||
30 | /* codec private data */ | 32 | /* codec private data */ |
31 | struct ad1836_priv { | 33 | struct ad1836_priv { |
32 | enum ad1836_type type; | 34 | enum ad1836_type type; |
35 | struct regmap *regmap; | ||
33 | }; | 36 | }; |
34 | 37 | ||
35 | /* | 38 | /* |
@@ -161,8 +164,8 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
161 | struct snd_pcm_hw_params *params, | 164 | struct snd_pcm_hw_params *params, |
162 | struct snd_soc_dai *dai) | 165 | struct snd_soc_dai *dai) |
163 | { | 166 | { |
167 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(dai->codec); | ||
164 | int word_len = 0; | 168 | int word_len = 0; |
165 | struct snd_soc_codec *codec = dai->codec; | ||
166 | 169 | ||
167 | /* bit size */ | 170 | /* bit size */ |
168 | switch (params_format(params)) { | 171 | switch (params_format(params)) { |
@@ -178,10 +181,12 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
178 | break; | 181 | break; |
179 | } | 182 | } |
180 | 183 | ||
181 | snd_soc_update_bits(codec, AD1836_DAC_CTRL1, AD1836_DAC_WORD_LEN_MASK, | 184 | regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1, |
185 | AD1836_DAC_WORD_LEN_MASK, | ||
182 | word_len << AD1836_DAC_WORD_LEN_OFFSET); | 186 | word_len << AD1836_DAC_WORD_LEN_OFFSET); |
183 | 187 | ||
184 | snd_soc_update_bits(codec, AD1836_ADC_CTRL2, AD1836_ADC_WORD_LEN_MASK, | 188 | regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, |
189 | AD1836_ADC_WORD_LEN_MASK, | ||
185 | word_len << AD1836_ADC_WORD_OFFSET); | 190 | word_len << AD1836_ADC_WORD_OFFSET); |
186 | 191 | ||
187 | return 0; | 192 | return 0; |
@@ -223,15 +228,17 @@ static struct snd_soc_dai_driver ad183x_dais[] = { | |||
223 | #ifdef CONFIG_PM | 228 | #ifdef CONFIG_PM |
224 | static int ad1836_suspend(struct snd_soc_codec *codec) | 229 | static int ad1836_suspend(struct snd_soc_codec *codec) |
225 | { | 230 | { |
231 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); | ||
226 | /* reset clock control mode */ | 232 | /* reset clock control mode */ |
227 | return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, | 233 | return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, |
228 | AD1836_ADC_SERFMT_MASK, 0); | 234 | AD1836_ADC_SERFMT_MASK, 0); |
229 | } | 235 | } |
230 | 236 | ||
231 | static int ad1836_resume(struct snd_soc_codec *codec) | 237 | static int ad1836_resume(struct snd_soc_codec *codec) |
232 | { | 238 | { |
239 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); | ||
233 | /* restore clock control mode */ | 240 | /* restore clock control mode */ |
234 | return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, | 241 | return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, |
235 | AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX); | 242 | AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX); |
236 | } | 243 | } |
237 | #else | 244 | #else |
@@ -250,37 +257,30 @@ static int ad1836_probe(struct snd_soc_codec *codec) | |||
250 | num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2; | 257 | num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2; |
251 | num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2; | 258 | num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2; |
252 | 259 | ||
253 | ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); | ||
254 | if (ret < 0) { | ||
255 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | ||
256 | ret); | ||
257 | return ret; | ||
258 | } | ||
259 | |||
260 | /* default setting for ad1836 */ | 260 | /* default setting for ad1836 */ |
261 | /* de-emphasis: 48kHz, power-on dac */ | 261 | /* de-emphasis: 48kHz, power-on dac */ |
262 | snd_soc_write(codec, AD1836_DAC_CTRL1, 0x300); | 262 | regmap_write(ad1836->regmap, AD1836_DAC_CTRL1, 0x300); |
263 | /* unmute dac channels */ | 263 | /* unmute dac channels */ |
264 | snd_soc_write(codec, AD1836_DAC_CTRL2, 0x0); | 264 | regmap_write(ad1836->regmap, AD1836_DAC_CTRL2, 0x0); |
265 | /* high-pass filter enable, power-on adc */ | 265 | /* high-pass filter enable, power-on adc */ |
266 | snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); | 266 | regmap_write(ad1836->regmap, AD1836_ADC_CTRL1, 0x100); |
267 | /* unmute adc channles, adc aux mode */ | 267 | /* unmute adc channles, adc aux mode */ |
268 | snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); | 268 | regmap_write(ad1836->regmap, AD1836_ADC_CTRL2, 0x180); |
269 | /* volume */ | 269 | /* volume */ |
270 | for (i = 1; i <= num_dacs; ++i) { | 270 | for (i = 1; i <= num_dacs; ++i) { |
271 | snd_soc_write(codec, AD1836_DAC_L_VOL(i), 0x3FF); | 271 | regmap_write(ad1836->regmap, AD1836_DAC_L_VOL(i), 0x3FF); |
272 | snd_soc_write(codec, AD1836_DAC_R_VOL(i), 0x3FF); | 272 | regmap_write(ad1836->regmap, AD1836_DAC_R_VOL(i), 0x3FF); |
273 | } | 273 | } |
274 | 274 | ||
275 | if (ad1836->type == AD1836) { | 275 | if (ad1836->type == AD1836) { |
276 | /* left/right diff:PGA/MUX */ | 276 | /* left/right diff:PGA/MUX */ |
277 | snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); | 277 | regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x3A); |
278 | ret = snd_soc_add_codec_controls(codec, ad1836_controls, | 278 | ret = snd_soc_add_codec_controls(codec, ad1836_controls, |
279 | ARRAY_SIZE(ad1836_controls)); | 279 | ARRAY_SIZE(ad1836_controls)); |
280 | if (ret) | 280 | if (ret) |
281 | return ret; | 281 | return ret; |
282 | } else { | 282 | } else { |
283 | snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00); | 283 | regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x00); |
284 | } | 284 | } |
285 | 285 | ||
286 | ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2); | 286 | ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2); |
@@ -313,8 +313,9 @@ static int ad1836_probe(struct snd_soc_codec *codec) | |||
313 | /* power down chip */ | 313 | /* power down chip */ |
314 | static int ad1836_remove(struct snd_soc_codec *codec) | 314 | static int ad1836_remove(struct snd_soc_codec *codec) |
315 | { | 315 | { |
316 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); | ||
316 | /* reset clock control mode */ | 317 | /* reset clock control mode */ |
317 | return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, | 318 | return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, |
318 | AD1836_ADC_SERFMT_MASK, 0); | 319 | AD1836_ADC_SERFMT_MASK, 0); |
319 | } | 320 | } |
320 | 321 | ||
@@ -323,8 +324,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { | |||
323 | .remove = ad1836_remove, | 324 | .remove = ad1836_remove, |
324 | .suspend = ad1836_suspend, | 325 | .suspend = ad1836_suspend, |
325 | .resume = ad1836_resume, | 326 | .resume = ad1836_resume, |
326 | .reg_cache_size = AD1836_NUM_REGS, | ||
327 | .reg_word_size = sizeof(u16), | ||
328 | 327 | ||
329 | .controls = ad183x_controls, | 328 | .controls = ad183x_controls, |
330 | .num_controls = ARRAY_SIZE(ad183x_controls), | 329 | .num_controls = ARRAY_SIZE(ad183x_controls), |
@@ -334,6 +333,33 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { | |||
334 | .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), | 333 | .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), |
335 | }; | 334 | }; |
336 | 335 | ||
336 | static const struct reg_default ad1836_reg_defaults[] = { | ||
337 | { AD1836_DAC_CTRL1, 0x0000 }, | ||
338 | { AD1836_DAC_CTRL2, 0x0000 }, | ||
339 | { AD1836_DAC_L_VOL(0), 0x0000 }, | ||
340 | { AD1836_DAC_R_VOL(0), 0x0000 }, | ||
341 | { AD1836_DAC_L_VOL(1), 0x0000 }, | ||
342 | { AD1836_DAC_R_VOL(1), 0x0000 }, | ||
343 | { AD1836_DAC_L_VOL(2), 0x0000 }, | ||
344 | { AD1836_DAC_R_VOL(2), 0x0000 }, | ||
345 | { AD1836_DAC_L_VOL(3), 0x0000 }, | ||
346 | { AD1836_DAC_R_VOL(3), 0x0000 }, | ||
347 | { AD1836_ADC_CTRL1, 0x0000 }, | ||
348 | { AD1836_ADC_CTRL2, 0x0000 }, | ||
349 | { AD1836_ADC_CTRL3, 0x0000 }, | ||
350 | }; | ||
351 | |||
352 | static const struct regmap_config ad1836_regmap_config = { | ||
353 | .val_bits = 12, | ||
354 | .reg_bits = 4, | ||
355 | .read_flag_mask = 0x08, | ||
356 | |||
357 | .max_register = AD1836_ADC_CTRL3, | ||
358 | .reg_defaults = ad1836_reg_defaults, | ||
359 | .num_reg_defaults = ARRAY_SIZE(ad1836_reg_defaults), | ||
360 | .cache_type = REGCACHE_RBTREE, | ||
361 | }; | ||
362 | |||
337 | static int __devinit ad1836_spi_probe(struct spi_device *spi) | 363 | static int __devinit ad1836_spi_probe(struct spi_device *spi) |
338 | { | 364 | { |
339 | struct ad1836_priv *ad1836; | 365 | struct ad1836_priv *ad1836; |
@@ -344,6 +370,10 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi) | |||
344 | if (ad1836 == NULL) | 370 | if (ad1836 == NULL) |
345 | return -ENOMEM; | 371 | return -ENOMEM; |
346 | 372 | ||
373 | ad1836->regmap = devm_regmap_init_spi(spi, &ad1836_regmap_config); | ||
374 | if (IS_ERR(ad1836->regmap)) | ||
375 | return PTR_ERR(ad1836->regmap); | ||
376 | |||
347 | ad1836->type = spi_get_device_id(spi)->driver_data; | 377 | ad1836->type = spi_get_device_id(spi)->driver_data; |
348 | 378 | ||
349 | spi_set_drvdata(spi, ad1836); | 379 | spi_set_drvdata(spi, ad1836); |
@@ -379,17 +409,7 @@ static struct spi_driver ad1836_spi_driver = { | |||
379 | .id_table = ad1836_ids, | 409 | .id_table = ad1836_ids, |
380 | }; | 410 | }; |
381 | 411 | ||
382 | static int __init ad1836_init(void) | 412 | module_spi_driver(ad1836_spi_driver); |
383 | { | ||
384 | return spi_register_driver(&ad1836_spi_driver); | ||
385 | } | ||
386 | module_init(ad1836_init); | ||
387 | |||
388 | static void __exit ad1836_exit(void) | ||
389 | { | ||
390 | spi_unregister_driver(&ad1836_spi_driver); | ||
391 | } | ||
392 | module_exit(ad1836_exit); | ||
393 | 413 | ||
394 | MODULE_DESCRIPTION("ASoC ad1836 driver"); | 414 | MODULE_DESCRIPTION("ASoC ad1836 driver"); |
395 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 415 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 13e62be4f990..2f752660f678 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -381,40 +381,25 @@ static const struct regmap_config ad193x_spi_regmap_config = { | |||
381 | static int __devinit ad193x_spi_probe(struct spi_device *spi) | 381 | static int __devinit ad193x_spi_probe(struct spi_device *spi) |
382 | { | 382 | { |
383 | struct ad193x_priv *ad193x; | 383 | struct ad193x_priv *ad193x; |
384 | int ret; | ||
385 | 384 | ||
386 | ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), | 385 | ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), |
387 | GFP_KERNEL); | 386 | GFP_KERNEL); |
388 | if (ad193x == NULL) | 387 | if (ad193x == NULL) |
389 | return -ENOMEM; | 388 | return -ENOMEM; |
390 | 389 | ||
391 | ad193x->regmap = regmap_init_spi(spi, &ad193x_spi_regmap_config); | 390 | ad193x->regmap = devm_regmap_init_spi(spi, &ad193x_spi_regmap_config); |
392 | if (IS_ERR(ad193x->regmap)) { | 391 | if (IS_ERR(ad193x->regmap)) |
393 | ret = PTR_ERR(ad193x->regmap); | 392 | return PTR_ERR(ad193x->regmap); |
394 | goto err_out; | ||
395 | } | ||
396 | 393 | ||
397 | spi_set_drvdata(spi, ad193x); | 394 | spi_set_drvdata(spi, ad193x); |
398 | 395 | ||
399 | ret = snd_soc_register_codec(&spi->dev, | 396 | return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x, |
400 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | 397 | &ad193x_dai, 1); |
401 | if (ret < 0) | ||
402 | goto err_regmap_exit; | ||
403 | |||
404 | return 0; | ||
405 | |||
406 | err_regmap_exit: | ||
407 | regmap_exit(ad193x->regmap); | ||
408 | err_out: | ||
409 | return ret; | ||
410 | } | 398 | } |
411 | 399 | ||
412 | static int __devexit ad193x_spi_remove(struct spi_device *spi) | 400 | static int __devexit ad193x_spi_remove(struct spi_device *spi) |
413 | { | 401 | { |
414 | struct ad193x_priv *ad193x = spi_get_drvdata(spi); | ||
415 | |||
416 | snd_soc_unregister_codec(&spi->dev); | 402 | snd_soc_unregister_codec(&spi->dev); |
417 | regmap_exit(ad193x->regmap); | ||
418 | return 0; | 403 | return 0; |
419 | } | 404 | } |
420 | 405 | ||
@@ -449,40 +434,25 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client, | |||
449 | const struct i2c_device_id *id) | 434 | const struct i2c_device_id *id) |
450 | { | 435 | { |
451 | struct ad193x_priv *ad193x; | 436 | struct ad193x_priv *ad193x; |
452 | int ret; | ||
453 | 437 | ||
454 | ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), | 438 | ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), |
455 | GFP_KERNEL); | 439 | GFP_KERNEL); |
456 | if (ad193x == NULL) | 440 | if (ad193x == NULL) |
457 | return -ENOMEM; | 441 | return -ENOMEM; |
458 | 442 | ||
459 | ad193x->regmap = regmap_init_i2c(client, &ad193x_i2c_regmap_config); | 443 | ad193x->regmap = devm_regmap_init_i2c(client, &ad193x_i2c_regmap_config); |
460 | if (IS_ERR(ad193x->regmap)) { | 444 | if (IS_ERR(ad193x->regmap)) |
461 | ret = PTR_ERR(ad193x->regmap); | 445 | return PTR_ERR(ad193x->regmap); |
462 | goto err_out; | ||
463 | } | ||
464 | 446 | ||
465 | i2c_set_clientdata(client, ad193x); | 447 | i2c_set_clientdata(client, ad193x); |
466 | 448 | ||
467 | ret = snd_soc_register_codec(&client->dev, | 449 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x, |
468 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | 450 | &ad193x_dai, 1); |
469 | if (ret < 0) | ||
470 | goto err_regmap_exit; | ||
471 | |||
472 | return 0; | ||
473 | |||
474 | err_regmap_exit: | ||
475 | regmap_exit(ad193x->regmap); | ||
476 | err_out: | ||
477 | return ret; | ||
478 | } | 451 | } |
479 | 452 | ||
480 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) | 453 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) |
481 | { | 454 | { |
482 | struct ad193x_priv *ad193x = i2c_get_clientdata(client); | ||
483 | |||
484 | snd_soc_unregister_codec(&client->dev); | 455 | snd_soc_unregister_codec(&client->dev); |
485 | regmap_exit(ad193x->regmap); | ||
486 | return 0; | 456 | return 0; |
487 | } | 457 | } |
488 | 458 | ||
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 11b1b714b8b5..8c39dddd7d00 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -186,7 +186,6 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) | |||
186 | 186 | ||
187 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); | 187 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); |
188 | 188 | ||
189 | codec->control_data = codec; /* we don't use regmap! */ | ||
190 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 189 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
191 | if (ret < 0) { | 190 | if (ret < 0) { |
192 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); | 191 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); |
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 44f59064d8de..704544bfc90d 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
@@ -1392,17 +1392,7 @@ static struct i2c_driver adau1373_i2c_driver = { | |||
1392 | .id_table = adau1373_i2c_id, | 1392 | .id_table = adau1373_i2c_id, |
1393 | }; | 1393 | }; |
1394 | 1394 | ||
1395 | static int __init adau1373_init(void) | 1395 | module_i2c_driver(adau1373_i2c_driver); |
1396 | { | ||
1397 | return i2c_add_driver(&adau1373_i2c_driver); | ||
1398 | } | ||
1399 | module_init(adau1373_init); | ||
1400 | |||
1401 | static void __exit adau1373_exit(void) | ||
1402 | { | ||
1403 | i2c_del_driver(&adau1373_i2c_driver); | ||
1404 | } | ||
1405 | module_exit(adau1373_exit); | ||
1406 | 1396 | ||
1407 | MODULE_DESCRIPTION("ASoC ADAU1373 driver"); | 1397 | MODULE_DESCRIPTION("ASoC ADAU1373 driver"); |
1408 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 1398 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index 3d50fc8646b6..51f2f3cd8136 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
@@ -527,17 +527,7 @@ static struct i2c_driver adau1701_i2c_driver = { | |||
527 | .id_table = adau1701_i2c_id, | 527 | .id_table = adau1701_i2c_id, |
528 | }; | 528 | }; |
529 | 529 | ||
530 | static int __init adau1701_init(void) | 530 | module_i2c_driver(adau1701_i2c_driver); |
531 | { | ||
532 | return i2c_add_driver(&adau1701_i2c_driver); | ||
533 | } | ||
534 | module_init(adau1701_init); | ||
535 | |||
536 | static void __exit adau1701_exit(void) | ||
537 | { | ||
538 | i2c_del_driver(&adau1701_i2c_driver); | ||
539 | } | ||
540 | module_exit(adau1701_exit); | ||
541 | 531 | ||
542 | MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver"); | 532 | MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver"); |
543 | MODULE_AUTHOR("Cliff Cai <cliff.cai@analog.com>"); | 533 | MODULE_AUTHOR("Cliff Cai <cliff.cai@analog.com>"); |
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 5fb7c2a80e6d..2b457976a7bf 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c | |||
@@ -696,17 +696,7 @@ static struct i2c_driver ak4671_i2c_driver = { | |||
696 | .id_table = ak4671_i2c_id, | 696 | .id_table = ak4671_i2c_id, |
697 | }; | 697 | }; |
698 | 698 | ||
699 | static int __init ak4671_modinit(void) | 699 | module_i2c_driver(ak4671_i2c_driver); |
700 | { | ||
701 | return i2c_add_driver(&ak4671_i2c_driver); | ||
702 | } | ||
703 | module_init(ak4671_modinit); | ||
704 | |||
705 | static void __exit ak4671_exit(void) | ||
706 | { | ||
707 | i2c_del_driver(&ak4671_i2c_driver); | ||
708 | } | ||
709 | module_exit(ak4671_exit); | ||
710 | 700 | ||
711 | MODULE_DESCRIPTION("ASoC AK4671 codec driver"); | 701 | MODULE_DESCRIPTION("ASoC AK4671 codec driver"); |
712 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 702 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 1cf7a32d1b21..c167c896eaee 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -229,6 +229,69 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, | |||
229 | } | 229 | } |
230 | EXPORT_SYMBOL_GPL(arizona_out_ev); | 230 | EXPORT_SYMBOL_GPL(arizona_out_ev); |
231 | 231 | ||
232 | static unsigned int arizona_sysclk_48k_rates[] = { | ||
233 | 6144000, | ||
234 | 12288000, | ||
235 | 22579200, | ||
236 | 49152000, | ||
237 | }; | ||
238 | |||
239 | static unsigned int arizona_sysclk_44k1_rates[] = { | ||
240 | 5644800, | ||
241 | 11289600, | ||
242 | 24576000, | ||
243 | 45158400, | ||
244 | }; | ||
245 | |||
246 | static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk, | ||
247 | unsigned int freq) | ||
248 | { | ||
249 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
250 | unsigned int reg; | ||
251 | unsigned int *rates; | ||
252 | int ref, div, refclk; | ||
253 | |||
254 | switch (clk) { | ||
255 | case ARIZONA_CLK_OPCLK: | ||
256 | reg = ARIZONA_OUTPUT_SYSTEM_CLOCK; | ||
257 | refclk = priv->sysclk; | ||
258 | break; | ||
259 | case ARIZONA_CLK_ASYNC_OPCLK: | ||
260 | reg = ARIZONA_OUTPUT_ASYNC_CLOCK; | ||
261 | refclk = priv->asyncclk; | ||
262 | break; | ||
263 | default: | ||
264 | return -EINVAL; | ||
265 | } | ||
266 | |||
267 | if (refclk % 8000) | ||
268 | rates = arizona_sysclk_44k1_rates; | ||
269 | else | ||
270 | rates = arizona_sysclk_48k_rates; | ||
271 | |||
272 | for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) && | ||
273 | rates[ref] <= refclk; ref++) { | ||
274 | div = 1; | ||
275 | while (rates[ref] / div >= freq && div < 32) { | ||
276 | if (rates[ref] / div == freq) { | ||
277 | dev_dbg(codec->dev, "Configured %dHz OPCLK\n", | ||
278 | freq); | ||
279 | snd_soc_update_bits(codec, reg, | ||
280 | ARIZONA_OPCLK_DIV_MASK | | ||
281 | ARIZONA_OPCLK_SEL_MASK, | ||
282 | (div << | ||
283 | ARIZONA_OPCLK_DIV_SHIFT) | | ||
284 | ref); | ||
285 | return 0; | ||
286 | } | ||
287 | div++; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq); | ||
292 | return -EINVAL; | ||
293 | } | ||
294 | |||
232 | int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | 295 | int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, |
233 | int source, unsigned int freq, int dir) | 296 | int source, unsigned int freq, int dir) |
234 | { | 297 | { |
@@ -252,6 +315,9 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
252 | reg = ARIZONA_ASYNC_CLOCK_1; | 315 | reg = ARIZONA_ASYNC_CLOCK_1; |
253 | clk = &priv->asyncclk; | 316 | clk = &priv->asyncclk; |
254 | break; | 317 | break; |
318 | case ARIZONA_CLK_OPCLK: | ||
319 | case ARIZONA_CLK_ASYNC_OPCLK: | ||
320 | return arizona_set_opclk(codec, clk_id, freq); | ||
255 | default: | 321 | default: |
256 | return -EINVAL; | 322 | return -EINVAL; |
257 | } | 323 | } |
@@ -666,7 +732,7 @@ static irqreturn_t arizona_fll_lock(int irq, void *data) | |||
666 | { | 732 | { |
667 | struct arizona_fll *fll = data; | 733 | struct arizona_fll *fll = data; |
668 | 734 | ||
669 | arizona_fll_dbg(fll, "Locked\n"); | 735 | arizona_fll_dbg(fll, "Lock status changed\n"); |
670 | 736 | ||
671 | complete(&fll->lock); | 737 | complete(&fll->lock); |
672 | 738 | ||
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 59caca8865e8..eb66b52777c9 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
@@ -17,8 +17,10 @@ | |||
17 | 17 | ||
18 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
19 | 19 | ||
20 | #define ARIZONA_CLK_SYSCLK 1 | 20 | #define ARIZONA_CLK_SYSCLK 1 |
21 | #define ARIZONA_CLK_ASYNCCLK 2 | 21 | #define ARIZONA_CLK_ASYNCCLK 2 |
22 | #define ARIZONA_CLK_OPCLK 3 | ||
23 | #define ARIZONA_CLK_ASYNC_OPCLK 4 | ||
22 | 24 | ||
23 | #define ARIZONA_CLK_SRC_MCLK1 0x0 | 25 | #define ARIZONA_CLK_SRC_MCLK1 0x0 |
24 | #define ARIZONA_CLK_SRC_MCLK2 0x1 | 26 | #define ARIZONA_CLK_SRC_MCLK2 0x1 |
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 047917f0b8ae..815b53bc2d27 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include <linux/regulator/consumer.h> | 31 | #include <linux/regulator/consumer.h> |
32 | #include <linux/of_device.h> | ||
33 | #include <linux/of_gpio.h> | ||
32 | 34 | ||
33 | /* | 35 | /* |
34 | * The codec isn't really big-endian or little-endian, since the I2S | 36 | * The codec isn't really big-endian or little-endian, since the I2S |
@@ -110,14 +112,15 @@ | |||
110 | * This array contains the power-on default values of the registers, with the | 112 | * This array contains the power-on default values of the registers, with the |
111 | * exception of the "CHIPID" register (01h). The lower four bits of that | 113 | * exception of the "CHIPID" register (01h). The lower four bits of that |
112 | * register contain the hardware revision, so it is treated as volatile. | 114 | * register contain the hardware revision, so it is treated as volatile. |
113 | * | ||
114 | * Also note that on the CS4270, the first readable register is 1, but ASoC | ||
115 | * assumes the first register is 0. Therfore, the array must have an entry for | ||
116 | * register 0, but we use cs4270_reg_is_readable() to tell ASoC that it can't | ||
117 | * be read. | ||
118 | */ | 115 | */ |
119 | static const u8 cs4270_default_reg_cache[CS4270_LASTREG + 1] = { | 116 | static const struct reg_default cs4270_reg_defaults[] = { |
120 | 0x00, 0x00, 0x00, 0x30, 0x00, 0x60, 0x20, 0x00, 0x00 | 117 | { 2, 0x00 }, |
118 | { 3, 0x30 }, | ||
119 | { 4, 0x00 }, | ||
120 | { 5, 0x60 }, | ||
121 | { 6, 0x20 }, | ||
122 | { 7, 0x00 }, | ||
123 | { 8, 0x00 }, | ||
121 | }; | 124 | }; |
122 | 125 | ||
123 | static const char *supply_names[] = { | 126 | static const char *supply_names[] = { |
@@ -126,7 +129,7 @@ static const char *supply_names[] = { | |||
126 | 129 | ||
127 | /* Private data for the CS4270 */ | 130 | /* Private data for the CS4270 */ |
128 | struct cs4270_private { | 131 | struct cs4270_private { |
129 | enum snd_soc_control_type control_type; | 132 | struct regmap *regmap; |
130 | unsigned int mclk; /* Input frequency of the MCLK pin */ | 133 | unsigned int mclk; /* Input frequency of the MCLK pin */ |
131 | unsigned int mode; /* The mode (I2S or left-justified) */ | 134 | unsigned int mode; /* The mode (I2S or left-justified) */ |
132 | unsigned int slave_mode; | 135 | unsigned int slave_mode; |
@@ -191,12 +194,12 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = { | |||
191 | /* The number of MCLK/LRCK ratios supported by the CS4270 */ | 194 | /* The number of MCLK/LRCK ratios supported by the CS4270 */ |
192 | #define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) | 195 | #define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) |
193 | 196 | ||
194 | static int cs4270_reg_is_readable(struct snd_soc_codec *codec, unsigned int reg) | 197 | static bool cs4270_reg_is_readable(struct device *dev, unsigned int reg) |
195 | { | 198 | { |
196 | return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG); | 199 | return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG); |
197 | } | 200 | } |
198 | 201 | ||
199 | static int cs4270_reg_is_volatile(struct snd_soc_codec *codec, unsigned int reg) | 202 | static bool cs4270_reg_is_volatile(struct device *dev, unsigned int reg) |
200 | { | 203 | { |
201 | /* Unreadable registers are considered volatile */ | 204 | /* Unreadable registers are considered volatile */ |
202 | if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) | 205 | if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) |
@@ -485,12 +488,12 @@ static struct snd_soc_dai_driver cs4270_dai = { | |||
485 | static int cs4270_probe(struct snd_soc_codec *codec) | 488 | static int cs4270_probe(struct snd_soc_codec *codec) |
486 | { | 489 | { |
487 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 490 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
488 | int i, ret; | 491 | int ret; |
489 | 492 | ||
490 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will | 493 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will |
491 | * then do the I2C transactions itself. | 494 | * then do the I2C transactions itself. |
492 | */ | 495 | */ |
493 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs4270->control_type); | 496 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); |
494 | if (ret < 0) { | 497 | if (ret < 0) { |
495 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); | 498 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); |
496 | return ret; | 499 | return ret; |
@@ -519,33 +522,8 @@ static int cs4270_probe(struct snd_soc_codec *codec) | |||
519 | return ret; | 522 | return ret; |
520 | } | 523 | } |
521 | 524 | ||
522 | /* Add the non-DAPM controls */ | ||
523 | ret = snd_soc_add_codec_controls(codec, cs4270_snd_controls, | ||
524 | ARRAY_SIZE(cs4270_snd_controls)); | ||
525 | if (ret < 0) { | ||
526 | dev_err(codec->dev, "failed to add controls\n"); | ||
527 | return ret; | ||
528 | } | ||
529 | |||
530 | /* get the power supply regulators */ | ||
531 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
532 | cs4270->supplies[i].supply = supply_names[i]; | ||
533 | |||
534 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), | ||
535 | cs4270->supplies); | ||
536 | if (ret < 0) | ||
537 | return ret; | ||
538 | |||
539 | ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), | 525 | ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), |
540 | cs4270->supplies); | 526 | cs4270->supplies); |
541 | if (ret < 0) | ||
542 | goto error_free_regulators; | ||
543 | |||
544 | return 0; | ||
545 | |||
546 | error_free_regulators: | ||
547 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), | ||
548 | cs4270->supplies); | ||
549 | 527 | ||
550 | return ret; | 528 | return ret; |
551 | } | 529 | } |
@@ -561,7 +539,6 @@ static int cs4270_remove(struct snd_soc_codec *codec) | |||
561 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 539 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
562 | 540 | ||
563 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | 541 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); |
564 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | ||
565 | 542 | ||
566 | return 0; | 543 | return 0; |
567 | }; | 544 | }; |
@@ -611,7 +588,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec) | |||
611 | ndelay(500); | 588 | ndelay(500); |
612 | 589 | ||
613 | /* first restore the entire register cache ... */ | 590 | /* first restore the entire register cache ... */ |
614 | snd_soc_cache_sync(codec); | 591 | regcache_sync(cs4270->regmap); |
615 | 592 | ||
616 | /* ... then disable the power-down bits */ | 593 | /* ... then disable the power-down bits */ |
617 | reg = snd_soc_read(codec, CS4270_PWRCTL); | 594 | reg = snd_soc_read(codec, CS4270_PWRCTL); |
@@ -632,11 +609,30 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { | |||
632 | .remove = cs4270_remove, | 609 | .remove = cs4270_remove, |
633 | .suspend = cs4270_soc_suspend, | 610 | .suspend = cs4270_soc_suspend, |
634 | .resume = cs4270_soc_resume, | 611 | .resume = cs4270_soc_resume, |
635 | .volatile_register = cs4270_reg_is_volatile, | 612 | |
636 | .readable_register = cs4270_reg_is_readable, | 613 | .controls = cs4270_snd_controls, |
637 | .reg_cache_size = CS4270_LASTREG + 1, | 614 | .num_controls = ARRAY_SIZE(cs4270_snd_controls), |
638 | .reg_word_size = sizeof(u8), | 615 | }; |
639 | .reg_cache_default = cs4270_default_reg_cache, | 616 | |
617 | /* | ||
618 | * cs4270_of_match - the device tree bindings | ||
619 | */ | ||
620 | static const struct of_device_id cs4270_of_match[] = { | ||
621 | { .compatible = "cirrus,cs4270", }, | ||
622 | { } | ||
623 | }; | ||
624 | MODULE_DEVICE_TABLE(of, cs4270_of_match); | ||
625 | |||
626 | static const struct regmap_config cs4270_regmap = { | ||
627 | .reg_bits = 8, | ||
628 | .val_bits = 8, | ||
629 | .max_register = CS4270_LASTREG, | ||
630 | .reg_defaults = cs4270_reg_defaults, | ||
631 | .num_reg_defaults = ARRAY_SIZE(cs4270_reg_defaults), | ||
632 | .cache_type = REGCACHE_RBTREE, | ||
633 | |||
634 | .readable_reg = cs4270_reg_is_readable, | ||
635 | .volatile_reg = cs4270_reg_is_volatile, | ||
640 | }; | 636 | }; |
641 | 637 | ||
642 | /** | 638 | /** |
@@ -650,19 +646,56 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { | |||
650 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, | 646 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, |
651 | const struct i2c_device_id *id) | 647 | const struct i2c_device_id *id) |
652 | { | 648 | { |
649 | struct device_node *np = i2c_client->dev.of_node; | ||
653 | struct cs4270_private *cs4270; | 650 | struct cs4270_private *cs4270; |
654 | int ret; | 651 | unsigned int val; |
652 | int ret, i; | ||
655 | 653 | ||
656 | /* Verify that we have a CS4270 */ | 654 | cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), |
655 | GFP_KERNEL); | ||
656 | if (!cs4270) { | ||
657 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
658 | return -ENOMEM; | ||
659 | } | ||
660 | |||
661 | /* get the power supply regulators */ | ||
662 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
663 | cs4270->supplies[i].supply = supply_names[i]; | ||
664 | |||
665 | ret = devm_regulator_bulk_get(&i2c_client->dev, | ||
666 | ARRAY_SIZE(cs4270->supplies), | ||
667 | cs4270->supplies); | ||
668 | if (ret < 0) | ||
669 | return ret; | ||
670 | |||
671 | /* See if we have a way to bring the codec out of reset */ | ||
672 | if (np) { | ||
673 | enum of_gpio_flags flags; | ||
674 | int gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags); | ||
675 | |||
676 | if (gpio_is_valid(gpio)) { | ||
677 | ret = devm_gpio_request_one(&i2c_client->dev, gpio, | ||
678 | flags & OF_GPIO_ACTIVE_LOW ? | ||
679 | GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, | ||
680 | "cs4270 reset"); | ||
681 | if (ret < 0) | ||
682 | return ret; | ||
683 | } | ||
684 | } | ||
685 | |||
686 | cs4270->regmap = devm_regmap_init_i2c(i2c_client, &cs4270_regmap); | ||
687 | if (IS_ERR(cs4270->regmap)) | ||
688 | return PTR_ERR(cs4270->regmap); | ||
657 | 689 | ||
658 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | 690 | /* Verify that we have a CS4270 */ |
691 | ret = regmap_read(cs4270->regmap, CS4270_CHIPID, &val); | ||
659 | if (ret < 0) { | 692 | if (ret < 0) { |
660 | dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", | 693 | dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", |
661 | i2c_client->addr); | 694 | i2c_client->addr); |
662 | return ret; | 695 | return ret; |
663 | } | 696 | } |
664 | /* The top four bits of the chip ID should be 1100. */ | 697 | /* The top four bits of the chip ID should be 1100. */ |
665 | if ((ret & 0xF0) != 0xC0) { | 698 | if ((val & 0xF0) != 0xC0) { |
666 | dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", | 699 | dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", |
667 | i2c_client->addr); | 700 | i2c_client->addr); |
668 | return -ENODEV; | 701 | return -ENODEV; |
@@ -670,17 +703,9 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, | |||
670 | 703 | ||
671 | dev_info(&i2c_client->dev, "found device at i2c address %X\n", | 704 | dev_info(&i2c_client->dev, "found device at i2c address %X\n", |
672 | i2c_client->addr); | 705 | i2c_client->addr); |
673 | dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); | 706 | dev_info(&i2c_client->dev, "hardware revision %X\n", val & 0xF); |
674 | |||
675 | cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), | ||
676 | GFP_KERNEL); | ||
677 | if (!cs4270) { | ||
678 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
679 | return -ENOMEM; | ||
680 | } | ||
681 | 707 | ||
682 | i2c_set_clientdata(i2c_client, cs4270); | 708 | i2c_set_clientdata(i2c_client, cs4270); |
683 | cs4270->control_type = SND_SOC_I2C; | ||
684 | 709 | ||
685 | ret = snd_soc_register_codec(&i2c_client->dev, | 710 | ret = snd_soc_register_codec(&i2c_client->dev, |
686 | &soc_codec_device_cs4270, &cs4270_dai, 1); | 711 | &soc_codec_device_cs4270, &cs4270_dai, 1); |
@@ -718,23 +743,14 @@ static struct i2c_driver cs4270_i2c_driver = { | |||
718 | .driver = { | 743 | .driver = { |
719 | .name = "cs4270", | 744 | .name = "cs4270", |
720 | .owner = THIS_MODULE, | 745 | .owner = THIS_MODULE, |
746 | .of_match_table = cs4270_of_match, | ||
721 | }, | 747 | }, |
722 | .id_table = cs4270_id, | 748 | .id_table = cs4270_id, |
723 | .probe = cs4270_i2c_probe, | 749 | .probe = cs4270_i2c_probe, |
724 | .remove = cs4270_i2c_remove, | 750 | .remove = cs4270_i2c_remove, |
725 | }; | 751 | }; |
726 | 752 | ||
727 | static int __init cs4270_init(void) | 753 | module_i2c_driver(cs4270_i2c_driver); |
728 | { | ||
729 | return i2c_add_driver(&cs4270_i2c_driver); | ||
730 | } | ||
731 | module_init(cs4270_init); | ||
732 | |||
733 | static void __exit cs4270_exit(void) | ||
734 | { | ||
735 | i2c_del_driver(&cs4270_i2c_driver); | ||
736 | } | ||
737 | module_exit(cs4270_exit); | ||
738 | 754 | ||
739 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 755 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); |
740 | MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); | 756 | MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); |
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 091d0193f507..1e0fa3b5f79a 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c | |||
@@ -614,24 +614,7 @@ static struct i2c_driver cs42l51_i2c_driver = { | |||
614 | .remove = cs42l51_i2c_remove, | 614 | .remove = cs42l51_i2c_remove, |
615 | }; | 615 | }; |
616 | 616 | ||
617 | static int __init cs42l51_init(void) | 617 | module_i2c_driver(cs42l51_i2c_driver); |
618 | { | ||
619 | int ret; | ||
620 | |||
621 | ret = i2c_add_driver(&cs42l51_i2c_driver); | ||
622 | if (ret != 0) { | ||
623 | printk(KERN_ERR "%s: can't add i2c driver\n", __func__); | ||
624 | return ret; | ||
625 | } | ||
626 | return 0; | ||
627 | } | ||
628 | module_init(cs42l51_init); | ||
629 | |||
630 | static void __exit cs42l51_exit(void) | ||
631 | { | ||
632 | i2c_del_driver(&cs42l51_i2c_driver); | ||
633 | } | ||
634 | module_exit(cs42l51_exit); | ||
635 | 618 | ||
636 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); | 619 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); |
637 | MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); | 620 | MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); |
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 628daf6a1d97..61599298fb26 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/slab.h> | ||
28 | #include <sound/core.h> | 27 | #include <sound/core.h> |
29 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
30 | #include <sound/pcm_params.h> | 29 | #include <sound/pcm_params.h> |
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 5d8f39e32978..1bf55602c9eb 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c | |||
@@ -13,7 +13,6 @@ | |||
13 | */ | 13 | */ |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
16 | #include <linux/version.h> | ||
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/init.h> | 17 | #include <linux/init.h> |
19 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index ba4fafb93e56..81a328c78838 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c | |||
@@ -250,17 +250,7 @@ static struct i2c_driver lm4857_i2c_driver = { | |||
250 | .id_table = lm4857_i2c_id, | 250 | .id_table = lm4857_i2c_id, |
251 | }; | 251 | }; |
252 | 252 | ||
253 | static int __init lm4857_init(void) | 253 | module_i2c_driver(lm4857_i2c_driver); |
254 | { | ||
255 | return i2c_add_driver(&lm4857_i2c_driver); | ||
256 | } | ||
257 | module_init(lm4857_init); | ||
258 | |||
259 | static void __exit lm4857_exit(void) | ||
260 | { | ||
261 | i2c_del_driver(&lm4857_i2c_driver); | ||
262 | } | ||
263 | module_exit(lm4857_exit); | ||
264 | 254 | ||
265 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 255 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
266 | MODULE_DESCRIPTION("LM4857 amplifier driver"); | 256 | MODULE_DESCRIPTION("LM4857 amplifier driver"); |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index af7324b79dd0..3264a5169306 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -2107,23 +2107,7 @@ static struct i2c_driver max98088_i2c_driver = { | |||
2107 | .id_table = max98088_i2c_id, | 2107 | .id_table = max98088_i2c_id, |
2108 | }; | 2108 | }; |
2109 | 2109 | ||
2110 | static int __init max98088_init(void) | 2110 | module_i2c_driver(max98088_i2c_driver); |
2111 | { | ||
2112 | int ret; | ||
2113 | |||
2114 | ret = i2c_add_driver(&max98088_i2c_driver); | ||
2115 | if (ret) | ||
2116 | pr_err("Failed to register max98088 I2C driver: %d\n", ret); | ||
2117 | |||
2118 | return ret; | ||
2119 | } | ||
2120 | module_init(max98088_init); | ||
2121 | |||
2122 | static void __exit max98088_exit(void) | ||
2123 | { | ||
2124 | i2c_del_driver(&max98088_i2c_driver); | ||
2125 | } | ||
2126 | module_exit(max98088_exit); | ||
2127 | 2111 | ||
2128 | MODULE_DESCRIPTION("ALSA SoC MAX98088 driver"); | 2112 | MODULE_DESCRIPTION("ALSA SoC MAX98088 driver"); |
2129 | MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin"); | 2113 | MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin"); |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 7cd508e16a5c..38d43c59d3f4 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c | |||
@@ -2533,23 +2533,7 @@ static struct i2c_driver max98095_i2c_driver = { | |||
2533 | .id_table = max98095_i2c_id, | 2533 | .id_table = max98095_i2c_id, |
2534 | }; | 2534 | }; |
2535 | 2535 | ||
2536 | static int __init max98095_init(void) | 2536 | module_i2c_driver(max98095_i2c_driver); |
2537 | { | ||
2538 | int ret; | ||
2539 | |||
2540 | ret = i2c_add_driver(&max98095_i2c_driver); | ||
2541 | if (ret) | ||
2542 | pr_err("Failed to register max98095 I2C driver: %d\n", ret); | ||
2543 | |||
2544 | return ret; | ||
2545 | } | ||
2546 | module_init(max98095_init); | ||
2547 | |||
2548 | static void __exit max98095_exit(void) | ||
2549 | { | ||
2550 | i2c_del_driver(&max98095_i2c_driver); | ||
2551 | } | ||
2552 | module_exit(max98095_exit); | ||
2553 | 2537 | ||
2554 | MODULE_DESCRIPTION("ALSA SoC MAX98095 driver"); | 2538 | MODULE_DESCRIPTION("ALSA SoC MAX98095 driver"); |
2555 | MODULE_AUTHOR("Peter Hsiang"); | 2539 | MODULE_AUTHOR("Peter Hsiang"); |
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index a1913091f56c..efe535c37b39 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c | |||
@@ -369,17 +369,7 @@ static struct i2c_driver max9850_i2c_driver = { | |||
369 | .id_table = max9850_i2c_id, | 369 | .id_table = max9850_i2c_id, |
370 | }; | 370 | }; |
371 | 371 | ||
372 | static int __init max9850_init(void) | 372 | module_i2c_driver(max9850_i2c_driver); |
373 | { | ||
374 | return i2c_add_driver(&max9850_i2c_driver); | ||
375 | } | ||
376 | module_init(max9850_init); | ||
377 | |||
378 | static void __exit max9850_exit(void) | ||
379 | { | ||
380 | i2c_del_driver(&max9850_i2c_driver); | ||
381 | } | ||
382 | module_exit(max9850_exit); | ||
383 | 373 | ||
384 | MODULE_AUTHOR("Christian Glindkamp <christian.glindkamp@taskit.de>"); | 374 | MODULE_AUTHOR("Christian Glindkamp <christian.glindkamp@taskit.de>"); |
385 | MODULE_DESCRIPTION("ASoC MAX9850 codec driver"); | 375 | MODULE_DESCRIPTION("ASoC MAX9850 codec driver"); |
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c index 3a2ba3d8fd6d..d15e5943c85e 100644 --- a/sound/soc/codecs/max9877.c +++ b/sound/soc/codecs/max9877.c | |||
@@ -291,17 +291,7 @@ static struct i2c_driver max9877_i2c_driver = { | |||
291 | .id_table = max9877_i2c_id, | 291 | .id_table = max9877_i2c_id, |
292 | }; | 292 | }; |
293 | 293 | ||
294 | static int __init max9877_init(void) | 294 | module_i2c_driver(max9877_i2c_driver); |
295 | { | ||
296 | return i2c_add_driver(&max9877_i2c_driver); | ||
297 | } | ||
298 | module_init(max9877_init); | ||
299 | |||
300 | static void __exit max9877_exit(void) | ||
301 | { | ||
302 | i2c_del_driver(&max9877_i2c_driver); | ||
303 | } | ||
304 | module_exit(max9877_exit); | ||
305 | 295 | ||
306 | MODULE_DESCRIPTION("ASoC MAX9877 amp driver"); | 296 | MODULE_DESCRIPTION("ASoC MAX9877 amp driver"); |
307 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 297 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 115a40301810..bc955999c8aa 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c | |||
@@ -426,16 +426,16 @@ static int mc13783_set_tdm_slot_sync(struct snd_soc_dai *dai, | |||
426 | } | 426 | } |
427 | 427 | ||
428 | static const struct snd_kcontrol_new mc1l_amp_ctl = | 428 | static const struct snd_kcontrol_new mc1l_amp_ctl = |
429 | SOC_DAPM_SINGLE("Switch", 38, 7, 1, 0); | 429 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 7, 1, 0); |
430 | 430 | ||
431 | static const struct snd_kcontrol_new mc1r_amp_ctl = | 431 | static const struct snd_kcontrol_new mc1r_amp_ctl = |
432 | SOC_DAPM_SINGLE("Switch", 38, 5, 1, 0); | 432 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 5, 1, 0); |
433 | 433 | ||
434 | static const struct snd_kcontrol_new mc2_amp_ctl = | 434 | static const struct snd_kcontrol_new mc2_amp_ctl = |
435 | SOC_DAPM_SINGLE("Switch", 38, 9, 1, 0); | 435 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 9, 1, 0); |
436 | 436 | ||
437 | static const struct snd_kcontrol_new atx_amp_ctl = | 437 | static const struct snd_kcontrol_new atx_amp_ctl = |
438 | SOC_DAPM_SINGLE("Switch", 38, 11, 1, 0); | 438 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 11, 1, 0); |
439 | 439 | ||
440 | 440 | ||
441 | /* Virtual mux. The chip does the input selection automatically | 441 | /* Virtual mux. The chip does the input selection automatically |
@@ -461,22 +461,22 @@ static const struct snd_kcontrol_new right_input_mux = | |||
461 | SOC_DAPM_ENUM_VIRT("Route", adcr_enum); | 461 | SOC_DAPM_ENUM_VIRT("Route", adcr_enum); |
462 | 462 | ||
463 | static const struct snd_kcontrol_new samp_ctl = | 463 | static const struct snd_kcontrol_new samp_ctl = |
464 | SOC_DAPM_SINGLE("Switch", 36, 3, 1, 0); | 464 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 3, 1, 0); |
465 | 465 | ||
466 | static const struct snd_kcontrol_new lamp_ctl = | 466 | static const struct snd_kcontrol_new lamp_ctl = |
467 | SOC_DAPM_SINGLE("Switch", 36, 5, 1, 0); | 467 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 5, 1, 0); |
468 | 468 | ||
469 | static const struct snd_kcontrol_new hlamp_ctl = | 469 | static const struct snd_kcontrol_new hlamp_ctl = |
470 | SOC_DAPM_SINGLE("Switch", 36, 10, 1, 0); | 470 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 10, 1, 0); |
471 | 471 | ||
472 | static const struct snd_kcontrol_new hramp_ctl = | 472 | static const struct snd_kcontrol_new hramp_ctl = |
473 | SOC_DAPM_SINGLE("Switch", 36, 9, 1, 0); | 473 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 9, 1, 0); |
474 | 474 | ||
475 | static const struct snd_kcontrol_new llamp_ctl = | 475 | static const struct snd_kcontrol_new llamp_ctl = |
476 | SOC_DAPM_SINGLE("Switch", 36, 16, 1, 0); | 476 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 16, 1, 0); |
477 | 477 | ||
478 | static const struct snd_kcontrol_new lramp_ctl = | 478 | static const struct snd_kcontrol_new lramp_ctl = |
479 | SOC_DAPM_SINGLE("Switch", 36, 15, 1, 0); | 479 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 15, 1, 0); |
480 | 480 | ||
481 | static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { | 481 | static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { |
482 | /* Input */ | 482 | /* Input */ |
@@ -487,13 +487,13 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { | |||
487 | SND_SOC_DAPM_INPUT("RXINL"), | 487 | SND_SOC_DAPM_INPUT("RXINL"), |
488 | SND_SOC_DAPM_INPUT("TXIN"), | 488 | SND_SOC_DAPM_INPUT("TXIN"), |
489 | 489 | ||
490 | SND_SOC_DAPM_SUPPLY("MC1 Bias", 38, 0, 0, NULL, 0), | 490 | SND_SOC_DAPM_SUPPLY("MC1 Bias", MC13783_AUDIO_TX, 0, 0, NULL, 0), |
491 | SND_SOC_DAPM_SUPPLY("MC2 Bias", 38, 1, 0, NULL, 0), | 491 | SND_SOC_DAPM_SUPPLY("MC2 Bias", MC13783_AUDIO_TX, 1, 0, NULL, 0), |
492 | 492 | ||
493 | SND_SOC_DAPM_SWITCH("MC1L Amp", 38, 7, 0, &mc1l_amp_ctl), | 493 | SND_SOC_DAPM_SWITCH("MC1L Amp", MC13783_AUDIO_TX, 7, 0, &mc1l_amp_ctl), |
494 | SND_SOC_DAPM_SWITCH("MC1R Amp", 38, 5, 0, &mc1r_amp_ctl), | 494 | SND_SOC_DAPM_SWITCH("MC1R Amp", MC13783_AUDIO_TX, 5, 0, &mc1r_amp_ctl), |
495 | SND_SOC_DAPM_SWITCH("MC2 Amp", 38, 9, 0, &mc2_amp_ctl), | 495 | SND_SOC_DAPM_SWITCH("MC2 Amp", MC13783_AUDIO_TX, 9, 0, &mc2_amp_ctl), |
496 | SND_SOC_DAPM_SWITCH("TXIN Amp", 38, 11, 0, &atx_amp_ctl), | 496 | SND_SOC_DAPM_SWITCH("TXIN Amp", MC13783_AUDIO_TX, 11, 0, &atx_amp_ctl), |
497 | 497 | ||
498 | SND_SOC_DAPM_VIRT_MUX("PGA Left Input Mux", SND_SOC_NOPM, 0, 0, | 498 | SND_SOC_DAPM_VIRT_MUX("PGA Left Input Mux", SND_SOC_NOPM, 0, 0, |
499 | &left_input_mux), | 499 | &left_input_mux), |
@@ -503,12 +503,12 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { | |||
503 | SND_SOC_DAPM_PGA("PGA Left Input", SND_SOC_NOPM, 0, 0, NULL, 0), | 503 | SND_SOC_DAPM_PGA("PGA Left Input", SND_SOC_NOPM, 0, 0, NULL, 0), |
504 | SND_SOC_DAPM_PGA("PGA Right Input", SND_SOC_NOPM, 0, 0, NULL, 0), | 504 | SND_SOC_DAPM_PGA("PGA Right Input", SND_SOC_NOPM, 0, 0, NULL, 0), |
505 | 505 | ||
506 | SND_SOC_DAPM_ADC("ADC", "Capture", 40, 11, 0), | 506 | SND_SOC_DAPM_ADC("ADC", "Capture", MC13783_AUDIO_CODEC, 11, 0), |
507 | SND_SOC_DAPM_SUPPLY("ADC_Reset", 40, 15, 0, NULL, 0), | 507 | SND_SOC_DAPM_SUPPLY("ADC_Reset", MC13783_AUDIO_CODEC, 15, 0, NULL, 0), |
508 | 508 | ||
509 | /* Output */ | 509 | /* Output */ |
510 | SND_SOC_DAPM_SUPPLY("DAC_E", 41, 11, 0, NULL, 0), | 510 | SND_SOC_DAPM_SUPPLY("DAC_E", MC13783_AUDIO_DAC, 11, 0, NULL, 0), |
511 | SND_SOC_DAPM_SUPPLY("DAC_Reset", 41, 15, 0, NULL, 0), | 511 | SND_SOC_DAPM_SUPPLY("DAC_Reset", MC13783_AUDIO_DAC, 15, 0, NULL, 0), |
512 | SND_SOC_DAPM_OUTPUT("RXOUTL"), | 512 | SND_SOC_DAPM_OUTPUT("RXOUTL"), |
513 | SND_SOC_DAPM_OUTPUT("RXOUTR"), | 513 | SND_SOC_DAPM_OUTPUT("RXOUTR"), |
514 | SND_SOC_DAPM_OUTPUT("HSL"), | 514 | SND_SOC_DAPM_OUTPUT("HSL"), |
@@ -516,14 +516,18 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { | |||
516 | SND_SOC_DAPM_OUTPUT("LSP"), | 516 | SND_SOC_DAPM_OUTPUT("LSP"), |
517 | SND_SOC_DAPM_OUTPUT("SP"), | 517 | SND_SOC_DAPM_OUTPUT("SP"), |
518 | 518 | ||
519 | SND_SOC_DAPM_SWITCH("Speaker Amp", 36, 3, 0, &samp_ctl), | 519 | SND_SOC_DAPM_SWITCH("Speaker Amp", MC13783_AUDIO_RX0, 3, 0, &samp_ctl), |
520 | SND_SOC_DAPM_SWITCH("Loudspeaker Amp", SND_SOC_NOPM, 0, 0, &lamp_ctl), | 520 | SND_SOC_DAPM_SWITCH("Loudspeaker Amp", SND_SOC_NOPM, 0, 0, &lamp_ctl), |
521 | SND_SOC_DAPM_SWITCH("Headset Amp Left", 36, 10, 0, &hlamp_ctl), | 521 | SND_SOC_DAPM_SWITCH("Headset Amp Left", MC13783_AUDIO_RX0, 10, 0, |
522 | SND_SOC_DAPM_SWITCH("Headset Amp Right", 36, 9, 0, &hramp_ctl), | 522 | &hlamp_ctl), |
523 | SND_SOC_DAPM_SWITCH("Line out Amp Left", 36, 16, 0, &llamp_ctl), | 523 | SND_SOC_DAPM_SWITCH("Headset Amp Right", MC13783_AUDIO_RX0, 9, 0, |
524 | SND_SOC_DAPM_SWITCH("Line out Amp Right", 36, 15, 0, &lramp_ctl), | 524 | &hramp_ctl), |
525 | SND_SOC_DAPM_DAC("DAC", "Playback", 36, 22, 0), | 525 | SND_SOC_DAPM_SWITCH("Line out Amp Left", MC13783_AUDIO_RX0, 16, 0, |
526 | SND_SOC_DAPM_PGA("DAC PGA", 37, 5, 0, NULL, 0), | 526 | &llamp_ctl), |
527 | SND_SOC_DAPM_SWITCH("Line out Amp Right", MC13783_AUDIO_RX0, 15, 0, | ||
528 | &lramp_ctl), | ||
529 | SND_SOC_DAPM_DAC("DAC", "Playback", MC13783_AUDIO_RX0, 22, 0), | ||
530 | SND_SOC_DAPM_PGA("DAC PGA", MC13783_AUDIO_RX1, 5, 0, NULL, 0), | ||
527 | }; | 531 | }; |
528 | 532 | ||
529 | static struct snd_soc_dapm_route mc13783_routes[] = { | 533 | static struct snd_soc_dapm_route mc13783_routes[] = { |
@@ -581,8 +585,6 @@ static int mc13783_probe(struct snd_soc_codec *codec) | |||
581 | { | 585 | { |
582 | struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); | 586 | struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); |
583 | 587 | ||
584 | codec->control_data = priv->mc13xxx; | ||
585 | |||
586 | mc13xxx_lock(priv->mc13xxx); | 588 | mc13xxx_lock(priv->mc13xxx); |
587 | 589 | ||
588 | /* these are the reset values */ | 590 | /* these are the reset values */ |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 8d717f4b5a87..0935bfe62471 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
27 | #include <linux/regmap.h> | ||
27 | #include <linux/regulator/consumer.h> | 28 | #include <linux/regulator/consumer.h> |
28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
29 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
@@ -55,12 +56,50 @@ | |||
55 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) | 56 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) |
56 | 57 | ||
57 | /* Power-up register defaults */ | 58 | /* Power-up register defaults */ |
58 | static const u8 sta32x_regs[STA32X_REGISTER_COUNT] = { | 59 | static const struct reg_default sta32x_regs[] = { |
59 | 0x63, 0x80, 0xc2, 0x40, 0xc2, 0x5c, 0x10, 0xff, 0x60, 0x60, | 60 | { 0x0, 0x63 }, |
60 | 0x60, 0x80, 0x00, 0x00, 0x00, 0x40, 0x80, 0x77, 0x6a, 0x69, | 61 | { 0x1, 0x80 }, |
61 | 0x6a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 62 | { 0x2, 0xc2 }, |
62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, | 63 | { 0x3, 0x40 }, |
63 | 0xc0, 0xf3, 0x33, 0x00, 0x0c, | 64 | { 0x4, 0xc2 }, |
65 | { 0x5, 0x5c }, | ||
66 | { 0x6, 0x10 }, | ||
67 | { 0x7, 0xff }, | ||
68 | { 0x8, 0x60 }, | ||
69 | { 0x9, 0x60 }, | ||
70 | { 0xa, 0x60 }, | ||
71 | { 0xb, 0x80 }, | ||
72 | { 0xc, 0x00 }, | ||
73 | { 0xd, 0x00 }, | ||
74 | { 0xe, 0x00 }, | ||
75 | { 0xf, 0x40 }, | ||
76 | { 0x10, 0x80 }, | ||
77 | { 0x11, 0x77 }, | ||
78 | { 0x12, 0x6a }, | ||
79 | { 0x13, 0x69 }, | ||
80 | { 0x14, 0x6a }, | ||
81 | { 0x15, 0x69 }, | ||
82 | { 0x16, 0x00 }, | ||
83 | { 0x17, 0x00 }, | ||
84 | { 0x18, 0x00 }, | ||
85 | { 0x19, 0x00 }, | ||
86 | { 0x1a, 0x00 }, | ||
87 | { 0x1b, 0x00 }, | ||
88 | { 0x1c, 0x00 }, | ||
89 | { 0x1d, 0x00 }, | ||
90 | { 0x1e, 0x00 }, | ||
91 | { 0x1f, 0x00 }, | ||
92 | { 0x20, 0x00 }, | ||
93 | { 0x21, 0x00 }, | ||
94 | { 0x22, 0x00 }, | ||
95 | { 0x23, 0x00 }, | ||
96 | { 0x24, 0x00 }, | ||
97 | { 0x25, 0x00 }, | ||
98 | { 0x26, 0x00 }, | ||
99 | { 0x27, 0x2d }, | ||
100 | { 0x28, 0xc0 }, | ||
101 | { 0x2b, 0x00 }, | ||
102 | { 0x2c, 0x0c }, | ||
64 | }; | 103 | }; |
65 | 104 | ||
66 | /* regulator power supply names */ | 105 | /* regulator power supply names */ |
@@ -72,6 +111,7 @@ static const char *sta32x_supply_names[] = { | |||
72 | 111 | ||
73 | /* codec private data */ | 112 | /* codec private data */ |
74 | struct sta32x_priv { | 113 | struct sta32x_priv { |
114 | struct regmap *regmap; | ||
75 | struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; | 115 | struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; |
76 | struct snd_soc_codec *codec; | 116 | struct snd_soc_codec *codec; |
77 | struct sta32x_platform_data *pdata; | 117 | struct sta32x_platform_data *pdata; |
@@ -291,17 +331,15 @@ static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec) | |||
291 | 331 | ||
292 | static int sta32x_cache_sync(struct snd_soc_codec *codec) | 332 | static int sta32x_cache_sync(struct snd_soc_codec *codec) |
293 | { | 333 | { |
334 | struct sta32x_priv *sta32x = codec->control_data; | ||
294 | unsigned int mute; | 335 | unsigned int mute; |
295 | int rc; | 336 | int rc; |
296 | 337 | ||
297 | if (!codec->cache_sync) | ||
298 | return 0; | ||
299 | |||
300 | /* mute during register sync */ | 338 | /* mute during register sync */ |
301 | mute = snd_soc_read(codec, STA32X_MMUTE); | 339 | mute = snd_soc_read(codec, STA32X_MMUTE); |
302 | snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); | 340 | snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); |
303 | sta32x_sync_coef_shadow(codec); | 341 | sta32x_sync_coef_shadow(codec); |
304 | rc = snd_soc_cache_sync(codec); | 342 | rc = regcache_sync(sta32x->regmap); |
305 | snd_soc_write(codec, STA32X_MMUTE, mute); | 343 | snd_soc_write(codec, STA32X_MMUTE, mute); |
306 | return rc; | 344 | return rc; |
307 | } | 345 | } |
@@ -316,11 +354,11 @@ static void sta32x_watchdog(struct work_struct *work) | |||
316 | 354 | ||
317 | /* check if sta32x has reset itself */ | 355 | /* check if sta32x has reset itself */ |
318 | confa_cached = snd_soc_read(codec, STA32X_CONFA); | 356 | confa_cached = snd_soc_read(codec, STA32X_CONFA); |
319 | codec->cache_bypass = 1; | 357 | regcache_cache_bypass(sta32x->regmap, true); |
320 | confa = snd_soc_read(codec, STA32X_CONFA); | 358 | confa = snd_soc_read(codec, STA32X_CONFA); |
321 | codec->cache_bypass = 0; | 359 | regcache_cache_bypass(sta32x->regmap, false); |
322 | if (confa != confa_cached) { | 360 | if (confa != confa_cached) { |
323 | codec->cache_sync = 1; | 361 | regcache_mark_dirty(sta32x->regmap); |
324 | sta32x_cache_sync(codec); | 362 | sta32x_cache_sync(codec); |
325 | } | 363 | } |
326 | 364 | ||
@@ -825,31 +863,21 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
825 | sta32x->codec = codec; | 863 | sta32x->codec = codec; |
826 | sta32x->pdata = dev_get_platdata(codec->dev); | 864 | sta32x->pdata = dev_get_platdata(codec->dev); |
827 | 865 | ||
828 | /* regulators */ | ||
829 | for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) | ||
830 | sta32x->supplies[i].supply = sta32x_supply_names[i]; | ||
831 | |||
832 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sta32x->supplies), | ||
833 | sta32x->supplies); | ||
834 | if (ret != 0) { | ||
835 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
836 | goto err; | ||
837 | } | ||
838 | |||
839 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), | 866 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), |
840 | sta32x->supplies); | 867 | sta32x->supplies); |
841 | if (ret != 0) { | 868 | if (ret != 0) { |
842 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | 869 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); |
843 | goto err_get; | 870 | return ret; |
844 | } | 871 | } |
845 | 872 | ||
846 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will | 873 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will |
847 | * then do the I2C transactions itself. | 874 | * then do the I2C transactions itself. |
848 | */ | 875 | */ |
849 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | 876 | codec->control_data = sta32x->regmap; |
877 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
850 | if (ret < 0) { | 878 | if (ret < 0) { |
851 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); | 879 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); |
852 | return ret; | 880 | goto err; |
853 | } | 881 | } |
854 | 882 | ||
855 | /* Chip documentation explicitly requires that the reset values | 883 | /* Chip documentation explicitly requires that the reset values |
@@ -858,13 +886,15 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
858 | * so the write to the these registers are suppressed by the cache | 886 | * so the write to the these registers are suppressed by the cache |
859 | * restore code when it skips writes of default registers. | 887 | * restore code when it skips writes of default registers. |
860 | */ | 888 | */ |
861 | snd_soc_cache_write(codec, STA32X_CONFC, 0xc2); | 889 | regcache_cache_only(sta32x->regmap, true); |
862 | snd_soc_cache_write(codec, STA32X_CONFE, 0xc2); | 890 | snd_soc_write(codec, STA32X_CONFC, 0xc2); |
863 | snd_soc_cache_write(codec, STA32X_CONFF, 0x5c); | 891 | snd_soc_write(codec, STA32X_CONFE, 0xc2); |
864 | snd_soc_cache_write(codec, STA32X_MMUTE, 0x10); | 892 | snd_soc_write(codec, STA32X_CONFF, 0x5c); |
865 | snd_soc_cache_write(codec, STA32X_AUTO1, 0x60); | 893 | snd_soc_write(codec, STA32X_MMUTE, 0x10); |
866 | snd_soc_cache_write(codec, STA32X_AUTO3, 0x00); | 894 | snd_soc_write(codec, STA32X_AUTO1, 0x60); |
867 | snd_soc_cache_write(codec, STA32X_C3CFG, 0x40); | 895 | snd_soc_write(codec, STA32X_AUTO3, 0x00); |
896 | snd_soc_write(codec, STA32X_C3CFG, 0x40); | ||
897 | regcache_cache_only(sta32x->regmap, false); | ||
868 | 898 | ||
869 | /* set thermal warning adjustment and recovery */ | 899 | /* set thermal warning adjustment and recovery */ |
870 | if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE)) | 900 | if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE)) |
@@ -915,9 +945,8 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
915 | 945 | ||
916 | return 0; | 946 | return 0; |
917 | 947 | ||
918 | err_get: | ||
919 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
920 | err: | 948 | err: |
949 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
921 | return ret; | 950 | return ret; |
922 | } | 951 | } |
923 | 952 | ||
@@ -928,13 +957,11 @@ static int sta32x_remove(struct snd_soc_codec *codec) | |||
928 | sta32x_watchdog_stop(sta32x); | 957 | sta32x_watchdog_stop(sta32x); |
929 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 958 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
930 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | 959 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); |
931 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
932 | 960 | ||
933 | return 0; | 961 | return 0; |
934 | } | 962 | } |
935 | 963 | ||
936 | static int sta32x_reg_is_volatile(struct snd_soc_codec *codec, | 964 | static bool sta32x_reg_is_volatile(struct device *dev, unsigned int reg) |
937 | unsigned int reg) | ||
938 | { | 965 | { |
939 | switch (reg) { | 966 | switch (reg) { |
940 | case STA32X_CONFA ... STA32X_L2ATRT: | 967 | case STA32X_CONFA ... STA32X_L2ATRT: |
@@ -949,10 +976,6 @@ static const struct snd_soc_codec_driver sta32x_codec = { | |||
949 | .remove = sta32x_remove, | 976 | .remove = sta32x_remove, |
950 | .suspend = sta32x_suspend, | 977 | .suspend = sta32x_suspend, |
951 | .resume = sta32x_resume, | 978 | .resume = sta32x_resume, |
952 | .reg_cache_size = STA32X_REGISTER_COUNT, | ||
953 | .reg_word_size = sizeof(u8), | ||
954 | .reg_cache_default = sta32x_regs, | ||
955 | .volatile_register = sta32x_reg_is_volatile, | ||
956 | .set_bias_level = sta32x_set_bias_level, | 979 | .set_bias_level = sta32x_set_bias_level, |
957 | .controls = sta32x_snd_controls, | 980 | .controls = sta32x_snd_controls, |
958 | .num_controls = ARRAY_SIZE(sta32x_snd_controls), | 981 | .num_controls = ARRAY_SIZE(sta32x_snd_controls), |
@@ -962,17 +985,45 @@ static const struct snd_soc_codec_driver sta32x_codec = { | |||
962 | .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), | 985 | .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), |
963 | }; | 986 | }; |
964 | 987 | ||
988 | static const struct regmap_config sta32x_regmap = { | ||
989 | .reg_bits = 8, | ||
990 | .val_bits = 8, | ||
991 | .max_register = STA32X_FDRC2, | ||
992 | .reg_defaults = sta32x_regs, | ||
993 | .num_reg_defaults = ARRAY_SIZE(sta32x_regs), | ||
994 | .cache_type = REGCACHE_RBTREE, | ||
995 | .volatile_reg = sta32x_reg_is_volatile, | ||
996 | }; | ||
997 | |||
965 | static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, | 998 | static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, |
966 | const struct i2c_device_id *id) | 999 | const struct i2c_device_id *id) |
967 | { | 1000 | { |
968 | struct sta32x_priv *sta32x; | 1001 | struct sta32x_priv *sta32x; |
969 | int ret; | 1002 | int ret, i; |
970 | 1003 | ||
971 | sta32x = devm_kzalloc(&i2c->dev, sizeof(struct sta32x_priv), | 1004 | sta32x = devm_kzalloc(&i2c->dev, sizeof(struct sta32x_priv), |
972 | GFP_KERNEL); | 1005 | GFP_KERNEL); |
973 | if (!sta32x) | 1006 | if (!sta32x) |
974 | return -ENOMEM; | 1007 | return -ENOMEM; |
975 | 1008 | ||
1009 | /* regulators */ | ||
1010 | for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) | ||
1011 | sta32x->supplies[i].supply = sta32x_supply_names[i]; | ||
1012 | |||
1013 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(sta32x->supplies), | ||
1014 | sta32x->supplies); | ||
1015 | if (ret != 0) { | ||
1016 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
1017 | return ret; | ||
1018 | } | ||
1019 | |||
1020 | sta32x->regmap = devm_regmap_init_i2c(i2c, &sta32x_regmap); | ||
1021 | if (IS_ERR(sta32x->regmap)) { | ||
1022 | ret = PTR_ERR(sta32x->regmap); | ||
1023 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); | ||
1024 | return ret; | ||
1025 | } | ||
1026 | |||
976 | i2c_set_clientdata(i2c, sta32x); | 1027 | i2c_set_clientdata(i2c, sta32x); |
977 | 1028 | ||
978 | ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); | 1029 | ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); |
@@ -1006,17 +1057,7 @@ static struct i2c_driver sta32x_i2c_driver = { | |||
1006 | .id_table = sta32x_i2c_id, | 1057 | .id_table = sta32x_i2c_id, |
1007 | }; | 1058 | }; |
1008 | 1059 | ||
1009 | static int __init sta32x_init(void) | 1060 | module_i2c_driver(sta32x_i2c_driver); |
1010 | { | ||
1011 | return i2c_add_driver(&sta32x_i2c_driver); | ||
1012 | } | ||
1013 | module_init(sta32x_init); | ||
1014 | |||
1015 | static void __exit sta32x_exit(void) | ||
1016 | { | ||
1017 | i2c_del_driver(&sta32x_i2c_driver); | ||
1018 | } | ||
1019 | module_exit(sta32x_exit); | ||
1020 | 1061 | ||
1021 | MODULE_DESCRIPTION("ASoC STA32X driver"); | 1062 | MODULE_DESCRIPTION("ASoC STA32X driver"); |
1022 | MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>"); | 1063 | MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>"); |
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 0c225cd569d2..9e3144862386 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c | |||
@@ -358,7 +358,7 @@ static int sta529_resume(struct snd_soc_codec *codec) | |||
358 | return 0; | 358 | return 0; |
359 | } | 359 | } |
360 | 360 | ||
361 | struct snd_soc_codec_driver sta529_codec_driver = { | 361 | static const struct snd_soc_codec_driver sta529_codec_driver = { |
362 | .probe = sta529_probe, | 362 | .probe = sta529_probe, |
363 | .remove = sta529_remove, | 363 | .remove = sta529_remove, |
364 | .set_bias_level = sta529_set_bias_level, | 364 | .set_bias_level = sta529_set_bias_level, |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 33c0f3d39c87..982e437799a8 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
@@ -340,7 +340,6 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) | |||
340 | 340 | ||
341 | printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); | 341 | printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); |
342 | 342 | ||
343 | codec->control_data = codec; /* we don't use regmap! */ | ||
344 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 343 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
345 | if (ret < 0) | 344 | if (ret < 0) |
346 | goto codec_err; | 345 | goto codec_err; |
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 85944e953578..b1f6982c7c9c 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
@@ -444,14 +444,4 @@ static struct spi_driver aic26_spi = { | |||
444 | .remove = aic26_spi_remove, | 444 | .remove = aic26_spi_remove, |
445 | }; | 445 | }; |
446 | 446 | ||
447 | static int __init aic26_init(void) | 447 | module_spi_driver(aic26_spi); |
448 | { | ||
449 | return spi_register_driver(&aic26_spi); | ||
450 | } | ||
451 | module_init(aic26_init); | ||
452 | |||
453 | static void __exit aic26_exit(void) | ||
454 | { | ||
455 | spi_unregister_driver(&aic26_spi); | ||
456 | } | ||
457 | module_exit(aic26_exit); | ||
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index b0a73d37ed52..f230292ba96b 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c | |||
@@ -746,24 +746,7 @@ static struct i2c_driver aic32x4_i2c_driver = { | |||
746 | .id_table = aic32x4_i2c_id, | 746 | .id_table = aic32x4_i2c_id, |
747 | }; | 747 | }; |
748 | 748 | ||
749 | static int __init aic32x4_modinit(void) | 749 | module_i2c_driver(aic32x4_i2c_driver); |
750 | { | ||
751 | int ret = 0; | ||
752 | |||
753 | ret = i2c_add_driver(&aic32x4_i2c_driver); | ||
754 | if (ret != 0) { | ||
755 | printk(KERN_ERR "Failed to register aic32x4 I2C driver: %d\n", | ||
756 | ret); | ||
757 | } | ||
758 | return ret; | ||
759 | } | ||
760 | module_init(aic32x4_modinit); | ||
761 | |||
762 | static void __exit aic32x4_exit(void) | ||
763 | { | ||
764 | i2c_del_driver(&aic32x4_i2c_driver); | ||
765 | } | ||
766 | module_exit(aic32x4_exit); | ||
767 | 750 | ||
768 | MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); | 751 | MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); |
769 | MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); | 752 | MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index dc78f5a4bcbf..5708a973a776 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/i2c.h> | 40 | #include <linux/i2c.h> |
41 | #include <linux/gpio.h> | 41 | #include <linux/gpio.h> |
42 | #include <linux/regulator/consumer.h> | 42 | #include <linux/regulator/consumer.h> |
43 | #include <linux/of_gpio.h> | ||
43 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
44 | #include <sound/core.h> | 45 | #include <sound/core.h> |
45 | #include <sound/pcm.h> | 46 | #include <sound/pcm.h> |
@@ -1457,6 +1458,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1457 | { | 1458 | { |
1458 | struct aic3x_pdata *pdata = i2c->dev.platform_data; | 1459 | struct aic3x_pdata *pdata = i2c->dev.platform_data; |
1459 | struct aic3x_priv *aic3x; | 1460 | struct aic3x_priv *aic3x; |
1461 | struct aic3x_setup_data *ai3x_setup; | ||
1462 | struct device_node *np = i2c->dev.of_node; | ||
1460 | int ret; | 1463 | int ret; |
1461 | 1464 | ||
1462 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); | 1465 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); |
@@ -1471,6 +1474,25 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1471 | if (pdata) { | 1474 | if (pdata) { |
1472 | aic3x->gpio_reset = pdata->gpio_reset; | 1475 | aic3x->gpio_reset = pdata->gpio_reset; |
1473 | aic3x->setup = pdata->setup; | 1476 | aic3x->setup = pdata->setup; |
1477 | } else if (np) { | ||
1478 | ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), | ||
1479 | GFP_KERNEL); | ||
1480 | if (ai3x_setup == NULL) { | ||
1481 | dev_err(&i2c->dev, "failed to create private data\n"); | ||
1482 | return -ENOMEM; | ||
1483 | } | ||
1484 | |||
1485 | ret = of_get_named_gpio(np, "gpio-reset", 0); | ||
1486 | if (ret >= 0) | ||
1487 | aic3x->gpio_reset = ret; | ||
1488 | else | ||
1489 | aic3x->gpio_reset = -1; | ||
1490 | |||
1491 | if (of_property_read_u32_array(np, "ai3x-gpio-func", | ||
1492 | ai3x_setup->gpio_func, 2) >= 0) { | ||
1493 | aic3x->setup = ai3x_setup; | ||
1494 | } | ||
1495 | |||
1474 | } else { | 1496 | } else { |
1475 | aic3x->gpio_reset = -1; | 1497 | aic3x->gpio_reset = -1; |
1476 | } | 1498 | } |
@@ -1488,34 +1510,27 @@ static int aic3x_i2c_remove(struct i2c_client *client) | |||
1488 | return 0; | 1510 | return 0; |
1489 | } | 1511 | } |
1490 | 1512 | ||
1513 | #if defined(CONFIG_OF) | ||
1514 | static const struct of_device_id tlv320aic3x_of_match[] = { | ||
1515 | { .compatible = "ti,tlv320aic3x", }, | ||
1516 | {}, | ||
1517 | }; | ||
1518 | MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); | ||
1519 | #endif | ||
1520 | |||
1491 | /* machine i2c codec control layer */ | 1521 | /* machine i2c codec control layer */ |
1492 | static struct i2c_driver aic3x_i2c_driver = { | 1522 | static struct i2c_driver aic3x_i2c_driver = { |
1493 | .driver = { | 1523 | .driver = { |
1494 | .name = "tlv320aic3x-codec", | 1524 | .name = "tlv320aic3x-codec", |
1495 | .owner = THIS_MODULE, | 1525 | .owner = THIS_MODULE, |
1526 | .of_match_table = of_match_ptr(tlv320aic3x_of_match), | ||
1496 | }, | 1527 | }, |
1497 | .probe = aic3x_i2c_probe, | 1528 | .probe = aic3x_i2c_probe, |
1498 | .remove = aic3x_i2c_remove, | 1529 | .remove = aic3x_i2c_remove, |
1499 | .id_table = aic3x_i2c_id, | 1530 | .id_table = aic3x_i2c_id, |
1500 | }; | 1531 | }; |
1501 | 1532 | ||
1502 | static int __init aic3x_modinit(void) | 1533 | module_i2c_driver(aic3x_i2c_driver); |
1503 | { | ||
1504 | int ret = 0; | ||
1505 | ret = i2c_add_driver(&aic3x_i2c_driver); | ||
1506 | if (ret != 0) { | ||
1507 | printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n", | ||
1508 | ret); | ||
1509 | } | ||
1510 | return ret; | ||
1511 | } | ||
1512 | module_init(aic3x_modinit); | ||
1513 | |||
1514 | static void __exit aic3x_exit(void) | ||
1515 | { | ||
1516 | i2c_del_driver(&aic3x_i2c_driver); | ||
1517 | } | ||
1518 | module_exit(aic3x_exit); | ||
1519 | 1534 | ||
1520 | MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); | 1535 | MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); |
1521 | MODULE_AUTHOR("Vladimir Barinov"); | 1536 | MODULE_AUTHOR("Vladimir Barinov"); |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 0dd41077ab79..d2e16c5d7d1f 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -1621,24 +1621,7 @@ static struct i2c_driver tlv320dac33_i2c_driver = { | |||
1621 | .id_table = tlv320dac33_i2c_id, | 1621 | .id_table = tlv320dac33_i2c_id, |
1622 | }; | 1622 | }; |
1623 | 1623 | ||
1624 | static int __init dac33_module_init(void) | 1624 | module_i2c_driver(tlv320dac33_i2c_driver); |
1625 | { | ||
1626 | int r; | ||
1627 | r = i2c_add_driver(&tlv320dac33_i2c_driver); | ||
1628 | if (r < 0) { | ||
1629 | printk(KERN_ERR "DAC33: driver registration failed\n"); | ||
1630 | return r; | ||
1631 | } | ||
1632 | return 0; | ||
1633 | } | ||
1634 | module_init(dac33_module_init); | ||
1635 | |||
1636 | static void __exit dac33_module_exit(void) | ||
1637 | { | ||
1638 | i2c_del_driver(&tlv320dac33_i2c_driver); | ||
1639 | } | ||
1640 | module_exit(dac33_module_exit); | ||
1641 | |||
1642 | 1625 | ||
1643 | MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver"); | 1626 | MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver"); |
1644 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | 1627 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); |
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 6fe4aa3ac544..565ff39ad3a3 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c | |||
@@ -487,19 +487,8 @@ static struct i2c_driver tpa6130a2_i2c_driver = { | |||
487 | .id_table = tpa6130a2_id, | 487 | .id_table = tpa6130a2_id, |
488 | }; | 488 | }; |
489 | 489 | ||
490 | static int __init tpa6130a2_init(void) | 490 | module_i2c_driver(tpa6130a2_i2c_driver); |
491 | { | ||
492 | return i2c_add_driver(&tpa6130a2_i2c_driver); | ||
493 | } | ||
494 | |||
495 | static void __exit tpa6130a2_exit(void) | ||
496 | { | ||
497 | i2c_del_driver(&tpa6130a2_i2c_driver); | ||
498 | } | ||
499 | 491 | ||
500 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | 492 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); |
501 | MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); | 493 | MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); |
502 | MODULE_LICENSE("GPL"); | 494 | MODULE_LICENSE("GPL"); |
503 | |||
504 | module_init(tpa6130a2_init); | ||
505 | module_exit(tpa6130a2_exit); | ||
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 391fcfc7b63b..e7f608996c41 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -26,8 +26,11 @@ | |||
26 | #include <linux/pm.h> | 26 | #include <linux/pm.h> |
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/of.h> | ||
30 | #include <linux/of_gpio.h> | ||
29 | #include <linux/i2c/twl.h> | 31 | #include <linux/i2c/twl.h> |
30 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/gpio.h> | ||
31 | #include <sound/core.h> | 34 | #include <sound/core.h> |
32 | #include <sound/pcm.h> | 35 | #include <sound/pcm.h> |
33 | #include <sound/pcm_params.h> | 36 | #include <sound/pcm_params.h> |
@@ -152,8 +155,7 @@ struct twl4030_priv { | |||
152 | u8 predrivel_enabled, predriver_enabled; | 155 | u8 predrivel_enabled, predriver_enabled; |
153 | u8 carkitl_enabled, carkitr_enabled; | 156 | u8 carkitl_enabled, carkitr_enabled; |
154 | 157 | ||
155 | /* Delay needed after enabling the digimic interface */ | 158 | struct twl4030_codec_data *pdata; |
156 | unsigned int digimic_delay; | ||
157 | }; | 159 | }; |
158 | 160 | ||
159 | /* | 161 | /* |
@@ -295,13 +297,73 @@ static inline void twl4030_reset_registers(struct snd_soc_codec *codec) | |||
295 | 297 | ||
296 | } | 298 | } |
297 | 299 | ||
298 | static void twl4030_init_chip(struct snd_soc_codec *codec) | 300 | static void twl4030_setup_pdata_of(struct twl4030_codec_data *pdata, |
301 | struct device_node *node) | ||
302 | { | ||
303 | int value; | ||
304 | |||
305 | of_property_read_u32(node, "ti,digimic_delay", | ||
306 | &pdata->digimic_delay); | ||
307 | of_property_read_u32(node, "ti,ramp_delay_value", | ||
308 | &pdata->ramp_delay_value); | ||
309 | of_property_read_u32(node, "ti,offset_cncl_path", | ||
310 | &pdata->offset_cncl_path); | ||
311 | if (!of_property_read_u32(node, "ti,hs_extmute", &value)) | ||
312 | pdata->hs_extmute = value; | ||
313 | |||
314 | pdata->hs_extmute_gpio = of_get_named_gpio(node, | ||
315 | "ti,hs_extmute_gpio", 0); | ||
316 | if (gpio_is_valid(pdata->hs_extmute_gpio)) | ||
317 | pdata->hs_extmute = 1; | ||
318 | } | ||
319 | |||
320 | static struct twl4030_codec_data *twl4030_get_pdata(struct snd_soc_codec *codec) | ||
299 | { | 321 | { |
300 | struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev); | 322 | struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev); |
323 | struct device_node *twl4030_codec_node = NULL; | ||
324 | |||
325 | twl4030_codec_node = of_find_node_by_name(codec->dev->parent->of_node, | ||
326 | "codec"); | ||
327 | |||
328 | if (!pdata && twl4030_codec_node) { | ||
329 | pdata = devm_kzalloc(codec->dev, | ||
330 | sizeof(struct twl4030_codec_data), | ||
331 | GFP_KERNEL); | ||
332 | if (!pdata) { | ||
333 | dev_err(codec->dev, "Can not allocate memory\n"); | ||
334 | return NULL; | ||
335 | } | ||
336 | twl4030_setup_pdata_of(pdata, twl4030_codec_node); | ||
337 | } | ||
338 | |||
339 | return pdata; | ||
340 | } | ||
341 | |||
342 | static void twl4030_init_chip(struct snd_soc_codec *codec) | ||
343 | { | ||
344 | struct twl4030_codec_data *pdata; | ||
301 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 345 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
302 | u8 reg, byte; | 346 | u8 reg, byte; |
303 | int i = 0; | 347 | int i = 0; |
304 | 348 | ||
349 | pdata = twl4030_get_pdata(codec); | ||
350 | |||
351 | if (pdata && pdata->hs_extmute && | ||
352 | gpio_is_valid(pdata->hs_extmute_gpio)) { | ||
353 | int ret; | ||
354 | |||
355 | if (!pdata->hs_extmute_gpio) | ||
356 | dev_warn(codec->dev, | ||
357 | "Extmute GPIO is 0 is this correct?\n"); | ||
358 | |||
359 | ret = gpio_request_one(pdata->hs_extmute_gpio, | ||
360 | GPIOF_OUT_INIT_LOW, "hs_extmute"); | ||
361 | if (ret) { | ||
362 | dev_err(codec->dev, "Failed to get hs_extmute GPIO\n"); | ||
363 | pdata->hs_extmute_gpio = -1; | ||
364 | } | ||
365 | } | ||
366 | |||
305 | /* Check defaults, if instructed before anything else */ | 367 | /* Check defaults, if instructed before anything else */ |
306 | if (pdata && pdata->check_defaults) | 368 | if (pdata && pdata->check_defaults) |
307 | twl4030_check_defaults(codec); | 369 | twl4030_check_defaults(codec); |
@@ -331,7 +393,7 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) | |||
331 | if (!pdata) | 393 | if (!pdata) |
332 | return; | 394 | return; |
333 | 395 | ||
334 | twl4030->digimic_delay = pdata->digimic_delay; | 396 | twl4030->pdata = pdata; |
335 | 397 | ||
336 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); | 398 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); |
337 | reg &= ~TWL4030_RAMP_DELAY; | 399 | reg &= ~TWL4030_RAMP_DELAY; |
@@ -732,9 +794,9 @@ static int aif_event(struct snd_soc_dapm_widget *w, | |||
732 | 794 | ||
733 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) | 795 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) |
734 | { | 796 | { |
735 | struct twl4030_codec_data *pdata = codec->dev->platform_data; | ||
736 | unsigned char hs_gain, hs_pop; | 797 | unsigned char hs_gain, hs_pop; |
737 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 798 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
799 | struct twl4030_codec_data *pdata = twl4030->pdata; | ||
738 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ | 800 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ |
739 | unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304, | 801 | unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304, |
740 | 8388608, 16777216, 33554432, 67108864}; | 802 | 8388608, 16777216, 33554432, 67108864}; |
@@ -748,8 +810,8 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
748 | /* Enable external mute control, this dramatically reduces | 810 | /* Enable external mute control, this dramatically reduces |
749 | * the pop-noise */ | 811 | * the pop-noise */ |
750 | if (pdata && pdata->hs_extmute) { | 812 | if (pdata && pdata->hs_extmute) { |
751 | if (pdata->set_hs_extmute) { | 813 | if (gpio_is_valid(pdata->hs_extmute_gpio)) { |
752 | pdata->set_hs_extmute(1); | 814 | gpio_set_value(pdata->hs_extmute_gpio, 1); |
753 | } else { | 815 | } else { |
754 | hs_pop |= TWL4030_EXTMUTE; | 816 | hs_pop |= TWL4030_EXTMUTE; |
755 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 817 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
@@ -786,8 +848,8 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
786 | 848 | ||
787 | /* Disable external mute */ | 849 | /* Disable external mute */ |
788 | if (pdata && pdata->hs_extmute) { | 850 | if (pdata && pdata->hs_extmute) { |
789 | if (pdata->set_hs_extmute) { | 851 | if (gpio_is_valid(pdata->hs_extmute_gpio)) { |
790 | pdata->set_hs_extmute(0); | 852 | gpio_set_value(pdata->hs_extmute_gpio, 0); |
791 | } else { | 853 | } else { |
792 | hs_pop &= ~TWL4030_EXTMUTE; | 854 | hs_pop &= ~TWL4030_EXTMUTE; |
793 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 855 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
@@ -847,9 +909,10 @@ static int digimic_event(struct snd_soc_dapm_widget *w, | |||
847 | struct snd_kcontrol *kcontrol, int event) | 909 | struct snd_kcontrol *kcontrol, int event) |
848 | { | 910 | { |
849 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); | 911 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); |
912 | struct twl4030_codec_data *pdata = twl4030->pdata; | ||
850 | 913 | ||
851 | if (twl4030->digimic_delay) | 914 | if (pdata && pdata->digimic_delay) |
852 | twl4030_wait_ms(twl4030->digimic_delay); | 915 | twl4030_wait_ms(pdata->digimic_delay); |
853 | return 0; | 916 | return 0; |
854 | } | 917 | } |
855 | 918 | ||
@@ -999,7 +1062,7 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, | |||
999 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1062 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
1000 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 1063 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
1001 | unsigned short val; | 1064 | unsigned short val; |
1002 | unsigned short mask, bitmask; | 1065 | unsigned short mask; |
1003 | 1066 | ||
1004 | if (twl4030->configured) { | 1067 | if (twl4030->configured) { |
1005 | dev_err(codec->dev, | 1068 | dev_err(codec->dev, |
@@ -1007,18 +1070,16 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, | |||
1007 | return -EBUSY; | 1070 | return -EBUSY; |
1008 | } | 1071 | } |
1009 | 1072 | ||
1010 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
1011 | ; | ||
1012 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 1073 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
1013 | return -EINVAL; | 1074 | return -EINVAL; |
1014 | 1075 | ||
1015 | val = ucontrol->value.enumerated.item[0] << e->shift_l; | 1076 | val = ucontrol->value.enumerated.item[0] << e->shift_l; |
1016 | mask = (bitmask - 1) << e->shift_l; | 1077 | mask = e->mask << e->shift_l; |
1017 | if (e->shift_l != e->shift_r) { | 1078 | if (e->shift_l != e->shift_r) { |
1018 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | 1079 | if (ucontrol->value.enumerated.item[1] > e->max - 1) |
1019 | return -EINVAL; | 1080 | return -EINVAL; |
1020 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 1081 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; |
1021 | mask |= (bitmask - 1) << e->shift_r; | 1082 | mask |= e->mask << e->shift_r; |
1022 | } | 1083 | } |
1023 | 1084 | ||
1024 | return snd_soc_update_bits(codec, e->reg, mask, val); | 1085 | return snd_soc_update_bits(codec, e->reg, mask, val); |
@@ -1239,16 +1300,11 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
1239 | SND_SOC_DAPM_OUTPUT("Virtual Voice OUT"), | 1300 | SND_SOC_DAPM_OUTPUT("Virtual Voice OUT"), |
1240 | 1301 | ||
1241 | /* DACs */ | 1302 | /* DACs */ |
1242 | SND_SOC_DAPM_DAC("DAC Right1", "Right Front HiFi Playback", | 1303 | SND_SOC_DAPM_DAC("DAC Right1", NULL, SND_SOC_NOPM, 0, 0), |
1243 | SND_SOC_NOPM, 0, 0), | 1304 | SND_SOC_DAPM_DAC("DAC Left1", NULL, SND_SOC_NOPM, 0, 0), |
1244 | SND_SOC_DAPM_DAC("DAC Left1", "Left Front HiFi Playback", | 1305 | SND_SOC_DAPM_DAC("DAC Right2", NULL, SND_SOC_NOPM, 0, 0), |
1245 | SND_SOC_NOPM, 0, 0), | 1306 | SND_SOC_DAPM_DAC("DAC Left2", NULL, SND_SOC_NOPM, 0, 0), |
1246 | SND_SOC_DAPM_DAC("DAC Right2", "Right Rear HiFi Playback", | 1307 | SND_SOC_DAPM_DAC("DAC Voice", NULL, SND_SOC_NOPM, 0, 0), |
1247 | SND_SOC_NOPM, 0, 0), | ||
1248 | SND_SOC_DAPM_DAC("DAC Left2", "Left Rear HiFi Playback", | ||
1249 | SND_SOC_NOPM, 0, 0), | ||
1250 | SND_SOC_DAPM_DAC("DAC Voice", "Voice Playback", | ||
1251 | SND_SOC_NOPM, 0, 0), | ||
1252 | 1308 | ||
1253 | /* Analog bypasses */ | 1309 | /* Analog bypasses */ |
1254 | SND_SOC_DAPM_SWITCH("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, | 1310 | SND_SOC_DAPM_SWITCH("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, |
@@ -1377,14 +1433,10 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
1377 | 1433 | ||
1378 | /* Introducing four virtual ADC, since TWL4030 have four channel for | 1434 | /* Introducing four virtual ADC, since TWL4030 have four channel for |
1379 | capture */ | 1435 | capture */ |
1380 | SND_SOC_DAPM_ADC("ADC Virtual Left1", "Left Front Capture", | 1436 | SND_SOC_DAPM_ADC("ADC Virtual Left1", NULL, SND_SOC_NOPM, 0, 0), |
1381 | SND_SOC_NOPM, 0, 0), | 1437 | SND_SOC_DAPM_ADC("ADC Virtual Right1", NULL, SND_SOC_NOPM, 0, 0), |
1382 | SND_SOC_DAPM_ADC("ADC Virtual Right1", "Right Front Capture", | 1438 | SND_SOC_DAPM_ADC("ADC Virtual Left2", NULL, SND_SOC_NOPM, 0, 0), |
1383 | SND_SOC_NOPM, 0, 0), | 1439 | SND_SOC_DAPM_ADC("ADC Virtual Right2", NULL, SND_SOC_NOPM, 0, 0), |
1384 | SND_SOC_DAPM_ADC("ADC Virtual Left2", "Left Rear Capture", | ||
1385 | SND_SOC_NOPM, 0, 0), | ||
1386 | SND_SOC_DAPM_ADC("ADC Virtual Right2", "Right Rear Capture", | ||
1387 | SND_SOC_NOPM, 0, 0), | ||
1388 | 1440 | ||
1389 | /* Analog/Digital mic path selection. | 1441 | /* Analog/Digital mic path selection. |
1390 | TX1 Left/Right: either analog Left/Right or Digimic0 | 1442 | TX1 Left/Right: either analog Left/Right or Digimic0 |
@@ -1428,6 +1480,23 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
1428 | }; | 1480 | }; |
1429 | 1481 | ||
1430 | static const struct snd_soc_dapm_route intercon[] = { | 1482 | static const struct snd_soc_dapm_route intercon[] = { |
1483 | /* Stream -> DAC mapping */ | ||
1484 | {"DAC Right1", NULL, "HiFi Playback"}, | ||
1485 | {"DAC Left1", NULL, "HiFi Playback"}, | ||
1486 | {"DAC Right2", NULL, "HiFi Playback"}, | ||
1487 | {"DAC Left2", NULL, "HiFi Playback"}, | ||
1488 | {"DAC Voice", NULL, "Voice Playback"}, | ||
1489 | |||
1490 | /* ADC -> Stream mapping */ | ||
1491 | {"HiFi Capture", NULL, "ADC Virtual Left1"}, | ||
1492 | {"HiFi Capture", NULL, "ADC Virtual Right1"}, | ||
1493 | {"HiFi Capture", NULL, "ADC Virtual Left2"}, | ||
1494 | {"HiFi Capture", NULL, "ADC Virtual Right2"}, | ||
1495 | {"Voice Capture", NULL, "ADC Virtual Left1"}, | ||
1496 | {"Voice Capture", NULL, "ADC Virtual Right1"}, | ||
1497 | {"Voice Capture", NULL, "ADC Virtual Left2"}, | ||
1498 | {"Voice Capture", NULL, "ADC Virtual Right2"}, | ||
1499 | |||
1431 | {"Digital L1 Playback Mixer", NULL, "DAC Left1"}, | 1500 | {"Digital L1 Playback Mixer", NULL, "DAC Left1"}, |
1432 | {"Digital R1 Playback Mixer", NULL, "DAC Right1"}, | 1501 | {"Digital R1 Playback Mixer", NULL, "DAC Right1"}, |
1433 | {"Digital L2 Playback Mixer", NULL, "DAC Left2"}, | 1502 | {"Digital L2 Playback Mixer", NULL, "DAC Left2"}, |
@@ -2172,7 +2241,7 @@ static struct snd_soc_dai_driver twl4030_dai[] = { | |||
2172 | .formats = TWL4030_FORMATS, | 2241 | .formats = TWL4030_FORMATS, |
2173 | .sig_bits = 24,}, | 2242 | .sig_bits = 24,}, |
2174 | .capture = { | 2243 | .capture = { |
2175 | .stream_name = "Capture", | 2244 | .stream_name = "HiFi Capture", |
2176 | .channels_min = 2, | 2245 | .channels_min = 2, |
2177 | .channels_max = 4, | 2246 | .channels_max = 4, |
2178 | .rates = TWL4030_RATES, | 2247 | .rates = TWL4030_RATES, |
@@ -2189,7 +2258,7 @@ static struct snd_soc_dai_driver twl4030_dai[] = { | |||
2189 | .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, | 2258 | .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, |
2190 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 2259 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
2191 | .capture = { | 2260 | .capture = { |
2192 | .stream_name = "Capture", | 2261 | .stream_name = "Voice Capture", |
2193 | .channels_min = 1, | 2262 | .channels_min = 1, |
2194 | .channels_max = 2, | 2263 | .channels_max = 2, |
2195 | .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, | 2264 | .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, |
@@ -2214,7 +2283,8 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec) | |||
2214 | { | 2283 | { |
2215 | struct twl4030_priv *twl4030; | 2284 | struct twl4030_priv *twl4030; |
2216 | 2285 | ||
2217 | twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); | 2286 | twl4030 = devm_kzalloc(codec->dev, sizeof(struct twl4030_priv), |
2287 | GFP_KERNEL); | ||
2218 | if (twl4030 == NULL) { | 2288 | if (twl4030 == NULL) { |
2219 | dev_err(codec->dev, "Can not allocate memory\n"); | 2289 | dev_err(codec->dev, "Can not allocate memory\n"); |
2220 | return -ENOMEM; | 2290 | return -ENOMEM; |
@@ -2231,11 +2301,15 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec) | |||
2231 | static int twl4030_soc_remove(struct snd_soc_codec *codec) | 2301 | static int twl4030_soc_remove(struct snd_soc_codec *codec) |
2232 | { | 2302 | { |
2233 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 2303 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
2304 | struct twl4030_codec_data *pdata = twl4030->pdata; | ||
2234 | 2305 | ||
2235 | /* Reset registers to their chip default before leaving */ | 2306 | /* Reset registers to their chip default before leaving */ |
2236 | twl4030_reset_registers(codec); | 2307 | twl4030_reset_registers(codec); |
2237 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2308 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2238 | kfree(twl4030); | 2309 | |
2310 | if (pdata && pdata->hs_extmute && gpio_is_valid(pdata->hs_extmute_gpio)) | ||
2311 | gpio_free(pdata->hs_extmute_gpio); | ||
2312 | |||
2239 | return 0; | 2313 | return 0; |
2240 | } | 2314 | } |
2241 | 2315 | ||
@@ -2262,13 +2336,6 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { | |||
2262 | 2336 | ||
2263 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) | 2337 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) |
2264 | { | 2338 | { |
2265 | struct twl4030_codec_data *pdata = pdev->dev.platform_data; | ||
2266 | |||
2267 | if (!pdata) { | ||
2268 | dev_err(&pdev->dev, "platform_data is missing\n"); | ||
2269 | return -EINVAL; | ||
2270 | } | ||
2271 | |||
2272 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030, | 2339 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030, |
2273 | twl4030_dai, ARRAY_SIZE(twl4030_dai)); | 2340 | twl4030_dai, ARRAY_SIZE(twl4030_dai)); |
2274 | } | 2341 | } |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index c084c549942e..e8f97af75928 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -727,10 +727,8 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { | |||
727 | TWL6040_REG_MICRCTL, 1, 0, NULL, 0), | 727 | TWL6040_REG_MICRCTL, 1, 0, NULL, 0), |
728 | 728 | ||
729 | /* ADCs */ | 729 | /* ADCs */ |
730 | SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture", | 730 | SND_SOC_DAPM_ADC("ADC Left", NULL, TWL6040_REG_MICLCTL, 2, 0), |
731 | TWL6040_REG_MICLCTL, 2, 0), | 731 | SND_SOC_DAPM_ADC("ADC Right", NULL, TWL6040_REG_MICRCTL, 2, 0), |
732 | SND_SOC_DAPM_ADC("ADC Right", "Right Front Capture", | ||
733 | TWL6040_REG_MICRCTL, 2, 0), | ||
734 | 732 | ||
735 | /* Microphone bias */ | 733 | /* Microphone bias */ |
736 | SND_SOC_DAPM_SUPPLY("Headset Mic Bias", | 734 | SND_SOC_DAPM_SUPPLY("Headset Mic Bias", |
@@ -743,15 +741,12 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { | |||
743 | TWL6040_REG_DMICBCTL, 4, 0, NULL, 0), | 741 | TWL6040_REG_DMICBCTL, 4, 0, NULL, 0), |
744 | 742 | ||
745 | /* DACs */ | 743 | /* DACs */ |
746 | SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", SND_SOC_NOPM, 0, 0), | 744 | SND_SOC_DAPM_DAC("HSDAC Left", NULL, SND_SOC_NOPM, 0, 0), |
747 | SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback", SND_SOC_NOPM, 0, 0), | 745 | SND_SOC_DAPM_DAC("HSDAC Right", NULL, SND_SOC_NOPM, 0, 0), |
748 | SND_SOC_DAPM_DAC("HFDAC Left", "Handsfree Playback", | 746 | SND_SOC_DAPM_DAC("HFDAC Left", NULL, TWL6040_REG_HFLCTL, 0, 0), |
749 | TWL6040_REG_HFLCTL, 0, 0), | 747 | SND_SOC_DAPM_DAC("HFDAC Right", NULL, TWL6040_REG_HFRCTL, 0, 0), |
750 | SND_SOC_DAPM_DAC("HFDAC Right", "Handsfree Playback", | ||
751 | TWL6040_REG_HFRCTL, 0, 0), | ||
752 | /* Virtual DAC for vibra path (DL4 channel) */ | 748 | /* Virtual DAC for vibra path (DL4 channel) */ |
753 | SND_SOC_DAPM_DAC("VIBRA DAC", "Vibra Playback", | 749 | SND_SOC_DAPM_DAC("VIBRA DAC", NULL, SND_SOC_NOPM, 0, 0), |
754 | SND_SOC_NOPM, 0, 0), | ||
755 | 750 | ||
756 | SND_SOC_DAPM_MUX("Handsfree Left Playback", | 751 | SND_SOC_DAPM_MUX("Handsfree Left Playback", |
757 | SND_SOC_NOPM, 0, 0, &hfl_mux_controls), | 752 | SND_SOC_NOPM, 0, 0, &hfl_mux_controls), |
@@ -810,6 +805,26 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { | |||
810 | }; | 805 | }; |
811 | 806 | ||
812 | static const struct snd_soc_dapm_route intercon[] = { | 807 | static const struct snd_soc_dapm_route intercon[] = { |
808 | /* Stream -> DAC mapping */ | ||
809 | {"HSDAC Left", NULL, "Legacy Playback"}, | ||
810 | {"HSDAC Left", NULL, "Headset Playback"}, | ||
811 | {"HSDAC Right", NULL, "Legacy Playback"}, | ||
812 | {"HSDAC Right", NULL, "Headset Playback"}, | ||
813 | |||
814 | {"HFDAC Left", NULL, "Legacy Playback"}, | ||
815 | {"HFDAC Left", NULL, "Handsfree Playback"}, | ||
816 | {"HFDAC Right", NULL, "Legacy Playback"}, | ||
817 | {"HFDAC Right", NULL, "Handsfree Playback"}, | ||
818 | |||
819 | {"VIBRA DAC", NULL, "Legacy Playback"}, | ||
820 | {"VIBRA DAC", NULL, "Vibra Playback"}, | ||
821 | |||
822 | /* ADC -> Stream mapping */ | ||
823 | {"ADC Left", NULL, "Legacy Capture"}, | ||
824 | {"ADC Left", NULL, "Capture"}, | ||
825 | {"ADC Right", NULL, "Legacy Capture"}, | ||
826 | {"ADC Right", NULL, "Capture"}, | ||
827 | |||
813 | /* Capture path */ | 828 | /* Capture path */ |
814 | {"Analog Left Capture Route", "Headset Mic", "HSMIC"}, | 829 | {"Analog Left Capture Route", "Headset Mic", "HSMIC"}, |
815 | {"Analog Left Capture Route", "Main Mic", "MAINMIC"}, | 830 | {"Analog Left Capture Route", "Main Mic", "MAINMIC"}, |
@@ -1028,14 +1043,14 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
1028 | { | 1043 | { |
1029 | .name = "twl6040-legacy", | 1044 | .name = "twl6040-legacy", |
1030 | .playback = { | 1045 | .playback = { |
1031 | .stream_name = "Playback", | 1046 | .stream_name = "Legacy Playback", |
1032 | .channels_min = 1, | 1047 | .channels_min = 1, |
1033 | .channels_max = 5, | 1048 | .channels_max = 5, |
1034 | .rates = TWL6040_RATES, | 1049 | .rates = TWL6040_RATES, |
1035 | .formats = TWL6040_FORMATS, | 1050 | .formats = TWL6040_FORMATS, |
1036 | }, | 1051 | }, |
1037 | .capture = { | 1052 | .capture = { |
1038 | .stream_name = "Capture", | 1053 | .stream_name = "Legacy Capture", |
1039 | .channels_min = 1, | 1054 | .channels_min = 1, |
1040 | .channels_max = 2, | 1055 | .channels_max = 2, |
1041 | .rates = TWL6040_RATES, | 1056 | .rates = TWL6040_RATES, |
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c new file mode 100644 index 000000000000..f8d6c31db870 --- /dev/null +++ b/sound/soc/codecs/wm0010.c | |||
@@ -0,0 +1,944 @@ | |||
1 | /* | ||
2 | * wm0010.c -- WM0010 DSP Driver | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Authors: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * Dimitris Papastamos <dp@opensource.wolfsonmicro.com> | ||
8 | * Scott Ling <sl@opensource.wolfsonmicro.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/irqreturn.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/spi/spi.h> | ||
20 | #include <linux/firmware.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/miscdevice.h> | ||
24 | #include <linux/gpio.h> | ||
25 | #include <linux/regulator/consumer.h> | ||
26 | #include <linux/mutex.h> | ||
27 | #include <linux/workqueue.h> | ||
28 | |||
29 | #include <sound/soc.h> | ||
30 | #include <sound/wm0010.h> | ||
31 | |||
32 | #define DEVICE_ID_WM0010 10 | ||
33 | |||
34 | enum dfw_cmd { | ||
35 | DFW_CMD_FUSE = 0x01, | ||
36 | DFW_CMD_CODE_HDR, | ||
37 | DFW_CMD_CODE_DATA, | ||
38 | DFW_CMD_PLL, | ||
39 | DFW_CMD_INFO = 0xff | ||
40 | }; | ||
41 | |||
42 | struct dfw_binrec { | ||
43 | u8 command; | ||
44 | u32 length:24; | ||
45 | u32 address; | ||
46 | uint8_t data[0]; | ||
47 | } __packed; | ||
48 | |||
49 | struct dfw_pllrec { | ||
50 | u8 command; | ||
51 | u32 length:24; | ||
52 | u32 address; | ||
53 | u32 clkctrl1; | ||
54 | u32 clkctrl2; | ||
55 | u32 clkctrl3; | ||
56 | u32 ldetctrl; | ||
57 | u32 uart_div; | ||
58 | u32 spi_div; | ||
59 | } __packed; | ||
60 | |||
61 | static struct pll_clock_map { | ||
62 | int max_sysclk; | ||
63 | int max_pll_spi_speed; | ||
64 | u32 pll_clkctrl1; | ||
65 | } pll_clock_map[] = { /* Dividers */ | ||
66 | { 22000000, 26000000, 0x00201f11 }, /* 2,32,2 */ | ||
67 | { 18000000, 26000000, 0x00203f21 }, /* 2,64,4 */ | ||
68 | { 14000000, 26000000, 0x00202620 }, /* 1,39,4 */ | ||
69 | { 10000000, 22000000, 0x00203120 }, /* 1,50,4 */ | ||
70 | { 6500000, 22000000, 0x00204520 }, /* 1,70,4 */ | ||
71 | { 5500000, 22000000, 0x00103f10 }, /* 1,64,2 */ | ||
72 | }; | ||
73 | |||
74 | enum wm0010_state { | ||
75 | WM0010_POWER_OFF, | ||
76 | WM0010_OUT_OF_RESET, | ||
77 | WM0010_BOOTROM, | ||
78 | WM0010_STAGE2, | ||
79 | WM0010_FIRMWARE, | ||
80 | }; | ||
81 | |||
82 | struct wm0010_priv { | ||
83 | struct snd_soc_codec *codec; | ||
84 | |||
85 | struct mutex lock; | ||
86 | struct device *dev; | ||
87 | |||
88 | struct wm0010_pdata pdata; | ||
89 | |||
90 | int gpio_reset; | ||
91 | int gpio_reset_value; | ||
92 | |||
93 | struct regulator_bulk_data core_supplies[2]; | ||
94 | struct regulator *dbvdd; | ||
95 | |||
96 | int sysclk; | ||
97 | |||
98 | enum wm0010_state state; | ||
99 | bool boot_failed; | ||
100 | int boot_done; | ||
101 | bool ready; | ||
102 | bool pll_running; | ||
103 | int max_spi_freq; | ||
104 | int board_max_spi_speed; | ||
105 | u32 pll_clkctrl1; | ||
106 | |||
107 | spinlock_t irq_lock; | ||
108 | int irq; | ||
109 | |||
110 | struct completion boot_completion; | ||
111 | }; | ||
112 | |||
113 | struct wm0010_spi_msg { | ||
114 | struct spi_message m; | ||
115 | struct spi_transfer t; | ||
116 | u8 *tx_buf; | ||
117 | u8 *rx_buf; | ||
118 | size_t len; | ||
119 | }; | ||
120 | |||
121 | static const struct snd_soc_dapm_widget wm0010_dapm_widgets[] = { | ||
122 | SND_SOC_DAPM_SUPPLY("CLKIN", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
123 | }; | ||
124 | |||
125 | static const struct snd_soc_dapm_route wm0010_dapm_routes[] = { | ||
126 | { "SDI2 Capture", NULL, "SDI1 Playback" }, | ||
127 | { "SDI1 Capture", NULL, "SDI2 Playback" }, | ||
128 | |||
129 | { "SDI1 Capture", NULL, "CLKIN" }, | ||
130 | { "SDI2 Capture", NULL, "CLKIN" }, | ||
131 | { "SDI1 Playback", NULL, "CLKIN" }, | ||
132 | { "SDI2 Playback", NULL, "CLKIN" }, | ||
133 | }; | ||
134 | |||
135 | static const char *wm0010_state_to_str(enum wm0010_state state) | ||
136 | { | ||
137 | const char *state_to_str[] = { | ||
138 | "Power off", | ||
139 | "Out of reset", | ||
140 | "Boot ROM", | ||
141 | "Stage2", | ||
142 | "Firmware" | ||
143 | }; | ||
144 | |||
145 | if (state < 0 || state >= ARRAY_SIZE(state_to_str)) | ||
146 | return "null"; | ||
147 | return state_to_str[state]; | ||
148 | } | ||
149 | |||
150 | /* Called with wm0010->lock held */ | ||
151 | static void wm0010_halt(struct snd_soc_codec *codec) | ||
152 | { | ||
153 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
154 | unsigned long flags; | ||
155 | enum wm0010_state state; | ||
156 | |||
157 | /* Fetch the wm0010 state */ | ||
158 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
159 | state = wm0010->state; | ||
160 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
161 | |||
162 | switch (state) { | ||
163 | case WM0010_POWER_OFF: | ||
164 | /* If there's nothing to do, bail out */ | ||
165 | return; | ||
166 | case WM0010_OUT_OF_RESET: | ||
167 | case WM0010_BOOTROM: | ||
168 | case WM0010_STAGE2: | ||
169 | case WM0010_FIRMWARE: | ||
170 | /* Remember to put chip back into reset */ | ||
171 | gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value); | ||
172 | /* Disable the regulators */ | ||
173 | regulator_disable(wm0010->dbvdd); | ||
174 | regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), | ||
175 | wm0010->core_supplies); | ||
176 | break; | ||
177 | } | ||
178 | |||
179 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
180 | wm0010->state = WM0010_POWER_OFF; | ||
181 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
182 | } | ||
183 | |||
184 | struct wm0010_boot_xfer { | ||
185 | struct list_head list; | ||
186 | struct snd_soc_codec *codec; | ||
187 | struct completion *done; | ||
188 | struct spi_message m; | ||
189 | struct spi_transfer t; | ||
190 | }; | ||
191 | |||
192 | /* Called with wm0010->lock held */ | ||
193 | static void wm0010_mark_boot_failure(struct wm0010_priv *wm0010) | ||
194 | { | ||
195 | enum wm0010_state state; | ||
196 | unsigned long flags; | ||
197 | |||
198 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
199 | state = wm0010->state; | ||
200 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
201 | |||
202 | dev_err(wm0010->dev, "Failed to transition from `%s' state to `%s' state\n", | ||
203 | wm0010_state_to_str(state), wm0010_state_to_str(state + 1)); | ||
204 | |||
205 | wm0010->boot_failed = true; | ||
206 | } | ||
207 | |||
208 | static void wm0010_boot_xfer_complete(void *data) | ||
209 | { | ||
210 | struct wm0010_boot_xfer *xfer = data; | ||
211 | struct snd_soc_codec *codec = xfer->codec; | ||
212 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
213 | u32 *out32 = xfer->t.rx_buf; | ||
214 | int i; | ||
215 | |||
216 | if (xfer->m.status != 0) { | ||
217 | dev_err(codec->dev, "SPI transfer failed: %d\n", | ||
218 | xfer->m.status); | ||
219 | wm0010_mark_boot_failure(wm0010); | ||
220 | if (xfer->done) | ||
221 | complete(xfer->done); | ||
222 | return; | ||
223 | } | ||
224 | |||
225 | for (i = 0; i < xfer->t.len / 4; i++) { | ||
226 | dev_dbg(codec->dev, "%d: %04x\n", i, out32[i]); | ||
227 | |||
228 | switch (be32_to_cpu(out32[i])) { | ||
229 | case 0xe0e0e0e0: | ||
230 | dev_err(codec->dev, | ||
231 | "%d: ROM error reported in stage 2\n", i); | ||
232 | wm0010_mark_boot_failure(wm0010); | ||
233 | break; | ||
234 | |||
235 | case 0x55555555: | ||
236 | if (wm0010->boot_done == 0) | ||
237 | break; | ||
238 | dev_err(codec->dev, | ||
239 | "%d: ROM bootloader running in stage 2\n", i); | ||
240 | wm0010_mark_boot_failure(wm0010); | ||
241 | break; | ||
242 | |||
243 | case 0x0fed0000: | ||
244 | dev_dbg(codec->dev, "Stage2 loader running\n"); | ||
245 | break; | ||
246 | |||
247 | case 0x0fed0007: | ||
248 | dev_dbg(codec->dev, "CODE_HDR packet received\n"); | ||
249 | break; | ||
250 | |||
251 | case 0x0fed0008: | ||
252 | dev_dbg(codec->dev, "CODE_DATA packet received\n"); | ||
253 | break; | ||
254 | |||
255 | case 0x0fed0009: | ||
256 | dev_dbg(codec->dev, "Download complete\n"); | ||
257 | break; | ||
258 | |||
259 | case 0x0fed000c: | ||
260 | dev_dbg(codec->dev, "Application start\n"); | ||
261 | break; | ||
262 | |||
263 | case 0x0fed000e: | ||
264 | dev_dbg(codec->dev, "PLL packet received\n"); | ||
265 | wm0010->pll_running = true; | ||
266 | break; | ||
267 | |||
268 | case 0x0fed0025: | ||
269 | dev_err(codec->dev, "Device reports image too long\n"); | ||
270 | wm0010_mark_boot_failure(wm0010); | ||
271 | break; | ||
272 | |||
273 | case 0x0fed002c: | ||
274 | dev_err(codec->dev, "Device reports bad SPI packet\n"); | ||
275 | wm0010_mark_boot_failure(wm0010); | ||
276 | break; | ||
277 | |||
278 | case 0x0fed0031: | ||
279 | dev_err(codec->dev, "Device reports SPI read overflow\n"); | ||
280 | wm0010_mark_boot_failure(wm0010); | ||
281 | break; | ||
282 | |||
283 | case 0x0fed0032: | ||
284 | dev_err(codec->dev, "Device reports SPI underclock\n"); | ||
285 | wm0010_mark_boot_failure(wm0010); | ||
286 | break; | ||
287 | |||
288 | case 0x0fed0033: | ||
289 | dev_err(codec->dev, "Device reports bad header packet\n"); | ||
290 | wm0010_mark_boot_failure(wm0010); | ||
291 | break; | ||
292 | |||
293 | case 0x0fed0034: | ||
294 | dev_err(codec->dev, "Device reports invalid packet type\n"); | ||
295 | wm0010_mark_boot_failure(wm0010); | ||
296 | break; | ||
297 | |||
298 | case 0x0fed0035: | ||
299 | dev_err(codec->dev, "Device reports data before header error\n"); | ||
300 | wm0010_mark_boot_failure(wm0010); | ||
301 | break; | ||
302 | |||
303 | case 0x0fed0038: | ||
304 | dev_err(codec->dev, "Device reports invalid PLL packet\n"); | ||
305 | break; | ||
306 | |||
307 | case 0x0fed003a: | ||
308 | dev_err(codec->dev, "Device reports packet alignment error\n"); | ||
309 | wm0010_mark_boot_failure(wm0010); | ||
310 | break; | ||
311 | |||
312 | default: | ||
313 | dev_err(codec->dev, "Unrecognised return 0x%x\n", | ||
314 | be32_to_cpu(out32[i])); | ||
315 | wm0010_mark_boot_failure(wm0010); | ||
316 | break; | ||
317 | } | ||
318 | |||
319 | if (wm0010->boot_failed) | ||
320 | break; | ||
321 | } | ||
322 | |||
323 | wm0010->boot_done++; | ||
324 | if (xfer->done) | ||
325 | complete(xfer->done); | ||
326 | } | ||
327 | |||
328 | static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len) | ||
329 | { | ||
330 | int i; | ||
331 | |||
332 | for (i = 0; i < len / 8; i++) | ||
333 | data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i])); | ||
334 | } | ||
335 | |||
336 | static int wm0010_boot(struct snd_soc_codec *codec) | ||
337 | { | ||
338 | struct spi_device *spi = to_spi_device(codec->dev); | ||
339 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
340 | unsigned long flags; | ||
341 | struct list_head xfer_list; | ||
342 | struct wm0010_boot_xfer *xfer; | ||
343 | int ret; | ||
344 | struct completion done; | ||
345 | const struct firmware *fw; | ||
346 | const struct dfw_binrec *rec; | ||
347 | struct spi_message m; | ||
348 | struct spi_transfer t; | ||
349 | struct dfw_pllrec pll_rec; | ||
350 | u32 *img, *p; | ||
351 | u64 *img_swap; | ||
352 | u8 *out; | ||
353 | u32 len, offset; | ||
354 | int i; | ||
355 | |||
356 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
357 | if (wm0010->state != WM0010_POWER_OFF) | ||
358 | dev_warn(wm0010->dev, "DSP already powered up!\n"); | ||
359 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
360 | |||
361 | if (wm0010->sysclk > 26000000) { | ||
362 | dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n"); | ||
363 | ret = -ECANCELED; | ||
364 | goto err; | ||
365 | } | ||
366 | |||
367 | INIT_LIST_HEAD(&xfer_list); | ||
368 | |||
369 | mutex_lock(&wm0010->lock); | ||
370 | wm0010->pll_running = false; | ||
371 | |||
372 | dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq); | ||
373 | |||
374 | ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies), | ||
375 | wm0010->core_supplies); | ||
376 | if (ret != 0) { | ||
377 | dev_err(&spi->dev, "Failed to enable core supplies: %d\n", | ||
378 | ret); | ||
379 | mutex_unlock(&wm0010->lock); | ||
380 | goto err; | ||
381 | } | ||
382 | |||
383 | ret = regulator_enable(wm0010->dbvdd); | ||
384 | if (ret != 0) { | ||
385 | dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret); | ||
386 | goto err_core; | ||
387 | } | ||
388 | |||
389 | /* Release reset */ | ||
390 | gpio_set_value(wm0010->gpio_reset, !wm0010->gpio_reset_value); | ||
391 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
392 | wm0010->state = WM0010_OUT_OF_RESET; | ||
393 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
394 | |||
395 | /* First the bootloader */ | ||
396 | ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev); | ||
397 | if (ret != 0) { | ||
398 | dev_err(codec->dev, "Failed to request stage2 loader: %d\n", | ||
399 | ret); | ||
400 | goto abort; | ||
401 | } | ||
402 | |||
403 | if (!wait_for_completion_timeout(&wm0010->boot_completion, | ||
404 | msecs_to_jiffies(10))) | ||
405 | dev_err(codec->dev, "Failed to get interrupt from DSP\n"); | ||
406 | |||
407 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
408 | wm0010->state = WM0010_BOOTROM; | ||
409 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
410 | |||
411 | dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size); | ||
412 | |||
413 | /* Copy to local buffer first as vmalloc causes problems for dma */ | ||
414 | img = kzalloc(fw->size, GFP_KERNEL); | ||
415 | if (!img) { | ||
416 | dev_err(codec->dev, "Failed to allocate image buffer\n"); | ||
417 | goto abort; | ||
418 | } | ||
419 | |||
420 | out = kzalloc(fw->size, GFP_KERNEL); | ||
421 | if (!out) { | ||
422 | dev_err(codec->dev, "Failed to allocate output buffer\n"); | ||
423 | goto abort; | ||
424 | } | ||
425 | |||
426 | memcpy(img, &fw->data[0], fw->size); | ||
427 | |||
428 | spi_message_init(&m); | ||
429 | memset(&t, 0, sizeof(t)); | ||
430 | t.rx_buf = out; | ||
431 | t.tx_buf = img; | ||
432 | t.len = fw->size; | ||
433 | t.bits_per_word = 8; | ||
434 | t.speed_hz = wm0010->sysclk / 10; | ||
435 | spi_message_add_tail(&t, &m); | ||
436 | |||
437 | dev_dbg(codec->dev, "Starting initial download at %dHz\n", | ||
438 | t.speed_hz); | ||
439 | |||
440 | ret = spi_sync(spi, &m); | ||
441 | if (ret != 0) { | ||
442 | dev_err(codec->dev, "Initial download failed: %d\n", ret); | ||
443 | goto abort; | ||
444 | } | ||
445 | |||
446 | /* Look for errors from the boot ROM */ | ||
447 | for (i = 0; i < fw->size; i++) { | ||
448 | if (out[i] != 0x55) { | ||
449 | ret = -EBUSY; | ||
450 | dev_err(codec->dev, "Boot ROM error: %x in %d\n", | ||
451 | out[i], i); | ||
452 | wm0010_mark_boot_failure(wm0010); | ||
453 | goto abort; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | release_firmware(fw); | ||
458 | kfree(img); | ||
459 | kfree(out); | ||
460 | |||
461 | if (!wait_for_completion_timeout(&wm0010->boot_completion, | ||
462 | msecs_to_jiffies(10))) | ||
463 | dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n"); | ||
464 | |||
465 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
466 | wm0010->state = WM0010_STAGE2; | ||
467 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
468 | |||
469 | /* Only initialise PLL if max_spi_freq initialised */ | ||
470 | if (wm0010->max_spi_freq) { | ||
471 | |||
472 | /* Initialise a PLL record */ | ||
473 | memset(&pll_rec, 0, sizeof(pll_rec)); | ||
474 | pll_rec.command = DFW_CMD_PLL; | ||
475 | pll_rec.length = (sizeof(pll_rec) - 8); | ||
476 | |||
477 | /* On wm0010 only the CLKCTRL1 value is used */ | ||
478 | pll_rec.clkctrl1 = wm0010->pll_clkctrl1; | ||
479 | |||
480 | len = pll_rec.length + 8; | ||
481 | out = kzalloc(len, GFP_KERNEL); | ||
482 | if (!out) { | ||
483 | dev_err(codec->dev, | ||
484 | "Failed to allocate RX buffer\n"); | ||
485 | goto abort; | ||
486 | } | ||
487 | |||
488 | img_swap = kzalloc(len, GFP_KERNEL); | ||
489 | if (!img_swap) { | ||
490 | dev_err(codec->dev, | ||
491 | "Failed to allocate image buffer\n"); | ||
492 | goto abort; | ||
493 | } | ||
494 | |||
495 | /* We need to re-order for 0010 */ | ||
496 | byte_swap_64((u64 *)&pll_rec, img_swap, len); | ||
497 | |||
498 | spi_message_init(&m); | ||
499 | memset(&t, 0, sizeof(t)); | ||
500 | t.rx_buf = out; | ||
501 | t.tx_buf = img_swap; | ||
502 | t.len = len; | ||
503 | t.bits_per_word = 8; | ||
504 | t.speed_hz = wm0010->sysclk / 6; | ||
505 | spi_message_add_tail(&t, &m); | ||
506 | |||
507 | ret = spi_sync(spi, &m); | ||
508 | if (ret != 0) { | ||
509 | dev_err(codec->dev, "First PLL write failed: %d\n", ret); | ||
510 | goto abort; | ||
511 | } | ||
512 | |||
513 | /* Use a second send of the message to get the return status */ | ||
514 | ret = spi_sync(spi, &m); | ||
515 | if (ret != 0) { | ||
516 | dev_err(codec->dev, "Second PLL write failed: %d\n", ret); | ||
517 | goto abort; | ||
518 | } | ||
519 | |||
520 | p = (u32 *)out; | ||
521 | |||
522 | /* Look for PLL active code from the DSP */ | ||
523 | for (i = 0; i < len / 4; i++) { | ||
524 | if (*p == 0x0e00ed0f) { | ||
525 | dev_dbg(codec->dev, "PLL packet received\n"); | ||
526 | wm0010->pll_running = true; | ||
527 | break; | ||
528 | } | ||
529 | p++; | ||
530 | } | ||
531 | |||
532 | kfree(img_swap); | ||
533 | kfree(out); | ||
534 | } else | ||
535 | dev_dbg(codec->dev, "Not enabling DSP PLL."); | ||
536 | |||
537 | ret = request_firmware(&fw, "wm0010.dfw", codec->dev); | ||
538 | if (ret != 0) { | ||
539 | dev_err(codec->dev, "Failed to request application: %d\n", | ||
540 | ret); | ||
541 | goto abort; | ||
542 | } | ||
543 | |||
544 | rec = (const struct dfw_binrec *)fw->data; | ||
545 | offset = 0; | ||
546 | wm0010->boot_done = 0; | ||
547 | wm0010->boot_failed = false; | ||
548 | BUG_ON(!list_empty(&xfer_list)); | ||
549 | init_completion(&done); | ||
550 | |||
551 | /* First record should be INFO */ | ||
552 | if (rec->command != DFW_CMD_INFO) { | ||
553 | dev_err(codec->dev, "First record not INFO\r\n"); | ||
554 | goto abort; | ||
555 | } | ||
556 | |||
557 | /* Check it's a 0010 file */ | ||
558 | if (rec->data[0] != DEVICE_ID_WM0010) { | ||
559 | dev_err(codec->dev, "Not a WM0010 firmware file.\r\n"); | ||
560 | goto abort; | ||
561 | } | ||
562 | |||
563 | /* Skip the info record as we don't need to send it */ | ||
564 | offset += ((rec->length) + 8); | ||
565 | rec = (void *)&rec->data[rec->length]; | ||
566 | |||
567 | while (offset < fw->size) { | ||
568 | dev_dbg(codec->dev, | ||
569 | "Packet: command %d, data length = 0x%x\r\n", | ||
570 | rec->command, rec->length); | ||
571 | len = rec->length + 8; | ||
572 | |||
573 | out = kzalloc(len, GFP_KERNEL); | ||
574 | if (!out) { | ||
575 | dev_err(codec->dev, | ||
576 | "Failed to allocate RX buffer\n"); | ||
577 | goto abort; | ||
578 | } | ||
579 | |||
580 | img_swap = kzalloc(len, GFP_KERNEL); | ||
581 | if (!img_swap) { | ||
582 | dev_err(codec->dev, | ||
583 | "Failed to allocate image buffer\n"); | ||
584 | goto abort; | ||
585 | } | ||
586 | |||
587 | /* We need to re-order for 0010 */ | ||
588 | byte_swap_64((u64 *)&rec->command, img_swap, len); | ||
589 | |||
590 | xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); | ||
591 | if (!xfer) { | ||
592 | dev_err(codec->dev, "Failed to allocate xfer\n"); | ||
593 | goto abort; | ||
594 | } | ||
595 | |||
596 | xfer->codec = codec; | ||
597 | list_add_tail(&xfer->list, &xfer_list); | ||
598 | |||
599 | spi_message_init(&xfer->m); | ||
600 | xfer->m.complete = wm0010_boot_xfer_complete; | ||
601 | xfer->m.context = xfer; | ||
602 | xfer->t.tx_buf = img_swap; | ||
603 | xfer->t.rx_buf = out; | ||
604 | xfer->t.len = len; | ||
605 | xfer->t.bits_per_word = 8; | ||
606 | |||
607 | if (!wm0010->pll_running) { | ||
608 | xfer->t.speed_hz = wm0010->sysclk / 6; | ||
609 | } else { | ||
610 | xfer->t.speed_hz = wm0010->max_spi_freq; | ||
611 | |||
612 | if (wm0010->board_max_spi_speed && | ||
613 | (wm0010->board_max_spi_speed < wm0010->max_spi_freq)) | ||
614 | xfer->t.speed_hz = wm0010->board_max_spi_speed; | ||
615 | } | ||
616 | |||
617 | /* Store max usable spi frequency for later use */ | ||
618 | wm0010->max_spi_freq = xfer->t.speed_hz; | ||
619 | |||
620 | spi_message_add_tail(&xfer->t, &xfer->m); | ||
621 | |||
622 | offset += ((rec->length) + 8); | ||
623 | rec = (void *)&rec->data[rec->length]; | ||
624 | |||
625 | if (offset >= fw->size) { | ||
626 | dev_dbg(codec->dev, "All transfers scheduled\n"); | ||
627 | xfer->done = &done; | ||
628 | } | ||
629 | |||
630 | ret = spi_async(spi, &xfer->m); | ||
631 | if (ret != 0) { | ||
632 | dev_err(codec->dev, "Write failed: %d\n", ret); | ||
633 | goto abort; | ||
634 | } | ||
635 | |||
636 | if (wm0010->boot_failed) | ||
637 | goto abort; | ||
638 | } | ||
639 | |||
640 | wait_for_completion(&done); | ||
641 | |||
642 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
643 | wm0010->state = WM0010_FIRMWARE; | ||
644 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
645 | |||
646 | mutex_unlock(&wm0010->lock); | ||
647 | |||
648 | release_firmware(fw); | ||
649 | |||
650 | while (!list_empty(&xfer_list)) { | ||
651 | xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer, | ||
652 | list); | ||
653 | kfree(xfer->t.rx_buf); | ||
654 | kfree(xfer->t.tx_buf); | ||
655 | list_del(&xfer->list); | ||
656 | kfree(xfer); | ||
657 | } | ||
658 | |||
659 | return 0; | ||
660 | |||
661 | abort: | ||
662 | /* Put the chip back into reset */ | ||
663 | wm0010_halt(codec); | ||
664 | mutex_unlock(&wm0010->lock); | ||
665 | return ret; | ||
666 | |||
667 | err_core: | ||
668 | mutex_unlock(&wm0010->lock); | ||
669 | regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), | ||
670 | wm0010->core_supplies); | ||
671 | err: | ||
672 | return ret; | ||
673 | } | ||
674 | |||
675 | static int wm0010_set_bias_level(struct snd_soc_codec *codec, | ||
676 | enum snd_soc_bias_level level) | ||
677 | { | ||
678 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
679 | |||
680 | switch (level) { | ||
681 | case SND_SOC_BIAS_ON: | ||
682 | if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) | ||
683 | wm0010_boot(codec); | ||
684 | break; | ||
685 | case SND_SOC_BIAS_PREPARE: | ||
686 | break; | ||
687 | case SND_SOC_BIAS_STANDBY: | ||
688 | if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) { | ||
689 | mutex_lock(&wm0010->lock); | ||
690 | wm0010_halt(codec); | ||
691 | mutex_unlock(&wm0010->lock); | ||
692 | } | ||
693 | break; | ||
694 | case SND_SOC_BIAS_OFF: | ||
695 | break; | ||
696 | } | ||
697 | |||
698 | codec->dapm.bias_level = level; | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | static int wm0010_set_sysclk(struct snd_soc_codec *codec, int source, | ||
704 | int clk_id, unsigned int freq, int dir) | ||
705 | { | ||
706 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
707 | unsigned int i; | ||
708 | |||
709 | wm0010->sysclk = freq; | ||
710 | |||
711 | if (freq < pll_clock_map[ARRAY_SIZE(pll_clock_map)-1].max_sysclk) { | ||
712 | wm0010->max_spi_freq = 0; | ||
713 | } else { | ||
714 | for (i = 0; i < ARRAY_SIZE(pll_clock_map); i++) | ||
715 | if (freq >= pll_clock_map[i].max_sysclk) | ||
716 | break; | ||
717 | |||
718 | wm0010->max_spi_freq = pll_clock_map[i].max_pll_spi_speed; | ||
719 | wm0010->pll_clkctrl1 = pll_clock_map[i].pll_clkctrl1; | ||
720 | } | ||
721 | |||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | static int wm0010_probe(struct snd_soc_codec *codec); | ||
726 | |||
727 | static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { | ||
728 | .probe = wm0010_probe, | ||
729 | .set_bias_level = wm0010_set_bias_level, | ||
730 | .set_sysclk = wm0010_set_sysclk, | ||
731 | .idle_bias_off = true, | ||
732 | |||
733 | .dapm_widgets = wm0010_dapm_widgets, | ||
734 | .num_dapm_widgets = ARRAY_SIZE(wm0010_dapm_widgets), | ||
735 | .dapm_routes = wm0010_dapm_routes, | ||
736 | .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), | ||
737 | }; | ||
738 | |||
739 | #define WM0010_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | ||
740 | #define WM0010_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
741 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\ | ||
742 | SNDRV_PCM_FMTBIT_S32_LE) | ||
743 | |||
744 | static struct snd_soc_dai_driver wm0010_dai[] = { | ||
745 | { | ||
746 | .name = "wm0010-sdi1", | ||
747 | .playback = { | ||
748 | .stream_name = "SDI1 Playback", | ||
749 | .channels_min = 1, | ||
750 | .channels_max = 2, | ||
751 | .rates = WM0010_RATES, | ||
752 | .formats = WM0010_FORMATS, | ||
753 | }, | ||
754 | .capture = { | ||
755 | .stream_name = "SDI1 Capture", | ||
756 | .channels_min = 1, | ||
757 | .channels_max = 2, | ||
758 | .rates = WM0010_RATES, | ||
759 | .formats = WM0010_FORMATS, | ||
760 | }, | ||
761 | }, | ||
762 | { | ||
763 | .name = "wm0010-sdi2", | ||
764 | .playback = { | ||
765 | .stream_name = "SDI2 Playback", | ||
766 | .channels_min = 1, | ||
767 | .channels_max = 2, | ||
768 | .rates = WM0010_RATES, | ||
769 | .formats = WM0010_FORMATS, | ||
770 | }, | ||
771 | .capture = { | ||
772 | .stream_name = "SDI2 Capture", | ||
773 | .channels_min = 1, | ||
774 | .channels_max = 2, | ||
775 | .rates = WM0010_RATES, | ||
776 | .formats = WM0010_FORMATS, | ||
777 | }, | ||
778 | }, | ||
779 | }; | ||
780 | |||
781 | static irqreturn_t wm0010_irq(int irq, void *data) | ||
782 | { | ||
783 | struct wm0010_priv *wm0010 = data; | ||
784 | |||
785 | switch (wm0010->state) { | ||
786 | case WM0010_POWER_OFF: | ||
787 | case WM0010_OUT_OF_RESET: | ||
788 | case WM0010_BOOTROM: | ||
789 | case WM0010_STAGE2: | ||
790 | spin_lock(&wm0010->irq_lock); | ||
791 | complete(&wm0010->boot_completion); | ||
792 | spin_unlock(&wm0010->irq_lock); | ||
793 | return IRQ_HANDLED; | ||
794 | default: | ||
795 | return IRQ_NONE; | ||
796 | } | ||
797 | |||
798 | return IRQ_NONE; | ||
799 | } | ||
800 | |||
801 | static int wm0010_probe(struct snd_soc_codec *codec) | ||
802 | { | ||
803 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
804 | |||
805 | wm0010->codec = codec; | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static int __devinit wm0010_spi_probe(struct spi_device *spi) | ||
811 | { | ||
812 | unsigned long flags; | ||
813 | unsigned long gpio_flags; | ||
814 | int ret; | ||
815 | int trigger; | ||
816 | int irq; | ||
817 | struct wm0010_priv *wm0010; | ||
818 | |||
819 | wm0010 = devm_kzalloc(&spi->dev, sizeof(*wm0010), | ||
820 | GFP_KERNEL); | ||
821 | if (!wm0010) | ||
822 | return -ENOMEM; | ||
823 | |||
824 | mutex_init(&wm0010->lock); | ||
825 | spin_lock_init(&wm0010->irq_lock); | ||
826 | |||
827 | spi_set_drvdata(spi, wm0010); | ||
828 | wm0010->dev = &spi->dev; | ||
829 | |||
830 | if (dev_get_platdata(&spi->dev)) | ||
831 | memcpy(&wm0010->pdata, dev_get_platdata(&spi->dev), | ||
832 | sizeof(wm0010->pdata)); | ||
833 | |||
834 | init_completion(&wm0010->boot_completion); | ||
835 | |||
836 | wm0010->core_supplies[0].supply = "AVDD"; | ||
837 | wm0010->core_supplies[1].supply = "DCVDD"; | ||
838 | ret = devm_regulator_bulk_get(wm0010->dev, ARRAY_SIZE(wm0010->core_supplies), | ||
839 | wm0010->core_supplies); | ||
840 | if (ret != 0) { | ||
841 | dev_err(wm0010->dev, "Failed to obtain core supplies: %d\n", | ||
842 | ret); | ||
843 | return ret; | ||
844 | } | ||
845 | |||
846 | wm0010->dbvdd = devm_regulator_get(wm0010->dev, "DBVDD"); | ||
847 | if (IS_ERR(wm0010->dbvdd)) { | ||
848 | ret = PTR_ERR(wm0010->dbvdd); | ||
849 | dev_err(wm0010->dev, "Failed to obtain DBVDD: %d\n", ret); | ||
850 | return ret; | ||
851 | } | ||
852 | |||
853 | if (wm0010->pdata.gpio_reset) { | ||
854 | wm0010->gpio_reset = wm0010->pdata.gpio_reset; | ||
855 | |||
856 | if (wm0010->pdata.reset_active_high) | ||
857 | wm0010->gpio_reset_value = 1; | ||
858 | else | ||
859 | wm0010->gpio_reset_value = 0; | ||
860 | |||
861 | if (wm0010->gpio_reset_value) | ||
862 | gpio_flags = GPIOF_OUT_INIT_HIGH; | ||
863 | else | ||
864 | gpio_flags = GPIOF_OUT_INIT_LOW; | ||
865 | |||
866 | ret = devm_gpio_request_one(wm0010->dev, wm0010->gpio_reset, | ||
867 | gpio_flags, "wm0010 reset"); | ||
868 | if (ret < 0) { | ||
869 | dev_err(wm0010->dev, | ||
870 | "Failed to request GPIO for DSP reset: %d\n", | ||
871 | ret); | ||
872 | return ret; | ||
873 | } | ||
874 | } else { | ||
875 | dev_err(wm0010->dev, "No reset GPIO configured\n"); | ||
876 | return -EINVAL; | ||
877 | } | ||
878 | |||
879 | irq = spi->irq; | ||
880 | if (wm0010->pdata.irq_flags) | ||
881 | trigger = wm0010->pdata.irq_flags; | ||
882 | else | ||
883 | trigger = IRQF_TRIGGER_FALLING; | ||
884 | trigger |= IRQF_ONESHOT; | ||
885 | |||
886 | ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger | IRQF_ONESHOT, | ||
887 | "wm0010", wm0010); | ||
888 | if (ret) { | ||
889 | dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", | ||
890 | irq, ret); | ||
891 | return ret; | ||
892 | } | ||
893 | wm0010->irq = irq; | ||
894 | |||
895 | if (spi->max_speed_hz) | ||
896 | wm0010->board_max_spi_speed = spi->max_speed_hz; | ||
897 | else | ||
898 | wm0010->board_max_spi_speed = 0; | ||
899 | |||
900 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
901 | wm0010->state = WM0010_POWER_OFF; | ||
902 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
903 | |||
904 | ret = snd_soc_register_codec(&spi->dev, | ||
905 | &soc_codec_dev_wm0010, wm0010_dai, | ||
906 | ARRAY_SIZE(wm0010_dai)); | ||
907 | if (ret < 0) | ||
908 | return ret; | ||
909 | |||
910 | return 0; | ||
911 | } | ||
912 | |||
913 | static int __devexit wm0010_spi_remove(struct spi_device *spi) | ||
914 | { | ||
915 | struct wm0010_priv *wm0010 = spi_get_drvdata(spi); | ||
916 | |||
917 | snd_soc_unregister_codec(&spi->dev); | ||
918 | |||
919 | if (wm0010->gpio_reset) { | ||
920 | /* Remember to put chip back into reset */ | ||
921 | gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value); | ||
922 | } | ||
923 | |||
924 | if (wm0010->irq) | ||
925 | free_irq(wm0010->irq, wm0010); | ||
926 | |||
927 | return 0; | ||
928 | } | ||
929 | |||
930 | static struct spi_driver wm0010_spi_driver = { | ||
931 | .driver = { | ||
932 | .name = "wm0010", | ||
933 | .bus = &spi_bus_type, | ||
934 | .owner = THIS_MODULE, | ||
935 | }, | ||
936 | .probe = wm0010_spi_probe, | ||
937 | .remove = __devexit_p(wm0010_spi_remove), | ||
938 | }; | ||
939 | |||
940 | module_spi_driver(wm0010_spi_driver); | ||
941 | |||
942 | MODULE_DESCRIPTION("ASoC WM0010 driver"); | ||
943 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
944 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 3fd5b29dc933..b723e910fcdc 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/i2c.h> | 31 | #include <linux/i2c.h> |
32 | #include <linux/regmap.h> | 32 | #include <linux/regmap.h> |
33 | #include <linux/debugfs.h> | 33 | #include <linux/debugfs.h> |
34 | #include <linux/regulator/consumer.h> | ||
34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
35 | #include <sound/core.h> | 36 | #include <sound/core.h> |
36 | #include <sound/pcm.h> | 37 | #include <sound/pcm.h> |
@@ -43,6 +44,14 @@ | |||
43 | 44 | ||
44 | #include "wm2000.h" | 45 | #include "wm2000.h" |
45 | 46 | ||
47 | #define WM2000_NUM_SUPPLIES 3 | ||
48 | |||
49 | static const char *wm2000_supplies[WM2000_NUM_SUPPLIES] = { | ||
50 | "SPKVDD", | ||
51 | "DBVDD", | ||
52 | "DCVDD", | ||
53 | }; | ||
54 | |||
46 | enum wm2000_anc_mode { | 55 | enum wm2000_anc_mode { |
47 | ANC_ACTIVE = 0, | 56 | ANC_ACTIVE = 0, |
48 | ANC_BYPASS = 1, | 57 | ANC_BYPASS = 1, |
@@ -54,6 +63,8 @@ struct wm2000_priv { | |||
54 | struct i2c_client *i2c; | 63 | struct i2c_client *i2c; |
55 | struct regmap *regmap; | 64 | struct regmap *regmap; |
56 | 65 | ||
66 | struct regulator_bulk_data supplies[WM2000_NUM_SUPPLIES]; | ||
67 | |||
57 | enum wm2000_anc_mode anc_mode; | 68 | enum wm2000_anc_mode anc_mode; |
58 | 69 | ||
59 | unsigned int anc_active:1; | 70 | unsigned int anc_active:1; |
@@ -126,6 +137,12 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
126 | 137 | ||
127 | dev_dbg(&i2c->dev, "Beginning power up\n"); | 138 | dev_dbg(&i2c->dev, "Beginning power up\n"); |
128 | 139 | ||
140 | ret = regulator_bulk_enable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
141 | if (ret != 0) { | ||
142 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | ||
143 | return ret; | ||
144 | } | ||
145 | |||
129 | if (!wm2000->mclk_div) { | 146 | if (!wm2000->mclk_div) { |
130 | dev_dbg(&i2c->dev, "Disabling MCLK divider\n"); | 147 | dev_dbg(&i2c->dev, "Disabling MCLK divider\n"); |
131 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, | 148 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, |
@@ -143,12 +160,14 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
143 | if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, | 160 | if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, |
144 | WM2000_ANC_ENG_IDLE)) { | 161 | WM2000_ANC_ENG_IDLE)) { |
145 | dev_err(&i2c->dev, "ANC engine failed to reset\n"); | 162 | dev_err(&i2c->dev, "ANC engine failed to reset\n"); |
163 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
146 | return -ETIMEDOUT; | 164 | return -ETIMEDOUT; |
147 | } | 165 | } |
148 | 166 | ||
149 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | 167 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, |
150 | WM2000_STATUS_BOOT_COMPLETE)) { | 168 | WM2000_STATUS_BOOT_COMPLETE)) { |
151 | dev_err(&i2c->dev, "ANC engine failed to initialise\n"); | 169 | dev_err(&i2c->dev, "ANC engine failed to initialise\n"); |
170 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
152 | return -ETIMEDOUT; | 171 | return -ETIMEDOUT; |
153 | } | 172 | } |
154 | 173 | ||
@@ -163,11 +182,13 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
163 | wm2000->anc_download_size); | 182 | wm2000->anc_download_size); |
164 | if (ret < 0) { | 183 | if (ret < 0) { |
165 | dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret); | 184 | dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret); |
185 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
166 | return ret; | 186 | return ret; |
167 | } | 187 | } |
168 | if (ret != wm2000->anc_download_size) { | 188 | if (ret != wm2000->anc_download_size) { |
169 | dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n", | 189 | dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n", |
170 | ret, wm2000->anc_download_size); | 190 | ret, wm2000->anc_download_size); |
191 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
171 | return -EIO; | 192 | return -EIO; |
172 | } | 193 | } |
173 | 194 | ||
@@ -201,6 +222,7 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
201 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | 222 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, |
202 | WM2000_STATUS_MOUSE_ACTIVE)) { | 223 | WM2000_STATUS_MOUSE_ACTIVE)) { |
203 | dev_err(&i2c->dev, "Timed out waiting for device\n"); | 224 | dev_err(&i2c->dev, "Timed out waiting for device\n"); |
225 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
204 | return -ETIMEDOUT; | 226 | return -ETIMEDOUT; |
205 | } | 227 | } |
206 | 228 | ||
@@ -238,6 +260,8 @@ static int wm2000_power_down(struct i2c_client *i2c, int analogue) | |||
238 | return -ETIMEDOUT; | 260 | return -ETIMEDOUT; |
239 | } | 261 | } |
240 | 262 | ||
263 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
264 | |||
241 | dev_dbg(&i2c->dev, "powered off\n"); | 265 | dev_dbg(&i2c->dev, "powered off\n"); |
242 | wm2000->anc_mode = ANC_OFF; | 266 | wm2000->anc_mode = ANC_OFF; |
243 | 267 | ||
@@ -747,7 +771,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
747 | struct wm2000_platform_data *pdata; | 771 | struct wm2000_platform_data *pdata; |
748 | const char *filename; | 772 | const char *filename; |
749 | const struct firmware *fw = NULL; | 773 | const struct firmware *fw = NULL; |
750 | int ret; | 774 | int ret, i; |
751 | int reg; | 775 | int reg; |
752 | u16 id; | 776 | u16 id; |
753 | 777 | ||
@@ -760,7 +784,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
760 | 784 | ||
761 | dev_set_drvdata(&i2c->dev, wm2000); | 785 | dev_set_drvdata(&i2c->dev, wm2000); |
762 | 786 | ||
763 | wm2000->regmap = regmap_init_i2c(i2c, &wm2000_regmap); | 787 | wm2000->regmap = devm_regmap_init_i2c(i2c, &wm2000_regmap); |
764 | if (IS_ERR(wm2000->regmap)) { | 788 | if (IS_ERR(wm2000->regmap)) { |
765 | ret = PTR_ERR(wm2000->regmap); | 789 | ret = PTR_ERR(wm2000->regmap); |
766 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 790 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
@@ -768,6 +792,22 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
768 | goto out; | 792 | goto out; |
769 | } | 793 | } |
770 | 794 | ||
795 | for (i = 0; i < WM2000_NUM_SUPPLIES; i++) | ||
796 | wm2000->supplies[i].supply = wm2000_supplies[i]; | ||
797 | |||
798 | ret = devm_regulator_bulk_get(&i2c->dev, WM2000_NUM_SUPPLIES, | ||
799 | wm2000->supplies); | ||
800 | if (ret != 0) { | ||
801 | dev_err(&i2c->dev, "Failed to get supplies: %d\n", ret); | ||
802 | return ret; | ||
803 | } | ||
804 | |||
805 | ret = regulator_bulk_enable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
806 | if (ret != 0) { | ||
807 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | ||
808 | return ret; | ||
809 | } | ||
810 | |||
771 | /* Verify that this is a WM2000 */ | 811 | /* Verify that this is a WM2000 */ |
772 | reg = wm2000_read(i2c, WM2000_REG_ID1); | 812 | reg = wm2000_read(i2c, WM2000_REG_ID1); |
773 | id = reg << 8; | 813 | id = reg << 8; |
@@ -777,7 +817,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
777 | if (id != 0x2000) { | 817 | if (id != 0x2000) { |
778 | dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id); | 818 | dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id); |
779 | ret = -ENODEV; | 819 | ret = -ENODEV; |
780 | goto out_regmap_exit; | 820 | goto err_supplies; |
781 | } | 821 | } |
782 | 822 | ||
783 | reg = wm2000_read(i2c, WM2000_REG_REVISON); | 823 | reg = wm2000_read(i2c, WM2000_REG_REVISON); |
@@ -796,7 +836,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
796 | ret = request_firmware(&fw, filename, &i2c->dev); | 836 | ret = request_firmware(&fw, filename, &i2c->dev); |
797 | if (ret != 0) { | 837 | if (ret != 0) { |
798 | dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret); | 838 | dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret); |
799 | goto out_regmap_exit; | 839 | goto err_supplies; |
800 | } | 840 | } |
801 | 841 | ||
802 | /* Pre-cook the concatenation of the register address onto the image */ | 842 | /* Pre-cook the concatenation of the register address onto the image */ |
@@ -807,7 +847,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
807 | if (wm2000->anc_download == NULL) { | 847 | if (wm2000->anc_download == NULL) { |
808 | dev_err(&i2c->dev, "Out of memory\n"); | 848 | dev_err(&i2c->dev, "Out of memory\n"); |
809 | ret = -ENOMEM; | 849 | ret = -ENOMEM; |
810 | goto out_regmap_exit; | 850 | goto err_supplies; |
811 | } | 851 | } |
812 | 852 | ||
813 | wm2000->anc_download[0] = 0x80; | 853 | wm2000->anc_download[0] = 0x80; |
@@ -822,11 +862,10 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
822 | wm2000_reset(wm2000); | 862 | wm2000_reset(wm2000); |
823 | 863 | ||
824 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0); | 864 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0); |
825 | if (!ret) | ||
826 | goto out; | ||
827 | 865 | ||
828 | out_regmap_exit: | 866 | err_supplies: |
829 | regmap_exit(wm2000->regmap); | 867 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); |
868 | |||
830 | out: | 869 | out: |
831 | release_firmware(fw); | 870 | release_firmware(fw); |
832 | return ret; | 871 | return ret; |
@@ -834,10 +873,7 @@ out: | |||
834 | 873 | ||
835 | static __devexit int wm2000_i2c_remove(struct i2c_client *i2c) | 874 | static __devexit int wm2000_i2c_remove(struct i2c_client *i2c) |
836 | { | 875 | { |
837 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
838 | |||
839 | snd_soc_unregister_codec(&i2c->dev); | 876 | snd_soc_unregister_codec(&i2c->dev); |
840 | regmap_exit(wm2000->regmap); | ||
841 | 877 | ||
842 | return 0; | 878 | return 0; |
843 | } | 879 | } |
@@ -858,17 +894,7 @@ static struct i2c_driver wm2000_i2c_driver = { | |||
858 | .id_table = wm2000_i2c_id, | 894 | .id_table = wm2000_i2c_id, |
859 | }; | 895 | }; |
860 | 896 | ||
861 | static int __init wm2000_init(void) | 897 | module_i2c_driver(wm2000_i2c_driver); |
862 | { | ||
863 | return i2c_add_driver(&wm2000_i2c_driver); | ||
864 | } | ||
865 | module_init(wm2000_init); | ||
866 | |||
867 | static void __exit wm2000_exit(void) | ||
868 | { | ||
869 | i2c_del_driver(&wm2000_i2c_driver); | ||
870 | } | ||
871 | module_exit(wm2000_exit); | ||
872 | 898 | ||
873 | MODULE_DESCRIPTION("ASoC WM2000 driver"); | 899 | MODULE_DESCRIPTION("ASoC WM2000 driver"); |
874 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>"); | 900 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>"); |
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 32682c1b7cde..efa93dbb0191 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c | |||
@@ -1117,8 +1117,8 @@ SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT, | |||
1117 | 0, NULL, 0), | 1117 | 0, NULL, 0), |
1118 | SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT, | 1118 | SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT, |
1119 | 0, NULL, 0), | 1119 | 0, NULL, 0), |
1120 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | 1120 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), |
1121 | SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20), | 1121 | SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20, 0), |
1122 | 1122 | ||
1123 | SND_SOC_DAPM_INPUT("IN1L"), | 1123 | SND_SOC_DAPM_INPUT("IN1L"), |
1124 | SND_SOC_DAPM_INPUT("IN1R"), | 1124 | SND_SOC_DAPM_INPUT("IN1R"), |
@@ -2270,17 +2270,7 @@ static struct i2c_driver wm2200_i2c_driver = { | |||
2270 | .id_table = wm2200_i2c_id, | 2270 | .id_table = wm2200_i2c_id, |
2271 | }; | 2271 | }; |
2272 | 2272 | ||
2273 | static int __init wm2200_modinit(void) | 2273 | module_i2c_driver(wm2200_i2c_driver); |
2274 | { | ||
2275 | return i2c_add_driver(&wm2200_i2c_driver); | ||
2276 | } | ||
2277 | module_init(wm2200_modinit); | ||
2278 | |||
2279 | static void __exit wm2200_exit(void) | ||
2280 | { | ||
2281 | i2c_del_driver(&wm2200_i2c_driver); | ||
2282 | } | ||
2283 | module_exit(wm2200_exit); | ||
2284 | 2274 | ||
2285 | MODULE_DESCRIPTION("ASoC WM2200 driver"); | 2275 | MODULE_DESCRIPTION("ASoC WM2200 driver"); |
2286 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 2276 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index f4817292ef45..4da1b92b22c2 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c | |||
@@ -848,9 +848,9 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0, | |||
848 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT, | 848 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT, |
849 | 0, NULL, 0), | 849 | 0, NULL, 0), |
850 | 850 | ||
851 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | 851 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), |
852 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | 852 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), |
853 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | 853 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), |
854 | 854 | ||
855 | SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0, | 855 | SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0, |
856 | NULL, 0), | 856 | NULL, 0), |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index e33d327396ad..4a2db4e10885 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -274,18 +274,43 @@ ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | |||
274 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 274 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
275 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | 275 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); |
276 | 276 | ||
277 | |||
278 | static const char *wm5102_aec_loopback_texts[] = { | ||
279 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT", | ||
280 | "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", | ||
281 | }; | ||
282 | |||
283 | static const unsigned int wm5102_aec_loopback_values[] = { | ||
284 | 0, 1, 2, 3, 4, 6, 7, 8, 9, | ||
285 | }; | ||
286 | |||
287 | static const struct soc_enum wm5102_aec_loopback = | ||
288 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, | ||
289 | ARIZONA_AEC_LOOPBACK_SRC_SHIFT, | ||
290 | ARIZONA_AEC_LOOPBACK_SRC_MASK, | ||
291 | ARRAY_SIZE(wm5102_aec_loopback_texts), | ||
292 | wm5102_aec_loopback_texts, | ||
293 | wm5102_aec_loopback_values); | ||
294 | |||
295 | static const struct snd_kcontrol_new wm5102_aec_loopback_mux = | ||
296 | SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5102_aec_loopback); | ||
297 | |||
277 | static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { | 298 | static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { |
278 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | 299 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, |
279 | 0, NULL, 0), | 300 | 0, NULL, 0), |
280 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | 301 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, |
281 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | 302 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), |
282 | 303 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, | |
283 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | 304 | ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0), |
284 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | 305 | SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, |
285 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | 306 | ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), |
286 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), | 307 | |
287 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), | 308 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), |
288 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), | 309 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), |
310 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), | ||
311 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, 0), | ||
312 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), | ||
313 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), | ||
289 | 314 | ||
290 | SND_SOC_DAPM_SIGGEN("TONE"), | 315 | SND_SOC_DAPM_SIGGEN("TONE"), |
291 | SND_SOC_DAPM_SIGGEN("NOISE"), | 316 | SND_SOC_DAPM_SIGGEN("NOISE"), |
@@ -421,6 +446,9 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, | |||
421 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | 446 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, |
422 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), | 447 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), |
423 | 448 | ||
449 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | ||
450 | ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux), | ||
451 | |||
424 | SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, | 452 | SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, |
425 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 453 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
426 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 454 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
@@ -516,6 +544,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"), | |||
516 | { name, "Noise Generator", "Noise Generator" }, \ | 544 | { name, "Noise Generator", "Noise Generator" }, \ |
517 | { name, "Tone Generator 1", "Tone Generator 1" }, \ | 545 | { name, "Tone Generator 1", "Tone Generator 1" }, \ |
518 | { name, "Tone Generator 2", "Tone Generator 2" }, \ | 546 | { name, "Tone Generator 2", "Tone Generator 2" }, \ |
547 | { name, "AEC", "AEC Loopback" }, \ | ||
519 | { name, "IN1L", "IN1L PGA" }, \ | 548 | { name, "IN1L", "IN1L PGA" }, \ |
520 | { name, "IN1R", "IN1R PGA" }, \ | 549 | { name, "IN1R", "IN1R PGA" }, \ |
521 | { name, "IN2L", "IN2L PGA" }, \ | 550 | { name, "IN2L", "IN2L PGA" }, \ |
@@ -681,21 +710,30 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |||
681 | ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), | 710 | ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), |
682 | ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), | 711 | ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), |
683 | 712 | ||
713 | { "AEC Loopback", "HPOUT1L", "OUT1L" }, | ||
714 | { "AEC Loopback", "HPOUT1R", "OUT1R" }, | ||
684 | { "HPOUT1L", NULL, "OUT1L" }, | 715 | { "HPOUT1L", NULL, "OUT1L" }, |
685 | { "HPOUT1R", NULL, "OUT1R" }, | 716 | { "HPOUT1R", NULL, "OUT1R" }, |
686 | 717 | ||
718 | { "AEC Loopback", "HPOUT2L", "OUT2L" }, | ||
719 | { "AEC Loopback", "HPOUT2R", "OUT2R" }, | ||
687 | { "HPOUT2L", NULL, "OUT2L" }, | 720 | { "HPOUT2L", NULL, "OUT2L" }, |
688 | { "HPOUT2R", NULL, "OUT2R" }, | 721 | { "HPOUT2R", NULL, "OUT2R" }, |
689 | 722 | ||
723 | { "AEC Loopback", "EPOUT", "OUT3L" }, | ||
690 | { "EPOUTN", NULL, "OUT3L" }, | 724 | { "EPOUTN", NULL, "OUT3L" }, |
691 | { "EPOUTP", NULL, "OUT3L" }, | 725 | { "EPOUTP", NULL, "OUT3L" }, |
692 | 726 | ||
727 | { "AEC Loopback", "SPKOUTL", "OUT4L" }, | ||
693 | { "SPKOUTLN", NULL, "OUT4L" }, | 728 | { "SPKOUTLN", NULL, "OUT4L" }, |
694 | { "SPKOUTLP", NULL, "OUT4L" }, | 729 | { "SPKOUTLP", NULL, "OUT4L" }, |
695 | 730 | ||
731 | { "AEC Loopback", "SPKOUTR", "OUT4R" }, | ||
696 | { "SPKOUTRN", NULL, "OUT4R" }, | 732 | { "SPKOUTRN", NULL, "OUT4R" }, |
697 | { "SPKOUTRP", NULL, "OUT4R" }, | 733 | { "SPKOUTRP", NULL, "OUT4R" }, |
698 | 734 | ||
735 | { "AEC Loopback", "SPKDAT1L", "OUT5L" }, | ||
736 | { "AEC Loopback", "SPKDAT1R", "OUT5R" }, | ||
699 | { "SPKDAT1L", NULL, "OUT5L" }, | 737 | { "SPKDAT1L", NULL, "OUT5L" }, |
700 | { "SPKDAT1R", NULL, "OUT5R" }, | 738 | { "SPKDAT1R", NULL, "OUT5R" }, |
701 | }; | 739 | }; |
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 01ebbcc5c6a4..bf47914234b3 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -305,13 +305,17 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | |||
305 | 0, NULL, 0), | 305 | 0, NULL, 0), |
306 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | 306 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, |
307 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | 307 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), |
308 | 308 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, | |
309 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | 309 | ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0), |
310 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | 310 | SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, |
311 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | 311 | ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), |
312 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), | 312 | |
313 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), | 313 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), |
314 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), | 314 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), |
315 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), | ||
316 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, 0), | ||
317 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), | ||
318 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), | ||
315 | 319 | ||
316 | SND_SOC_DAPM_SIGGEN("TONE"), | 320 | SND_SOC_DAPM_SIGGEN("TONE"), |
317 | SND_SOC_DAPM_SIGGEN("NOISE"), | 321 | SND_SOC_DAPM_SIGGEN("NOISE"), |
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 56a049555e2c..c12a54e72e89 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/of_device.h> | 22 | #include <linux/of_device.h> |
23 | #include <linux/regmap.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -33,24 +34,75 @@ | |||
33 | * We can't read the WM8510 register space when we are | 34 | * We can't read the WM8510 register space when we are |
34 | * using 2 wire for device control, so we cache them instead. | 35 | * using 2 wire for device control, so we cache them instead. |
35 | */ | 36 | */ |
36 | static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { | 37 | static const struct reg_default wm8510_reg_defaults[] = { |
37 | 0x0000, 0x0000, 0x0000, 0x0000, | 38 | { 1, 0x0000 }, |
38 | 0x0050, 0x0000, 0x0140, 0x0000, | 39 | { 2, 0x0000 }, |
39 | 0x0000, 0x0000, 0x0000, 0x00ff, | 40 | { 3, 0x0000 }, |
40 | 0x0000, 0x0000, 0x0100, 0x00ff, | 41 | { 4, 0x0050 }, |
41 | 0x0000, 0x0000, 0x012c, 0x002c, | 42 | { 5, 0x0000 }, |
42 | 0x002c, 0x002c, 0x002c, 0x0000, | 43 | { 6, 0x0140 }, |
43 | 0x0032, 0x0000, 0x0000, 0x0000, | 44 | { 7, 0x0000 }, |
44 | 0x0000, 0x0000, 0x0000, 0x0000, | 45 | { 8, 0x0000 }, |
45 | 0x0038, 0x000b, 0x0032, 0x0000, | 46 | { 9, 0x0000 }, |
46 | 0x0008, 0x000c, 0x0093, 0x00e9, | 47 | { 10, 0x0000 }, |
47 | 0x0000, 0x0000, 0x0000, 0x0000, | 48 | { 11, 0x00ff }, |
48 | 0x0003, 0x0010, 0x0000, 0x0000, | 49 | { 12, 0x0000 }, |
49 | 0x0000, 0x0002, 0x0001, 0x0000, | 50 | { 13, 0x0000 }, |
50 | 0x0000, 0x0000, 0x0039, 0x0000, | 51 | { 14, 0x0100 }, |
51 | 0x0001, | 52 | { 15, 0x00ff }, |
53 | { 16, 0x0000 }, | ||
54 | { 17, 0x0000 }, | ||
55 | { 18, 0x012c }, | ||
56 | { 19, 0x002c }, | ||
57 | { 20, 0x002c }, | ||
58 | { 21, 0x002c }, | ||
59 | { 22, 0x002c }, | ||
60 | { 23, 0x0000 }, | ||
61 | { 24, 0x0032 }, | ||
62 | { 25, 0x0000 }, | ||
63 | { 26, 0x0000 }, | ||
64 | { 27, 0x0000 }, | ||
65 | { 28, 0x0000 }, | ||
66 | { 29, 0x0000 }, | ||
67 | { 30, 0x0000 }, | ||
68 | { 31, 0x0000 }, | ||
69 | { 32, 0x0038 }, | ||
70 | { 33, 0x000b }, | ||
71 | { 34, 0x0032 }, | ||
72 | { 35, 0x0000 }, | ||
73 | { 36, 0x0008 }, | ||
74 | { 37, 0x000c }, | ||
75 | { 38, 0x0093 }, | ||
76 | { 39, 0x00e9 }, | ||
77 | { 40, 0x0000 }, | ||
78 | { 41, 0x0000 }, | ||
79 | { 42, 0x0000 }, | ||
80 | { 43, 0x0000 }, | ||
81 | { 44, 0x0003 }, | ||
82 | { 45, 0x0010 }, | ||
83 | { 46, 0x0000 }, | ||
84 | { 47, 0x0000 }, | ||
85 | { 48, 0x0000 }, | ||
86 | { 49, 0x0002 }, | ||
87 | { 50, 0x0001 }, | ||
88 | { 51, 0x0000 }, | ||
89 | { 52, 0x0000 }, | ||
90 | { 53, 0x0000 }, | ||
91 | { 54, 0x0039 }, | ||
92 | { 55, 0x0000 }, | ||
93 | { 56, 0x0001 }, | ||
52 | }; | 94 | }; |
53 | 95 | ||
96 | static bool wm8510_volatile(struct device *dev, unsigned int reg) | ||
97 | { | ||
98 | switch (reg) { | ||
99 | case WM8510_RESET: | ||
100 | return true; | ||
101 | default: | ||
102 | return false; | ||
103 | } | ||
104 | } | ||
105 | |||
54 | #define WM8510_POWER1_BIASEN 0x08 | 106 | #define WM8510_POWER1_BIASEN 0x08 |
55 | #define WM8510_POWER1_BUFIOEN 0x10 | 107 | #define WM8510_POWER1_BUFIOEN 0x10 |
56 | 108 | ||
@@ -58,7 +110,7 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { | |||
58 | 110 | ||
59 | /* codec private data */ | 111 | /* codec private data */ |
60 | struct wm8510_priv { | 112 | struct wm8510_priv { |
61 | enum snd_soc_control_type control_type; | 113 | struct regmap *regmap; |
62 | }; | 114 | }; |
63 | 115 | ||
64 | static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; | 116 | static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; |
@@ -454,6 +506,7 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute) | |||
454 | static int wm8510_set_bias_level(struct snd_soc_codec *codec, | 506 | static int wm8510_set_bias_level(struct snd_soc_codec *codec, |
455 | enum snd_soc_bias_level level) | 507 | enum snd_soc_bias_level level) |
456 | { | 508 | { |
509 | struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); | ||
457 | u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3; | 510 | u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3; |
458 | 511 | ||
459 | switch (level) { | 512 | switch (level) { |
@@ -467,7 +520,7 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec, | |||
467 | power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN; | 520 | power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN; |
468 | 521 | ||
469 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 522 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
470 | snd_soc_cache_sync(codec); | 523 | regcache_sync(wm8510->regmap); |
471 | 524 | ||
472 | /* Initial cap charge at VMID 5k */ | 525 | /* Initial cap charge at VMID 5k */ |
473 | snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); | 526 | snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); |
@@ -536,10 +589,9 @@ static int wm8510_resume(struct snd_soc_codec *codec) | |||
536 | 589 | ||
537 | static int wm8510_probe(struct snd_soc_codec *codec) | 590 | static int wm8510_probe(struct snd_soc_codec *codec) |
538 | { | 591 | { |
539 | struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); | ||
540 | int ret; | 592 | int ret; |
541 | 593 | ||
542 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type); | 594 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
543 | if (ret < 0) { | 595 | if (ret < 0) { |
544 | printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); | 596 | printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); |
545 | return ret; | 597 | return ret; |
@@ -569,9 +621,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { | |||
569 | .suspend = wm8510_suspend, | 621 | .suspend = wm8510_suspend, |
570 | .resume = wm8510_resume, | 622 | .resume = wm8510_resume, |
571 | .set_bias_level = wm8510_set_bias_level, | 623 | .set_bias_level = wm8510_set_bias_level, |
572 | .reg_cache_size = ARRAY_SIZE(wm8510_reg), | ||
573 | .reg_word_size = sizeof(u16), | ||
574 | .reg_cache_default =wm8510_reg, | ||
575 | 624 | ||
576 | .controls = wm8510_snd_controls, | 625 | .controls = wm8510_snd_controls, |
577 | .num_controls = ARRAY_SIZE(wm8510_snd_controls), | 626 | .num_controls = ARRAY_SIZE(wm8510_snd_controls), |
@@ -586,23 +635,38 @@ static const struct of_device_id wm8510_of_match[] = { | |||
586 | { }, | 635 | { }, |
587 | }; | 636 | }; |
588 | 637 | ||
638 | static const struct regmap_config wm8510_regmap = { | ||
639 | .reg_bits = 7, | ||
640 | .val_bits = 9, | ||
641 | .max_register = WM8510_MONOMIX, | ||
642 | |||
643 | .reg_defaults = wm8510_reg_defaults, | ||
644 | .num_reg_defaults = ARRAY_SIZE(wm8510_reg_defaults), | ||
645 | .cache_type = REGCACHE_RBTREE, | ||
646 | |||
647 | .volatile_reg = wm8510_volatile, | ||
648 | }; | ||
649 | |||
589 | #if defined(CONFIG_SPI_MASTER) | 650 | #if defined(CONFIG_SPI_MASTER) |
590 | static int __devinit wm8510_spi_probe(struct spi_device *spi) | 651 | static int __devinit wm8510_spi_probe(struct spi_device *spi) |
591 | { | 652 | { |
592 | struct wm8510_priv *wm8510; | 653 | struct wm8510_priv *wm8510; |
593 | int ret; | 654 | int ret; |
594 | 655 | ||
595 | wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); | 656 | wm8510 = devm_kzalloc(&spi->dev, sizeof(struct wm8510_priv), |
657 | GFP_KERNEL); | ||
596 | if (wm8510 == NULL) | 658 | if (wm8510 == NULL) |
597 | return -ENOMEM; | 659 | return -ENOMEM; |
598 | 660 | ||
599 | wm8510->control_type = SND_SOC_SPI; | 661 | wm8510->regmap = devm_regmap_init_spi(spi, &wm8510_regmap); |
662 | if (IS_ERR(wm8510->regmap)) | ||
663 | return PTR_ERR(wm8510->regmap); | ||
664 | |||
600 | spi_set_drvdata(spi, wm8510); | 665 | spi_set_drvdata(spi, wm8510); |
601 | 666 | ||
602 | ret = snd_soc_register_codec(&spi->dev, | 667 | ret = snd_soc_register_codec(&spi->dev, |
603 | &soc_codec_dev_wm8510, &wm8510_dai, 1); | 668 | &soc_codec_dev_wm8510, &wm8510_dai, 1); |
604 | if (ret < 0) | 669 | |
605 | kfree(wm8510); | ||
606 | return ret; | 670 | return ret; |
607 | } | 671 | } |
608 | 672 | ||
@@ -630,17 +694,20 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, | |||
630 | struct wm8510_priv *wm8510; | 694 | struct wm8510_priv *wm8510; |
631 | int ret; | 695 | int ret; |
632 | 696 | ||
633 | wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); | 697 | wm8510 = devm_kzalloc(&i2c->dev, sizeof(struct wm8510_priv), |
698 | GFP_KERNEL); | ||
634 | if (wm8510 == NULL) | 699 | if (wm8510 == NULL) |
635 | return -ENOMEM; | 700 | return -ENOMEM; |
636 | 701 | ||
702 | wm8510->regmap = devm_regmap_init_i2c(i2c, &wm8510_regmap); | ||
703 | if (IS_ERR(wm8510->regmap)) | ||
704 | return PTR_ERR(wm8510->regmap); | ||
705 | |||
637 | i2c_set_clientdata(i2c, wm8510); | 706 | i2c_set_clientdata(i2c, wm8510); |
638 | wm8510->control_type = SND_SOC_I2C; | ||
639 | 707 | ||
640 | ret = snd_soc_register_codec(&i2c->dev, | 708 | ret = snd_soc_register_codec(&i2c->dev, |
641 | &soc_codec_dev_wm8510, &wm8510_dai, 1); | 709 | &soc_codec_dev_wm8510, &wm8510_dai, 1); |
642 | if (ret < 0) | 710 | |
643 | kfree(wm8510); | ||
644 | return ret; | 711 | return ret; |
645 | } | 712 | } |
646 | 713 | ||
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 1c3ffb290cdc..8d5c27673501 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/regmap.h> | ||
20 | #include <linux/regulator/consumer.h> | 21 | #include <linux/regulator/consumer.h> |
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
22 | #include <linux/of_device.h> | 23 | #include <linux/of_device.h> |
@@ -39,41 +40,34 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { | |||
39 | 40 | ||
40 | /* codec private data */ | 41 | /* codec private data */ |
41 | struct wm8523_priv { | 42 | struct wm8523_priv { |
42 | enum snd_soc_control_type control_type; | 43 | struct regmap *regmap; |
43 | struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; | 44 | struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; |
44 | unsigned int sysclk; | 45 | unsigned int sysclk; |
45 | unsigned int rate_constraint_list[WM8523_NUM_RATES]; | 46 | unsigned int rate_constraint_list[WM8523_NUM_RATES]; |
46 | struct snd_pcm_hw_constraint_list rate_constraint; | 47 | struct snd_pcm_hw_constraint_list rate_constraint; |
47 | }; | 48 | }; |
48 | 49 | ||
49 | static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = { | 50 | static const struct reg_default wm8523_reg_defaults[] = { |
50 | 0x8523, /* R0 - DEVICE_ID */ | 51 | { 2, 0x0000 }, /* R2 - PSCTRL1 */ |
51 | 0x0001, /* R1 - REVISION */ | 52 | { 3, 0x1812 }, /* R3 - AIF_CTRL1 */ |
52 | 0x0000, /* R2 - PSCTRL1 */ | 53 | { 4, 0x0000 }, /* R4 - AIF_CTRL2 */ |
53 | 0x1812, /* R3 - AIF_CTRL1 */ | 54 | { 5, 0x0001 }, /* R5 - DAC_CTRL3 */ |
54 | 0x0000, /* R4 - AIF_CTRL2 */ | 55 | { 6, 0x0190 }, /* R6 - DAC_GAINL */ |
55 | 0x0001, /* R5 - DAC_CTRL3 */ | 56 | { 7, 0x0190 }, /* R7 - DAC_GAINR */ |
56 | 0x0190, /* R6 - DAC_GAINL */ | 57 | { 8, 0x0000 }, /* R8 - ZERO_DETECT */ |
57 | 0x0190, /* R7 - DAC_GAINR */ | ||
58 | 0x0000, /* R8 - ZERO_DETECT */ | ||
59 | }; | 58 | }; |
60 | 59 | ||
61 | static int wm8523_volatile_register(struct snd_soc_codec *codec, unsigned int reg) | 60 | static bool wm8523_volatile_register(struct device *dev, unsigned int reg) |
62 | { | 61 | { |
63 | switch (reg) { | 62 | switch (reg) { |
64 | case WM8523_DEVICE_ID: | 63 | case WM8523_DEVICE_ID: |
65 | case WM8523_REVISION: | 64 | case WM8523_REVISION: |
66 | return 1; | 65 | return true; |
67 | default: | 66 | default: |
68 | return 0; | 67 | return false; |
69 | } | 68 | } |
70 | } | 69 | } |
71 | 70 | ||
72 | static int wm8523_reset(struct snd_soc_codec *codec) | ||
73 | { | ||
74 | return snd_soc_write(codec, WM8523_DEVICE_ID, 0); | ||
75 | } | ||
76 | |||
77 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0); | 71 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0); |
78 | 72 | ||
79 | static const char *wm8523_zd_count_text[] = { | 73 | static const char *wm8523_zd_count_text[] = { |
@@ -301,8 +295,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, | |||
301 | enum snd_soc_bias_level level) | 295 | enum snd_soc_bias_level level) |
302 | { | 296 | { |
303 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); | 297 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
304 | u16 *reg_cache = codec->reg_cache; | 298 | int ret; |
305 | int ret, i; | ||
306 | 299 | ||
307 | switch (level) { | 300 | switch (level) { |
308 | case SND_SOC_BIAS_ON: | 301 | case SND_SOC_BIAS_ON: |
@@ -325,16 +318,13 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, | |||
325 | return ret; | 318 | return ret; |
326 | } | 319 | } |
327 | 320 | ||
321 | /* Sync back default/cached values */ | ||
322 | regcache_sync(wm8523->regmap); | ||
323 | |||
328 | /* Initial power up */ | 324 | /* Initial power up */ |
329 | snd_soc_update_bits(codec, WM8523_PSCTRL1, | 325 | snd_soc_update_bits(codec, WM8523_PSCTRL1, |
330 | WM8523_SYS_ENA_MASK, 1); | 326 | WM8523_SYS_ENA_MASK, 1); |
331 | 327 | ||
332 | /* Sync back default/cached values */ | ||
333 | for (i = WM8523_AIF_CTRL1; | ||
334 | i < WM8523_MAX_REGISTER; i++) | ||
335 | snd_soc_write(codec, i, reg_cache[i]); | ||
336 | |||
337 | |||
338 | msleep(100); | 328 | msleep(100); |
339 | } | 329 | } |
340 | 330 | ||
@@ -402,60 +392,18 @@ static int wm8523_resume(struct snd_soc_codec *codec) | |||
402 | static int wm8523_probe(struct snd_soc_codec *codec) | 392 | static int wm8523_probe(struct snd_soc_codec *codec) |
403 | { | 393 | { |
404 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); | 394 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
405 | int ret, i; | 395 | int ret; |
406 | 396 | ||
407 | wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; | 397 | wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; |
408 | wm8523->rate_constraint.count = | 398 | wm8523->rate_constraint.count = |
409 | ARRAY_SIZE(wm8523->rate_constraint_list); | 399 | ARRAY_SIZE(wm8523->rate_constraint_list); |
410 | 400 | ||
411 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type); | 401 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); |
412 | if (ret != 0) { | 402 | if (ret != 0) { |
413 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 403 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
414 | return ret; | 404 | return ret; |
415 | } | 405 | } |
416 | 406 | ||
417 | for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) | ||
418 | wm8523->supplies[i].supply = wm8523_supply_names[i]; | ||
419 | |||
420 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies), | ||
421 | wm8523->supplies); | ||
422 | if (ret != 0) { | ||
423 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
424 | return ret; | ||
425 | } | ||
426 | |||
427 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), | ||
428 | wm8523->supplies); | ||
429 | if (ret != 0) { | ||
430 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
431 | goto err_get; | ||
432 | } | ||
433 | |||
434 | ret = snd_soc_read(codec, WM8523_DEVICE_ID); | ||
435 | if (ret < 0) { | ||
436 | dev_err(codec->dev, "Failed to read ID register\n"); | ||
437 | goto err_enable; | ||
438 | } | ||
439 | if (ret != wm8523_reg[WM8523_DEVICE_ID]) { | ||
440 | dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret); | ||
441 | ret = -EINVAL; | ||
442 | goto err_enable; | ||
443 | } | ||
444 | |||
445 | ret = snd_soc_read(codec, WM8523_REVISION); | ||
446 | if (ret < 0) { | ||
447 | dev_err(codec->dev, "Failed to read revision register\n"); | ||
448 | goto err_enable; | ||
449 | } | ||
450 | dev_info(codec->dev, "revision %c\n", | ||
451 | (ret & WM8523_CHIP_REV_MASK) + 'A'); | ||
452 | |||
453 | ret = wm8523_reset(codec); | ||
454 | if (ret < 0) { | ||
455 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
456 | goto err_enable; | ||
457 | } | ||
458 | |||
459 | /* Change some default settings - latch VU and enable ZC */ | 407 | /* Change some default settings - latch VU and enable ZC */ |
460 | snd_soc_update_bits(codec, WM8523_DAC_GAINR, | 408 | snd_soc_update_bits(codec, WM8523_DAC_GAINR, |
461 | WM8523_DACR_VU, WM8523_DACR_VU); | 409 | WM8523_DACR_VU, WM8523_DACR_VU); |
@@ -463,25 +411,12 @@ static int wm8523_probe(struct snd_soc_codec *codec) | |||
463 | 411 | ||
464 | wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 412 | wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
465 | 413 | ||
466 | /* Bias level configuration will have done an extra enable */ | ||
467 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | ||
468 | |||
469 | return 0; | 414 | return 0; |
470 | |||
471 | err_enable: | ||
472 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | ||
473 | err_get: | ||
474 | regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | ||
475 | |||
476 | return ret; | ||
477 | } | 415 | } |
478 | 416 | ||
479 | static int wm8523_remove(struct snd_soc_codec *codec) | 417 | static int wm8523_remove(struct snd_soc_codec *codec) |
480 | { | 418 | { |
481 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); | ||
482 | |||
483 | wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); | 419 | wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); |
484 | regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | ||
485 | return 0; | 420 | return 0; |
486 | } | 421 | } |
487 | 422 | ||
@@ -491,10 +426,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { | |||
491 | .suspend = wm8523_suspend, | 426 | .suspend = wm8523_suspend, |
492 | .resume = wm8523_resume, | 427 | .resume = wm8523_resume, |
493 | .set_bias_level = wm8523_set_bias_level, | 428 | .set_bias_level = wm8523_set_bias_level, |
494 | .reg_cache_size = WM8523_REGISTER_COUNT, | ||
495 | .reg_word_size = sizeof(u16), | ||
496 | .reg_cache_default = wm8523_reg, | ||
497 | .volatile_register = wm8523_volatile_register, | ||
498 | 429 | ||
499 | .controls = wm8523_controls, | 430 | .controls = wm8523_controls, |
500 | .num_controls = ARRAY_SIZE(wm8523_controls), | 431 | .num_controls = ARRAY_SIZE(wm8523_controls), |
@@ -509,32 +440,97 @@ static const struct of_device_id wm8523_of_match[] = { | |||
509 | { }, | 440 | { }, |
510 | }; | 441 | }; |
511 | 442 | ||
443 | static const struct regmap_config wm8523_regmap = { | ||
444 | .reg_bits = 8, | ||
445 | .val_bits = 16, | ||
446 | .max_register = WM8523_ZERO_DETECT, | ||
447 | |||
448 | .reg_defaults = wm8523_reg_defaults, | ||
449 | .num_reg_defaults = ARRAY_SIZE(wm8523_reg_defaults), | ||
450 | .cache_type = REGCACHE_RBTREE, | ||
451 | |||
452 | .volatile_reg = wm8523_volatile_register, | ||
453 | }; | ||
454 | |||
512 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 455 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
513 | static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, | 456 | static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, |
514 | const struct i2c_device_id *id) | 457 | const struct i2c_device_id *id) |
515 | { | 458 | { |
516 | struct wm8523_priv *wm8523; | 459 | struct wm8523_priv *wm8523; |
517 | int ret; | 460 | unsigned int val; |
461 | int ret, i; | ||
518 | 462 | ||
519 | wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); | 463 | wm8523 = devm_kzalloc(&i2c->dev, sizeof(struct wm8523_priv), |
464 | GFP_KERNEL); | ||
520 | if (wm8523 == NULL) | 465 | if (wm8523 == NULL) |
521 | return -ENOMEM; | 466 | return -ENOMEM; |
522 | 467 | ||
468 | wm8523->regmap = devm_regmap_init_i2c(i2c, &wm8523_regmap); | ||
469 | if (IS_ERR(wm8523->regmap)) { | ||
470 | ret = PTR_ERR(wm8523->regmap); | ||
471 | dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); | ||
472 | return ret; | ||
473 | } | ||
474 | |||
475 | for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) | ||
476 | wm8523->supplies[i].supply = wm8523_supply_names[i]; | ||
477 | |||
478 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8523->supplies), | ||
479 | wm8523->supplies); | ||
480 | if (ret != 0) { | ||
481 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
482 | return ret; | ||
483 | } | ||
484 | |||
485 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), | ||
486 | wm8523->supplies); | ||
487 | if (ret != 0) { | ||
488 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | ||
489 | return ret; | ||
490 | } | ||
491 | |||
492 | ret = regmap_read(wm8523->regmap, WM8523_DEVICE_ID, &val); | ||
493 | if (ret < 0) { | ||
494 | dev_err(&i2c->dev, "Failed to read ID register\n"); | ||
495 | goto err_enable; | ||
496 | } | ||
497 | if (val != 0x8523) { | ||
498 | dev_err(&i2c->dev, "Device is not a WM8523, ID is %x\n", ret); | ||
499 | ret = -EINVAL; | ||
500 | goto err_enable; | ||
501 | } | ||
502 | |||
503 | ret = regmap_read(wm8523->regmap, WM8523_REVISION, &val); | ||
504 | if (ret < 0) { | ||
505 | dev_err(&i2c->dev, "Failed to read revision register\n"); | ||
506 | goto err_enable; | ||
507 | } | ||
508 | dev_info(&i2c->dev, "revision %c\n", | ||
509 | (val & WM8523_CHIP_REV_MASK) + 'A'); | ||
510 | |||
511 | ret = regmap_write(wm8523->regmap, WM8523_DEVICE_ID, 0x8523); | ||
512 | if (ret != 0) { | ||
513 | dev_err(&i2c->dev, "Failed to reset device: %d\n", ret); | ||
514 | goto err_enable; | ||
515 | } | ||
516 | |||
517 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | ||
518 | |||
523 | i2c_set_clientdata(i2c, wm8523); | 519 | i2c_set_clientdata(i2c, wm8523); |
524 | wm8523->control_type = SND_SOC_I2C; | ||
525 | 520 | ||
526 | ret = snd_soc_register_codec(&i2c->dev, | 521 | ret = snd_soc_register_codec(&i2c->dev, |
527 | &soc_codec_dev_wm8523, &wm8523_dai, 1); | 522 | &soc_codec_dev_wm8523, &wm8523_dai, 1); |
528 | if (ret < 0) | 523 | |
529 | kfree(wm8523); | ||
530 | return ret; | 524 | return ret; |
531 | 525 | ||
526 | err_enable: | ||
527 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | ||
528 | return ret; | ||
532 | } | 529 | } |
533 | 530 | ||
534 | static __devexit int wm8523_i2c_remove(struct i2c_client *client) | 531 | static __devexit int wm8523_i2c_remove(struct i2c_client *client) |
535 | { | 532 | { |
536 | snd_soc_unregister_codec(&client->dev); | 533 | snd_soc_unregister_codec(&client->dev); |
537 | kfree(i2c_get_clientdata(client)); | ||
538 | return 0; | 534 | return 0; |
539 | } | 535 | } |
540 | 536 | ||
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 7c68226376e4..5e9c40fa7eb2 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8580.c -- WM8580 ALSA Soc Audio driver | 2 | * wm8580.c -- WM8580 ALSA Soc Audio driver |
3 | * | 3 | * |
4 | * Copyright 2008-11 Wolfson Microelectronics PLC. | 4 | * Copyright 2008-12 Wolfson Microelectronics PLC. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 7 | * under the terms of the GNU General Public License as published by the |
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/regmap.h> | ||
26 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
28 | #include <linux/of_device.h> | 29 | #include <linux/of_device.h> |
@@ -157,23 +158,72 @@ | |||
157 | * We can't read the WM8580 register space when we | 158 | * We can't read the WM8580 register space when we |
158 | * are using 2 wire for device control, so we cache them instead. | 159 | * are using 2 wire for device control, so we cache them instead. |
159 | */ | 160 | */ |
160 | static const u16 wm8580_reg[] = { | 161 | static const struct reg_default wm8580_reg_defaults[] = { |
161 | 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/ | 162 | { 0, 0x0121 }, |
162 | 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ | 163 | { 1, 0x017e }, |
163 | 0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/ | 164 | { 2, 0x007d }, |
164 | 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/ | 165 | { 3, 0x0014 }, |
165 | 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/ | 166 | { 4, 0x0121 }, |
166 | 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ | 167 | { 5, 0x017e }, |
167 | 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R27*/ | 168 | { 6, 0x007d }, |
168 | 0x01f0, 0x0040, 0x0000, 0x0000, /*R31(0x1F)*/ | 169 | { 7, 0x0194 }, |
169 | 0x0000, 0x0000, 0x0031, 0x000b, /*R35*/ | 170 | { 8, 0x0010 }, |
170 | 0x0039, 0x0000, 0x0010, 0x0032, /*R39*/ | 171 | { 9, 0x0002 }, |
171 | 0x0054, 0x0076, 0x0098, 0x0000, /*R43(0x2B)*/ | 172 | { 10, 0x0002 }, |
172 | 0x0000, 0x0000, 0x0000, 0x0000, /*R47*/ | 173 | { 11, 0x00c2 }, |
173 | 0x0000, 0x0000, 0x005e, 0x003e, /*R51(0x33)*/ | 174 | { 12, 0x0182 }, |
174 | 0x0000, 0x0000 /*R53*/ | 175 | { 13, 0x0082 }, |
176 | { 14, 0x000a }, | ||
177 | { 15, 0x0024 }, | ||
178 | { 16, 0x0009 }, | ||
179 | { 17, 0x0000 }, | ||
180 | { 18, 0x00ff }, | ||
181 | { 19, 0x0000 }, | ||
182 | { 20, 0x00ff }, | ||
183 | { 21, 0x00ff }, | ||
184 | { 22, 0x00ff }, | ||
185 | { 23, 0x00ff }, | ||
186 | { 24, 0x00ff }, | ||
187 | { 25, 0x00ff }, | ||
188 | { 26, 0x00ff }, | ||
189 | { 27, 0x00ff }, | ||
190 | { 28, 0x01f0 }, | ||
191 | { 29, 0x0040 }, | ||
192 | { 30, 0x0000 }, | ||
193 | { 31, 0x0000 }, | ||
194 | { 32, 0x0000 }, | ||
195 | { 33, 0x0000 }, | ||
196 | { 34, 0x0031 }, | ||
197 | { 35, 0x000b }, | ||
198 | { 36, 0x0039 }, | ||
199 | { 37, 0x0000 }, | ||
200 | { 38, 0x0010 }, | ||
201 | { 39, 0x0032 }, | ||
202 | { 40, 0x0054 }, | ||
203 | { 41, 0x0076 }, | ||
204 | { 42, 0x0098 }, | ||
205 | { 43, 0x0000 }, | ||
206 | { 44, 0x0000 }, | ||
207 | { 45, 0x0000 }, | ||
208 | { 46, 0x0000 }, | ||
209 | { 47, 0x0000 }, | ||
210 | { 48, 0x0000 }, | ||
211 | { 49, 0x0000 }, | ||
212 | { 50, 0x005e }, | ||
213 | { 51, 0x003e }, | ||
214 | { 52, 0x0000 }, | ||
175 | }; | 215 | }; |
176 | 216 | ||
217 | static bool wm8580_volatile(struct device *dev, unsigned int reg) | ||
218 | { | ||
219 | switch (reg) { | ||
220 | case WM8580_RESET: | ||
221 | return true; | ||
222 | default: | ||
223 | return false; | ||
224 | } | ||
225 | } | ||
226 | |||
177 | struct pll_state { | 227 | struct pll_state { |
178 | unsigned int in; | 228 | unsigned int in; |
179 | unsigned int out; | 229 | unsigned int out; |
@@ -188,7 +238,7 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { | |||
188 | 238 | ||
189 | /* codec private data */ | 239 | /* codec private data */ |
190 | struct wm8580_priv { | 240 | struct wm8580_priv { |
191 | enum snd_soc_control_type control_type; | 241 | struct regmap *regmap; |
192 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; | 242 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; |
193 | struct pll_state a; | 243 | struct pll_state a; |
194 | struct pll_state b; | 244 | struct pll_state b; |
@@ -203,14 +253,16 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, | |||
203 | struct soc_mixer_control *mc = | 253 | struct soc_mixer_control *mc = |
204 | (struct soc_mixer_control *)kcontrol->private_value; | 254 | (struct soc_mixer_control *)kcontrol->private_value; |
205 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 255 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
206 | u16 *reg_cache = codec->reg_cache; | 256 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
207 | unsigned int reg = mc->reg; | 257 | unsigned int reg = mc->reg; |
208 | unsigned int reg2 = mc->rreg; | 258 | unsigned int reg2 = mc->rreg; |
209 | int ret; | 259 | int ret; |
210 | 260 | ||
211 | /* Clear the register cache so we write without VU set */ | 261 | /* Clear the register cache VU so we write without VU set */ |
212 | reg_cache[reg] = 0; | 262 | regcache_cache_only(wm8580->regmap, true); |
213 | reg_cache[reg2] = 0; | 263 | regmap_update_bits(wm8580->regmap, reg, 0x100, 0x000); |
264 | regmap_update_bits(wm8580->regmap, reg2, 0x100, 0x000); | ||
265 | regcache_cache_only(wm8580->regmap, false); | ||
214 | 266 | ||
215 | ret = snd_soc_put_volsw(kcontrol, ucontrol); | 267 | ret = snd_soc_put_volsw(kcontrol, ucontrol); |
216 | if (ret < 0) | 268 | if (ret < 0) |
@@ -815,24 +867,14 @@ static struct snd_soc_dai_driver wm8580_dai[] = { | |||
815 | static int wm8580_probe(struct snd_soc_codec *codec) | 867 | static int wm8580_probe(struct snd_soc_codec *codec) |
816 | { | 868 | { |
817 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); | 869 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
818 | int ret = 0,i; | 870 | int ret = 0; |
819 | 871 | ||
820 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type); | 872 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
821 | if (ret < 0) { | 873 | if (ret < 0) { |
822 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 874 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
823 | return ret; | 875 | return ret; |
824 | } | 876 | } |
825 | 877 | ||
826 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) | ||
827 | wm8580->supplies[i].supply = wm8580_supply_names[i]; | ||
828 | |||
829 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies), | ||
830 | wm8580->supplies); | ||
831 | if (ret != 0) { | ||
832 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
833 | return ret; | ||
834 | } | ||
835 | |||
836 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), | 878 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), |
837 | wm8580->supplies); | 879 | wm8580->supplies); |
838 | if (ret != 0) { | 880 | if (ret != 0) { |
@@ -854,7 +896,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) | |||
854 | err_regulator_enable: | 896 | err_regulator_enable: |
855 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 897 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
856 | err_regulator_get: | 898 | err_regulator_get: |
857 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | ||
858 | return ret; | 899 | return ret; |
859 | } | 900 | } |
860 | 901 | ||
@@ -866,7 +907,6 @@ static int wm8580_remove(struct snd_soc_codec *codec) | |||
866 | wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); | 907 | wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); |
867 | 908 | ||
868 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 909 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
869 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | ||
870 | 910 | ||
871 | return 0; | 911 | return 0; |
872 | } | 912 | } |
@@ -875,9 +915,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { | |||
875 | .probe = wm8580_probe, | 915 | .probe = wm8580_probe, |
876 | .remove = wm8580_remove, | 916 | .remove = wm8580_remove, |
877 | .set_bias_level = wm8580_set_bias_level, | 917 | .set_bias_level = wm8580_set_bias_level, |
878 | .reg_cache_size = ARRAY_SIZE(wm8580_reg), | ||
879 | .reg_word_size = sizeof(u16), | ||
880 | .reg_cache_default = wm8580_reg, | ||
881 | 918 | ||
882 | .controls = wm8580_snd_controls, | 919 | .controls = wm8580_snd_controls, |
883 | .num_controls = ARRAY_SIZE(wm8580_snd_controls), | 920 | .num_controls = ARRAY_SIZE(wm8580_snd_controls), |
@@ -892,31 +929,55 @@ static const struct of_device_id wm8580_of_match[] = { | |||
892 | { }, | 929 | { }, |
893 | }; | 930 | }; |
894 | 931 | ||
932 | static const struct regmap_config wm8580_regmap = { | ||
933 | .reg_bits = 7, | ||
934 | .val_bits = 9, | ||
935 | .max_register = WM8580_MAX_REGISTER, | ||
936 | |||
937 | .reg_defaults = wm8580_reg_defaults, | ||
938 | .num_reg_defaults = ARRAY_SIZE(wm8580_reg_defaults), | ||
939 | .cache_type = REGCACHE_RBTREE, | ||
940 | |||
941 | .volatile_reg = wm8580_volatile, | ||
942 | }; | ||
943 | |||
895 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 944 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
896 | static int wm8580_i2c_probe(struct i2c_client *i2c, | 945 | static int wm8580_i2c_probe(struct i2c_client *i2c, |
897 | const struct i2c_device_id *id) | 946 | const struct i2c_device_id *id) |
898 | { | 947 | { |
899 | struct wm8580_priv *wm8580; | 948 | struct wm8580_priv *wm8580; |
900 | int ret; | 949 | int ret, i; |
901 | 950 | ||
902 | wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); | 951 | wm8580 = devm_kzalloc(&i2c->dev, sizeof(struct wm8580_priv), |
952 | GFP_KERNEL); | ||
903 | if (wm8580 == NULL) | 953 | if (wm8580 == NULL) |
904 | return -ENOMEM; | 954 | return -ENOMEM; |
905 | 955 | ||
956 | wm8580->regmap = devm_regmap_init_i2c(i2c, &wm8580_regmap); | ||
957 | if (IS_ERR(wm8580->regmap)) | ||
958 | return PTR_ERR(wm8580->regmap); | ||
959 | |||
960 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) | ||
961 | wm8580->supplies[i].supply = wm8580_supply_names[i]; | ||
962 | |||
963 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8580->supplies), | ||
964 | wm8580->supplies); | ||
965 | if (ret != 0) { | ||
966 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
967 | return ret; | ||
968 | } | ||
969 | |||
906 | i2c_set_clientdata(i2c, wm8580); | 970 | i2c_set_clientdata(i2c, wm8580); |
907 | wm8580->control_type = SND_SOC_I2C; | ||
908 | 971 | ||
909 | ret = snd_soc_register_codec(&i2c->dev, | 972 | ret = snd_soc_register_codec(&i2c->dev, |
910 | &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); | 973 | &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); |
911 | if (ret < 0) | 974 | |
912 | kfree(wm8580); | ||
913 | return ret; | 975 | return ret; |
914 | } | 976 | } |
915 | 977 | ||
916 | static int wm8580_i2c_remove(struct i2c_client *client) | 978 | static int wm8580_i2c_remove(struct i2c_client *client) |
917 | { | 979 | { |
918 | snd_soc_unregister_codec(&client->dev); | 980 | snd_soc_unregister_codec(&client->dev); |
919 | kfree(i2c_get_clientdata(client)); | ||
920 | return 0; | 981 | return 0; |
921 | } | 982 | } |
922 | 983 | ||
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 0b76d1dca5ea..8b8bb70f1eb9 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/regmap.h> | ||
21 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
23 | #include <linux/of_device.h> | 24 | #include <linux/of_device.h> |
@@ -32,7 +33,7 @@ | |||
32 | 33 | ||
33 | /* codec private data */ | 34 | /* codec private data */ |
34 | struct wm8711_priv { | 35 | struct wm8711_priv { |
35 | enum snd_soc_control_type bus_type; | 36 | struct regmap *regmap; |
36 | unsigned int sysclk; | 37 | unsigned int sysclk; |
37 | }; | 38 | }; |
38 | 39 | ||
@@ -42,11 +43,21 @@ struct wm8711_priv { | |||
42 | * using 2 wire for device control, so we cache them instead. | 43 | * using 2 wire for device control, so we cache them instead. |
43 | * There is no point in caching the reset register | 44 | * There is no point in caching the reset register |
44 | */ | 45 | */ |
45 | static const u16 wm8711_reg[WM8711_CACHEREGNUM] = { | 46 | static const struct reg_default wm8711_reg_defaults[] = { |
46 | 0x0079, 0x0079, 0x000a, 0x0008, | 47 | { 0, 0x0079 }, { 1, 0x0079 }, { 2, 0x000a }, { 3, 0x0008 }, |
47 | 0x009f, 0x000a, 0x0000, 0x0000 | 48 | { 4, 0x009f }, { 5, 0x000a }, { 6, 0x0000 }, { 7, 0x0000 }, |
48 | }; | 49 | }; |
49 | 50 | ||
51 | static bool wm8711_volatile(struct device *dev, unsigned int reg) | ||
52 | { | ||
53 | switch (reg) { | ||
54 | case WM8711_RESET: | ||
55 | return true; | ||
56 | default: | ||
57 | return false; | ||
58 | } | ||
59 | } | ||
60 | |||
50 | #define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0) | 61 | #define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0) |
51 | 62 | ||
52 | static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); | 63 | static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); |
@@ -289,6 +300,7 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
289 | static int wm8711_set_bias_level(struct snd_soc_codec *codec, | 300 | static int wm8711_set_bias_level(struct snd_soc_codec *codec, |
290 | enum snd_soc_bias_level level) | 301 | enum snd_soc_bias_level level) |
291 | { | 302 | { |
303 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); | ||
292 | u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f; | 304 | u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f; |
293 | 305 | ||
294 | switch (level) { | 306 | switch (level) { |
@@ -299,7 +311,7 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec, | |||
299 | break; | 311 | break; |
300 | case SND_SOC_BIAS_STANDBY: | 312 | case SND_SOC_BIAS_STANDBY: |
301 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 313 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) |
302 | snd_soc_cache_sync(codec); | 314 | regcache_sync(wm8711->regmap); |
303 | 315 | ||
304 | snd_soc_write(codec, WM8711_PWR, reg | 0x0040); | 316 | snd_soc_write(codec, WM8711_PWR, reg | 0x0040); |
305 | break; | 317 | break; |
@@ -353,10 +365,9 @@ static int wm8711_resume(struct snd_soc_codec *codec) | |||
353 | 365 | ||
354 | static int wm8711_probe(struct snd_soc_codec *codec) | 366 | static int wm8711_probe(struct snd_soc_codec *codec) |
355 | { | 367 | { |
356 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); | ||
357 | int ret; | 368 | int ret; |
358 | 369 | ||
359 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type); | 370 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
360 | if (ret < 0) { | 371 | if (ret < 0) { |
361 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 372 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
362 | return ret; | 373 | return ret; |
@@ -391,9 +402,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { | |||
391 | .suspend = wm8711_suspend, | 402 | .suspend = wm8711_suspend, |
392 | .resume = wm8711_resume, | 403 | .resume = wm8711_resume, |
393 | .set_bias_level = wm8711_set_bias_level, | 404 | .set_bias_level = wm8711_set_bias_level, |
394 | .reg_cache_size = ARRAY_SIZE(wm8711_reg), | ||
395 | .reg_word_size = sizeof(u16), | ||
396 | .reg_cache_default = wm8711_reg, | ||
397 | .controls = wm8711_snd_controls, | 405 | .controls = wm8711_snd_controls, |
398 | .num_controls = ARRAY_SIZE(wm8711_snd_controls), | 406 | .num_controls = ARRAY_SIZE(wm8711_snd_controls), |
399 | .dapm_widgets = wm8711_dapm_widgets, | 407 | .dapm_widgets = wm8711_dapm_widgets, |
@@ -408,30 +416,45 @@ static const struct of_device_id wm8711_of_match[] = { | |||
408 | }; | 416 | }; |
409 | MODULE_DEVICE_TABLE(of, wm8711_of_match); | 417 | MODULE_DEVICE_TABLE(of, wm8711_of_match); |
410 | 418 | ||
419 | static const struct regmap_config wm8711_regmap = { | ||
420 | .reg_bits = 7, | ||
421 | .val_bits = 9, | ||
422 | .max_register = WM8711_RESET, | ||
423 | |||
424 | .reg_defaults = wm8711_reg_defaults, | ||
425 | .num_reg_defaults = ARRAY_SIZE(wm8711_reg_defaults), | ||
426 | .cache_type = REGCACHE_RBTREE, | ||
427 | |||
428 | .volatile_reg = wm8711_volatile, | ||
429 | }; | ||
430 | |||
411 | #if defined(CONFIG_SPI_MASTER) | 431 | #if defined(CONFIG_SPI_MASTER) |
412 | static int __devinit wm8711_spi_probe(struct spi_device *spi) | 432 | static int __devinit wm8711_spi_probe(struct spi_device *spi) |
413 | { | 433 | { |
414 | struct wm8711_priv *wm8711; | 434 | struct wm8711_priv *wm8711; |
415 | int ret; | 435 | int ret; |
416 | 436 | ||
417 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); | 437 | wm8711 = devm_kzalloc(&spi->dev, sizeof(struct wm8711_priv), |
438 | GFP_KERNEL); | ||
418 | if (wm8711 == NULL) | 439 | if (wm8711 == NULL) |
419 | return -ENOMEM; | 440 | return -ENOMEM; |
420 | 441 | ||
442 | wm8711->regmap = devm_regmap_init_spi(spi, &wm8711_regmap); | ||
443 | if (IS_ERR(wm8711->regmap)) | ||
444 | return PTR_ERR(wm8711->regmap); | ||
445 | |||
421 | spi_set_drvdata(spi, wm8711); | 446 | spi_set_drvdata(spi, wm8711); |
422 | wm8711->bus_type = SND_SOC_SPI; | ||
423 | 447 | ||
424 | ret = snd_soc_register_codec(&spi->dev, | 448 | ret = snd_soc_register_codec(&spi->dev, |
425 | &soc_codec_dev_wm8711, &wm8711_dai, 1); | 449 | &soc_codec_dev_wm8711, &wm8711_dai, 1); |
426 | if (ret < 0) | 450 | |
427 | kfree(wm8711); | ||
428 | return ret; | 451 | return ret; |
429 | } | 452 | } |
430 | 453 | ||
431 | static int __devexit wm8711_spi_remove(struct spi_device *spi) | 454 | static int __devexit wm8711_spi_remove(struct spi_device *spi) |
432 | { | 455 | { |
433 | snd_soc_unregister_codec(&spi->dev); | 456 | snd_soc_unregister_codec(&spi->dev); |
434 | kfree(spi_get_drvdata(spi)); | 457 | |
435 | return 0; | 458 | return 0; |
436 | } | 459 | } |
437 | 460 | ||
@@ -453,24 +476,26 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client, | |||
453 | struct wm8711_priv *wm8711; | 476 | struct wm8711_priv *wm8711; |
454 | int ret; | 477 | int ret; |
455 | 478 | ||
456 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); | 479 | wm8711 = devm_kzalloc(&client->dev, sizeof(struct wm8711_priv), |
480 | GFP_KERNEL); | ||
457 | if (wm8711 == NULL) | 481 | if (wm8711 == NULL) |
458 | return -ENOMEM; | 482 | return -ENOMEM; |
459 | 483 | ||
484 | wm8711->regmap = devm_regmap_init_i2c(client, &wm8711_regmap); | ||
485 | if (IS_ERR(wm8711->regmap)) | ||
486 | return PTR_ERR(wm8711->regmap); | ||
487 | |||
460 | i2c_set_clientdata(client, wm8711); | 488 | i2c_set_clientdata(client, wm8711); |
461 | wm8711->bus_type = SND_SOC_I2C; | ||
462 | 489 | ||
463 | ret = snd_soc_register_codec(&client->dev, | 490 | ret = snd_soc_register_codec(&client->dev, |
464 | &soc_codec_dev_wm8711, &wm8711_dai, 1); | 491 | &soc_codec_dev_wm8711, &wm8711_dai, 1); |
465 | if (ret < 0) | 492 | |
466 | kfree(wm8711); | ||
467 | return ret; | 493 | return ret; |
468 | } | 494 | } |
469 | 495 | ||
470 | static __devexit int wm8711_i2c_remove(struct i2c_client *client) | 496 | static __devexit int wm8711_i2c_remove(struct i2c_client *client) |
471 | { | 497 | { |
472 | snd_soc_unregister_codec(&client->dev); | 498 | snd_soc_unregister_codec(&client->dev); |
473 | kfree(i2c_get_clientdata(client)); | ||
474 | return 0; | 499 | return 0; |
475 | } | 500 | } |
476 | 501 | ||
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 1467f97dce21..00a12a0c3919 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/regmap.h> | ||
20 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
22 | #include <linux/of_device.h> | 23 | #include <linux/of_device.h> |
@@ -35,16 +36,16 @@ | |||
35 | * the volume update bits, mute the output and enable infinite zero | 36 | * the volume update bits, mute the output and enable infinite zero |
36 | * detect. | 37 | * detect. |
37 | */ | 38 | */ |
38 | static const u16 wm8728_reg_defaults[] = { | 39 | static const struct reg_default wm8728_reg_defaults[] = { |
39 | 0x1ff, | 40 | { 0, 0x1ff }, |
40 | 0x1ff, | 41 | { 1, 0x1ff }, |
41 | 0x001, | 42 | { 2, 0x001 }, |
42 | 0x100, | 43 | { 3, 0x100 }, |
43 | }; | 44 | }; |
44 | 45 | ||
45 | /* codec private data */ | 46 | /* codec private data */ |
46 | struct wm8728_priv { | 47 | struct wm8728_priv { |
47 | enum snd_soc_control_type control_type; | 48 | struct regmap *regmap; |
48 | }; | 49 | }; |
49 | 50 | ||
50 | static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); | 51 | static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); |
@@ -162,8 +163,8 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
162 | static int wm8728_set_bias_level(struct snd_soc_codec *codec, | 163 | static int wm8728_set_bias_level(struct snd_soc_codec *codec, |
163 | enum snd_soc_bias_level level) | 164 | enum snd_soc_bias_level level) |
164 | { | 165 | { |
166 | struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); | ||
165 | u16 reg; | 167 | u16 reg; |
166 | int i; | ||
167 | 168 | ||
168 | switch (level) { | 169 | switch (level) { |
169 | case SND_SOC_BIAS_ON: | 170 | case SND_SOC_BIAS_ON: |
@@ -175,9 +176,7 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec, | |||
175 | snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4); | 176 | snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4); |
176 | 177 | ||
177 | /* ..then sync in the register cache. */ | 178 | /* ..then sync in the register cache. */ |
178 | for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++) | 179 | regcache_sync(wm8728->regmap); |
179 | snd_soc_write(codec, i, | ||
180 | snd_soc_read(codec, i)); | ||
181 | } | 180 | } |
182 | break; | 181 | break; |
183 | 182 | ||
@@ -229,10 +228,9 @@ static int wm8728_resume(struct snd_soc_codec *codec) | |||
229 | 228 | ||
230 | static int wm8728_probe(struct snd_soc_codec *codec) | 229 | static int wm8728_probe(struct snd_soc_codec *codec) |
231 | { | 230 | { |
232 | struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); | ||
233 | int ret; | 231 | int ret; |
234 | 232 | ||
235 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type); | 233 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
236 | if (ret < 0) { | 234 | if (ret < 0) { |
237 | printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", | 235 | printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", |
238 | ret); | 236 | ret); |
@@ -257,9 +255,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { | |||
257 | .suspend = wm8728_suspend, | 255 | .suspend = wm8728_suspend, |
258 | .resume = wm8728_resume, | 256 | .resume = wm8728_resume, |
259 | .set_bias_level = wm8728_set_bias_level, | 257 | .set_bias_level = wm8728_set_bias_level, |
260 | .reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults), | ||
261 | .reg_word_size = sizeof(u16), | ||
262 | .reg_cache_default = wm8728_reg_defaults, | ||
263 | .controls = wm8728_snd_controls, | 258 | .controls = wm8728_snd_controls, |
264 | .num_controls = ARRAY_SIZE(wm8728_snd_controls), | 259 | .num_controls = ARRAY_SIZE(wm8728_snd_controls), |
265 | .dapm_widgets = wm8728_dapm_widgets, | 260 | .dapm_widgets = wm8728_dapm_widgets, |
@@ -274,30 +269,43 @@ static const struct of_device_id wm8728_of_match[] = { | |||
274 | }; | 269 | }; |
275 | MODULE_DEVICE_TABLE(of, wm8728_of_match); | 270 | MODULE_DEVICE_TABLE(of, wm8728_of_match); |
276 | 271 | ||
272 | static const struct regmap_config wm8728_regmap = { | ||
273 | .reg_bits = 7, | ||
274 | .val_bits = 9, | ||
275 | .max_register = WM8728_IFCTL, | ||
276 | |||
277 | .reg_defaults = wm8728_reg_defaults, | ||
278 | .num_reg_defaults = ARRAY_SIZE(wm8728_reg_defaults), | ||
279 | .cache_type = REGCACHE_RBTREE, | ||
280 | }; | ||
281 | |||
277 | #if defined(CONFIG_SPI_MASTER) | 282 | #if defined(CONFIG_SPI_MASTER) |
278 | static int __devinit wm8728_spi_probe(struct spi_device *spi) | 283 | static int __devinit wm8728_spi_probe(struct spi_device *spi) |
279 | { | 284 | { |
280 | struct wm8728_priv *wm8728; | 285 | struct wm8728_priv *wm8728; |
281 | int ret; | 286 | int ret; |
282 | 287 | ||
283 | wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); | 288 | wm8728 = devm_kzalloc(&spi->dev, sizeof(struct wm8728_priv), |
289 | GFP_KERNEL); | ||
284 | if (wm8728 == NULL) | 290 | if (wm8728 == NULL) |
285 | return -ENOMEM; | 291 | return -ENOMEM; |
286 | 292 | ||
287 | wm8728->control_type = SND_SOC_SPI; | 293 | wm8728->regmap = devm_regmap_init_spi(spi, &wm8728_regmap); |
294 | if (IS_ERR(wm8728->regmap)) | ||
295 | return PTR_ERR(wm8728->regmap); | ||
296 | |||
288 | spi_set_drvdata(spi, wm8728); | 297 | spi_set_drvdata(spi, wm8728); |
289 | 298 | ||
290 | ret = snd_soc_register_codec(&spi->dev, | 299 | ret = snd_soc_register_codec(&spi->dev, |
291 | &soc_codec_dev_wm8728, &wm8728_dai, 1); | 300 | &soc_codec_dev_wm8728, &wm8728_dai, 1); |
292 | if (ret < 0) | 301 | |
293 | kfree(wm8728); | ||
294 | return ret; | 302 | return ret; |
295 | } | 303 | } |
296 | 304 | ||
297 | static int __devexit wm8728_spi_remove(struct spi_device *spi) | 305 | static int __devexit wm8728_spi_remove(struct spi_device *spi) |
298 | { | 306 | { |
299 | snd_soc_unregister_codec(&spi->dev); | 307 | snd_soc_unregister_codec(&spi->dev); |
300 | kfree(spi_get_drvdata(spi)); | 308 | |
301 | return 0; | 309 | return 0; |
302 | } | 310 | } |
303 | 311 | ||
@@ -319,24 +327,26 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, | |||
319 | struct wm8728_priv *wm8728; | 327 | struct wm8728_priv *wm8728; |
320 | int ret; | 328 | int ret; |
321 | 329 | ||
322 | wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); | 330 | wm8728 = devm_kzalloc(&i2c->dev, sizeof(struct wm8728_priv), |
331 | GFP_KERNEL); | ||
323 | if (wm8728 == NULL) | 332 | if (wm8728 == NULL) |
324 | return -ENOMEM; | 333 | return -ENOMEM; |
325 | 334 | ||
335 | wm8728->regmap = devm_regmap_init_i2c(i2c, &wm8728_regmap); | ||
336 | if (IS_ERR(wm8728->regmap)) | ||
337 | return PTR_ERR(wm8728->regmap); | ||
338 | |||
326 | i2c_set_clientdata(i2c, wm8728); | 339 | i2c_set_clientdata(i2c, wm8728); |
327 | wm8728->control_type = SND_SOC_I2C; | ||
328 | 340 | ||
329 | ret = snd_soc_register_codec(&i2c->dev, | 341 | ret = snd_soc_register_codec(&i2c->dev, |
330 | &soc_codec_dev_wm8728, &wm8728_dai, 1); | 342 | &soc_codec_dev_wm8728, &wm8728_dai, 1); |
331 | if (ret < 0) | 343 | |
332 | kfree(wm8728); | ||
333 | return ret; | 344 | return ret; |
334 | } | 345 | } |
335 | 346 | ||
336 | static __devexit int wm8728_i2c_remove(struct i2c_client *client) | 347 | static __devexit int wm8728_i2c_remove(struct i2c_client *client) |
337 | { | 348 | { |
338 | snd_soc_unregister_codec(&client->dev); | 349 | snd_soc_unregister_codec(&client->dev); |
339 | kfree(i2c_get_clientdata(client)); | ||
340 | return 0; | 350 | return 0; |
341 | } | 351 | } |
342 | 352 | ||
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index d0520124616d..5c9634f4c1f0 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/regmap.h> | ||
19 | #include <linux/regulator/consumer.h> | 20 | #include <linux/regulator/consumer.h> |
20 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
@@ -40,29 +41,39 @@ static const char *wm8737_supply_names[WM8737_NUM_SUPPLIES] = { | |||
40 | 41 | ||
41 | /* codec private data */ | 42 | /* codec private data */ |
42 | struct wm8737_priv { | 43 | struct wm8737_priv { |
43 | enum snd_soc_control_type control_type; | 44 | struct regmap *regmap; |
44 | struct regulator_bulk_data supplies[WM8737_NUM_SUPPLIES]; | 45 | struct regulator_bulk_data supplies[WM8737_NUM_SUPPLIES]; |
45 | unsigned int mclk; | 46 | unsigned int mclk; |
46 | }; | 47 | }; |
47 | 48 | ||
48 | static const u16 wm8737_reg[WM8737_REGISTER_COUNT] = { | 49 | static const struct reg_default wm8737_reg_defaults[] = { |
49 | 0x00C3, /* R0 - Left PGA volume */ | 50 | { 0, 0x00C3 }, /* R0 - Left PGA volume */ |
50 | 0x00C3, /* R1 - Right PGA volume */ | 51 | { 1, 0x00C3 }, /* R1 - Right PGA volume */ |
51 | 0x0007, /* R2 - AUDIO path L */ | 52 | { 2, 0x0007 }, /* R2 - AUDIO path L */ |
52 | 0x0007, /* R3 - AUDIO path R */ | 53 | { 3, 0x0007 }, /* R3 - AUDIO path R */ |
53 | 0x0000, /* R4 - 3D Enhance */ | 54 | { 4, 0x0000 }, /* R4 - 3D Enhance */ |
54 | 0x0000, /* R5 - ADC Control */ | 55 | { 5, 0x0000 }, /* R5 - ADC Control */ |
55 | 0x0000, /* R6 - Power Management */ | 56 | { 6, 0x0000 }, /* R6 - Power Management */ |
56 | 0x000A, /* R7 - Audio Format */ | 57 | { 7, 0x000A }, /* R7 - Audio Format */ |
57 | 0x0000, /* R8 - Clocking */ | 58 | { 8, 0x0000 }, /* R8 - Clocking */ |
58 | 0x000F, /* R9 - MIC Preamp Control */ | 59 | { 9, 0x000F }, /* R9 - MIC Preamp Control */ |
59 | 0x0003, /* R10 - Misc Bias Control */ | 60 | { 10, 0x0003 }, /* R10 - Misc Bias Control */ |
60 | 0x0000, /* R11 - Noise Gate */ | 61 | { 11, 0x0000 }, /* R11 - Noise Gate */ |
61 | 0x007C, /* R12 - ALC1 */ | 62 | { 12, 0x007C }, /* R12 - ALC1 */ |
62 | 0x0000, /* R13 - ALC2 */ | 63 | { 13, 0x0000 }, /* R13 - ALC2 */ |
63 | 0x0032, /* R14 - ALC3 */ | 64 | { 14, 0x0032 }, /* R14 - ALC3 */ |
64 | }; | 65 | }; |
65 | 66 | ||
67 | static bool wm8737_volatile(struct device *dev, unsigned int reg) | ||
68 | { | ||
69 | switch (reg) { | ||
70 | case WM8737_RESET: | ||
71 | return true; | ||
72 | default: | ||
73 | return false; | ||
74 | } | ||
75 | } | ||
76 | |||
66 | static int wm8737_reset(struct snd_soc_codec *codec) | 77 | static int wm8737_reset(struct snd_soc_codec *codec) |
67 | { | 78 | { |
68 | return snd_soc_write(codec, WM8737_RESET, 0); | 79 | return snd_soc_write(codec, WM8737_RESET, 0); |
@@ -479,7 +490,7 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec, | |||
479 | return ret; | 490 | return ret; |
480 | } | 491 | } |
481 | 492 | ||
482 | snd_soc_cache_sync(codec); | 493 | regcache_sync(wm8737->regmap); |
483 | 494 | ||
484 | /* Fast VMID ramp at 2*2.5k */ | 495 | /* Fast VMID ramp at 2*2.5k */ |
485 | snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, | 496 | snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, |
@@ -557,24 +568,14 @@ static int wm8737_resume(struct snd_soc_codec *codec) | |||
557 | static int wm8737_probe(struct snd_soc_codec *codec) | 568 | static int wm8737_probe(struct snd_soc_codec *codec) |
558 | { | 569 | { |
559 | struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); | 570 | struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); |
560 | int ret, i; | 571 | int ret; |
561 | 572 | ||
562 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8737->control_type); | 573 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
563 | if (ret != 0) { | 574 | if (ret != 0) { |
564 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 575 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
565 | return ret; | 576 | return ret; |
566 | } | 577 | } |
567 | 578 | ||
568 | for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) | ||
569 | wm8737->supplies[i].supply = wm8737_supply_names[i]; | ||
570 | |||
571 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8737->supplies), | ||
572 | wm8737->supplies); | ||
573 | if (ret != 0) { | ||
574 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), | 579 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), |
579 | wm8737->supplies); | 580 | wm8737->supplies); |
580 | if (ret != 0) { | 581 | if (ret != 0) { |
@@ -607,17 +608,12 @@ static int wm8737_probe(struct snd_soc_codec *codec) | |||
607 | err_enable: | 608 | err_enable: |
608 | regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); | 609 | regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); |
609 | err_get: | 610 | err_get: |
610 | regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); | ||
611 | |||
612 | return ret; | 611 | return ret; |
613 | } | 612 | } |
614 | 613 | ||
615 | static int wm8737_remove(struct snd_soc_codec *codec) | 614 | static int wm8737_remove(struct snd_soc_codec *codec) |
616 | { | 615 | { |
617 | struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); | ||
618 | |||
619 | wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF); | 616 | wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF); |
620 | regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); | ||
621 | return 0; | 617 | return 0; |
622 | } | 618 | } |
623 | 619 | ||
@@ -627,10 +623,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { | |||
627 | .suspend = wm8737_suspend, | 623 | .suspend = wm8737_suspend, |
628 | .resume = wm8737_resume, | 624 | .resume = wm8737_resume, |
629 | .set_bias_level = wm8737_set_bias_level, | 625 | .set_bias_level = wm8737_set_bias_level, |
630 | |||
631 | .reg_cache_size = WM8737_REGISTER_COUNT - 1, /* Skip reset */ | ||
632 | .reg_word_size = sizeof(u16), | ||
633 | .reg_cache_default = wm8737_reg, | ||
634 | }; | 626 | }; |
635 | 627 | ||
636 | static const struct of_device_id wm8737_of_match[] = { | 628 | static const struct of_device_id wm8737_of_match[] = { |
@@ -640,24 +632,49 @@ static const struct of_device_id wm8737_of_match[] = { | |||
640 | 632 | ||
641 | MODULE_DEVICE_TABLE(of, wm8737_of_match); | 633 | MODULE_DEVICE_TABLE(of, wm8737_of_match); |
642 | 634 | ||
635 | static const struct regmap_config wm8737_regmap = { | ||
636 | .reg_bits = 7, | ||
637 | .val_bits = 9, | ||
638 | .max_register = WM8737_MAX_REGISTER, | ||
639 | |||
640 | .reg_defaults = wm8737_reg_defaults, | ||
641 | .num_reg_defaults = ARRAY_SIZE(wm8737_reg_defaults), | ||
642 | .cache_type = REGCACHE_RBTREE, | ||
643 | |||
644 | .volatile_reg = wm8737_volatile, | ||
645 | }; | ||
646 | |||
643 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 647 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
644 | static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, | 648 | static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, |
645 | const struct i2c_device_id *id) | 649 | const struct i2c_device_id *id) |
646 | { | 650 | { |
647 | struct wm8737_priv *wm8737; | 651 | struct wm8737_priv *wm8737; |
648 | int ret; | 652 | int ret, i; |
649 | 653 | ||
650 | wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL); | 654 | wm8737 = devm_kzalloc(&i2c->dev, sizeof(struct wm8737_priv), |
655 | GFP_KERNEL); | ||
651 | if (wm8737 == NULL) | 656 | if (wm8737 == NULL) |
652 | return -ENOMEM; | 657 | return -ENOMEM; |
653 | 658 | ||
659 | for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) | ||
660 | wm8737->supplies[i].supply = wm8737_supply_names[i]; | ||
661 | |||
662 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8737->supplies), | ||
663 | wm8737->supplies); | ||
664 | if (ret != 0) { | ||
665 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
666 | return ret; | ||
667 | } | ||
668 | |||
669 | wm8737->regmap = devm_regmap_init_i2c(i2c, &wm8737_regmap); | ||
670 | if (IS_ERR(wm8737->regmap)) | ||
671 | return PTR_ERR(wm8737->regmap); | ||
672 | |||
654 | i2c_set_clientdata(i2c, wm8737); | 673 | i2c_set_clientdata(i2c, wm8737); |
655 | wm8737->control_type = SND_SOC_I2C; | ||
656 | 674 | ||
657 | ret = snd_soc_register_codec(&i2c->dev, | 675 | ret = snd_soc_register_codec(&i2c->dev, |
658 | &soc_codec_dev_wm8737, &wm8737_dai, 1); | 676 | &soc_codec_dev_wm8737, &wm8737_dai, 1); |
659 | if (ret < 0) | 677 | |
660 | kfree(wm8737); | ||
661 | return ret; | 678 | return ret; |
662 | 679 | ||
663 | } | 680 | } |
@@ -665,7 +682,7 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, | |||
665 | static __devexit int wm8737_i2c_remove(struct i2c_client *client) | 682 | static __devexit int wm8737_i2c_remove(struct i2c_client *client) |
666 | { | 683 | { |
667 | snd_soc_unregister_codec(&client->dev); | 684 | snd_soc_unregister_codec(&client->dev); |
668 | kfree(i2c_get_clientdata(client)); | 685 | |
669 | return 0; | 686 | return 0; |
670 | } | 687 | } |
671 | 688 | ||
@@ -691,26 +708,39 @@ static struct i2c_driver wm8737_i2c_driver = { | |||
691 | static int __devinit wm8737_spi_probe(struct spi_device *spi) | 708 | static int __devinit wm8737_spi_probe(struct spi_device *spi) |
692 | { | 709 | { |
693 | struct wm8737_priv *wm8737; | 710 | struct wm8737_priv *wm8737; |
694 | int ret; | 711 | int ret, i; |
695 | 712 | ||
696 | wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL); | 713 | wm8737 = devm_kzalloc(&spi->dev, sizeof(struct wm8737_priv), |
714 | GFP_KERNEL); | ||
697 | if (wm8737 == NULL) | 715 | if (wm8737 == NULL) |
698 | return -ENOMEM; | 716 | return -ENOMEM; |
699 | 717 | ||
700 | wm8737->control_type = SND_SOC_SPI; | 718 | for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) |
719 | wm8737->supplies[i].supply = wm8737_supply_names[i]; | ||
720 | |||
721 | ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8737->supplies), | ||
722 | wm8737->supplies); | ||
723 | if (ret != 0) { | ||
724 | dev_err(&spi->dev, "Failed to request supplies: %d\n", ret); | ||
725 | return ret; | ||
726 | } | ||
727 | |||
728 | wm8737->regmap = devm_regmap_init_spi(spi, &wm8737_regmap); | ||
729 | if (IS_ERR(wm8737->regmap)) | ||
730 | return PTR_ERR(wm8737->regmap); | ||
731 | |||
701 | spi_set_drvdata(spi, wm8737); | 732 | spi_set_drvdata(spi, wm8737); |
702 | 733 | ||
703 | ret = snd_soc_register_codec(&spi->dev, | 734 | ret = snd_soc_register_codec(&spi->dev, |
704 | &soc_codec_dev_wm8737, &wm8737_dai, 1); | 735 | &soc_codec_dev_wm8737, &wm8737_dai, 1); |
705 | if (ret < 0) | 736 | |
706 | kfree(wm8737); | ||
707 | return ret; | 737 | return ret; |
708 | } | 738 | } |
709 | 739 | ||
710 | static int __devexit wm8737_spi_remove(struct spi_device *spi) | 740 | static int __devexit wm8737_spi_remove(struct spi_device *spi) |
711 | { | 741 | { |
712 | snd_soc_unregister_codec(&spi->dev); | 742 | snd_soc_unregister_codec(&spi->dev); |
713 | kfree(spi_get_drvdata(spi)); | 743 | |
714 | return 0; | 744 | return 0; |
715 | } | 745 | } |
716 | 746 | ||
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 35f3d23200e0..4281a0802138 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
21 | #include <linux/regmap.h> | ||
21 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
23 | #include <linux/of_device.h> | 24 | #include <linux/of_device.h> |
@@ -40,26 +41,43 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { | |||
40 | 41 | ||
41 | /* codec private data */ | 42 | /* codec private data */ |
42 | struct wm8741_priv { | 43 | struct wm8741_priv { |
43 | enum snd_soc_control_type control_type; | 44 | struct regmap *regmap; |
44 | struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; | 45 | struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; |
45 | unsigned int sysclk; | 46 | unsigned int sysclk; |
46 | struct snd_pcm_hw_constraint_list *sysclk_constraints; | 47 | struct snd_pcm_hw_constraint_list *sysclk_constraints; |
47 | }; | 48 | }; |
48 | 49 | ||
49 | static const u16 wm8741_reg_defaults[WM8741_REGISTER_COUNT] = { | 50 | static const struct reg_default wm8741_reg_defaults[] = { |
50 | 0x0000, /* R0 - DACLLSB Attenuation */ | 51 | { 0, 0x0000 }, /* R0 - DACLLSB Attenuation */ |
51 | 0x0000, /* R1 - DACLMSB Attenuation */ | 52 | { 1, 0x0000 }, /* R1 - DACLMSB Attenuation */ |
52 | 0x0000, /* R2 - DACRLSB Attenuation */ | 53 | { 2, 0x0000 }, /* R2 - DACRLSB Attenuation */ |
53 | 0x0000, /* R3 - DACRMSB Attenuation */ | 54 | { 3, 0x0000 }, /* R3 - DACRMSB Attenuation */ |
54 | 0x0000, /* R4 - Volume Control */ | 55 | { 4, 0x0000 }, /* R4 - Volume Control */ |
55 | 0x000A, /* R5 - Format Control */ | 56 | { 5, 0x000A }, /* R5 - Format Control */ |
56 | 0x0000, /* R6 - Filter Control */ | 57 | { 6, 0x0000 }, /* R6 - Filter Control */ |
57 | 0x0000, /* R7 - Mode Control 1 */ | 58 | { 7, 0x0000 }, /* R7 - Mode Control 1 */ |
58 | 0x0002, /* R8 - Mode Control 2 */ | 59 | { 8, 0x0002 }, /* R8 - Mode Control 2 */ |
59 | 0x0000, /* R9 - Reset */ | 60 | { 32, 0x0002 }, /* R32 - ADDITONAL_CONTROL_1 */ |
60 | 0x0002, /* R32 - ADDITONAL_CONTROL_1 */ | ||
61 | }; | 61 | }; |
62 | 62 | ||
63 | static bool wm8741_readable(struct device *dev, unsigned int reg) | ||
64 | { | ||
65 | switch (reg) { | ||
66 | case WM8741_DACLLSB_ATTENUATION: | ||
67 | case WM8741_DACLMSB_ATTENUATION: | ||
68 | case WM8741_DACRLSB_ATTENUATION: | ||
69 | case WM8741_DACRMSB_ATTENUATION: | ||
70 | case WM8741_VOLUME_CONTROL: | ||
71 | case WM8741_FORMAT_CONTROL: | ||
72 | case WM8741_FILTER_CONTROL: | ||
73 | case WM8741_MODE_CONTROL_1: | ||
74 | case WM8741_MODE_CONTROL_2: | ||
75 | case WM8741_ADDITIONAL_CONTROL_1: | ||
76 | return true; | ||
77 | default: | ||
78 | return false; | ||
79 | } | ||
80 | } | ||
63 | 81 | ||
64 | static int wm8741_reset(struct snd_soc_codec *codec) | 82 | static int wm8741_reset(struct snd_soc_codec *codec) |
65 | { | 83 | { |
@@ -403,17 +421,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
403 | { | 421 | { |
404 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | 422 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
405 | int ret = 0; | 423 | int ret = 0; |
406 | int i; | ||
407 | |||
408 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) | ||
409 | wm8741->supplies[i].supply = wm8741_supply_names[i]; | ||
410 | |||
411 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), | ||
412 | wm8741->supplies); | ||
413 | if (ret != 0) { | ||
414 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
415 | goto err; | ||
416 | } | ||
417 | 424 | ||
418 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), | 425 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), |
419 | wm8741->supplies); | 426 | wm8741->supplies); |
@@ -422,7 +429,7 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
422 | goto err_get; | 429 | goto err_get; |
423 | } | 430 | } |
424 | 431 | ||
425 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); | 432 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
426 | if (ret != 0) { | 433 | if (ret != 0) { |
427 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 434 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
428 | goto err_enable; | 435 | goto err_enable; |
@@ -450,8 +457,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
450 | err_enable: | 457 | err_enable: |
451 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | 458 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); |
452 | err_get: | 459 | err_get: |
453 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
454 | err: | ||
455 | return ret; | 460 | return ret; |
456 | } | 461 | } |
457 | 462 | ||
@@ -460,7 +465,6 @@ static int wm8741_remove(struct snd_soc_codec *codec) | |||
460 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | 465 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
461 | 466 | ||
462 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | 467 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); |
463 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
464 | 468 | ||
465 | return 0; | 469 | return 0; |
466 | } | 470 | } |
@@ -469,9 +473,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { | |||
469 | .probe = wm8741_probe, | 473 | .probe = wm8741_probe, |
470 | .remove = wm8741_remove, | 474 | .remove = wm8741_remove, |
471 | .resume = wm8741_resume, | 475 | .resume = wm8741_resume, |
472 | .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults), | ||
473 | .reg_word_size = sizeof(u16), | ||
474 | .reg_cache_default = wm8741_reg_defaults, | ||
475 | 476 | ||
476 | .controls = wm8741_snd_controls, | 477 | .controls = wm8741_snd_controls, |
477 | .num_controls = ARRAY_SIZE(wm8741_snd_controls), | 478 | .num_controls = ARRAY_SIZE(wm8741_snd_controls), |
@@ -487,20 +488,48 @@ static const struct of_device_id wm8741_of_match[] = { | |||
487 | }; | 488 | }; |
488 | MODULE_DEVICE_TABLE(of, wm8741_of_match); | 489 | MODULE_DEVICE_TABLE(of, wm8741_of_match); |
489 | 490 | ||
491 | static const struct regmap_config wm8741_regmap = { | ||
492 | .reg_bits = 7, | ||
493 | .val_bits = 9, | ||
494 | .max_register = WM8741_MAX_REGISTER, | ||
495 | |||
496 | .reg_defaults = wm8741_reg_defaults, | ||
497 | .num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults), | ||
498 | .cache_type = REGCACHE_RBTREE, | ||
499 | |||
500 | .readable_reg = wm8741_readable, | ||
501 | }; | ||
502 | |||
490 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 503 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
491 | static int wm8741_i2c_probe(struct i2c_client *i2c, | 504 | static int wm8741_i2c_probe(struct i2c_client *i2c, |
492 | const struct i2c_device_id *id) | 505 | const struct i2c_device_id *id) |
493 | { | 506 | { |
494 | struct wm8741_priv *wm8741; | 507 | struct wm8741_priv *wm8741; |
495 | int ret; | 508 | int ret, i; |
496 | 509 | ||
497 | wm8741 = devm_kzalloc(&i2c->dev, sizeof(struct wm8741_priv), | 510 | wm8741 = devm_kzalloc(&i2c->dev, sizeof(struct wm8741_priv), |
498 | GFP_KERNEL); | 511 | GFP_KERNEL); |
499 | if (wm8741 == NULL) | 512 | if (wm8741 == NULL) |
500 | return -ENOMEM; | 513 | return -ENOMEM; |
501 | 514 | ||
515 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) | ||
516 | wm8741->supplies[i].supply = wm8741_supply_names[i]; | ||
517 | |||
518 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), | ||
519 | wm8741->supplies); | ||
520 | if (ret != 0) { | ||
521 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
522 | return ret; | ||
523 | } | ||
524 | |||
525 | wm8741->regmap = regmap_init_i2c(i2c, &wm8741_regmap); | ||
526 | if (IS_ERR(wm8741->regmap)) { | ||
527 | ret = PTR_ERR(wm8741->regmap); | ||
528 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); | ||
529 | return ret; | ||
530 | } | ||
531 | |||
502 | i2c_set_clientdata(i2c, wm8741); | 532 | i2c_set_clientdata(i2c, wm8741); |
503 | wm8741->control_type = SND_SOC_I2C; | ||
504 | 533 | ||
505 | ret = snd_soc_register_codec(&i2c->dev, | 534 | ret = snd_soc_register_codec(&i2c->dev, |
506 | &soc_codec_dev_wm8741, &wm8741_dai, 1); | 535 | &soc_codec_dev_wm8741, &wm8741_dai, 1); |
@@ -536,14 +565,30 @@ static struct i2c_driver wm8741_i2c_driver = { | |||
536 | static int __devinit wm8741_spi_probe(struct spi_device *spi) | 565 | static int __devinit wm8741_spi_probe(struct spi_device *spi) |
537 | { | 566 | { |
538 | struct wm8741_priv *wm8741; | 567 | struct wm8741_priv *wm8741; |
539 | int ret; | 568 | int ret, i; |
540 | 569 | ||
541 | wm8741 = devm_kzalloc(&spi->dev, sizeof(struct wm8741_priv), | 570 | wm8741 = devm_kzalloc(&spi->dev, sizeof(struct wm8741_priv), |
542 | GFP_KERNEL); | 571 | GFP_KERNEL); |
543 | if (wm8741 == NULL) | 572 | if (wm8741 == NULL) |
544 | return -ENOMEM; | 573 | return -ENOMEM; |
545 | 574 | ||
546 | wm8741->control_type = SND_SOC_SPI; | 575 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) |
576 | wm8741->supplies[i].supply = wm8741_supply_names[i]; | ||
577 | |||
578 | ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8741->supplies), | ||
579 | wm8741->supplies); | ||
580 | if (ret != 0) { | ||
581 | dev_err(&spi->dev, "Failed to request supplies: %d\n", ret); | ||
582 | return ret; | ||
583 | } | ||
584 | |||
585 | wm8741->regmap = regmap_init_spi(spi, &wm8741_regmap); | ||
586 | if (IS_ERR(wm8741->regmap)) { | ||
587 | ret = PTR_ERR(wm8741->regmap); | ||
588 | dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); | ||
589 | return ret; | ||
590 | } | ||
591 | |||
547 | spi_set_drvdata(spi, wm8741); | 592 | spi_set_drvdata(spi, wm8741); |
548 | 593 | ||
549 | ret = snd_soc_register_codec(&spi->dev, | 594 | ret = snd_soc_register_codec(&spi->dev, |
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index a5127b4ff9e1..c7c0034d3966 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c | |||
@@ -724,24 +724,7 @@ static struct spi_driver wm8770_spi_driver = { | |||
724 | .remove = __devexit_p(wm8770_spi_remove) | 724 | .remove = __devexit_p(wm8770_spi_remove) |
725 | }; | 725 | }; |
726 | 726 | ||
727 | static int __init wm8770_modinit(void) | 727 | module_spi_driver(wm8770_spi_driver); |
728 | { | ||
729 | int ret = 0; | ||
730 | |||
731 | ret = spi_register_driver(&wm8770_spi_driver); | ||
732 | if (ret) { | ||
733 | printk(KERN_ERR "Failed to register wm8770 SPI driver: %d\n", | ||
734 | ret); | ||
735 | } | ||
736 | return ret; | ||
737 | } | ||
738 | module_init(wm8770_modinit); | ||
739 | |||
740 | static void __exit wm8770_exit(void) | ||
741 | { | ||
742 | spi_unregister_driver(&wm8770_spi_driver); | ||
743 | } | ||
744 | module_exit(wm8770_exit); | ||
745 | 728 | ||
746 | MODULE_DESCRIPTION("ASoC WM8770 driver"); | 729 | MODULE_DESCRIPTION("ASoC WM8770 driver"); |
747 | MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>"); | 730 | MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 879c356a9045..c32249ddb2e0 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/of_device.h> | 21 | #include <linux/of_device.h> |
22 | #include <linux/regmap.h> | ||
22 | #include <linux/spi/spi.h> | 23 | #include <linux/spi/spi.h> |
23 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
@@ -37,18 +38,46 @@ enum wm8776_chip_type { | |||
37 | 38 | ||
38 | /* codec private data */ | 39 | /* codec private data */ |
39 | struct wm8776_priv { | 40 | struct wm8776_priv { |
40 | enum snd_soc_control_type control_type; | 41 | struct regmap *regmap; |
41 | int sysclk[2]; | 42 | int sysclk[2]; |
42 | }; | 43 | }; |
43 | 44 | ||
44 | static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { | 45 | static const struct reg_default wm8776_reg_defaults[] = { |
45 | 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ | 46 | { 0, 0x79 }, |
46 | 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ | 47 | { 1, 0x79 }, |
47 | 0x22, 0x22, 0x22, 0x08, 0xcf, /* 14 */ | 48 | { 2, 0x79 }, |
48 | 0xcf, 0x7b, 0x00, 0x32, 0x00, /* 19 */ | 49 | { 3, 0xff }, |
49 | 0xa6, 0x01, 0x01 | 50 | { 4, 0xff }, |
51 | { 5, 0xff }, | ||
52 | { 6, 0x00 }, | ||
53 | { 7, 0x90 }, | ||
54 | { 8, 0x00 }, | ||
55 | { 9, 0x00 }, | ||
56 | { 10, 0x22 }, | ||
57 | { 11, 0x22 }, | ||
58 | { 12, 0x22 }, | ||
59 | { 13, 0x08 }, | ||
60 | { 14, 0xcf }, | ||
61 | { 15, 0xcf }, | ||
62 | { 16, 0x7b }, | ||
63 | { 17, 0x00 }, | ||
64 | { 18, 0x32 }, | ||
65 | { 19, 0x00 }, | ||
66 | { 20, 0xa6 }, | ||
67 | { 21, 0x01 }, | ||
68 | { 22, 0x01 }, | ||
50 | }; | 69 | }; |
51 | 70 | ||
71 | static bool wm8776_volatile(struct device *dev, unsigned int reg) | ||
72 | { | ||
73 | switch (reg) { | ||
74 | case WM8776_RESET: | ||
75 | return true; | ||
76 | default: | ||
77 | return false; | ||
78 | } | ||
79 | } | ||
80 | |||
52 | static int wm8776_reset(struct snd_soc_codec *codec) | 81 | static int wm8776_reset(struct snd_soc_codec *codec) |
53 | { | 82 | { |
54 | return snd_soc_write(codec, WM8776_RESET, 0); | 83 | return snd_soc_write(codec, WM8776_RESET, 0); |
@@ -306,6 +335,8 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai, | |||
306 | static int wm8776_set_bias_level(struct snd_soc_codec *codec, | 335 | static int wm8776_set_bias_level(struct snd_soc_codec *codec, |
307 | enum snd_soc_bias_level level) | 336 | enum snd_soc_bias_level level) |
308 | { | 337 | { |
338 | struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); | ||
339 | |||
309 | switch (level) { | 340 | switch (level) { |
310 | case SND_SOC_BIAS_ON: | 341 | case SND_SOC_BIAS_ON: |
311 | break; | 342 | break; |
@@ -313,7 +344,7 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec, | |||
313 | break; | 344 | break; |
314 | case SND_SOC_BIAS_STANDBY: | 345 | case SND_SOC_BIAS_STANDBY: |
315 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 346 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
316 | snd_soc_cache_sync(codec); | 347 | regcache_sync(wm8776->regmap); |
317 | 348 | ||
318 | /* Disable the global powerdown; DAPM does the rest */ | 349 | /* Disable the global powerdown; DAPM does the rest */ |
319 | snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); | 350 | snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); |
@@ -396,10 +427,9 @@ static int wm8776_resume(struct snd_soc_codec *codec) | |||
396 | 427 | ||
397 | static int wm8776_probe(struct snd_soc_codec *codec) | 428 | static int wm8776_probe(struct snd_soc_codec *codec) |
398 | { | 429 | { |
399 | struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); | ||
400 | int ret = 0; | 430 | int ret = 0; |
401 | 431 | ||
402 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type); | 432 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
403 | if (ret < 0) { | 433 | if (ret < 0) { |
404 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 434 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
405 | return ret; | 435 | return ret; |
@@ -434,9 +464,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { | |||
434 | .suspend = wm8776_suspend, | 464 | .suspend = wm8776_suspend, |
435 | .resume = wm8776_resume, | 465 | .resume = wm8776_resume, |
436 | .set_bias_level = wm8776_set_bias_level, | 466 | .set_bias_level = wm8776_set_bias_level, |
437 | .reg_cache_size = ARRAY_SIZE(wm8776_reg), | ||
438 | .reg_word_size = sizeof(u16), | ||
439 | .reg_cache_default = wm8776_reg, | ||
440 | 467 | ||
441 | .controls = wm8776_snd_controls, | 468 | .controls = wm8776_snd_controls, |
442 | .num_controls = ARRAY_SIZE(wm8776_snd_controls), | 469 | .num_controls = ARRAY_SIZE(wm8776_snd_controls), |
@@ -452,6 +479,18 @@ static const struct of_device_id wm8776_of_match[] = { | |||
452 | }; | 479 | }; |
453 | MODULE_DEVICE_TABLE(of, wm8776_of_match); | 480 | MODULE_DEVICE_TABLE(of, wm8776_of_match); |
454 | 481 | ||
482 | static const struct regmap_config wm8776_regmap = { | ||
483 | .reg_bits = 7, | ||
484 | .val_bits = 9, | ||
485 | .max_register = WM8776_RESET, | ||
486 | |||
487 | .reg_defaults = wm8776_reg_defaults, | ||
488 | .num_reg_defaults = ARRAY_SIZE(wm8776_reg_defaults), | ||
489 | .cache_type = REGCACHE_RBTREE, | ||
490 | |||
491 | .volatile_reg = wm8776_volatile, | ||
492 | }; | ||
493 | |||
455 | #if defined(CONFIG_SPI_MASTER) | 494 | #if defined(CONFIG_SPI_MASTER) |
456 | static int __devinit wm8776_spi_probe(struct spi_device *spi) | 495 | static int __devinit wm8776_spi_probe(struct spi_device *spi) |
457 | { | 496 | { |
@@ -463,7 +502,10 @@ static int __devinit wm8776_spi_probe(struct spi_device *spi) | |||
463 | if (wm8776 == NULL) | 502 | if (wm8776 == NULL) |
464 | return -ENOMEM; | 503 | return -ENOMEM; |
465 | 504 | ||
466 | wm8776->control_type = SND_SOC_SPI; | 505 | wm8776->regmap = devm_regmap_init_spi(spi, &wm8776_regmap); |
506 | if (IS_ERR(wm8776->regmap)) | ||
507 | return PTR_ERR(wm8776->regmap); | ||
508 | |||
467 | spi_set_drvdata(spi, wm8776); | 509 | spi_set_drvdata(spi, wm8776); |
468 | 510 | ||
469 | ret = snd_soc_register_codec(&spi->dev, | 511 | ret = snd_soc_register_codec(&spi->dev, |
@@ -501,8 +543,11 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c, | |||
501 | if (wm8776 == NULL) | 543 | if (wm8776 == NULL) |
502 | return -ENOMEM; | 544 | return -ENOMEM; |
503 | 545 | ||
546 | wm8776->regmap = devm_regmap_init_i2c(i2c, &wm8776_regmap); | ||
547 | if (IS_ERR(wm8776->regmap)) | ||
548 | return PTR_ERR(wm8776->regmap); | ||
549 | |||
504 | i2c_set_clientdata(i2c, wm8776); | 550 | i2c_set_clientdata(i2c, wm8776); |
505 | wm8776->control_type = SND_SOC_I2C; | ||
506 | 551 | ||
507 | ret = snd_soc_register_codec(&i2c->dev, | 552 | ret = snd_soc_register_codec(&i2c->dev, |
508 | &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); | 553 | &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); |
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 077c9628c70d..e781f865e5d7 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/regmap.h> | ||
26 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
@@ -137,7 +138,7 @@ | |||
137 | #define WM8900_LRC_MASK 0x03ff | 138 | #define WM8900_LRC_MASK 0x03ff |
138 | 139 | ||
139 | struct wm8900_priv { | 140 | struct wm8900_priv { |
140 | enum snd_soc_control_type control_type; | 141 | struct regmap *regmap; |
141 | 142 | ||
142 | u32 fll_in; /* FLL input frequency */ | 143 | u32 fll_in; /* FLL input frequency */ |
143 | u32 fll_out; /* FLL output frequency */ | 144 | u32 fll_out; /* FLL output frequency */ |
@@ -147,54 +148,77 @@ struct wm8900_priv { | |||
147 | * wm8900 register cache. We can't read the entire register space and we | 148 | * wm8900 register cache. We can't read the entire register space and we |
148 | * have slow control buses so we cache the registers. | 149 | * have slow control buses so we cache the registers. |
149 | */ | 150 | */ |
150 | static const u16 wm8900_reg_defaults[WM8900_MAXREG] = { | 151 | static const struct reg_default wm8900_reg_defaults[] = { |
151 | 0x8900, 0x0000, | 152 | { 1, 0x0000 }, |
152 | 0xc000, 0x0000, | 153 | { 2, 0xc000 }, |
153 | 0x4050, 0x4000, | 154 | { 3, 0x0000 }, |
154 | 0x0008, 0x0000, | 155 | { 4, 0x4050 }, |
155 | 0x0040, 0x0040, | 156 | { 5, 0x4000 }, |
156 | 0x1004, 0x00c0, | 157 | { 6, 0x0008 }, |
157 | 0x00c0, 0x0000, | 158 | { 7, 0x0000 }, |
158 | 0x0100, 0x00c0, | 159 | { 8, 0x0040 }, |
159 | 0x00c0, 0x0000, | 160 | { 9, 0x0040 }, |
160 | 0xb001, 0x0000, | 161 | { 10, 0x1004 }, |
161 | 0x0000, 0x0044, | 162 | { 11, 0x00c0 }, |
162 | 0x004c, 0x004c, | 163 | { 12, 0x00c0 }, |
163 | 0x0044, 0x0044, | 164 | { 13, 0x0000 }, |
164 | 0x0000, 0x0044, | 165 | { 14, 0x0100 }, |
165 | 0x0000, 0x0000, | 166 | { 15, 0x00c0 }, |
166 | 0x0002, 0x0000, | 167 | { 16, 0x00c0 }, |
167 | 0x0000, 0x0000, | 168 | { 17, 0x0000 }, |
168 | 0x0000, 0x0000, | 169 | { 18, 0xb001 }, |
169 | 0x0008, 0x0000, | 170 | { 19, 0x0000 }, |
170 | 0x0000, 0x0008, | 171 | { 20, 0x0000 }, |
171 | 0x0097, 0x0100, | 172 | { 21, 0x0044 }, |
172 | 0x0000, 0x0000, | 173 | { 22, 0x004c }, |
173 | 0x0050, 0x0050, | 174 | { 23, 0x004c }, |
174 | 0x0055, 0x0055, | 175 | { 24, 0x0044 }, |
175 | 0x0055, 0x0000, | 176 | { 25, 0x0044 }, |
176 | 0x0000, 0x0079, | 177 | { 26, 0x0000 }, |
177 | 0x0079, 0x0079, | 178 | { 27, 0x0044 }, |
178 | 0x0079, 0x0000, | 179 | { 28, 0x0000 }, |
179 | /* Remaining registers all zero */ | 180 | { 29, 0x0000 }, |
181 | { 30, 0x0002 }, | ||
182 | { 31, 0x0000 }, | ||
183 | { 32, 0x0000 }, | ||
184 | { 33, 0x0000 }, | ||
185 | { 34, 0x0000 }, | ||
186 | { 35, 0x0000 }, | ||
187 | { 36, 0x0008 }, | ||
188 | { 37, 0x0000 }, | ||
189 | { 38, 0x0000 }, | ||
190 | { 39, 0x0008 }, | ||
191 | { 40, 0x0097 }, | ||
192 | { 41, 0x0100 }, | ||
193 | { 42, 0x0000 }, | ||
194 | { 43, 0x0000 }, | ||
195 | { 44, 0x0050 }, | ||
196 | { 45, 0x0050 }, | ||
197 | { 46, 0x0055 }, | ||
198 | { 47, 0x0055 }, | ||
199 | { 48, 0x0055 }, | ||
200 | { 49, 0x0000 }, | ||
201 | { 50, 0x0000 }, | ||
202 | { 51, 0x0079 }, | ||
203 | { 52, 0x0079 }, | ||
204 | { 53, 0x0079 }, | ||
205 | { 54, 0x0079 }, | ||
206 | { 55, 0x0000 }, | ||
180 | }; | 207 | }; |
181 | 208 | ||
182 | static int wm8900_volatile_register(struct snd_soc_codec *codec, unsigned int reg) | 209 | static bool wm8900_volatile_register(struct device *dev, unsigned int reg) |
183 | { | 210 | { |
184 | switch (reg) { | 211 | switch (reg) { |
185 | case WM8900_REG_ID: | 212 | case WM8900_REG_ID: |
186 | return 1; | 213 | return true; |
187 | default: | 214 | default: |
188 | return 0; | 215 | return false; |
189 | } | 216 | } |
190 | } | 217 | } |
191 | 218 | ||
192 | static void wm8900_reset(struct snd_soc_codec *codec) | 219 | static void wm8900_reset(struct snd_soc_codec *codec) |
193 | { | 220 | { |
194 | snd_soc_write(codec, WM8900_REG_RESET, 0); | 221 | snd_soc_write(codec, WM8900_REG_RESET, 0); |
195 | |||
196 | memcpy(codec->reg_cache, wm8900_reg_defaults, | ||
197 | sizeof(wm8900_reg_defaults)); | ||
198 | } | 222 | } |
199 | 223 | ||
200 | static int wm8900_hp_event(struct snd_soc_dapm_widget *w, | 224 | static int wm8900_hp_event(struct snd_soc_dapm_widget *w, |
@@ -469,10 +493,10 @@ SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INCTL, 1, 1, 0), | |||
469 | SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0), | 493 | SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0), |
470 | }; | 494 | }; |
471 | 495 | ||
472 | static const char *wm9700_lp_mux[] = { "Disabled", "Enabled" }; | 496 | static const char *wm8900_lp_mux[] = { "Disabled", "Enabled" }; |
473 | 497 | ||
474 | static const struct soc_enum wm8900_lineout2_lp_mux = | 498 | static const struct soc_enum wm8900_lineout2_lp_mux = |
475 | SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm9700_lp_mux); | 499 | SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm8900_lp_mux); |
476 | 500 | ||
477 | static const struct snd_kcontrol_new wm8900_lineout2_lp = | 501 | static const struct snd_kcontrol_new wm8900_lineout2_lp = |
478 | SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux); | 502 | SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux); |
@@ -1119,13 +1143,16 @@ static int wm8900_suspend(struct snd_soc_codec *codec) | |||
1119 | static int wm8900_resume(struct snd_soc_codec *codec) | 1143 | static int wm8900_resume(struct snd_soc_codec *codec) |
1120 | { | 1144 | { |
1121 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); | 1145 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); |
1122 | u16 *cache; | 1146 | int ret; |
1123 | int i, ret; | ||
1124 | |||
1125 | cache = kmemdup(codec->reg_cache, sizeof(wm8900_reg_defaults), | ||
1126 | GFP_KERNEL); | ||
1127 | 1147 | ||
1128 | wm8900_reset(codec); | 1148 | wm8900_reset(codec); |
1149 | |||
1150 | ret = regcache_sync(wm8900->regmap); | ||
1151 | if (ret != 0) { | ||
1152 | dev_err(codec->dev, "Failed to restore cache: %d\n", ret); | ||
1153 | return ret; | ||
1154 | } | ||
1155 | |||
1129 | wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1156 | wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1130 | 1157 | ||
1131 | /* Restart the FLL? */ | 1158 | /* Restart the FLL? */ |
@@ -1139,27 +1166,18 @@ static int wm8900_resume(struct snd_soc_codec *codec) | |||
1139 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); | 1166 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); |
1140 | if (ret != 0) { | 1167 | if (ret != 0) { |
1141 | dev_err(codec->dev, "Failed to restart FLL\n"); | 1168 | dev_err(codec->dev, "Failed to restart FLL\n"); |
1142 | kfree(cache); | ||
1143 | return ret; | 1169 | return ret; |
1144 | } | 1170 | } |
1145 | } | 1171 | } |
1146 | 1172 | ||
1147 | if (cache) { | ||
1148 | for (i = 0; i < WM8900_MAXREG; i++) | ||
1149 | snd_soc_write(codec, i, cache[i]); | ||
1150 | kfree(cache); | ||
1151 | } else | ||
1152 | dev_err(codec->dev, "Unable to allocate register cache\n"); | ||
1153 | |||
1154 | return 0; | 1173 | return 0; |
1155 | } | 1174 | } |
1156 | 1175 | ||
1157 | static int wm8900_probe(struct snd_soc_codec *codec) | 1176 | static int wm8900_probe(struct snd_soc_codec *codec) |
1158 | { | 1177 | { |
1159 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); | ||
1160 | int ret = 0, reg; | 1178 | int ret = 0, reg; |
1161 | 1179 | ||
1162 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type); | 1180 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); |
1163 | if (ret != 0) { | 1181 | if (ret != 0) { |
1164 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 1182 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1165 | return ret; | 1183 | return ret; |
@@ -1207,10 +1225,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { | |||
1207 | .suspend = wm8900_suspend, | 1225 | .suspend = wm8900_suspend, |
1208 | .resume = wm8900_resume, | 1226 | .resume = wm8900_resume, |
1209 | .set_bias_level = wm8900_set_bias_level, | 1227 | .set_bias_level = wm8900_set_bias_level, |
1210 | .volatile_register = wm8900_volatile_register, | ||
1211 | .reg_cache_size = ARRAY_SIZE(wm8900_reg_defaults), | ||
1212 | .reg_word_size = sizeof(u16), | ||
1213 | .reg_cache_default = wm8900_reg_defaults, | ||
1214 | 1228 | ||
1215 | .controls = wm8900_snd_controls, | 1229 | .controls = wm8900_snd_controls, |
1216 | .num_controls = ARRAY_SIZE(wm8900_snd_controls), | 1230 | .num_controls = ARRAY_SIZE(wm8900_snd_controls), |
@@ -1220,30 +1234,44 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { | |||
1220 | .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes), | 1234 | .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes), |
1221 | }; | 1235 | }; |
1222 | 1236 | ||
1237 | static const struct regmap_config wm8900_regmap = { | ||
1238 | .reg_bits = 8, | ||
1239 | .val_bits = 16, | ||
1240 | .max_register = WM8900_MAXREG, | ||
1241 | |||
1242 | .reg_defaults = wm8900_reg_defaults, | ||
1243 | .num_reg_defaults = ARRAY_SIZE(wm8900_reg_defaults), | ||
1244 | .cache_type = REGCACHE_RBTREE, | ||
1245 | |||
1246 | .volatile_reg = wm8900_volatile_register, | ||
1247 | }; | ||
1248 | |||
1223 | #if defined(CONFIG_SPI_MASTER) | 1249 | #if defined(CONFIG_SPI_MASTER) |
1224 | static int __devinit wm8900_spi_probe(struct spi_device *spi) | 1250 | static int __devinit wm8900_spi_probe(struct spi_device *spi) |
1225 | { | 1251 | { |
1226 | struct wm8900_priv *wm8900; | 1252 | struct wm8900_priv *wm8900; |
1227 | int ret; | 1253 | int ret; |
1228 | 1254 | ||
1229 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | 1255 | wm8900 = devm_kzalloc(&spi->dev, sizeof(struct wm8900_priv), |
1256 | GFP_KERNEL); | ||
1230 | if (wm8900 == NULL) | 1257 | if (wm8900 == NULL) |
1231 | return -ENOMEM; | 1258 | return -ENOMEM; |
1232 | 1259 | ||
1233 | wm8900->control_type = SND_SOC_SPI; | 1260 | wm8900->regmap = devm_regmap_init_spi(spi, &wm8900_regmap); |
1261 | if (IS_ERR(wm8900->regmap)) | ||
1262 | return PTR_ERR(wm8900->regmap); | ||
1263 | |||
1234 | spi_set_drvdata(spi, wm8900); | 1264 | spi_set_drvdata(spi, wm8900); |
1235 | 1265 | ||
1236 | ret = snd_soc_register_codec(&spi->dev, | 1266 | ret = snd_soc_register_codec(&spi->dev, |
1237 | &soc_codec_dev_wm8900, &wm8900_dai, 1); | 1267 | &soc_codec_dev_wm8900, &wm8900_dai, 1); |
1238 | if (ret < 0) | 1268 | |
1239 | kfree(wm8900); | ||
1240 | return ret; | 1269 | return ret; |
1241 | } | 1270 | } |
1242 | 1271 | ||
1243 | static int __devexit wm8900_spi_remove(struct spi_device *spi) | 1272 | static int __devexit wm8900_spi_remove(struct spi_device *spi) |
1244 | { | 1273 | { |
1245 | snd_soc_unregister_codec(&spi->dev); | 1274 | snd_soc_unregister_codec(&spi->dev); |
1246 | kfree(spi_get_drvdata(spi)); | ||
1247 | return 0; | 1275 | return 0; |
1248 | } | 1276 | } |
1249 | 1277 | ||
@@ -1264,24 +1292,26 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, | |||
1264 | struct wm8900_priv *wm8900; | 1292 | struct wm8900_priv *wm8900; |
1265 | int ret; | 1293 | int ret; |
1266 | 1294 | ||
1267 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | 1295 | wm8900 = devm_kzalloc(&i2c->dev, sizeof(struct wm8900_priv), |
1296 | GFP_KERNEL); | ||
1268 | if (wm8900 == NULL) | 1297 | if (wm8900 == NULL) |
1269 | return -ENOMEM; | 1298 | return -ENOMEM; |
1270 | 1299 | ||
1300 | wm8900->regmap = devm_regmap_init_i2c(i2c, &wm8900_regmap); | ||
1301 | if (IS_ERR(wm8900->regmap)) | ||
1302 | return PTR_ERR(wm8900->regmap); | ||
1303 | |||
1271 | i2c_set_clientdata(i2c, wm8900); | 1304 | i2c_set_clientdata(i2c, wm8900); |
1272 | wm8900->control_type = SND_SOC_I2C; | ||
1273 | 1305 | ||
1274 | ret = snd_soc_register_codec(&i2c->dev, | 1306 | ret = snd_soc_register_codec(&i2c->dev, |
1275 | &soc_codec_dev_wm8900, &wm8900_dai, 1); | 1307 | &soc_codec_dev_wm8900, &wm8900_dai, 1); |
1276 | if (ret < 0) | 1308 | |
1277 | kfree(wm8900); | ||
1278 | return ret; | 1309 | return ret; |
1279 | } | 1310 | } |
1280 | 1311 | ||
1281 | static __devexit int wm8900_i2c_remove(struct i2c_client *client) | 1312 | static __devexit int wm8900_i2c_remove(struct i2c_client *client) |
1282 | { | 1313 | { |
1283 | snd_soc_unregister_codec(&client->dev); | 1314 | snd_soc_unregister_codec(&client->dev); |
1284 | kfree(i2c_get_clientdata(client)); | ||
1285 | return 0; | 1315 | return 0; |
1286 | } | 1316 | } |
1287 | 1317 | ||
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 73f1c8d7bafb..839414f9e2ed 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -2241,23 +2241,7 @@ static struct i2c_driver wm8903_i2c_driver = { | |||
2241 | .id_table = wm8903_i2c_id, | 2241 | .id_table = wm8903_i2c_id, |
2242 | }; | 2242 | }; |
2243 | 2243 | ||
2244 | static int __init wm8903_modinit(void) | 2244 | module_i2c_driver(wm8903_i2c_driver); |
2245 | { | ||
2246 | int ret = 0; | ||
2247 | ret = i2c_add_driver(&wm8903_i2c_driver); | ||
2248 | if (ret != 0) { | ||
2249 | printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n", | ||
2250 | ret); | ||
2251 | } | ||
2252 | return ret; | ||
2253 | } | ||
2254 | module_init(wm8903_modinit); | ||
2255 | |||
2256 | static void __exit wm8903_exit(void) | ||
2257 | { | ||
2258 | i2c_del_driver(&wm8903_i2c_driver); | ||
2259 | } | ||
2260 | module_exit(wm8903_exit); | ||
2261 | 2245 | ||
2262 | MODULE_DESCRIPTION("ASoC WM8903 driver"); | 2246 | MODULE_DESCRIPTION("ASoC WM8903 driver"); |
2263 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>"); | 2247 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>"); |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index dc4262eea4b7..7c8df52a8d9d 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -1185,8 +1185,6 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec) | |||
1185 | snd_soc_dapm_new_controls(dapm, wm8904_dapm_widgets, | 1185 | snd_soc_dapm_new_controls(dapm, wm8904_dapm_widgets, |
1186 | ARRAY_SIZE(wm8904_dapm_widgets)); | 1186 | ARRAY_SIZE(wm8904_dapm_widgets)); |
1187 | 1187 | ||
1188 | snd_soc_dapm_add_routes(dapm, core_intercon, | ||
1189 | ARRAY_SIZE(core_intercon)); | ||
1190 | snd_soc_dapm_add_routes(dapm, adc_intercon, | 1188 | snd_soc_dapm_add_routes(dapm, adc_intercon, |
1191 | ARRAY_SIZE(adc_intercon)); | 1189 | ARRAY_SIZE(adc_intercon)); |
1192 | snd_soc_dapm_add_routes(dapm, dac_intercon, | 1190 | snd_soc_dapm_add_routes(dapm, dac_intercon, |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 481a3d9cfe48..b20aa4e7c3f9 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -785,23 +785,7 @@ static struct i2c_driver wm8940_i2c_driver = { | |||
785 | .id_table = wm8940_i2c_id, | 785 | .id_table = wm8940_i2c_id, |
786 | }; | 786 | }; |
787 | 787 | ||
788 | static int __init wm8940_modinit(void) | 788 | module_i2c_driver(wm8940_i2c_driver); |
789 | { | ||
790 | int ret = 0; | ||
791 | ret = i2c_add_driver(&wm8940_i2c_driver); | ||
792 | if (ret != 0) { | ||
793 | printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n", | ||
794 | ret); | ||
795 | } | ||
796 | return ret; | ||
797 | } | ||
798 | module_init(wm8940_modinit); | ||
799 | |||
800 | static void __exit wm8940_exit(void) | ||
801 | { | ||
802 | i2c_del_driver(&wm8940_i2c_driver); | ||
803 | } | ||
804 | module_exit(wm8940_exit); | ||
805 | 789 | ||
806 | MODULE_DESCRIPTION("ASoC WM8940 driver"); | 790 | MODULE_DESCRIPTION("ASoC WM8940 driver"); |
807 | MODULE_AUTHOR("Jonathan Cameron"); | 791 | MODULE_AUTHOR("Jonathan Cameron"); |
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 61fe97433e73..2f1c075755b1 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -1071,23 +1071,7 @@ static struct i2c_driver wm8955_i2c_driver = { | |||
1071 | .id_table = wm8955_i2c_id, | 1071 | .id_table = wm8955_i2c_id, |
1072 | }; | 1072 | }; |
1073 | 1073 | ||
1074 | static int __init wm8955_modinit(void) | 1074 | module_i2c_driver(wm8955_i2c_driver); |
1075 | { | ||
1076 | int ret = 0; | ||
1077 | ret = i2c_add_driver(&wm8955_i2c_driver); | ||
1078 | if (ret != 0) { | ||
1079 | printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n", | ||
1080 | ret); | ||
1081 | } | ||
1082 | return ret; | ||
1083 | } | ||
1084 | module_init(wm8955_modinit); | ||
1085 | |||
1086 | static void __exit wm8955_exit(void) | ||
1087 | { | ||
1088 | i2c_del_driver(&wm8955_i2c_driver); | ||
1089 | } | ||
1090 | module_exit(wm8955_exit); | ||
1091 | 1075 | ||
1092 | MODULE_DESCRIPTION("ASoC WM8955 driver"); | 1076 | MODULE_DESCRIPTION("ASoC WM8955 driver"); |
1093 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 1077 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 1332692ef81b..00121ba36597 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c | |||
@@ -946,7 +946,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
946 | wm8994->mbc_texts = kmalloc(sizeof(char *) | 946 | wm8994->mbc_texts = kmalloc(sizeof(char *) |
947 | * pdata->num_mbc_cfgs, GFP_KERNEL); | 947 | * pdata->num_mbc_cfgs, GFP_KERNEL); |
948 | if (!wm8994->mbc_texts) { | 948 | if (!wm8994->mbc_texts) { |
949 | dev_err(wm8994->codec->dev, | 949 | dev_err(wm8994->hubs.codec->dev, |
950 | "Failed to allocate %d MBC config texts\n", | 950 | "Failed to allocate %d MBC config texts\n", |
951 | pdata->num_mbc_cfgs); | 951 | pdata->num_mbc_cfgs); |
952 | return; | 952 | return; |
@@ -958,9 +958,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
958 | wm8994->mbc_enum.max = pdata->num_mbc_cfgs; | 958 | wm8994->mbc_enum.max = pdata->num_mbc_cfgs; |
959 | wm8994->mbc_enum.texts = wm8994->mbc_texts; | 959 | wm8994->mbc_enum.texts = wm8994->mbc_texts; |
960 | 960 | ||
961 | ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); | 961 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
962 | control, 1); | ||
962 | if (ret != 0) | 963 | if (ret != 0) |
963 | dev_err(wm8994->codec->dev, | 964 | dev_err(wm8994->hubs.codec->dev, |
964 | "Failed to add MBC mode controls: %d\n", ret); | 965 | "Failed to add MBC mode controls: %d\n", ret); |
965 | } | 966 | } |
966 | 967 | ||
@@ -974,7 +975,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
974 | wm8994->vss_texts = kmalloc(sizeof(char *) | 975 | wm8994->vss_texts = kmalloc(sizeof(char *) |
975 | * pdata->num_vss_cfgs, GFP_KERNEL); | 976 | * pdata->num_vss_cfgs, GFP_KERNEL); |
976 | if (!wm8994->vss_texts) { | 977 | if (!wm8994->vss_texts) { |
977 | dev_err(wm8994->codec->dev, | 978 | dev_err(wm8994->hubs.codec->dev, |
978 | "Failed to allocate %d VSS config texts\n", | 979 | "Failed to allocate %d VSS config texts\n", |
979 | pdata->num_vss_cfgs); | 980 | pdata->num_vss_cfgs); |
980 | return; | 981 | return; |
@@ -986,9 +987,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
986 | wm8994->vss_enum.max = pdata->num_vss_cfgs; | 987 | wm8994->vss_enum.max = pdata->num_vss_cfgs; |
987 | wm8994->vss_enum.texts = wm8994->vss_texts; | 988 | wm8994->vss_enum.texts = wm8994->vss_texts; |
988 | 989 | ||
989 | ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); | 990 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
991 | control, 1); | ||
990 | if (ret != 0) | 992 | if (ret != 0) |
991 | dev_err(wm8994->codec->dev, | 993 | dev_err(wm8994->hubs.codec->dev, |
992 | "Failed to add VSS mode controls: %d\n", ret); | 994 | "Failed to add VSS mode controls: %d\n", ret); |
993 | } | 995 | } |
994 | 996 | ||
@@ -1003,7 +1005,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
1003 | wm8994->vss_hpf_texts = kmalloc(sizeof(char *) | 1005 | wm8994->vss_hpf_texts = kmalloc(sizeof(char *) |
1004 | * pdata->num_vss_hpf_cfgs, GFP_KERNEL); | 1006 | * pdata->num_vss_hpf_cfgs, GFP_KERNEL); |
1005 | if (!wm8994->vss_hpf_texts) { | 1007 | if (!wm8994->vss_hpf_texts) { |
1006 | dev_err(wm8994->codec->dev, | 1008 | dev_err(wm8994->hubs.codec->dev, |
1007 | "Failed to allocate %d VSS HPF config texts\n", | 1009 | "Failed to allocate %d VSS HPF config texts\n", |
1008 | pdata->num_vss_hpf_cfgs); | 1010 | pdata->num_vss_hpf_cfgs); |
1009 | return; | 1011 | return; |
@@ -1015,9 +1017,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
1015 | wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; | 1017 | wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; |
1016 | wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; | 1018 | wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; |
1017 | 1019 | ||
1018 | ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); | 1020 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
1021 | control, 1); | ||
1019 | if (ret != 0) | 1022 | if (ret != 0) |
1020 | dev_err(wm8994->codec->dev, | 1023 | dev_err(wm8994->hubs.codec->dev, |
1021 | "Failed to add VSS HPFmode controls: %d\n", | 1024 | "Failed to add VSS HPFmode controls: %d\n", |
1022 | ret); | 1025 | ret); |
1023 | } | 1026 | } |
@@ -1033,7 +1036,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
1033 | wm8994->enh_eq_texts = kmalloc(sizeof(char *) | 1036 | wm8994->enh_eq_texts = kmalloc(sizeof(char *) |
1034 | * pdata->num_enh_eq_cfgs, GFP_KERNEL); | 1037 | * pdata->num_enh_eq_cfgs, GFP_KERNEL); |
1035 | if (!wm8994->enh_eq_texts) { | 1038 | if (!wm8994->enh_eq_texts) { |
1036 | dev_err(wm8994->codec->dev, | 1039 | dev_err(wm8994->hubs.codec->dev, |
1037 | "Failed to allocate %d enhanced EQ config texts\n", | 1040 | "Failed to allocate %d enhanced EQ config texts\n", |
1038 | pdata->num_enh_eq_cfgs); | 1041 | pdata->num_enh_eq_cfgs); |
1039 | return; | 1042 | return; |
@@ -1045,9 +1048,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
1045 | wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; | 1048 | wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; |
1046 | wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; | 1049 | wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; |
1047 | 1050 | ||
1048 | ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); | 1051 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
1052 | control, 1); | ||
1049 | if (ret != 0) | 1053 | if (ret != 0) |
1050 | dev_err(wm8994->codec->dev, | 1054 | dev_err(wm8994->hubs.codec->dev, |
1051 | "Failed to add enhanced EQ controls: %d\n", | 1055 | "Failed to add enhanced EQ controls: %d\n", |
1052 | ret); | 1056 | ret); |
1053 | } | 1057 | } |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 96518ac8e24c..f0f6f6601785 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -52,25 +52,72 @@ | |||
52 | * We can't read the WM8960 register space when we are | 52 | * We can't read the WM8960 register space when we are |
53 | * using 2 wire for device control, so we cache them instead. | 53 | * using 2 wire for device control, so we cache them instead. |
54 | */ | 54 | */ |
55 | static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { | 55 | static const struct reg_default wm8960_reg_defaults[] = { |
56 | 0x0097, 0x0097, 0x0000, 0x0000, | 56 | { 0x0, 0x0097 }, |
57 | 0x0000, 0x0008, 0x0000, 0x000a, | 57 | { 0x1, 0x0097 }, |
58 | 0x01c0, 0x0000, 0x00ff, 0x00ff, | 58 | { 0x2, 0x0000 }, |
59 | 0x0000, 0x0000, 0x0000, 0x0000, | 59 | { 0x3, 0x0000 }, |
60 | 0x0000, 0x007b, 0x0100, 0x0032, | 60 | { 0x4, 0x0000 }, |
61 | 0x0000, 0x00c3, 0x00c3, 0x01c0, | 61 | { 0x5, 0x0008 }, |
62 | 0x0000, 0x0000, 0x0000, 0x0000, | 62 | { 0x6, 0x0000 }, |
63 | 0x0000, 0x0000, 0x0000, 0x0000, | 63 | { 0x7, 0x000a }, |
64 | 0x0100, 0x0100, 0x0050, 0x0050, | 64 | { 0x8, 0x01c0 }, |
65 | 0x0050, 0x0050, 0x0000, 0x0000, | 65 | { 0x9, 0x0000 }, |
66 | 0x0000, 0x0000, 0x0040, 0x0000, | 66 | { 0xa, 0x00ff }, |
67 | 0x0000, 0x0050, 0x0050, 0x0000, | 67 | { 0xb, 0x00ff }, |
68 | 0x0002, 0x0037, 0x004d, 0x0080, | 68 | |
69 | 0x0008, 0x0031, 0x0026, 0x00e9, | 69 | { 0x10, 0x0000 }, |
70 | { 0x11, 0x007b }, | ||
71 | { 0x12, 0x0100 }, | ||
72 | { 0x13, 0x0032 }, | ||
73 | { 0x14, 0x0000 }, | ||
74 | { 0x15, 0x00c3 }, | ||
75 | { 0x16, 0x00c3 }, | ||
76 | { 0x17, 0x01c0 }, | ||
77 | { 0x18, 0x0000 }, | ||
78 | { 0x19, 0x0000 }, | ||
79 | { 0x1a, 0x0000 }, | ||
80 | { 0x1b, 0x0000 }, | ||
81 | { 0x1c, 0x0000 }, | ||
82 | { 0x1d, 0x0000 }, | ||
83 | |||
84 | { 0x20, 0x0100 }, | ||
85 | { 0x21, 0x0100 }, | ||
86 | { 0x22, 0x0050 }, | ||
87 | |||
88 | { 0x25, 0x0050 }, | ||
89 | { 0x26, 0x0000 }, | ||
90 | { 0x27, 0x0000 }, | ||
91 | { 0x28, 0x0000 }, | ||
92 | { 0x29, 0x0000 }, | ||
93 | { 0x2a, 0x0040 }, | ||
94 | { 0x2b, 0x0000 }, | ||
95 | { 0x2c, 0x0000 }, | ||
96 | { 0x2d, 0x0050 }, | ||
97 | { 0x2e, 0x0050 }, | ||
98 | { 0x2f, 0x0000 }, | ||
99 | { 0x30, 0x0002 }, | ||
100 | { 0x31, 0x0037 }, | ||
101 | |||
102 | { 0x33, 0x0080 }, | ||
103 | { 0x34, 0x0008 }, | ||
104 | { 0x35, 0x0031 }, | ||
105 | { 0x36, 0x0026 }, | ||
106 | { 0x37, 0x00e9 }, | ||
70 | }; | 107 | }; |
71 | 108 | ||
109 | static bool wm8960_volatile(struct device *dev, unsigned int reg) | ||
110 | { | ||
111 | switch (reg) { | ||
112 | case WM8960_RESET: | ||
113 | return true; | ||
114 | default: | ||
115 | return false; | ||
116 | } | ||
117 | } | ||
118 | |||
72 | struct wm8960_priv { | 119 | struct wm8960_priv { |
73 | enum snd_soc_control_type control_type; | 120 | struct regmap *regmap; |
74 | int (*set_bias_level)(struct snd_soc_codec *, | 121 | int (*set_bias_level)(struct snd_soc_codec *, |
75 | enum snd_soc_bias_level level); | 122 | enum snd_soc_bias_level level); |
76 | struct snd_soc_dapm_widget *lout1; | 123 | struct snd_soc_dapm_widget *lout1; |
@@ -510,18 +557,25 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
510 | struct snd_soc_codec *codec = dai->codec; | 557 | struct snd_soc_codec *codec = dai->codec; |
511 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 558 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
512 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; | 559 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; |
560 | snd_pcm_format_t format = params_format(params); | ||
513 | int i; | 561 | int i; |
514 | 562 | ||
515 | /* bit size */ | 563 | /* bit size */ |
516 | switch (params_format(params)) { | 564 | switch (format) { |
517 | case SNDRV_PCM_FORMAT_S16_LE: | 565 | case SNDRV_PCM_FORMAT_S16_LE: |
566 | case SNDRV_PCM_FORMAT_S16_BE: | ||
518 | break; | 567 | break; |
519 | case SNDRV_PCM_FORMAT_S20_3LE: | 568 | case SNDRV_PCM_FORMAT_S20_3LE: |
569 | case SNDRV_PCM_FORMAT_S20_3BE: | ||
520 | iface |= 0x0004; | 570 | iface |= 0x0004; |
521 | break; | 571 | break; |
522 | case SNDRV_PCM_FORMAT_S24_LE: | 572 | case SNDRV_PCM_FORMAT_S24_LE: |
573 | case SNDRV_PCM_FORMAT_S24_BE: | ||
523 | iface |= 0x0008; | 574 | iface |= 0x0008; |
524 | break; | 575 | break; |
576 | default: | ||
577 | dev_err(codec->dev, "unsupported format %i\n", format); | ||
578 | return -EINVAL; | ||
525 | } | 579 | } |
526 | 580 | ||
527 | /* Update filters for the new rate */ | 581 | /* Update filters for the new rate */ |
@@ -555,6 +609,8 @@ static int wm8960_mute(struct snd_soc_dai *dai, int mute) | |||
555 | static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, | 609 | static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, |
556 | enum snd_soc_bias_level level) | 610 | enum snd_soc_bias_level level) |
557 | { | 611 | { |
612 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
613 | |||
558 | switch (level) { | 614 | switch (level) { |
559 | case SND_SOC_BIAS_ON: | 615 | case SND_SOC_BIAS_ON: |
560 | break; | 616 | break; |
@@ -566,7 +622,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, | |||
566 | 622 | ||
567 | case SND_SOC_BIAS_STANDBY: | 623 | case SND_SOC_BIAS_STANDBY: |
568 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 624 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
569 | snd_soc_cache_sync(codec); | 625 | regcache_sync(wm8960->regmap); |
570 | 626 | ||
571 | /* Enable anti-pop features */ | 627 | /* Enable anti-pop features */ |
572 | snd_soc_write(codec, WM8960_APOP1, | 628 | snd_soc_write(codec, WM8960_APOP1, |
@@ -667,7 +723,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | |||
667 | break; | 723 | break; |
668 | 724 | ||
669 | case SND_SOC_BIAS_OFF: | 725 | case SND_SOC_BIAS_OFF: |
670 | snd_soc_cache_sync(codec); | 726 | regcache_sync(wm8960->regmap); |
671 | break; | 727 | break; |
672 | default: | 728 | default: |
673 | break; | 729 | break; |
@@ -906,16 +962,11 @@ static int wm8960_probe(struct snd_soc_codec *codec) | |||
906 | if (!pdata) { | 962 | if (!pdata) { |
907 | dev_warn(codec->dev, "No platform data supplied\n"); | 963 | dev_warn(codec->dev, "No platform data supplied\n"); |
908 | } else { | 964 | } else { |
909 | if (pdata->dres > WM8960_DRES_MAX) { | ||
910 | dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres); | ||
911 | pdata->dres = 0; | ||
912 | } | ||
913 | |||
914 | if (pdata->capless) | 965 | if (pdata->capless) |
915 | wm8960->set_bias_level = wm8960_set_bias_level_capless; | 966 | wm8960->set_bias_level = wm8960_set_bias_level_capless; |
916 | } | 967 | } |
917 | 968 | ||
918 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8960->control_type); | 969 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
919 | if (ret < 0) { | 970 | if (ret < 0) { |
920 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 971 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
921 | return ret; | 972 | return ret; |
@@ -963,14 +1014,24 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { | |||
963 | .suspend = wm8960_suspend, | 1014 | .suspend = wm8960_suspend, |
964 | .resume = wm8960_resume, | 1015 | .resume = wm8960_resume, |
965 | .set_bias_level = wm8960_set_bias_level, | 1016 | .set_bias_level = wm8960_set_bias_level, |
966 | .reg_cache_size = ARRAY_SIZE(wm8960_reg), | 1017 | }; |
967 | .reg_word_size = sizeof(u16), | 1018 | |
968 | .reg_cache_default = wm8960_reg, | 1019 | static const struct regmap_config wm8960_regmap = { |
1020 | .reg_bits = 7, | ||
1021 | .val_bits = 9, | ||
1022 | .max_register = WM8960_PLL4, | ||
1023 | |||
1024 | .reg_defaults = wm8960_reg_defaults, | ||
1025 | .num_reg_defaults = ARRAY_SIZE(wm8960_reg_defaults), | ||
1026 | .cache_type = REGCACHE_RBTREE, | ||
1027 | |||
1028 | .volatile_reg = wm8960_volatile, | ||
969 | }; | 1029 | }; |
970 | 1030 | ||
971 | static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, | 1031 | static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, |
972 | const struct i2c_device_id *id) | 1032 | const struct i2c_device_id *id) |
973 | { | 1033 | { |
1034 | struct wm8960_data *pdata = dev_get_platdata(&i2c->dev); | ||
974 | struct wm8960_priv *wm8960; | 1035 | struct wm8960_priv *wm8960; |
975 | int ret; | 1036 | int ret; |
976 | 1037 | ||
@@ -979,8 +1040,21 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, | |||
979 | if (wm8960 == NULL) | 1040 | if (wm8960 == NULL) |
980 | return -ENOMEM; | 1041 | return -ENOMEM; |
981 | 1042 | ||
1043 | wm8960->regmap = regmap_init_i2c(i2c, &wm8960_regmap); | ||
1044 | if (IS_ERR(wm8960->regmap)) | ||
1045 | return PTR_ERR(wm8960->regmap); | ||
1046 | |||
1047 | if (pdata && pdata->shared_lrclk) { | ||
1048 | ret = regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2, | ||
1049 | 0x4, 0x4); | ||
1050 | if (ret != 0) { | ||
1051 | dev_err(&i2c->dev, "Failed to enable LRCM: %d\n", | ||
1052 | ret); | ||
1053 | return ret; | ||
1054 | } | ||
1055 | } | ||
1056 | |||
982 | i2c_set_clientdata(i2c, wm8960); | 1057 | i2c_set_clientdata(i2c, wm8960); |
983 | wm8960->control_type = SND_SOC_I2C; | ||
984 | 1058 | ||
985 | ret = snd_soc_register_codec(&i2c->dev, | 1059 | ret = snd_soc_register_codec(&i2c->dev, |
986 | &soc_codec_dev_wm8960, &wm8960_dai, 1); | 1060 | &soc_codec_dev_wm8960, &wm8960_dai, 1); |
@@ -1010,23 +1084,7 @@ static struct i2c_driver wm8960_i2c_driver = { | |||
1010 | .id_table = wm8960_i2c_id, | 1084 | .id_table = wm8960_i2c_id, |
1011 | }; | 1085 | }; |
1012 | 1086 | ||
1013 | static int __init wm8960_modinit(void) | 1087 | module_i2c_driver(wm8960_i2c_driver); |
1014 | { | ||
1015 | int ret = 0; | ||
1016 | ret = i2c_add_driver(&wm8960_i2c_driver); | ||
1017 | if (ret != 0) { | ||
1018 | printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", | ||
1019 | ret); | ||
1020 | } | ||
1021 | return ret; | ||
1022 | } | ||
1023 | module_init(wm8960_modinit); | ||
1024 | |||
1025 | static void __exit wm8960_exit(void) | ||
1026 | { | ||
1027 | i2c_del_driver(&wm8960_i2c_driver); | ||
1028 | } | ||
1029 | module_exit(wm8960_exit); | ||
1030 | 1088 | ||
1031 | MODULE_DESCRIPTION("ASoC WM8960 driver"); | 1089 | MODULE_DESCRIPTION("ASoC WM8960 driver"); |
1032 | MODULE_AUTHOR("Liam Girdwood"); | 1090 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 01edbcc754d2..f387670d0d75 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/pm.h> | 20 | #include <linux/pm.h> |
21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
22 | #include <linux/regmap.h> | ||
22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
@@ -31,283 +32,159 @@ | |||
31 | 32 | ||
32 | #define WM8961_MAX_REGISTER 0xFC | 33 | #define WM8961_MAX_REGISTER 0xFC |
33 | 34 | ||
34 | static u16 wm8961_reg_defaults[] = { | 35 | static const struct reg_default wm8961_reg_defaults[] = { |
35 | 0x009F, /* R0 - Left Input volume */ | 36 | { 0, 0x009F }, /* R0 - Left Input volume */ |
36 | 0x009F, /* R1 - Right Input volume */ | 37 | { 1, 0x009F }, /* R1 - Right Input volume */ |
37 | 0x0000, /* R2 - LOUT1 volume */ | 38 | { 2, 0x0000 }, /* R2 - LOUT1 volume */ |
38 | 0x0000, /* R3 - ROUT1 volume */ | 39 | { 3, 0x0000 }, /* R3 - ROUT1 volume */ |
39 | 0x0020, /* R4 - Clocking1 */ | 40 | { 4, 0x0020 }, /* R4 - Clocking1 */ |
40 | 0x0008, /* R5 - ADC & DAC Control 1 */ | 41 | { 5, 0x0008 }, /* R5 - ADC & DAC Control 1 */ |
41 | 0x0000, /* R6 - ADC & DAC Control 2 */ | 42 | { 6, 0x0000 }, /* R6 - ADC & DAC Control 2 */ |
42 | 0x000A, /* R7 - Audio Interface 0 */ | 43 | { 7, 0x000A }, /* R7 - Audio Interface 0 */ |
43 | 0x01F4, /* R8 - Clocking2 */ | 44 | { 8, 0x01F4 }, /* R8 - Clocking2 */ |
44 | 0x0000, /* R9 - Audio Interface 1 */ | 45 | { 9, 0x0000 }, /* R9 - Audio Interface 1 */ |
45 | 0x00FF, /* R10 - Left DAC volume */ | 46 | { 10, 0x00FF }, /* R10 - Left DAC volume */ |
46 | 0x00FF, /* R11 - Right DAC volume */ | 47 | { 11, 0x00FF }, /* R11 - Right DAC volume */ |
47 | 0x0000, /* R12 */ | 48 | |
48 | 0x0000, /* R13 */ | 49 | { 14, 0x0040 }, /* R14 - Audio Interface 2 */ |
49 | 0x0040, /* R14 - Audio Interface 2 */ | 50 | |
50 | 0x0000, /* R15 - Software Reset */ | 51 | { 17, 0x007B }, /* R17 - ALC1 */ |
51 | 0x0000, /* R16 */ | 52 | { 18, 0x0000 }, /* R18 - ALC2 */ |
52 | 0x007B, /* R17 - ALC1 */ | 53 | { 19, 0x0032 }, /* R19 - ALC3 */ |
53 | 0x0000, /* R18 - ALC2 */ | 54 | { 20, 0x0000 }, /* R20 - Noise Gate */ |
54 | 0x0032, /* R19 - ALC3 */ | 55 | { 21, 0x00C0 }, /* R21 - Left ADC volume */ |
55 | 0x0000, /* R20 - Noise Gate */ | 56 | { 22, 0x00C0 }, /* R22 - Right ADC volume */ |
56 | 0x00C0, /* R21 - Left ADC volume */ | 57 | { 23, 0x0120 }, /* R23 - Additional control(1) */ |
57 | 0x00C0, /* R22 - Right ADC volume */ | 58 | { 24, 0x0000 }, /* R24 - Additional control(2) */ |
58 | 0x0120, /* R23 - Additional control(1) */ | 59 | { 25, 0x0000 }, /* R25 - Pwr Mgmt (1) */ |
59 | 0x0000, /* R24 - Additional control(2) */ | 60 | { 26, 0x0000 }, /* R26 - Pwr Mgmt (2) */ |
60 | 0x0000, /* R25 - Pwr Mgmt (1) */ | 61 | { 27, 0x0000 }, /* R27 - Additional Control (3) */ |
61 | 0x0000, /* R26 - Pwr Mgmt (2) */ | 62 | { 28, 0x0000 }, /* R28 - Anti-pop */ |
62 | 0x0000, /* R27 - Additional Control (3) */ | 63 | |
63 | 0x0000, /* R28 - Anti-pop */ | 64 | { 30, 0x005F }, /* R30 - Clocking 3 */ |
64 | 0x0000, /* R29 */ | 65 | |
65 | 0x005F, /* R30 - Clocking 3 */ | 66 | { 32, 0x0000 }, /* R32 - ADCL signal path */ |
66 | 0x0000, /* R31 */ | 67 | { 33, 0x0000 }, /* R33 - ADCR signal path */ |
67 | 0x0000, /* R32 - ADCL signal path */ | 68 | |
68 | 0x0000, /* R33 - ADCR signal path */ | 69 | { 40, 0x0000 }, /* R40 - LOUT2 volume */ |
69 | 0x0000, /* R34 */ | 70 | { 41, 0x0000 }, /* R41 - ROUT2 volume */ |
70 | 0x0000, /* R35 */ | 71 | |
71 | 0x0000, /* R36 */ | 72 | { 47, 0x0000 }, /* R47 - Pwr Mgmt (3) */ |
72 | 0x0000, /* R37 */ | 73 | { 48, 0x0023 }, /* R48 - Additional Control (4) */ |
73 | 0x0000, /* R38 */ | 74 | { 49, 0x0000 }, /* R49 - Class D Control 1 */ |
74 | 0x0000, /* R39 */ | 75 | |
75 | 0x0000, /* R40 - LOUT2 volume */ | 76 | { 51, 0x0003 }, /* R51 - Class D Control 2 */ |
76 | 0x0000, /* R41 - ROUT2 volume */ | 77 | |
77 | 0x0000, /* R42 */ | 78 | { 56, 0x0106 }, /* R56 - Clocking 4 */ |
78 | 0x0000, /* R43 */ | 79 | { 57, 0x0000 }, /* R57 - DSP Sidetone 0 */ |
79 | 0x0000, /* R44 */ | 80 | { 58, 0x0000 }, /* R58 - DSP Sidetone 1 */ |
80 | 0x0000, /* R45 */ | 81 | |
81 | 0x0000, /* R46 */ | 82 | { 60, 0x0000 }, /* R60 - DC Servo 0 */ |
82 | 0x0000, /* R47 - Pwr Mgmt (3) */ | 83 | { 61, 0x0000 }, /* R61 - DC Servo 1 */ |
83 | 0x0023, /* R48 - Additional Control (4) */ | 84 | |
84 | 0x0000, /* R49 - Class D Control 1 */ | 85 | { 63, 0x015E }, /* R63 - DC Servo 3 */ |
85 | 0x0000, /* R50 */ | 86 | |
86 | 0x0003, /* R51 - Class D Control 2 */ | 87 | { 65, 0x0010 }, /* R65 - DC Servo 5 */ |
87 | 0x0000, /* R52 */ | 88 | |
88 | 0x0000, /* R53 */ | 89 | { 68, 0x0003 }, /* R68 - Analogue PGA Bias */ |
89 | 0x0000, /* R54 */ | 90 | { 69, 0x0000 }, /* R69 - Analogue HP 0 */ |
90 | 0x0000, /* R55 */ | 91 | |
91 | 0x0106, /* R56 - Clocking 4 */ | 92 | { 71, 0x01FB }, /* R71 - Analogue HP 2 */ |
92 | 0x0000, /* R57 - DSP Sidetone 0 */ | 93 | { 72, 0x0000 }, /* R72 - Charge Pump 1 */ |
93 | 0x0000, /* R58 - DSP Sidetone 1 */ | 94 | |
94 | 0x0000, /* R59 */ | 95 | { 82, 0x0000 }, /* R82 - Charge Pump B */ |
95 | 0x0000, /* R60 - DC Servo 0 */ | 96 | |
96 | 0x0000, /* R61 - DC Servo 1 */ | 97 | { 87, 0x0000 }, /* R87 - Write Sequencer 1 */ |
97 | 0x0000, /* R62 */ | 98 | { 88, 0x0000 }, /* R88 - Write Sequencer 2 */ |
98 | 0x015E, /* R63 - DC Servo 3 */ | 99 | { 89, 0x0000 }, /* R89 - Write Sequencer 3 */ |
99 | 0x0010, /* R64 */ | 100 | { 90, 0x0000 }, /* R90 - Write Sequencer 4 */ |
100 | 0x0010, /* R65 - DC Servo 5 */ | 101 | { 91, 0x0000 }, /* R91 - Write Sequencer 5 */ |
101 | 0x0000, /* R66 */ | 102 | { 92, 0x0000 }, /* R92 - Write Sequencer 6 */ |
102 | 0x0001, /* R67 */ | 103 | { 93, 0x0000 }, /* R93 - Write Sequencer 7 */ |
103 | 0x0003, /* R68 - Analogue PGA Bias */ | 104 | |
104 | 0x0000, /* R69 - Analogue HP 0 */ | 105 | { 252, 0x0001 }, /* R252 - General test 1 */ |
105 | 0x0060, /* R70 */ | ||
106 | 0x01FB, /* R71 - Analogue HP 2 */ | ||
107 | 0x0000, /* R72 - Charge Pump 1 */ | ||
108 | 0x0065, /* R73 */ | ||
109 | 0x005F, /* R74 */ | ||
110 | 0x0059, /* R75 */ | ||
111 | 0x006B, /* R76 */ | ||
112 | 0x0038, /* R77 */ | ||
113 | 0x000C, /* R78 */ | ||
114 | 0x000A, /* R79 */ | ||
115 | 0x006B, /* R80 */ | ||
116 | 0x0000, /* R81 */ | ||
117 | 0x0000, /* R82 - Charge Pump B */ | ||
118 | 0x0087, /* R83 */ | ||
119 | 0x0000, /* R84 */ | ||
120 | 0x005C, /* R85 */ | ||
121 | 0x0000, /* R86 */ | ||
122 | 0x0000, /* R87 - Write Sequencer 1 */ | ||
123 | 0x0000, /* R88 - Write Sequencer 2 */ | ||
124 | 0x0000, /* R89 - Write Sequencer 3 */ | ||
125 | 0x0000, /* R90 - Write Sequencer 4 */ | ||
126 | 0x0000, /* R91 - Write Sequencer 5 */ | ||
127 | 0x0000, /* R92 - Write Sequencer 6 */ | ||
128 | 0x0000, /* R93 - Write Sequencer 7 */ | ||
129 | 0x0000, /* R94 */ | ||
130 | 0x0000, /* R95 */ | ||
131 | 0x0000, /* R96 */ | ||
132 | 0x0000, /* R97 */ | ||
133 | 0x0000, /* R98 */ | ||
134 | 0x0000, /* R99 */ | ||
135 | 0x0000, /* R100 */ | ||
136 | 0x0000, /* R101 */ | ||
137 | 0x0000, /* R102 */ | ||
138 | 0x0000, /* R103 */ | ||
139 | 0x0000, /* R104 */ | ||
140 | 0x0000, /* R105 */ | ||
141 | 0x0000, /* R106 */ | ||
142 | 0x0000, /* R107 */ | ||
143 | 0x0000, /* R108 */ | ||
144 | 0x0000, /* R109 */ | ||
145 | 0x0000, /* R110 */ | ||
146 | 0x0000, /* R111 */ | ||
147 | 0x0000, /* R112 */ | ||
148 | 0x0000, /* R113 */ | ||
149 | 0x0000, /* R114 */ | ||
150 | 0x0000, /* R115 */ | ||
151 | 0x0000, /* R116 */ | ||
152 | 0x0000, /* R117 */ | ||
153 | 0x0000, /* R118 */ | ||
154 | 0x0000, /* R119 */ | ||
155 | 0x0000, /* R120 */ | ||
156 | 0x0000, /* R121 */ | ||
157 | 0x0000, /* R122 */ | ||
158 | 0x0000, /* R123 */ | ||
159 | 0x0000, /* R124 */ | ||
160 | 0x0000, /* R125 */ | ||
161 | 0x0000, /* R126 */ | ||
162 | 0x0000, /* R127 */ | ||
163 | 0x0000, /* R128 */ | ||
164 | 0x0000, /* R129 */ | ||
165 | 0x0000, /* R130 */ | ||
166 | 0x0000, /* R131 */ | ||
167 | 0x0000, /* R132 */ | ||
168 | 0x0000, /* R133 */ | ||
169 | 0x0000, /* R134 */ | ||
170 | 0x0000, /* R135 */ | ||
171 | 0x0000, /* R136 */ | ||
172 | 0x0000, /* R137 */ | ||
173 | 0x0000, /* R138 */ | ||
174 | 0x0000, /* R139 */ | ||
175 | 0x0000, /* R140 */ | ||
176 | 0x0000, /* R141 */ | ||
177 | 0x0000, /* R142 */ | ||
178 | 0x0000, /* R143 */ | ||
179 | 0x0000, /* R144 */ | ||
180 | 0x0000, /* R145 */ | ||
181 | 0x0000, /* R146 */ | ||
182 | 0x0000, /* R147 */ | ||
183 | 0x0000, /* R148 */ | ||
184 | 0x0000, /* R149 */ | ||
185 | 0x0000, /* R150 */ | ||
186 | 0x0000, /* R151 */ | ||
187 | 0x0000, /* R152 */ | ||
188 | 0x0000, /* R153 */ | ||
189 | 0x0000, /* R154 */ | ||
190 | 0x0000, /* R155 */ | ||
191 | 0x0000, /* R156 */ | ||
192 | 0x0000, /* R157 */ | ||
193 | 0x0000, /* R158 */ | ||
194 | 0x0000, /* R159 */ | ||
195 | 0x0000, /* R160 */ | ||
196 | 0x0000, /* R161 */ | ||
197 | 0x0000, /* R162 */ | ||
198 | 0x0000, /* R163 */ | ||
199 | 0x0000, /* R164 */ | ||
200 | 0x0000, /* R165 */ | ||
201 | 0x0000, /* R166 */ | ||
202 | 0x0000, /* R167 */ | ||
203 | 0x0000, /* R168 */ | ||
204 | 0x0000, /* R169 */ | ||
205 | 0x0000, /* R170 */ | ||
206 | 0x0000, /* R171 */ | ||
207 | 0x0000, /* R172 */ | ||
208 | 0x0000, /* R173 */ | ||
209 | 0x0000, /* R174 */ | ||
210 | 0x0000, /* R175 */ | ||
211 | 0x0000, /* R176 */ | ||
212 | 0x0000, /* R177 */ | ||
213 | 0x0000, /* R178 */ | ||
214 | 0x0000, /* R179 */ | ||
215 | 0x0000, /* R180 */ | ||
216 | 0x0000, /* R181 */ | ||
217 | 0x0000, /* R182 */ | ||
218 | 0x0000, /* R183 */ | ||
219 | 0x0000, /* R184 */ | ||
220 | 0x0000, /* R185 */ | ||
221 | 0x0000, /* R186 */ | ||
222 | 0x0000, /* R187 */ | ||
223 | 0x0000, /* R188 */ | ||
224 | 0x0000, /* R189 */ | ||
225 | 0x0000, /* R190 */ | ||
226 | 0x0000, /* R191 */ | ||
227 | 0x0000, /* R192 */ | ||
228 | 0x0000, /* R193 */ | ||
229 | 0x0000, /* R194 */ | ||
230 | 0x0000, /* R195 */ | ||
231 | 0x0030, /* R196 */ | ||
232 | 0x0006, /* R197 */ | ||
233 | 0x0000, /* R198 */ | ||
234 | 0x0060, /* R199 */ | ||
235 | 0x0000, /* R200 */ | ||
236 | 0x003F, /* R201 */ | ||
237 | 0x0000, /* R202 */ | ||
238 | 0x0000, /* R203 */ | ||
239 | 0x0000, /* R204 */ | ||
240 | 0x0001, /* R205 */ | ||
241 | 0x0000, /* R206 */ | ||
242 | 0x0181, /* R207 */ | ||
243 | 0x0005, /* R208 */ | ||
244 | 0x0008, /* R209 */ | ||
245 | 0x0008, /* R210 */ | ||
246 | 0x0000, /* R211 */ | ||
247 | 0x013B, /* R212 */ | ||
248 | 0x0000, /* R213 */ | ||
249 | 0x0000, /* R214 */ | ||
250 | 0x0000, /* R215 */ | ||
251 | 0x0000, /* R216 */ | ||
252 | 0x0070, /* R217 */ | ||
253 | 0x0000, /* R218 */ | ||
254 | 0x0000, /* R219 */ | ||
255 | 0x0000, /* R220 */ | ||
256 | 0x0000, /* R221 */ | ||
257 | 0x0000, /* R222 */ | ||
258 | 0x0003, /* R223 */ | ||
259 | 0x0000, /* R224 */ | ||
260 | 0x0000, /* R225 */ | ||
261 | 0x0001, /* R226 */ | ||
262 | 0x0008, /* R227 */ | ||
263 | 0x0000, /* R228 */ | ||
264 | 0x0000, /* R229 */ | ||
265 | 0x0000, /* R230 */ | ||
266 | 0x0000, /* R231 */ | ||
267 | 0x0004, /* R232 */ | ||
268 | 0x0000, /* R233 */ | ||
269 | 0x0000, /* R234 */ | ||
270 | 0x0000, /* R235 */ | ||
271 | 0x0000, /* R236 */ | ||
272 | 0x0000, /* R237 */ | ||
273 | 0x0080, /* R238 */ | ||
274 | 0x0000, /* R239 */ | ||
275 | 0x0000, /* R240 */ | ||
276 | 0x0000, /* R241 */ | ||
277 | 0x0000, /* R242 */ | ||
278 | 0x0000, /* R243 */ | ||
279 | 0x0000, /* R244 */ | ||
280 | 0x0052, /* R245 */ | ||
281 | 0x0110, /* R246 */ | ||
282 | 0x0040, /* R247 */ | ||
283 | 0x0000, /* R248 */ | ||
284 | 0x0030, /* R249 */ | ||
285 | 0x0000, /* R250 */ | ||
286 | 0x0000, /* R251 */ | ||
287 | 0x0001, /* R252 - General test 1 */ | ||
288 | }; | 106 | }; |
289 | 107 | ||
290 | struct wm8961_priv { | 108 | struct wm8961_priv { |
291 | enum snd_soc_control_type control_type; | 109 | struct regmap *regmap; |
292 | int sysclk; | 110 | int sysclk; |
293 | }; | 111 | }; |
294 | 112 | ||
295 | static int wm8961_volatile_register(struct snd_soc_codec *codec, unsigned int reg) | 113 | static bool wm8961_volatile(struct device *dev, unsigned int reg) |
296 | { | 114 | { |
297 | switch (reg) { | 115 | switch (reg) { |
298 | case WM8961_SOFTWARE_RESET: | 116 | case WM8961_SOFTWARE_RESET: |
299 | case WM8961_WRITE_SEQUENCER_7: | 117 | case WM8961_WRITE_SEQUENCER_7: |
300 | case WM8961_DC_SERVO_1: | 118 | case WM8961_DC_SERVO_1: |
301 | return 1; | 119 | return true; |
302 | 120 | ||
303 | default: | 121 | default: |
304 | return 0; | 122 | return false; |
305 | } | 123 | } |
306 | } | 124 | } |
307 | 125 | ||
308 | static int wm8961_reset(struct snd_soc_codec *codec) | 126 | static bool wm8961_readable(struct device *dev, unsigned int reg) |
309 | { | 127 | { |
310 | return snd_soc_write(codec, WM8961_SOFTWARE_RESET, 0); | 128 | switch (reg) { |
129 | case WM8961_LEFT_INPUT_VOLUME: | ||
130 | case WM8961_RIGHT_INPUT_VOLUME: | ||
131 | case WM8961_LOUT1_VOLUME: | ||
132 | case WM8961_ROUT1_VOLUME: | ||
133 | case WM8961_CLOCKING1: | ||
134 | case WM8961_ADC_DAC_CONTROL_1: | ||
135 | case WM8961_ADC_DAC_CONTROL_2: | ||
136 | case WM8961_AUDIO_INTERFACE_0: | ||
137 | case WM8961_CLOCKING2: | ||
138 | case WM8961_AUDIO_INTERFACE_1: | ||
139 | case WM8961_LEFT_DAC_VOLUME: | ||
140 | case WM8961_RIGHT_DAC_VOLUME: | ||
141 | case WM8961_AUDIO_INTERFACE_2: | ||
142 | case WM8961_SOFTWARE_RESET: | ||
143 | case WM8961_ALC1: | ||
144 | case WM8961_ALC2: | ||
145 | case WM8961_ALC3: | ||
146 | case WM8961_NOISE_GATE: | ||
147 | case WM8961_LEFT_ADC_VOLUME: | ||
148 | case WM8961_RIGHT_ADC_VOLUME: | ||
149 | case WM8961_ADDITIONAL_CONTROL_1: | ||
150 | case WM8961_ADDITIONAL_CONTROL_2: | ||
151 | case WM8961_PWR_MGMT_1: | ||
152 | case WM8961_PWR_MGMT_2: | ||
153 | case WM8961_ADDITIONAL_CONTROL_3: | ||
154 | case WM8961_ANTI_POP: | ||
155 | case WM8961_CLOCKING_3: | ||
156 | case WM8961_ADCL_SIGNAL_PATH: | ||
157 | case WM8961_ADCR_SIGNAL_PATH: | ||
158 | case WM8961_LOUT2_VOLUME: | ||
159 | case WM8961_ROUT2_VOLUME: | ||
160 | case WM8961_PWR_MGMT_3: | ||
161 | case WM8961_ADDITIONAL_CONTROL_4: | ||
162 | case WM8961_CLASS_D_CONTROL_1: | ||
163 | case WM8961_CLASS_D_CONTROL_2: | ||
164 | case WM8961_CLOCKING_4: | ||
165 | case WM8961_DSP_SIDETONE_0: | ||
166 | case WM8961_DSP_SIDETONE_1: | ||
167 | case WM8961_DC_SERVO_0: | ||
168 | case WM8961_DC_SERVO_1: | ||
169 | case WM8961_DC_SERVO_3: | ||
170 | case WM8961_DC_SERVO_5: | ||
171 | case WM8961_ANALOGUE_PGA_BIAS: | ||
172 | case WM8961_ANALOGUE_HP_0: | ||
173 | case WM8961_ANALOGUE_HP_2: | ||
174 | case WM8961_CHARGE_PUMP_1: | ||
175 | case WM8961_CHARGE_PUMP_B: | ||
176 | case WM8961_WRITE_SEQUENCER_1: | ||
177 | case WM8961_WRITE_SEQUENCER_2: | ||
178 | case WM8961_WRITE_SEQUENCER_3: | ||
179 | case WM8961_WRITE_SEQUENCER_4: | ||
180 | case WM8961_WRITE_SEQUENCER_5: | ||
181 | case WM8961_WRITE_SEQUENCER_6: | ||
182 | case WM8961_WRITE_SEQUENCER_7: | ||
183 | case WM8961_GENERAL_TEST_1: | ||
184 | return true; | ||
185 | default: | ||
186 | return false; | ||
187 | } | ||
311 | } | 188 | } |
312 | 189 | ||
313 | /* | 190 | /* |
@@ -962,33 +839,12 @@ static int wm8961_probe(struct snd_soc_codec *codec) | |||
962 | int ret = 0; | 839 | int ret = 0; |
963 | u16 reg; | 840 | u16 reg; |
964 | 841 | ||
965 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 842 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); |
966 | if (ret != 0) { | 843 | if (ret != 0) { |
967 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 844 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
968 | return ret; | 845 | return ret; |
969 | } | 846 | } |
970 | 847 | ||
971 | reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); | ||
972 | if (reg != 0x1801) { | ||
973 | dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); | ||
974 | return -EINVAL; | ||
975 | } | ||
976 | |||
977 | /* This isn't volatile - readback doesn't correspond to write */ | ||
978 | codec->cache_bypass = 1; | ||
979 | reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); | ||
980 | codec->cache_bypass = 0; | ||
981 | dev_info(codec->dev, "WM8961 family %d revision %c\n", | ||
982 | (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, | ||
983 | ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) | ||
984 | + 'A'); | ||
985 | |||
986 | ret = wm8961_reset(codec); | ||
987 | if (ret < 0) { | ||
988 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
989 | return ret; | ||
990 | } | ||
991 | |||
992 | /* Enable class W */ | 848 | /* Enable class W */ |
993 | reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); | 849 | reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); |
994 | reg |= WM8961_CP_DYN_PWR_MASK; | 850 | reg |= WM8961_CP_DYN_PWR_MASK; |
@@ -1066,16 +922,26 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { | |||
1066 | .suspend = wm8961_suspend, | 922 | .suspend = wm8961_suspend, |
1067 | .resume = wm8961_resume, | 923 | .resume = wm8961_resume, |
1068 | .set_bias_level = wm8961_set_bias_level, | 924 | .set_bias_level = wm8961_set_bias_level, |
1069 | .reg_cache_size = ARRAY_SIZE(wm8961_reg_defaults), | 925 | }; |
1070 | .reg_word_size = sizeof(u16), | 926 | |
1071 | .reg_cache_default = wm8961_reg_defaults, | 927 | static const struct regmap_config wm8961_regmap = { |
1072 | .volatile_register = wm8961_volatile_register, | 928 | .reg_bits = 8, |
929 | .val_bits = 16, | ||
930 | .max_register = WM8961_MAX_REGISTER, | ||
931 | |||
932 | .reg_defaults = wm8961_reg_defaults, | ||
933 | .num_reg_defaults = ARRAY_SIZE(wm8961_reg_defaults), | ||
934 | .cache_type = REGCACHE_RBTREE, | ||
935 | |||
936 | .volatile_reg = wm8961_volatile, | ||
937 | .readable_reg = wm8961_readable, | ||
1073 | }; | 938 | }; |
1074 | 939 | ||
1075 | static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, | 940 | static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, |
1076 | const struct i2c_device_id *id) | 941 | const struct i2c_device_id *id) |
1077 | { | 942 | { |
1078 | struct wm8961_priv *wm8961; | 943 | struct wm8961_priv *wm8961; |
944 | unsigned int val; | ||
1079 | int ret; | 945 | int ret; |
1080 | 946 | ||
1081 | wm8961 = devm_kzalloc(&i2c->dev, sizeof(struct wm8961_priv), | 947 | wm8961 = devm_kzalloc(&i2c->dev, sizeof(struct wm8961_priv), |
@@ -1083,6 +949,42 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, | |||
1083 | if (wm8961 == NULL) | 949 | if (wm8961 == NULL) |
1084 | return -ENOMEM; | 950 | return -ENOMEM; |
1085 | 951 | ||
952 | wm8961->regmap = devm_regmap_init_i2c(i2c, &wm8961_regmap); | ||
953 | if (IS_ERR(wm8961->regmap)) | ||
954 | return PTR_ERR(wm8961->regmap); | ||
955 | |||
956 | ret = regmap_read(wm8961->regmap, WM8961_SOFTWARE_RESET, &val); | ||
957 | if (ret != 0) { | ||
958 | dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); | ||
959 | return ret; | ||
960 | } | ||
961 | |||
962 | if (val != 0x1801) { | ||
963 | dev_err(&i2c->dev, "Device is not a WM8961: ID=0x%x\n", val); | ||
964 | return -EINVAL; | ||
965 | } | ||
966 | |||
967 | /* This isn't volatile - readback doesn't correspond to write */ | ||
968 | regcache_cache_bypass(wm8961->regmap, true); | ||
969 | ret = regmap_read(wm8961->regmap, WM8961_RIGHT_INPUT_VOLUME, &val); | ||
970 | regcache_cache_bypass(wm8961->regmap, false); | ||
971 | |||
972 | if (ret != 0) { | ||
973 | dev_err(&i2c->dev, "Failed to read chip revision: %d\n", ret); | ||
974 | return ret; | ||
975 | } | ||
976 | |||
977 | dev_info(&i2c->dev, "WM8961 family %d revision %c\n", | ||
978 | (val & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, | ||
979 | ((val & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) | ||
980 | + 'A'); | ||
981 | |||
982 | ret = regmap_write(wm8961->regmap, WM8961_SOFTWARE_RESET, 0x1801); | ||
983 | if (ret != 0) { | ||
984 | dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); | ||
985 | return ret; | ||
986 | } | ||
987 | |||
1086 | i2c_set_clientdata(i2c, wm8961); | 988 | i2c_set_clientdata(i2c, wm8961); |
1087 | 989 | ||
1088 | ret = snd_soc_register_codec(&i2c->dev, | 990 | ret = snd_soc_register_codec(&i2c->dev, |
@@ -1114,23 +1016,7 @@ static struct i2c_driver wm8961_i2c_driver = { | |||
1114 | .id_table = wm8961_i2c_id, | 1016 | .id_table = wm8961_i2c_id, |
1115 | }; | 1017 | }; |
1116 | 1018 | ||
1117 | static int __init wm8961_modinit(void) | 1019 | module_i2c_driver(wm8961_i2c_driver); |
1118 | { | ||
1119 | int ret = 0; | ||
1120 | ret = i2c_add_driver(&wm8961_i2c_driver); | ||
1121 | if (ret != 0) { | ||
1122 | printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n", | ||
1123 | ret); | ||
1124 | } | ||
1125 | return ret; | ||
1126 | } | ||
1127 | module_init(wm8961_modinit); | ||
1128 | |||
1129 | static void __exit wm8961_exit(void) | ||
1130 | { | ||
1131 | i2c_del_driver(&wm8961_i2c_driver); | ||
1132 | } | ||
1133 | module_exit(wm8961_exit); | ||
1134 | 1020 | ||
1135 | MODULE_DESCRIPTION("ASoC WM8961 driver"); | 1021 | MODULE_DESCRIPTION("ASoC WM8961 driver"); |
1136 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 1022 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index eef783f6b6d6..5ce647758443 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -721,23 +721,7 @@ static struct i2c_driver wm8971_i2c_driver = { | |||
721 | .id_table = wm8971_i2c_id, | 721 | .id_table = wm8971_i2c_id, |
722 | }; | 722 | }; |
723 | 723 | ||
724 | static int __init wm8971_modinit(void) | 724 | module_i2c_driver(wm8971_i2c_driver); |
725 | { | ||
726 | int ret = 0; | ||
727 | ret = i2c_add_driver(&wm8971_i2c_driver); | ||
728 | if (ret != 0) { | ||
729 | printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n", | ||
730 | ret); | ||
731 | } | ||
732 | return ret; | ||
733 | } | ||
734 | module_init(wm8971_modinit); | ||
735 | |||
736 | static void __exit wm8971_exit(void) | ||
737 | { | ||
738 | i2c_del_driver(&wm8971_i2c_driver); | ||
739 | } | ||
740 | module_exit(wm8971_exit); | ||
741 | 725 | ||
742 | MODULE_DESCRIPTION("ASoC WM8971 driver"); | 726 | MODULE_DESCRIPTION("ASoC WM8971 driver"); |
743 | MODULE_AUTHOR("Lab126"); | 727 | MODULE_AUTHOR("Lab126"); |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index d93c03f820c9..9a39511af52a 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -659,23 +659,7 @@ static struct i2c_driver wm8974_i2c_driver = { | |||
659 | .id_table = wm8974_i2c_id, | 659 | .id_table = wm8974_i2c_id, |
660 | }; | 660 | }; |
661 | 661 | ||
662 | static int __init wm8974_modinit(void) | 662 | module_i2c_driver(wm8974_i2c_driver); |
663 | { | ||
664 | int ret = 0; | ||
665 | ret = i2c_add_driver(&wm8974_i2c_driver); | ||
666 | if (ret != 0) { | ||
667 | printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n", | ||
668 | ret); | ||
669 | } | ||
670 | return ret; | ||
671 | } | ||
672 | module_init(wm8974_modinit); | ||
673 | |||
674 | static void __exit wm8974_exit(void) | ||
675 | { | ||
676 | i2c_del_driver(&wm8974_i2c_driver); | ||
677 | } | ||
678 | module_exit(wm8974_exit); | ||
679 | 663 | ||
680 | MODULE_DESCRIPTION("ASoC WM8974 driver"); | 664 | MODULE_DESCRIPTION("ASoC WM8974 driver"); |
681 | MODULE_AUTHOR("Liam Girdwood"); | 665 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index a5be3adecf75..5421fd9fbcb5 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -1105,23 +1105,7 @@ static struct i2c_driver wm8978_i2c_driver = { | |||
1105 | .id_table = wm8978_i2c_id, | 1105 | .id_table = wm8978_i2c_id, |
1106 | }; | 1106 | }; |
1107 | 1107 | ||
1108 | static int __init wm8978_modinit(void) | 1108 | module_i2c_driver(wm8978_i2c_driver); |
1109 | { | ||
1110 | int ret = 0; | ||
1111 | ret = i2c_add_driver(&wm8978_i2c_driver); | ||
1112 | if (ret != 0) { | ||
1113 | printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n", | ||
1114 | ret); | ||
1115 | } | ||
1116 | return ret; | ||
1117 | } | ||
1118 | module_init(wm8978_modinit); | ||
1119 | |||
1120 | static void __exit wm8978_exit(void) | ||
1121 | { | ||
1122 | i2c_del_driver(&wm8978_i2c_driver); | ||
1123 | } | ||
1124 | module_exit(wm8978_exit); | ||
1125 | 1109 | ||
1126 | MODULE_DESCRIPTION("ASoC WM8978 codec driver"); | 1110 | MODULE_DESCRIPTION("ASoC WM8978 codec driver"); |
1127 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | 1111 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); |
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 367388fdc486..d8879f262d27 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/regmap.h> | ||
19 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
@@ -27,61 +28,60 @@ | |||
27 | 28 | ||
28 | #include "wm8983.h" | 29 | #include "wm8983.h" |
29 | 30 | ||
30 | static const u16 wm8983_reg_defs[WM8983_MAX_REGISTER + 1] = { | 31 | static const struct reg_default wm8983_defaults[] = { |
31 | [0x00] = 0x0000, /* R0 - Software Reset */ | 32 | { 0x01, 0x0000 }, /* R1 - Power management 1 */ |
32 | [0x01] = 0x0000, /* R1 - Power management 1 */ | 33 | { 0x02, 0x0000 }, /* R2 - Power management 2 */ |
33 | [0x02] = 0x0000, /* R2 - Power management 2 */ | 34 | { 0x03, 0x0000 }, /* R3 - Power management 3 */ |
34 | [0x03] = 0x0000, /* R3 - Power management 3 */ | 35 | { 0x04, 0x0050 }, /* R4 - Audio Interface */ |
35 | [0x04] = 0x0050, /* R4 - Audio Interface */ | 36 | { 0x05, 0x0000 }, /* R5 - Companding control */ |
36 | [0x05] = 0x0000, /* R5 - Companding control */ | 37 | { 0x06, 0x0140 }, /* R6 - Clock Gen control */ |
37 | [0x06] = 0x0140, /* R6 - Clock Gen control */ | 38 | { 0x07, 0x0000 }, /* R7 - Additional control */ |
38 | [0x07] = 0x0000, /* R7 - Additional control */ | 39 | { 0x08, 0x0000 }, /* R8 - GPIO Control */ |
39 | [0x08] = 0x0000, /* R8 - GPIO Control */ | 40 | { 0x09, 0x0000 }, /* R9 - Jack Detect Control 1 */ |
40 | [0x09] = 0x0000, /* R9 - Jack Detect Control 1 */ | 41 | { 0x0A, 0x0000 }, /* R10 - DAC Control */ |
41 | [0x0A] = 0x0000, /* R10 - DAC Control */ | 42 | { 0x0B, 0x00FF }, /* R11 - Left DAC digital Vol */ |
42 | [0x0B] = 0x00FF, /* R11 - Left DAC digital Vol */ | 43 | { 0x0C, 0x00FF }, /* R12 - Right DAC digital vol */ |
43 | [0x0C] = 0x00FF, /* R12 - Right DAC digital vol */ | 44 | { 0x0D, 0x0000 }, /* R13 - Jack Detect Control 2 */ |
44 | [0x0D] = 0x0000, /* R13 - Jack Detect Control 2 */ | 45 | { 0x0E, 0x0100 }, /* R14 - ADC Control */ |
45 | [0x0E] = 0x0100, /* R14 - ADC Control */ | 46 | { 0x0F, 0x00FF }, /* R15 - Left ADC Digital Vol */ |
46 | [0x0F] = 0x00FF, /* R15 - Left ADC Digital Vol */ | 47 | { 0x10, 0x00FF }, /* R16 - Right ADC Digital Vol */ |
47 | [0x10] = 0x00FF, /* R16 - Right ADC Digital Vol */ | 48 | { 0x12, 0x012C }, /* R18 - EQ1 - low shelf */ |
48 | [0x12] = 0x012C, /* R18 - EQ1 - low shelf */ | 49 | { 0x13, 0x002C }, /* R19 - EQ2 - peak 1 */ |
49 | [0x13] = 0x002C, /* R19 - EQ2 - peak 1 */ | 50 | { 0x14, 0x002C }, /* R20 - EQ3 - peak 2 */ |
50 | [0x14] = 0x002C, /* R20 - EQ3 - peak 2 */ | 51 | { 0x15, 0x002C }, /* R21 - EQ4 - peak 3 */ |
51 | [0x15] = 0x002C, /* R21 - EQ4 - peak 3 */ | 52 | { 0x16, 0x002C }, /* R22 - EQ5 - high shelf */ |
52 | [0x16] = 0x002C, /* R22 - EQ5 - high shelf */ | 53 | { 0x18, 0x0032 }, /* R24 - DAC Limiter 1 */ |
53 | [0x18] = 0x0032, /* R24 - DAC Limiter 1 */ | 54 | { 0x19, 0x0000 }, /* R25 - DAC Limiter 2 */ |
54 | [0x19] = 0x0000, /* R25 - DAC Limiter 2 */ | 55 | { 0x1B, 0x0000 }, /* R27 - Notch Filter 1 */ |
55 | [0x1B] = 0x0000, /* R27 - Notch Filter 1 */ | 56 | { 0x1C, 0x0000 }, /* R28 - Notch Filter 2 */ |
56 | [0x1C] = 0x0000, /* R28 - Notch Filter 2 */ | 57 | { 0x1D, 0x0000 }, /* R29 - Notch Filter 3 */ |
57 | [0x1D] = 0x0000, /* R29 - Notch Filter 3 */ | 58 | { 0x1E, 0x0000 }, /* R30 - Notch Filter 4 */ |
58 | [0x1E] = 0x0000, /* R30 - Notch Filter 4 */ | 59 | { 0x20, 0x0038 }, /* R32 - ALC control 1 */ |
59 | [0x20] = 0x0038, /* R32 - ALC control 1 */ | 60 | { 0x21, 0x000B }, /* R33 - ALC control 2 */ |
60 | [0x21] = 0x000B, /* R33 - ALC control 2 */ | 61 | { 0x22, 0x0032 }, /* R34 - ALC control 3 */ |
61 | [0x22] = 0x0032, /* R34 - ALC control 3 */ | 62 | { 0x23, 0x0000 }, /* R35 - Noise Gate */ |
62 | [0x23] = 0x0000, /* R35 - Noise Gate */ | 63 | { 0x24, 0x0008 }, /* R36 - PLL N */ |
63 | [0x24] = 0x0008, /* R36 - PLL N */ | 64 | { 0x25, 0x000C }, /* R37 - PLL K 1 */ |
64 | [0x25] = 0x000C, /* R37 - PLL K 1 */ | 65 | { 0x26, 0x0093 }, /* R38 - PLL K 2 */ |
65 | [0x26] = 0x0093, /* R38 - PLL K 2 */ | 66 | { 0x27, 0x00E9 }, /* R39 - PLL K 3 */ |
66 | [0x27] = 0x00E9, /* R39 - PLL K 3 */ | 67 | { 0x29, 0x0000 }, /* R41 - 3D control */ |
67 | [0x29] = 0x0000, /* R41 - 3D control */ | 68 | { 0x2A, 0x0000 }, /* R42 - OUT4 to ADC */ |
68 | [0x2A] = 0x0000, /* R42 - OUT4 to ADC */ | 69 | { 0x2B, 0x0000 }, /* R43 - Beep control */ |
69 | [0x2B] = 0x0000, /* R43 - Beep control */ | 70 | { 0x2C, 0x0033 }, /* R44 - Input ctrl */ |
70 | [0x2C] = 0x0033, /* R44 - Input ctrl */ | 71 | { 0x2D, 0x0010 }, /* R45 - Left INP PGA gain ctrl */ |
71 | [0x2D] = 0x0010, /* R45 - Left INP PGA gain ctrl */ | 72 | { 0x2E, 0x0010 }, /* R46 - Right INP PGA gain ctrl */ |
72 | [0x2E] = 0x0010, /* R46 - Right INP PGA gain ctrl */ | 73 | { 0x2F, 0x0100 }, /* R47 - Left ADC BOOST ctrl */ |
73 | [0x2F] = 0x0100, /* R47 - Left ADC BOOST ctrl */ | 74 | { 0x30, 0x0100 }, /* R48 - Right ADC BOOST ctrl */ |
74 | [0x30] = 0x0100, /* R48 - Right ADC BOOST ctrl */ | 75 | { 0x31, 0x0002 }, /* R49 - Output ctrl */ |
75 | [0x31] = 0x0002, /* R49 - Output ctrl */ | 76 | { 0x32, 0x0001 }, /* R50 - Left mixer ctrl */ |
76 | [0x32] = 0x0001, /* R50 - Left mixer ctrl */ | 77 | { 0x33, 0x0001 }, /* R51 - Right mixer ctrl */ |
77 | [0x33] = 0x0001, /* R51 - Right mixer ctrl */ | 78 | { 0x34, 0x0039 }, /* R52 - LOUT1 (HP) volume ctrl */ |
78 | [0x34] = 0x0039, /* R52 - LOUT1 (HP) volume ctrl */ | 79 | { 0x35, 0x0039 }, /* R53 - ROUT1 (HP) volume ctrl */ |
79 | [0x35] = 0x0039, /* R53 - ROUT1 (HP) volume ctrl */ | 80 | { 0x36, 0x0039 }, /* R54 - LOUT2 (SPK) volume ctrl */ |
80 | [0x36] = 0x0039, /* R54 - LOUT2 (SPK) volume ctrl */ | 81 | { 0x37, 0x0039 }, /* R55 - ROUT2 (SPK) volume ctrl */ |
81 | [0x37] = 0x0039, /* R55 - ROUT2 (SPK) volume ctrl */ | 82 | { 0x38, 0x0001 }, /* R56 - OUT3 mixer ctrl */ |
82 | [0x38] = 0x0001, /* R56 - OUT3 mixer ctrl */ | 83 | { 0x39, 0x0001 }, /* R57 - OUT4 (MONO) mix ctrl */ |
83 | [0x39] = 0x0001, /* R57 - OUT4 (MONO) mix ctrl */ | 84 | { 0x3D, 0x0000 }, /* R61 - BIAS CTRL */ |
84 | [0x3D] = 0x0000 /* R61 - BIAS CTRL */ | ||
85 | }; | 85 | }; |
86 | 86 | ||
87 | static const struct wm8983_reg_access { | 87 | static const struct wm8983_reg_access { |
@@ -159,7 +159,7 @@ static const int vol_update_regs[] = { | |||
159 | }; | 159 | }; |
160 | 160 | ||
161 | struct wm8983_priv { | 161 | struct wm8983_priv { |
162 | enum snd_soc_control_type control_type; | 162 | struct regmap *regmap; |
163 | u32 sysclk; | 163 | u32 sysclk; |
164 | u32 bclk; | 164 | u32 bclk; |
165 | }; | 165 | }; |
@@ -610,7 +610,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, | |||
610 | return 0; | 610 | return 0; |
611 | } | 611 | } |
612 | 612 | ||
613 | static int wm8983_readable(struct snd_soc_codec *codec, unsigned int reg) | 613 | static bool wm8983_readable(struct device *dev, unsigned int reg) |
614 | { | 614 | { |
615 | if (reg > WM8983_MAX_REGISTER) | 615 | if (reg > WM8983_MAX_REGISTER) |
616 | return 0; | 616 | return 0; |
@@ -905,6 +905,7 @@ static int wm8983_set_sysclk(struct snd_soc_dai *dai, | |||
905 | static int wm8983_set_bias_level(struct snd_soc_codec *codec, | 905 | static int wm8983_set_bias_level(struct snd_soc_codec *codec, |
906 | enum snd_soc_bias_level level) | 906 | enum snd_soc_bias_level level) |
907 | { | 907 | { |
908 | struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); | ||
908 | int ret; | 909 | int ret; |
909 | 910 | ||
910 | switch (level) { | 911 | switch (level) { |
@@ -917,7 +918,7 @@ static int wm8983_set_bias_level(struct snd_soc_codec *codec, | |||
917 | break; | 918 | break; |
918 | case SND_SOC_BIAS_STANDBY: | 919 | case SND_SOC_BIAS_STANDBY: |
919 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 920 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
920 | ret = snd_soc_cache_sync(codec); | 921 | ret = regcache_sync(wm8983->regmap); |
921 | if (ret < 0) { | 922 | if (ret < 0) { |
922 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); | 923 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); |
923 | return ret; | 924 | return ret; |
@@ -994,10 +995,9 @@ static int wm8983_remove(struct snd_soc_codec *codec) | |||
994 | static int wm8983_probe(struct snd_soc_codec *codec) | 995 | static int wm8983_probe(struct snd_soc_codec *codec) |
995 | { | 996 | { |
996 | int ret; | 997 | int ret; |
997 | struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); | ||
998 | int i; | 998 | int i; |
999 | 999 | ||
1000 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8983->control_type); | 1000 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
1001 | if (ret < 0) { | 1001 | if (ret < 0) { |
1002 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | 1002 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); |
1003 | return ret; | 1003 | return ret; |
@@ -1067,16 +1067,23 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { | |||
1067 | .suspend = wm8983_suspend, | 1067 | .suspend = wm8983_suspend, |
1068 | .resume = wm8983_resume, | 1068 | .resume = wm8983_resume, |
1069 | .set_bias_level = wm8983_set_bias_level, | 1069 | .set_bias_level = wm8983_set_bias_level, |
1070 | .reg_cache_size = ARRAY_SIZE(wm8983_reg_defs), | ||
1071 | .reg_word_size = sizeof(u16), | ||
1072 | .reg_cache_default = wm8983_reg_defs, | ||
1073 | .controls = wm8983_snd_controls, | 1070 | .controls = wm8983_snd_controls, |
1074 | .num_controls = ARRAY_SIZE(wm8983_snd_controls), | 1071 | .num_controls = ARRAY_SIZE(wm8983_snd_controls), |
1075 | .dapm_widgets = wm8983_dapm_widgets, | 1072 | .dapm_widgets = wm8983_dapm_widgets, |
1076 | .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), | 1073 | .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), |
1077 | .dapm_routes = wm8983_audio_map, | 1074 | .dapm_routes = wm8983_audio_map, |
1078 | .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), | 1075 | .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), |
1079 | .readable_register = wm8983_readable | 1076 | }; |
1077 | |||
1078 | static const struct regmap_config wm8983_regmap = { | ||
1079 | .reg_bits = 7, | ||
1080 | .val_bits = 9, | ||
1081 | |||
1082 | .reg_defaults = wm8983_defaults, | ||
1083 | .num_reg_defaults = ARRAY_SIZE(wm8983_defaults), | ||
1084 | .cache_type = REGCACHE_RBTREE, | ||
1085 | |||
1086 | .readable_reg = wm8983_readable, | ||
1080 | }; | 1087 | }; |
1081 | 1088 | ||
1082 | #if defined(CONFIG_SPI_MASTER) | 1089 | #if defined(CONFIG_SPI_MASTER) |
@@ -1085,24 +1092,27 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi) | |||
1085 | struct wm8983_priv *wm8983; | 1092 | struct wm8983_priv *wm8983; |
1086 | int ret; | 1093 | int ret; |
1087 | 1094 | ||
1088 | wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); | 1095 | wm8983 = devm_kzalloc(&spi->dev, sizeof *wm8983, GFP_KERNEL); |
1089 | if (!wm8983) | 1096 | if (!wm8983) |
1090 | return -ENOMEM; | 1097 | return -ENOMEM; |
1091 | 1098 | ||
1092 | wm8983->control_type = SND_SOC_SPI; | 1099 | wm8983->regmap = devm_regmap_init_spi(spi, &wm8983_regmap); |
1100 | if (IS_ERR(wm8983->regmap)) { | ||
1101 | ret = PTR_ERR(wm8983->regmap); | ||
1102 | dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); | ||
1103 | return ret; | ||
1104 | } | ||
1105 | |||
1093 | spi_set_drvdata(spi, wm8983); | 1106 | spi_set_drvdata(spi, wm8983); |
1094 | 1107 | ||
1095 | ret = snd_soc_register_codec(&spi->dev, | 1108 | ret = snd_soc_register_codec(&spi->dev, |
1096 | &soc_codec_dev_wm8983, &wm8983_dai, 1); | 1109 | &soc_codec_dev_wm8983, &wm8983_dai, 1); |
1097 | if (ret < 0) | ||
1098 | kfree(wm8983); | ||
1099 | return ret; | 1110 | return ret; |
1100 | } | 1111 | } |
1101 | 1112 | ||
1102 | static int __devexit wm8983_spi_remove(struct spi_device *spi) | 1113 | static int __devexit wm8983_spi_remove(struct spi_device *spi) |
1103 | { | 1114 | { |
1104 | snd_soc_unregister_codec(&spi->dev); | 1115 | snd_soc_unregister_codec(&spi->dev); |
1105 | kfree(spi_get_drvdata(spi)); | ||
1106 | return 0; | 1116 | return 0; |
1107 | } | 1117 | } |
1108 | 1118 | ||
@@ -1123,24 +1133,28 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c, | |||
1123 | struct wm8983_priv *wm8983; | 1133 | struct wm8983_priv *wm8983; |
1124 | int ret; | 1134 | int ret; |
1125 | 1135 | ||
1126 | wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); | 1136 | wm8983 = devm_kzalloc(&i2c->dev, sizeof *wm8983, GFP_KERNEL); |
1127 | if (!wm8983) | 1137 | if (!wm8983) |
1128 | return -ENOMEM; | 1138 | return -ENOMEM; |
1129 | 1139 | ||
1130 | wm8983->control_type = SND_SOC_I2C; | 1140 | wm8983->regmap = devm_regmap_init_i2c(i2c, &wm8983_regmap); |
1141 | if (IS_ERR(wm8983->regmap)) { | ||
1142 | ret = PTR_ERR(wm8983->regmap); | ||
1143 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); | ||
1144 | return ret; | ||
1145 | } | ||
1146 | |||
1131 | i2c_set_clientdata(i2c, wm8983); | 1147 | i2c_set_clientdata(i2c, wm8983); |
1132 | 1148 | ||
1133 | ret = snd_soc_register_codec(&i2c->dev, | 1149 | ret = snd_soc_register_codec(&i2c->dev, |
1134 | &soc_codec_dev_wm8983, &wm8983_dai, 1); | 1150 | &soc_codec_dev_wm8983, &wm8983_dai, 1); |
1135 | if (ret < 0) | 1151 | |
1136 | kfree(wm8983); | ||
1137 | return ret; | 1152 | return ret; |
1138 | } | 1153 | } |
1139 | 1154 | ||
1140 | static __devexit int wm8983_i2c_remove(struct i2c_client *client) | 1155 | static __devexit int wm8983_i2c_remove(struct i2c_client *client) |
1141 | { | 1156 | { |
1142 | snd_soc_unregister_codec(&client->dev); | 1157 | snd_soc_unregister_codec(&client->dev); |
1143 | kfree(i2c_get_clientdata(client)); | ||
1144 | return 0; | 1158 | return 0; |
1145 | } | 1159 | } |
1146 | 1160 | ||
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index db63c97ddf51..c28c83e5395d 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -1388,7 +1388,8 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, | |||
1388 | struct wm8990_priv *wm8990; | 1388 | struct wm8990_priv *wm8990; |
1389 | int ret; | 1389 | int ret; |
1390 | 1390 | ||
1391 | wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); | 1391 | wm8990 = devm_kzalloc(&i2c->dev, sizeof(struct wm8990_priv), |
1392 | GFP_KERNEL); | ||
1392 | if (wm8990 == NULL) | 1393 | if (wm8990 == NULL) |
1393 | return -ENOMEM; | 1394 | return -ENOMEM; |
1394 | 1395 | ||
@@ -1396,15 +1397,14 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, | |||
1396 | 1397 | ||
1397 | ret = snd_soc_register_codec(&i2c->dev, | 1398 | ret = snd_soc_register_codec(&i2c->dev, |
1398 | &soc_codec_dev_wm8990, &wm8990_dai, 1); | 1399 | &soc_codec_dev_wm8990, &wm8990_dai, 1); |
1399 | if (ret < 0) | 1400 | |
1400 | kfree(wm8990); | ||
1401 | return ret; | 1401 | return ret; |
1402 | } | 1402 | } |
1403 | 1403 | ||
1404 | static __devexit int wm8990_i2c_remove(struct i2c_client *client) | 1404 | static __devexit int wm8990_i2c_remove(struct i2c_client *client) |
1405 | { | 1405 | { |
1406 | snd_soc_unregister_codec(&client->dev); | 1406 | snd_soc_unregister_codec(&client->dev); |
1407 | kfree(i2c_get_clientdata(client)); | 1407 | |
1408 | return 0; | 1408 | return 0; |
1409 | } | 1409 | } |
1410 | 1410 | ||
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 9ac31ba9b82e..fe439f027e10 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c | |||
@@ -1363,7 +1363,7 @@ static __devinit int wm8991_i2c_probe(struct i2c_client *i2c, | |||
1363 | struct wm8991_priv *wm8991; | 1363 | struct wm8991_priv *wm8991; |
1364 | int ret; | 1364 | int ret; |
1365 | 1365 | ||
1366 | wm8991 = kzalloc(sizeof *wm8991, GFP_KERNEL); | 1366 | wm8991 = devm_kzalloc(&i2c->dev, sizeof(*wm8991), GFP_KERNEL); |
1367 | if (!wm8991) | 1367 | if (!wm8991) |
1368 | return -ENOMEM; | 1368 | return -ENOMEM; |
1369 | 1369 | ||
@@ -1372,15 +1372,14 @@ static __devinit int wm8991_i2c_probe(struct i2c_client *i2c, | |||
1372 | 1372 | ||
1373 | ret = snd_soc_register_codec(&i2c->dev, | 1373 | ret = snd_soc_register_codec(&i2c->dev, |
1374 | &soc_codec_dev_wm8991, &wm8991_dai, 1); | 1374 | &soc_codec_dev_wm8991, &wm8991_dai, 1); |
1375 | if (ret < 0) | 1375 | |
1376 | kfree(wm8991); | ||
1377 | return ret; | 1376 | return ret; |
1378 | } | 1377 | } |
1379 | 1378 | ||
1380 | static __devexit int wm8991_i2c_remove(struct i2c_client *client) | 1379 | static __devexit int wm8991_i2c_remove(struct i2c_client *client) |
1381 | { | 1380 | { |
1382 | snd_soc_unregister_codec(&client->dev); | 1381 | snd_soc_unregister_codec(&client->dev); |
1383 | kfree(i2c_get_clientdata(client)); | 1382 | |
1384 | return 0; | 1383 | return 0; |
1385 | } | 1384 | } |
1386 | 1385 | ||
@@ -1400,23 +1399,7 @@ static struct i2c_driver wm8991_i2c_driver = { | |||
1400 | .id_table = wm8991_i2c_id, | 1399 | .id_table = wm8991_i2c_id, |
1401 | }; | 1400 | }; |
1402 | 1401 | ||
1403 | static int __init wm8991_modinit(void) | 1402 | module_i2c_driver(wm8991_i2c_driver); |
1404 | { | ||
1405 | int ret; | ||
1406 | ret = i2c_add_driver(&wm8991_i2c_driver); | ||
1407 | if (ret != 0) { | ||
1408 | printk(KERN_ERR "Failed to register WM8991 I2C driver: %d\n", | ||
1409 | ret); | ||
1410 | } | ||
1411 | return 0; | ||
1412 | } | ||
1413 | module_init(wm8991_modinit); | ||
1414 | |||
1415 | static void __exit wm8991_exit(void) | ||
1416 | { | ||
1417 | i2c_del_driver(&wm8991_i2c_driver); | ||
1418 | } | ||
1419 | module_exit(wm8991_exit); | ||
1420 | 1403 | ||
1421 | MODULE_DESCRIPTION("ASoC WM8991 driver"); | 1404 | MODULE_DESCRIPTION("ASoC WM8991 driver"); |
1422 | MODULE_AUTHOR("Graeme Gregory"); | 1405 | MODULE_AUTHOR("Graeme Gregory"); |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 9fd80d688979..94737a30716b 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -1520,6 +1520,8 @@ static int wm8993_probe(struct snd_soc_codec *codec) | |||
1520 | wm8993->pdata.lineout2fb, | 1520 | wm8993->pdata.lineout2fb, |
1521 | wm8993->pdata.jd_scthr, | 1521 | wm8993->pdata.jd_scthr, |
1522 | wm8993->pdata.jd_thr, | 1522 | wm8993->pdata.jd_thr, |
1523 | wm8993->pdata.micbias1_delay, | ||
1524 | wm8993->pdata.micbias2_delay, | ||
1523 | wm8993->pdata.micbias1_lvl, | 1525 | wm8993->pdata.micbias1_lvl, |
1524 | wm8993->pdata.micbias2_lvl); | 1526 | wm8993->pdata.micbias2_lvl); |
1525 | 1527 | ||
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 6c9eeca85b95..2b2dadc54dac 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -671,6 +671,18 @@ SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0, | |||
671 | eq_tlv), | 671 | eq_tlv), |
672 | }; | 672 | }; |
673 | 673 | ||
674 | static const struct snd_kcontrol_new wm8994_drc_controls[] = { | ||
675 | SND_SOC_BYTES_MASK("AIF1.1 DRC", WM8994_AIF1_DRC1_1, 5, | ||
676 | WM8994_AIF1DAC1_DRC_ENA | WM8994_AIF1ADC1L_DRC_ENA | | ||
677 | WM8994_AIF1ADC1R_DRC_ENA), | ||
678 | SND_SOC_BYTES_MASK("AIF1.2 DRC", WM8994_AIF1_DRC2_1, 5, | ||
679 | WM8994_AIF1DAC2_DRC_ENA | WM8994_AIF1ADC2L_DRC_ENA | | ||
680 | WM8994_AIF1ADC2R_DRC_ENA), | ||
681 | SND_SOC_BYTES_MASK("AIF2 DRC", WM8994_AIF2_DRC_1, 5, | ||
682 | WM8994_AIF2DAC_DRC_ENA | WM8994_AIF2ADCL_DRC_ENA | | ||
683 | WM8994_AIF2ADCR_DRC_ENA), | ||
684 | }; | ||
685 | |||
674 | static const char *wm8958_ng_text[] = { | 686 | static const char *wm8958_ng_text[] = { |
675 | "30ms", "125ms", "250ms", "500ms", | 687 | "30ms", "125ms", "250ms", "500ms", |
676 | }; | 688 | }; |
@@ -789,11 +801,27 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, | |||
789 | struct snd_kcontrol *kcontrol, int event) | 801 | struct snd_kcontrol *kcontrol, int event) |
790 | { | 802 | { |
791 | struct snd_soc_codec *codec = w->codec; | 803 | struct snd_soc_codec *codec = w->codec; |
804 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
792 | 805 | ||
793 | switch (event) { | 806 | switch (event) { |
794 | case SND_SOC_DAPM_PRE_PMU: | 807 | case SND_SOC_DAPM_PRE_PMU: |
795 | return configure_clock(codec); | 808 | return configure_clock(codec); |
796 | 809 | ||
810 | case SND_SOC_DAPM_POST_PMU: | ||
811 | /* | ||
812 | * JACKDET won't run until we start the clock and it | ||
813 | * only reports deltas, make sure we notify the state | ||
814 | * up the stack on startup. Use a *very* generous | ||
815 | * timeout for paranoia, there's no urgency and we | ||
816 | * don't want false reports. | ||
817 | */ | ||
818 | if (wm8994->jackdet && !wm8994->clk_has_run) { | ||
819 | schedule_delayed_work(&wm8994->jackdet_bootstrap, | ||
820 | msecs_to_jiffies(1000)); | ||
821 | wm8994->clk_has_run = true; | ||
822 | } | ||
823 | break; | ||
824 | |||
797 | case SND_SOC_DAPM_POST_PMD: | 825 | case SND_SOC_DAPM_POST_PMD: |
798 | configure_clock(codec); | 826 | configure_clock(codec); |
799 | break; | 827 | break; |
@@ -1632,7 +1660,8 @@ SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event, | |||
1632 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | 1660 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
1633 | 1661 | ||
1634 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, | 1662 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, |
1635 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 1663 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1664 | SND_SOC_DAPM_PRE_PMD), | ||
1636 | 1665 | ||
1637 | SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), | 1666 | SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), |
1638 | SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), | 1667 | SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), |
@@ -2102,6 +2131,10 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
2102 | case WM8994_FLL_SRC_LRCLK: | 2131 | case WM8994_FLL_SRC_LRCLK: |
2103 | case WM8994_FLL_SRC_BCLK: | 2132 | case WM8994_FLL_SRC_BCLK: |
2104 | break; | 2133 | break; |
2134 | case WM8994_FLL_SRC_INTERNAL: | ||
2135 | freq_in = 12000000; | ||
2136 | freq_out = 12000000; | ||
2137 | break; | ||
2105 | default: | 2138 | default: |
2106 | return -EINVAL; | 2139 | return -EINVAL; |
2107 | } | 2140 | } |
@@ -2161,12 +2194,14 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
2161 | 2194 | ||
2162 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset, | 2195 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset, |
2163 | WM8994_FLL1_N_MASK, | 2196 | WM8994_FLL1_N_MASK, |
2164 | fll.n << WM8994_FLL1_N_SHIFT); | 2197 | fll.n << WM8994_FLL1_N_SHIFT); |
2165 | 2198 | ||
2166 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, | 2199 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, |
2167 | WM8958_FLL1_BYP | | 2200 | WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | |
2168 | WM8994_FLL1_REFCLK_DIV_MASK | | 2201 | WM8994_FLL1_REFCLK_DIV_MASK | |
2169 | WM8994_FLL1_REFCLK_SRC_MASK, | 2202 | WM8994_FLL1_REFCLK_SRC_MASK, |
2203 | ((src == WM8994_FLL_SRC_INTERNAL) | ||
2204 | << WM8994_FLL1_FRC_NCO_SHIFT) | | ||
2170 | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | | 2205 | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | |
2171 | (src - 1)); | 2206 | (src - 1)); |
2172 | 2207 | ||
@@ -2192,13 +2227,16 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
2192 | } | 2227 | } |
2193 | } | 2228 | } |
2194 | 2229 | ||
2230 | reg = WM8994_FLL1_ENA; | ||
2231 | |||
2195 | if (fll.k) | 2232 | if (fll.k) |
2196 | reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC; | 2233 | reg |= WM8994_FLL1_FRAC; |
2197 | else | 2234 | if (src == WM8994_FLL_SRC_INTERNAL) |
2198 | reg = WM8994_FLL1_ENA; | 2235 | reg |= WM8994_FLL1_OSC_ENA; |
2236 | |||
2199 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, | 2237 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, |
2200 | WM8994_FLL1_ENA | WM8994_FLL1_FRAC, | 2238 | WM8994_FLL1_ENA | WM8994_FLL1_OSC_ENA | |
2201 | reg); | 2239 | WM8994_FLL1_FRAC, reg); |
2202 | 2240 | ||
2203 | if (wm8994->fll_locked_irq) { | 2241 | if (wm8994->fll_locked_irq) { |
2204 | timeout = wait_for_completion_timeout(&wm8994->fll_locked[id], | 2242 | timeout = wait_for_completion_timeout(&wm8994->fll_locked[id], |
@@ -3027,7 +3065,7 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec) | |||
3027 | 3065 | ||
3028 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | 3066 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) |
3029 | { | 3067 | { |
3030 | struct snd_soc_codec *codec = wm8994->codec; | 3068 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3031 | struct wm8994_pdata *pdata = wm8994->pdata; | 3069 | struct wm8994_pdata *pdata = wm8994->pdata; |
3032 | struct snd_kcontrol_new controls[] = { | 3070 | struct snd_kcontrol_new controls[] = { |
3033 | SOC_ENUM_EXT("AIF1.1 EQ Mode", | 3071 | SOC_ENUM_EXT("AIF1.1 EQ Mode", |
@@ -3085,16 +3123,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | |||
3085 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; | 3123 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; |
3086 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; | 3124 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; |
3087 | 3125 | ||
3088 | ret = snd_soc_add_codec_controls(wm8994->codec, controls, | 3126 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, |
3089 | ARRAY_SIZE(controls)); | 3127 | ARRAY_SIZE(controls)); |
3090 | if (ret != 0) | 3128 | if (ret != 0) |
3091 | dev_err(wm8994->codec->dev, | 3129 | dev_err(wm8994->hubs.codec->dev, |
3092 | "Failed to add ReTune Mobile controls: %d\n", ret); | 3130 | "Failed to add ReTune Mobile controls: %d\n", ret); |
3093 | } | 3131 | } |
3094 | 3132 | ||
3095 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | 3133 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) |
3096 | { | 3134 | { |
3097 | struct snd_soc_codec *codec = wm8994->codec; | 3135 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3098 | struct wm8994_pdata *pdata = wm8994->pdata; | 3136 | struct wm8994_pdata *pdata = wm8994->pdata; |
3099 | int ret, i; | 3137 | int ret, i; |
3100 | 3138 | ||
@@ -3107,6 +3145,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3107 | pdata->lineout2fb, | 3145 | pdata->lineout2fb, |
3108 | pdata->jd_scthr, | 3146 | pdata->jd_scthr, |
3109 | pdata->jd_thr, | 3147 | pdata->jd_thr, |
3148 | pdata->micb1_delay, | ||
3149 | pdata->micb2_delay, | ||
3110 | pdata->micbias1_lvl, | 3150 | pdata->micbias1_lvl, |
3111 | pdata->micbias2_lvl); | 3151 | pdata->micbias2_lvl); |
3112 | 3152 | ||
@@ -3123,10 +3163,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3123 | }; | 3163 | }; |
3124 | 3164 | ||
3125 | /* We need an array of texts for the enum API */ | 3165 | /* We need an array of texts for the enum API */ |
3126 | wm8994->drc_texts = devm_kzalloc(wm8994->codec->dev, | 3166 | wm8994->drc_texts = devm_kzalloc(wm8994->hubs.codec->dev, |
3127 | sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); | 3167 | sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); |
3128 | if (!wm8994->drc_texts) { | 3168 | if (!wm8994->drc_texts) { |
3129 | dev_err(wm8994->codec->dev, | 3169 | dev_err(wm8994->hubs.codec->dev, |
3130 | "Failed to allocate %d DRC config texts\n", | 3170 | "Failed to allocate %d DRC config texts\n", |
3131 | pdata->num_drc_cfgs); | 3171 | pdata->num_drc_cfgs); |
3132 | return; | 3172 | return; |
@@ -3138,23 +3178,28 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3138 | wm8994->drc_enum.max = pdata->num_drc_cfgs; | 3178 | wm8994->drc_enum.max = pdata->num_drc_cfgs; |
3139 | wm8994->drc_enum.texts = wm8994->drc_texts; | 3179 | wm8994->drc_enum.texts = wm8994->drc_texts; |
3140 | 3180 | ||
3141 | ret = snd_soc_add_codec_controls(wm8994->codec, controls, | 3181 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, |
3142 | ARRAY_SIZE(controls)); | 3182 | ARRAY_SIZE(controls)); |
3143 | if (ret != 0) | ||
3144 | dev_err(wm8994->codec->dev, | ||
3145 | "Failed to add DRC mode controls: %d\n", ret); | ||
3146 | |||
3147 | for (i = 0; i < WM8994_NUM_DRC; i++) | 3183 | for (i = 0; i < WM8994_NUM_DRC; i++) |
3148 | wm8994_set_drc(codec, i); | 3184 | wm8994_set_drc(codec, i); |
3185 | } else { | ||
3186 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, | ||
3187 | wm8994_drc_controls, | ||
3188 | ARRAY_SIZE(wm8994_drc_controls)); | ||
3149 | } | 3189 | } |
3150 | 3190 | ||
3191 | if (ret != 0) | ||
3192 | dev_err(wm8994->hubs.codec->dev, | ||
3193 | "Failed to add DRC mode controls: %d\n", ret); | ||
3194 | |||
3195 | |||
3151 | dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", | 3196 | dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", |
3152 | pdata->num_retune_mobile_cfgs); | 3197 | pdata->num_retune_mobile_cfgs); |
3153 | 3198 | ||
3154 | if (pdata->num_retune_mobile_cfgs) | 3199 | if (pdata->num_retune_mobile_cfgs) |
3155 | wm8994_handle_retune_mobile_pdata(wm8994); | 3200 | wm8994_handle_retune_mobile_pdata(wm8994); |
3156 | else | 3201 | else |
3157 | snd_soc_add_codec_controls(wm8994->codec, wm8994_eq_controls, | 3202 | snd_soc_add_codec_controls(wm8994->hubs.codec, wm8994_eq_controls, |
3158 | ARRAY_SIZE(wm8994_eq_controls)); | 3203 | ARRAY_SIZE(wm8994_eq_controls)); |
3159 | 3204 | ||
3160 | for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) { | 3205 | for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) { |
@@ -3236,6 +3281,12 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3236 | 3281 | ||
3237 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg); | 3282 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg); |
3238 | 3283 | ||
3284 | /* enable MICDET and MICSHRT deboune */ | ||
3285 | snd_soc_update_bits(codec, WM8994_IRQ_DEBOUNCE, | ||
3286 | WM8994_MIC1_DET_DB_MASK | WM8994_MIC1_SHRT_DB_MASK | | ||
3287 | WM8994_MIC2_DET_DB_MASK | WM8994_MIC2_SHRT_DB_MASK, | ||
3288 | WM8994_MIC1_DET_DB | WM8994_MIC1_SHRT_DB); | ||
3289 | |||
3239 | snd_soc_dapm_sync(&codec->dapm); | 3290 | snd_soc_dapm_sync(&codec->dapm); |
3240 | 3291 | ||
3241 | return 0; | 3292 | return 0; |
@@ -3309,7 +3360,7 @@ static void wm8994_mic_work(struct work_struct *work) | |||
3309 | static irqreturn_t wm8994_mic_irq(int irq, void *data) | 3360 | static irqreturn_t wm8994_mic_irq(int irq, void *data) |
3310 | { | 3361 | { |
3311 | struct wm8994_priv *priv = data; | 3362 | struct wm8994_priv *priv = data; |
3312 | struct snd_soc_codec *codec = priv->codec; | 3363 | struct snd_soc_codec *codec = priv->hubs.codec; |
3313 | 3364 | ||
3314 | #ifndef CONFIG_SND_SOC_WM8994_MODULE | 3365 | #ifndef CONFIG_SND_SOC_WM8994_MODULE |
3315 | trace_snd_soc_jack_irq(dev_name(codec->dev)); | 3366 | trace_snd_soc_jack_irq(dev_name(codec->dev)); |
@@ -3345,7 +3396,7 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
3345 | 3396 | ||
3346 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, | 3397 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, |
3347 | wm8994->btn_mask | | 3398 | wm8994->btn_mask | |
3348 | SND_JACK_HEADSET); | 3399 | SND_JACK_HEADSET); |
3349 | } | 3400 | } |
3350 | return; | 3401 | return; |
3351 | } | 3402 | } |
@@ -3422,7 +3473,7 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
3422 | static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | 3473 | static irqreturn_t wm1811_jackdet_irq(int irq, void *data) |
3423 | { | 3474 | { |
3424 | struct wm8994_priv *wm8994 = data; | 3475 | struct wm8994_priv *wm8994 = data; |
3425 | struct snd_soc_codec *codec = wm8994->codec; | 3476 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3426 | int reg; | 3477 | int reg; |
3427 | bool present; | 3478 | bool present; |
3428 | 3479 | ||
@@ -3499,10 +3550,22 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | |||
3499 | SND_JACK_MECHANICAL | SND_JACK_HEADSET | | 3550 | SND_JACK_MECHANICAL | SND_JACK_HEADSET | |
3500 | wm8994->btn_mask); | 3551 | wm8994->btn_mask); |
3501 | 3552 | ||
3553 | /* Since we only report deltas force an update, ensures we | ||
3554 | * avoid bootstrapping issues with the core. */ | ||
3555 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, 0); | ||
3556 | |||
3502 | pm_runtime_put(codec->dev); | 3557 | pm_runtime_put(codec->dev); |
3503 | return IRQ_HANDLED; | 3558 | return IRQ_HANDLED; |
3504 | } | 3559 | } |
3505 | 3560 | ||
3561 | static void wm1811_jackdet_bootstrap(struct work_struct *work) | ||
3562 | { | ||
3563 | struct wm8994_priv *wm8994 = container_of(work, | ||
3564 | struct wm8994_priv, | ||
3565 | jackdet_bootstrap.work); | ||
3566 | wm1811_jackdet_irq(0, wm8994); | ||
3567 | } | ||
3568 | |||
3506 | /** | 3569 | /** |
3507 | * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ | 3570 | * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ |
3508 | * | 3571 | * |
@@ -3573,6 +3636,10 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3573 | * otherwise jump straight to microphone detection. | 3636 | * otherwise jump straight to microphone detection. |
3574 | */ | 3637 | */ |
3575 | if (wm8994->jackdet) { | 3638 | if (wm8994->jackdet) { |
3639 | /* Disable debounce for the initial detect */ | ||
3640 | snd_soc_update_bits(codec, WM1811_JACKDET_CTRL, | ||
3641 | WM1811_JACKDET_DB, 0); | ||
3642 | |||
3576 | snd_soc_update_bits(codec, WM8958_MICBIAS2, | 3643 | snd_soc_update_bits(codec, WM8958_MICBIAS2, |
3577 | WM8958_MICB2_DISCH, | 3644 | WM8958_MICB2_DISCH, |
3578 | WM8958_MICB2_DISCH); | 3645 | WM8958_MICB2_DISCH); |
@@ -3600,7 +3667,7 @@ EXPORT_SYMBOL_GPL(wm8958_mic_detect); | |||
3600 | static irqreturn_t wm8958_mic_irq(int irq, void *data) | 3667 | static irqreturn_t wm8958_mic_irq(int irq, void *data) |
3601 | { | 3668 | { |
3602 | struct wm8994_priv *wm8994 = data; | 3669 | struct wm8994_priv *wm8994 = data; |
3603 | struct snd_soc_codec *codec = wm8994->codec; | 3670 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3604 | int reg, count; | 3671 | int reg, count; |
3605 | 3672 | ||
3606 | /* | 3673 | /* |
@@ -3690,15 +3757,15 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3690 | unsigned int reg; | 3757 | unsigned int reg; |
3691 | int ret, i; | 3758 | int ret, i; |
3692 | 3759 | ||
3693 | wm8994->codec = codec; | 3760 | wm8994->hubs.codec = codec; |
3694 | codec->control_data = control->regmap; | 3761 | codec->control_data = control->regmap; |
3695 | 3762 | ||
3696 | snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | 3763 | snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); |
3697 | 3764 | ||
3698 | wm8994->codec = codec; | ||
3699 | |||
3700 | mutex_init(&wm8994->accdet_lock); | 3765 | mutex_init(&wm8994->accdet_lock); |
3701 | INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); | 3766 | INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); |
3767 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, | ||
3768 | wm1811_jackdet_bootstrap); | ||
3702 | 3769 | ||
3703 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | 3770 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) |
3704 | init_completion(&wm8994->fll_locked[i]); | 3771 | init_completion(&wm8994->fll_locked[i]); |
@@ -3756,14 +3823,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3756 | wm8994->hubs.no_cache_dac_hp_direct = true; | 3823 | wm8994->hubs.no_cache_dac_hp_direct = true; |
3757 | wm8994->fll_byp = true; | 3824 | wm8994->fll_byp = true; |
3758 | 3825 | ||
3759 | switch (wm8994->revision) { | 3826 | switch (control->cust_id) { |
3760 | case 0: | 3827 | case 0: |
3761 | case 1: | ||
3762 | case 2: | 3828 | case 2: |
3763 | case 3: | ||
3764 | wm8994->hubs.dcs_codes_l = -9; | 3829 | wm8994->hubs.dcs_codes_l = -9; |
3765 | wm8994->hubs.dcs_codes_r = -7; | 3830 | wm8994->hubs.dcs_codes_r = -7; |
3766 | break; | 3831 | break; |
3832 | case 1: | ||
3833 | case 3: | ||
3834 | wm8994->hubs.dcs_codes_l = -8; | ||
3835 | wm8994->hubs.dcs_codes_r = -7; | ||
3836 | break; | ||
3767 | default: | 3837 | default: |
3768 | break; | 3838 | break; |
3769 | } | 3839 | } |
@@ -3852,7 +3922,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3852 | 3922 | ||
3853 | switch (control->type) { | 3923 | switch (control->type) { |
3854 | case WM1811: | 3924 | case WM1811: |
3855 | if (wm8994->revision > 1) { | 3925 | if (control->cust_id > 1 || wm8994->revision > 1) { |
3856 | ret = wm8994_request_irq(wm8994->wm8994, | 3926 | ret = wm8994_request_irq(wm8994->wm8994, |
3857 | WM8994_IRQ_GPIO(6), | 3927 | WM8994_IRQ_GPIO(6), |
3858 | wm1811_jackdet_irq, "JACKDET", | 3928 | wm1811_jackdet_irq, "JACKDET", |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index d77e06f0a675..f142ec198db3 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -28,10 +28,11 @@ | |||
28 | #define WM8994_FLL1 1 | 28 | #define WM8994_FLL1 1 |
29 | #define WM8994_FLL2 2 | 29 | #define WM8994_FLL2 2 |
30 | 30 | ||
31 | #define WM8994_FLL_SRC_MCLK1 1 | 31 | #define WM8994_FLL_SRC_MCLK1 1 |
32 | #define WM8994_FLL_SRC_MCLK2 2 | 32 | #define WM8994_FLL_SRC_MCLK2 2 |
33 | #define WM8994_FLL_SRC_LRCLK 3 | 33 | #define WM8994_FLL_SRC_LRCLK 3 |
34 | #define WM8994_FLL_SRC_BCLK 4 | 34 | #define WM8994_FLL_SRC_BCLK 4 |
35 | #define WM8994_FLL_SRC_INTERNAL 5 | ||
35 | 36 | ||
36 | enum wm8994_vmid_mode { | 37 | enum wm8994_vmid_mode { |
37 | WM8994_VMID_NORMAL, | 38 | WM8994_VMID_NORMAL, |
@@ -72,7 +73,6 @@ struct wm8994; | |||
72 | struct wm8994_priv { | 73 | struct wm8994_priv { |
73 | struct wm_hubs_data hubs; | 74 | struct wm_hubs_data hubs; |
74 | struct wm8994 *wm8994; | 75 | struct wm8994 *wm8994; |
75 | struct snd_soc_codec *codec; | ||
76 | int sysclk[2]; | 76 | int sysclk[2]; |
77 | int sysclk_rate[2]; | 77 | int sysclk_rate[2]; |
78 | int mclk[2]; | 78 | int mclk[2]; |
@@ -81,6 +81,7 @@ struct wm8994_priv { | |||
81 | struct completion fll_locked[2]; | 81 | struct completion fll_locked[2]; |
82 | bool fll_locked_irq; | 82 | bool fll_locked_irq; |
83 | bool fll_byp; | 83 | bool fll_byp; |
84 | bool clk_has_run; | ||
84 | 85 | ||
85 | int vmid_refcount; | 86 | int vmid_refcount; |
86 | int active_refcount; | 87 | int active_refcount; |
@@ -134,6 +135,7 @@ struct wm8994_priv { | |||
134 | int btn_mask; | 135 | int btn_mask; |
135 | bool jackdet; | 136 | bool jackdet; |
136 | int jackdet_mode; | 137 | int jackdet_mode; |
138 | struct delayed_work jackdet_bootstrap; | ||
137 | 139 | ||
138 | wm8958_micdet_cb jack_cb; | 140 | wm8958_micdet_cb jack_cb; |
139 | void *jack_cb_data; | 141 | void *jack_cb_data; |
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 00f183dfa454..6dcb02c3666f 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -931,7 +931,7 @@ SND_SOC_DAPM_INPUT("IN2RP"), | |||
931 | SND_SOC_DAPM_INPUT("DMIC1DAT"), | 931 | SND_SOC_DAPM_INPUT("DMIC1DAT"), |
932 | SND_SOC_DAPM_INPUT("DMIC2DAT"), | 932 | SND_SOC_DAPM_INPUT("DMIC2DAT"), |
933 | 933 | ||
934 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | 934 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), |
935 | SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), | 935 | SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), |
936 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), | 936 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), |
937 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), | 937 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), |
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 2c2346fdd637..c7ddc56175d1 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -695,17 +695,7 @@ static struct i2c_driver wm9090_i2c_driver = { | |||
695 | .id_table = wm9090_id, | 695 | .id_table = wm9090_id, |
696 | }; | 696 | }; |
697 | 697 | ||
698 | static int __init wm9090_init(void) | 698 | module_i2c_driver(wm9090_i2c_driver); |
699 | { | ||
700 | return i2c_add_driver(&wm9090_i2c_driver); | ||
701 | } | ||
702 | module_init(wm9090_init); | ||
703 | |||
704 | static void __exit wm9090_exit(void) | ||
705 | { | ||
706 | i2c_del_driver(&wm9090_i2c_driver); | ||
707 | } | ||
708 | module_exit(wm9090_exit); | ||
709 | 699 | ||
710 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 700 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
711 | MODULE_DESCRIPTION("WM9090 ASoC driver"); | 701 | MODULE_DESCRIPTION("WM9090 ASoC driver"); |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index c6d2076a796b..4dd73ea08d0b 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -132,8 +132,9 @@ SOC_SINGLE("Aux Playback Phone Volume", AC97_CD, 4, 7, 1), | |||
132 | SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 1), | 132 | SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 1), |
133 | SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1), | 133 | SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1), |
134 | 134 | ||
135 | SOC_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0), | 135 | SOC_SINGLE_TLV("Capture Boost Switch", AC97_REC_SEL, 14, 1, 0, boost_tlv), |
136 | SOC_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1), | 136 | SOC_SINGLE_TLV("Capture to Phone Boost Switch", AC97_REC_SEL, 11, 1, 1, |
137 | boost_tlv), | ||
137 | 138 | ||
138 | SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1), | 139 | SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1), |
139 | SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1), | 140 | SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1), |
@@ -146,7 +147,7 @@ SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0), | |||
146 | SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1), | 147 | SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1), |
147 | SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), | 148 | SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), |
148 | 149 | ||
149 | SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1), | 150 | SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1), |
150 | SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), | 151 | SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), |
151 | SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 0), | 152 | SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 0), |
152 | SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), | 153 | SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), |
@@ -634,7 +635,6 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) | |||
634 | { | 635 | { |
635 | int ret = 0; | 636 | int ret = 0; |
636 | 637 | ||
637 | codec->control_data = codec; /* we don't use regmap! */ | ||
638 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 638 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
639 | if (ret < 0) { | 639 | if (ret < 0) { |
640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); | 640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); |
@@ -699,8 +699,8 @@ static int __devexit wm9712_remove(struct platform_device *pdev) | |||
699 | 699 | ||
700 | static struct platform_driver wm9712_codec_driver = { | 700 | static struct platform_driver wm9712_codec_driver = { |
701 | .driver = { | 701 | .driver = { |
702 | .name = "wm9712-codec", | 702 | .name = "wm9712-codec", |
703 | .owner = THIS_MODULE, | 703 | .owner = THIS_MODULE, |
704 | }, | 704 | }, |
705 | 705 | ||
706 | .probe = wm9712_probe, | 706 | .probe = wm9712_probe, |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index d0b8a3287a85..3eb19fb71d17 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -1196,7 +1196,6 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) | |||
1196 | if (wm9713 == NULL) | 1196 | if (wm9713 == NULL) |
1197 | return -ENOMEM; | 1197 | return -ENOMEM; |
1198 | snd_soc_codec_set_drvdata(codec, wm9713); | 1198 | snd_soc_codec_set_drvdata(codec, wm9713); |
1199 | codec->control_data = wm9713; /* we don't use regmap! */ | ||
1200 | 1199 | ||
1201 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 1200 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
1202 | if (ret < 0) | 1201 | if (ret < 0) |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 61baa48823cb..7a773a835b8e 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -199,15 +199,56 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_codec *codec, u16 dcs_cfg) | |||
199 | list_add_tail(&cache->list, &hubs->dcs_cache); | 199 | list_add_tail(&cache->list, &hubs->dcs_cache); |
200 | } | 200 | } |
201 | 201 | ||
202 | static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec, | ||
203 | u16 *reg_l, u16 *reg_r) | ||
204 | { | ||
205 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | ||
206 | u16 dcs_reg, reg; | ||
207 | |||
208 | switch (hubs->dcs_readback_mode) { | ||
209 | case 2: | ||
210 | dcs_reg = WM8994_DC_SERVO_4E; | ||
211 | break; | ||
212 | case 1: | ||
213 | dcs_reg = WM8994_DC_SERVO_READBACK; | ||
214 | break; | ||
215 | default: | ||
216 | dcs_reg = WM8993_DC_SERVO_3; | ||
217 | break; | ||
218 | } | ||
219 | |||
220 | /* Different chips in the family support different readback | ||
221 | * methods. | ||
222 | */ | ||
223 | switch (hubs->dcs_readback_mode) { | ||
224 | case 0: | ||
225 | *reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) | ||
226 | & WM8993_DCS_INTEG_CHAN_0_MASK; | ||
227 | *reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) | ||
228 | & WM8993_DCS_INTEG_CHAN_1_MASK; | ||
229 | break; | ||
230 | case 2: | ||
231 | case 1: | ||
232 | reg = snd_soc_read(codec, dcs_reg); | ||
233 | *reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | ||
234 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
235 | *reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | ||
236 | break; | ||
237 | default: | ||
238 | WARN(1, "Unknown DCS readback method\n"); | ||
239 | return; | ||
240 | } | ||
241 | } | ||
242 | |||
202 | /* | 243 | /* |
203 | * Startup calibration of the DC servo | 244 | * Startup calibration of the DC servo |
204 | */ | 245 | */ |
205 | static void calibrate_dc_servo(struct snd_soc_codec *codec) | 246 | static void enable_dc_servo(struct snd_soc_codec *codec) |
206 | { | 247 | { |
207 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 248 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
208 | struct wm_hubs_dcs_cache *cache; | 249 | struct wm_hubs_dcs_cache *cache; |
209 | s8 offset; | 250 | s8 offset; |
210 | u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg; | 251 | u16 reg_l, reg_r, dcs_cfg, dcs_reg; |
211 | 252 | ||
212 | switch (hubs->dcs_readback_mode) { | 253 | switch (hubs->dcs_readback_mode) { |
213 | case 2: | 254 | case 2: |
@@ -245,27 +286,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
245 | WM8993_DCS_TRIG_STARTUP_1); | 286 | WM8993_DCS_TRIG_STARTUP_1); |
246 | } | 287 | } |
247 | 288 | ||
248 | /* Different chips in the family support different readback | 289 | wm_hubs_read_dc_servo(codec, ®_l, ®_r); |
249 | * methods. | ||
250 | */ | ||
251 | switch (hubs->dcs_readback_mode) { | ||
252 | case 0: | ||
253 | reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) | ||
254 | & WM8993_DCS_INTEG_CHAN_0_MASK; | ||
255 | reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) | ||
256 | & WM8993_DCS_INTEG_CHAN_1_MASK; | ||
257 | break; | ||
258 | case 2: | ||
259 | case 1: | ||
260 | reg = snd_soc_read(codec, dcs_reg); | ||
261 | reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | ||
262 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
263 | reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | ||
264 | break; | ||
265 | default: | ||
266 | WARN(1, "Unknown DCS readback method\n"); | ||
267 | return; | ||
268 | } | ||
269 | 290 | ||
270 | dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); | 291 | dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); |
271 | 292 | ||
@@ -276,12 +297,16 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
276 | hubs->dcs_codes_l, hubs->dcs_codes_r); | 297 | hubs->dcs_codes_l, hubs->dcs_codes_r); |
277 | 298 | ||
278 | /* HPOUT1R */ | 299 | /* HPOUT1R */ |
279 | offset = reg_r; | 300 | offset = (s8)reg_r; |
301 | dev_dbg(codec->dev, "DCS right %d->%d\n", offset, | ||
302 | offset + hubs->dcs_codes_r); | ||
280 | offset += hubs->dcs_codes_r; | 303 | offset += hubs->dcs_codes_r; |
281 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 304 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
282 | 305 | ||
283 | /* HPOUT1L */ | 306 | /* HPOUT1L */ |
284 | offset = reg_l; | 307 | offset = (s8)reg_l; |
308 | dev_dbg(codec->dev, "DCS left %d->%d\n", offset, | ||
309 | offset + hubs->dcs_codes_l); | ||
285 | offset += hubs->dcs_codes_l; | 310 | offset += hubs->dcs_codes_l; |
286 | dcs_cfg |= (u8)offset; | 311 | dcs_cfg |= (u8)offset; |
287 | 312 | ||
@@ -535,7 +560,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, | |||
535 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, | 560 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, |
536 | WM8993_DCS_TIMER_PERIOD_01_MASK, 0); | 561 | WM8993_DCS_TIMER_PERIOD_01_MASK, 0); |
537 | 562 | ||
538 | calibrate_dc_servo(codec); | 563 | enable_dc_servo(codec); |
539 | 564 | ||
540 | reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | | 565 | reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | |
541 | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; | 566 | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; |
@@ -619,6 +644,28 @@ static int lineout_event(struct snd_soc_dapm_widget *w, | |||
619 | return 0; | 644 | return 0; |
620 | } | 645 | } |
621 | 646 | ||
647 | static int micbias_event(struct snd_soc_dapm_widget *w, | ||
648 | struct snd_kcontrol *kcontrol, int event) | ||
649 | { | ||
650 | struct snd_soc_codec *codec = w->codec; | ||
651 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | ||
652 | |||
653 | switch (w->shift) { | ||
654 | case WM8993_MICB1_ENA_SHIFT: | ||
655 | if (hubs->micb1_delay) | ||
656 | msleep(hubs->micb1_delay); | ||
657 | break; | ||
658 | case WM8993_MICB2_ENA_SHIFT: | ||
659 | if (hubs->micb2_delay) | ||
660 | msleep(hubs->micb2_delay); | ||
661 | break; | ||
662 | default: | ||
663 | return -EINVAL; | ||
664 | } | ||
665 | |||
666 | return 0; | ||
667 | } | ||
668 | |||
622 | void wm_hubs_update_class_w(struct snd_soc_codec *codec) | 669 | void wm_hubs_update_class_w(struct snd_soc_codec *codec) |
623 | { | 670 | { |
624 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 671 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
@@ -809,8 +856,10 @@ SND_SOC_DAPM_INPUT("IN1RP"), | |||
809 | SND_SOC_DAPM_INPUT("IN2RN"), | 856 | SND_SOC_DAPM_INPUT("IN2RN"), |
810 | SND_SOC_DAPM_INPUT("IN2RP:VXRP"), | 857 | SND_SOC_DAPM_INPUT("IN2RP:VXRP"), |
811 | 858 | ||
812 | SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0), | 859 | SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, |
813 | SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0), | 860 | micbias_event, SND_SOC_DAPM_POST_PMU), |
861 | SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, | ||
862 | micbias_event, SND_SOC_DAPM_POST_PMU), | ||
814 | 863 | ||
815 | SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, | 864 | SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, |
816 | in1l_pga, ARRAY_SIZE(in1l_pga)), | 865 | in1l_pga, ARRAY_SIZE(in1l_pga)), |
@@ -1112,6 +1161,8 @@ int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, | |||
1112 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 1161 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
1113 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 1162 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
1114 | 1163 | ||
1164 | hubs->codec = codec; | ||
1165 | |||
1115 | INIT_LIST_HEAD(&hubs->dcs_cache); | 1166 | INIT_LIST_HEAD(&hubs->dcs_cache); |
1116 | init_completion(&hubs->dcs_done); | 1167 | init_completion(&hubs->dcs_done); |
1117 | 1168 | ||
@@ -1143,13 +1194,16 @@ EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); | |||
1143 | int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, | 1194 | int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, |
1144 | int lineout1_diff, int lineout2_diff, | 1195 | int lineout1_diff, int lineout2_diff, |
1145 | int lineout1fb, int lineout2fb, | 1196 | int lineout1fb, int lineout2fb, |
1146 | int jd_scthr, int jd_thr, int micbias1_lvl, | 1197 | int jd_scthr, int jd_thr, |
1147 | int micbias2_lvl) | 1198 | int micbias1_delay, int micbias2_delay, |
1199 | int micbias1_lvl, int micbias2_lvl) | ||
1148 | { | 1200 | { |
1149 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 1201 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
1150 | 1202 | ||
1151 | hubs->lineout1_se = !lineout1_diff; | 1203 | hubs->lineout1_se = !lineout1_diff; |
1152 | hubs->lineout2_se = !lineout2_diff; | 1204 | hubs->lineout2_se = !lineout2_diff; |
1205 | hubs->micb1_delay = micbias1_delay; | ||
1206 | hubs->micb2_delay = micbias2_delay; | ||
1153 | 1207 | ||
1154 | if (!lineout1_diff) | 1208 | if (!lineout1_diff) |
1155 | snd_soc_update_bits(codec, WM8993_LINE_MIXER1, | 1209 | snd_soc_update_bits(codec, WM8993_LINE_MIXER1, |
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index da2dc899ce6d..24c763df21f9 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h | |||
@@ -36,6 +36,9 @@ struct wm_hubs_data { | |||
36 | struct list_head dcs_cache; | 36 | struct list_head dcs_cache; |
37 | bool (*check_class_w_digital)(struct snd_soc_codec *); | 37 | bool (*check_class_w_digital)(struct snd_soc_codec *); |
38 | 38 | ||
39 | int micb1_delay; | ||
40 | int micb2_delay; | ||
41 | |||
39 | bool lineout1_se; | 42 | bool lineout1_se; |
40 | bool lineout1n_ena; | 43 | bool lineout1n_ena; |
41 | bool lineout1p_ena; | 44 | bool lineout1p_ena; |
@@ -46,6 +49,8 @@ struct wm_hubs_data { | |||
46 | 49 | ||
47 | bool dcs_done_irq; | 50 | bool dcs_done_irq; |
48 | struct completion dcs_done; | 51 | struct completion dcs_done; |
52 | |||
53 | struct snd_soc_codec *codec; | ||
49 | }; | 54 | }; |
50 | 55 | ||
51 | extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); | 56 | extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); |
@@ -54,6 +59,7 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *, | |||
54 | int lineout1_diff, int lineout2_diff, | 59 | int lineout1_diff, int lineout2_diff, |
55 | int lineout1fb, int lineout2fb, | 60 | int lineout1fb, int lineout2fb, |
56 | int jd_scthr, int jd_thr, | 61 | int jd_scthr, int jd_thr, |
62 | int micbias1_dly, int micbias2_dly, | ||
57 | int micbias1_lvl, int micbias2_lvl); | 63 | int micbias1_lvl, int micbias2_lvl); |
58 | 64 | ||
59 | extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); | 65 | extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); |
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 10a2d8c788b7..6fac5af13298 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
@@ -22,10 +22,6 @@ | |||
22 | #include <asm/dma.h> | 22 | #include <asm/dma.h> |
23 | #include <asm/mach-types.h> | 23 | #include <asm/mach-types.h> |
24 | 24 | ||
25 | #include <mach/asp.h> | ||
26 | #include <mach/edma.h> | ||
27 | #include <mach/mux.h> | ||
28 | |||
29 | #include "davinci-pcm.h" | 25 | #include "davinci-pcm.h" |
30 | #include "davinci-i2s.h" | 26 | #include "davinci-i2s.h" |
31 | #include "davinci-mcasp.h" | 27 | #include "davinci-mcasp.h" |
@@ -160,7 +156,7 @@ static struct snd_soc_dai_link dm6446_evm_dai = { | |||
160 | .cpu_dai_name = "davinci-mcbsp", | 156 | .cpu_dai_name = "davinci-mcbsp", |
161 | .codec_dai_name = "tlv320aic3x-hifi", | 157 | .codec_dai_name = "tlv320aic3x-hifi", |
162 | .codec_name = "tlv320aic3x-codec.1-001b", | 158 | .codec_name = "tlv320aic3x-codec.1-001b", |
163 | .platform_name = "davinci-pcm-audio", | 159 | .platform_name = "davinci-mcbsp", |
164 | .init = evm_aic3x_init, | 160 | .init = evm_aic3x_init, |
165 | .ops = &evm_ops, | 161 | .ops = &evm_ops, |
166 | }; | 162 | }; |
@@ -171,7 +167,7 @@ static struct snd_soc_dai_link dm355_evm_dai = { | |||
171 | .cpu_dai_name = "davinci-mcbsp.1", | 167 | .cpu_dai_name = "davinci-mcbsp.1", |
172 | .codec_dai_name = "tlv320aic3x-hifi", | 168 | .codec_dai_name = "tlv320aic3x-hifi", |
173 | .codec_name = "tlv320aic3x-codec.1-001b", | 169 | .codec_name = "tlv320aic3x-codec.1-001b", |
174 | .platform_name = "davinci-pcm-audio", | 170 | .platform_name = "davinci-mcbsp.1", |
175 | .init = evm_aic3x_init, | 171 | .init = evm_aic3x_init, |
176 | .ops = &evm_ops, | 172 | .ops = &evm_ops, |
177 | }; | 173 | }; |
@@ -185,14 +181,15 @@ static struct snd_soc_dai_link dm365_evm_dai = { | |||
185 | .init = evm_aic3x_init, | 181 | .init = evm_aic3x_init, |
186 | .codec_name = "tlv320aic3x-codec.1-0018", | 182 | .codec_name = "tlv320aic3x-codec.1-0018", |
187 | .ops = &evm_ops, | 183 | .ops = &evm_ops, |
184 | .platform_name = "davinci-mcbsp", | ||
188 | #elif defined(CONFIG_SND_DM365_VOICE_CODEC) | 185 | #elif defined(CONFIG_SND_DM365_VOICE_CODEC) |
189 | .name = "Voice Codec - CQ93VC", | 186 | .name = "Voice Codec - CQ93VC", |
190 | .stream_name = "CQ93", | 187 | .stream_name = "CQ93", |
191 | .cpu_dai_name = "davinci-vcif", | 188 | .cpu_dai_name = "davinci-vcif", |
192 | .codec_dai_name = "cq93vc-hifi", | 189 | .codec_dai_name = "cq93vc-hifi", |
193 | .codec_name = "cq93vc-codec", | 190 | .codec_name = "cq93vc-codec", |
191 | .platform_name = "davinci-vcif", | ||
194 | #endif | 192 | #endif |
195 | .platform_name = "davinci-pcm-audio", | ||
196 | }; | 193 | }; |
197 | 194 | ||
198 | static struct snd_soc_dai_link dm6467_evm_dai[] = { | 195 | static struct snd_soc_dai_link dm6467_evm_dai[] = { |
@@ -201,7 +198,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { | |||
201 | .stream_name = "AIC3X", | 198 | .stream_name = "AIC3X", |
202 | .cpu_dai_name= "davinci-mcasp.0", | 199 | .cpu_dai_name= "davinci-mcasp.0", |
203 | .codec_dai_name = "tlv320aic3x-hifi", | 200 | .codec_dai_name = "tlv320aic3x-hifi", |
204 | .platform_name ="davinci-pcm-audio", | 201 | .platform_name = "davinci-mcasp.0", |
205 | .codec_name = "tlv320aic3x-codec.0-001a", | 202 | .codec_name = "tlv320aic3x-codec.0-001a", |
206 | .init = evm_aic3x_init, | 203 | .init = evm_aic3x_init, |
207 | .ops = &evm_ops, | 204 | .ops = &evm_ops, |
@@ -212,7 +209,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { | |||
212 | .cpu_dai_name= "davinci-mcasp.1", | 209 | .cpu_dai_name= "davinci-mcasp.1", |
213 | .codec_dai_name = "dit-hifi", | 210 | .codec_dai_name = "dit-hifi", |
214 | .codec_name = "spdif_dit", | 211 | .codec_name = "spdif_dit", |
215 | .platform_name = "davinci-pcm-audio", | 212 | .platform_name = "davinci-mcasp.1", |
216 | .ops = &evm_spdif_ops, | 213 | .ops = &evm_spdif_ops, |
217 | }, | 214 | }, |
218 | }; | 215 | }; |
@@ -223,7 +220,7 @@ static struct snd_soc_dai_link da830_evm_dai = { | |||
223 | .cpu_dai_name = "davinci-mcasp.1", | 220 | .cpu_dai_name = "davinci-mcasp.1", |
224 | .codec_dai_name = "tlv320aic3x-hifi", | 221 | .codec_dai_name = "tlv320aic3x-hifi", |
225 | .codec_name = "tlv320aic3x-codec.1-0018", | 222 | .codec_name = "tlv320aic3x-codec.1-0018", |
226 | .platform_name = "davinci-pcm-audio", | 223 | .platform_name = "davinci-mcasp.1", |
227 | .init = evm_aic3x_init, | 224 | .init = evm_aic3x_init, |
228 | .ops = &evm_ops, | 225 | .ops = &evm_ops, |
229 | }; | 226 | }; |
@@ -234,7 +231,7 @@ static struct snd_soc_dai_link da850_evm_dai = { | |||
234 | .cpu_dai_name= "davinci-mcasp.0", | 231 | .cpu_dai_name= "davinci-mcasp.0", |
235 | .codec_dai_name = "tlv320aic3x-hifi", | 232 | .codec_dai_name = "tlv320aic3x-hifi", |
236 | .codec_name = "tlv320aic3x-codec.1-0018", | 233 | .codec_name = "tlv320aic3x-codec.1-0018", |
237 | .platform_name = "davinci-pcm-audio", | 234 | .platform_name = "davinci-mcasp.0", |
238 | .init = evm_aic3x_init, | 235 | .init = evm_aic3x_init, |
239 | .ops = &evm_ops, | 236 | .ops = &evm_ops, |
240 | }; | 237 | }; |
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 0a74b9587a2c..821831207180 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/platform_data/davinci_asp.h> | ||
19 | 20 | ||
20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
21 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
@@ -23,8 +24,6 @@ | |||
23 | #include <sound/initval.h> | 24 | #include <sound/initval.h> |
24 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
25 | 26 | ||
26 | #include <mach/asp.h> | ||
27 | |||
28 | #include "davinci-pcm.h" | 27 | #include "davinci-pcm.h" |
29 | #include "davinci-i2s.h" | 28 | #include "davinci-i2s.h" |
30 | 29 | ||
@@ -732,8 +731,16 @@ static int davinci_i2s_probe(struct platform_device *pdev) | |||
732 | if (ret != 0) | 731 | if (ret != 0) |
733 | goto err_release_clk; | 732 | goto err_release_clk; |
734 | 733 | ||
734 | ret = davinci_soc_platform_register(&pdev->dev); | ||
735 | if (ret) { | ||
736 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); | ||
737 | goto err_unregister_dai; | ||
738 | } | ||
739 | |||
735 | return 0; | 740 | return 0; |
736 | 741 | ||
742 | err_unregister_dai: | ||
743 | snd_soc_unregister_dai(&pdev->dev); | ||
737 | err_release_clk: | 744 | err_release_clk: |
738 | clk_disable(dev->clk); | 745 | clk_disable(dev->clk); |
739 | clk_put(dev->clk); | 746 | clk_put(dev->clk); |
@@ -745,6 +752,8 @@ static int davinci_i2s_remove(struct platform_device *pdev) | |||
745 | struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); | 752 | struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); |
746 | 753 | ||
747 | snd_soc_unregister_dai(&pdev->dev); | 754 | snd_soc_unregister_dai(&pdev->dev); |
755 | davinci_soc_platform_unregister(&pdev->dev); | ||
756 | |||
748 | clk_disable(dev->clk); | 757 | clk_disable(dev->clk); |
749 | clk_put(dev->clk); | 758 | clk_put(dev->clk); |
750 | dev->clk = NULL; | 759 | dev->clk = NULL; |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index ce5e5cd254dd..714e51e5be5b 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -21,7 +21,10 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/clk.h> | 24 | #include <linux/pm_runtime.h> |
25 | #include <linux/of.h> | ||
26 | #include <linux/of_platform.h> | ||
27 | #include <linux/of_device.h> | ||
25 | 28 | ||
26 | #include <sound/core.h> | 29 | #include <sound/core.h> |
27 | #include <sound/pcm.h> | 30 | #include <sound/pcm.h> |
@@ -108,6 +111,10 @@ | |||
108 | #define DAVINCI_MCASP_WFIFOSTS (0x1014) | 111 | #define DAVINCI_MCASP_WFIFOSTS (0x1014) |
109 | #define DAVINCI_MCASP_RFIFOCTL (0x1018) | 112 | #define DAVINCI_MCASP_RFIFOCTL (0x1018) |
110 | #define DAVINCI_MCASP_RFIFOSTS (0x101C) | 113 | #define DAVINCI_MCASP_RFIFOSTS (0x101C) |
114 | #define MCASP_VER3_WFIFOCTL (0x1000) | ||
115 | #define MCASP_VER3_WFIFOSTS (0x1004) | ||
116 | #define MCASP_VER3_RFIFOCTL (0x1008) | ||
117 | #define MCASP_VER3_RFIFOSTS (0x100C) | ||
111 | 118 | ||
112 | /* | 119 | /* |
113 | * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management | 120 | * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management |
@@ -381,18 +388,36 @@ static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) | |||
381 | { | 388 | { |
382 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 389 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
383 | if (dev->txnumevt) { /* enable FIFO */ | 390 | if (dev->txnumevt) { /* enable FIFO */ |
384 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | 391 | switch (dev->version) { |
392 | case MCASP_VERSION_3: | ||
393 | mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL, | ||
385 | FIFO_ENABLE); | 394 | FIFO_ENABLE); |
386 | mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | 395 | mcasp_set_bits(dev->base + MCASP_VER3_WFIFOCTL, |
387 | FIFO_ENABLE); | 396 | FIFO_ENABLE); |
397 | break; | ||
398 | default: | ||
399 | mcasp_clr_bits(dev->base + | ||
400 | DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); | ||
401 | mcasp_set_bits(dev->base + | ||
402 | DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); | ||
403 | } | ||
388 | } | 404 | } |
389 | mcasp_start_tx(dev); | 405 | mcasp_start_tx(dev); |
390 | } else { | 406 | } else { |
391 | if (dev->rxnumevt) { /* enable FIFO */ | 407 | if (dev->rxnumevt) { /* enable FIFO */ |
392 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | 408 | switch (dev->version) { |
409 | case MCASP_VERSION_3: | ||
410 | mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL, | ||
393 | FIFO_ENABLE); | 411 | FIFO_ENABLE); |
394 | mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | 412 | mcasp_set_bits(dev->base + MCASP_VER3_RFIFOCTL, |
395 | FIFO_ENABLE); | 413 | FIFO_ENABLE); |
414 | break; | ||
415 | default: | ||
416 | mcasp_clr_bits(dev->base + | ||
417 | DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); | ||
418 | mcasp_set_bits(dev->base + | ||
419 | DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); | ||
420 | } | ||
396 | } | 421 | } |
397 | mcasp_start_rx(dev); | 422 | mcasp_start_rx(dev); |
398 | } | 423 | } |
@@ -413,14 +438,31 @@ static void mcasp_stop_tx(struct davinci_audio_dev *dev) | |||
413 | static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) | 438 | static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) |
414 | { | 439 | { |
415 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 440 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
416 | if (dev->txnumevt) /* disable FIFO */ | 441 | if (dev->txnumevt) { /* disable FIFO */ |
417 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | 442 | switch (dev->version) { |
443 | case MCASP_VERSION_3: | ||
444 | mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL, | ||
418 | FIFO_ENABLE); | 445 | FIFO_ENABLE); |
446 | break; | ||
447 | default: | ||
448 | mcasp_clr_bits(dev->base + | ||
449 | DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); | ||
450 | } | ||
451 | } | ||
419 | mcasp_stop_tx(dev); | 452 | mcasp_stop_tx(dev); |
420 | } else { | 453 | } else { |
421 | if (dev->rxnumevt) /* disable FIFO */ | 454 | if (dev->rxnumevt) { /* disable FIFO */ |
422 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | 455 | switch (dev->version) { |
456 | case MCASP_VERSION_3: | ||
457 | mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL, | ||
423 | FIFO_ENABLE); | 458 | FIFO_ENABLE); |
459 | break; | ||
460 | |||
461 | default: | ||
462 | mcasp_clr_bits(dev->base + | ||
463 | DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); | ||
464 | } | ||
465 | } | ||
424 | mcasp_stop_rx(dev); | 466 | mcasp_stop_rx(dev); |
425 | } | 467 | } |
426 | } | 468 | } |
@@ -619,20 +661,37 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) | |||
619 | if (dev->txnumevt * tx_ser > 64) | 661 | if (dev->txnumevt * tx_ser > 64) |
620 | dev->txnumevt = 1; | 662 | dev->txnumevt = 1; |
621 | 663 | ||
622 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser, | 664 | switch (dev->version) { |
665 | case MCASP_VERSION_3: | ||
666 | mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, tx_ser, | ||
623 | NUMDMA_MASK); | 667 | NUMDMA_MASK); |
624 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | 668 | mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, |
625 | ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); | 669 | ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); |
670 | break; | ||
671 | default: | ||
672 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | ||
673 | tx_ser, NUMDMA_MASK); | ||
674 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | ||
675 | ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); | ||
676 | } | ||
626 | } | 677 | } |
627 | 678 | ||
628 | if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { | 679 | if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { |
629 | if (dev->rxnumevt * rx_ser > 64) | 680 | if (dev->rxnumevt * rx_ser > 64) |
630 | dev->rxnumevt = 1; | 681 | dev->rxnumevt = 1; |
631 | 682 | switch (dev->version) { | |
632 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser, | 683 | case MCASP_VERSION_3: |
684 | mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, rx_ser, | ||
633 | NUMDMA_MASK); | 685 | NUMDMA_MASK); |
634 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | 686 | mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, |
635 | ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); | 687 | ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); |
688 | break; | ||
689 | default: | ||
690 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | ||
691 | rx_ser, NUMDMA_MASK); | ||
692 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | ||
693 | ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); | ||
694 | } | ||
636 | } | 695 | } |
637 | } | 696 | } |
638 | 697 | ||
@@ -782,20 +841,17 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, | |||
782 | case SNDRV_PCM_TRIGGER_RESUME: | 841 | case SNDRV_PCM_TRIGGER_RESUME: |
783 | case SNDRV_PCM_TRIGGER_START: | 842 | case SNDRV_PCM_TRIGGER_START: |
784 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 843 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
785 | if (!dev->clk_active) { | 844 | ret = pm_runtime_get_sync(dev->dev); |
786 | clk_enable(dev->clk); | 845 | if (IS_ERR_VALUE(ret)) |
787 | dev->clk_active = 1; | 846 | dev_err(dev->dev, "pm_runtime_get_sync() failed\n"); |
788 | } | ||
789 | davinci_mcasp_start(dev, substream->stream); | 847 | davinci_mcasp_start(dev, substream->stream); |
790 | break; | 848 | break; |
791 | 849 | ||
792 | case SNDRV_PCM_TRIGGER_SUSPEND: | 850 | case SNDRV_PCM_TRIGGER_SUSPEND: |
793 | davinci_mcasp_stop(dev, substream->stream); | 851 | davinci_mcasp_stop(dev, substream->stream); |
794 | if (dev->clk_active) { | 852 | ret = pm_runtime_put_sync(dev->dev); |
795 | clk_disable(dev->clk); | 853 | if (IS_ERR_VALUE(ret)) |
796 | dev->clk_active = 0; | 854 | dev_err(dev->dev, "pm_runtime_put_sync() failed\n"); |
797 | } | ||
798 | |||
799 | break; | 855 | break; |
800 | 856 | ||
801 | case SNDRV_PCM_TRIGGER_STOP: | 857 | case SNDRV_PCM_TRIGGER_STOP: |
@@ -865,6 +921,118 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | |||
865 | 921 | ||
866 | }; | 922 | }; |
867 | 923 | ||
924 | static const struct of_device_id mcasp_dt_ids[] = { | ||
925 | { | ||
926 | .compatible = "ti,dm646x-mcasp-audio", | ||
927 | .data = (void *)MCASP_VERSION_1, | ||
928 | }, | ||
929 | { | ||
930 | .compatible = "ti,da830-mcasp-audio", | ||
931 | .data = (void *)MCASP_VERSION_2, | ||
932 | }, | ||
933 | { | ||
934 | .compatible = "ti,omap2-mcasp-audio", | ||
935 | .data = (void *)MCASP_VERSION_3, | ||
936 | }, | ||
937 | { /* sentinel */ } | ||
938 | }; | ||
939 | MODULE_DEVICE_TABLE(of, mcasp_dt_ids); | ||
940 | |||
941 | static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | ||
942 | struct platform_device *pdev) | ||
943 | { | ||
944 | struct device_node *np = pdev->dev.of_node; | ||
945 | struct snd_platform_data *pdata = NULL; | ||
946 | const struct of_device_id *match = | ||
947 | of_match_device(of_match_ptr(mcasp_dt_ids), &pdev->dev); | ||
948 | |||
949 | const u32 *of_serial_dir32; | ||
950 | u8 *of_serial_dir; | ||
951 | u32 val; | ||
952 | int i, ret = 0; | ||
953 | |||
954 | if (pdev->dev.platform_data) { | ||
955 | pdata = pdev->dev.platform_data; | ||
956 | return pdata; | ||
957 | } else if (match) { | ||
958 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
959 | if (!pdata) { | ||
960 | ret = -ENOMEM; | ||
961 | goto nodata; | ||
962 | } | ||
963 | } else { | ||
964 | /* control shouldn't reach here. something is wrong */ | ||
965 | ret = -EINVAL; | ||
966 | goto nodata; | ||
967 | } | ||
968 | |||
969 | if (match->data) | ||
970 | pdata->version = (u8)((int)match->data); | ||
971 | |||
972 | ret = of_property_read_u32(np, "op-mode", &val); | ||
973 | if (ret >= 0) | ||
974 | pdata->op_mode = val; | ||
975 | |||
976 | ret = of_property_read_u32(np, "tdm-slots", &val); | ||
977 | if (ret >= 0) | ||
978 | pdata->tdm_slots = val; | ||
979 | |||
980 | ret = of_property_read_u32(np, "num-serializer", &val); | ||
981 | if (ret >= 0) | ||
982 | pdata->num_serializer = val; | ||
983 | |||
984 | of_serial_dir32 = of_get_property(np, "serial-dir", &val); | ||
985 | val /= sizeof(u32); | ||
986 | if (val != pdata->num_serializer) { | ||
987 | dev_err(&pdev->dev, | ||
988 | "num-serializer(%d) != serial-dir size(%d)\n", | ||
989 | pdata->num_serializer, val); | ||
990 | ret = -EINVAL; | ||
991 | goto nodata; | ||
992 | } | ||
993 | |||
994 | if (of_serial_dir32) { | ||
995 | of_serial_dir = devm_kzalloc(&pdev->dev, | ||
996 | (sizeof(*of_serial_dir) * val), | ||
997 | GFP_KERNEL); | ||
998 | if (!of_serial_dir) { | ||
999 | ret = -ENOMEM; | ||
1000 | goto nodata; | ||
1001 | } | ||
1002 | |||
1003 | for (i = 0; i < pdata->num_serializer; i++) | ||
1004 | of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]); | ||
1005 | |||
1006 | pdata->serial_dir = of_serial_dir; | ||
1007 | } | ||
1008 | |||
1009 | ret = of_property_read_u32(np, "tx-num-evt", &val); | ||
1010 | if (ret >= 0) | ||
1011 | pdata->txnumevt = val; | ||
1012 | |||
1013 | ret = of_property_read_u32(np, "rx-num-evt", &val); | ||
1014 | if (ret >= 0) | ||
1015 | pdata->rxnumevt = val; | ||
1016 | |||
1017 | ret = of_property_read_u32(np, "sram-size-playback", &val); | ||
1018 | if (ret >= 0) | ||
1019 | pdata->sram_size_playback = val; | ||
1020 | |||
1021 | ret = of_property_read_u32(np, "sram-size-capture", &val); | ||
1022 | if (ret >= 0) | ||
1023 | pdata->sram_size_capture = val; | ||
1024 | |||
1025 | return pdata; | ||
1026 | |||
1027 | nodata: | ||
1028 | if (ret < 0) { | ||
1029 | dev_err(&pdev->dev, "Error populating platform data, err %d\n", | ||
1030 | ret); | ||
1031 | pdata = NULL; | ||
1032 | } | ||
1033 | return pdata; | ||
1034 | } | ||
1035 | |||
868 | static int davinci_mcasp_probe(struct platform_device *pdev) | 1036 | static int davinci_mcasp_probe(struct platform_device *pdev) |
869 | { | 1037 | { |
870 | struct davinci_pcm_dma_params *dma_data; | 1038 | struct davinci_pcm_dma_params *dma_data; |
@@ -873,11 +1041,22 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
873 | struct davinci_audio_dev *dev; | 1041 | struct davinci_audio_dev *dev; |
874 | int ret; | 1042 | int ret; |
875 | 1043 | ||
1044 | if (!pdev->dev.platform_data && !pdev->dev.of_node) { | ||
1045 | dev_err(&pdev->dev, "No platform data supplied\n"); | ||
1046 | return -EINVAL; | ||
1047 | } | ||
1048 | |||
876 | dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), | 1049 | dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), |
877 | GFP_KERNEL); | 1050 | GFP_KERNEL); |
878 | if (!dev) | 1051 | if (!dev) |
879 | return -ENOMEM; | 1052 | return -ENOMEM; |
880 | 1053 | ||
1054 | pdata = davinci_mcasp_set_pdata_from_of(pdev); | ||
1055 | if (!pdata) { | ||
1056 | dev_err(&pdev->dev, "no platform data\n"); | ||
1057 | return -EINVAL; | ||
1058 | } | ||
1059 | |||
881 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1060 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
882 | if (!mem) { | 1061 | if (!mem) { |
883 | dev_err(&pdev->dev, "no mem resource?\n"); | 1062 | dev_err(&pdev->dev, "no mem resource?\n"); |
@@ -891,13 +1070,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
891 | return -EBUSY; | 1070 | return -EBUSY; |
892 | } | 1071 | } |
893 | 1072 | ||
894 | pdata = pdev->dev.platform_data; | 1073 | pm_runtime_enable(&pdev->dev); |
895 | dev->clk = clk_get(&pdev->dev, NULL); | ||
896 | if (IS_ERR(dev->clk)) | ||
897 | return -ENODEV; | ||
898 | 1074 | ||
899 | clk_enable(dev->clk); | 1075 | ret = pm_runtime_get_sync(&pdev->dev); |
900 | dev->clk_active = 1; | 1076 | if (IS_ERR_VALUE(ret)) { |
1077 | dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); | ||
1078 | return ret; | ||
1079 | } | ||
901 | 1080 | ||
902 | dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | 1081 | dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); |
903 | if (!dev->base) { | 1082 | if (!dev->base) { |
@@ -914,6 +1093,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
914 | dev->version = pdata->version; | 1093 | dev->version = pdata->version; |
915 | dev->txnumevt = pdata->txnumevt; | 1094 | dev->txnumevt = pdata->txnumevt; |
916 | dev->rxnumevt = pdata->rxnumevt; | 1095 | dev->rxnumevt = pdata->rxnumevt; |
1096 | dev->dev = &pdev->dev; | ||
917 | 1097 | ||
918 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; | 1098 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; |
919 | dma_data->asp_chan_q = pdata->asp_chan_q; | 1099 | dma_data->asp_chan_q = pdata->asp_chan_q; |
@@ -952,22 +1132,31 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
952 | 1132 | ||
953 | if (ret != 0) | 1133 | if (ret != 0) |
954 | goto err_release_clk; | 1134 | goto err_release_clk; |
1135 | |||
1136 | ret = davinci_soc_platform_register(&pdev->dev); | ||
1137 | if (ret) { | ||
1138 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); | ||
1139 | goto err_unregister_dai; | ||
1140 | } | ||
1141 | |||
955 | return 0; | 1142 | return 0; |
956 | 1143 | ||
1144 | err_unregister_dai: | ||
1145 | snd_soc_unregister_dai(&pdev->dev); | ||
957 | err_release_clk: | 1146 | err_release_clk: |
958 | clk_disable(dev->clk); | 1147 | pm_runtime_put_sync(&pdev->dev); |
959 | clk_put(dev->clk); | 1148 | pm_runtime_disable(&pdev->dev); |
960 | return ret; | 1149 | return ret; |
961 | } | 1150 | } |
962 | 1151 | ||
963 | static int davinci_mcasp_remove(struct platform_device *pdev) | 1152 | static int davinci_mcasp_remove(struct platform_device *pdev) |
964 | { | 1153 | { |
965 | struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev); | ||
966 | 1154 | ||
967 | snd_soc_unregister_dai(&pdev->dev); | 1155 | snd_soc_unregister_dai(&pdev->dev); |
968 | clk_disable(dev->clk); | 1156 | davinci_soc_platform_unregister(&pdev->dev); |
969 | clk_put(dev->clk); | 1157 | |
970 | dev->clk = NULL; | 1158 | pm_runtime_put_sync(&pdev->dev); |
1159 | pm_runtime_disable(&pdev->dev); | ||
971 | 1160 | ||
972 | return 0; | 1161 | return 0; |
973 | } | 1162 | } |
@@ -978,6 +1167,7 @@ static struct platform_driver davinci_mcasp_driver = { | |||
978 | .driver = { | 1167 | .driver = { |
979 | .name = "davinci-mcasp", | 1168 | .name = "davinci-mcasp", |
980 | .owner = THIS_MODULE, | 1169 | .owner = THIS_MODULE, |
1170 | .of_match_table = of_match_ptr(mcasp_dt_ids), | ||
981 | }, | 1171 | }, |
982 | }; | 1172 | }; |
983 | 1173 | ||
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 4681acc63606..0de9ed6ce038 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h | |||
@@ -19,7 +19,8 @@ | |||
19 | #define DAVINCI_MCASP_H | 19 | #define DAVINCI_MCASP_H |
20 | 20 | ||
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <mach/asp.h> | 22 | #include <linux/platform_data/davinci_asp.h> |
23 | |||
23 | #include "davinci-pcm.h" | 24 | #include "davinci-pcm.h" |
24 | 25 | ||
25 | #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 | 26 | #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 |
@@ -40,9 +41,8 @@ struct davinci_audio_dev { | |||
40 | struct davinci_pcm_dma_params dma_params[2]; | 41 | struct davinci_pcm_dma_params dma_params[2]; |
41 | void __iomem *base; | 42 | void __iomem *base; |
42 | int sample_rate; | 43 | int sample_rate; |
43 | struct clk *clk; | 44 | struct device *dev; |
44 | unsigned int codec_fmt; | 45 | unsigned int codec_fmt; |
45 | u8 clk_active; | ||
46 | 46 | ||
47 | /* McASP specific data */ | 47 | /* McASP specific data */ |
48 | int tdm_slots; | 48 | int tdm_slots; |
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 97d77b298968..93ea3bf567e1 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
24 | 24 | ||
25 | #include <asm/dma.h> | 25 | #include <asm/dma.h> |
26 | #include <mach/edma.h> | ||
27 | #include <mach/sram.h> | 26 | #include <mach/sram.h> |
28 | 27 | ||
29 | #include "davinci-pcm.h" | 28 | #include "davinci-pcm.h" |
@@ -864,28 +863,17 @@ static struct snd_soc_platform_driver davinci_soc_platform = { | |||
864 | .pcm_free = davinci_pcm_free, | 863 | .pcm_free = davinci_pcm_free, |
865 | }; | 864 | }; |
866 | 865 | ||
867 | static int __devinit davinci_soc_platform_probe(struct platform_device *pdev) | 866 | int davinci_soc_platform_register(struct device *dev) |
868 | { | 867 | { |
869 | return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform); | 868 | return snd_soc_register_platform(dev, &davinci_soc_platform); |
870 | } | 869 | } |
870 | EXPORT_SYMBOL_GPL(davinci_soc_platform_register); | ||
871 | 871 | ||
872 | static int __devexit davinci_soc_platform_remove(struct platform_device *pdev) | 872 | void davinci_soc_platform_unregister(struct device *dev) |
873 | { | 873 | { |
874 | snd_soc_unregister_platform(&pdev->dev); | 874 | snd_soc_unregister_platform(dev); |
875 | return 0; | ||
876 | } | 875 | } |
877 | 876 | EXPORT_SYMBOL_GPL(davinci_soc_platform_unregister); | |
878 | static struct platform_driver davinci_pcm_driver = { | ||
879 | .driver = { | ||
880 | .name = "davinci-pcm-audio", | ||
881 | .owner = THIS_MODULE, | ||
882 | }, | ||
883 | |||
884 | .probe = davinci_soc_platform_probe, | ||
885 | .remove = __devexit_p(davinci_soc_platform_remove), | ||
886 | }; | ||
887 | |||
888 | module_platform_driver(davinci_pcm_driver); | ||
889 | 877 | ||
890 | MODULE_AUTHOR("Vladimir Barinov"); | 878 | MODULE_AUTHOR("Vladimir Barinov"); |
891 | MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); | 879 | MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); |
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index c0d6c9be4b4d..fc4d01cdd8c9 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h | |||
@@ -12,9 +12,8 @@ | |||
12 | #ifndef _DAVINCI_PCM_H | 12 | #ifndef _DAVINCI_PCM_H |
13 | #define _DAVINCI_PCM_H | 13 | #define _DAVINCI_PCM_H |
14 | 14 | ||
15 | #include <linux/platform_data/davinci_asp.h> | ||
15 | #include <mach/edma.h> | 16 | #include <mach/edma.h> |
16 | #include <mach/asp.h> | ||
17 | |||
18 | 17 | ||
19 | struct davinci_pcm_dma_params { | 18 | struct davinci_pcm_dma_params { |
20 | int channel; /* sync dma channel ID */ | 19 | int channel; /* sync dma channel ID */ |
@@ -28,4 +27,7 @@ struct davinci_pcm_dma_params { | |||
28 | unsigned int fifo_level; | 27 | unsigned int fifo_level; |
29 | }; | 28 | }; |
30 | 29 | ||
30 | int davinci_soc_platform_register(struct device *dev); | ||
31 | void davinci_soc_platform_unregister(struct device *dev); | ||
32 | |||
31 | #endif | 33 | #endif |
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index f71175b29e38..5be65aae7e0e 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c | |||
@@ -86,7 +86,7 @@ static struct snd_soc_dai_link sffsdr_dai = { | |||
86 | .cpu_dai_name = "davinci-mcbsp", | 86 | .cpu_dai_name = "davinci-mcbsp", |
87 | .codec_dai_name = "pcm3008-hifi", | 87 | .codec_dai_name = "pcm3008-hifi", |
88 | .codec_name = "pcm3008-codec", | 88 | .codec_name = "pcm3008-codec", |
89 | .platform_name = "davinci-pcm-audio", | 89 | .platform_name = "davinci-mcbsp", |
90 | .ops = &sffsdr_ops, | 90 | .ops = &sffsdr_ops, |
91 | }; | 91 | }; |
92 | 92 | ||
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index da030ff883d5..07bde2e6f84e 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c | |||
@@ -240,12 +240,20 @@ static int davinci_vcif_probe(struct platform_device *pdev) | |||
240 | return ret; | 240 | return ret; |
241 | } | 241 | } |
242 | 242 | ||
243 | ret = davinci_soc_platform_register(&pdev->dev); | ||
244 | if (ret) { | ||
245 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); | ||
246 | snd_soc_unregister_dai(&pdev->dev); | ||
247 | return ret; | ||
248 | } | ||
249 | |||
243 | return 0; | 250 | return 0; |
244 | } | 251 | } |
245 | 252 | ||
246 | static int davinci_vcif_remove(struct platform_device *pdev) | 253 | static int davinci_vcif_remove(struct platform_device *pdev) |
247 | { | 254 | { |
248 | snd_soc_unregister_dai(&pdev->dev); | 255 | snd_soc_unregister_dai(&pdev->dev); |
256 | davinci_soc_platform_unregister(&pdev->dev); | ||
249 | 257 | ||
250 | return 0; | 258 | return 0; |
251 | } | 259 | } |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index d70133086ac3..4563b28bd625 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -6,7 +6,7 @@ config SND_SOC_FSL_UTILS | |||
6 | 6 | ||
7 | menuconfig SND_POWERPC_SOC | 7 | menuconfig SND_POWERPC_SOC |
8 | tristate "SoC Audio for Freescale PowerPC CPUs" | 8 | tristate "SoC Audio for Freescale PowerPC CPUs" |
9 | depends on FSL_SOC | 9 | depends on FSL_SOC || PPC_MPC52xx |
10 | help | 10 | help |
11 | Say Y or M if you want to add support for codecs attached to | 11 | Say Y or M if you want to add support for codecs attached to |
12 | the PowerPC CPUs. | 12 | the PowerPC CPUs. |
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 96bb92dd174c..6feb26500580 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c | |||
@@ -823,12 +823,6 @@ static int fsl_dma_close(struct snd_pcm_substream *substream) | |||
823 | if (dma_private->irq) | 823 | if (dma_private->irq) |
824 | free_irq(dma_private->irq, dma_private); | 824 | free_irq(dma_private->irq, dma_private); |
825 | 825 | ||
826 | if (dma_private->ld_buf_phys) { | ||
827 | dma_unmap_single(dev, dma_private->ld_buf_phys, | ||
828 | sizeof(dma_private->link), | ||
829 | DMA_TO_DEVICE); | ||
830 | } | ||
831 | |||
832 | /* Deallocate the fsl_dma_private structure */ | 826 | /* Deallocate the fsl_dma_private structure */ |
833 | dma_free_coherent(dev, sizeof(struct fsl_dma_private), | 827 | dma_free_coherent(dev, sizeof(struct fsl_dma_private), |
834 | dma_private, dma_private->ld_buf_phys); | 828 | dma_private, dma_private->ld_buf_phys); |
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index e7c800ebbd75..524ce6210cee 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c | |||
@@ -74,9 +74,6 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, | |||
74 | if (!buf) | 74 | if (!buf) |
75 | return -ENOMEM; | 75 | return -ENOMEM; |
76 | 76 | ||
77 | if (!audmux_base) | ||
78 | return -ENOSYS; | ||
79 | |||
80 | if (audmux_clk) | 77 | if (audmux_clk) |
81 | clk_prepare_enable(audmux_clk); | 78 | clk_prepare_enable(audmux_clk); |
82 | 79 | ||
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index 48f9d886f020..9a15bc4bd570 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c | |||
@@ -109,6 +109,9 @@ static int snd_imx_open(struct snd_pcm_substream *substream) | |||
109 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 109 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
110 | 110 | ||
111 | dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL); | 111 | dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL); |
112 | if (!dma_data) | ||
113 | return -ENOMEM; | ||
114 | |||
112 | dma_data->peripheral_type = dma_params->shared_peripheral ? | 115 | dma_data->peripheral_type = dma_params->shared_peripheral ? |
113 | IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI; | 116 | IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI; |
114 | dma_data->priority = DMA_PRIO_HIGH; | 117 | dma_data->priority = DMA_PRIO_HIGH; |
@@ -117,7 +120,7 @@ static int snd_imx_open(struct snd_pcm_substream *substream) | |||
117 | ret = snd_dmaengine_pcm_open(substream, filter, dma_data); | 120 | ret = snd_dmaengine_pcm_open(substream, filter, dma_data); |
118 | if (ret) { | 121 | if (ret) { |
119 | kfree(dma_data); | 122 | kfree(dma_data); |
120 | return 0; | 123 | return ret; |
121 | } | 124 | } |
122 | 125 | ||
123 | snd_dmaengine_pcm_set_data(substream, dma_data); | 126 | snd_dmaengine_pcm_set_data(substream, dma_data); |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 81d7728cf67f..3c520c46fa4a 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
@@ -380,14 +380,13 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai) | |||
380 | static struct snd_soc_dai_driver imx_ssi_dai = { | 380 | static struct snd_soc_dai_driver imx_ssi_dai = { |
381 | .probe = imx_ssi_dai_probe, | 381 | .probe = imx_ssi_dai_probe, |
382 | .playback = { | 382 | .playback = { |
383 | /* The SSI does not support monaural audio. */ | 383 | .channels_min = 1, |
384 | .channels_min = 2, | ||
385 | .channels_max = 2, | 384 | .channels_max = 2, |
386 | .rates = SNDRV_PCM_RATE_8000_96000, | 385 | .rates = SNDRV_PCM_RATE_8000_96000, |
387 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 386 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
388 | }, | 387 | }, |
389 | .capture = { | 388 | .capture = { |
390 | .channels_min = 2, | 389 | .channels_min = 1, |
391 | .channels_max = 2, | 390 | .channels_max = 2, |
392 | .rates = SNDRV_PCM_RATE_8000_96000, | 391 | .rates = SNDRV_PCM_RATE_8000_96000, |
393 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 392 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
@@ -524,7 +523,7 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
524 | int ret = 0; | 523 | int ret = 0; |
525 | struct snd_soc_dai_driver *dai; | 524 | struct snd_soc_dai_driver *dai; |
526 | 525 | ||
527 | ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); | 526 | ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL); |
528 | if (!ssi) | 527 | if (!ssi) |
529 | return -ENOMEM; | 528 | return -ENOMEM; |
530 | dev_set_drvdata(&pdev->dev, ssi); | 529 | dev_set_drvdata(&pdev->dev, ssi); |
@@ -537,7 +536,7 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
537 | 536 | ||
538 | ssi->irq = platform_get_irq(pdev, 0); | 537 | ssi->irq = platform_get_irq(pdev, 0); |
539 | 538 | ||
540 | ssi->clk = clk_get(&pdev->dev, NULL); | 539 | ssi->clk = devm_clk_get(&pdev->dev, NULL); |
541 | if (IS_ERR(ssi->clk)) { | 540 | if (IS_ERR(ssi->clk)) { |
542 | ret = PTR_ERR(ssi->clk); | 541 | ret = PTR_ERR(ssi->clk); |
543 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", | 542 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", |
@@ -552,23 +551,18 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
552 | goto failed_get_resource; | 551 | goto failed_get_resource; |
553 | } | 552 | } |
554 | 553 | ||
555 | if (!request_mem_region(res->start, resource_size(res), DRV_NAME)) { | 554 | ssi->base = devm_request_and_ioremap(&pdev->dev, res); |
556 | dev_err(&pdev->dev, "request_mem_region failed\n"); | ||
557 | ret = -EBUSY; | ||
558 | goto failed_get_resource; | ||
559 | } | ||
560 | |||
561 | ssi->base = ioremap(res->start, resource_size(res)); | ||
562 | if (!ssi->base) { | 555 | if (!ssi->base) { |
563 | dev_err(&pdev->dev, "ioremap failed\n"); | 556 | dev_err(&pdev->dev, "ioremap failed\n"); |
564 | ret = -ENODEV; | 557 | ret = -ENODEV; |
565 | goto failed_ioremap; | 558 | goto failed_register; |
566 | } | 559 | } |
567 | 560 | ||
568 | if (ssi->flags & IMX_SSI_USE_AC97) { | 561 | if (ssi->flags & IMX_SSI_USE_AC97) { |
569 | if (ac97_ssi) { | 562 | if (ac97_ssi) { |
563 | dev_err(&pdev->dev, "AC'97 SSI already registered\n"); | ||
570 | ret = -EBUSY; | 564 | ret = -EBUSY; |
571 | goto failed_ac97; | 565 | goto failed_register; |
572 | } | 566 | } |
573 | ac97_ssi = ssi; | 567 | ac97_ssi = ssi; |
574 | setup_channel_to_ac97(ssi); | 568 | setup_channel_to_ac97(ssi); |
@@ -637,15 +631,10 @@ failed_pdev_fiq_add: | |||
637 | failed_pdev_fiq_alloc: | 631 | failed_pdev_fiq_alloc: |
638 | snd_soc_unregister_dai(&pdev->dev); | 632 | snd_soc_unregister_dai(&pdev->dev); |
639 | failed_register: | 633 | failed_register: |
640 | failed_ac97: | ||
641 | iounmap(ssi->base); | ||
642 | failed_ioremap: | ||
643 | release_mem_region(res->start, resource_size(res)); | 634 | release_mem_region(res->start, resource_size(res)); |
644 | failed_get_resource: | 635 | failed_get_resource: |
645 | clk_disable_unprepare(ssi->clk); | 636 | clk_disable_unprepare(ssi->clk); |
646 | clk_put(ssi->clk); | ||
647 | failed_clk: | 637 | failed_clk: |
648 | kfree(ssi); | ||
649 | 638 | ||
650 | return ret; | 639 | return ret; |
651 | } | 640 | } |
@@ -663,11 +652,8 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev) | |||
663 | if (ssi->flags & IMX_SSI_USE_AC97) | 652 | if (ssi->flags & IMX_SSI_USE_AC97) |
664 | ac97_ssi = NULL; | 653 | ac97_ssi = NULL; |
665 | 654 | ||
666 | iounmap(ssi->base); | ||
667 | release_mem_region(res->start, resource_size(res)); | 655 | release_mem_region(res->start, resource_size(res)); |
668 | clk_disable_unprepare(ssi->clk); | 656 | clk_disable_unprepare(ssi->clk); |
669 | clk_put(ssi->clk); | ||
670 | kfree(ssi); | ||
671 | 657 | ||
672 | return 0; | 658 | return 0; |
673 | } | 659 | } |
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 9a3f7c5ab687..9997c039bb24 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c | |||
@@ -370,7 +370,7 @@ static struct snd_soc_platform_driver mpc5200_audio_dma_platform = { | |||
370 | .pcm_free = &psc_dma_free, | 370 | .pcm_free = &psc_dma_free, |
371 | }; | 371 | }; |
372 | 372 | ||
373 | static int mpc5200_hpcd_probe(struct platform_device *op) | 373 | int mpc5200_audio_dma_create(struct platform_device *op) |
374 | { | 374 | { |
375 | phys_addr_t fifo; | 375 | phys_addr_t fifo; |
376 | struct psc_dma *psc_dma; | 376 | struct psc_dma *psc_dma; |
@@ -487,8 +487,9 @@ out_unmap: | |||
487 | iounmap(regs); | 487 | iounmap(regs); |
488 | return ret; | 488 | return ret; |
489 | } | 489 | } |
490 | EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create); | ||
490 | 491 | ||
491 | static int mpc5200_hpcd_remove(struct platform_device *op) | 492 | int mpc5200_audio_dma_destroy(struct platform_device *op) |
492 | { | 493 | { |
493 | struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); | 494 | struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); |
494 | 495 | ||
@@ -510,24 +511,7 @@ static int mpc5200_hpcd_remove(struct platform_device *op) | |||
510 | 511 | ||
511 | return 0; | 512 | return 0; |
512 | } | 513 | } |
513 | 514 | EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy); | |
514 | static struct of_device_id mpc5200_hpcd_match[] = { | ||
515 | { .compatible = "fsl,mpc5200-pcm", }, | ||
516 | {} | ||
517 | }; | ||
518 | MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match); | ||
519 | |||
520 | static struct platform_driver mpc5200_hpcd_of_driver = { | ||
521 | .probe = mpc5200_hpcd_probe, | ||
522 | .remove = mpc5200_hpcd_remove, | ||
523 | .driver = { | ||
524 | .owner = THIS_MODULE, | ||
525 | .name = "mpc5200-pcm-audio", | ||
526 | .of_match_table = mpc5200_hpcd_match, | ||
527 | } | ||
528 | }; | ||
529 | |||
530 | module_platform_driver(mpc5200_hpcd_of_driver); | ||
531 | 515 | ||
532 | MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); | 516 | MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); |
533 | MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); | 517 | MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); |
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index a3c0cd5382fb..dff253fde29a 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h | |||
@@ -81,4 +81,7 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) | |||
81 | return &psc_dma->playback; | 81 | return &psc_dma->playback; |
82 | } | 82 | } |
83 | 83 | ||
84 | int mpc5200_audio_dma_create(struct platform_device *op); | ||
85 | int mpc5200_audio_dma_destroy(struct platform_device *op); | ||
86 | |||
84 | #endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ | 87 | #endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ |
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index ffa00a2eb770..a313c0ae36db 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c | |||
@@ -237,15 +237,18 @@ static const struct snd_soc_dai_ops psc_ac97_digital_ops = { | |||
237 | 237 | ||
238 | static struct snd_soc_dai_driver psc_ac97_dai[] = { | 238 | static struct snd_soc_dai_driver psc_ac97_dai[] = { |
239 | { | 239 | { |
240 | .name = "mpc5200-psc-ac97.0", | ||
240 | .ac97_control = 1, | 241 | .ac97_control = 1, |
241 | .probe = psc_ac97_probe, | 242 | .probe = psc_ac97_probe, |
242 | .playback = { | 243 | .playback = { |
244 | .stream_name = "AC97 Playback", | ||
243 | .channels_min = 1, | 245 | .channels_min = 1, |
244 | .channels_max = 6, | 246 | .channels_max = 6, |
245 | .rates = SNDRV_PCM_RATE_8000_48000, | 247 | .rates = SNDRV_PCM_RATE_8000_48000, |
246 | .formats = SNDRV_PCM_FMTBIT_S32_BE, | 248 | .formats = SNDRV_PCM_FMTBIT_S32_BE, |
247 | }, | 249 | }, |
248 | .capture = { | 250 | .capture = { |
251 | .stream_name = "AC97 Capture", | ||
249 | .channels_min = 1, | 252 | .channels_min = 1, |
250 | .channels_max = 2, | 253 | .channels_max = 2, |
251 | .rates = SNDRV_PCM_RATE_8000_48000, | 254 | .rates = SNDRV_PCM_RATE_8000_48000, |
@@ -254,8 +257,10 @@ static struct snd_soc_dai_driver psc_ac97_dai[] = { | |||
254 | .ops = &psc_ac97_analog_ops, | 257 | .ops = &psc_ac97_analog_ops, |
255 | }, | 258 | }, |
256 | { | 259 | { |
260 | .name = "mpc5200-psc-ac97.1", | ||
257 | .ac97_control = 1, | 261 | .ac97_control = 1, |
258 | .playback = { | 262 | .playback = { |
263 | .stream_name = "AC97 SPDIF", | ||
259 | .channels_min = 1, | 264 | .channels_min = 1, |
260 | .channels_max = 2, | 265 | .channels_max = 2, |
261 | .rates = SNDRV_PCM_RATE_32000 | \ | 266 | .rates = SNDRV_PCM_RATE_32000 | \ |
@@ -278,6 +283,10 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op) | |||
278 | struct snd_ac97 ac97; | 283 | struct snd_ac97 ac97; |
279 | struct mpc52xx_psc __iomem *regs; | 284 | struct mpc52xx_psc __iomem *regs; |
280 | 285 | ||
286 | rc = mpc5200_audio_dma_create(op); | ||
287 | if (rc != 0) | ||
288 | return rc; | ||
289 | |||
281 | rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); | 290 | rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); |
282 | if (rc != 0) { | 291 | if (rc != 0) { |
283 | dev_err(&op->dev, "Failed to register DAI\n"); | 292 | dev_err(&op->dev, "Failed to register DAI\n"); |
@@ -303,6 +312,7 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op) | |||
303 | 312 | ||
304 | static int __devexit psc_ac97_of_remove(struct platform_device *op) | 313 | static int __devexit psc_ac97_of_remove(struct platform_device *op) |
305 | { | 314 | { |
315 | mpc5200_audio_dma_destroy(op); | ||
306 | snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai)); | 316 | snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai)); |
307 | return 0; | 317 | return 0; |
308 | } | 318 | } |
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 7b530327553a..ba1f0a66358f 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c | |||
@@ -130,13 +130,16 @@ static const struct snd_soc_dai_ops psc_i2s_dai_ops = { | |||
130 | }; | 130 | }; |
131 | 131 | ||
132 | static struct snd_soc_dai_driver psc_i2s_dai[] = {{ | 132 | static struct snd_soc_dai_driver psc_i2s_dai[] = {{ |
133 | .name = "mpc5200-psc-i2s.0", | ||
133 | .playback = { | 134 | .playback = { |
135 | .stream_name = "I2S Playback", | ||
134 | .channels_min = 2, | 136 | .channels_min = 2, |
135 | .channels_max = 2, | 137 | .channels_max = 2, |
136 | .rates = PSC_I2S_RATES, | 138 | .rates = PSC_I2S_RATES, |
137 | .formats = PSC_I2S_FORMATS, | 139 | .formats = PSC_I2S_FORMATS, |
138 | }, | 140 | }, |
139 | .capture = { | 141 | .capture = { |
142 | .stream_name = "I2S Capture", | ||
140 | .channels_min = 2, | 143 | .channels_min = 2, |
141 | .channels_max = 2, | 144 | .channels_max = 2, |
142 | .rates = PSC_I2S_RATES, | 145 | .rates = PSC_I2S_RATES, |
@@ -156,6 +159,10 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op) | |||
156 | struct psc_dma *psc_dma; | 159 | struct psc_dma *psc_dma; |
157 | struct mpc52xx_psc __iomem *regs; | 160 | struct mpc52xx_psc __iomem *regs; |
158 | 161 | ||
162 | rc = mpc5200_audio_dma_create(op); | ||
163 | if (rc != 0) | ||
164 | return rc; | ||
165 | |||
159 | rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); | 166 | rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); |
160 | if (rc != 0) { | 167 | if (rc != 0) { |
161 | pr_err("Failed to register DAI\n"); | 168 | pr_err("Failed to register DAI\n"); |
@@ -200,6 +207,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op) | |||
200 | 207 | ||
201 | static int __devexit psc_i2s_of_remove(struct platform_device *op) | 208 | static int __devexit psc_i2s_of_remove(struct platform_device *op) |
202 | { | 209 | { |
210 | mpc5200_audio_dma_destroy(op); | ||
203 | snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai)); | 211 | snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai)); |
204 | return 0; | 212 | return 0; |
205 | } | 213 | } |
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 60bcba1bc30e..9ff9318c52b9 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c | |||
@@ -192,7 +192,6 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) | |||
192 | container_of(dev, struct platform_device, dev); | 192 | container_of(dev, struct platform_device, dev); |
193 | struct device_node *np = ssi_pdev->dev.of_node; | 193 | struct device_node *np = ssi_pdev->dev.of_node; |
194 | struct device_node *codec_np = NULL; | 194 | struct device_node *codec_np = NULL; |
195 | struct platform_device *sound_device = NULL; | ||
196 | struct mpc8610_hpcd_data *machine_data; | 195 | struct mpc8610_hpcd_data *machine_data; |
197 | int ret = -ENODEV; | 196 | int ret = -ENODEV; |
198 | const char *sprop; | 197 | const char *sprop; |
@@ -341,34 +340,22 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) | |||
341 | machine_data->card.probe = mpc8610_hpcd_machine_probe; | 340 | machine_data->card.probe = mpc8610_hpcd_machine_probe; |
342 | machine_data->card.remove = mpc8610_hpcd_machine_remove; | 341 | machine_data->card.remove = mpc8610_hpcd_machine_remove; |
343 | machine_data->card.name = pdev->name; /* The platform driver name */ | 342 | machine_data->card.name = pdev->name; /* The platform driver name */ |
343 | machine_data->card.owner = THIS_MODULE; | ||
344 | machine_data->card.dev = &pdev->dev; | ||
344 | machine_data->card.num_links = 2; | 345 | machine_data->card.num_links = 2; |
345 | machine_data->card.dai_link = machine_data->dai; | 346 | machine_data->card.dai_link = machine_data->dai; |
346 | 347 | ||
347 | /* Allocate a new audio platform device structure */ | ||
348 | sound_device = platform_device_alloc("soc-audio", -1); | ||
349 | if (!sound_device) { | ||
350 | dev_err(&pdev->dev, "platform device alloc failed\n"); | ||
351 | ret = -ENOMEM; | ||
352 | goto error; | ||
353 | } | ||
354 | |||
355 | /* Associate the card data with the sound device */ | ||
356 | platform_set_drvdata(sound_device, &machine_data->card); | ||
357 | |||
358 | /* Register with ASoC */ | 348 | /* Register with ASoC */ |
359 | ret = platform_device_add(sound_device); | 349 | ret = snd_soc_register_card(&machine_data->card); |
360 | if (ret) { | 350 | if (ret) { |
361 | dev_err(&pdev->dev, "platform device add failed\n"); | 351 | dev_err(&pdev->dev, "could not register card\n"); |
362 | goto error_sound; | 352 | goto error; |
363 | } | 353 | } |
364 | dev_set_drvdata(&pdev->dev, sound_device); | ||
365 | 354 | ||
366 | of_node_put(codec_np); | 355 | of_node_put(codec_np); |
367 | 356 | ||
368 | return 0; | 357 | return 0; |
369 | 358 | ||
370 | error_sound: | ||
371 | platform_device_put(sound_device); | ||
372 | error: | 359 | error: |
373 | kfree(machine_data); | 360 | kfree(machine_data); |
374 | error_alloc: | 361 | error_alloc: |
@@ -383,17 +370,12 @@ error_alloc: | |||
383 | */ | 370 | */ |
384 | static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev) | 371 | static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev) |
385 | { | 372 | { |
386 | struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); | 373 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
387 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
388 | struct mpc8610_hpcd_data *machine_data = | 374 | struct mpc8610_hpcd_data *machine_data = |
389 | container_of(card, struct mpc8610_hpcd_data, card); | 375 | container_of(card, struct mpc8610_hpcd_data, card); |
390 | 376 | ||
391 | platform_device_unregister(sound_device); | 377 | snd_soc_unregister_card(card); |
392 | |||
393 | kfree(machine_data); | 378 | kfree(machine_data); |
394 | sound_device->dev.platform_data = NULL; | ||
395 | |||
396 | dev_set_drvdata(&pdev->dev, NULL); | ||
397 | 379 | ||
398 | return 0; | 380 | return 0; |
399 | } | 381 | } |
diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c index f6d04ad4bb39..2b76877b1789 100644 --- a/sound/soc/fsl/mx27vis-aic32x4.c +++ b/sound/soc/fsl/mx27vis-aic32x4.c | |||
@@ -26,13 +26,13 @@ | |||
26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
28 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
29 | #include <linux/platform_data/asoc-mx27vis.h> | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
31 | #include <sound/soc.h> | 32 | #include <sound/soc.h> |
32 | #include <sound/soc-dapm.h> | 33 | #include <sound/soc-dapm.h> |
33 | #include <sound/tlv.h> | 34 | #include <sound/tlv.h> |
34 | #include <asm/mach-types.h> | 35 | #include <asm/mach-types.h> |
35 | #include <mach/iomux-mx27.h> | ||
36 | 36 | ||
37 | #include "../codecs/tlv320aic32x4.h" | 37 | #include "../codecs/tlv320aic32x4.h" |
38 | #include "imx-ssi.h" | 38 | #include "imx-ssi.h" |
@@ -41,20 +41,12 @@ | |||
41 | #define MX27VIS_AMP_GAIN 0 | 41 | #define MX27VIS_AMP_GAIN 0 |
42 | #define MX27VIS_AMP_MUTE 1 | 42 | #define MX27VIS_AMP_MUTE 1 |
43 | 43 | ||
44 | #define MX27VIS_PIN_G0 (GPIO_PORTF + 9) | ||
45 | #define MX27VIS_PIN_G1 (GPIO_PORTF + 8) | ||
46 | #define MX27VIS_PIN_SDL (GPIO_PORTE + 5) | ||
47 | #define MX27VIS_PIN_SDR (GPIO_PORTF + 7) | ||
48 | |||
49 | static int mx27vis_amp_gain; | 44 | static int mx27vis_amp_gain; |
50 | static int mx27vis_amp_mute; | 45 | static int mx27vis_amp_mute; |
51 | 46 | static int mx27vis_amp_gain0_gpio; | |
52 | static const int mx27vis_amp_pins[] = { | 47 | static int mx27vis_amp_gain1_gpio; |
53 | MX27VIS_PIN_G0 | GPIO_GPIO | GPIO_OUT, | 48 | static int mx27vis_amp_mutel_gpio; |
54 | MX27VIS_PIN_G1 | GPIO_GPIO | GPIO_OUT, | 49 | static int mx27vis_amp_muter_gpio; |
55 | MX27VIS_PIN_SDL | GPIO_GPIO | GPIO_OUT, | ||
56 | MX27VIS_PIN_SDR | GPIO_GPIO | GPIO_OUT, | ||
57 | }; | ||
58 | 50 | ||
59 | static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, | 51 | static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, |
60 | struct snd_pcm_hw_params *params) | 52 | struct snd_pcm_hw_params *params) |
@@ -109,13 +101,13 @@ static int mx27vis_amp_set(struct snd_kcontrol *kcontrol, | |||
109 | 101 | ||
110 | switch (reg) { | 102 | switch (reg) { |
111 | case MX27VIS_AMP_GAIN: | 103 | case MX27VIS_AMP_GAIN: |
112 | gpio_set_value(MX27VIS_PIN_G0, value & 1); | 104 | gpio_set_value(mx27vis_amp_gain0_gpio, value & 1); |
113 | gpio_set_value(MX27VIS_PIN_G1, value >> 1); | 105 | gpio_set_value(mx27vis_amp_gain1_gpio, value >> 1); |
114 | mx27vis_amp_gain = value; | 106 | mx27vis_amp_gain = value; |
115 | break; | 107 | break; |
116 | case MX27VIS_AMP_MUTE: | 108 | case MX27VIS_AMP_MUTE: |
117 | gpio_set_value(MX27VIS_PIN_SDL, value & 1); | 109 | gpio_set_value(mx27vis_amp_mutel_gpio, value & 1); |
118 | gpio_set_value(MX27VIS_PIN_SDR, value >> 1); | 110 | gpio_set_value(mx27vis_amp_muter_gpio, value >> 1); |
119 | mx27vis_amp_mute = value; | 111 | mx27vis_amp_mute = value; |
120 | break; | 112 | break; |
121 | } | 113 | } |
@@ -190,8 +182,19 @@ static struct snd_soc_card mx27vis_aic32x4 = { | |||
190 | 182 | ||
191 | static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev) | 183 | static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev) |
192 | { | 184 | { |
185 | struct snd_mx27vis_platform_data *pdata = pdev->dev.platform_data; | ||
193 | int ret; | 186 | int ret; |
194 | 187 | ||
188 | if (!pdata) { | ||
189 | dev_err(&pdev->dev, "No platform data supplied\n"); | ||
190 | return -EINVAL; | ||
191 | } | ||
192 | |||
193 | mx27vis_amp_gain0_gpio = pdata->amp_gain0_gpio; | ||
194 | mx27vis_amp_gain1_gpio = pdata->amp_gain1_gpio; | ||
195 | mx27vis_amp_mutel_gpio = pdata->amp_mutel_gpio; | ||
196 | mx27vis_amp_muter_gpio = pdata->amp_muter_gpio; | ||
197 | |||
195 | mx27vis_aic32x4.dev = &pdev->dev; | 198 | mx27vis_aic32x4.dev = &pdev->dev; |
196 | ret = snd_soc_register_card(&mx27vis_aic32x4); | 199 | ret = snd_soc_register_card(&mx27vis_aic32x4); |
197 | if (ret) { | 200 | if (ret) { |
@@ -213,11 +216,6 @@ static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev) | |||
213 | IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) | 216 | IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) |
214 | ); | 217 | ); |
215 | 218 | ||
216 | ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins, | ||
217 | ARRAY_SIZE(mx27vis_amp_pins), "MX27VIS_AMP"); | ||
218 | if (ret) | ||
219 | printk(KERN_ERR "ASoC: unable to setup gpios\n"); | ||
220 | |||
221 | return ret; | 219 | return ret; |
222 | } | 220 | } |
223 | 221 | ||
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 50adf4032bcc..144d49603637 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c | |||
@@ -202,7 +202,6 @@ static int p1022_ds_probe(struct platform_device *pdev) | |||
202 | container_of(dev, struct platform_device, dev); | 202 | container_of(dev, struct platform_device, dev); |
203 | struct device_node *np = ssi_pdev->dev.of_node; | 203 | struct device_node *np = ssi_pdev->dev.of_node; |
204 | struct device_node *codec_np = NULL; | 204 | struct device_node *codec_np = NULL; |
205 | struct platform_device *sound_device = NULL; | ||
206 | struct machine_data *mdata; | 205 | struct machine_data *mdata; |
207 | int ret = -ENODEV; | 206 | int ret = -ENODEV; |
208 | const char *sprop; | 207 | const char *sprop; |
@@ -349,36 +348,23 @@ static int p1022_ds_probe(struct platform_device *pdev) | |||
349 | mdata->card.probe = p1022_ds_machine_probe; | 348 | mdata->card.probe = p1022_ds_machine_probe; |
350 | mdata->card.remove = p1022_ds_machine_remove; | 349 | mdata->card.remove = p1022_ds_machine_remove; |
351 | mdata->card.name = pdev->name; /* The platform driver name */ | 350 | mdata->card.name = pdev->name; /* The platform driver name */ |
351 | mdata->card.owner = THIS_MODULE; | ||
352 | mdata->card.dev = &pdev->dev; | ||
352 | mdata->card.num_links = 2; | 353 | mdata->card.num_links = 2; |
353 | mdata->card.dai_link = mdata->dai; | 354 | mdata->card.dai_link = mdata->dai; |
354 | 355 | ||
355 | /* Allocate a new audio platform device structure */ | ||
356 | sound_device = platform_device_alloc("soc-audio", -1); | ||
357 | if (!sound_device) { | ||
358 | dev_err(&pdev->dev, "platform device alloc failed\n"); | ||
359 | ret = -ENOMEM; | ||
360 | goto error; | ||
361 | } | ||
362 | |||
363 | /* Associate the card data with the sound device */ | ||
364 | platform_set_drvdata(sound_device, &mdata->card); | ||
365 | |||
366 | /* Register with ASoC */ | 356 | /* Register with ASoC */ |
367 | ret = platform_device_add(sound_device); | 357 | ret = snd_soc_register_card(&mdata->card); |
368 | if (ret) { | 358 | if (ret) { |
369 | dev_err(&pdev->dev, "platform device add failed\n"); | 359 | dev_err(&pdev->dev, "could not register card\n"); |
370 | goto error; | 360 | goto error; |
371 | } | 361 | } |
372 | dev_set_drvdata(&pdev->dev, sound_device); | ||
373 | 362 | ||
374 | of_node_put(codec_np); | 363 | of_node_put(codec_np); |
375 | 364 | ||
376 | return 0; | 365 | return 0; |
377 | 366 | ||
378 | error: | 367 | error: |
379 | if (sound_device) | ||
380 | platform_device_put(sound_device); | ||
381 | |||
382 | kfree(mdata); | 368 | kfree(mdata); |
383 | error_put: | 369 | error_put: |
384 | of_node_put(codec_np); | 370 | of_node_put(codec_np); |
@@ -392,17 +378,12 @@ error_put: | |||
392 | */ | 378 | */ |
393 | static int __devexit p1022_ds_remove(struct platform_device *pdev) | 379 | static int __devexit p1022_ds_remove(struct platform_device *pdev) |
394 | { | 380 | { |
395 | struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); | 381 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
396 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
397 | struct machine_data *mdata = | 382 | struct machine_data *mdata = |
398 | container_of(card, struct machine_data, card); | 383 | container_of(card, struct machine_data, card); |
399 | 384 | ||
400 | platform_device_unregister(sound_device); | 385 | snd_soc_unregister_card(card); |
401 | |||
402 | kfree(mdata); | 386 | kfree(mdata); |
403 | sound_device->dev.platform_data = NULL; | ||
404 | |||
405 | dev_set_drvdata(&pdev->dev, NULL); | ||
406 | 387 | ||
407 | return 0; | 388 | return 0; |
408 | } | 389 | } |
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index b3af55dcde9d..4b63ec8eb372 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c | |||
@@ -12,32 +12,27 @@ | |||
12 | 12 | ||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/device.h> | 15 | #include <linux/device.h> |
17 | #include <linux/delay.h> | ||
18 | #include <linux/of_device.h> | 16 | #include <linux/of_device.h> |
19 | #include <linux/of_platform.h> | 17 | #include <linux/of_platform.h> |
20 | #include <linux/dma-mapping.h> | ||
21 | 18 | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/initval.h> | ||
26 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
27 | 20 | ||
28 | #include "mpc5200_dma.h" | 21 | #include "mpc5200_dma.h" |
29 | #include "mpc5200_psc_ac97.h" | ||
30 | #include "../codecs/wm9712.h" | ||
31 | 22 | ||
32 | #define DRV_NAME "pcm030-audio-fabric" | 23 | #define DRV_NAME "pcm030-audio-fabric" |
33 | 24 | ||
25 | struct pcm030_audio_data { | ||
26 | struct snd_soc_card *card; | ||
27 | struct platform_device *codec_device; | ||
28 | }; | ||
29 | |||
34 | static struct snd_soc_dai_link pcm030_fabric_dai[] = { | 30 | static struct snd_soc_dai_link pcm030_fabric_dai[] = { |
35 | { | 31 | { |
36 | .name = "AC97", | 32 | .name = "AC97", |
37 | .stream_name = "AC97 Analog", | 33 | .stream_name = "AC97 Analog", |
38 | .codec_dai_name = "wm9712-hifi", | 34 | .codec_dai_name = "wm9712-hifi", |
39 | .cpu_dai_name = "mpc5200-psc-ac97.0", | 35 | .cpu_dai_name = "mpc5200-psc-ac97.0", |
40 | .platform_name = "mpc5200-pcm-audio", | ||
41 | .codec_name = "wm9712-codec", | 36 | .codec_name = "wm9712-codec", |
42 | }, | 37 | }, |
43 | { | 38 | { |
@@ -45,44 +40,95 @@ static struct snd_soc_dai_link pcm030_fabric_dai[] = { | |||
45 | .stream_name = "AC97 IEC958", | 40 | .stream_name = "AC97 IEC958", |
46 | .codec_dai_name = "wm9712-aux", | 41 | .codec_dai_name = "wm9712-aux", |
47 | .cpu_dai_name = "mpc5200-psc-ac97.1", | 42 | .cpu_dai_name = "mpc5200-psc-ac97.1", |
48 | .platform_name = "mpc5200-pcm-audio", | ||
49 | .codec_name = "wm9712-codec", | 43 | .codec_name = "wm9712-codec", |
50 | }, | 44 | }, |
51 | }; | 45 | }; |
52 | 46 | ||
53 | static struct snd_soc_card card = { | 47 | static struct snd_soc_card pcm030_card = { |
54 | .name = "pcm030", | 48 | .name = "pcm030", |
55 | .owner = THIS_MODULE, | 49 | .owner = THIS_MODULE, |
56 | .dai_link = pcm030_fabric_dai, | 50 | .dai_link = pcm030_fabric_dai, |
57 | .num_links = ARRAY_SIZE(pcm030_fabric_dai), | 51 | .num_links = ARRAY_SIZE(pcm030_fabric_dai), |
58 | }; | 52 | }; |
59 | 53 | ||
60 | static __init int pcm030_fabric_init(void) | 54 | static int __init pcm030_fabric_probe(struct platform_device *op) |
61 | { | 55 | { |
62 | struct platform_device *pdev; | 56 | struct device_node *np = op->dev.of_node; |
63 | int rc; | 57 | struct device_node *platform_np; |
58 | struct snd_soc_card *card = &pcm030_card; | ||
59 | struct pcm030_audio_data *pdata; | ||
60 | int ret; | ||
61 | int i; | ||
64 | 62 | ||
65 | if (!of_machine_is_compatible("phytec,pcm030")) | 63 | if (!of_machine_is_compatible("phytec,pcm030")) |
66 | return -ENODEV; | 64 | return -ENODEV; |
67 | 65 | ||
68 | pdev = platform_device_alloc("soc-audio", 1); | 66 | pdata = devm_kzalloc(&op->dev, sizeof(struct pcm030_audio_data), |
69 | if (!pdev) { | 67 | GFP_KERNEL); |
70 | pr_err("pcm030_fabric_init: platform_device_alloc() failed\n"); | 68 | if (!pdata) |
71 | return -ENODEV; | 69 | return -ENOMEM; |
72 | } | 70 | |
71 | card->dev = &op->dev; | ||
72 | platform_set_drvdata(op, pdata); | ||
73 | 73 | ||
74 | platform_set_drvdata(pdev, &card); | 74 | pdata->card = card; |
75 | 75 | ||
76 | rc = platform_device_add(pdev); | 76 | platform_np = of_parse_phandle(np, "asoc-platform", 0); |
77 | if (rc) { | 77 | if (!platform_np) { |
78 | pr_err("pcm030_fabric_init: platform_device_add() failed\n"); | 78 | dev_err(&op->dev, "ac97 not registered\n"); |
79 | platform_device_put(pdev); | ||
80 | return -ENODEV; | 79 | return -ENODEV; |
81 | } | 80 | } |
82 | return 0; | 81 | |
82 | for (i = 0; i < card->num_links; i++) | ||
83 | card->dai_link[i].platform_of_node = platform_np; | ||
84 | |||
85 | ret = request_module("snd-soc-wm9712"); | ||
86 | if (ret) | ||
87 | dev_err(&op->dev, "request_module returned: %d\n", ret); | ||
88 | |||
89 | pdata->codec_device = platform_device_alloc("wm9712-codec", -1); | ||
90 | if (!pdata->codec_device) | ||
91 | dev_err(&op->dev, "platform_device_alloc() failed\n"); | ||
92 | |||
93 | ret = platform_device_add(pdata->codec_device); | ||
94 | if (ret) | ||
95 | dev_err(&op->dev, "platform_device_add() failed: %d\n", ret); | ||
96 | |||
97 | ret = snd_soc_register_card(card); | ||
98 | if (ret) | ||
99 | dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret); | ||
100 | |||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static int __devexit pcm030_fabric_remove(struct platform_device *op) | ||
105 | { | ||
106 | struct pcm030_audio_data *pdata = platform_get_drvdata(op); | ||
107 | int ret; | ||
108 | |||
109 | ret = snd_soc_unregister_card(pdata->card); | ||
110 | platform_device_unregister(pdata->codec_device); | ||
111 | |||
112 | return ret; | ||
83 | } | 113 | } |
84 | 114 | ||
85 | module_init(pcm030_fabric_init); | 115 | static struct of_device_id pcm030_audio_match[] = { |
116 | { .compatible = "phytec,pcm030-audio-fabric", }, | ||
117 | {} | ||
118 | }; | ||
119 | MODULE_DEVICE_TABLE(of, pcm030_audio_match); | ||
120 | |||
121 | static struct platform_driver pcm030_fabric_driver = { | ||
122 | .probe = pcm030_fabric_probe, | ||
123 | .remove = __devexit_p(pcm030_fabric_remove), | ||
124 | .driver = { | ||
125 | .name = DRV_NAME, | ||
126 | .owner = THIS_MODULE, | ||
127 | .of_match_table = pcm030_audio_match, | ||
128 | }, | ||
129 | }; | ||
130 | |||
131 | module_platform_driver(pcm030_fabric_driver); | ||
86 | 132 | ||
87 | 133 | ||
88 | MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>"); | 134 | MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>"); |
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c index 2937e54da49e..2cc7782714b5 100644 --- a/sound/soc/mid-x86/mfld_machine.c +++ b/sound/soc/mid-x86/mfld_machine.c | |||
@@ -318,6 +318,15 @@ static struct snd_soc_dai_link mfld_msic_dailink[] = { | |||
318 | .platform_name = "sst-platform", | 318 | .platform_name = "sst-platform", |
319 | .init = NULL, | 319 | .init = NULL, |
320 | }, | 320 | }, |
321 | { | ||
322 | .name = "Medfield Compress", | ||
323 | .stream_name = "Speaker", | ||
324 | .cpu_dai_name = "Compress-cpu-dai", | ||
325 | .codec_dai_name = "SN95031 Speaker", | ||
326 | .codec_name = "sn95031", | ||
327 | .platform_name = "sst-platform", | ||
328 | .init = NULL, | ||
329 | }, | ||
321 | }; | 330 | }; |
322 | 331 | ||
323 | /* SoC card */ | 332 | /* SoC card */ |
diff --git a/sound/soc/mid-x86/sst_dsp.h b/sound/soc/mid-x86/sst_dsp.h new file mode 100644 index 000000000000..0fce1de284ff --- /dev/null +++ b/sound/soc/mid-x86/sst_dsp.h | |||
@@ -0,0 +1,134 @@ | |||
1 | #ifndef __SST_DSP_H__ | ||
2 | #define __SST_DSP_H__ | ||
3 | /* | ||
4 | * sst_dsp.h - Intel SST Driver for audio engine | ||
5 | * | ||
6 | * Copyright (C) 2008-12 Intel Corporation | ||
7 | * Authors: Vinod Koul <vinod.koul@linux.intel.com> | ||
8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; version 2 of the License. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
22 | * | ||
23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
24 | */ | ||
25 | |||
26 | enum sst_codec_types { | ||
27 | /* AUDIO/MUSIC CODEC Type Definitions */ | ||
28 | SST_CODEC_TYPE_UNKNOWN = 0, | ||
29 | SST_CODEC_TYPE_PCM, /* Pass through Audio codec */ | ||
30 | SST_CODEC_TYPE_MP3, | ||
31 | SST_CODEC_TYPE_MP24, | ||
32 | SST_CODEC_TYPE_AAC, | ||
33 | SST_CODEC_TYPE_AACP, | ||
34 | SST_CODEC_TYPE_eAACP, | ||
35 | }; | ||
36 | |||
37 | enum stream_type { | ||
38 | SST_STREAM_TYPE_NONE = 0, | ||
39 | SST_STREAM_TYPE_MUSIC = 1, | ||
40 | }; | ||
41 | |||
42 | struct snd_pcm_params { | ||
43 | u16 codec; /* codec type */ | ||
44 | u8 num_chan; /* 1=Mono, 2=Stereo */ | ||
45 | u8 pcm_wd_sz; /* 16/24 - bit*/ | ||
46 | u32 reserved; /* Bitrate in bits per second */ | ||
47 | u32 sfreq; /* Sampling rate in Hz */ | ||
48 | u8 use_offload_path; | ||
49 | u8 reserved2; | ||
50 | u16 reserved3; | ||
51 | u8 channel_map[8]; | ||
52 | } __packed; | ||
53 | |||
54 | /* MP3 Music Parameters Message */ | ||
55 | struct snd_mp3_params { | ||
56 | u16 codec; | ||
57 | u8 num_chan; /* 1=Mono, 2=Stereo */ | ||
58 | u8 pcm_wd_sz; /* 16/24 - bit*/ | ||
59 | u8 crc_check; /* crc_check - disable (0) or enable (1) */ | ||
60 | u8 reserved1; /* unused*/ | ||
61 | u16 reserved2; /* Unused */ | ||
62 | } __packed; | ||
63 | |||
64 | #define AAC_BIT_STREAM_ADTS 0 | ||
65 | #define AAC_BIT_STREAM_ADIF 1 | ||
66 | #define AAC_BIT_STREAM_RAW 2 | ||
67 | |||
68 | /* AAC Music Parameters Message */ | ||
69 | struct snd_aac_params { | ||
70 | u16 codec; | ||
71 | u8 num_chan; /* 1=Mono, 2=Stereo*/ | ||
72 | u8 pcm_wd_sz; /* 16/24 - bit*/ | ||
73 | u8 bdownsample; /*SBR downsampling 0 - disable 1 -enabled AAC+ only */ | ||
74 | u8 bs_format; /* input bit stream format adts=0, adif=1, raw=2 */ | ||
75 | u16 reser2; | ||
76 | u32 externalsr; /*sampling rate of basic AAC raw bit stream*/ | ||
77 | u8 sbr_signalling;/*disable/enable/set automode the SBR tool.AAC+*/ | ||
78 | u8 reser1; | ||
79 | u16 reser3; | ||
80 | } __packed; | ||
81 | |||
82 | /* WMA Music Parameters Message */ | ||
83 | struct snd_wma_params { | ||
84 | u16 codec; | ||
85 | u8 num_chan; /* 1=Mono, 2=Stereo */ | ||
86 | u8 pcm_wd_sz; /* 16/24 - bit*/ | ||
87 | u32 brate; /* Use the hard coded value. */ | ||
88 | u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ | ||
89 | u32 channel_mask; /* Channel Mask */ | ||
90 | u16 format_tag; /* Format Tag */ | ||
91 | u16 block_align; /* packet size */ | ||
92 | u16 wma_encode_opt;/* Encoder option */ | ||
93 | u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB */ | ||
94 | u8 reserved; /* reserved */ | ||
95 | } __packed; | ||
96 | |||
97 | /* Codec params struture */ | ||
98 | union snd_sst_codec_params { | ||
99 | struct snd_pcm_params pcm_params; | ||
100 | struct snd_mp3_params mp3_params; | ||
101 | struct snd_aac_params aac_params; | ||
102 | struct snd_wma_params wma_params; | ||
103 | } __packed; | ||
104 | |||
105 | /* Address and size info of a frame buffer */ | ||
106 | struct sst_address_info { | ||
107 | u32 addr; /* Address at IA */ | ||
108 | u32 size; /* Size of the buffer */ | ||
109 | }; | ||
110 | |||
111 | struct snd_sst_alloc_params_ext { | ||
112 | struct sst_address_info ring_buf_info[8]; | ||
113 | u8 sg_count; | ||
114 | u8 reserved; | ||
115 | u16 reserved2; | ||
116 | u32 frag_size; /*Number of samples after which period elapsed | ||
117 | message is sent valid only if path = 0*/ | ||
118 | } __packed; | ||
119 | |||
120 | struct snd_sst_stream_params { | ||
121 | union snd_sst_codec_params uc; | ||
122 | } __packed; | ||
123 | |||
124 | struct snd_sst_params { | ||
125 | u32 stream_id; | ||
126 | u8 codec; | ||
127 | u8 ops; | ||
128 | u8 stream_type; | ||
129 | u8 device_type; | ||
130 | struct snd_sst_stream_params sparams; | ||
131 | struct snd_sst_alloc_params_ext aparams; | ||
132 | }; | ||
133 | |||
134 | #endif /* __SST_DSP_H__ */ | ||
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c index d34563b12c3b..a263cbed8624 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/mid-x86/sst_platform.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * sst_platform.c - Intel MID Platform driver | 2 | * sst_platform.c - Intel MID Platform driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Intel Corp | 4 | * Copyright (C) 2010-2012 Intel Corp |
5 | * Author: Vinod Koul <vinod.koul@intel.com> | 5 | * Author: Vinod Koul <vinod.koul@intel.com> |
6 | * Author: Harsha Priya <priya.harsha@intel.com> | 6 | * Author: Harsha Priya <priya.harsha@intel.com> |
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
@@ -32,6 +32,7 @@ | |||
32 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
33 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
34 | #include <sound/soc.h> | 34 | #include <sound/soc.h> |
35 | #include <sound/compress_driver.h> | ||
35 | #include "sst_platform.h" | 36 | #include "sst_platform.h" |
36 | 37 | ||
37 | static struct sst_device *sst; | 38 | static struct sst_device *sst; |
@@ -152,6 +153,16 @@ static struct snd_soc_dai_driver sst_platform_dai[] = { | |||
152 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | 153 | .formats = SNDRV_PCM_FMTBIT_S24_LE, |
153 | }, | 154 | }, |
154 | }, | 155 | }, |
156 | { | ||
157 | .name = "Compress-cpu-dai", | ||
158 | .compress_dai = 1, | ||
159 | .playback = { | ||
160 | .channels_min = SST_STEREO, | ||
161 | .channels_max = SST_STEREO, | ||
162 | .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000, | ||
163 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
164 | }, | ||
165 | }, | ||
155 | }; | 166 | }; |
156 | 167 | ||
157 | /* helper functions */ | 168 | /* helper functions */ |
@@ -463,8 +474,199 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
463 | } | 474 | } |
464 | return retval; | 475 | return retval; |
465 | } | 476 | } |
477 | |||
478 | /* compress stream operations */ | ||
479 | static void sst_compr_fragment_elapsed(void *arg) | ||
480 | { | ||
481 | struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg; | ||
482 | |||
483 | pr_debug("fragment elapsed by driver\n"); | ||
484 | if (cstream) | ||
485 | snd_compr_fragment_elapsed(cstream); | ||
486 | } | ||
487 | |||
488 | static int sst_platform_compr_open(struct snd_compr_stream *cstream) | ||
489 | { | ||
490 | |||
491 | int ret_val = 0; | ||
492 | struct snd_compr_runtime *runtime = cstream->runtime; | ||
493 | struct sst_runtime_stream *stream; | ||
494 | |||
495 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); | ||
496 | if (!stream) | ||
497 | return -ENOMEM; | ||
498 | |||
499 | spin_lock_init(&stream->status_lock); | ||
500 | |||
501 | /* get the sst ops */ | ||
502 | if (!sst || !try_module_get(sst->dev->driver->owner)) { | ||
503 | pr_err("no device available to run\n"); | ||
504 | ret_val = -ENODEV; | ||
505 | goto out_ops; | ||
506 | } | ||
507 | stream->compr_ops = sst->compr_ops; | ||
508 | |||
509 | stream->id = 0; | ||
510 | sst_set_stream_status(stream, SST_PLATFORM_INIT); | ||
511 | runtime->private_data = stream; | ||
512 | return 0; | ||
513 | out_ops: | ||
514 | kfree(stream); | ||
515 | return ret_val; | ||
516 | } | ||
517 | |||
518 | static int sst_platform_compr_free(struct snd_compr_stream *cstream) | ||
519 | { | ||
520 | struct sst_runtime_stream *stream; | ||
521 | int ret_val = 0, str_id; | ||
522 | |||
523 | stream = cstream->runtime->private_data; | ||
524 | /*need to check*/ | ||
525 | str_id = stream->id; | ||
526 | if (str_id) | ||
527 | ret_val = stream->compr_ops->close(str_id); | ||
528 | module_put(sst->dev->driver->owner); | ||
529 | kfree(stream); | ||
530 | pr_debug("%s: %d\n", __func__, ret_val); | ||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, | ||
535 | struct snd_compr_params *params) | ||
536 | { | ||
537 | struct sst_runtime_stream *stream; | ||
538 | int retval; | ||
539 | struct snd_sst_params str_params; | ||
540 | struct sst_compress_cb cb; | ||
541 | |||
542 | stream = cstream->runtime->private_data; | ||
543 | /* construct fw structure for this*/ | ||
544 | memset(&str_params, 0, sizeof(str_params)); | ||
545 | |||
546 | str_params.ops = STREAM_OPS_PLAYBACK; | ||
547 | str_params.stream_type = SST_STREAM_TYPE_MUSIC; | ||
548 | str_params.device_type = SND_SST_DEVICE_COMPRESS; | ||
549 | |||
550 | switch (params->codec.id) { | ||
551 | case SND_AUDIOCODEC_MP3: { | ||
552 | str_params.codec = SST_CODEC_TYPE_MP3; | ||
553 | str_params.sparams.uc.mp3_params.codec = SST_CODEC_TYPE_MP3; | ||
554 | str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in; | ||
555 | str_params.sparams.uc.mp3_params.pcm_wd_sz = 16; | ||
556 | break; | ||
557 | } | ||
558 | |||
559 | case SND_AUDIOCODEC_AAC: { | ||
560 | str_params.codec = SST_CODEC_TYPE_AAC; | ||
561 | str_params.sparams.uc.aac_params.codec = SST_CODEC_TYPE_AAC; | ||
562 | str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in; | ||
563 | str_params.sparams.uc.aac_params.pcm_wd_sz = 16; | ||
564 | if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS) | ||
565 | str_params.sparams.uc.aac_params.bs_format = | ||
566 | AAC_BIT_STREAM_ADTS; | ||
567 | else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW) | ||
568 | str_params.sparams.uc.aac_params.bs_format = | ||
569 | AAC_BIT_STREAM_RAW; | ||
570 | else { | ||
571 | pr_err("Undefined format%d\n", params->codec.format); | ||
572 | return -EINVAL; | ||
573 | } | ||
574 | str_params.sparams.uc.aac_params.externalsr = | ||
575 | params->codec.sample_rate; | ||
576 | break; | ||
577 | } | ||
578 | |||
579 | default: | ||
580 | pr_err("codec not supported, id =%d\n", params->codec.id); | ||
581 | return -EINVAL; | ||
582 | } | ||
583 | |||
584 | str_params.aparams.ring_buf_info[0].addr = | ||
585 | virt_to_phys(cstream->runtime->buffer); | ||
586 | str_params.aparams.ring_buf_info[0].size = | ||
587 | cstream->runtime->buffer_size; | ||
588 | str_params.aparams.sg_count = 1; | ||
589 | str_params.aparams.frag_size = cstream->runtime->fragment_size; | ||
590 | |||
591 | cb.param = cstream; | ||
592 | cb.compr_cb = sst_compr_fragment_elapsed; | ||
593 | |||
594 | retval = stream->compr_ops->open(&str_params, &cb); | ||
595 | if (retval < 0) { | ||
596 | pr_err("stream allocation failed %d\n", retval); | ||
597 | return retval; | ||
598 | } | ||
599 | |||
600 | stream->id = retval; | ||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd) | ||
605 | { | ||
606 | struct sst_runtime_stream *stream = | ||
607 | cstream->runtime->private_data; | ||
608 | |||
609 | return stream->compr_ops->control(cmd, stream->id); | ||
610 | } | ||
611 | |||
612 | static int sst_platform_compr_pointer(struct snd_compr_stream *cstream, | ||
613 | struct snd_compr_tstamp *tstamp) | ||
614 | { | ||
615 | struct sst_runtime_stream *stream; | ||
616 | |||
617 | stream = cstream->runtime->private_data; | ||
618 | stream->compr_ops->tstamp(stream->id, tstamp); | ||
619 | tstamp->byte_offset = tstamp->copied_total % | ||
620 | (u32)cstream->runtime->buffer_size; | ||
621 | pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset); | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static int sst_platform_compr_ack(struct snd_compr_stream *cstream, | ||
626 | size_t bytes) | ||
627 | { | ||
628 | struct sst_runtime_stream *stream; | ||
629 | |||
630 | stream = cstream->runtime->private_data; | ||
631 | stream->compr_ops->ack(stream->id, (unsigned long)bytes); | ||
632 | stream->bytes_written += bytes; | ||
633 | |||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream, | ||
638 | struct snd_compr_caps *caps) | ||
639 | { | ||
640 | struct sst_runtime_stream *stream = | ||
641 | cstream->runtime->private_data; | ||
642 | |||
643 | return stream->compr_ops->get_caps(caps); | ||
644 | } | ||
645 | |||
646 | static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream, | ||
647 | struct snd_compr_codec_caps *codec) | ||
648 | { | ||
649 | struct sst_runtime_stream *stream = | ||
650 | cstream->runtime->private_data; | ||
651 | |||
652 | return stream->compr_ops->get_codec_caps(codec); | ||
653 | } | ||
654 | |||
655 | static struct snd_compr_ops sst_platform_compr_ops = { | ||
656 | |||
657 | .open = sst_platform_compr_open, | ||
658 | .free = sst_platform_compr_free, | ||
659 | .set_params = sst_platform_compr_set_params, | ||
660 | .trigger = sst_platform_compr_trigger, | ||
661 | .pointer = sst_platform_compr_pointer, | ||
662 | .ack = sst_platform_compr_ack, | ||
663 | .get_caps = sst_platform_compr_get_caps, | ||
664 | .get_codec_caps = sst_platform_compr_get_codec_caps, | ||
665 | }; | ||
666 | |||
466 | static struct snd_soc_platform_driver sst_soc_platform_drv = { | 667 | static struct snd_soc_platform_driver sst_soc_platform_drv = { |
467 | .ops = &sst_platform_ops, | 668 | .ops = &sst_platform_ops, |
669 | .compr_ops = &sst_platform_compr_ops, | ||
468 | .pcm_new = sst_pcm_new, | 670 | .pcm_new = sst_pcm_new, |
469 | .pcm_free = sst_pcm_free, | 671 | .pcm_free = sst_pcm_free, |
470 | }; | 672 | }; |
diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/mid-x86/sst_platform.h index f04f4f72daa0..d61c5d514ffa 100644 --- a/sound/soc/mid-x86/sst_platform.h +++ b/sound/soc/mid-x86/sst_platform.h | |||
@@ -27,6 +27,8 @@ | |||
27 | #ifndef __SST_PLATFORMDRV_H__ | 27 | #ifndef __SST_PLATFORMDRV_H__ |
28 | #define __SST_PLATFORMDRV_H__ | 28 | #define __SST_PLATFORMDRV_H__ |
29 | 29 | ||
30 | #include "sst_dsp.h" | ||
31 | |||
30 | #define SST_MONO 1 | 32 | #define SST_MONO 1 |
31 | #define SST_STEREO 2 | 33 | #define SST_STEREO 2 |
32 | #define SST_MAX_CAP 5 | 34 | #define SST_MAX_CAP 5 |
@@ -42,7 +44,6 @@ | |||
42 | #define SST_MIN_PERIODS 2 | 44 | #define SST_MIN_PERIODS 2 |
43 | #define SST_MAX_PERIODS (1024*2) | 45 | #define SST_MAX_PERIODS (1024*2) |
44 | #define SST_FIFO_SIZE 0 | 46 | #define SST_FIFO_SIZE 0 |
45 | #define SST_CODEC_TYPE_PCM 1 | ||
46 | 47 | ||
47 | struct pcm_stream_info { | 48 | struct pcm_stream_info { |
48 | int str_id; | 49 | int str_id; |
@@ -83,6 +84,7 @@ enum sst_audio_device_type { | |||
83 | SND_SST_DEVICE_VIBRA, | 84 | SND_SST_DEVICE_VIBRA, |
84 | SND_SST_DEVICE_HAPTIC, | 85 | SND_SST_DEVICE_HAPTIC, |
85 | SND_SST_DEVICE_CAPTURE, | 86 | SND_SST_DEVICE_CAPTURE, |
87 | SND_SST_DEVICE_COMPRESS, | ||
86 | }; | 88 | }; |
87 | 89 | ||
88 | /* PCM Parameters */ | 90 | /* PCM Parameters */ |
@@ -107,6 +109,24 @@ struct sst_stream_params { | |||
107 | struct sst_pcm_params sparams; | 109 | struct sst_pcm_params sparams; |
108 | }; | 110 | }; |
109 | 111 | ||
112 | struct sst_compress_cb { | ||
113 | void *param; | ||
114 | void (*compr_cb)(void *param); | ||
115 | }; | ||
116 | |||
117 | struct compress_sst_ops { | ||
118 | const char *name; | ||
119 | int (*open) (struct snd_sst_params *str_params, | ||
120 | struct sst_compress_cb *cb); | ||
121 | int (*control) (unsigned int cmd, unsigned int str_id); | ||
122 | int (*tstamp) (unsigned int str_id, struct snd_compr_tstamp *tstamp); | ||
123 | int (*ack) (unsigned int str_id, unsigned long bytes); | ||
124 | int (*close) (unsigned int str_id); | ||
125 | int (*get_caps) (struct snd_compr_caps *caps); | ||
126 | int (*get_codec_caps) (struct snd_compr_codec_caps *codec); | ||
127 | |||
128 | }; | ||
129 | |||
110 | struct sst_ops { | 130 | struct sst_ops { |
111 | int (*open) (struct sst_stream_params *str_param); | 131 | int (*open) (struct sst_stream_params *str_param); |
112 | int (*device_control) (int cmd, void *arg); | 132 | int (*device_control) (int cmd, void *arg); |
@@ -115,8 +135,11 @@ struct sst_ops { | |||
115 | 135 | ||
116 | struct sst_runtime_stream { | 136 | struct sst_runtime_stream { |
117 | int stream_status; | 137 | int stream_status; |
138 | unsigned int id; | ||
139 | size_t bytes_written; | ||
118 | struct pcm_stream_info stream_info; | 140 | struct pcm_stream_info stream_info; |
119 | struct sst_ops *ops; | 141 | struct sst_ops *ops; |
142 | struct compress_sst_ops *compr_ops; | ||
120 | spinlock_t status_lock; | 143 | spinlock_t status_lock; |
121 | }; | 144 | }; |
122 | 145 | ||
@@ -124,6 +147,7 @@ struct sst_device { | |||
124 | char *name; | 147 | char *name; |
125 | struct device *dev; | 148 | struct device *dev; |
126 | struct sst_ops *ops; | 149 | struct sst_ops *ops; |
150 | struct compress_sst_ops *compr_ops; | ||
127 | }; | 151 | }; |
128 | 152 | ||
129 | int sst_register_dsp(struct sst_device *sst); | 153 | int sst_register_dsp(struct sst_device *sst); |
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index b3030718c228..aa037b292f3d 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
@@ -704,7 +704,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
704 | return ret; | 704 | return ret; |
705 | } | 705 | } |
706 | 706 | ||
707 | saif->clk = clk_get(&pdev->dev, NULL); | 707 | saif->clk = devm_clk_get(&pdev->dev, NULL); |
708 | if (IS_ERR(saif->clk)) { | 708 | if (IS_ERR(saif->clk)) { |
709 | ret = PTR_ERR(saif->clk); | 709 | ret = PTR_ERR(saif->clk); |
710 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", | 710 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", |
@@ -717,8 +717,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
717 | saif->base = devm_request_and_ioremap(&pdev->dev, iores); | 717 | saif->base = devm_request_and_ioremap(&pdev->dev, iores); |
718 | if (!saif->base) { | 718 | if (!saif->base) { |
719 | dev_err(&pdev->dev, "ioremap failed\n"); | 719 | dev_err(&pdev->dev, "ioremap failed\n"); |
720 | ret = -ENODEV; | 720 | return -ENODEV; |
721 | goto failed_get_resource; | ||
722 | } | 721 | } |
723 | 722 | ||
724 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 723 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
@@ -731,7 +730,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
731 | &saif->dma_param.chan_num); | 730 | &saif->dma_param.chan_num); |
732 | if (ret) { | 731 | if (ret) { |
733 | dev_err(&pdev->dev, "failed to get dma channel\n"); | 732 | dev_err(&pdev->dev, "failed to get dma channel\n"); |
734 | goto failed_get_resource; | 733 | return ret; |
735 | } | 734 | } |
736 | } else { | 735 | } else { |
737 | saif->dma_param.chan_num = dmares->start; | 736 | saif->dma_param.chan_num = dmares->start; |
@@ -742,7 +741,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
742 | ret = saif->irq; | 741 | ret = saif->irq; |
743 | dev_err(&pdev->dev, "failed to get irq resource: %d\n", | 742 | dev_err(&pdev->dev, "failed to get irq resource: %d\n", |
744 | ret); | 743 | ret); |
745 | goto failed_get_resource; | 744 | return ret; |
746 | } | 745 | } |
747 | 746 | ||
748 | saif->dev = &pdev->dev; | 747 | saif->dev = &pdev->dev; |
@@ -750,7 +749,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
750 | "mxs-saif", saif); | 749 | "mxs-saif", saif); |
751 | if (ret) { | 750 | if (ret) { |
752 | dev_err(&pdev->dev, "failed to request irq\n"); | 751 | dev_err(&pdev->dev, "failed to request irq\n"); |
753 | goto failed_get_resource; | 752 | return ret; |
754 | } | 753 | } |
755 | 754 | ||
756 | saif->dma_param.chan_irq = platform_get_irq(pdev, 1); | 755 | saif->dma_param.chan_irq = platform_get_irq(pdev, 1); |
@@ -758,7 +757,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
758 | ret = saif->dma_param.chan_irq; | 757 | ret = saif->dma_param.chan_irq; |
759 | dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", | 758 | dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", |
760 | ret); | 759 | ret); |
761 | goto failed_get_resource; | 760 | return ret; |
762 | } | 761 | } |
763 | 762 | ||
764 | platform_set_drvdata(pdev, saif); | 763 | platform_set_drvdata(pdev, saif); |
@@ -766,7 +765,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
766 | ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); | 765 | ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); |
767 | if (ret) { | 766 | if (ret) { |
768 | dev_err(&pdev->dev, "register DAI failed\n"); | 767 | dev_err(&pdev->dev, "register DAI failed\n"); |
769 | goto failed_get_resource; | 768 | return ret; |
770 | } | 769 | } |
771 | 770 | ||
772 | ret = mxs_pcm_platform_register(&pdev->dev); | 771 | ret = mxs_pcm_platform_register(&pdev->dev); |
@@ -779,19 +778,14 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
779 | 778 | ||
780 | failed_pdev_alloc: | 779 | failed_pdev_alloc: |
781 | snd_soc_unregister_dai(&pdev->dev); | 780 | snd_soc_unregister_dai(&pdev->dev); |
782 | failed_get_resource: | ||
783 | clk_put(saif->clk); | ||
784 | 781 | ||
785 | return ret; | 782 | return ret; |
786 | } | 783 | } |
787 | 784 | ||
788 | static int __devexit mxs_saif_remove(struct platform_device *pdev) | 785 | static int __devexit mxs_saif_remove(struct platform_device *pdev) |
789 | { | 786 | { |
790 | struct mxs_saif *saif = platform_get_drvdata(pdev); | ||
791 | |||
792 | mxs_pcm_platform_unregister(&pdev->dev); | 787 | mxs_pcm_platform_unregister(&pdev->dev); |
793 | snd_soc_unregister_dai(&pdev->dev); | 788 | snd_soc_unregister_dai(&pdev->dev); |
794 | clk_put(saif->clk); | ||
795 | 789 | ||
796 | return 0; | 790 | return 0; |
797 | } | 791 | } |
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 57a2fa751085..7048137f9a33 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config SND_OMAP_SOC | 1 | config SND_OMAP_SOC |
2 | tristate "SoC Audio for the Texas Instruments OMAP chips" | 2 | tristate "SoC Audio for the Texas Instruments OMAP chips" |
3 | depends on ARCH_OMAP | 3 | depends on ARCH_OMAP && DMA_OMAP |
4 | select SND_SOC_DMAENGINE_PCM | ||
4 | 5 | ||
5 | config SND_OMAP_SOC_DMIC | 6 | config SND_OMAP_SOC_DMIC |
6 | tristate | 7 | tristate |
@@ -60,23 +61,6 @@ config SND_OMAP_SOC_OSK5912 | |||
60 | help | 61 | help |
61 | Say Y if you want to add support for SoC audio on osk5912. | 62 | Say Y if you want to add support for SoC audio on osk5912. |
62 | 63 | ||
63 | config SND_OMAP_SOC_OVERO | ||
64 | tristate "SoC Audio support for Gumstix Overo and CompuLab CM-T35" | ||
65 | depends on TWL4030_CORE && SND_OMAP_SOC && (MACH_OVERO || MACH_CM_T35) | ||
66 | select SND_OMAP_SOC_MCBSP | ||
67 | select SND_SOC_TWL4030 | ||
68 | help | ||
69 | Say Y if you want to add support for SoC audio on the | ||
70 | Gumstix Overo or CompuLab CM-T35 | ||
71 | |||
72 | config SND_OMAP_SOC_OMAP3EVM | ||
73 | tristate "SoC Audio support for OMAP3EVM board" | ||
74 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3EVM | ||
75 | select SND_OMAP_SOC_MCBSP | ||
76 | select SND_SOC_TWL4030 | ||
77 | help | ||
78 | Say Y if you want to add support for SoC audio on the omap3evm board. | ||
79 | |||
80 | config SND_OMAP_SOC_AM3517EVM | 64 | config SND_OMAP_SOC_AM3517EVM |
81 | tristate "SoC Audio support for OMAP3517 / AM3517 EVM" | 65 | tristate "SoC Audio support for OMAP3517 / AM3517 EVM" |
82 | depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C | 66 | depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C |
@@ -95,6 +79,19 @@ config SND_OMAP_SOC_SDP3430 | |||
95 | Say Y if you want to add support for SoC audio on Texas Instruments | 79 | Say Y if you want to add support for SoC audio on Texas Instruments |
96 | SDP3430. | 80 | SDP3430. |
97 | 81 | ||
82 | config SND_OMAP_SOC_OMAP_TWL4030 | ||
83 | tristate "SoC Audio support for TI SoC based boards with twl4030 codec" | ||
84 | depends on TWL4030_CORE && SND_OMAP_SOC | ||
85 | select SND_OMAP_SOC_MCBSP | ||
86 | select SND_SOC_TWL4030 | ||
87 | help | ||
88 | Say Y if you want to add support for SoC audio on TI SoC based boards | ||
89 | using twl4030 as c codec. This driver currently supports: | ||
90 | - Beagleboard or Devkit8000 | ||
91 | - Gumstix Overo or CompuLab CM-T35/CM-T3730 | ||
92 | - IGEP v2 | ||
93 | - OMAP3EVM | ||
94 | |||
98 | config SND_OMAP_SOC_OMAP_ABE_TWL6040 | 95 | config SND_OMAP_SOC_OMAP_ABE_TWL6040 |
99 | tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" | 96 | tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" |
100 | depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4 | 97 | depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4 |
@@ -127,16 +124,6 @@ config SND_OMAP_SOC_OMAP3_PANDORA | |||
127 | help | 124 | help |
128 | Say Y if you want to add support for SoC audio on the OMAP3 Pandora. | 125 | Say Y if you want to add support for SoC audio on the OMAP3 Pandora. |
129 | 126 | ||
130 | config SND_OMAP_SOC_OMAP3_BEAGLE | ||
131 | tristate "SoC Audio support for OMAP3 Beagle and Devkit8000" | ||
132 | depends on TWL4030_CORE && SND_OMAP_SOC | ||
133 | depends on (MACH_OMAP3_BEAGLE || MACH_DEVKIT8000) | ||
134 | select SND_OMAP_SOC_MCBSP | ||
135 | select SND_SOC_TWL4030 | ||
136 | help | ||
137 | Say Y if you want to add support for SoC audio on the Beagleboard or | ||
138 | the clone Devkit8000. | ||
139 | |||
140 | config SND_OMAP_SOC_ZOOM2 | 127 | config SND_OMAP_SOC_ZOOM2 |
141 | tristate "SoC Audio support for Zoom2" | 128 | tristate "SoC Audio support for Zoom2" |
142 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2 | 129 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2 |
@@ -144,11 +131,3 @@ config SND_OMAP_SOC_ZOOM2 | |||
144 | select SND_SOC_TWL4030 | 131 | select SND_SOC_TWL4030 |
145 | help | 132 | help |
146 | Say Y if you want to add support for Soc audio on Zoom2 board. | 133 | Say Y if you want to add support for Soc audio on Zoom2 board. |
147 | |||
148 | config SND_OMAP_SOC_IGEP0020 | ||
149 | tristate "SoC Audio support for IGEP v2" | ||
150 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_IGEP0020 | ||
151 | select SND_OMAP_SOC_MCBSP | ||
152 | select SND_SOC_TWL4030 | ||
153 | help | ||
154 | Say Y if you want to add support for Soc audio on IGEP v2 board. | ||
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 0e14dd322565..19637e55ea48 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile | |||
@@ -16,29 +16,23 @@ snd-soc-n810-objs := n810.o | |||
16 | snd-soc-rx51-objs := rx51.o | 16 | snd-soc-rx51-objs := rx51.o |
17 | snd-soc-ams-delta-objs := ams-delta.o | 17 | snd-soc-ams-delta-objs := ams-delta.o |
18 | snd-soc-osk5912-objs := osk5912.o | 18 | snd-soc-osk5912-objs := osk5912.o |
19 | snd-soc-overo-objs := overo.o | ||
20 | snd-soc-omap3evm-objs := omap3evm.o | ||
21 | snd-soc-am3517evm-objs := am3517evm.o | 19 | snd-soc-am3517evm-objs := am3517evm.o |
22 | snd-soc-sdp3430-objs := sdp3430.o | 20 | snd-soc-sdp3430-objs := sdp3430.o |
23 | snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o | 21 | snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o |
22 | snd-soc-omap-twl4030-objs := omap-twl4030.o | ||
24 | snd-soc-omap3pandora-objs := omap3pandora.o | 23 | snd-soc-omap3pandora-objs := omap3pandora.o |
25 | snd-soc-omap3beagle-objs := omap3beagle.o | ||
26 | snd-soc-zoom2-objs := zoom2.o | 24 | snd-soc-zoom2-objs := zoom2.o |
27 | snd-soc-igep0020-objs := igep0020.o | ||
28 | snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o | 25 | snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o |
29 | 26 | ||
30 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o | 27 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o |
31 | obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o | 28 | obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o |
32 | obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o | 29 | obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o |
33 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o | 30 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o |
34 | obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o | ||
35 | obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o | 31 | obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o |
36 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o | ||
37 | obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o | 32 | obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o |
38 | obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o | 33 | obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o |
39 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o | 34 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o |
35 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o | ||
40 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o | 36 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o |
41 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o | ||
42 | obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o | 37 | obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o |
43 | obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o | ||
44 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o | 38 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o |
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index df65f98211ec..77a87012977c 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c | |||
@@ -41,32 +41,15 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, | |||
41 | { | 41 | { |
42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
44 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
45 | int ret; | 44 | int ret; |
46 | 45 | ||
47 | /* Set the codec system clock for DAC and ADC */ | 46 | /* Set the codec system clock for DAC and ADC */ |
48 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, | 47 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, |
49 | CODEC_CLOCK, SND_SOC_CLOCK_IN); | 48 | CODEC_CLOCK, SND_SOC_CLOCK_IN); |
50 | if (ret < 0) { | 49 | if (ret < 0) |
51 | printk(KERN_ERR "can't set codec system clock\n"); | 50 | printk(KERN_ERR "can't set codec system clock\n"); |
52 | return ret; | ||
53 | } | ||
54 | |||
55 | ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_CLKR_SRC_CLKX, 0, | ||
56 | SND_SOC_CLOCK_IN); | ||
57 | if (ret < 0) { | ||
58 | printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_CLKR_SRC_CLKX\n"); | ||
59 | return ret; | ||
60 | } | ||
61 | 51 | ||
62 | ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, | 52 | return ret; |
63 | SND_SOC_CLOCK_IN); | ||
64 | if (ret < 0) { | ||
65 | printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n"); | ||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | return 0; | ||
70 | } | 53 | } |
71 | 54 | ||
72 | static struct snd_soc_ops am3517evm_ops = { | 55 | static struct snd_soc_ops am3517evm_ops = { |
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c deleted file mode 100644 index e8357819175b..000000000000 --- a/sound/soc/omap/igep0020.c +++ /dev/null | |||
@@ -1,120 +0,0 @@ | |||
1 | /* | ||
2 | * igep0020.c -- SoC audio for IGEP v2 | ||
3 | * | ||
4 | * Based on sound/soc/omap/overo.c by Steve Sakoman | ||
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/clk.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <sound/core.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/soc.h> | ||
28 | |||
29 | #include <asm/mach-types.h> | ||
30 | #include <mach/hardware.h> | ||
31 | #include <mach/gpio.h> | ||
32 | #include <plat/mcbsp.h> | ||
33 | |||
34 | #include "omap-mcbsp.h" | ||
35 | #include "omap-pcm.h" | ||
36 | |||
37 | static int igep2_hw_params(struct snd_pcm_substream *substream, | ||
38 | struct snd_pcm_hw_params *params) | ||
39 | { | ||
40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
42 | int ret; | ||
43 | |||
44 | /* Set the codec system clock for DAC and ADC */ | ||
45 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
46 | SND_SOC_CLOCK_IN); | ||
47 | if (ret < 0) { | ||
48 | printk(KERN_ERR "can't set codec system clock\n"); | ||
49 | return ret; | ||
50 | } | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static struct snd_soc_ops igep2_ops = { | ||
56 | .hw_params = igep2_hw_params, | ||
57 | }; | ||
58 | |||
59 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
60 | static struct snd_soc_dai_link igep2_dai = { | ||
61 | .name = "TWL4030", | ||
62 | .stream_name = "TWL4030", | ||
63 | .cpu_dai_name = "omap-mcbsp.2", | ||
64 | .codec_dai_name = "twl4030-hifi", | ||
65 | .platform_name = "omap-pcm-audio", | ||
66 | .codec_name = "twl4030-codec", | ||
67 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
68 | SND_SOC_DAIFMT_CBM_CFM, | ||
69 | .ops = &igep2_ops, | ||
70 | }; | ||
71 | |||
72 | /* Audio machine driver */ | ||
73 | static struct snd_soc_card snd_soc_card_igep2 = { | ||
74 | .name = "igep2", | ||
75 | .owner = THIS_MODULE, | ||
76 | .dai_link = &igep2_dai, | ||
77 | .num_links = 1, | ||
78 | }; | ||
79 | |||
80 | static struct platform_device *igep2_snd_device; | ||
81 | |||
82 | static int __init igep2_soc_init(void) | ||
83 | { | ||
84 | int ret; | ||
85 | |||
86 | if (!machine_is_igep0020()) | ||
87 | return -ENODEV; | ||
88 | printk(KERN_INFO "IGEP v2 SoC init\n"); | ||
89 | |||
90 | igep2_snd_device = platform_device_alloc("soc-audio", -1); | ||
91 | if (!igep2_snd_device) { | ||
92 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
93 | return -ENOMEM; | ||
94 | } | ||
95 | |||
96 | platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2); | ||
97 | |||
98 | ret = platform_device_add(igep2_snd_device); | ||
99 | if (ret) | ||
100 | goto err1; | ||
101 | |||
102 | return 0; | ||
103 | |||
104 | err1: | ||
105 | printk(KERN_ERR "Unable to add platform device\n"); | ||
106 | platform_device_put(igep2_snd_device); | ||
107 | |||
108 | return ret; | ||
109 | } | ||
110 | module_init(igep2_soc_init); | ||
111 | |||
112 | static void __exit igep2_soc_exit(void) | ||
113 | { | ||
114 | platform_device_unregister(igep2_snd_device); | ||
115 | } | ||
116 | module_exit(igep2_soc_exit); | ||
117 | |||
118 | MODULE_AUTHOR("Enric Balletbo i Serra <eballetbo@iseebcn.com>"); | ||
119 | MODULE_DESCRIPTION("ALSA SoC IGEP v2"); | ||
120 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index d33c48baaf71..bc06175e6367 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/pm_runtime.h> | ||
27 | 28 | ||
28 | #include <plat/mcbsp.h> | 29 | #include <plat/mcbsp.h> |
29 | 30 | ||
@@ -726,50 +727,39 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx) | |||
726 | 727 | ||
727 | int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) | 728 | int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) |
728 | { | 729 | { |
730 | struct clk *fck_src; | ||
729 | const char *src; | 731 | const char *src; |
732 | int r; | ||
730 | 733 | ||
731 | if (fck_src_id == MCBSP_CLKS_PAD_SRC) | 734 | if (fck_src_id == MCBSP_CLKS_PAD_SRC) |
732 | src = "clks_ext"; | 735 | src = "pad_fck"; |
733 | else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) | 736 | else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) |
734 | src = "clks_fclk"; | 737 | src = "prcm_fck"; |
735 | else | 738 | else |
736 | return -EINVAL; | 739 | return -EINVAL; |
737 | 740 | ||
738 | if (mcbsp->pdata->set_clk_src) | 741 | fck_src = clk_get(mcbsp->dev, src); |
739 | return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src); | 742 | if (IS_ERR(fck_src)) { |
740 | else | 743 | dev_err(mcbsp->dev, "CLKS: could not clk_get() %s\n", src); |
741 | return -EINVAL; | 744 | return -EINVAL; |
742 | } | 745 | } |
743 | |||
744 | int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) | ||
745 | { | ||
746 | const char *signal, *src; | ||
747 | 746 | ||
748 | if (!mcbsp->pdata->mux_signal) | 747 | pm_runtime_put_sync(mcbsp->dev); |
749 | return -EINVAL; | ||
750 | 748 | ||
751 | switch (mux) { | 749 | r = clk_set_parent(mcbsp->fclk, fck_src); |
752 | case CLKR_SRC_CLKR: | 750 | if (r) { |
753 | signal = "clkr"; | 751 | dev_err(mcbsp->dev, "CLKS: could not clk_set_parent() to %s\n", |
754 | src = "clkr"; | 752 | src); |
755 | break; | 753 | clk_put(fck_src); |
756 | case CLKR_SRC_CLKX: | 754 | return r; |
757 | signal = "clkr"; | ||
758 | src = "clkx"; | ||
759 | break; | ||
760 | case FSR_SRC_FSR: | ||
761 | signal = "fsr"; | ||
762 | src = "fsr"; | ||
763 | break; | ||
764 | case FSR_SRC_FSX: | ||
765 | signal = "fsr"; | ||
766 | src = "fsx"; | ||
767 | break; | ||
768 | default: | ||
769 | return -EINVAL; | ||
770 | } | 755 | } |
771 | 756 | ||
772 | return mcbsp->pdata->mux_signal(mcbsp->dev, signal, src); | 757 | pm_runtime_get_sync(mcbsp->dev); |
758 | |||
759 | clk_put(fck_src); | ||
760 | |||
761 | return 0; | ||
762 | |||
773 | } | 763 | } |
774 | 764 | ||
775 | #define max_thres(m) (mcbsp->pdata->buffer_size) | 765 | #define max_thres(m) (mcbsp->pdata->buffer_size) |
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h index 262a6152111f..49a67259ce5a 100644 --- a/sound/soc/omap/mcbsp.h +++ b/sound/soc/omap/mcbsp.h | |||
@@ -334,9 +334,6 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx); | |||
334 | /* McBSP functional clock source changing function */ | 334 | /* McBSP functional clock source changing function */ |
335 | int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id); | 335 | int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id); |
336 | 336 | ||
337 | /* McBSP signal muxing API */ | ||
338 | int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux); | ||
339 | |||
340 | /* Sidetone specific API */ | 337 | /* Sidetone specific API */ |
341 | int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain); | 338 | int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain); |
342 | int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain); | 339 | int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain); |
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index 9d93793d3077..be525dfe9faa 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/mfd/twl6040.h> | 25 | #include <linux/mfd/twl6040.h> |
26 | #include <linux/platform_data/omap-abe-twl6040.h> | 26 | #include <linux/platform_data/omap-abe-twl6040.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/of.h> | ||
28 | 29 | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
@@ -43,6 +44,8 @@ | |||
43 | struct abe_twl6040 { | 44 | struct abe_twl6040 { |
44 | int jack_detection; /* board can detect jack events */ | 45 | int jack_detection; /* board can detect jack events */ |
45 | int mclk_freq; /* MCLK frequency speed for twl6040 */ | 46 | int mclk_freq; /* MCLK frequency speed for twl6040 */ |
47 | |||
48 | struct platform_device *dmic_codec_dev; | ||
46 | }; | 49 | }; |
47 | 50 | ||
48 | static int omap_abe_hw_params(struct snd_pcm_substream *substream, | 51 | static int omap_abe_hw_params(struct snd_pcm_substream *substream, |
@@ -185,17 +188,6 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) | |||
185 | int hs_trim; | 188 | int hs_trim; |
186 | int ret = 0; | 189 | int ret = 0; |
187 | 190 | ||
188 | /* Disable not connected paths if not used */ | ||
189 | twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); | ||
190 | twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); | ||
191 | twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); | ||
192 | twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); | ||
193 | twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); | ||
194 | twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); | ||
195 | twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); | ||
196 | twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); | ||
197 | twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); | ||
198 | |||
199 | /* | 191 | /* |
200 | * Configure McPDM offset cancellation based on the HSOTRIM value from | 192 | * Configure McPDM offset cancellation based on the HSOTRIM value from |
201 | * twl6040. | 193 | * twl6040. |
@@ -216,6 +208,24 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) | |||
216 | twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); | 208 | twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); |
217 | } | 209 | } |
218 | 210 | ||
211 | /* | ||
212 | * NULL pdata means we booted with DT. In this case the routing is | ||
213 | * provided and the card is fully routed, no need to mark pins. | ||
214 | */ | ||
215 | if (!pdata) | ||
216 | return ret; | ||
217 | |||
218 | /* Disable not connected paths if not used */ | ||
219 | twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); | ||
220 | twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); | ||
221 | twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); | ||
222 | twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); | ||
223 | twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); | ||
224 | twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); | ||
225 | twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); | ||
226 | twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); | ||
227 | twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); | ||
228 | |||
219 | return ret; | 229 | return ret; |
220 | } | 230 | } |
221 | 231 | ||
@@ -270,52 +280,116 @@ static struct snd_soc_card omap_abe_card = { | |||
270 | static __devinit int omap_abe_probe(struct platform_device *pdev) | 280 | static __devinit int omap_abe_probe(struct platform_device *pdev) |
271 | { | 281 | { |
272 | struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); | 282 | struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); |
283 | struct device_node *node = pdev->dev.of_node; | ||
273 | struct snd_soc_card *card = &omap_abe_card; | 284 | struct snd_soc_card *card = &omap_abe_card; |
274 | struct abe_twl6040 *priv; | 285 | struct abe_twl6040 *priv; |
275 | int num_links = 0; | 286 | int num_links = 0; |
276 | int ret; | 287 | int ret = 0; |
277 | 288 | ||
278 | card->dev = &pdev->dev; | 289 | card->dev = &pdev->dev; |
279 | 290 | ||
280 | if (!pdata) { | ||
281 | dev_err(&pdev->dev, "Missing pdata\n"); | ||
282 | return -ENODEV; | ||
283 | } | ||
284 | |||
285 | priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); | 291 | priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); |
286 | if (priv == NULL) | 292 | if (priv == NULL) |
287 | return -ENOMEM; | 293 | return -ENOMEM; |
288 | 294 | ||
289 | if (pdata->card_name) { | 295 | priv->dmic_codec_dev = ERR_PTR(-EINVAL); |
290 | card->name = pdata->card_name; | 296 | |
297 | if (node) { | ||
298 | struct device_node *dai_node; | ||
299 | |||
300 | if (snd_soc_of_parse_card_name(card, "ti,model")) { | ||
301 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
302 | return -ENODEV; | ||
303 | } | ||
304 | |||
305 | ret = snd_soc_of_parse_audio_routing(card, | ||
306 | "ti,audio-routing"); | ||
307 | if (ret) { | ||
308 | dev_err(&pdev->dev, | ||
309 | "Error while parsing DAPM routing\n"); | ||
310 | return ret; | ||
311 | } | ||
312 | |||
313 | dai_node = of_parse_phandle(node, "ti,mcpdm", 0); | ||
314 | if (!dai_node) { | ||
315 | dev_err(&pdev->dev, "McPDM node is not provided\n"); | ||
316 | return -EINVAL; | ||
317 | } | ||
318 | abe_twl6040_dai_links[0].cpu_dai_name = NULL; | ||
319 | abe_twl6040_dai_links[0].cpu_of_node = dai_node; | ||
320 | |||
321 | dai_node = of_parse_phandle(node, "ti,dmic", 0); | ||
322 | if (dai_node) { | ||
323 | num_links = 2; | ||
324 | abe_twl6040_dai_links[1].cpu_dai_name = NULL; | ||
325 | abe_twl6040_dai_links[1].cpu_of_node = dai_node; | ||
326 | |||
327 | priv->dmic_codec_dev = platform_device_register_simple( | ||
328 | "dmic-codec", -1, NULL, 0); | ||
329 | if (IS_ERR(priv->dmic_codec_dev)) { | ||
330 | dev_err(&pdev->dev, | ||
331 | "Can't instantiate dmic-codec\n"); | ||
332 | return PTR_ERR(priv->dmic_codec_dev); | ||
333 | } | ||
334 | } else { | ||
335 | num_links = 1; | ||
336 | } | ||
337 | |||
338 | of_property_read_u32(node, "ti,jack-detection", | ||
339 | &priv->jack_detection); | ||
340 | of_property_read_u32(node, "ti,mclk-freq", | ||
341 | &priv->mclk_freq); | ||
342 | if (!priv->mclk_freq) { | ||
343 | dev_err(&pdev->dev, "MCLK frequency not provided\n"); | ||
344 | ret = -EINVAL; | ||
345 | goto err_unregister; | ||
346 | } | ||
347 | |||
348 | omap_abe_card.fully_routed = 1; | ||
349 | } else if (pdata) { | ||
350 | if (pdata->card_name) { | ||
351 | card->name = pdata->card_name; | ||
352 | } else { | ||
353 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
354 | return -ENODEV; | ||
355 | } | ||
356 | |||
357 | if (pdata->has_dmic) | ||
358 | num_links = 2; | ||
359 | else | ||
360 | num_links = 1; | ||
361 | |||
362 | priv->jack_detection = pdata->jack_detection; | ||
363 | priv->mclk_freq = pdata->mclk_freq; | ||
291 | } else { | 364 | } else { |
292 | dev_err(&pdev->dev, "Card name is not provided\n"); | 365 | dev_err(&pdev->dev, "Missing pdata\n"); |
293 | return -ENODEV; | 366 | return -ENODEV; |
294 | } | 367 | } |
295 | 368 | ||
296 | priv->jack_detection = pdata->jack_detection; | ||
297 | priv->mclk_freq = pdata->mclk_freq; | ||
298 | |||
299 | 369 | ||
300 | if (!priv->mclk_freq) { | 370 | if (!priv->mclk_freq) { |
301 | dev_err(&pdev->dev, "MCLK frequency missing\n"); | 371 | dev_err(&pdev->dev, "MCLK frequency missing\n"); |
302 | return -ENODEV; | 372 | ret = -ENODEV; |
373 | goto err_unregister; | ||
303 | } | 374 | } |
304 | 375 | ||
305 | if (pdata->has_dmic) | ||
306 | num_links = 2; | ||
307 | else | ||
308 | num_links = 1; | ||
309 | |||
310 | card->dai_link = abe_twl6040_dai_links; | 376 | card->dai_link = abe_twl6040_dai_links; |
311 | card->num_links = num_links; | 377 | card->num_links = num_links; |
312 | 378 | ||
313 | snd_soc_card_set_drvdata(card, priv); | 379 | snd_soc_card_set_drvdata(card, priv); |
314 | 380 | ||
315 | ret = snd_soc_register_card(card); | 381 | ret = snd_soc_register_card(card); |
316 | if (ret) | 382 | if (ret) { |
317 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | 383 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", |
318 | ret); | 384 | ret); |
385 | goto err_unregister; | ||
386 | } | ||
387 | |||
388 | return 0; | ||
389 | |||
390 | err_unregister: | ||
391 | if (!IS_ERR(priv->dmic_codec_dev)) | ||
392 | platform_device_unregister(priv->dmic_codec_dev); | ||
319 | 393 | ||
320 | return ret; | 394 | return ret; |
321 | } | 395 | } |
@@ -323,17 +397,28 @@ static __devinit int omap_abe_probe(struct platform_device *pdev) | |||
323 | static int __devexit omap_abe_remove(struct platform_device *pdev) | 397 | static int __devexit omap_abe_remove(struct platform_device *pdev) |
324 | { | 398 | { |
325 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 399 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
400 | struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); | ||
326 | 401 | ||
327 | snd_soc_unregister_card(card); | 402 | snd_soc_unregister_card(card); |
328 | 403 | ||
404 | if (!IS_ERR(priv->dmic_codec_dev)) | ||
405 | platform_device_unregister(priv->dmic_codec_dev); | ||
406 | |||
329 | return 0; | 407 | return 0; |
330 | } | 408 | } |
331 | 409 | ||
410 | static const struct of_device_id omap_abe_of_match[] = { | ||
411 | {.compatible = "ti,abe-twl6040", }, | ||
412 | { }, | ||
413 | }; | ||
414 | MODULE_DEVICE_TABLE(of, omap_abe_of_match); | ||
415 | |||
332 | static struct platform_driver omap_abe_driver = { | 416 | static struct platform_driver omap_abe_driver = { |
333 | .driver = { | 417 | .driver = { |
334 | .name = "omap-abe-twl6040", | 418 | .name = "omap-abe-twl6040", |
335 | .owner = THIS_MODULE, | 419 | .owner = THIS_MODULE, |
336 | .pm = &snd_soc_pm_ops, | 420 | .pm = &snd_soc_pm_ops, |
421 | .of_match_table = omap_abe_of_match, | ||
337 | }, | 422 | }, |
338 | .probe = omap_abe_probe, | 423 | .probe = omap_abe_probe, |
339 | .remove = __devexit_p(omap_abe_remove), | 424 | .remove = __devexit_p(omap_abe_remove), |
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 75f5dca0e8d2..68f2cd1a9206 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/pm_runtime.h> | 34 | #include <linux/pm_runtime.h> |
35 | #include <linux/of_device.h> | 35 | #include <linux/of_device.h> |
36 | #include <plat/dma.h> | ||
37 | 36 | ||
38 | #include <sound/core.h> | 37 | #include <sound/core.h> |
39 | #include <sound/pcm.h> | 38 | #include <sound/pcm.h> |
@@ -63,8 +62,6 @@ struct omap_dmic { | |||
63 | */ | 62 | */ |
64 | static struct omap_pcm_dma_data omap_dmic_dai_dma_params = { | 63 | static struct omap_pcm_dma_data omap_dmic_dai_dma_params = { |
65 | .name = "DMIC capture", | 64 | .name = "DMIC capture", |
66 | .data_type = OMAP_DMA_DATA_TYPE_S32, | ||
67 | .sync_mode = OMAP_DMA_SYNC_PACKET, | ||
68 | }; | 65 | }; |
69 | 66 | ||
70 | static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) | 67 | static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) |
@@ -121,6 +118,7 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream, | |||
121 | 118 | ||
122 | mutex_unlock(&dmic->mutex); | 119 | mutex_unlock(&dmic->mutex); |
123 | 120 | ||
121 | snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params); | ||
124 | return ret; | 122 | return ret; |
125 | } | 123 | } |
126 | 124 | ||
@@ -205,6 +203,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream, | |||
205 | struct snd_soc_dai *dai) | 203 | struct snd_soc_dai *dai) |
206 | { | 204 | { |
207 | struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); | 205 | struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); |
206 | struct omap_pcm_dma_data *dma_data; | ||
208 | int channels; | 207 | int channels; |
209 | 208 | ||
210 | dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params)); | 209 | dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params)); |
@@ -230,8 +229,8 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream, | |||
230 | } | 229 | } |
231 | 230 | ||
232 | /* packet size is threshold * channels */ | 231 | /* packet size is threshold * channels */ |
233 | omap_dmic_dai_dma_params.packet_size = dmic->threshold * channels; | 232 | dma_data = snd_soc_dai_get_dma_data(dai, substream); |
234 | snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params); | 233 | dma_data->packet_size = dmic->threshold * channels; |
235 | 234 | ||
236 | return 0; | 235 | return 0; |
237 | } | 236 | } |
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c index a08245d9203c..f59c69fb400e 100644 --- a/sound/soc/omap/omap-hdmi.c +++ b/sound/soc/omap/omap-hdmi.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <sound/asoundef.h> | 34 | #include <sound/asoundef.h> |
35 | #include <video/omapdss.h> | 35 | #include <video/omapdss.h> |
36 | 36 | ||
37 | #include <plat/dma.h> | ||
38 | #include "omap-pcm.h" | 37 | #include "omap-pcm.h" |
39 | #include "omap-hdmi.h" | 38 | #include "omap-hdmi.h" |
40 | 39 | ||
@@ -68,6 +67,9 @@ static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream, | |||
68 | dev_err(dai->dev, "audio not supported\n"); | 67 | dev_err(dai->dev, "audio not supported\n"); |
69 | return -ENODEV; | 68 | return -ENODEV; |
70 | } | 69 | } |
70 | |||
71 | snd_soc_dai_set_dma_data(dai, substream, &priv->dma_params); | ||
72 | |||
71 | return 0; | 73 | return 0; |
72 | } | 74 | } |
73 | 75 | ||
@@ -86,24 +88,24 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, | |||
86 | struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai); | 88 | struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai); |
87 | struct snd_aes_iec958 *iec = &priv->iec; | 89 | struct snd_aes_iec958 *iec = &priv->iec; |
88 | struct snd_cea_861_aud_if *cea = &priv->cea; | 90 | struct snd_cea_861_aud_if *cea = &priv->cea; |
91 | struct omap_pcm_dma_data *dma_data; | ||
89 | int err = 0; | 92 | int err = 0; |
90 | 93 | ||
94 | dma_data = snd_soc_dai_get_dma_data(dai, substream); | ||
95 | |||
91 | switch (params_format(params)) { | 96 | switch (params_format(params)) { |
92 | case SNDRV_PCM_FORMAT_S16_LE: | 97 | case SNDRV_PCM_FORMAT_S16_LE: |
93 | priv->dma_params.packet_size = 16; | 98 | dma_data->packet_size = 16; |
94 | break; | 99 | break; |
95 | case SNDRV_PCM_FORMAT_S24_LE: | 100 | case SNDRV_PCM_FORMAT_S24_LE: |
96 | priv->dma_params.packet_size = 32; | 101 | dma_data->packet_size = 32; |
97 | break; | 102 | break; |
98 | default: | 103 | default: |
99 | dev_err(dai->dev, "format not supported!\n"); | 104 | dev_err(dai->dev, "format not supported!\n"); |
100 | return -EINVAL; | 105 | return -EINVAL; |
101 | } | 106 | } |
102 | 107 | ||
103 | priv->dma_params.data_type = OMAP_DMA_DATA_TYPE_S32; | 108 | dma_data->data_type = 32; |
104 | |||
105 | snd_soc_dai_set_dma_data(dai, substream, | ||
106 | &priv->dma_params); | ||
107 | 109 | ||
108 | /* | 110 | /* |
109 | * fill the IEC-60958 channel status word | 111 | * fill the IEC-60958 channel status word |
@@ -290,7 +292,6 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev) | |||
290 | 292 | ||
291 | hdmi_data->dma_params.dma_req = hdmi_rsrc->start; | 293 | hdmi_data->dma_params.dma_req = hdmi_rsrc->start; |
292 | hdmi_data->dma_params.name = "HDMI playback"; | 294 | hdmi_data->dma_params.name = "HDMI playback"; |
293 | hdmi_data->dma_params.sync_mode = OMAP_DMA_SYNC_PACKET; | ||
294 | 295 | ||
295 | /* | 296 | /* |
296 | * TODO: We assume that there is only one DSS HDMI device. Future | 297 | * TODO: We assume that there is only one DSS HDMI device. Future |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index acdd3ef14e08..fef2f5933bb2 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -26,13 +26,14 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/device.h> | 27 | #include <linux/device.h> |
28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
29 | #include <linux/of.h> | ||
30 | #include <linux/of_device.h> | ||
29 | #include <sound/core.h> | 31 | #include <sound/core.h> |
30 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
31 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
32 | #include <sound/initval.h> | 34 | #include <sound/initval.h> |
33 | #include <sound/soc.h> | 35 | #include <sound/soc.h> |
34 | 36 | ||
35 | #include <plat/dma.h> | ||
36 | #include <plat/mcbsp.h> | 37 | #include <plat/mcbsp.h> |
37 | #include "mcbsp.h" | 38 | #include "mcbsp.h" |
38 | #include "omap-mcbsp.h" | 39 | #include "omap-mcbsp.h" |
@@ -79,9 +80,6 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) | |||
79 | */ | 80 | */ |
80 | if (dma_data->packet_size) | 81 | if (dma_data->packet_size) |
81 | words = dma_data->packet_size; | 82 | words = dma_data->packet_size; |
82 | else if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) | ||
83 | words = snd_pcm_lib_period_bytes(substream) / | ||
84 | (mcbsp->wlen / 8); | ||
85 | else | 83 | else |
86 | words = 1; | 84 | words = 1; |
87 | 85 | ||
@@ -153,6 +151,9 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, | |||
153 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2); | 151 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2); |
154 | } | 152 | } |
155 | 153 | ||
154 | snd_soc_dai_set_dma_data(cpu_dai, substream, | ||
155 | &mcbsp->dma_data[substream->stream]); | ||
156 | |||
156 | return err; | 157 | return err; |
157 | } | 158 | } |
158 | 159 | ||
@@ -226,20 +227,18 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
226 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); | 227 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); |
227 | struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; | 228 | struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; |
228 | struct omap_pcm_dma_data *dma_data; | 229 | struct omap_pcm_dma_data *dma_data; |
229 | int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; | 230 | int wlen, channels, wpf; |
230 | int pkt_size = 0; | 231 | int pkt_size = 0; |
231 | unsigned int format, div, framesize, master; | 232 | unsigned int format, div, framesize, master; |
232 | 233 | ||
233 | dma_data = &mcbsp->dma_data[substream->stream]; | 234 | dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream); |
234 | channels = params_channels(params); | 235 | channels = params_channels(params); |
235 | 236 | ||
236 | switch (params_format(params)) { | 237 | switch (params_format(params)) { |
237 | case SNDRV_PCM_FORMAT_S16_LE: | 238 | case SNDRV_PCM_FORMAT_S16_LE: |
238 | dma_data->data_type = OMAP_DMA_DATA_TYPE_S16; | ||
239 | wlen = 16; | 239 | wlen = 16; |
240 | break; | 240 | break; |
241 | case SNDRV_PCM_FORMAT_S32_LE: | 241 | case SNDRV_PCM_FORMAT_S32_LE: |
242 | dma_data->data_type = OMAP_DMA_DATA_TYPE_S32; | ||
243 | wlen = 32; | 242 | wlen = 32; |
244 | break; | 243 | break; |
245 | default: | 244 | default: |
@@ -249,6 +248,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
249 | dma_data->set_threshold = omap_mcbsp_set_threshold; | 248 | dma_data->set_threshold = omap_mcbsp_set_threshold; |
250 | if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { | 249 | if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { |
251 | int period_words, max_thrsh; | 250 | int period_words, max_thrsh; |
251 | int divider = 0; | ||
252 | 252 | ||
253 | period_words = params_period_bytes(params) / (wlen / 8); | 253 | period_words = params_period_bytes(params) / (wlen / 8); |
254 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 254 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -256,46 +256,30 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
256 | else | 256 | else |
257 | max_thrsh = mcbsp->max_rx_thres; | 257 | max_thrsh = mcbsp->max_rx_thres; |
258 | /* | 258 | /* |
259 | * If the period contains less or equal number of words, | 259 | * Use sDMA packet mode if McBSP is in threshold mode: |
260 | * we are using the original threshold mode setup: | 260 | * If period words less than the FIFO size the packet |
261 | * McBSP threshold = sDMA frame size = period_size | 261 | * size is set to the number of period words, otherwise |
262 | * Otherwise we switch to sDMA packet mode: | 262 | * Look for the biggest threshold value which divides |
263 | * McBSP threshold = sDMA packet size | 263 | * the period size evenly. |
264 | * sDMA frame size = period size | ||
265 | */ | 264 | */ |
266 | if (period_words > max_thrsh) { | 265 | divider = period_words / max_thrsh; |
267 | int divider = 0; | 266 | if (period_words % max_thrsh) |
268 | 267 | divider++; | |
269 | /* | 268 | while (period_words % divider && |
270 | * Look for the biggest threshold value, which | 269 | divider < period_words) |
271 | * divides the period size evenly. | 270 | divider++; |
272 | */ | 271 | if (divider == period_words) |
273 | divider = period_words / max_thrsh; | 272 | return -EINVAL; |
274 | if (period_words % max_thrsh) | 273 | |
275 | divider++; | 274 | pkt_size = period_words / divider; |
276 | while (period_words % divider && | ||
277 | divider < period_words) | ||
278 | divider++; | ||
279 | if (divider == period_words) | ||
280 | return -EINVAL; | ||
281 | |||
282 | pkt_size = period_words / divider; | ||
283 | sync_mode = OMAP_DMA_SYNC_PACKET; | ||
284 | } else { | ||
285 | sync_mode = OMAP_DMA_SYNC_FRAME; | ||
286 | } | ||
287 | } else if (channels > 1) { | 275 | } else if (channels > 1) { |
288 | /* Use packet mode for non mono streams */ | 276 | /* Use packet mode for non mono streams */ |
289 | pkt_size = channels; | 277 | pkt_size = channels; |
290 | sync_mode = OMAP_DMA_SYNC_PACKET; | ||
291 | } | 278 | } |
292 | } | 279 | } |
293 | 280 | ||
294 | dma_data->sync_mode = sync_mode; | ||
295 | dma_data->packet_size = pkt_size; | 281 | dma_data->packet_size = pkt_size; |
296 | 282 | ||
297 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); | ||
298 | |||
299 | if (mcbsp->configured) { | 283 | if (mcbsp->configured) { |
300 | /* McBSP already configured by another stream */ | 284 | /* McBSP already configured by another stream */ |
301 | return 0; | 285 | return 0; |
@@ -398,12 +382,14 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
398 | /* Generic McBSP register settings */ | 382 | /* Generic McBSP register settings */ |
399 | regs->spcr2 |= XINTM(3) | FREE; | 383 | regs->spcr2 |= XINTM(3) | FREE; |
400 | regs->spcr1 |= RINTM(3); | 384 | regs->spcr1 |= RINTM(3); |
401 | /* RFIG and XFIG are not defined in 34xx */ | 385 | /* RFIG and XFIG are not defined in 2430 and on OMAP3+ */ |
402 | if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) { | 386 | if (!mcbsp->pdata->has_ccr) { |
403 | regs->rcr2 |= RFIG; | 387 | regs->rcr2 |= RFIG; |
404 | regs->xcr2 |= XFIG; | 388 | regs->xcr2 |= XFIG; |
405 | } | 389 | } |
406 | if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { | 390 | |
391 | /* Configure XCCR/RCCR only for revisions which have ccr registers */ | ||
392 | if (mcbsp->pdata->has_ccr) { | ||
407 | regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; | 393 | regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; |
408 | regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; | 394 | regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; |
409 | } | 395 | } |
@@ -516,21 +502,9 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
516 | return -EBUSY; | 502 | return -EBUSY; |
517 | } | 503 | } |
518 | 504 | ||
519 | if (clk_id == OMAP_MCBSP_SYSCLK_CLK || | 505 | mcbsp->in_freq = freq; |
520 | clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK || | 506 | regs->srgr2 &= ~CLKSM; |
521 | clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT || | 507 | regs->pcr0 &= ~SCLKME; |
522 | clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT || | ||
523 | clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) { | ||
524 | mcbsp->in_freq = freq; | ||
525 | regs->srgr2 &= ~CLKSM; | ||
526 | regs->pcr0 &= ~SCLKME; | ||
527 | } else if (cpu_class_is_omap1()) { | ||
528 | /* | ||
529 | * McBSP CLKR/FSR signal muxing functions are only available on | ||
530 | * OMAP2 or newer versions | ||
531 | */ | ||
532 | return -EINVAL; | ||
533 | } | ||
534 | 508 | ||
535 | switch (clk_id) { | 509 | switch (clk_id) { |
536 | case OMAP_MCBSP_SYSCLK_CLK: | 510 | case OMAP_MCBSP_SYSCLK_CLK: |
@@ -558,20 +532,6 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
558 | case OMAP_MCBSP_SYSCLK_CLKR_EXT: | 532 | case OMAP_MCBSP_SYSCLK_CLKR_EXT: |
559 | regs->pcr0 |= SCLKME; | 533 | regs->pcr0 |= SCLKME; |
560 | break; | 534 | break; |
561 | |||
562 | |||
563 | case OMAP_MCBSP_CLKR_SRC_CLKR: | ||
564 | err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR); | ||
565 | break; | ||
566 | case OMAP_MCBSP_CLKR_SRC_CLKX: | ||
567 | err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX); | ||
568 | break; | ||
569 | case OMAP_MCBSP_FSR_SRC_FSR: | ||
570 | err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR); | ||
571 | break; | ||
572 | case OMAP_MCBSP_FSR_SRC_FSX: | ||
573 | err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX); | ||
574 | break; | ||
575 | default: | 535 | default: |
576 | err = -ENODEV; | 536 | err = -ENODEV; |
577 | } | 537 | } |
@@ -641,9 +601,9 @@ static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, | |||
641 | return 0; | 601 | return 0; |
642 | } | 602 | } |
643 | 603 | ||
644 | #define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(channel) \ | 604 | #define OMAP_MCBSP_ST_CHANNEL_VOLUME(channel) \ |
645 | static int \ | 605 | static int \ |
646 | omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | 606 | omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ |
647 | struct snd_ctl_elem_value *uc) \ | 607 | struct snd_ctl_elem_value *uc) \ |
648 | { \ | 608 | { \ |
649 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ | 609 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ |
@@ -659,11 +619,10 @@ omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | |||
659 | \ | 619 | \ |
660 | /* OMAP McBSP implementation uses index values 0..4 */ \ | 620 | /* OMAP McBSP implementation uses index values 0..4 */ \ |
661 | return omap_st_set_chgain(mcbsp, channel, val); \ | 621 | return omap_st_set_chgain(mcbsp, channel, val); \ |
662 | } | 622 | } \ |
663 | 623 | \ | |
664 | #define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(channel) \ | ||
665 | static int \ | 624 | static int \ |
666 | omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | 625 | omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ |
667 | struct snd_ctl_elem_value *uc) \ | 626 | struct snd_ctl_elem_value *uc) \ |
668 | { \ | 627 | { \ |
669 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ | 628 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ |
@@ -677,10 +636,8 @@ omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | |||
677 | return 0; \ | 636 | return 0; \ |
678 | } | 637 | } |
679 | 638 | ||
680 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(0) | 639 | OMAP_MCBSP_ST_CHANNEL_VOLUME(0) |
681 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(1) | 640 | OMAP_MCBSP_ST_CHANNEL_VOLUME(1) |
682 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(0) | ||
683 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(1) | ||
684 | 641 | ||
685 | static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, | 642 | static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, |
686 | struct snd_ctl_elem_value *ucontrol) | 643 | struct snd_ctl_elem_value *ucontrol) |
@@ -710,41 +667,34 @@ static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol, | |||
710 | return 0; | 667 | return 0; |
711 | } | 668 | } |
712 | 669 | ||
713 | static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { | 670 | #define OMAP_MCBSP_ST_CONTROLS(port) \ |
714 | SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0, | 671 | static const struct snd_kcontrol_new omap_mcbsp##port##_st_controls[] = { \ |
715 | omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), | 672 | SOC_SINGLE_EXT("McBSP" #port " Sidetone Switch", 1, 0, 1, 0, \ |
716 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", | 673 | omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), \ |
717 | -32768, 32767, | 674 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 0 Volume", \ |
718 | omap_mcbsp_get_st_ch0_volume, | 675 | -32768, 32767, \ |
719 | omap_mcbsp_set_st_ch0_volume), | 676 | omap_mcbsp_get_st_ch0_volume, \ |
720 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", | 677 | omap_mcbsp_set_st_ch0_volume), \ |
721 | -32768, 32767, | 678 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 1 Volume", \ |
722 | omap_mcbsp_get_st_ch1_volume, | 679 | -32768, 32767, \ |
723 | omap_mcbsp_set_st_ch1_volume), | 680 | omap_mcbsp_get_st_ch1_volume, \ |
724 | }; | 681 | omap_mcbsp_set_st_ch1_volume), \ |
682 | } | ||
725 | 683 | ||
726 | static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { | 684 | OMAP_MCBSP_ST_CONTROLS(2); |
727 | SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0, | 685 | OMAP_MCBSP_ST_CONTROLS(3); |
728 | omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), | ||
729 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume", | ||
730 | -32768, 32767, | ||
731 | omap_mcbsp_get_st_ch0_volume, | ||
732 | omap_mcbsp_set_st_ch0_volume), | ||
733 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume", | ||
734 | -32768, 32767, | ||
735 | omap_mcbsp_get_st_ch1_volume, | ||
736 | omap_mcbsp_set_st_ch1_volume), | ||
737 | }; | ||
738 | 686 | ||
739 | int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) | 687 | int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) |
740 | { | 688 | { |
741 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 689 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
742 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); | 690 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); |
743 | 691 | ||
744 | if (!mcbsp->st_data) | 692 | if (!mcbsp->st_data) { |
745 | return -ENODEV; | 693 | dev_warn(mcbsp->dev, "No sidetone data for port\n"); |
694 | return 0; | ||
695 | } | ||
746 | 696 | ||
747 | switch (cpu_dai->id) { | 697 | switch (mcbsp->id) { |
748 | case 2: /* McBSP 2 */ | 698 | case 2: /* McBSP 2 */ |
749 | return snd_soc_add_dai_controls(cpu_dai, | 699 | return snd_soc_add_dai_controls(cpu_dai, |
750 | omap_mcbsp2_st_controls, | 700 | omap_mcbsp2_st_controls, |
@@ -761,13 +711,74 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) | |||
761 | } | 711 | } |
762 | EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); | 712 | EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); |
763 | 713 | ||
714 | static struct omap_mcbsp_platform_data omap2420_pdata = { | ||
715 | .reg_step = 4, | ||
716 | .reg_size = 2, | ||
717 | }; | ||
718 | |||
719 | static struct omap_mcbsp_platform_data omap2430_pdata = { | ||
720 | .reg_step = 4, | ||
721 | .reg_size = 4, | ||
722 | .has_ccr = true, | ||
723 | }; | ||
724 | |||
725 | static struct omap_mcbsp_platform_data omap3_pdata = { | ||
726 | .reg_step = 4, | ||
727 | .reg_size = 4, | ||
728 | .has_ccr = true, | ||
729 | .has_wakeup = true, | ||
730 | }; | ||
731 | |||
732 | static struct omap_mcbsp_platform_data omap4_pdata = { | ||
733 | .reg_step = 4, | ||
734 | .reg_size = 4, | ||
735 | .has_ccr = true, | ||
736 | .has_wakeup = true, | ||
737 | }; | ||
738 | |||
739 | static const struct of_device_id omap_mcbsp_of_match[] = { | ||
740 | { | ||
741 | .compatible = "ti,omap2420-mcbsp", | ||
742 | .data = &omap2420_pdata, | ||
743 | }, | ||
744 | { | ||
745 | .compatible = "ti,omap2430-mcbsp", | ||
746 | .data = &omap2430_pdata, | ||
747 | }, | ||
748 | { | ||
749 | .compatible = "ti,omap3-mcbsp", | ||
750 | .data = &omap3_pdata, | ||
751 | }, | ||
752 | { | ||
753 | .compatible = "ti,omap4-mcbsp", | ||
754 | .data = &omap4_pdata, | ||
755 | }, | ||
756 | { }, | ||
757 | }; | ||
758 | MODULE_DEVICE_TABLE(of, omap_mcbsp_of_match); | ||
759 | |||
764 | static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) | 760 | static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) |
765 | { | 761 | { |
766 | struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev); | 762 | struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev); |
767 | struct omap_mcbsp *mcbsp; | 763 | struct omap_mcbsp *mcbsp; |
764 | const struct of_device_id *match; | ||
768 | int ret; | 765 | int ret; |
769 | 766 | ||
770 | if (!pdata) { | 767 | match = of_match_device(omap_mcbsp_of_match, &pdev->dev); |
768 | if (match) { | ||
769 | struct device_node *node = pdev->dev.of_node; | ||
770 | int buffer_size; | ||
771 | |||
772 | pdata = devm_kzalloc(&pdev->dev, | ||
773 | sizeof(struct omap_mcbsp_platform_data), | ||
774 | GFP_KERNEL); | ||
775 | if (!pdata) | ||
776 | return -ENOMEM; | ||
777 | |||
778 | memcpy(pdata, match->data, sizeof(*pdata)); | ||
779 | if (!of_property_read_u32(node, "ti,buffer-size", &buffer_size)) | ||
780 | pdata->buffer_size = buffer_size; | ||
781 | } else if (!pdata) { | ||
771 | dev_err(&pdev->dev, "missing platform data.\n"); | 782 | dev_err(&pdev->dev, "missing platform data.\n"); |
772 | return -EINVAL; | 783 | return -EINVAL; |
773 | } | 784 | } |
@@ -809,6 +820,7 @@ static struct platform_driver asoc_mcbsp_driver = { | |||
809 | .driver = { | 820 | .driver = { |
810 | .name = "omap-mcbsp", | 821 | .name = "omap-mcbsp", |
811 | .owner = THIS_MODULE, | 822 | .owner = THIS_MODULE, |
823 | .of_match_table = omap_mcbsp_of_match, | ||
812 | }, | 824 | }, |
813 | 825 | ||
814 | .probe = asoc_mcbsp_probe, | 826 | .probe = asoc_mcbsp_probe, |
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index f877b16f19c9..ba8386a0d8dc 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h | |||
@@ -32,10 +32,6 @@ enum omap_mcbsp_clksrg_clk { | |||
32 | OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */ | 32 | OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */ |
33 | OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */ | 33 | OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */ |
34 | OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */ | 34 | OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */ |
35 | OMAP_MCBSP_CLKR_SRC_CLKR, /* CLKR from CLKR pin */ | ||
36 | OMAP_MCBSP_CLKR_SRC_CLKX, /* CLKR from CLKX pin */ | ||
37 | OMAP_MCBSP_FSR_SRC_FSR, /* FSR from FSR pin */ | ||
38 | OMAP_MCBSP_FSR_SRC_FSX, /* FSR from FSX pin */ | ||
39 | }; | 35 | }; |
40 | 36 | ||
41 | /* McBSP dividers */ | 37 | /* McBSP dividers */ |
@@ -43,22 +39,6 @@ enum omap_mcbsp_div { | |||
43 | OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */ | 39 | OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */ |
44 | }; | 40 | }; |
45 | 41 | ||
46 | #if defined(CONFIG_SOC_OMAP2420) | ||
47 | #define NUM_LINKS 2 | ||
48 | #endif | ||
49 | #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) | ||
50 | #undef NUM_LINKS | ||
51 | #define NUM_LINKS 3 | ||
52 | #endif | ||
53 | #if defined(CONFIG_ARCH_OMAP4) | ||
54 | #undef NUM_LINKS | ||
55 | #define NUM_LINKS 4 | ||
56 | #endif | ||
57 | #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_OMAP2430) | ||
58 | #undef NUM_LINKS | ||
59 | #define NUM_LINKS 5 | ||
60 | #endif | ||
61 | |||
62 | int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd); | 42 | int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd); |
63 | 43 | ||
64 | #endif | 44 | #endif |
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 2c66e2498a45..775565032ce3 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <sound/pcm_params.h> | 40 | #include <sound/pcm_params.h> |
41 | #include <sound/soc.h> | 41 | #include <sound/soc.h> |
42 | 42 | ||
43 | #include <plat/dma.h> | ||
44 | #include <plat/omap_hwmod.h> | 43 | #include <plat/omap_hwmod.h> |
45 | #include "omap-mcpdm.h" | 44 | #include "omap-mcpdm.h" |
46 | #include "omap-pcm.h" | 45 | #include "omap-pcm.h" |
@@ -71,17 +70,9 @@ struct omap_mcpdm { | |||
71 | static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { | 70 | static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { |
72 | { | 71 | { |
73 | .name = "Audio playback", | 72 | .name = "Audio playback", |
74 | .dma_req = OMAP44XX_DMA_MCPDM_DL, | ||
75 | .data_type = OMAP_DMA_DATA_TYPE_S32, | ||
76 | .sync_mode = OMAP_DMA_SYNC_PACKET, | ||
77 | .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA, | ||
78 | }, | 73 | }, |
79 | { | 74 | { |
80 | .name = "Audio capture", | 75 | .name = "Audio capture", |
81 | .dma_req = OMAP44XX_DMA_MCPDM_UP, | ||
82 | .data_type = OMAP_DMA_DATA_TYPE_S32, | ||
83 | .sync_mode = OMAP_DMA_SYNC_PACKET, | ||
84 | .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA, | ||
85 | }, | 76 | }, |
86 | }; | 77 | }; |
87 | 78 | ||
@@ -276,9 +267,11 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, | |||
276 | } | 267 | } |
277 | omap_mcpdm_open_streams(mcpdm); | 268 | omap_mcpdm_open_streams(mcpdm); |
278 | } | 269 | } |
279 | |||
280 | mutex_unlock(&mcpdm->mutex); | 270 | mutex_unlock(&mcpdm->mutex); |
281 | 271 | ||
272 | snd_soc_dai_set_dma_data(dai, substream, | ||
273 | &omap_mcpdm_dai_dma_params[substream->stream]); | ||
274 | |||
282 | return 0; | 275 | return 0; |
283 | } | 276 | } |
284 | 277 | ||
@@ -333,7 +326,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, | |||
333 | return -EINVAL; | 326 | return -EINVAL; |
334 | } | 327 | } |
335 | 328 | ||
336 | dma_data = &omap_mcpdm_dai_dma_params[stream]; | 329 | dma_data = snd_soc_dai_get_dma_data(dai, substream); |
337 | 330 | ||
338 | /* Configure McPDM channels, and DMA packet size */ | 331 | /* Configure McPDM channels, and DMA packet size */ |
339 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 332 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
@@ -345,8 +338,6 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, | |||
345 | dma_data->packet_size = mcpdm->up_threshold * channels; | 338 | dma_data->packet_size = mcpdm->up_threshold * channels; |
346 | } | 339 | } |
347 | 340 | ||
348 | snd_soc_dai_set_dma_data(dai, substream, dma_data); | ||
349 | |||
350 | return 0; | 341 | return 0; |
351 | } | 342 | } |
352 | 343 | ||
@@ -445,9 +436,8 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) | |||
445 | { | 436 | { |
446 | struct omap_mcpdm *mcpdm; | 437 | struct omap_mcpdm *mcpdm; |
447 | struct resource *res; | 438 | struct resource *res; |
448 | int ret = 0; | ||
449 | 439 | ||
450 | mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL); | 440 | mcpdm = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcpdm), GFP_KERNEL); |
451 | if (!mcpdm) | 441 | if (!mcpdm) |
452 | return -ENOMEM; | 442 | return -ENOMEM; |
453 | 443 | ||
@@ -455,56 +445,54 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) | |||
455 | 445 | ||
456 | mutex_init(&mcpdm->mutex); | 446 | mutex_init(&mcpdm->mutex); |
457 | 447 | ||
448 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); | ||
449 | if (res == NULL) | ||
450 | return -ENOMEM; | ||
451 | |||
452 | omap_mcpdm_dai_dma_params[0].port_addr = res->start + MCPDM_REG_DN_DATA; | ||
453 | omap_mcpdm_dai_dma_params[1].port_addr = res->start + MCPDM_REG_UP_DATA; | ||
454 | |||
458 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 455 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
459 | if (res == NULL) { | 456 | if (res == NULL) |
460 | dev_err(&pdev->dev, "no resource\n"); | 457 | return -ENOMEM; |
461 | goto err_res; | ||
462 | } | ||
463 | 458 | ||
464 | if (!request_mem_region(res->start, resource_size(res), "McPDM")) { | 459 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link"); |
465 | ret = -EBUSY; | 460 | if (!res) |
466 | goto err_res; | 461 | return -ENODEV; |
467 | } | ||
468 | 462 | ||
469 | mcpdm->io_base = ioremap(res->start, resource_size(res)); | 463 | omap_mcpdm_dai_dma_params[0].dma_req = res->start; |
470 | if (!mcpdm->io_base) { | 464 | |
471 | ret = -ENOMEM; | 465 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link"); |
472 | goto err_iomap; | 466 | if (!res) |
473 | } | 467 | return -ENODEV; |
468 | |||
469 | omap_mcpdm_dai_dma_params[1].dma_req = res->start; | ||
470 | |||
471 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); | ||
472 | if (res == NULL) | ||
473 | return -ENOMEM; | ||
474 | |||
475 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
476 | resource_size(res), "McPDM")) | ||
477 | return -EBUSY; | ||
478 | |||
479 | mcpdm->io_base = devm_ioremap(&pdev->dev, res->start, | ||
480 | resource_size(res)); | ||
481 | if (!mcpdm->io_base) | ||
482 | return -ENOMEM; | ||
474 | 483 | ||
475 | mcpdm->irq = platform_get_irq(pdev, 0); | 484 | mcpdm->irq = platform_get_irq(pdev, 0); |
476 | if (mcpdm->irq < 0) { | 485 | if (mcpdm->irq < 0) |
477 | ret = mcpdm->irq; | 486 | return mcpdm->irq; |
478 | goto err_irq; | ||
479 | } | ||
480 | 487 | ||
481 | mcpdm->dev = &pdev->dev; | 488 | mcpdm->dev = &pdev->dev; |
482 | 489 | ||
483 | ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); | 490 | return snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); |
484 | if (!ret) | ||
485 | return 0; | ||
486 | |||
487 | err_irq: | ||
488 | iounmap(mcpdm->io_base); | ||
489 | err_iomap: | ||
490 | release_mem_region(res->start, resource_size(res)); | ||
491 | err_res: | ||
492 | kfree(mcpdm); | ||
493 | return ret; | ||
494 | } | 491 | } |
495 | 492 | ||
496 | static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) | 493 | static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) |
497 | { | 494 | { |
498 | struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev); | ||
499 | struct resource *res; | ||
500 | |||
501 | snd_soc_unregister_dai(&pdev->dev); | 495 | snd_soc_unregister_dai(&pdev->dev); |
502 | |||
503 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
504 | iounmap(mcpdm->io_base); | ||
505 | release_mem_region(res->start, resource_size(res)); | ||
506 | |||
507 | kfree(mcpdm); | ||
508 | return 0; | 496 | return 0; |
509 | } | 497 | } |
510 | 498 | ||
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index f0feb06615f8..a2636f6b8362 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -25,12 +25,13 @@ | |||
25 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/omap-dma.h> | ||
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
29 | #include <sound/pcm.h> | 30 | #include <sound/pcm.h> |
30 | #include <sound/pcm_params.h> | 31 | #include <sound/pcm_params.h> |
32 | #include <sound/dmaengine_pcm.h> | ||
31 | #include <sound/soc.h> | 33 | #include <sound/soc.h> |
32 | 34 | ||
33 | #include <plat/dma.h> | ||
34 | #include "omap-pcm.h" | 35 | #include "omap-pcm.h" |
35 | 36 | ||
36 | static const struct snd_pcm_hardware omap_pcm_hardware = { | 37 | static const struct snd_pcm_hardware omap_pcm_hardware = { |
@@ -49,61 +50,34 @@ static const struct snd_pcm_hardware omap_pcm_hardware = { | |||
49 | .buffer_bytes_max = 128 * 1024, | 50 | .buffer_bytes_max = 128 * 1024, |
50 | }; | 51 | }; |
51 | 52 | ||
52 | struct omap_runtime_data { | 53 | static int omap_pcm_get_dma_buswidth(int num_bits) |
53 | spinlock_t lock; | ||
54 | struct omap_pcm_dma_data *dma_data; | ||
55 | int dma_ch; | ||
56 | int period_index; | ||
57 | }; | ||
58 | |||
59 | static void omap_pcm_dma_irq(int ch, u16 stat, void *data) | ||
60 | { | 54 | { |
61 | struct snd_pcm_substream *substream = data; | 55 | int buswidth; |
62 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
63 | struct omap_runtime_data *prtd = runtime->private_data; | ||
64 | unsigned long flags; | ||
65 | |||
66 | if ((cpu_is_omap1510())) { | ||
67 | /* | ||
68 | * OMAP1510 doesn't fully support DMA progress counter | ||
69 | * and there is no software emulation implemented yet, | ||
70 | * so have to maintain our own progress counters | ||
71 | * that can be used by omap_pcm_pointer() instead. | ||
72 | */ | ||
73 | spin_lock_irqsave(&prtd->lock, flags); | ||
74 | if ((stat == OMAP_DMA_LAST_IRQ) && | ||
75 | (prtd->period_index == runtime->periods - 1)) { | ||
76 | /* we are in sync, do nothing */ | ||
77 | spin_unlock_irqrestore(&prtd->lock, flags); | ||
78 | return; | ||
79 | } | ||
80 | if (prtd->period_index >= 0) { | ||
81 | if (stat & OMAP_DMA_BLOCK_IRQ) { | ||
82 | /* end of buffer reached, loop back */ | ||
83 | prtd->period_index = 0; | ||
84 | } else if (stat & OMAP_DMA_LAST_IRQ) { | ||
85 | /* update the counter for the last period */ | ||
86 | prtd->period_index = runtime->periods - 1; | ||
87 | } else if (++prtd->period_index >= runtime->periods) { | ||
88 | /* end of buffer missed? loop back */ | ||
89 | prtd->period_index = 0; | ||
90 | } | ||
91 | } | ||
92 | spin_unlock_irqrestore(&prtd->lock, flags); | ||
93 | } | ||
94 | 56 | ||
95 | snd_pcm_period_elapsed(substream); | 57 | switch (num_bits) { |
58 | case 16: | ||
59 | buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
60 | break; | ||
61 | case 32: | ||
62 | buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
63 | break; | ||
64 | default: | ||
65 | buswidth = -EINVAL; | ||
66 | break; | ||
67 | } | ||
68 | return buswidth; | ||
96 | } | 69 | } |
97 | 70 | ||
71 | |||
98 | /* this may get called several times by oss emulation */ | 72 | /* this may get called several times by oss emulation */ |
99 | static int omap_pcm_hw_params(struct snd_pcm_substream *substream, | 73 | static int omap_pcm_hw_params(struct snd_pcm_substream *substream, |
100 | struct snd_pcm_hw_params *params) | 74 | struct snd_pcm_hw_params *params) |
101 | { | 75 | { |
102 | struct snd_pcm_runtime *runtime = substream->runtime; | 76 | struct snd_pcm_runtime *runtime = substream->runtime; |
103 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 77 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
104 | struct omap_runtime_data *prtd = runtime->private_data; | ||
105 | struct omap_pcm_dma_data *dma_data; | 78 | struct omap_pcm_dma_data *dma_data; |
106 | 79 | struct dma_slave_config config; | |
80 | struct dma_chan *chan; | ||
107 | int err = 0; | 81 | int err = 0; |
108 | 82 | ||
109 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 83 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
@@ -116,162 +90,78 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, | |||
116 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 90 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); |
117 | runtime->dma_bytes = params_buffer_bytes(params); | 91 | runtime->dma_bytes = params_buffer_bytes(params); |
118 | 92 | ||
119 | if (prtd->dma_data) | 93 | chan = snd_dmaengine_pcm_get_chan(substream); |
120 | return 0; | 94 | if (!chan) |
121 | prtd->dma_data = dma_data; | 95 | return -EINVAL; |
122 | err = omap_request_dma(dma_data->dma_req, dma_data->name, | ||
123 | omap_pcm_dma_irq, substream, &prtd->dma_ch); | ||
124 | if (!err) { | ||
125 | /* | ||
126 | * Link channel with itself so DMA doesn't need any | ||
127 | * reprogramming while looping the buffer | ||
128 | */ | ||
129 | omap_dma_link_lch(prtd->dma_ch, prtd->dma_ch); | ||
130 | } | ||
131 | 96 | ||
132 | return err; | 97 | /* fills in addr_width and direction */ |
133 | } | 98 | err = snd_hwparams_to_dma_slave_config(substream, params, &config); |
99 | if (err) | ||
100 | return err; | ||
134 | 101 | ||
135 | static int omap_pcm_hw_free(struct snd_pcm_substream *substream) | 102 | /* Override the *_dma addr_width if requested by the DAI driver */ |
136 | { | 103 | if (dma_data->data_type) { |
137 | struct snd_pcm_runtime *runtime = substream->runtime; | 104 | int buswidth = omap_pcm_get_dma_buswidth(dma_data->data_type); |
138 | struct omap_runtime_data *prtd = runtime->private_data; | ||
139 | 105 | ||
140 | if (prtd->dma_data == NULL) | 106 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
141 | return 0; | 107 | config.dst_addr_width = buswidth; |
142 | 108 | else | |
143 | omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch); | 109 | config.src_addr_width = buswidth; |
144 | omap_free_dma(prtd->dma_ch); | 110 | } |
145 | prtd->dma_data = NULL; | ||
146 | 111 | ||
147 | snd_pcm_set_runtime_buffer(substream, NULL); | 112 | config.src_addr = dma_data->port_addr; |
113 | config.dst_addr = dma_data->port_addr; | ||
114 | config.src_maxburst = dma_data->packet_size; | ||
115 | config.dst_maxburst = dma_data->packet_size; | ||
148 | 116 | ||
149 | return 0; | 117 | return dmaengine_slave_config(chan, &config); |
150 | } | 118 | } |
151 | 119 | ||
152 | static int omap_pcm_prepare(struct snd_pcm_substream *substream) | 120 | static int omap_pcm_hw_free(struct snd_pcm_substream *substream) |
153 | { | 121 | { |
154 | struct snd_pcm_runtime *runtime = substream->runtime; | 122 | snd_pcm_set_runtime_buffer(substream, NULL); |
155 | struct omap_runtime_data *prtd = runtime->private_data; | ||
156 | struct omap_pcm_dma_data *dma_data = prtd->dma_data; | ||
157 | struct omap_dma_channel_params dma_params; | ||
158 | int bytes; | ||
159 | |||
160 | /* return if this is a bufferless transfer e.g. | ||
161 | * codec <--> BT codec or GSM modem -- lg FIXME */ | ||
162 | if (!prtd->dma_data) | ||
163 | return 0; | ||
164 | |||
165 | memset(&dma_params, 0, sizeof(dma_params)); | ||
166 | dma_params.data_type = dma_data->data_type; | ||
167 | dma_params.trigger = dma_data->dma_req; | ||
168 | dma_params.sync_mode = dma_data->sync_mode; | ||
169 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
170 | dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; | ||
171 | dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT; | ||
172 | dma_params.src_or_dst_synch = OMAP_DMA_DST_SYNC; | ||
173 | dma_params.src_start = runtime->dma_addr; | ||
174 | dma_params.dst_start = dma_data->port_addr; | ||
175 | dma_params.dst_port = OMAP_DMA_PORT_MPUI; | ||
176 | dma_params.dst_fi = dma_data->packet_size; | ||
177 | } else { | ||
178 | dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT; | ||
179 | dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC; | ||
180 | dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC; | ||
181 | dma_params.src_start = dma_data->port_addr; | ||
182 | dma_params.dst_start = runtime->dma_addr; | ||
183 | dma_params.src_port = OMAP_DMA_PORT_MPUI; | ||
184 | dma_params.src_fi = dma_data->packet_size; | ||
185 | } | ||
186 | /* | ||
187 | * Set DMA transfer frame size equal to ALSA period size and frame | ||
188 | * count as no. of ALSA periods. Then with DMA frame interrupt enabled, | ||
189 | * we can transfer the whole ALSA buffer with single DMA transfer but | ||
190 | * still can get an interrupt at each period bounary | ||
191 | */ | ||
192 | bytes = snd_pcm_lib_period_bytes(substream); | ||
193 | dma_params.elem_count = bytes >> dma_data->data_type; | ||
194 | dma_params.frame_count = runtime->periods; | ||
195 | omap_set_dma_params(prtd->dma_ch, &dma_params); | ||
196 | |||
197 | if ((cpu_is_omap1510())) | ||
198 | omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | | ||
199 | OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); | ||
200 | else if (!substream->runtime->no_period_wakeup) | ||
201 | omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ); | ||
202 | else { | ||
203 | /* | ||
204 | * No period wakeup: | ||
205 | * we need to disable BLOCK_IRQ, which is enabled by the omap | ||
206 | * dma core at request dma time. | ||
207 | */ | ||
208 | omap_disable_dma_irq(prtd->dma_ch, OMAP_DMA_BLOCK_IRQ); | ||
209 | } | ||
210 | |||
211 | if (!(cpu_class_is_omap1())) { | ||
212 | omap_set_dma_src_burst_mode(prtd->dma_ch, | ||
213 | OMAP_DMA_DATA_BURST_16); | ||
214 | omap_set_dma_dest_burst_mode(prtd->dma_ch, | ||
215 | OMAP_DMA_DATA_BURST_16); | ||
216 | } | ||
217 | |||
218 | return 0; | 123 | return 0; |
219 | } | 124 | } |
220 | 125 | ||
221 | static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 126 | static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
222 | { | 127 | { |
223 | struct snd_pcm_runtime *runtime = substream->runtime; | 128 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
224 | struct omap_runtime_data *prtd = runtime->private_data; | 129 | struct omap_pcm_dma_data *dma_data; |
225 | struct omap_pcm_dma_data *dma_data = prtd->dma_data; | ||
226 | unsigned long flags; | ||
227 | int ret = 0; | 130 | int ret = 0; |
228 | 131 | ||
229 | spin_lock_irqsave(&prtd->lock, flags); | 132 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
133 | |||
230 | switch (cmd) { | 134 | switch (cmd) { |
231 | case SNDRV_PCM_TRIGGER_START: | 135 | case SNDRV_PCM_TRIGGER_START: |
232 | case SNDRV_PCM_TRIGGER_RESUME: | 136 | case SNDRV_PCM_TRIGGER_RESUME: |
233 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 137 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
234 | prtd->period_index = 0; | ||
235 | /* Configure McBSP internal buffer usage */ | 138 | /* Configure McBSP internal buffer usage */ |
236 | if (dma_data->set_threshold) | 139 | if (dma_data->set_threshold) |
237 | dma_data->set_threshold(substream); | 140 | dma_data->set_threshold(substream); |
238 | |||
239 | omap_start_dma(prtd->dma_ch); | ||
240 | break; | 141 | break; |
241 | 142 | ||
242 | case SNDRV_PCM_TRIGGER_STOP: | 143 | case SNDRV_PCM_TRIGGER_STOP: |
243 | case SNDRV_PCM_TRIGGER_SUSPEND: | 144 | case SNDRV_PCM_TRIGGER_SUSPEND: |
244 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 145 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
245 | prtd->period_index = -1; | ||
246 | omap_stop_dma(prtd->dma_ch); | ||
247 | break; | 146 | break; |
248 | default: | 147 | default: |
249 | ret = -EINVAL; | 148 | ret = -EINVAL; |
250 | } | 149 | } |
251 | spin_unlock_irqrestore(&prtd->lock, flags); | 150 | |
151 | if (ret == 0) | ||
152 | ret = snd_dmaengine_pcm_trigger(substream, cmd); | ||
252 | 153 | ||
253 | return ret; | 154 | return ret; |
254 | } | 155 | } |
255 | 156 | ||
256 | static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) | 157 | static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) |
257 | { | 158 | { |
258 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
259 | struct omap_runtime_data *prtd = runtime->private_data; | ||
260 | dma_addr_t ptr; | ||
261 | snd_pcm_uframes_t offset; | 159 | snd_pcm_uframes_t offset; |
262 | 160 | ||
263 | if (cpu_is_omap1510()) { | 161 | if (cpu_is_omap1510()) |
264 | offset = prtd->period_index * runtime->period_size; | 162 | offset = snd_dmaengine_pcm_pointer_no_residue(substream); |
265 | } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 163 | else |
266 | ptr = omap_get_dma_dst_pos(prtd->dma_ch); | 164 | offset = snd_dmaengine_pcm_pointer(substream); |
267 | offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); | ||
268 | } else { | ||
269 | ptr = omap_get_dma_src_pos(prtd->dma_ch); | ||
270 | offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); | ||
271 | } | ||
272 | |||
273 | if (offset >= runtime->buffer_size) | ||
274 | offset = 0; | ||
275 | 165 | ||
276 | return offset; | 166 | return offset; |
277 | } | 167 | } |
@@ -279,7 +169,8 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) | |||
279 | static int omap_pcm_open(struct snd_pcm_substream *substream) | 169 | static int omap_pcm_open(struct snd_pcm_substream *substream) |
280 | { | 170 | { |
281 | struct snd_pcm_runtime *runtime = substream->runtime; | 171 | struct snd_pcm_runtime *runtime = substream->runtime; |
282 | struct omap_runtime_data *prtd; | 172 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
173 | struct omap_pcm_dma_data *dma_data; | ||
283 | int ret; | 174 | int ret; |
284 | 175 | ||
285 | snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); | 176 | snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); |
@@ -288,25 +179,17 @@ static int omap_pcm_open(struct snd_pcm_substream *substream) | |||
288 | ret = snd_pcm_hw_constraint_integer(runtime, | 179 | ret = snd_pcm_hw_constraint_integer(runtime, |
289 | SNDRV_PCM_HW_PARAM_PERIODS); | 180 | SNDRV_PCM_HW_PARAM_PERIODS); |
290 | if (ret < 0) | 181 | if (ret < 0) |
291 | goto out; | 182 | return ret; |
292 | 183 | ||
293 | prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); | 184 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
294 | if (prtd == NULL) { | 185 | ret = snd_dmaengine_pcm_open(substream, omap_dma_filter_fn, |
295 | ret = -ENOMEM; | 186 | &dma_data->dma_req); |
296 | goto out; | ||
297 | } | ||
298 | spin_lock_init(&prtd->lock); | ||
299 | runtime->private_data = prtd; | ||
300 | |||
301 | out: | ||
302 | return ret; | 187 | return ret; |
303 | } | 188 | } |
304 | 189 | ||
305 | static int omap_pcm_close(struct snd_pcm_substream *substream) | 190 | static int omap_pcm_close(struct snd_pcm_substream *substream) |
306 | { | 191 | { |
307 | struct snd_pcm_runtime *runtime = substream->runtime; | 192 | snd_dmaengine_pcm_close(substream); |
308 | |||
309 | kfree(runtime->private_data); | ||
310 | return 0; | 193 | return 0; |
311 | } | 194 | } |
312 | 195 | ||
@@ -327,7 +210,6 @@ static struct snd_pcm_ops omap_pcm_ops = { | |||
327 | .ioctl = snd_pcm_lib_ioctl, | 210 | .ioctl = snd_pcm_lib_ioctl, |
328 | .hw_params = omap_pcm_hw_params, | 211 | .hw_params = omap_pcm_hw_params, |
329 | .hw_free = omap_pcm_hw_free, | 212 | .hw_free = omap_pcm_hw_free, |
330 | .prepare = omap_pcm_prepare, | ||
331 | .trigger = omap_pcm_trigger, | 213 | .trigger = omap_pcm_trigger, |
332 | .pointer = omap_pcm_pointer, | 214 | .pointer = omap_pcm_pointer, |
333 | .mmap = omap_pcm_mmap, | 215 | .mmap = omap_pcm_mmap, |
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index b92248cbd47a..cabe74c4068b 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h | |||
@@ -32,8 +32,8 @@ struct omap_pcm_dma_data { | |||
32 | int dma_req; /* DMA request line */ | 32 | int dma_req; /* DMA request line */ |
33 | unsigned long port_addr; /* transmit/receive register */ | 33 | unsigned long port_addr; /* transmit/receive register */ |
34 | void (*set_threshold)(struct snd_pcm_substream *substream); | 34 | void (*set_threshold)(struct snd_pcm_substream *substream); |
35 | int data_type; /* data type 8,16,32 */ | 35 | int data_type; /* 8, 16, 32 (bits) or 0 to let omap-pcm |
36 | int sync_mode; /* DMA sync mode */ | 36 | * to decide the sDMA data type */ |
37 | int packet_size; /* packet size only in PACKET mode */ | 37 | int packet_size; /* packet size only in PACKET mode */ |
38 | }; | 38 | }; |
39 | 39 | ||
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c new file mode 100644 index 000000000000..3b97b87971f5 --- /dev/null +++ b/sound/soc/omap/omap-twl4030.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * omap-twl4030.c -- SoC audio for TI SoC based boards with twl4030 codec | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
8 | * | ||
9 | * This driver replaces the following machine drivers: | ||
10 | * omap3beagle (Author: Steve Sakoman <steve@sakoman.com>) | ||
11 | * omap3evm (Author: Anuj Aggarwal <anuj.aggarwal@ti.com>) | ||
12 | * overo (Author: Steve Sakoman <steve@sakoman.com>) | ||
13 | * igep0020 (Author: Enric Balletbo i Serra <eballetbo@iseebcn.com>) | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * version 2 as published by the Free Software Foundation. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, but | ||
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
22 | * General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
27 | * 02110-1301 USA | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/platform_data/omap-twl4030.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/of.h> | ||
35 | |||
36 | #include <sound/core.h> | ||
37 | #include <sound/pcm.h> | ||
38 | #include <sound/soc.h> | ||
39 | |||
40 | #include "omap-mcbsp.h" | ||
41 | #include "omap-pcm.h" | ||
42 | |||
43 | static int omap_twl4030_hw_params(struct snd_pcm_substream *substream, | ||
44 | struct snd_pcm_hw_params *params) | ||
45 | { | ||
46 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
47 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
48 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
49 | struct snd_soc_codec *codec = rtd->codec; | ||
50 | struct snd_soc_card *card = codec->card; | ||
51 | unsigned int fmt; | ||
52 | int ret; | ||
53 | |||
54 | switch (params_channels(params)) { | ||
55 | case 2: /* Stereo I2S mode */ | ||
56 | fmt = SND_SOC_DAIFMT_I2S | | ||
57 | SND_SOC_DAIFMT_NB_NF | | ||
58 | SND_SOC_DAIFMT_CBM_CFM; | ||
59 | break; | ||
60 | case 4: /* Four channel TDM mode */ | ||
61 | fmt = SND_SOC_DAIFMT_DSP_A | | ||
62 | SND_SOC_DAIFMT_IB_NF | | ||
63 | SND_SOC_DAIFMT_CBM_CFM; | ||
64 | break; | ||
65 | default: | ||
66 | return -EINVAL; | ||
67 | } | ||
68 | |||
69 | /* Set codec DAI configuration */ | ||
70 | ret = snd_soc_dai_set_fmt(codec_dai, fmt); | ||
71 | if (ret < 0) { | ||
72 | dev_err(card->dev, "can't set codec DAI configuration\n"); | ||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | /* Set cpu DAI configuration */ | ||
77 | ret = snd_soc_dai_set_fmt(cpu_dai, fmt); | ||
78 | if (ret < 0) { | ||
79 | dev_err(card->dev, "can't set cpu DAI configuration\n"); | ||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static struct snd_soc_ops omap_twl4030_ops = { | ||
87 | .hw_params = omap_twl4030_hw_params, | ||
88 | }; | ||
89 | |||
90 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
91 | static struct snd_soc_dai_link omap_twl4030_dai_links[] = { | ||
92 | { | ||
93 | .name = "TWL4030", | ||
94 | .stream_name = "TWL4030", | ||
95 | .cpu_dai_name = "omap-mcbsp.2", | ||
96 | .codec_dai_name = "twl4030-hifi", | ||
97 | .platform_name = "omap-pcm-audio", | ||
98 | .codec_name = "twl4030-codec", | ||
99 | .ops = &omap_twl4030_ops, | ||
100 | }, | ||
101 | }; | ||
102 | |||
103 | /* Audio machine driver */ | ||
104 | static struct snd_soc_card omap_twl4030_card = { | ||
105 | .owner = THIS_MODULE, | ||
106 | .dai_link = omap_twl4030_dai_links, | ||
107 | .num_links = ARRAY_SIZE(omap_twl4030_dai_links), | ||
108 | }; | ||
109 | |||
110 | static __devinit int omap_twl4030_probe(struct platform_device *pdev) | ||
111 | { | ||
112 | struct omap_tw4030_pdata *pdata = dev_get_platdata(&pdev->dev); | ||
113 | struct device_node *node = pdev->dev.of_node; | ||
114 | struct snd_soc_card *card = &omap_twl4030_card; | ||
115 | int ret = 0; | ||
116 | |||
117 | card->dev = &pdev->dev; | ||
118 | |||
119 | if (node) { | ||
120 | struct device_node *dai_node; | ||
121 | |||
122 | if (snd_soc_of_parse_card_name(card, "ti,model")) { | ||
123 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
124 | return -ENODEV; | ||
125 | } | ||
126 | |||
127 | dai_node = of_parse_phandle(node, "ti,mcbsp", 0); | ||
128 | if (!dai_node) { | ||
129 | dev_err(&pdev->dev, "McBSP node is not provided\n"); | ||
130 | return -EINVAL; | ||
131 | } | ||
132 | omap_twl4030_dai_links[0].cpu_dai_name = NULL; | ||
133 | omap_twl4030_dai_links[0].cpu_of_node = dai_node; | ||
134 | |||
135 | } else if (pdata) { | ||
136 | if (pdata->card_name) { | ||
137 | card->name = pdata->card_name; | ||
138 | } else { | ||
139 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
140 | return -ENODEV; | ||
141 | } | ||
142 | } else { | ||
143 | dev_err(&pdev->dev, "Missing pdata\n"); | ||
144 | return -ENODEV; | ||
145 | } | ||
146 | |||
147 | ret = snd_soc_register_card(card); | ||
148 | if (ret) { | ||
149 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
150 | ret); | ||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static int __devexit omap_twl4030_remove(struct platform_device *pdev) | ||
158 | { | ||
159 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
160 | |||
161 | snd_soc_unregister_card(card); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static const struct of_device_id omap_twl4030_of_match[] = { | ||
167 | {.compatible = "ti,omap-twl4030", }, | ||
168 | { }, | ||
169 | }; | ||
170 | MODULE_DEVICE_TABLE(of, omap_twl4030_of_match); | ||
171 | |||
172 | static struct platform_driver omap_twl4030_driver = { | ||
173 | .driver = { | ||
174 | .name = "omap-twl4030", | ||
175 | .owner = THIS_MODULE, | ||
176 | .pm = &snd_soc_pm_ops, | ||
177 | .of_match_table = omap_twl4030_of_match, | ||
178 | }, | ||
179 | .probe = omap_twl4030_probe, | ||
180 | .remove = __devexit_p(omap_twl4030_remove), | ||
181 | }; | ||
182 | |||
183 | module_platform_driver(omap_twl4030_driver); | ||
184 | |||
185 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | ||
186 | MODULE_DESCRIPTION("ALSA SoC for TI SoC based boards with twl4030 codec"); | ||
187 | MODULE_LICENSE("GPL"); | ||
188 | MODULE_ALIAS("platform:omap-twl4030"); | ||
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c deleted file mode 100644 index 2830dfd05661..000000000000 --- a/sound/soc/omap/omap3beagle.c +++ /dev/null | |||
@@ -1,150 +0,0 @@ | |||
1 | /* | ||
2 | * omap3beagle.c -- SoC audio for OMAP3 Beagle | ||
3 | * | ||
4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
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/clk.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <sound/core.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/soc.h> | ||
28 | |||
29 | #include <asm/mach-types.h> | ||
30 | #include <mach/hardware.h> | ||
31 | #include <mach/gpio.h> | ||
32 | #include <plat/mcbsp.h> | ||
33 | |||
34 | #include "omap-mcbsp.h" | ||
35 | #include "omap-pcm.h" | ||
36 | |||
37 | static int omap3beagle_hw_params(struct snd_pcm_substream *substream, | ||
38 | struct snd_pcm_hw_params *params) | ||
39 | { | ||
40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
43 | unsigned int fmt; | ||
44 | int ret; | ||
45 | |||
46 | switch (params_channels(params)) { | ||
47 | case 2: /* Stereo I2S mode */ | ||
48 | fmt = SND_SOC_DAIFMT_I2S | | ||
49 | SND_SOC_DAIFMT_NB_NF | | ||
50 | SND_SOC_DAIFMT_CBM_CFM; | ||
51 | break; | ||
52 | case 4: /* Four channel TDM mode */ | ||
53 | fmt = SND_SOC_DAIFMT_DSP_A | | ||
54 | SND_SOC_DAIFMT_IB_NF | | ||
55 | SND_SOC_DAIFMT_CBM_CFM; | ||
56 | break; | ||
57 | default: | ||
58 | return -EINVAL; | ||
59 | } | ||
60 | |||
61 | /* Set codec DAI configuration */ | ||
62 | ret = snd_soc_dai_set_fmt(codec_dai, fmt); | ||
63 | if (ret < 0) { | ||
64 | printk(KERN_ERR "can't set codec DAI configuration\n"); | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | /* Set cpu DAI configuration */ | ||
69 | ret = snd_soc_dai_set_fmt(cpu_dai, fmt); | ||
70 | if (ret < 0) { | ||
71 | printk(KERN_ERR "can't set cpu DAI configuration\n"); | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | /* Set the codec system clock for DAC and ADC */ | ||
76 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
77 | SND_SOC_CLOCK_IN); | ||
78 | if (ret < 0) { | ||
79 | printk(KERN_ERR "can't set codec system clock\n"); | ||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static struct snd_soc_ops omap3beagle_ops = { | ||
87 | .hw_params = omap3beagle_hw_params, | ||
88 | }; | ||
89 | |||
90 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
91 | static struct snd_soc_dai_link omap3beagle_dai = { | ||
92 | .name = "TWL4030", | ||
93 | .stream_name = "TWL4030", | ||
94 | .cpu_dai_name = "omap-mcbsp.2", | ||
95 | .platform_name = "omap-pcm-audio", | ||
96 | .codec_dai_name = "twl4030-hifi", | ||
97 | .codec_name = "twl4030-codec", | ||
98 | .ops = &omap3beagle_ops, | ||
99 | }; | ||
100 | |||
101 | /* Audio machine driver */ | ||
102 | static struct snd_soc_card snd_soc_omap3beagle = { | ||
103 | .name = "omap3beagle", | ||
104 | .owner = THIS_MODULE, | ||
105 | .dai_link = &omap3beagle_dai, | ||
106 | .num_links = 1, | ||
107 | }; | ||
108 | |||
109 | static struct platform_device *omap3beagle_snd_device; | ||
110 | |||
111 | static int __init omap3beagle_soc_init(void) | ||
112 | { | ||
113 | int ret; | ||
114 | |||
115 | if (!(machine_is_omap3_beagle() || machine_is_devkit8000())) | ||
116 | return -ENODEV; | ||
117 | pr_info("OMAP3 Beagle/Devkit8000 SoC init\n"); | ||
118 | |||
119 | omap3beagle_snd_device = platform_device_alloc("soc-audio", -1); | ||
120 | if (!omap3beagle_snd_device) { | ||
121 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
122 | return -ENOMEM; | ||
123 | } | ||
124 | |||
125 | platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle); | ||
126 | |||
127 | ret = platform_device_add(omap3beagle_snd_device); | ||
128 | if (ret) | ||
129 | goto err1; | ||
130 | |||
131 | return 0; | ||
132 | |||
133 | err1: | ||
134 | printk(KERN_ERR "Unable to add platform device\n"); | ||
135 | platform_device_put(omap3beagle_snd_device); | ||
136 | |||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | static void __exit omap3beagle_soc_exit(void) | ||
141 | { | ||
142 | platform_device_unregister(omap3beagle_snd_device); | ||
143 | } | ||
144 | |||
145 | module_init(omap3beagle_soc_init); | ||
146 | module_exit(omap3beagle_soc_exit); | ||
147 | |||
148 | MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>"); | ||
149 | MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle"); | ||
150 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c deleted file mode 100644 index 3d468c9179d7..000000000000 --- a/sound/soc/omap/omap3evm.c +++ /dev/null | |||
@@ -1,118 +0,0 @@ | |||
1 | /* | ||
2 | * omap3evm.c -- ALSA SoC support for OMAP3 EVM | ||
3 | * | ||
4 | * Author: Anuj Aggarwal <anuj.aggarwal@ti.com> | ||
5 | * | ||
6 | * Based on sound/soc/omap/beagle.c by Steve Sakoman | ||
7 | * | ||
8 | * Copyright (C) 2008 Texas Instruments, Incorporated | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation version 2. | ||
13 | * | ||
14 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, | ||
15 | * whether express or implied; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | */ | ||
19 | |||
20 | #include <linux/clk.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/soc.h> | ||
26 | |||
27 | #include <asm/mach-types.h> | ||
28 | #include <mach/hardware.h> | ||
29 | #include <mach/gpio.h> | ||
30 | #include <plat/mcbsp.h> | ||
31 | |||
32 | #include "omap-mcbsp.h" | ||
33 | #include "omap-pcm.h" | ||
34 | |||
35 | static int omap3evm_hw_params(struct snd_pcm_substream *substream, | ||
36 | struct snd_pcm_hw_params *params) | ||
37 | { | ||
38 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
39 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
40 | int ret; | ||
41 | |||
42 | /* Set the codec system clock for DAC and ADC */ | ||
43 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
44 | SND_SOC_CLOCK_IN); | ||
45 | if (ret < 0) { | ||
46 | printk(KERN_ERR "Can't set codec system clock\n"); | ||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static struct snd_soc_ops omap3evm_ops = { | ||
54 | .hw_params = omap3evm_hw_params, | ||
55 | }; | ||
56 | |||
57 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
58 | static struct snd_soc_dai_link omap3evm_dai = { | ||
59 | .name = "TWL4030", | ||
60 | .stream_name = "TWL4030", | ||
61 | .cpu_dai_name = "omap-mcbsp.2", | ||
62 | .codec_dai_name = "twl4030-hifi", | ||
63 | .platform_name = "omap-pcm-audio", | ||
64 | .codec_name = "twl4030-codec", | ||
65 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
66 | SND_SOC_DAIFMT_CBM_CFM, | ||
67 | .ops = &omap3evm_ops, | ||
68 | }; | ||
69 | |||
70 | /* Audio machine driver */ | ||
71 | static struct snd_soc_card snd_soc_omap3evm = { | ||
72 | .name = "omap3evm", | ||
73 | .owner = THIS_MODULE, | ||
74 | .dai_link = &omap3evm_dai, | ||
75 | .num_links = 1, | ||
76 | }; | ||
77 | |||
78 | static struct platform_device *omap3evm_snd_device; | ||
79 | |||
80 | static int __init omap3evm_soc_init(void) | ||
81 | { | ||
82 | int ret; | ||
83 | |||
84 | if (!machine_is_omap3evm()) | ||
85 | return -ENODEV; | ||
86 | pr_info("OMAP3 EVM SoC init\n"); | ||
87 | |||
88 | omap3evm_snd_device = platform_device_alloc("soc-audio", -1); | ||
89 | if (!omap3evm_snd_device) { | ||
90 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
91 | return -ENOMEM; | ||
92 | } | ||
93 | |||
94 | platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm); | ||
95 | ret = platform_device_add(omap3evm_snd_device); | ||
96 | if (ret) | ||
97 | goto err1; | ||
98 | |||
99 | return 0; | ||
100 | |||
101 | err1: | ||
102 | printk(KERN_ERR "Unable to add platform device\n"); | ||
103 | platform_device_put(omap3evm_snd_device); | ||
104 | |||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | static void __exit omap3evm_soc_exit(void) | ||
109 | { | ||
110 | platform_device_unregister(omap3evm_snd_device); | ||
111 | } | ||
112 | |||
113 | module_init(omap3evm_soc_init); | ||
114 | module_exit(omap3evm_soc_exit); | ||
115 | |||
116 | MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>"); | ||
117 | MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM"); | ||
118 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c deleted file mode 100644 index 6ac3e0c3c282..000000000000 --- a/sound/soc/omap/overo.c +++ /dev/null | |||
@@ -1,122 +0,0 @@ | |||
1 | /* | ||
2 | * overo.c -- SoC audio for Gumstix Overo | ||
3 | * | ||
4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
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/clk.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <sound/core.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/soc.h> | ||
28 | |||
29 | #include <asm/mach-types.h> | ||
30 | #include <mach/hardware.h> | ||
31 | #include <mach/gpio.h> | ||
32 | #include <plat/mcbsp.h> | ||
33 | |||
34 | #include "omap-mcbsp.h" | ||
35 | #include "omap-pcm.h" | ||
36 | |||
37 | static int overo_hw_params(struct snd_pcm_substream *substream, | ||
38 | struct snd_pcm_hw_params *params) | ||
39 | { | ||
40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
42 | int ret; | ||
43 | |||
44 | /* Set the codec system clock for DAC and ADC */ | ||
45 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
46 | SND_SOC_CLOCK_IN); | ||
47 | if (ret < 0) { | ||
48 | printk(KERN_ERR "can't set codec system clock\n"); | ||
49 | return ret; | ||
50 | } | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static struct snd_soc_ops overo_ops = { | ||
56 | .hw_params = overo_hw_params, | ||
57 | }; | ||
58 | |||
59 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
60 | static struct snd_soc_dai_link overo_dai = { | ||
61 | .name = "TWL4030", | ||
62 | .stream_name = "TWL4030", | ||
63 | .cpu_dai_name = "omap-mcbsp.2", | ||
64 | .codec_dai_name = "twl4030-hifi", | ||
65 | .platform_name = "omap-pcm-audio", | ||
66 | .codec_name = "twl4030-codec", | ||
67 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
68 | SND_SOC_DAIFMT_CBM_CFM, | ||
69 | .ops = &overo_ops, | ||
70 | }; | ||
71 | |||
72 | /* Audio machine driver */ | ||
73 | static struct snd_soc_card snd_soc_card_overo = { | ||
74 | .name = "overo", | ||
75 | .owner = THIS_MODULE, | ||
76 | .dai_link = &overo_dai, | ||
77 | .num_links = 1, | ||
78 | }; | ||
79 | |||
80 | static struct platform_device *overo_snd_device; | ||
81 | |||
82 | static int __init overo_soc_init(void) | ||
83 | { | ||
84 | int ret; | ||
85 | |||
86 | if (!(machine_is_overo() || machine_is_cm_t35())) { | ||
87 | pr_debug("Incomatible machine!\n"); | ||
88 | return -ENODEV; | ||
89 | } | ||
90 | printk(KERN_INFO "overo SoC init\n"); | ||
91 | |||
92 | overo_snd_device = platform_device_alloc("soc-audio", -1); | ||
93 | if (!overo_snd_device) { | ||
94 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
95 | return -ENOMEM; | ||
96 | } | ||
97 | |||
98 | platform_set_drvdata(overo_snd_device, &snd_soc_card_overo); | ||
99 | |||
100 | ret = platform_device_add(overo_snd_device); | ||
101 | if (ret) | ||
102 | goto err1; | ||
103 | |||
104 | return 0; | ||
105 | |||
106 | err1: | ||
107 | printk(KERN_ERR "Unable to add platform device\n"); | ||
108 | platform_device_put(overo_snd_device); | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | module_init(overo_soc_init); | ||
113 | |||
114 | static void __exit overo_soc_exit(void) | ||
115 | { | ||
116 | platform_device_unregister(overo_snd_device); | ||
117 | } | ||
118 | module_exit(overo_soc_exit); | ||
119 | |||
120 | MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>"); | ||
121 | MODULE_DESCRIPTION("ALSA SoC overo"); | ||
122 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 920e0d9e03db..df97a4196cd3 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c | |||
@@ -191,9 +191,6 @@ static int __init zoom2_soc_init(void) | |||
191 | BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0); | 191 | BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0); |
192 | gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0); | 192 | gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0); |
193 | 193 | ||
194 | BUG_ON(gpio_request(ZOOM2_HEADSET_EXTMUTE_GPIO, "ext_mute") < 0); | ||
195 | gpio_direction_output(ZOOM2_HEADSET_EXTMUTE_GPIO, 0); | ||
196 | |||
197 | return 0; | 194 | return 0; |
198 | 195 | ||
199 | err1: | 196 | err1: |
@@ -207,7 +204,6 @@ module_init(zoom2_soc_init); | |||
207 | static void __exit zoom2_soc_exit(void) | 204 | static void __exit zoom2_soc_exit(void) |
208 | { | 205 | { |
209 | gpio_free(ZOOM2_HEADSET_MUX_GPIO); | 206 | gpio_free(ZOOM2_HEADSET_MUX_GPIO); |
210 | gpio_free(ZOOM2_HEADSET_EXTMUTE_GPIO); | ||
211 | 207 | ||
212 | platform_device_unregister(zoom2_snd_device); | 208 | platform_device_unregister(zoom2_snd_device); |
213 | } | 209 | } |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index fe3995ce9b38..e7b83179aca2 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config SND_SOC_SAMSUNG | 1 | config SND_SOC_SAMSUNG |
2 | tristate "ASoC support for Samsung" | 2 | tristate "ASoC support for Samsung" |
3 | depends on ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5P64X0 || ARCH_EXYNOS4 | 3 | depends on PLAT_SAMSUNG |
4 | select S3C64XX_DMA if ARCH_S3C64XX | 4 | select S3C64XX_DMA if ARCH_S3C64XX |
5 | select S3C2410_DMA if ARCH_S3C24XX | 5 | select S3C2410_DMA if ARCH_S3C24XX |
6 | help | 6 | help |
@@ -191,6 +191,7 @@ config SND_SOC_SPEYSIDE | |||
191 | select SND_SAMSUNG_I2S | 191 | select SND_SAMSUNG_I2S |
192 | select SND_SOC_WM8996 | 192 | select SND_SOC_WM8996 |
193 | select SND_SOC_WM9081 | 193 | select SND_SOC_WM9081 |
194 | select SND_SOC_WM0010 | ||
194 | select SND_SOC_WM1250_EV1 | 195 | select SND_SOC_WM1250_EV1 |
195 | 196 | ||
196 | config SND_SOC_TOBERMORY | 197 | config SND_SOC_TOBERMORY |
@@ -199,6 +200,14 @@ config SND_SOC_TOBERMORY | |||
199 | select SND_SAMSUNG_I2S | 200 | select SND_SAMSUNG_I2S |
200 | select SND_SOC_WM8962 | 201 | select SND_SOC_WM8962 |
201 | 202 | ||
203 | config SND_SOC_BELLS | ||
204 | tristate "Audio support for Wolfson Bells" | ||
205 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 | ||
206 | select SND_SAMSUNG_I2S | ||
207 | select SND_SOC_WM5102 | ||
208 | select SND_SOC_WM5110 | ||
209 | select SND_SOC_WM9081 | ||
210 | |||
202 | config SND_SOC_LOWLAND | 211 | config SND_SOC_LOWLAND |
203 | tristate "Audio support for Wolfson Lowland" | 212 | tristate "Audio support for Wolfson Lowland" |
204 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 | 213 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 |
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 9d03beb40c86..709f6059ad67 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -42,6 +42,7 @@ snd-soc-speyside-objs := speyside.o | |||
42 | snd-soc-tobermory-objs := tobermory.o | 42 | snd-soc-tobermory-objs := tobermory.o |
43 | snd-soc-lowland-objs := lowland.o | 43 | snd-soc-lowland-objs := lowland.o |
44 | snd-soc-littlemill-objs := littlemill.o | 44 | snd-soc-littlemill-objs := littlemill.o |
45 | snd-soc-bells-objs := bells.o | ||
45 | 46 | ||
46 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o | 47 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o |
47 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 48 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
@@ -65,3 +66,4 @@ obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o | |||
65 | obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o | 66 | obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o |
66 | obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o | 67 | obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o |
67 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o | 68 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o |
69 | obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o | ||
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c new file mode 100644 index 000000000000..5dc10dfc0d42 --- /dev/null +++ b/sound/soc/samsung/bells.c | |||
@@ -0,0 +1,346 @@ | |||
1 | /* | ||
2 | * Bells audio support | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <sound/soc.h> | ||
13 | #include <sound/soc-dapm.h> | ||
14 | #include <sound/jack.h> | ||
15 | #include <linux/gpio.h> | ||
16 | #include <linux/module.h> | ||
17 | |||
18 | #include "../codecs/wm5102.h" | ||
19 | #include "../codecs/wm9081.h" | ||
20 | |||
21 | /* | ||
22 | * 44.1kHz based clocks for the SYSCLK domain, use a very high clock | ||
23 | * to allow all the DSP functionality to be enabled if desired. | ||
24 | */ | ||
25 | #define SYSCLK_RATE (44100 * 1024) | ||
26 | |||
27 | /* 48kHz based clocks for the ASYNC domain */ | ||
28 | #define ASYNCCLK_RATE (48000 * 512) | ||
29 | |||
30 | /* BCLK2 is fixed at this currently */ | ||
31 | #define BCLK2_RATE (64 * 8000) | ||
32 | |||
33 | /* | ||
34 | * Expect a 24.576MHz crystal if one is fitted (the driver will function | ||
35 | * if this is not fitted). | ||
36 | */ | ||
37 | #define MCLK_RATE 24576000 | ||
38 | |||
39 | #define WM9081_AUDIO_RATE 44100 | ||
40 | #define WM9081_MCLK_RATE (WM9081_AUDIO_RATE * 256) | ||
41 | |||
42 | static int bells_set_bias_level(struct snd_soc_card *card, | ||
43 | struct snd_soc_dapm_context *dapm, | ||
44 | enum snd_soc_bias_level level) | ||
45 | { | ||
46 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
47 | struct snd_soc_codec *codec = codec_dai->codec; | ||
48 | int ret; | ||
49 | |||
50 | if (dapm->dev != codec_dai->dev) | ||
51 | return 0; | ||
52 | |||
53 | switch (level) { | ||
54 | case SND_SOC_BIAS_PREPARE: | ||
55 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { | ||
56 | ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, | ||
57 | ARIZONA_FLL_SRC_MCLK1, | ||
58 | MCLK_RATE, | ||
59 | SYSCLK_RATE); | ||
60 | if (ret < 0) | ||
61 | pr_err("Failed to start FLL: %d\n", ret); | ||
62 | |||
63 | ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, | ||
64 | ARIZONA_FLL_SRC_AIF2BCLK, | ||
65 | BCLK2_RATE, | ||
66 | ASYNCCLK_RATE); | ||
67 | if (ret < 0) | ||
68 | pr_err("Failed to start FLL: %d\n", ret); | ||
69 | } | ||
70 | break; | ||
71 | |||
72 | default: | ||
73 | break; | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int bells_set_bias_level_post(struct snd_soc_card *card, | ||
80 | struct snd_soc_dapm_context *dapm, | ||
81 | enum snd_soc_bias_level level) | ||
82 | { | ||
83 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
84 | struct snd_soc_codec *codec = codec_dai->codec; | ||
85 | int ret; | ||
86 | |||
87 | if (dapm->dev != codec_dai->dev) | ||
88 | return 0; | ||
89 | |||
90 | switch (level) { | ||
91 | case SND_SOC_BIAS_STANDBY: | ||
92 | ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, 0, 0, 0); | ||
93 | if (ret < 0) { | ||
94 | pr_err("Failed to stop FLL: %d\n", ret); | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 0, 0, 0); | ||
99 | if (ret < 0) { | ||
100 | pr_err("Failed to stop FLL: %d\n", ret); | ||
101 | return ret; | ||
102 | } | ||
103 | break; | ||
104 | |||
105 | default: | ||
106 | break; | ||
107 | } | ||
108 | |||
109 | dapm->bias_level = level; | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int bells_late_probe(struct snd_soc_card *card) | ||
115 | { | ||
116 | struct snd_soc_codec *codec = card->rtd[0].codec; | ||
117 | struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai; | ||
118 | struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai; | ||
119 | struct snd_soc_dai *aif3_dai = card->rtd[2].cpu_dai; | ||
120 | struct snd_soc_dai *wm9081_dai = card->rtd[2].codec_dai; | ||
121 | int ret; | ||
122 | |||
123 | ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0); | ||
124 | if (ret != 0) { | ||
125 | dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); | ||
126 | return ret; | ||
127 | } | ||
128 | |||
129 | ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0); | ||
130 | if (ret != 0) { | ||
131 | dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret); | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0); | ||
136 | if (ret != 0) { | ||
137 | dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK, | ||
142 | ARIZONA_CLK_SRC_FLL1, SYSCLK_RATE, | ||
143 | SND_SOC_CLOCK_IN); | ||
144 | if (ret != 0) { | ||
145 | dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); | ||
146 | return ret; | ||
147 | } | ||
148 | |||
149 | ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0, | ||
150 | WM9081_MCLK_RATE, SND_SOC_CLOCK_OUT); | ||
151 | if (ret != 0) { | ||
152 | dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret); | ||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK, | ||
157 | ARIZONA_CLK_SRC_FLL2, ASYNCCLK_RATE, | ||
158 | SND_SOC_CLOCK_IN); | ||
159 | if (ret != 0) { | ||
160 | dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | ret = snd_soc_codec_set_sysclk(wm9081_dai->codec, WM9081_SYSCLK_MCLK, | ||
165 | 0, WM9081_MCLK_RATE, 0); | ||
166 | if (ret != 0) { | ||
167 | dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static const struct snd_soc_pcm_stream baseband_params = { | ||
175 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
176 | .rate_min = 8000, | ||
177 | .rate_max = 8000, | ||
178 | .channels_min = 2, | ||
179 | .channels_max = 2, | ||
180 | }; | ||
181 | |||
182 | static const struct snd_soc_pcm_stream sub_params = { | ||
183 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
184 | .rate_min = WM9081_AUDIO_RATE, | ||
185 | .rate_max = WM9081_AUDIO_RATE, | ||
186 | .channels_min = 2, | ||
187 | .channels_max = 2, | ||
188 | }; | ||
189 | |||
190 | static struct snd_soc_dai_link bells_dai_wm5102[] = { | ||
191 | { | ||
192 | .name = "CPU", | ||
193 | .stream_name = "CPU", | ||
194 | .cpu_dai_name = "samsung-i2s.0", | ||
195 | .codec_dai_name = "wm5102-aif1", | ||
196 | .platform_name = "samsung-audio", | ||
197 | .codec_name = "wm5102-codec", | ||
198 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
199 | | SND_SOC_DAIFMT_CBM_CFM, | ||
200 | }, | ||
201 | { | ||
202 | .name = "Baseband", | ||
203 | .stream_name = "Baseband", | ||
204 | .cpu_dai_name = "wm5102-aif2", | ||
205 | .codec_dai_name = "wm1250-ev1", | ||
206 | .codec_name = "wm1250-ev1.1-0027", | ||
207 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
208 | | SND_SOC_DAIFMT_CBM_CFM, | ||
209 | .ignore_suspend = 1, | ||
210 | .params = &baseband_params, | ||
211 | }, | ||
212 | { | ||
213 | .name = "Sub", | ||
214 | .stream_name = "Sub", | ||
215 | .cpu_dai_name = "wm5102-aif3", | ||
216 | .codec_dai_name = "wm9081-hifi", | ||
217 | .codec_name = "wm9081.1-006c", | ||
218 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
219 | | SND_SOC_DAIFMT_CBS_CFS, | ||
220 | .ignore_suspend = 1, | ||
221 | .params = &sub_params, | ||
222 | }, | ||
223 | }; | ||
224 | |||
225 | static struct snd_soc_dai_link bells_dai_wm5110[] = { | ||
226 | { | ||
227 | .name = "CPU", | ||
228 | .stream_name = "CPU", | ||
229 | .cpu_dai_name = "samsung-i2s.0", | ||
230 | .codec_dai_name = "wm5110-aif1", | ||
231 | .platform_name = "samsung-audio", | ||
232 | .codec_name = "wm5110-codec", | ||
233 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
234 | | SND_SOC_DAIFMT_CBM_CFM, | ||
235 | }, | ||
236 | { | ||
237 | .name = "Baseband", | ||
238 | .stream_name = "Baseband", | ||
239 | .cpu_dai_name = "wm5110-aif2", | ||
240 | .codec_dai_name = "wm1250-ev1", | ||
241 | .codec_name = "wm1250-ev1.1-0027", | ||
242 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
243 | | SND_SOC_DAIFMT_CBM_CFM, | ||
244 | .ignore_suspend = 1, | ||
245 | .params = &baseband_params, | ||
246 | }, | ||
247 | { | ||
248 | .name = "Sub", | ||
249 | .stream_name = "Sub", | ||
250 | .cpu_dai_name = "wm5102-aif3", | ||
251 | .codec_dai_name = "wm9081-hifi", | ||
252 | .codec_name = "wm9081.1-006c", | ||
253 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
254 | | SND_SOC_DAIFMT_CBS_CFS, | ||
255 | .ignore_suspend = 1, | ||
256 | .params = &sub_params, | ||
257 | }, | ||
258 | }; | ||
259 | |||
260 | static struct snd_soc_codec_conf bells_codec_conf[] = { | ||
261 | { | ||
262 | .dev_name = "wm9081.1-006c", | ||
263 | .name_prefix = "Sub", | ||
264 | }, | ||
265 | }; | ||
266 | |||
267 | static struct snd_soc_dapm_route bells_routes[] = { | ||
268 | { "Sub CLK_SYS", NULL, "OPCLK" }, | ||
269 | }; | ||
270 | |||
271 | static struct snd_soc_card bells_cards[] = { | ||
272 | { | ||
273 | .name = "Bells WM5102", | ||
274 | .owner = THIS_MODULE, | ||
275 | .dai_link = bells_dai_wm5102, | ||
276 | .num_links = ARRAY_SIZE(bells_dai_wm5102), | ||
277 | .codec_conf = bells_codec_conf, | ||
278 | .num_configs = ARRAY_SIZE(bells_codec_conf), | ||
279 | |||
280 | .late_probe = bells_late_probe, | ||
281 | |||
282 | .dapm_routes = bells_routes, | ||
283 | .num_dapm_routes = ARRAY_SIZE(bells_routes), | ||
284 | |||
285 | .set_bias_level = bells_set_bias_level, | ||
286 | .set_bias_level_post = bells_set_bias_level_post, | ||
287 | }, | ||
288 | { | ||
289 | .name = "Bells WM5110", | ||
290 | .owner = THIS_MODULE, | ||
291 | .dai_link = bells_dai_wm5110, | ||
292 | .num_links = ARRAY_SIZE(bells_dai_wm5110), | ||
293 | .codec_conf = bells_codec_conf, | ||
294 | .num_configs = ARRAY_SIZE(bells_codec_conf), | ||
295 | |||
296 | .late_probe = bells_late_probe, | ||
297 | |||
298 | .dapm_routes = bells_routes, | ||
299 | .num_dapm_routes = ARRAY_SIZE(bells_routes), | ||
300 | |||
301 | .set_bias_level = bells_set_bias_level, | ||
302 | .set_bias_level_post = bells_set_bias_level_post, | ||
303 | }, | ||
304 | }; | ||
305 | |||
306 | |||
307 | static __devinit int bells_probe(struct platform_device *pdev) | ||
308 | { | ||
309 | int ret; | ||
310 | |||
311 | bells_cards[pdev->id].dev = &pdev->dev; | ||
312 | |||
313 | ret = snd_soc_register_card(&bells_cards[pdev->id]); | ||
314 | if (ret) { | ||
315 | dev_err(&pdev->dev, | ||
316 | "snd_soc_register_card(%s) failed: %d\n", | ||
317 | bells_cards[pdev->id].name, ret); | ||
318 | return ret; | ||
319 | } | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int __devexit bells_remove(struct platform_device *pdev) | ||
325 | { | ||
326 | snd_soc_unregister_card(&bells_cards[pdev->id]); | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static struct platform_driver bells_driver = { | ||
332 | .driver = { | ||
333 | .name = "bells", | ||
334 | .owner = THIS_MODULE, | ||
335 | .pm = &snd_soc_pm_ops, | ||
336 | }, | ||
337 | .probe = bells_probe, | ||
338 | .remove = __devexit_p(bells_remove), | ||
339 | }; | ||
340 | |||
341 | module_platform_driver(bells_driver); | ||
342 | |||
343 | MODULE_DESCRIPTION("Bells audio support"); | ||
344 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
345 | MODULE_LICENSE("GPL"); | ||
346 | MODULE_ALIAS("platform:bells"); | ||
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index a4a9fc7e8c76..c7e1c28528a4 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c | |||
@@ -25,7 +25,7 @@ static int speyside_set_bias_level(struct snd_soc_card *card, | |||
25 | struct snd_soc_dapm_context *dapm, | 25 | struct snd_soc_dapm_context *dapm, |
26 | enum snd_soc_bias_level level) | 26 | enum snd_soc_bias_level level) |
27 | { | 27 | { |
28 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | 28 | struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai; |
29 | int ret; | 29 | int ret; |
30 | 30 | ||
31 | if (dapm->dev != codec_dai->dev) | 31 | if (dapm->dev != codec_dai->dev) |
@@ -57,7 +57,7 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card, | |||
57 | struct snd_soc_dapm_context *dapm, | 57 | struct snd_soc_dapm_context *dapm, |
58 | enum snd_soc_bias_level level) | 58 | enum snd_soc_bias_level level) |
59 | { | 59 | { |
60 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | 60 | struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai; |
61 | int ret; | 61 | int ret; |
62 | 62 | ||
63 | if (dapm->dev != codec_dai->dev) | 63 | if (dapm->dev != codec_dai->dev) |
@@ -126,6 +126,18 @@ static void speyside_set_polarity(struct snd_soc_codec *codec, | |||
126 | snd_soc_dapm_sync(&codec->dapm); | 126 | snd_soc_dapm_sync(&codec->dapm); |
127 | } | 127 | } |
128 | 128 | ||
129 | static int speyside_wm0010_init(struct snd_soc_pcm_runtime *rtd) | ||
130 | { | ||
131 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
132 | int ret; | ||
133 | |||
134 | ret = snd_soc_dai_set_sysclk(dai, 0, MCLK_AUDIO_RATE, 0); | ||
135 | if (ret < 0) | ||
136 | return ret; | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
129 | static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd) | 141 | static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd) |
130 | { | 142 | { |
131 | struct snd_soc_dai *dai = rtd->codec_dai; | 143 | struct snd_soc_dai *dai = rtd->codec_dai; |
@@ -172,17 +184,37 @@ static int speyside_late_probe(struct snd_soc_card *card) | |||
172 | return 0; | 184 | return 0; |
173 | } | 185 | } |
174 | 186 | ||
187 | static const struct snd_soc_pcm_stream dsp_codec_params = { | ||
188 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
189 | .rate_min = 48000, | ||
190 | .rate_max = 48000, | ||
191 | .channels_min = 2, | ||
192 | .channels_max = 2, | ||
193 | }; | ||
194 | |||
175 | static struct snd_soc_dai_link speyside_dai[] = { | 195 | static struct snd_soc_dai_link speyside_dai[] = { |
176 | { | 196 | { |
177 | .name = "CPU", | 197 | .name = "CPU-DSP", |
178 | .stream_name = "CPU", | 198 | .stream_name = "CPU-DSP", |
179 | .cpu_dai_name = "samsung-i2s.0", | 199 | .cpu_dai_name = "samsung-i2s.0", |
180 | .codec_dai_name = "wm8996-aif1", | 200 | .codec_dai_name = "wm0010-sdi1", |
181 | .platform_name = "samsung-audio", | 201 | .platform_name = "samsung-audio", |
202 | .codec_name = "spi0.0", | ||
203 | .init = speyside_wm0010_init, | ||
204 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
205 | | SND_SOC_DAIFMT_CBM_CFM, | ||
206 | }, | ||
207 | { | ||
208 | .name = "DSP-CODEC", | ||
209 | .stream_name = "DSP-CODEC", | ||
210 | .cpu_dai_name = "wm0010-sdi2", | ||
211 | .codec_dai_name = "wm8996-aif1", | ||
182 | .codec_name = "wm8996.1-001a", | 212 | .codec_name = "wm8996.1-001a", |
183 | .init = speyside_wm8996_init, | 213 | .init = speyside_wm8996_init, |
184 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 214 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
185 | | SND_SOC_DAIFMT_CBM_CFM, | 215 | | SND_SOC_DAIFMT_CBM_CFM, |
216 | .params = &dsp_codec_params, | ||
217 | .ignore_suspend = 1, | ||
186 | }, | 218 | }, |
187 | { | 219 | { |
188 | .name = "Baseband", | 220 | .name = "Baseband", |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 0540408a9fa9..5328ae5539f1 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -1655,22 +1655,20 @@ static int fsi_probe(struct platform_device *pdev) | |||
1655 | irq = platform_get_irq(pdev, 0); | 1655 | irq = platform_get_irq(pdev, 0); |
1656 | if (!res || (int)irq <= 0) { | 1656 | if (!res || (int)irq <= 0) { |
1657 | dev_err(&pdev->dev, "Not enough FSI platform resources.\n"); | 1657 | dev_err(&pdev->dev, "Not enough FSI platform resources.\n"); |
1658 | ret = -ENODEV; | 1658 | return -ENODEV; |
1659 | goto exit; | ||
1660 | } | 1659 | } |
1661 | 1660 | ||
1662 | master = kzalloc(sizeof(*master), GFP_KERNEL); | 1661 | master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); |
1663 | if (!master) { | 1662 | if (!master) { |
1664 | dev_err(&pdev->dev, "Could not allocate master\n"); | 1663 | dev_err(&pdev->dev, "Could not allocate master\n"); |
1665 | ret = -ENOMEM; | 1664 | return -ENOMEM; |
1666 | goto exit; | ||
1667 | } | 1665 | } |
1668 | 1666 | ||
1669 | master->base = ioremap_nocache(res->start, resource_size(res)); | 1667 | master->base = devm_ioremap_nocache(&pdev->dev, |
1668 | res->start, resource_size(res)); | ||
1670 | if (!master->base) { | 1669 | if (!master->base) { |
1671 | ret = -ENXIO; | ||
1672 | dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n"); | 1670 | dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n"); |
1673 | goto exit_kfree; | 1671 | return -ENXIO; |
1674 | } | 1672 | } |
1675 | 1673 | ||
1676 | /* master setting */ | 1674 | /* master setting */ |
@@ -1686,7 +1684,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
1686 | ret = fsi_stream_probe(&master->fsia, &pdev->dev); | 1684 | ret = fsi_stream_probe(&master->fsia, &pdev->dev); |
1687 | if (ret < 0) { | 1685 | if (ret < 0) { |
1688 | dev_err(&pdev->dev, "FSIA stream probe failed\n"); | 1686 | dev_err(&pdev->dev, "FSIA stream probe failed\n"); |
1689 | goto exit_iounmap; | 1687 | return ret; |
1690 | } | 1688 | } |
1691 | 1689 | ||
1692 | /* FSI B setting */ | 1690 | /* FSI B setting */ |
@@ -1730,16 +1728,11 @@ exit_snd_soc: | |||
1730 | exit_free_irq: | 1728 | exit_free_irq: |
1731 | free_irq(irq, master); | 1729 | free_irq(irq, master); |
1732 | exit_fsib: | 1730 | exit_fsib: |
1731 | pm_runtime_disable(&pdev->dev); | ||
1733 | fsi_stream_remove(&master->fsib); | 1732 | fsi_stream_remove(&master->fsib); |
1734 | exit_fsia: | 1733 | exit_fsia: |
1735 | fsi_stream_remove(&master->fsia); | 1734 | fsi_stream_remove(&master->fsia); |
1736 | exit_iounmap: | 1735 | |
1737 | iounmap(master->base); | ||
1738 | pm_runtime_disable(&pdev->dev); | ||
1739 | exit_kfree: | ||
1740 | kfree(master); | ||
1741 | master = NULL; | ||
1742 | exit: | ||
1743 | return ret; | 1736 | return ret; |
1744 | } | 1737 | } |
1745 | 1738 | ||
@@ -1758,9 +1751,6 @@ static int fsi_remove(struct platform_device *pdev) | |||
1758 | fsi_stream_remove(&master->fsia); | 1751 | fsi_stream_remove(&master->fsia); |
1759 | fsi_stream_remove(&master->fsib); | 1752 | fsi_stream_remove(&master->fsib); |
1760 | 1753 | ||
1761 | iounmap(master->base); | ||
1762 | kfree(master); | ||
1763 | |||
1764 | return 0; | 1754 | return 0; |
1765 | } | 1755 | } |
1766 | 1756 | ||
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c new file mode 100644 index 000000000000..967d0e173e1b --- /dev/null +++ b/sound/soc/soc-compress.c | |||
@@ -0,0 +1,294 @@ | |||
1 | /* | ||
2 | * soc-compress.c -- ALSA SoC Compress | ||
3 | * | ||
4 | * Copyright (C) 2012 Intel Corp. | ||
5 | * | ||
6 | * Authors: Namarta Kohli <namartax.kohli@intel.com> | ||
7 | * Ramesh Babu K V <ramesh.babu@linux.intel.com> | ||
8 | * Vinod Koul <vinod.koul@linux.intel.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/compress_params.h> | ||
24 | #include <sound/compress_driver.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/initval.h> | ||
27 | |||
28 | static int soc_compr_open(struct snd_compr_stream *cstream) | ||
29 | { | ||
30 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
31 | struct snd_soc_platform *platform = rtd->platform; | ||
32 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
33 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
34 | int ret = 0; | ||
35 | |||
36 | if (platform->driver->compr_ops && platform->driver->compr_ops->open) { | ||
37 | ret = platform->driver->compr_ops->open(cstream); | ||
38 | if (ret < 0) { | ||
39 | pr_err("compress asoc: can't open platform %s\n", platform->name); | ||
40 | goto out; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) { | ||
45 | ret = rtd->dai_link->compr_ops->startup(cstream); | ||
46 | if (ret < 0) { | ||
47 | pr_err("compress asoc: %s startup failed\n", rtd->dai_link->name); | ||
48 | goto machine_err; | ||
49 | } | ||
50 | } | ||
51 | |||
52 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | ||
53 | cpu_dai->playback_active++; | ||
54 | codec_dai->playback_active++; | ||
55 | } else { | ||
56 | cpu_dai->capture_active++; | ||
57 | codec_dai->capture_active++; | ||
58 | } | ||
59 | |||
60 | cpu_dai->active++; | ||
61 | codec_dai->active++; | ||
62 | rtd->codec->active++; | ||
63 | |||
64 | return 0; | ||
65 | |||
66 | machine_err: | ||
67 | if (platform->driver->compr_ops && platform->driver->compr_ops->free) | ||
68 | platform->driver->compr_ops->free(cstream); | ||
69 | out: | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | static int soc_compr_free(struct snd_compr_stream *cstream) | ||
74 | { | ||
75 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
76 | struct snd_soc_platform *platform = rtd->platform; | ||
77 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
78 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
79 | struct snd_soc_codec *codec = rtd->codec; | ||
80 | |||
81 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | ||
82 | cpu_dai->playback_active--; | ||
83 | codec_dai->playback_active--; | ||
84 | } else { | ||
85 | cpu_dai->capture_active--; | ||
86 | codec_dai->capture_active--; | ||
87 | } | ||
88 | |||
89 | snd_soc_dai_digital_mute(codec_dai, 1); | ||
90 | |||
91 | cpu_dai->active--; | ||
92 | codec_dai->active--; | ||
93 | codec->active--; | ||
94 | |||
95 | if (!cpu_dai->active) | ||
96 | cpu_dai->rate = 0; | ||
97 | |||
98 | if (!codec_dai->active) | ||
99 | codec_dai->rate = 0; | ||
100 | |||
101 | |||
102 | if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown) | ||
103 | rtd->dai_link->compr_ops->shutdown(cstream); | ||
104 | |||
105 | if (platform->driver->compr_ops && platform->driver->compr_ops->free) | ||
106 | platform->driver->compr_ops->free(cstream); | ||
107 | cpu_dai->runtime = NULL; | ||
108 | |||
109 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | ||
110 | if (!rtd->pmdown_time || codec->ignore_pmdown_time || | ||
111 | rtd->dai_link->ignore_pmdown_time) { | ||
112 | snd_soc_dapm_stream_event(rtd, | ||
113 | SNDRV_PCM_STREAM_PLAYBACK, | ||
114 | SND_SOC_DAPM_STREAM_STOP); | ||
115 | } else | ||
116 | codec_dai->pop_wait = 1; | ||
117 | schedule_delayed_work(&rtd->delayed_work, | ||
118 | msecs_to_jiffies(rtd->pmdown_time)); | ||
119 | } else { | ||
120 | /* capture streams can be powered down now */ | ||
121 | snd_soc_dapm_stream_event(rtd, | ||
122 | SNDRV_PCM_STREAM_CAPTURE, | ||
123 | SND_SOC_DAPM_STREAM_STOP); | ||
124 | } | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) | ||
130 | { | ||
131 | |||
132 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
133 | struct snd_soc_platform *platform = rtd->platform; | ||
134 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
135 | int ret = 0; | ||
136 | |||
137 | if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) { | ||
138 | ret = platform->driver->compr_ops->trigger(cstream, cmd); | ||
139 | if (ret < 0) | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | if (cmd == SNDRV_PCM_TRIGGER_START) | ||
144 | snd_soc_dai_digital_mute(codec_dai, 0); | ||
145 | else if (cmd == SNDRV_PCM_TRIGGER_STOP) | ||
146 | snd_soc_dai_digital_mute(codec_dai, 1); | ||
147 | |||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | static int soc_compr_set_params(struct snd_compr_stream *cstream, | ||
152 | struct snd_compr_params *params) | ||
153 | { | ||
154 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
155 | struct snd_soc_platform *platform = rtd->platform; | ||
156 | int ret = 0; | ||
157 | |||
158 | /* first we call set_params for the platform driver | ||
159 | * this should configure the soc side | ||
160 | * if the machine has compressed ops then we call that as well | ||
161 | * expectation is that platform and machine will configure everything | ||
162 | * for this compress path, like configuring pcm port for codec | ||
163 | */ | ||
164 | if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) { | ||
165 | ret = platform->driver->compr_ops->set_params(cstream, params); | ||
166 | if (ret < 0) | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) { | ||
171 | ret = rtd->dai_link->compr_ops->set_params(cstream); | ||
172 | if (ret < 0) | ||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, | ||
177 | SND_SOC_DAPM_STREAM_START); | ||
178 | |||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | static int soc_compr_get_params(struct snd_compr_stream *cstream, | ||
183 | struct snd_codec *params) | ||
184 | { | ||
185 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
186 | struct snd_soc_platform *platform = rtd->platform; | ||
187 | int ret = 0; | ||
188 | |||
189 | if (platform->driver->compr_ops && platform->driver->compr_ops->get_params) | ||
190 | ret = platform->driver->compr_ops->get_params(cstream, params); | ||
191 | |||
192 | return ret; | ||
193 | } | ||
194 | |||
195 | static int soc_compr_get_caps(struct snd_compr_stream *cstream, | ||
196 | struct snd_compr_caps *caps) | ||
197 | { | ||
198 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
199 | struct snd_soc_platform *platform = rtd->platform; | ||
200 | int ret = 0; | ||
201 | |||
202 | if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps) | ||
203 | ret = platform->driver->compr_ops->get_caps(cstream, caps); | ||
204 | |||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, | ||
209 | struct snd_compr_codec_caps *codec) | ||
210 | { | ||
211 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
212 | struct snd_soc_platform *platform = rtd->platform; | ||
213 | int ret = 0; | ||
214 | |||
215 | if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps) | ||
216 | ret = platform->driver->compr_ops->get_codec_caps(cstream, codec); | ||
217 | |||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) | ||
222 | { | ||
223 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
224 | struct snd_soc_platform *platform = rtd->platform; | ||
225 | int ret = 0; | ||
226 | |||
227 | if (platform->driver->compr_ops && platform->driver->compr_ops->ack) | ||
228 | ret = platform->driver->compr_ops->ack(cstream, bytes); | ||
229 | |||
230 | return ret; | ||
231 | } | ||
232 | |||
233 | static int soc_compr_pointer(struct snd_compr_stream *cstream, | ||
234 | struct snd_compr_tstamp *tstamp) | ||
235 | { | ||
236 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
237 | struct snd_soc_platform *platform = rtd->platform; | ||
238 | |||
239 | if (platform->driver->compr_ops && platform->driver->compr_ops->pointer) | ||
240 | platform->driver->compr_ops->pointer(cstream, tstamp); | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | /* ASoC Compress operations */ | ||
246 | static struct snd_compr_ops soc_compr_ops = { | ||
247 | .open = soc_compr_open, | ||
248 | .free = soc_compr_free, | ||
249 | .set_params = soc_compr_set_params, | ||
250 | .get_params = soc_compr_get_params, | ||
251 | .trigger = soc_compr_trigger, | ||
252 | .pointer = soc_compr_pointer, | ||
253 | .ack = soc_compr_ack, | ||
254 | .get_caps = soc_compr_get_caps, | ||
255 | .get_codec_caps = soc_compr_get_codec_caps | ||
256 | }; | ||
257 | |||
258 | /* create a new compress */ | ||
259 | int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) | ||
260 | { | ||
261 | struct snd_soc_codec *codec = rtd->codec; | ||
262 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
263 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
264 | struct snd_compr *compr; | ||
265 | char new_name[64]; | ||
266 | int ret = 0, direction = 0; | ||
267 | |||
268 | /* check client and interface hw capabilities */ | ||
269 | snprintf(new_name, sizeof(new_name), "%s %s-%d", | ||
270 | rtd->dai_link->stream_name, codec_dai->name, num); | ||
271 | direction = SND_COMPRESS_PLAYBACK; | ||
272 | compr = kzalloc(sizeof(*compr), GFP_KERNEL); | ||
273 | if (compr == NULL) { | ||
274 | snd_printk(KERN_ERR "Cannot allocate compr\n"); | ||
275 | return -ENOMEM; | ||
276 | } | ||
277 | |||
278 | compr->ops = &soc_compr_ops; | ||
279 | mutex_init(&compr->lock); | ||
280 | ret = snd_compress_new(rtd->card->snd_card, num, direction, compr); | ||
281 | if (ret < 0) { | ||
282 | pr_err("compress asoc: can't create compress for codec %s\n", | ||
283 | codec->name); | ||
284 | kfree(compr); | ||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | rtd->compr = compr; | ||
289 | compr->private_data = rtd; | ||
290 | |||
291 | printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name, | ||
292 | cpu_dai->name); | ||
293 | return ret; | ||
294 | } | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c501af6d8dbe..9a6daf997319 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -609,6 +609,10 @@ int snd_soc_suspend(struct device *dev) | |||
609 | SND_SOC_DAPM_STREAM_SUSPEND); | 609 | SND_SOC_DAPM_STREAM_SUSPEND); |
610 | } | 610 | } |
611 | 611 | ||
612 | /* Recheck all analogue paths too */ | ||
613 | dapm_mark_io_dirty(&card->dapm); | ||
614 | snd_soc_dapm_sync(&card->dapm); | ||
615 | |||
612 | /* suspend all CODECs */ | 616 | /* suspend all CODECs */ |
613 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { | 617 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { |
614 | /* If there are paths active then the CODEC will be held with | 618 | /* If there are paths active then the CODEC will be held with |
@@ -631,6 +635,8 @@ int snd_soc_suspend(struct device *dev) | |||
631 | codec->driver->suspend(codec); | 635 | codec->driver->suspend(codec); |
632 | codec->suspended = 1; | 636 | codec->suspended = 1; |
633 | codec->cache_sync = 1; | 637 | codec->cache_sync = 1; |
638 | if (codec->using_regmap) | ||
639 | regcache_mark_dirty(codec->control_data); | ||
634 | break; | 640 | break; |
635 | default: | 641 | default: |
636 | dev_dbg(codec->dev, "CODEC is on over suspend\n"); | 642 | dev_dbg(codec->dev, "CODEC is on over suspend\n"); |
@@ -756,6 +762,10 @@ static void soc_resume_deferred(struct work_struct *work) | |||
756 | 762 | ||
757 | /* userspace can access us now we are back as we were before */ | 763 | /* userspace can access us now we are back as we were before */ |
758 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); | 764 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); |
765 | |||
766 | /* Recheck all analogue paths too */ | ||
767 | dapm_mark_io_dirty(&card->dapm); | ||
768 | snd_soc_dapm_sync(&card->dapm); | ||
759 | } | 769 | } |
760 | 770 | ||
761 | /* powers up audio subsystem after a suspend */ | 771 | /* powers up audio subsystem after a suspend */ |
@@ -1388,37 +1398,48 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1388 | if (ret < 0) | 1398 | if (ret < 0) |
1389 | pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret); | 1399 | pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret); |
1390 | 1400 | ||
1391 | if (!dai_link->params) { | 1401 | if (cpu_dai->driver->compress_dai) { |
1392 | /* create the pcm */ | 1402 | /*create compress_device"*/ |
1393 | ret = soc_new_pcm(rtd, num); | 1403 | ret = soc_new_compress(rtd, num); |
1394 | if (ret < 0) { | 1404 | if (ret < 0) { |
1395 | pr_err("asoc: can't create pcm %s :%d\n", | 1405 | pr_err("asoc: can't create compress %s\n", |
1396 | dai_link->stream_name, ret); | 1406 | dai_link->stream_name); |
1397 | return ret; | 1407 | return ret; |
1398 | } | 1408 | } |
1399 | } else { | 1409 | } else { |
1400 | /* link the DAI widgets */ | 1410 | |
1401 | play_w = codec_dai->playback_widget; | 1411 | if (!dai_link->params) { |
1402 | capture_w = cpu_dai->capture_widget; | 1412 | /* create the pcm */ |
1403 | if (play_w && capture_w) { | 1413 | ret = soc_new_pcm(rtd, num); |
1404 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, | 1414 | if (ret < 0) { |
1405 | capture_w, play_w); | 1415 | pr_err("asoc: can't create pcm %s :%d\n", |
1406 | if (ret != 0) { | 1416 | dai_link->stream_name, ret); |
1407 | dev_err(card->dev, "Can't link %s to %s: %d\n", | ||
1408 | play_w->name, capture_w->name, ret); | ||
1409 | return ret; | 1417 | return ret; |
1410 | } | 1418 | } |
1411 | } | 1419 | } else { |
1420 | /* link the DAI widgets */ | ||
1421 | play_w = codec_dai->playback_widget; | ||
1422 | capture_w = cpu_dai->capture_widget; | ||
1423 | if (play_w && capture_w) { | ||
1424 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, | ||
1425 | capture_w, play_w); | ||
1426 | if (ret != 0) { | ||
1427 | dev_err(card->dev, "Can't link %s to %s: %d\n", | ||
1428 | play_w->name, capture_w->name, ret); | ||
1429 | return ret; | ||
1430 | } | ||
1431 | } | ||
1412 | 1432 | ||
1413 | play_w = cpu_dai->playback_widget; | 1433 | play_w = cpu_dai->playback_widget; |
1414 | capture_w = codec_dai->capture_widget; | 1434 | capture_w = codec_dai->capture_widget; |
1415 | if (play_w && capture_w) { | 1435 | if (play_w && capture_w) { |
1416 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, | 1436 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, |
1417 | capture_w, play_w); | 1437 | capture_w, play_w); |
1418 | if (ret != 0) { | 1438 | if (ret != 0) { |
1419 | dev_err(card->dev, "Can't link %s to %s: %d\n", | 1439 | dev_err(card->dev, "Can't link %s to %s: %d\n", |
1420 | play_w->name, capture_w->name, ret); | 1440 | play_w->name, capture_w->name, ret); |
1421 | return ret; | 1441 | return ret; |
1442 | } | ||
1422 | } | 1443 | } |
1423 | } | 1444 | } |
1424 | } | 1445 | } |
@@ -1816,7 +1837,6 @@ base_error: | |||
1816 | static int soc_probe(struct platform_device *pdev) | 1837 | static int soc_probe(struct platform_device *pdev) |
1817 | { | 1838 | { |
1818 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 1839 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
1819 | int ret = 0; | ||
1820 | 1840 | ||
1821 | /* | 1841 | /* |
1822 | * no card, so machine driver should be registering card | 1842 | * no card, so machine driver should be registering card |
@@ -1832,13 +1852,7 @@ static int soc_probe(struct platform_device *pdev) | |||
1832 | /* Bodge while we unpick instantiation */ | 1852 | /* Bodge while we unpick instantiation */ |
1833 | card->dev = &pdev->dev; | 1853 | card->dev = &pdev->dev; |
1834 | 1854 | ||
1835 | ret = snd_soc_register_card(card); | 1855 | return snd_soc_register_card(card); |
1836 | if (ret != 0) { | ||
1837 | dev_err(&pdev->dev, "Failed to register card\n"); | ||
1838 | return ret; | ||
1839 | } | ||
1840 | |||
1841 | return 0; | ||
1842 | } | 1856 | } |
1843 | 1857 | ||
1844 | static int soc_cleanup_card_resources(struct snd_soc_card *card) | 1858 | static int soc_cleanup_card_resources(struct snd_soc_card *card) |
@@ -2399,16 +2413,14 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, | |||
2399 | { | 2413 | { |
2400 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2414 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2401 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2415 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2402 | unsigned int val, bitmask; | 2416 | unsigned int val; |
2403 | 2417 | ||
2404 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
2405 | ; | ||
2406 | val = snd_soc_read(codec, e->reg); | 2418 | val = snd_soc_read(codec, e->reg); |
2407 | ucontrol->value.enumerated.item[0] | 2419 | ucontrol->value.enumerated.item[0] |
2408 | = (val >> e->shift_l) & (bitmask - 1); | 2420 | = (val >> e->shift_l) & e->mask; |
2409 | if (e->shift_l != e->shift_r) | 2421 | if (e->shift_l != e->shift_r) |
2410 | ucontrol->value.enumerated.item[1] = | 2422 | ucontrol->value.enumerated.item[1] = |
2411 | (val >> e->shift_r) & (bitmask - 1); | 2423 | (val >> e->shift_r) & e->mask; |
2412 | 2424 | ||
2413 | return 0; | 2425 | return 0; |
2414 | } | 2426 | } |
@@ -2429,19 +2441,17 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2429 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2441 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2430 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2442 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2431 | unsigned int val; | 2443 | unsigned int val; |
2432 | unsigned int mask, bitmask; | 2444 | unsigned int mask; |
2433 | 2445 | ||
2434 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
2435 | ; | ||
2436 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2446 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
2437 | return -EINVAL; | 2447 | return -EINVAL; |
2438 | val = ucontrol->value.enumerated.item[0] << e->shift_l; | 2448 | val = ucontrol->value.enumerated.item[0] << e->shift_l; |
2439 | mask = (bitmask - 1) << e->shift_l; | 2449 | mask = e->mask << e->shift_l; |
2440 | if (e->shift_l != e->shift_r) { | 2450 | if (e->shift_l != e->shift_r) { |
2441 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | 2451 | if (ucontrol->value.enumerated.item[1] > e->max - 1) |
2442 | return -EINVAL; | 2452 | return -EINVAL; |
2443 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 2453 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; |
2444 | mask |= (bitmask - 1) << e->shift_r; | 2454 | mask |= e->mask << e->shift_r; |
2445 | } | 2455 | } |
2446 | 2456 | ||
2447 | return snd_soc_update_bits_locked(codec, e->reg, mask, val); | 2457 | return snd_soc_update_bits_locked(codec, e->reg, mask, val); |
@@ -3717,6 +3727,9 @@ int snd_soc_register_dai(struct device *dev, | |||
3717 | } | 3727 | } |
3718 | } | 3728 | } |
3719 | 3729 | ||
3730 | if (!dai->codec) | ||
3731 | dai->dapm.idle_bias_off = 1; | ||
3732 | |||
3720 | list_add(&dai->list, &dai_list); | 3733 | list_add(&dai->list, &dai_list); |
3721 | 3734 | ||
3722 | mutex_unlock(&client_mutex); | 3735 | mutex_unlock(&client_mutex); |
@@ -3805,6 +3818,9 @@ int snd_soc_register_dais(struct device *dev, | |||
3805 | } | 3818 | } |
3806 | } | 3819 | } |
3807 | 3820 | ||
3821 | if (!dai->codec) | ||
3822 | dai->dapm.idle_bias_off = 1; | ||
3823 | |||
3808 | list_add(&dai->list, &dai_list); | 3824 | list_add(&dai->list, &dai_list); |
3809 | 3825 | ||
3810 | mutex_unlock(&client_mutex); | 3826 | mutex_unlock(&client_mutex); |
@@ -4034,8 +4050,6 @@ int snd_soc_register_codec(struct device *dev, | |||
4034 | return 0; | 4050 | return 0; |
4035 | 4051 | ||
4036 | fail: | 4052 | fail: |
4037 | kfree(codec->reg_def_copy); | ||
4038 | codec->reg_def_copy = NULL; | ||
4039 | kfree(codec->name); | 4053 | kfree(codec->name); |
4040 | kfree(codec); | 4054 | kfree(codec); |
4041 | return ret; | 4055 | return ret; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f90139b5f50d..873e6e76ee87 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -141,6 +141,28 @@ void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) | |||
141 | } | 141 | } |
142 | EXPORT_SYMBOL_GPL(dapm_mark_dirty); | 142 | EXPORT_SYMBOL_GPL(dapm_mark_dirty); |
143 | 143 | ||
144 | void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm) | ||
145 | { | ||
146 | struct snd_soc_card *card = dapm->card; | ||
147 | struct snd_soc_dapm_widget *w; | ||
148 | |||
149 | mutex_lock(&card->dapm_mutex); | ||
150 | |||
151 | list_for_each_entry(w, &card->widgets, list) { | ||
152 | switch (w->id) { | ||
153 | case snd_soc_dapm_input: | ||
154 | case snd_soc_dapm_output: | ||
155 | dapm_mark_dirty(w, "Rechecking inputs and outputs"); | ||
156 | break; | ||
157 | default: | ||
158 | break; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | mutex_unlock(&card->dapm_mutex); | ||
163 | } | ||
164 | EXPORT_SYMBOL_GPL(dapm_mark_io_dirty); | ||
165 | |||
144 | /* create a new dapm widget */ | 166 | /* create a new dapm widget */ |
145 | static inline struct snd_soc_dapm_widget *dapm_cnew_widget( | 167 | static inline struct snd_soc_dapm_widget *dapm_cnew_widget( |
146 | const struct snd_soc_dapm_widget *_widget) | 168 | const struct snd_soc_dapm_widget *_widget) |
@@ -336,12 +358,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
336 | case snd_soc_dapm_mux: { | 358 | case snd_soc_dapm_mux: { |
337 | struct soc_enum *e = (struct soc_enum *) | 359 | struct soc_enum *e = (struct soc_enum *) |
338 | w->kcontrol_news[i].private_value; | 360 | w->kcontrol_news[i].private_value; |
339 | int val, item, bitmask; | 361 | int val, item; |
340 | 362 | ||
341 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
342 | ; | ||
343 | val = soc_widget_read(w, e->reg); | 363 | val = soc_widget_read(w, e->reg); |
344 | item = (val >> e->shift_l) & (bitmask - 1); | 364 | item = (val >> e->shift_l) & e->mask; |
345 | 365 | ||
346 | p->connect = 0; | 366 | p->connect = 0; |
347 | for (i = 0; i < e->max; i++) { | 367 | for (i = 0; i < e->max; i++) { |
@@ -2658,15 +2678,13 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | |||
2658 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 2678 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
2659 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | 2679 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; |
2660 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2680 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2661 | unsigned int val, bitmask; | 2681 | unsigned int val; |
2662 | 2682 | ||
2663 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
2664 | ; | ||
2665 | val = snd_soc_read(widget->codec, e->reg); | 2683 | val = snd_soc_read(widget->codec, e->reg); |
2666 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); | 2684 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; |
2667 | if (e->shift_l != e->shift_r) | 2685 | if (e->shift_l != e->shift_r) |
2668 | ucontrol->value.enumerated.item[1] = | 2686 | ucontrol->value.enumerated.item[1] = |
2669 | (val >> e->shift_r) & (bitmask - 1); | 2687 | (val >> e->shift_r) & e->mask; |
2670 | 2688 | ||
2671 | return 0; | 2689 | return 0; |
2672 | } | 2690 | } |
@@ -2690,22 +2708,20 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
2690 | struct snd_soc_card *card = codec->card; | 2708 | struct snd_soc_card *card = codec->card; |
2691 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2709 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
2692 | unsigned int val, mux, change; | 2710 | unsigned int val, mux, change; |
2693 | unsigned int mask, bitmask; | 2711 | unsigned int mask; |
2694 | struct snd_soc_dapm_update update; | 2712 | struct snd_soc_dapm_update update; |
2695 | int wi; | 2713 | int wi; |
2696 | 2714 | ||
2697 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
2698 | ; | ||
2699 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2715 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
2700 | return -EINVAL; | 2716 | return -EINVAL; |
2701 | mux = ucontrol->value.enumerated.item[0]; | 2717 | mux = ucontrol->value.enumerated.item[0]; |
2702 | val = mux << e->shift_l; | 2718 | val = mux << e->shift_l; |
2703 | mask = (bitmask - 1) << e->shift_l; | 2719 | mask = e->mask << e->shift_l; |
2704 | if (e->shift_l != e->shift_r) { | 2720 | if (e->shift_l != e->shift_r) { |
2705 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | 2721 | if (ucontrol->value.enumerated.item[1] > e->max - 1) |
2706 | return -EINVAL; | 2722 | return -EINVAL; |
2707 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 2723 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; |
2708 | mask |= (bitmask - 1) << e->shift_r; | 2724 | mask |= e->mask << e->shift_r; |
2709 | } | 2725 | } |
2710 | 2726 | ||
2711 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2727 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 0c172938b82a..fa0fd8ddae90 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
@@ -83,11 +83,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) | |||
83 | jack->status &= ~mask; | 83 | jack->status &= ~mask; |
84 | jack->status |= status & mask; | 84 | jack->status |= status & mask; |
85 | 85 | ||
86 | /* The DAPM sync is expensive enough to be worth skipping. | ||
87 | * However, empty mask means pin synchronization is desired. */ | ||
88 | if (mask && (jack->status == oldstatus)) | ||
89 | goto out; | ||
90 | |||
91 | trace_snd_soc_jack_notify(jack, status); | 86 | trace_snd_soc_jack_notify(jack, status); |
92 | 87 | ||
93 | list_for_each_entry(pin, &jack->pins, list) { | 88 | list_for_each_entry(pin, &jack->pins, list) { |
@@ -109,7 +104,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) | |||
109 | 104 | ||
110 | snd_jack_report(jack->jack, jack->status); | 105 | snd_jack_report(jack->jack, jack->status); |
111 | 106 | ||
112 | out: | ||
113 | mutex_unlock(&jack->mutex); | 107 | mutex_unlock(&jack->mutex); |
114 | } | 108 | } |
115 | EXPORT_SYMBOL_GPL(snd_soc_jack_report); | 109 | EXPORT_SYMBOL_GPL(snd_soc_jack_report); |
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index d4f14e492341..cee13b7bfb94 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c | |||
@@ -34,13 +34,12 @@ | |||
34 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
35 | #include <linux/of_gpio.h> | 35 | #include <linux/of_gpio.h> |
36 | 36 | ||
37 | #include <mach/tegra_wm8903_pdata.h> | ||
38 | |||
39 | #include <sound/core.h> | 37 | #include <sound/core.h> |
40 | #include <sound/jack.h> | 38 | #include <sound/jack.h> |
41 | #include <sound/pcm.h> | 39 | #include <sound/pcm.h> |
42 | #include <sound/pcm_params.h> | 40 | #include <sound/pcm_params.h> |
43 | #include <sound/soc.h> | 41 | #include <sound/soc.h> |
42 | #include <sound/tegra_wm8903.h> | ||
44 | 43 | ||
45 | #include "../codecs/wm8903.h" | 44 | #include "../codecs/wm8903.h" |
46 | 45 | ||
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 45e43b4057b0..be94bf9bf94f 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c | |||
@@ -760,6 +760,9 @@ static int __devinit ux500_msp_drv_probe(struct platform_device *pdev) | |||
760 | drvdata = devm_kzalloc(&pdev->dev, | 760 | drvdata = devm_kzalloc(&pdev->dev, |
761 | sizeof(struct ux500_msp_i2s_drvdata), | 761 | sizeof(struct ux500_msp_i2s_drvdata), |
762 | GFP_KERNEL); | 762 | GFP_KERNEL); |
763 | if (!drvdata) | ||
764 | return -ENOMEM; | ||
765 | |||
763 | drvdata->fmt = 0; | 766 | drvdata->fmt = 0; |
764 | drvdata->slots = 1; | 767 | drvdata->slots = 1; |
765 | drvdata->tx_mask = 0x01; | 768 | drvdata->tx_mask = 0x01; |
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index e5c79ca42518..b7c996e77570 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c | |||
@@ -689,6 +689,8 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, | |||
689 | 689 | ||
690 | *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL); | 690 | *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL); |
691 | msp = *msp_p; | 691 | msp = *msp_p; |
692 | if (!msp) | ||
693 | return -ENOMEM; | ||
692 | 694 | ||
693 | if (np) { | 695 | if (np) { |
694 | if (!platform_data) { | 696 | if (!platform_data) { |