diff options
Diffstat (limited to 'sound/soc/codecs')
121 files changed, 3703 insertions, 8611 deletions
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 1f5e57a4bb7a..12c87d37eba1 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <sound/ac97_codec.h> | 21 | #include <sound/ac97_codec.h> |
22 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
23 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
24 | #include "ac97.h" | ||
25 | 24 | ||
26 | #define AC97_VERSION "0.6" | 25 | #define AC97_VERSION "0.6" |
27 | 26 | ||
@@ -30,8 +29,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
30 | { | 29 | { |
31 | struct snd_pcm_runtime *runtime = substream->runtime; | 30 | struct snd_pcm_runtime *runtime = substream->runtime; |
32 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 31 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
33 | struct snd_soc_device *socdev = rtd->socdev; | 32 | struct snd_soc_codec *codec = rtd->codec; |
34 | struct snd_soc_codec *codec = socdev->card->codec; | ||
35 | 33 | ||
36 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | 34 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
37 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; | 35 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; |
@@ -46,8 +44,8 @@ static struct snd_soc_dai_ops ac97_dai_ops = { | |||
46 | .prepare = ac97_prepare, | 44 | .prepare = ac97_prepare, |
47 | }; | 45 | }; |
48 | 46 | ||
49 | struct snd_soc_dai ac97_dai = { | 47 | static struct snd_soc_dai_driver ac97_dai = { |
50 | .name = "AC97 HiFi", | 48 | .name = "ac97-hifi", |
51 | .ac97_control = 1, | 49 | .ac97_control = 1, |
52 | .playback = { | 50 | .playback = { |
53 | .stream_name = "AC97 Playback", | 51 | .stream_name = "AC97 Playback", |
@@ -63,7 +61,6 @@ struct snd_soc_dai ac97_dai = { | |||
63 | .formats = SND_SOC_STD_AC97_FMTS,}, | 61 | .formats = SND_SOC_STD_AC97_FMTS,}, |
64 | .ops = &ac97_dai_ops, | 62 | .ops = &ac97_dai_ops, |
65 | }; | 63 | }; |
66 | EXPORT_SYMBOL_GPL(ac97_dai); | ||
67 | 64 | ||
68 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 65 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
69 | unsigned int reg) | 66 | unsigned int reg) |
@@ -78,95 +75,49 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
78 | return 0; | 75 | return 0; |
79 | } | 76 | } |
80 | 77 | ||
81 | static int ac97_soc_probe(struct platform_device *pdev) | 78 | static int ac97_soc_probe(struct snd_soc_codec *codec) |
82 | { | 79 | { |
83 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
84 | struct snd_soc_card *card = socdev->card; | ||
85 | struct snd_soc_codec *codec; | ||
86 | struct snd_ac97_bus *ac97_bus; | 80 | struct snd_ac97_bus *ac97_bus; |
87 | struct snd_ac97_template ac97_template; | 81 | struct snd_ac97_template ac97_template; |
88 | int i; | 82 | int ret; |
89 | int ret = 0; | ||
90 | 83 | ||
91 | printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); | 84 | printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); |
92 | 85 | ||
93 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 86 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
94 | if (!socdev->card->codec) | 87 | if (ret < 0) { |
95 | return -ENOMEM; | 88 | printk(KERN_ERR "ASoC: failed to init gen ac97 glue\n"); |
96 | codec = socdev->card->codec; | 89 | return ret; |
97 | mutex_init(&codec->mutex); | 90 | } |
98 | |||
99 | codec->name = "AC97"; | ||
100 | codec->owner = THIS_MODULE; | ||
101 | codec->dai = &ac97_dai; | ||
102 | codec->num_dai = 1; | ||
103 | codec->write = ac97_write; | ||
104 | codec->read = ac97_read; | ||
105 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
106 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
107 | |||
108 | /* register pcms */ | ||
109 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
110 | if (ret < 0) | ||
111 | goto err; | ||
112 | 91 | ||
113 | /* add codec as bus device for standard ac97 */ | 92 | /* add codec as bus device for standard ac97 */ |
114 | ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus); | 93 | ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus); |
115 | if (ret < 0) | 94 | if (ret < 0) |
116 | goto bus_err; | 95 | return ret; |
117 | 96 | ||
118 | memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); | 97 | memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); |
119 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97); | 98 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97); |
120 | if (ret < 0) | 99 | if (ret < 0) |
121 | goto bus_err; | 100 | return ret; |
122 | |||
123 | for (i = 0; i < card->num_links; i++) { | ||
124 | if (card->dai_link[i].codec_dai->ac97_control) { | ||
125 | snd_ac97_dev_add_pdata(codec->ac97, | ||
126 | card->dai_link[i].cpu_dai->ac97_pdata); | ||
127 | } | ||
128 | } | ||
129 | 101 | ||
130 | return 0; | 102 | return 0; |
131 | |||
132 | bus_err: | ||
133 | snd_soc_free_pcms(socdev); | ||
134 | |||
135 | err: | ||
136 | kfree(socdev->card->codec); | ||
137 | socdev->card->codec = NULL; | ||
138 | return ret; | ||
139 | } | 103 | } |
140 | 104 | ||
141 | static int ac97_soc_remove(struct platform_device *pdev) | 105 | static int ac97_soc_remove(struct snd_soc_codec *codec) |
142 | { | 106 | { |
143 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
144 | struct snd_soc_codec *codec = socdev->card->codec; | ||
145 | |||
146 | if (!codec) | ||
147 | return 0; | ||
148 | |||
149 | snd_soc_free_pcms(socdev); | ||
150 | kfree(socdev->card->codec); | ||
151 | |||
152 | return 0; | 107 | return 0; |
153 | } | 108 | } |
154 | 109 | ||
155 | #ifdef CONFIG_PM | 110 | #ifdef CONFIG_PM |
156 | static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg) | 111 | static int ac97_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg) |
157 | { | 112 | { |
158 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 113 | snd_ac97_suspend(codec->ac97); |
159 | |||
160 | snd_ac97_suspend(socdev->card->codec->ac97); | ||
161 | 114 | ||
162 | return 0; | 115 | return 0; |
163 | } | 116 | } |
164 | 117 | ||
165 | static int ac97_soc_resume(struct platform_device *pdev) | 118 | static int ac97_soc_resume(struct snd_soc_codec *codec) |
166 | { | 119 | { |
167 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 120 | snd_ac97_resume(codec->ac97); |
168 | |||
169 | snd_ac97_resume(socdev->card->codec->ac97); | ||
170 | 121 | ||
171 | return 0; | 122 | return 0; |
172 | } | 123 | } |
@@ -175,13 +126,48 @@ static int ac97_soc_resume(struct platform_device *pdev) | |||
175 | #define ac97_soc_resume NULL | 126 | #define ac97_soc_resume NULL |
176 | #endif | 127 | #endif |
177 | 128 | ||
178 | struct snd_soc_codec_device soc_codec_dev_ac97 = { | 129 | static struct snd_soc_codec_driver soc_codec_dev_ac97 = { |
130 | .write = ac97_write, | ||
131 | .read = ac97_read, | ||
179 | .probe = ac97_soc_probe, | 132 | .probe = ac97_soc_probe, |
180 | .remove = ac97_soc_remove, | 133 | .remove = ac97_soc_remove, |
181 | .suspend = ac97_soc_suspend, | 134 | .suspend = ac97_soc_suspend, |
182 | .resume = ac97_soc_resume, | 135 | .resume = ac97_soc_resume, |
183 | }; | 136 | }; |
184 | EXPORT_SYMBOL_GPL(soc_codec_dev_ac97); | 137 | |
138 | static __devinit int ac97_probe(struct platform_device *pdev) | ||
139 | { | ||
140 | return snd_soc_register_codec(&pdev->dev, | ||
141 | &soc_codec_dev_ac97, &ac97_dai, 1); | ||
142 | } | ||
143 | |||
144 | static int __devexit ac97_remove(struct platform_device *pdev) | ||
145 | { | ||
146 | snd_soc_unregister_codec(&pdev->dev); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static struct platform_driver ac97_codec_driver = { | ||
151 | .driver = { | ||
152 | .name = "ac97-codec", | ||
153 | .owner = THIS_MODULE, | ||
154 | }, | ||
155 | |||
156 | .probe = ac97_probe, | ||
157 | .remove = __devexit_p(ac97_remove), | ||
158 | }; | ||
159 | |||
160 | static int __init ac97_init(void) | ||
161 | { | ||
162 | return platform_driver_register(&ac97_codec_driver); | ||
163 | } | ||
164 | module_init(ac97_init); | ||
165 | |||
166 | static void __exit ac97_exit(void) | ||
167 | { | ||
168 | platform_driver_unregister(&ac97_codec_driver); | ||
169 | } | ||
170 | module_exit(ac97_exit); | ||
185 | 171 | ||
186 | MODULE_DESCRIPTION("Soc Generic AC97 driver"); | 172 | MODULE_DESCRIPTION("Soc Generic AC97 driver"); |
187 | MODULE_AUTHOR("Liam Girdwood"); | 173 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/ac97.h b/sound/soc/codecs/ac97.h deleted file mode 100644 index 281aa42e2bbb..000000000000 --- a/sound/soc/codecs/ac97.h +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | /* | ||
2 | * linux/sound/codecs/ac97.h -- ALSA SoC Layer | ||
3 | * | ||
4 | * Author: Liam Girdwood | ||
5 | * Created: Dec 1st 2005 | ||
6 | * Copyright: Wolfson Microelectronics. PLC. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __LINUX_SND_SOC_AC97_H | ||
14 | #define __LINUX_SND_SOC_AC97_H | ||
15 | |||
16 | extern struct snd_soc_codec_device soc_codec_dev_ac97; | ||
17 | extern struct snd_soc_dai ac97_dai; | ||
18 | |||
19 | #endif | ||
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index a01006c8c606..d272534c8f84 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -33,15 +33,10 @@ | |||
33 | 33 | ||
34 | /* codec private data */ | 34 | /* codec private data */ |
35 | struct ad1836_priv { | 35 | struct ad1836_priv { |
36 | struct snd_soc_codec codec; | 36 | enum snd_soc_control_type control_type; |
37 | u16 reg_cache[AD1836_NUM_REGS]; | 37 | void *control_data; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | static struct snd_soc_codec *ad1836_codec; | ||
41 | struct snd_soc_codec_device soc_codec_dev_ad1836; | ||
42 | static int ad1836_register(struct ad1836_priv *ad1836); | ||
43 | static void ad1836_unregister(struct ad1836_priv *ad1836); | ||
44 | |||
45 | /* | 40 | /* |
46 | * AD1836 volume/mute/de-emphasis etc. controls | 41 | * AD1836 volume/mute/de-emphasis etc. controls |
47 | */ | 42 | */ |
@@ -146,8 +141,7 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
146 | int word_len = 0; | 141 | int word_len = 0; |
147 | 142 | ||
148 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 143 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
149 | struct snd_soc_device *socdev = rtd->socdev; | 144 | struct snd_soc_codec *codec = rtd->codec; |
150 | struct snd_soc_codec *codec = socdev->card->codec; | ||
151 | 145 | ||
152 | /* bit size */ | 146 | /* bit size */ |
153 | switch (params_format(params)) { | 147 | switch (params_format(params)) { |
@@ -173,12 +167,9 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
173 | } | 167 | } |
174 | 168 | ||
175 | #ifdef CONFIG_PM | 169 | #ifdef CONFIG_PM |
176 | static int ad1836_soc_suspend(struct platform_device *pdev, | 170 | static int ad1836_soc_suspend(struct snd_soc_codec *codec, |
177 | pm_message_t state) | 171 | pm_message_t state) |
178 | { | 172 | { |
179 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
180 | struct snd_soc_codec *codec = socdev->card->codec; | ||
181 | |||
182 | /* reset clock control mode */ | 173 | /* reset clock control mode */ |
183 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); | 174 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); |
184 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; | 175 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; |
@@ -186,11 +177,8 @@ static int ad1836_soc_suspend(struct platform_device *pdev, | |||
186 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); | 177 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); |
187 | } | 178 | } |
188 | 179 | ||
189 | static int ad1836_soc_resume(struct platform_device *pdev) | 180 | static int ad1836_soc_resume(struct snd_soc_codec *codec) |
190 | { | 181 | { |
191 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
192 | struct snd_soc_codec *codec = socdev->card->codec; | ||
193 | |||
194 | /* restore clock control mode */ | 182 | /* restore clock control mode */ |
195 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); | 183 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); |
196 | adc_ctrl2 |= AD1836_ADC_AUX; | 184 | adc_ctrl2 |= AD1836_ADC_AUX; |
@@ -202,49 +190,14 @@ static int ad1836_soc_resume(struct platform_device *pdev) | |||
202 | #define ad1836_soc_resume NULL | 190 | #define ad1836_soc_resume NULL |
203 | #endif | 191 | #endif |
204 | 192 | ||
205 | static int __devinit ad1836_spi_probe(struct spi_device *spi) | ||
206 | { | ||
207 | struct snd_soc_codec *codec; | ||
208 | struct ad1836_priv *ad1836; | ||
209 | |||
210 | ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL); | ||
211 | if (ad1836 == NULL) | ||
212 | return -ENOMEM; | ||
213 | |||
214 | codec = &ad1836->codec; | ||
215 | codec->control_data = spi; | ||
216 | codec->dev = &spi->dev; | ||
217 | |||
218 | dev_set_drvdata(&spi->dev, ad1836); | ||
219 | |||
220 | return ad1836_register(ad1836); | ||
221 | } | ||
222 | |||
223 | static int __devexit ad1836_spi_remove(struct spi_device *spi) | ||
224 | { | ||
225 | struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev); | ||
226 | |||
227 | ad1836_unregister(ad1836); | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static struct spi_driver ad1836_spi_driver = { | ||
232 | .driver = { | ||
233 | .name = "ad1836", | ||
234 | .owner = THIS_MODULE, | ||
235 | }, | ||
236 | .probe = ad1836_spi_probe, | ||
237 | .remove = __devexit_p(ad1836_spi_remove), | ||
238 | }; | ||
239 | |||
240 | static struct snd_soc_dai_ops ad1836_dai_ops = { | 193 | static struct snd_soc_dai_ops ad1836_dai_ops = { |
241 | .hw_params = ad1836_hw_params, | 194 | .hw_params = ad1836_hw_params, |
242 | .set_fmt = ad1836_set_dai_fmt, | 195 | .set_fmt = ad1836_set_dai_fmt, |
243 | }; | 196 | }; |
244 | 197 | ||
245 | /* codec DAI instance */ | 198 | /* codec DAI instance */ |
246 | struct snd_soc_dai ad1836_dai = { | 199 | static struct snd_soc_dai_driver ad1836_dai = { |
247 | .name = "AD1836", | 200 | .name = "ad1836-hifi", |
248 | .playback = { | 201 | .playback = { |
249 | .stream_name = "Playback", | 202 | .stream_name = "Playback", |
250 | .channels_min = 2, | 203 | .channels_min = 2, |
@@ -263,35 +216,13 @@ struct snd_soc_dai ad1836_dai = { | |||
263 | }, | 216 | }, |
264 | .ops = &ad1836_dai_ops, | 217 | .ops = &ad1836_dai_ops, |
265 | }; | 218 | }; |
266 | EXPORT_SYMBOL_GPL(ad1836_dai); | ||
267 | 219 | ||
268 | static int ad1836_register(struct ad1836_priv *ad1836) | 220 | static int ad1836_probe(struct snd_soc_codec *codec) |
269 | { | 221 | { |
270 | int ret; | 222 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); |
271 | struct snd_soc_codec *codec = &ad1836->codec; | 223 | int ret = 0; |
272 | |||
273 | if (ad1836_codec) { | ||
274 | dev_err(codec->dev, "Another ad1836 is registered\n"); | ||
275 | kfree(ad1836); | ||
276 | return -EINVAL; | ||
277 | } | ||
278 | |||
279 | mutex_init(&codec->mutex); | ||
280 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
281 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
282 | snd_soc_codec_set_drvdata(codec, ad1836); | ||
283 | codec->reg_cache = ad1836->reg_cache; | ||
284 | codec->reg_cache_size = AD1836_NUM_REGS; | ||
285 | codec->name = "AD1836"; | ||
286 | codec->owner = THIS_MODULE; | ||
287 | codec->dai = &ad1836_dai; | ||
288 | codec->num_dai = 1; | ||
289 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
290 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
291 | |||
292 | ad1836_dai.dev = codec->dev; | ||
293 | ad1836_codec = codec; | ||
294 | 224 | ||
225 | codec->control_data = ad1836->control_data; | ||
295 | ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); | 226 | ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); |
296 | if (ret < 0) { | 227 | if (ret < 0) { |
297 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | 228 | dev_err(codec->dev, "failed to set cache I/O: %d\n", |
@@ -319,81 +250,69 @@ static int ad1836_register(struct ad1836_priv *ad1836) | |||
319 | snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); | 250 | snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); |
320 | snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); | 251 | snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); |
321 | 252 | ||
322 | ret = snd_soc_register_codec(codec); | ||
323 | if (ret != 0) { | ||
324 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
325 | kfree(ad1836); | ||
326 | return ret; | ||
327 | } | ||
328 | |||
329 | ret = snd_soc_register_dai(&ad1836_dai); | ||
330 | if (ret != 0) { | ||
331 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
332 | snd_soc_unregister_codec(codec); | ||
333 | kfree(ad1836); | ||
334 | return ret; | ||
335 | } | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static void ad1836_unregister(struct ad1836_priv *ad1836) | ||
341 | { | ||
342 | snd_soc_unregister_dai(&ad1836_dai); | ||
343 | snd_soc_unregister_codec(&ad1836->codec); | ||
344 | kfree(ad1836); | ||
345 | ad1836_codec = NULL; | ||
346 | } | ||
347 | |||
348 | static int ad1836_probe(struct platform_device *pdev) | ||
349 | { | ||
350 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
351 | struct snd_soc_codec *codec; | ||
352 | int ret = 0; | ||
353 | |||
354 | if (ad1836_codec == NULL) { | ||
355 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
356 | return -ENODEV; | ||
357 | } | ||
358 | |||
359 | socdev->card->codec = ad1836_codec; | ||
360 | codec = ad1836_codec; | ||
361 | |||
362 | /* register pcms */ | ||
363 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
364 | if (ret < 0) { | ||
365 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
366 | goto pcm_err; | ||
367 | } | ||
368 | |||
369 | snd_soc_add_controls(codec, ad1836_snd_controls, | 253 | snd_soc_add_controls(codec, ad1836_snd_controls, |
370 | ARRAY_SIZE(ad1836_snd_controls)); | 254 | ARRAY_SIZE(ad1836_snd_controls)); |
371 | snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, | 255 | snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, |
372 | ARRAY_SIZE(ad1836_dapm_widgets)); | 256 | ARRAY_SIZE(ad1836_dapm_widgets)); |
373 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 257 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
374 | 258 | ||
375 | pcm_err: | ||
376 | return ret; | 259 | return ret; |
377 | } | 260 | } |
378 | 261 | ||
379 | /* power down chip */ | 262 | /* power down chip */ |
380 | static int ad1836_remove(struct platform_device *pdev) | 263 | static int ad1836_remove(struct snd_soc_codec *codec) |
381 | { | 264 | { |
382 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 265 | /* reset clock control mode */ |
383 | 266 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); | |
384 | snd_soc_free_pcms(socdev); | 267 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; |
385 | snd_soc_dapm_free(socdev); | ||
386 | 268 | ||
387 | return 0; | 269 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); |
388 | } | 270 | } |
389 | 271 | ||
390 | struct snd_soc_codec_device soc_codec_dev_ad1836 = { | 272 | static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { |
391 | .probe = ad1836_probe, | 273 | .probe = ad1836_probe, |
392 | .remove = ad1836_remove, | 274 | .remove = ad1836_remove, |
393 | .suspend = ad1836_soc_suspend, | 275 | .suspend = ad1836_soc_suspend, |
394 | .resume = ad1836_soc_resume, | 276 | .resume = ad1836_soc_resume, |
277 | .reg_cache_size = AD1836_NUM_REGS, | ||
278 | .reg_word_size = sizeof(u16), | ||
279 | }; | ||
280 | |||
281 | static int __devinit ad1836_spi_probe(struct spi_device *spi) | ||
282 | { | ||
283 | struct ad1836_priv *ad1836; | ||
284 | int ret; | ||
285 | |||
286 | ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL); | ||
287 | if (ad1836 == NULL) | ||
288 | return -ENOMEM; | ||
289 | |||
290 | spi_set_drvdata(spi, ad1836); | ||
291 | ad1836->control_data = spi; | ||
292 | ad1836->control_type = SND_SOC_SPI; | ||
293 | |||
294 | ret = snd_soc_register_codec(&spi->dev, | ||
295 | &soc_codec_dev_ad1836, &ad1836_dai, 1); | ||
296 | if (ret < 0) | ||
297 | kfree(ad1836); | ||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | static int __devexit ad1836_spi_remove(struct spi_device *spi) | ||
302 | { | ||
303 | snd_soc_unregister_codec(&spi->dev); | ||
304 | kfree(spi_get_drvdata(spi)); | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static struct spi_driver ad1836_spi_driver = { | ||
309 | .driver = { | ||
310 | .name = "ad1836-codec", | ||
311 | .owner = THIS_MODULE, | ||
312 | }, | ||
313 | .probe = ad1836_spi_probe, | ||
314 | .remove = __devexit_p(ad1836_spi_remove), | ||
395 | }; | 315 | }; |
396 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836); | ||
397 | 316 | ||
398 | static int __init ad1836_init(void) | 317 | static int __init ad1836_init(void) |
399 | { | 318 | { |
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index e9d90d3951c5..845596717fdf 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h | |||
@@ -60,6 +60,4 @@ | |||
60 | 60 | ||
61 | #define AD1836_NUM_REGS 16 | 61 | #define AD1836_NUM_REGS 16 |
62 | 62 | ||
63 | extern struct snd_soc_dai ad1836_dai; | ||
64 | extern struct snd_soc_codec_device soc_codec_dev_ad1836; | ||
65 | #endif | 63 | #endif |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 1def75e4862f..fa2834c91b9f 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -24,9 +24,10 @@ | |||
24 | 24 | ||
25 | /* codec private data */ | 25 | /* codec private data */ |
26 | struct ad193x_priv { | 26 | struct ad193x_priv { |
27 | unsigned int sysclk; | ||
28 | struct snd_soc_codec codec; | ||
29 | u8 reg_cache[AD193X_NUM_REGS]; | 27 | u8 reg_cache[AD193X_NUM_REGS]; |
28 | enum snd_soc_control_type bus_type; | ||
29 | void *control_data; | ||
30 | int sysclk; | ||
30 | }; | 31 | }; |
31 | 32 | ||
32 | /* ad193x register cache & default register settings */ | 33 | /* ad193x register cache & default register settings */ |
@@ -34,9 +35,6 @@ static const u8 ad193x_reg[AD193X_NUM_REGS] = { | |||
34 | 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, | 35 | 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, |
35 | }; | 36 | }; |
36 | 37 | ||
37 | static struct snd_soc_codec *ad193x_codec; | ||
38 | struct snd_soc_codec_device soc_codec_dev_ad193x; | ||
39 | |||
40 | /* | 38 | /* |
41 | * AD193X volume/mute/de-emphasis etc. controls | 39 | * AD193X volume/mute/de-emphasis etc. controls |
42 | */ | 40 | */ |
@@ -275,8 +273,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, | |||
275 | int word_len = 0, reg = 0, master_rate = 0; | 273 | int word_len = 0, reg = 0, master_rate = 0; |
276 | 274 | ||
277 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 275 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
278 | struct snd_soc_device *socdev = rtd->socdev; | 276 | struct snd_soc_codec *codec = rtd->codec; |
279 | struct snd_soc_codec *codec = socdev->card->codec; | ||
280 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); | 277 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); |
281 | 278 | ||
282 | /* bit size */ | 279 | /* bit size */ |
@@ -323,100 +320,6 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, | |||
323 | return 0; | 320 | return 0; |
324 | } | 321 | } |
325 | 322 | ||
326 | static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type) | ||
327 | { | ||
328 | struct snd_soc_codec *codec; | ||
329 | struct ad193x_priv *ad193x; | ||
330 | int ret; | ||
331 | |||
332 | if (ad193x_codec) { | ||
333 | dev_err(dev, "Another ad193x is registered\n"); | ||
334 | return -EINVAL; | ||
335 | } | ||
336 | |||
337 | ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); | ||
338 | if (ad193x == NULL) | ||
339 | return -ENOMEM; | ||
340 | |||
341 | dev_set_drvdata(dev, ad193x); | ||
342 | |||
343 | codec = &ad193x->codec; | ||
344 | mutex_init(&codec->mutex); | ||
345 | codec->control_data = ctrl_data; | ||
346 | codec->dev = dev; | ||
347 | snd_soc_codec_set_drvdata(codec, ad193x); | ||
348 | codec->reg_cache = ad193x->reg_cache; | ||
349 | codec->reg_cache_size = AD193X_NUM_REGS; | ||
350 | codec->name = "AD193X"; | ||
351 | codec->owner = THIS_MODULE; | ||
352 | codec->dai = &ad193x_dai; | ||
353 | codec->num_dai = 1; | ||
354 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
355 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
356 | |||
357 | ad193x_dai.dev = codec->dev; | ||
358 | ad193x_codec = codec; | ||
359 | |||
360 | memcpy(codec->reg_cache, ad193x_reg, AD193X_NUM_REGS); | ||
361 | |||
362 | if (bus_type == SND_SOC_I2C) | ||
363 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, bus_type); | ||
364 | else | ||
365 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, bus_type); | ||
366 | if (ret < 0) { | ||
367 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | ||
368 | ret); | ||
369 | kfree(ad193x); | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | /* default setting for ad193x */ | ||
374 | |||
375 | /* unmute dac channels */ | ||
376 | snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0); | ||
377 | /* de-emphasis: 48kHz, powedown dac */ | ||
378 | snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A); | ||
379 | /* powerdown dac, dac in tdm mode */ | ||
380 | snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41); | ||
381 | /* high-pass filter enable */ | ||
382 | snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3); | ||
383 | /* sata delay=1, adc aux mode */ | ||
384 | snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43); | ||
385 | /* pll input: mclki/xi */ | ||
386 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ | ||
387 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04); | ||
388 | ad193x->sysclk = 12288000; | ||
389 | |||
390 | ret = snd_soc_register_codec(codec); | ||
391 | if (ret != 0) { | ||
392 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
393 | kfree(ad193x); | ||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | ret = snd_soc_register_dai(&ad193x_dai); | ||
398 | if (ret != 0) { | ||
399 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
400 | snd_soc_unregister_codec(codec); | ||
401 | kfree(ad193x); | ||
402 | return ret; | ||
403 | } | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static int ad193x_bus_remove(struct device *dev) | ||
409 | { | ||
410 | struct ad193x_priv *ad193x = dev_get_drvdata(dev); | ||
411 | |||
412 | snd_soc_unregister_dai(&ad193x_dai); | ||
413 | snd_soc_unregister_codec(&ad193x->codec); | ||
414 | kfree(ad193x); | ||
415 | ad193x_codec = NULL; | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static struct snd_soc_dai_ops ad193x_dai_ops = { | 323 | static struct snd_soc_dai_ops ad193x_dai_ops = { |
421 | .hw_params = ad193x_hw_params, | 324 | .hw_params = ad193x_hw_params, |
422 | .digital_mute = ad193x_mute, | 325 | .digital_mute = ad193x_mute, |
@@ -426,8 +329,8 @@ static struct snd_soc_dai_ops ad193x_dai_ops = { | |||
426 | }; | 329 | }; |
427 | 330 | ||
428 | /* codec DAI instance */ | 331 | /* codec DAI instance */ |
429 | struct snd_soc_dai ad193x_dai = { | 332 | static struct snd_soc_dai_driver ad193x_dai = { |
430 | .name = "AD193X", | 333 | .name = "ad193x-hifi", |
431 | .playback = { | 334 | .playback = { |
432 | .stream_name = "Playback", | 335 | .stream_name = "Playback", |
433 | .channels_min = 2, | 336 | .channels_min = 2, |
@@ -446,28 +349,39 @@ struct snd_soc_dai ad193x_dai = { | |||
446 | }, | 349 | }, |
447 | .ops = &ad193x_dai_ops, | 350 | .ops = &ad193x_dai_ops, |
448 | }; | 351 | }; |
449 | EXPORT_SYMBOL_GPL(ad193x_dai); | ||
450 | 352 | ||
451 | static int ad193x_probe(struct platform_device *pdev) | 353 | static int ad193x_probe(struct snd_soc_codec *codec) |
452 | { | 354 | { |
453 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 355 | struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); |
454 | struct snd_soc_codec *codec; | 356 | int ret; |
455 | int ret = 0; | ||
456 | 357 | ||
457 | if (ad193x_codec == NULL) { | 358 | codec->control_data = ad193x->control_data; |
458 | dev_err(&pdev->dev, "Codec device not registered\n"); | 359 | if (ad193x->bus_type == SND_SOC_I2C) |
459 | return -ENODEV; | 360 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->bus_type); |
361 | else | ||
362 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->bus_type); | ||
363 | if (ret < 0) { | ||
364 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | ||
365 | ret); | ||
366 | kfree(ad193x); | ||
367 | return ret; | ||
460 | } | 368 | } |
461 | 369 | ||
462 | socdev->card->codec = ad193x_codec; | 370 | /* default setting for ad193x */ |
463 | codec = ad193x_codec; | ||
464 | 371 | ||
465 | /* register pcms */ | 372 | /* unmute dac channels */ |
466 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 373 | snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0); |
467 | if (ret < 0) { | 374 | /* de-emphasis: 48kHz, powedown dac */ |
468 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | 375 | snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A); |
469 | goto pcm_err; | 376 | /* powerdown dac, dac in tdm mode */ |
470 | } | 377 | snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41); |
378 | /* high-pass filter enable */ | ||
379 | snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3); | ||
380 | /* sata delay=1, adc aux mode */ | ||
381 | snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43); | ||
382 | /* pll input: mclki/xi */ | ||
383 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ | ||
384 | snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04); | ||
471 | 385 | ||
472 | snd_soc_add_controls(codec, ad193x_snd_controls, | 386 | snd_soc_add_controls(codec, ad193x_snd_controls, |
473 | ARRAY_SIZE(ad193x_snd_controls)); | 387 | ARRAY_SIZE(ad193x_snd_controls)); |
@@ -475,41 +389,47 @@ static int ad193x_probe(struct platform_device *pdev) | |||
475 | ARRAY_SIZE(ad193x_dapm_widgets)); | 389 | ARRAY_SIZE(ad193x_dapm_widgets)); |
476 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 390 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
477 | 391 | ||
478 | pcm_err: | ||
479 | return ret; | 392 | return ret; |
480 | } | 393 | } |
481 | 394 | ||
482 | /* power down chip */ | 395 | static struct snd_soc_codec_driver soc_codec_dev_ad193x = { |
483 | static int ad193x_remove(struct platform_device *pdev) | ||
484 | { | ||
485 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
486 | |||
487 | snd_soc_free_pcms(socdev); | ||
488 | snd_soc_dapm_free(socdev); | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | struct snd_soc_codec_device soc_codec_dev_ad193x = { | ||
494 | .probe = ad193x_probe, | 396 | .probe = ad193x_probe, |
495 | .remove = ad193x_remove, | 397 | .reg_cache_default = ad193x_reg, |
398 | .reg_cache_size = AD193X_NUM_REGS, | ||
399 | .reg_word_size = sizeof(u16), | ||
496 | }; | 400 | }; |
497 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad193x); | ||
498 | 401 | ||
499 | #if defined(CONFIG_SPI_MASTER) | 402 | #if defined(CONFIG_SPI_MASTER) |
500 | static int __devinit ad193x_spi_probe(struct spi_device *spi) | 403 | static int __devinit ad193x_spi_probe(struct spi_device *spi) |
501 | { | 404 | { |
502 | return ad193x_bus_probe(&spi->dev, spi, SND_SOC_SPI); | 405 | struct ad193x_priv *ad193x; |
406 | int ret; | ||
407 | |||
408 | ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); | ||
409 | if (ad193x == NULL) | ||
410 | return -ENOMEM; | ||
411 | |||
412 | spi_set_drvdata(spi, ad193x); | ||
413 | ad193x->control_data = spi; | ||
414 | ad193x->bus_type = SND_SOC_SPI; | ||
415 | |||
416 | ret = snd_soc_register_codec(&spi->dev, | ||
417 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | ||
418 | if (ret < 0) | ||
419 | kfree(ad193x); | ||
420 | return ret; | ||
503 | } | 421 | } |
504 | 422 | ||
505 | static int __devexit ad193x_spi_remove(struct spi_device *spi) | 423 | static int __devexit ad193x_spi_remove(struct spi_device *spi) |
506 | { | 424 | { |
507 | return ad193x_bus_remove(&spi->dev); | 425 | snd_soc_unregister_codec(&spi->dev); |
426 | kfree(spi_get_drvdata(spi)); | ||
427 | return 0; | ||
508 | } | 428 | } |
509 | 429 | ||
510 | static struct spi_driver ad193x_spi_driver = { | 430 | static struct spi_driver ad193x_spi_driver = { |
511 | .driver = { | 431 | .driver = { |
512 | .name = "ad193x", | 432 | .name = "ad193x-codec", |
513 | .owner = THIS_MODULE, | 433 | .owner = THIS_MODULE, |
514 | }, | 434 | }, |
515 | .probe = ad193x_spi_probe, | 435 | .probe = ad193x_spi_probe, |
@@ -528,17 +448,34 @@ MODULE_DEVICE_TABLE(i2c, ad193x_id); | |||
528 | static int __devinit ad193x_i2c_probe(struct i2c_client *client, | 448 | static int __devinit ad193x_i2c_probe(struct i2c_client *client, |
529 | const struct i2c_device_id *id) | 449 | const struct i2c_device_id *id) |
530 | { | 450 | { |
531 | return ad193x_bus_probe(&client->dev, client, SND_SOC_I2C); | 451 | struct ad193x_priv *ad193x; |
452 | int ret; | ||
453 | |||
454 | ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL); | ||
455 | if (ad193x == NULL) | ||
456 | return -ENOMEM; | ||
457 | |||
458 | i2c_set_clientdata(client, ad193x); | ||
459 | ad193x->control_data = client; | ||
460 | ad193x->bus_type = SND_SOC_I2C; | ||
461 | |||
462 | ret = snd_soc_register_codec(&client->dev, | ||
463 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | ||
464 | if (ret < 0) | ||
465 | kfree(ad193x); | ||
466 | return ret; | ||
532 | } | 467 | } |
533 | 468 | ||
534 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) | 469 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) |
535 | { | 470 | { |
536 | return ad193x_bus_remove(&client->dev); | 471 | snd_soc_unregister_codec(&client->dev); |
472 | kfree(i2c_get_clientdata(client)); | ||
473 | return 0; | ||
537 | } | 474 | } |
538 | 475 | ||
539 | static struct i2c_driver ad193x_i2c_driver = { | 476 | static struct i2c_driver ad193x_i2c_driver = { |
540 | .driver = { | 477 | .driver = { |
541 | .name = "ad193x", | 478 | .name = "ad193x-codec", |
542 | }, | 479 | }, |
543 | .probe = ad193x_i2c_probe, | 480 | .probe = ad193x_i2c_probe, |
544 | .remove = __devexit_p(ad193x_i2c_remove), | 481 | .remove = __devexit_p(ad193x_i2c_remove), |
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index 654ba64ae04c..9747b5497877 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h | |||
@@ -80,7 +80,4 @@ | |||
80 | 80 | ||
81 | #define AD193X_NUM_REGS 17 | 81 | #define AD193X_NUM_REGS 17 |
82 | 82 | ||
83 | extern struct snd_soc_dai ad193x_dai; | ||
84 | extern struct snd_soc_codec_device soc_codec_dev_ad193x; | ||
85 | |||
86 | #endif | 83 | #endif |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 042072738cdc..1371afac657b 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -130,8 +130,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
130 | return 0; | 130 | return 0; |
131 | } | 131 | } |
132 | 132 | ||
133 | struct snd_soc_dai ad1980_dai = { | 133 | struct snd_soc_dai_driver ad1980_dai = { |
134 | .name = "AC97", | 134 | .name = "ad1980-hifi", |
135 | .ac97_control = 1, | 135 | .ac97_control = 1, |
136 | .playback = { | 136 | .playback = { |
137 | .stream_name = "Playback", | 137 | .stream_name = "Playback", |
@@ -177,53 +177,20 @@ err: | |||
177 | return -EIO; | 177 | return -EIO; |
178 | } | 178 | } |
179 | 179 | ||
180 | static int ad1980_soc_probe(struct platform_device *pdev) | 180 | static int ad1980_soc_probe(struct snd_soc_codec *codec) |
181 | { | 181 | { |
182 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 182 | int ret; |
183 | struct snd_soc_codec *codec; | ||
184 | int ret = 0; | ||
185 | u16 vendor_id2; | 183 | u16 vendor_id2; |
186 | u16 ext_status; | 184 | u16 ext_status; |
187 | 185 | ||
188 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); | 186 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); |
189 | 187 | ||
190 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
191 | if (socdev->card->codec == NULL) | ||
192 | return -ENOMEM; | ||
193 | codec = socdev->card->codec; | ||
194 | mutex_init(&codec->mutex); | ||
195 | |||
196 | codec->reg_cache = | ||
197 | kzalloc(sizeof(u16) * ARRAY_SIZE(ad1980_reg), GFP_KERNEL); | ||
198 | if (codec->reg_cache == NULL) { | ||
199 | ret = -ENOMEM; | ||
200 | goto cache_err; | ||
201 | } | ||
202 | memcpy(codec->reg_cache, ad1980_reg, sizeof(u16) * \ | ||
203 | ARRAY_SIZE(ad1980_reg)); | ||
204 | codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(ad1980_reg); | ||
205 | codec->reg_cache_step = 2; | ||
206 | codec->name = "AD1980"; | ||
207 | codec->owner = THIS_MODULE; | ||
208 | codec->dai = &ad1980_dai; | ||
209 | codec->num_dai = 1; | ||
210 | codec->write = ac97_write; | ||
211 | codec->read = ac97_read; | ||
212 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
213 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
214 | |||
215 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 188 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
216 | if (ret < 0) { | 189 | if (ret < 0) { |
217 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); | 190 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); |
218 | goto codec_err; | 191 | return ret; |
219 | } | 192 | } |
220 | 193 | ||
221 | /* register pcms */ | ||
222 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
223 | if (ret < 0) | ||
224 | goto pcm_err; | ||
225 | |||
226 | |||
227 | ret = ad1980_reset(codec, 0); | 194 | ret = ad1980_reset(codec, 0); |
228 | if (ret < 0) { | 195 | if (ret < 0) { |
229 | printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); | 196 | printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); |
@@ -262,41 +229,59 @@ static int ad1980_soc_probe(struct platform_device *pdev) | |||
262 | return 0; | 229 | return 0; |
263 | 230 | ||
264 | reset_err: | 231 | reset_err: |
265 | snd_soc_free_pcms(socdev); | ||
266 | |||
267 | pcm_err: | ||
268 | snd_soc_free_ac97_codec(codec); | 232 | snd_soc_free_ac97_codec(codec); |
269 | |||
270 | codec_err: | ||
271 | kfree(codec->reg_cache); | ||
272 | |||
273 | cache_err: | ||
274 | kfree(socdev->card->codec); | ||
275 | socdev->card->codec = NULL; | ||
276 | return ret; | 233 | return ret; |
277 | } | 234 | } |
278 | 235 | ||
279 | static int ad1980_soc_remove(struct platform_device *pdev) | 236 | static int ad1980_soc_remove(struct snd_soc_codec *codec) |
280 | { | 237 | { |
281 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
282 | struct snd_soc_codec *codec = socdev->card->codec; | ||
283 | |||
284 | if (codec == NULL) | ||
285 | return 0; | ||
286 | |||
287 | snd_soc_dapm_free(socdev); | ||
288 | snd_soc_free_pcms(socdev); | ||
289 | snd_soc_free_ac97_codec(codec); | 238 | snd_soc_free_ac97_codec(codec); |
290 | kfree(codec->reg_cache); | ||
291 | kfree(codec); | ||
292 | return 0; | 239 | return 0; |
293 | } | 240 | } |
294 | 241 | ||
295 | struct snd_soc_codec_device soc_codec_dev_ad1980 = { | 242 | static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { |
296 | .probe = ad1980_soc_probe, | 243 | .probe = ad1980_soc_probe, |
297 | .remove = ad1980_soc_remove, | 244 | .remove = ad1980_soc_remove, |
245 | .reg_cache_size = ARRAY_SIZE(ad1980_reg), | ||
246 | .reg_word_size = sizeof(u16), | ||
247 | .reg_cache_step = 2, | ||
248 | .write = ac97_write, | ||
249 | .read = ac97_read, | ||
298 | }; | 250 | }; |
299 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980); | 251 | |
252 | static __devinit int ad1980_probe(struct platform_device *pdev) | ||
253 | { | ||
254 | return snd_soc_register_codec(&pdev->dev, | ||
255 | &soc_codec_dev_ad1980, &ad1980_dai, 1); | ||
256 | } | ||
257 | |||
258 | static int __devexit ad1980_remove(struct platform_device *pdev) | ||
259 | { | ||
260 | snd_soc_unregister_codec(&pdev->dev); | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static struct platform_driver ad1980_codec_driver = { | ||
265 | .driver = { | ||
266 | .name = "ad1980-codec", | ||
267 | .owner = THIS_MODULE, | ||
268 | }, | ||
269 | |||
270 | .probe = ad1980_probe, | ||
271 | .remove = __devexit_p(ad1980_remove), | ||
272 | }; | ||
273 | |||
274 | static int __init ad1980_init(void) | ||
275 | { | ||
276 | return platform_driver_register(&ad1980_codec_driver); | ||
277 | } | ||
278 | module_init(ad1980_init); | ||
279 | |||
280 | static void __exit ad1980_exit(void) | ||
281 | { | ||
282 | platform_driver_unregister(&ad1980_codec_driver); | ||
283 | } | ||
284 | module_exit(ad1980_exit); | ||
300 | 285 | ||
301 | MODULE_DESCRIPTION("ASoC ad1980 driver"); | 286 | MODULE_DESCRIPTION("ASoC ad1980 driver"); |
302 | MODULE_AUTHOR("Roy Huang, Cliff Cai"); | 287 | MODULE_AUTHOR("Roy Huang, Cliff Cai"); |
diff --git a/sound/soc/codecs/ad1980.h b/sound/soc/codecs/ad1980.h index db6c8500d66b..29b5a8750926 100644 --- a/sound/soc/codecs/ad1980.h +++ b/sound/soc/codecs/ad1980.h | |||
@@ -17,7 +17,4 @@ | |||
17 | #define PR5 0x2000 | 17 | #define PR5 0x2000 |
18 | #define PR6 0x4000 | 18 | #define PR6 0x4000 |
19 | 19 | ||
20 | extern struct snd_soc_dai ad1980_dai; | ||
21 | extern struct snd_soc_codec_device soc_codec_dev_ad1980; | ||
22 | |||
23 | #endif | 20 | #endif |
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index 475807bea2c2..c53955fe17b6 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c | |||
@@ -23,8 +23,8 @@ | |||
23 | 23 | ||
24 | #include "ad73311.h" | 24 | #include "ad73311.h" |
25 | 25 | ||
26 | struct snd_soc_dai ad73311_dai = { | 26 | static struct snd_soc_dai_driver ad73311_dai = { |
27 | .name = "AD73311", | 27 | .name = "ad73311-hifi", |
28 | .playback = { | 28 | .playback = { |
29 | .stream_name = "Playback", | 29 | .stream_name = "Playback", |
30 | .channels_min = 1, | 30 | .channels_min = 1, |
@@ -38,68 +38,40 @@ struct snd_soc_dai ad73311_dai = { | |||
38 | .rates = SNDRV_PCM_RATE_8000, | 38 | .rates = SNDRV_PCM_RATE_8000, |
39 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | 39 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, |
40 | }; | 40 | }; |
41 | EXPORT_SYMBOL_GPL(ad73311_dai); | ||
42 | 41 | ||
43 | static int ad73311_soc_probe(struct platform_device *pdev) | 42 | static struct snd_soc_codec_driver soc_codec_dev_ad73311; |
44 | { | ||
45 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
46 | struct snd_soc_codec *codec; | ||
47 | int ret = 0; | ||
48 | |||
49 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
50 | if (codec == NULL) | ||
51 | return -ENOMEM; | ||
52 | mutex_init(&codec->mutex); | ||
53 | codec->name = "AD73311"; | ||
54 | codec->owner = THIS_MODULE; | ||
55 | codec->dai = &ad73311_dai; | ||
56 | codec->num_dai = 1; | ||
57 | socdev->card->codec = codec; | ||
58 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
59 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
60 | |||
61 | /* register pcms */ | ||
62 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
63 | if (ret < 0) { | ||
64 | printk(KERN_ERR "ad73311: failed to create pcms\n"); | ||
65 | goto pcm_err; | ||
66 | } | ||
67 | |||
68 | return ret; | ||
69 | 43 | ||
70 | pcm_err: | 44 | static int ad73311_probe(struct platform_device *pdev) |
71 | kfree(socdev->card->codec); | 45 | { |
72 | socdev->card->codec = NULL; | 46 | return snd_soc_register_codec(&pdev->dev, |
73 | return ret; | 47 | &soc_codec_dev_ad73311, &ad73311_dai, 1); |
74 | } | 48 | } |
75 | 49 | ||
76 | static int ad73311_soc_remove(struct platform_device *pdev) | 50 | static int ad73311_remove(struct platform_device *pdev) |
77 | { | 51 | { |
78 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 52 | snd_soc_unregister_codec(&pdev->dev); |
79 | struct snd_soc_codec *codec = socdev->card->codec; | ||
80 | |||
81 | if (codec == NULL) | ||
82 | return 0; | ||
83 | snd_soc_free_pcms(socdev); | ||
84 | kfree(codec); | ||
85 | return 0; | 53 | return 0; |
86 | } | 54 | } |
87 | 55 | ||
88 | struct snd_soc_codec_device soc_codec_dev_ad73311 = { | 56 | static struct platform_driver ad73311_codec_driver = { |
89 | .probe = ad73311_soc_probe, | 57 | .driver = { |
90 | .remove = ad73311_soc_remove, | 58 | .name = "ad73311-codec", |
59 | .owner = THIS_MODULE, | ||
60 | }, | ||
61 | |||
62 | .probe = ad73311_probe, | ||
63 | .remove = __devexit_p(ad73311_remove), | ||
91 | }; | 64 | }; |
92 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311); | ||
93 | 65 | ||
94 | static int __init ad73311_init(void) | 66 | static int __init ad73311_init(void) |
95 | { | 67 | { |
96 | return snd_soc_register_dai(&ad73311_dai); | 68 | return platform_driver_register(&ad73311_codec_driver); |
97 | } | 69 | } |
98 | module_init(ad73311_init); | 70 | module_init(ad73311_init); |
99 | 71 | ||
100 | static void __exit ad73311_exit(void) | 72 | static void __exit ad73311_exit(void) |
101 | { | 73 | { |
102 | snd_soc_unregister_dai(&ad73311_dai); | 74 | platform_driver_unregister(&ad73311_codec_driver); |
103 | } | 75 | } |
104 | module_exit(ad73311_exit); | 76 | module_exit(ad73311_exit); |
105 | 77 | ||
diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h index 569573d2d4d7..4b353eefc0bf 100644 --- a/sound/soc/codecs/ad73311.h +++ b/sound/soc/codecs/ad73311.h | |||
@@ -85,6 +85,4 @@ | |||
85 | #define REGF_INV (1 << 6) | 85 | #define REGF_INV (1 << 6) |
86 | #define REGF_ALB (1 << 7) | 86 | #define REGF_ALB (1 << 7) |
87 | 87 | ||
88 | extern struct snd_soc_dai ad73311_dai; | ||
89 | extern struct snd_soc_codec_device soc_codec_dev_ad73311; | ||
90 | #endif | 88 | #endif |
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c index f8e75edb27b7..8402854ec15e 100644 --- a/sound/soc/codecs/ads117x.c +++ b/sound/soc/codecs/ads117x.c | |||
@@ -19,16 +19,12 @@ | |||
19 | #include <sound/initval.h> | 19 | #include <sound/initval.h> |
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | 21 | ||
22 | #include "ads117x.h" | ||
23 | |||
24 | #define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) | 22 | #define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) |
25 | |||
26 | #define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) | 23 | #define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) |
27 | 24 | ||
28 | struct snd_soc_dai ads117x_dai = { | 25 | static struct snd_soc_dai_driver ads117x_dai = { |
29 | /* ADC */ | 26 | /* ADC */ |
30 | .name = "ADS117X ADC", | 27 | .name = "ads117x-hifi", |
31 | .id = 1, | ||
32 | .capture = { | 28 | .capture = { |
33 | .stream_name = "Capture", | 29 | .stream_name = "Capture", |
34 | .channels_min = 1, | 30 | .channels_min = 1, |
@@ -36,75 +32,29 @@ struct snd_soc_dai ads117x_dai = { | |||
36 | .rates = ADS117X_RATES, | 32 | .rates = ADS117X_RATES, |
37 | .formats = ADS117X_FORMATS,}, | 33 | .formats = ADS117X_FORMATS,}, |
38 | }; | 34 | }; |
39 | EXPORT_SYMBOL_GPL(ads117x_dai); | ||
40 | |||
41 | static int ads117x_probe(struct platform_device *pdev) | ||
42 | { | ||
43 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
44 | struct snd_soc_codec *codec; | ||
45 | int ret; | ||
46 | |||
47 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
48 | if (codec == NULL) | ||
49 | return -ENOMEM; | ||
50 | 35 | ||
51 | socdev->card->codec = codec; | 36 | static struct snd_soc_codec_driver soc_codec_dev_ads117x; |
52 | mutex_init(&codec->mutex); | ||
53 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
54 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
55 | codec->name = "ADS117X"; | ||
56 | codec->owner = THIS_MODULE; | ||
57 | codec->dai = &ads117x_dai; | ||
58 | codec->num_dai = 1; | ||
59 | |||
60 | /* register pcms */ | ||
61 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
62 | if (ret < 0) { | ||
63 | printk(KERN_ERR "ads117x: failed to create pcms\n"); | ||
64 | kfree(codec); | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int ads117x_remove(struct platform_device *pdev) | ||
72 | { | ||
73 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
74 | struct snd_soc_codec *codec = socdev->card->codec; | ||
75 | |||
76 | snd_soc_free_pcms(socdev); | ||
77 | kfree(codec); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | struct snd_soc_codec_device soc_codec_dev_ads117x = { | ||
83 | .probe = ads117x_probe, | ||
84 | .remove = ads117x_remove, | ||
85 | }; | ||
86 | EXPORT_SYMBOL_GPL(soc_codec_dev_ads117x); | ||
87 | 37 | ||
88 | static __devinit int ads117x_platform_probe(struct platform_device *pdev) | 38 | static __devinit int ads117x_probe(struct platform_device *pdev) |
89 | { | 39 | { |
90 | ads117x_dai.dev = &pdev->dev; | 40 | return snd_soc_register_codec(&pdev->dev, |
91 | return snd_soc_register_dai(&ads117x_dai); | 41 | &soc_codec_dev_ads117x, &ads117x_dai, 1); |
92 | } | 42 | } |
93 | 43 | ||
94 | static int __devexit ads117x_platform_remove(struct platform_device *pdev) | 44 | static int __devexit ads117x_remove(struct platform_device *pdev) |
95 | { | 45 | { |
96 | snd_soc_unregister_dai(&ads117x_dai); | 46 | snd_soc_unregister_codec(&pdev->dev); |
97 | return 0; | 47 | return 0; |
98 | } | 48 | } |
99 | 49 | ||
100 | static struct platform_driver ads117x_codec_driver = { | 50 | static struct platform_driver ads117x_codec_driver = { |
101 | .driver = { | 51 | .driver = { |
102 | .name = "ads117x", | 52 | .name = "ads117x-codec", |
103 | .owner = THIS_MODULE, | 53 | .owner = THIS_MODULE, |
104 | }, | 54 | }, |
105 | 55 | ||
106 | .probe = ads117x_platform_probe, | 56 | .probe = ads117x_probe, |
107 | .remove = __devexit_p(ads117x_platform_remove), | 57 | .remove = __devexit_p(ads117x_remove), |
108 | }; | 58 | }; |
109 | 59 | ||
110 | static int __init ads117x_init(void) | 60 | static int __init ads117x_init(void) |
diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h index dbcf50ec9bd1..3ce028614002 100644 --- a/sound/soc/codecs/ads117x.h +++ b/sound/soc/codecs/ads117x.h | |||
@@ -9,5 +9,5 @@ | |||
9 | * Free Software Foundation; either version 2 of the License, or (at your | 9 | * Free Software Foundation; either version 2 of the License, or (at your |
10 | * option) any later version. | 10 | * option) any later version. |
11 | */ | 11 | */ |
12 | extern struct snd_soc_dai ads117x_dai; | 12 | extern struct snd_soc_dai_driver ads117x_dai; |
13 | extern struct snd_soc_codec_device soc_codec_dev_ads117x; | 13 | extern struct snd_soc_codec_driver soc_codec_dev_ads117x; |
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index 192aebda3029..c27f8f59dc66 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #include <linux/spi/spi.h> | 17 | #include <linux/spi/spi.h> |
18 | #include <sound/asoundef.h> | 18 | #include <sound/asoundef.h> |
19 | 19 | ||
20 | #include "ak4104.h" | ||
21 | |||
22 | /* AK4104 registers addresses */ | 20 | /* AK4104 registers addresses */ |
23 | #define AK4104_REG_CONTROL1 0x00 | 21 | #define AK4104_REG_CONTROL1 0x00 |
24 | #define AK4104_REG_RESERVED 0x01 | 22 | #define AK4104_REG_RESERVED 0x01 |
@@ -45,11 +43,11 @@ | |||
45 | #define AK4104_TX_TXE (1 << 0) | 43 | #define AK4104_TX_TXE (1 << 0) |
46 | #define AK4104_TX_V (1 << 1) | 44 | #define AK4104_TX_V (1 << 1) |
47 | 45 | ||
48 | #define DRV_NAME "ak4104" | 46 | #define DRV_NAME "ak4104-codec" |
49 | 47 | ||
50 | struct ak4104_private { | 48 | struct ak4104_private { |
51 | struct snd_soc_codec codec; | 49 | enum snd_soc_control_type control_type; |
52 | u8 reg_cache[AK4104_NUM_REGS]; | 50 | void *control_data; |
53 | }; | 51 | }; |
54 | 52 | ||
55 | static int ak4104_fill_cache(struct snd_soc_codec *codec) | 53 | static int ak4104_fill_cache(struct snd_soc_codec *codec) |
@@ -58,7 +56,7 @@ static int ak4104_fill_cache(struct snd_soc_codec *codec) | |||
58 | u8 *reg_cache = codec->reg_cache; | 56 | u8 *reg_cache = codec->reg_cache; |
59 | struct spi_device *spi = codec->control_data; | 57 | struct spi_device *spi = codec->control_data; |
60 | 58 | ||
61 | for (i = 0; i < codec->reg_cache_size; i++) { | 59 | for (i = 0; i < codec->driver->reg_cache_size; i++) { |
62 | int ret = spi_w8r8(spi, i | AK4104_READ); | 60 | int ret = spi_w8r8(spi, i | AK4104_READ); |
63 | if (ret < 0) { | 61 | if (ret < 0) { |
64 | dev_err(&spi->dev, "SPI write failure\n"); | 62 | dev_err(&spi->dev, "SPI write failure\n"); |
@@ -76,7 +74,7 @@ static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec, | |||
76 | { | 74 | { |
77 | u8 *reg_cache = codec->reg_cache; | 75 | u8 *reg_cache = codec->reg_cache; |
78 | 76 | ||
79 | if (reg >= codec->reg_cache_size) | 77 | if (reg >= codec->driver->reg_cache_size) |
80 | return -EINVAL; | 78 | return -EINVAL; |
81 | 79 | ||
82 | return reg_cache[reg]; | 80 | return reg_cache[reg]; |
@@ -88,7 +86,7 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg, | |||
88 | u8 *cache = codec->reg_cache; | 86 | u8 *cache = codec->reg_cache; |
89 | struct spi_device *spi = codec->control_data; | 87 | struct spi_device *spi = codec->control_data; |
90 | 88 | ||
91 | if (reg >= codec->reg_cache_size) | 89 | if (reg >= codec->driver->reg_cache_size) |
92 | return -EINVAL; | 90 | return -EINVAL; |
93 | 91 | ||
94 | /* only write to the hardware if value has changed */ | 92 | /* only write to the hardware if value has changed */ |
@@ -145,8 +143,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream, | |||
145 | struct snd_soc_dai *dai) | 143 | struct snd_soc_dai *dai) |
146 | { | 144 | { |
147 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 145 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
148 | struct snd_soc_device *socdev = rtd->socdev; | 146 | struct snd_soc_codec *codec = rtd->codec; |
149 | struct snd_soc_codec *codec = socdev->card->codec; | ||
150 | int val = 0; | 147 | int val = 0; |
151 | 148 | ||
152 | /* set the IEC958 bits: consumer mode, no copyright bit */ | 149 | /* set the IEC958 bits: consumer mode, no copyright bit */ |
@@ -178,8 +175,8 @@ static struct snd_soc_dai_ops ak4101_dai_ops = { | |||
178 | .set_fmt = ak4104_set_dai_fmt, | 175 | .set_fmt = ak4104_set_dai_fmt, |
179 | }; | 176 | }; |
180 | 177 | ||
181 | struct snd_soc_dai ak4104_dai = { | 178 | static struct snd_soc_dai_driver ak4104_dai = { |
182 | .name = DRV_NAME, | 179 | .name = "ak4104-hifi", |
183 | .playback = { | 180 | .playback = { |
184 | .stream_name = "Playback", | 181 | .stream_name = "Playback", |
185 | .channels_min = 2, | 182 | .channels_min = 2, |
@@ -192,45 +189,17 @@ struct snd_soc_dai ak4104_dai = { | |||
192 | .ops = &ak4101_dai_ops, | 189 | .ops = &ak4101_dai_ops, |
193 | }; | 190 | }; |
194 | 191 | ||
195 | static struct snd_soc_codec *ak4104_codec; | 192 | static int ak4104_probe(struct snd_soc_codec *codec) |
196 | |||
197 | static int ak4104_spi_probe(struct spi_device *spi) | ||
198 | { | 193 | { |
199 | struct snd_soc_codec *codec; | 194 | struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); |
200 | struct ak4104_private *ak4104; | ||
201 | int ret, val; | 195 | int ret, val; |
202 | 196 | ||
203 | spi->bits_per_word = 8; | 197 | codec->control_data = ak4104->control_data; |
204 | spi->mode = SPI_MODE_0; | ||
205 | ret = spi_setup(spi); | ||
206 | if (ret < 0) | ||
207 | return ret; | ||
208 | |||
209 | ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL); | ||
210 | if (!ak4104) { | ||
211 | dev_err(&spi->dev, "could not allocate codec\n"); | ||
212 | return -ENOMEM; | ||
213 | } | ||
214 | |||
215 | codec = &ak4104->codec; | ||
216 | mutex_init(&codec->mutex); | ||
217 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
218 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
219 | |||
220 | codec->dev = &spi->dev; | ||
221 | codec->name = DRV_NAME; | ||
222 | codec->owner = THIS_MODULE; | ||
223 | codec->dai = &ak4104_dai; | ||
224 | codec->num_dai = 1; | ||
225 | snd_soc_codec_set_drvdata(codec, ak4104); | ||
226 | codec->control_data = spi; | ||
227 | codec->reg_cache = ak4104->reg_cache; | ||
228 | codec->reg_cache_size = AK4104_NUM_REGS; | ||
229 | 198 | ||
230 | /* read all regs and fill the cache */ | 199 | /* read all regs and fill the cache */ |
231 | ret = ak4104_fill_cache(codec); | 200 | ret = ak4104_fill_cache(codec); |
232 | if (ret < 0) { | 201 | if (ret < 0) { |
233 | dev_err(&spi->dev, "failed to fill register cache\n"); | 202 | dev_err(codec->dev, "failed to fill register cache\n"); |
234 | return ret; | 203 | return ret; |
235 | } | 204 | } |
236 | 205 | ||
@@ -238,93 +207,81 @@ static int ak4104_spi_probe(struct spi_device *spi) | |||
238 | * should contain 0x5b. Not a good way to verify the presence of | 207 | * should contain 0x5b. Not a good way to verify the presence of |
239 | * the device, but there is no hardware ID register. */ | 208 | * the device, but there is no hardware ID register. */ |
240 | if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) != | 209 | if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) != |
241 | AK4104_RESERVED_VAL) { | 210 | AK4104_RESERVED_VAL) |
242 | ret = -ENODEV; | 211 | return -ENODEV; |
243 | goto error_free_codec; | ||
244 | } | ||
245 | 212 | ||
246 | /* set power-up and non-reset bits */ | 213 | /* set power-up and non-reset bits */ |
247 | val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); | 214 | val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); |
248 | val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN; | 215 | val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN; |
249 | ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); | 216 | ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); |
250 | if (ret < 0) | 217 | if (ret < 0) |
251 | goto error_free_codec; | 218 | return ret; |
252 | 219 | ||
253 | /* enable transmitter */ | 220 | /* enable transmitter */ |
254 | val = ak4104_read_reg_cache(codec, AK4104_REG_TX); | 221 | val = ak4104_read_reg_cache(codec, AK4104_REG_TX); |
255 | val |= AK4104_TX_TXE; | 222 | val |= AK4104_TX_TXE; |
256 | ret = ak4104_spi_write(codec, AK4104_REG_TX, val); | 223 | ret = ak4104_spi_write(codec, AK4104_REG_TX, val); |
257 | if (ret < 0) | 224 | if (ret < 0) |
258 | goto error_free_codec; | 225 | return ret; |
259 | |||
260 | ak4104_codec = codec; | ||
261 | ret = snd_soc_register_dai(&ak4104_dai); | ||
262 | if (ret < 0) { | ||
263 | dev_err(&spi->dev, "failed to register DAI\n"); | ||
264 | goto error_free_codec; | ||
265 | } | ||
266 | 226 | ||
267 | spi_set_drvdata(spi, ak4104); | 227 | dev_info(codec->dev, "SPI device initialized\n"); |
268 | dev_info(&spi->dev, "SPI device initialized\n"); | ||
269 | return 0; | 228 | return 0; |
270 | |||
271 | error_free_codec: | ||
272 | kfree(ak4104); | ||
273 | ak4104_dai.dev = NULL; | ||
274 | return ret; | ||
275 | } | 229 | } |
276 | 230 | ||
277 | static int __devexit ak4104_spi_remove(struct spi_device *spi) | 231 | static int ak4104_remove(struct snd_soc_codec *codec) |
278 | { | 232 | { |
279 | int ret, val; | 233 | int val, ret; |
280 | struct ak4104_private *ak4104 = spi_get_drvdata(spi); | ||
281 | 234 | ||
282 | val = ak4104_read_reg_cache(&ak4104->codec, AK4104_REG_CONTROL1); | 235 | val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); |
283 | if (val < 0) | 236 | if (val < 0) |
284 | return val; | 237 | return val; |
285 | 238 | ||
286 | /* clear power-up and non-reset bits */ | 239 | /* clear power-up and non-reset bits */ |
287 | val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); | 240 | val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); |
288 | ret = ak4104_spi_write(&ak4104->codec, AK4104_REG_CONTROL1, val); | 241 | ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); |
289 | if (ret < 0) | ||
290 | return ret; | ||
291 | 242 | ||
292 | ak4104_codec = NULL; | 243 | return ret; |
293 | kfree(ak4104); | ||
294 | return 0; | ||
295 | } | 244 | } |
296 | 245 | ||
297 | static int ak4104_probe(struct platform_device *pdev) | 246 | static struct snd_soc_codec_driver soc_codec_device_ak4104 = { |
247 | .probe = ak4104_probe, | ||
248 | .remove = ak4104_remove, | ||
249 | .reg_cache_size = AK4104_NUM_REGS, | ||
250 | .reg_word_size = sizeof(u16), | ||
251 | }; | ||
252 | |||
253 | static int ak4104_spi_probe(struct spi_device *spi) | ||
298 | { | 254 | { |
299 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 255 | struct ak4104_private *ak4104; |
300 | struct snd_soc_codec *codec = ak4104_codec; | ||
301 | int ret; | 256 | int ret; |
302 | 257 | ||
303 | /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ | 258 | spi->bits_per_word = 8; |
304 | socdev->card->codec = codec; | 259 | spi->mode = SPI_MODE_0; |
305 | 260 | ret = spi_setup(spi); | |
306 | /* Register PCMs */ | 261 | if (ret < 0) |
307 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
308 | if (ret < 0) { | ||
309 | dev_err(codec->dev, "failed to create pcms\n"); | ||
310 | return ret; | 262 | return ret; |
311 | } | ||
312 | 263 | ||
313 | return 0; | 264 | ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL); |
265 | if (ak4104 == NULL) | ||
266 | return -ENOMEM; | ||
267 | |||
268 | ak4104->control_data = spi; | ||
269 | ak4104->control_type = SND_SOC_SPI; | ||
270 | spi_set_drvdata(spi, ak4104); | ||
271 | |||
272 | ret = snd_soc_register_codec(&spi->dev, | ||
273 | &soc_codec_device_ak4104, &ak4104_dai, 1); | ||
274 | if (ret < 0) | ||
275 | kfree(ak4104); | ||
276 | return ret; | ||
314 | } | 277 | } |
315 | 278 | ||
316 | static int ak4104_remove(struct platform_device *pdev) | 279 | static int __devexit ak4104_spi_remove(struct spi_device *spi) |
317 | { | 280 | { |
318 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 281 | snd_soc_unregister_codec(&spi->dev); |
319 | snd_soc_free_pcms(socdev); | 282 | kfree(spi_get_drvdata(spi)); |
320 | return 0; | 283 | return 0; |
321 | }; | 284 | } |
322 | |||
323 | struct snd_soc_codec_device soc_codec_device_ak4104 = { | ||
324 | .probe = ak4104_probe, | ||
325 | .remove = ak4104_remove | ||
326 | }; | ||
327 | EXPORT_SYMBOL_GPL(soc_codec_device_ak4104); | ||
328 | 285 | ||
329 | static struct spi_driver ak4104_spi_driver = { | 286 | static struct spi_driver ak4104_spi_driver = { |
330 | .driver = { | 287 | .driver = { |
diff --git a/sound/soc/codecs/ak4104.h b/sound/soc/codecs/ak4104.h deleted file mode 100644 index eb88fe7e4def..000000000000 --- a/sound/soc/codecs/ak4104.h +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | #ifndef _AK4104_H | ||
2 | #define _AK4104_H | ||
3 | |||
4 | extern struct snd_soc_dai ak4104_dai; | ||
5 | extern struct snd_soc_codec_device soc_codec_device_ak4104; | ||
6 | |||
7 | #endif | ||
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index d4253675b2d3..cd88c8f32a38 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -31,11 +31,11 @@ | |||
31 | 31 | ||
32 | #define AK4535_VERSION "0.3" | 32 | #define AK4535_VERSION "0.3" |
33 | 33 | ||
34 | struct snd_soc_codec_device soc_codec_dev_ak4535; | ||
35 | |||
36 | /* codec private data */ | 34 | /* codec private data */ |
37 | struct ak4535_priv { | 35 | struct ak4535_priv { |
38 | unsigned int sysclk; | 36 | unsigned int sysclk; |
37 | enum snd_soc_control_type control_type; | ||
38 | void *control_data; | ||
39 | }; | 39 | }; |
40 | 40 | ||
41 | /* | 41 | /* |
@@ -313,8 +313,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream, | |||
313 | struct snd_soc_dai *dai) | 313 | struct snd_soc_dai *dai) |
314 | { | 314 | { |
315 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 315 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
316 | struct snd_soc_device *socdev = rtd->socdev; | 316 | struct snd_soc_codec *codec = rtd->codec; |
317 | struct snd_soc_codec *codec = socdev->card->codec; | ||
318 | struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); | 317 | struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); |
319 | u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); | 318 | u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); |
320 | int rate = params_rate(params), fs = 256; | 319 | int rate = params_rate(params), fs = 256; |
@@ -378,14 +377,16 @@ static int ak4535_mute(struct snd_soc_dai *dai, int mute) | |||
378 | static int ak4535_set_bias_level(struct snd_soc_codec *codec, | 377 | static int ak4535_set_bias_level(struct snd_soc_codec *codec, |
379 | enum snd_soc_bias_level level) | 378 | enum snd_soc_bias_level level) |
380 | { | 379 | { |
381 | u16 i; | 380 | u16 i, mute_reg; |
382 | 381 | ||
383 | switch (level) { | 382 | switch (level) { |
384 | case SND_SOC_BIAS_ON: | 383 | case SND_SOC_BIAS_ON: |
385 | ak4535_mute(codec->dai, 0); | 384 | mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf; |
385 | ak4535_write(codec, AK4535_DAC, mute_reg); | ||
386 | break; | 386 | break; |
387 | case SND_SOC_BIAS_PREPARE: | 387 | case SND_SOC_BIAS_PREPARE: |
388 | ak4535_mute(codec->dai, 1); | 388 | mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf; |
389 | ak4535_write(codec, AK4535_DAC, mute_reg | 0x20); | ||
389 | break; | 390 | break; |
390 | case SND_SOC_BIAS_STANDBY: | 391 | case SND_SOC_BIAS_STANDBY: |
391 | i = ak4535_read_reg_cache(codec, AK4535_PM1); | 392 | i = ak4535_read_reg_cache(codec, AK4535_PM1); |
@@ -413,8 +414,8 @@ static struct snd_soc_dai_ops ak4535_dai_ops = { | |||
413 | .set_sysclk = ak4535_set_dai_sysclk, | 414 | .set_sysclk = ak4535_set_dai_sysclk, |
414 | }; | 415 | }; |
415 | 416 | ||
416 | struct snd_soc_dai ak4535_dai = { | 417 | static struct snd_soc_dai_driver ak4535_dai = { |
417 | .name = "AK4535", | 418 | .name = "ak4535-hifi", |
418 | .playback = { | 419 | .playback = { |
419 | .stream_name = "Playback", | 420 | .stream_name = "Playback", |
420 | .channels_min = 1, | 421 | .channels_min = 1, |
@@ -429,54 +430,27 @@ struct snd_soc_dai ak4535_dai = { | |||
429 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 430 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
430 | .ops = &ak4535_dai_ops, | 431 | .ops = &ak4535_dai_ops, |
431 | }; | 432 | }; |
432 | EXPORT_SYMBOL_GPL(ak4535_dai); | ||
433 | 433 | ||
434 | static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) | 434 | static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state) |
435 | { | 435 | { |
436 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
437 | struct snd_soc_codec *codec = socdev->card->codec; | ||
438 | |||
439 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | 436 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); |
440 | return 0; | 437 | return 0; |
441 | } | 438 | } |
442 | 439 | ||
443 | static int ak4535_resume(struct platform_device *pdev) | 440 | static int ak4535_resume(struct snd_soc_codec *codec) |
444 | { | 441 | { |
445 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
446 | struct snd_soc_codec *codec = socdev->card->codec; | ||
447 | ak4535_sync(codec); | 442 | ak4535_sync(codec); |
448 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 443 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
449 | return 0; | 444 | return 0; |
450 | } | 445 | } |
451 | 446 | ||
452 | /* | 447 | static int ak4535_probe(struct snd_soc_codec *codec) |
453 | * initialise the AK4535 driver | ||
454 | * register the mixer and dsp interfaces with the kernel | ||
455 | */ | ||
456 | static int ak4535_init(struct snd_soc_device *socdev) | ||
457 | { | 448 | { |
458 | struct snd_soc_codec *codec = socdev->card->codec; | 449 | struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); |
459 | int ret = 0; | ||
460 | 450 | ||
461 | codec->name = "AK4535"; | 451 | printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION); |
462 | codec->owner = THIS_MODULE; | ||
463 | codec->read = ak4535_read_reg_cache; | ||
464 | codec->write = ak4535_write; | ||
465 | codec->set_bias_level = ak4535_set_bias_level; | ||
466 | codec->dai = &ak4535_dai; | ||
467 | codec->num_dai = 1; | ||
468 | codec->reg_cache_size = ARRAY_SIZE(ak4535_reg); | ||
469 | codec->reg_cache = kmemdup(ak4535_reg, sizeof(ak4535_reg), GFP_KERNEL); | ||
470 | |||
471 | if (codec->reg_cache == NULL) | ||
472 | return -ENOMEM; | ||
473 | 452 | ||
474 | /* register pcms */ | 453 | codec->control_data = ak4535->control_data; |
475 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
476 | if (ret < 0) { | ||
477 | printk(KERN_ERR "ak4535: failed to create pcms\n"); | ||
478 | goto pcm_err; | ||
479 | } | ||
480 | 454 | ||
481 | /* power on device */ | 455 | /* power on device */ |
482 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 456 | ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -485,39 +459,55 @@ static int ak4535_init(struct snd_soc_device *socdev) | |||
485 | ARRAY_SIZE(ak4535_snd_controls)); | 459 | ARRAY_SIZE(ak4535_snd_controls)); |
486 | ak4535_add_widgets(codec); | 460 | ak4535_add_widgets(codec); |
487 | 461 | ||
488 | return ret; | 462 | return 0; |
489 | 463 | } | |
490 | pcm_err: | ||
491 | kfree(codec->reg_cache); | ||
492 | 464 | ||
493 | return ret; | 465 | /* power down chip */ |
466 | static int ak4535_remove(struct snd_soc_codec *codec) | ||
467 | { | ||
468 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
469 | return 0; | ||
494 | } | 470 | } |
495 | 471 | ||
496 | static struct snd_soc_device *ak4535_socdev; | 472 | static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { |
473 | .probe = ak4535_probe, | ||
474 | .remove = ak4535_remove, | ||
475 | .suspend = ak4535_suspend, | ||
476 | .resume = ak4535_resume, | ||
477 | .read = ak4535_read_reg_cache, | ||
478 | .write = ak4535_write, | ||
479 | .set_bias_level = ak4535_set_bias_level, | ||
480 | .reg_cache_size = ARRAY_SIZE(ak4535_reg), | ||
481 | .reg_word_size = sizeof(u8), | ||
482 | .reg_cache_default = ak4535_reg, | ||
483 | }; | ||
497 | 484 | ||
498 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 485 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
499 | 486 | static __devinit int ak4535_i2c_probe(struct i2c_client *i2c, | |
500 | static int ak4535_i2c_probe(struct i2c_client *i2c, | 487 | const struct i2c_device_id *id) |
501 | const struct i2c_device_id *id) | ||
502 | { | 488 | { |
503 | struct snd_soc_device *socdev = ak4535_socdev; | 489 | struct ak4535_priv *ak4535; |
504 | struct snd_soc_codec *codec = socdev->card->codec; | ||
505 | int ret; | 490 | int ret; |
506 | 491 | ||
507 | i2c_set_clientdata(i2c, codec); | 492 | ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL); |
508 | codec->control_data = i2c; | 493 | if (ak4535 == NULL) |
494 | return -ENOMEM; | ||
509 | 495 | ||
510 | ret = ak4535_init(socdev); | 496 | i2c_set_clientdata(i2c, ak4535); |
511 | if (ret < 0) | 497 | ak4535->control_data = i2c; |
512 | printk(KERN_ERR "failed to initialise AK4535\n"); | 498 | ak4535->control_type = SND_SOC_I2C; |
513 | 499 | ||
500 | ret = snd_soc_register_codec(&i2c->dev, | ||
501 | &soc_codec_dev_ak4535, &ak4535_dai, 1); | ||
502 | if (ret < 0) | ||
503 | kfree(ak4535); | ||
514 | return ret; | 504 | return ret; |
515 | } | 505 | } |
516 | 506 | ||
517 | static int ak4535_i2c_remove(struct i2c_client *client) | 507 | static __devexit int ak4535_i2c_remove(struct i2c_client *client) |
518 | { | 508 | { |
519 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 509 | snd_soc_unregister_codec(&client->dev); |
520 | kfree(codec->reg_cache); | 510 | kfree(i2c_get_clientdata(client)); |
521 | return 0; | 511 | return 0; |
522 | } | 512 | } |
523 | 513 | ||
@@ -529,138 +519,34 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id); | |||
529 | 519 | ||
530 | static struct i2c_driver ak4535_i2c_driver = { | 520 | static struct i2c_driver ak4535_i2c_driver = { |
531 | .driver = { | 521 | .driver = { |
532 | .name = "AK4535 I2C Codec", | 522 | .name = "ak4535-codec", |
533 | .owner = THIS_MODULE, | 523 | .owner = THIS_MODULE, |
534 | }, | 524 | }, |
535 | .probe = ak4535_i2c_probe, | 525 | .probe = ak4535_i2c_probe, |
536 | .remove = ak4535_i2c_remove, | 526 | .remove = __devexit_p(ak4535_i2c_remove), |
537 | .id_table = ak4535_i2c_id, | 527 | .id_table = ak4535_i2c_id, |
538 | }; | 528 | }; |
539 | |||
540 | static int ak4535_add_i2c_device(struct platform_device *pdev, | ||
541 | const struct ak4535_setup_data *setup) | ||
542 | { | ||
543 | struct i2c_board_info info; | ||
544 | struct i2c_adapter *adapter; | ||
545 | struct i2c_client *client; | ||
546 | int ret; | ||
547 | |||
548 | ret = i2c_add_driver(&ak4535_i2c_driver); | ||
549 | if (ret != 0) { | ||
550 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
551 | return ret; | ||
552 | } | ||
553 | |||
554 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
555 | info.addr = setup->i2c_address; | ||
556 | strlcpy(info.type, "ak4535", I2C_NAME_SIZE); | ||
557 | |||
558 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
559 | if (!adapter) { | ||
560 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
561 | setup->i2c_bus); | ||
562 | goto err_driver; | ||
563 | } | ||
564 | |||
565 | client = i2c_new_device(adapter, &info); | ||
566 | i2c_put_adapter(adapter); | ||
567 | if (!client) { | ||
568 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
569 | (unsigned int)info.addr); | ||
570 | goto err_driver; | ||
571 | } | ||
572 | |||
573 | return 0; | ||
574 | |||
575 | err_driver: | ||
576 | i2c_del_driver(&ak4535_i2c_driver); | ||
577 | return -ENODEV; | ||
578 | } | ||
579 | #endif | 529 | #endif |
580 | 530 | ||
581 | static int ak4535_probe(struct platform_device *pdev) | 531 | static int __init ak4535_modinit(void) |
582 | { | 532 | { |
583 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 533 | int ret = 0; |
584 | struct ak4535_setup_data *setup; | ||
585 | struct snd_soc_codec *codec; | ||
586 | struct ak4535_priv *ak4535; | ||
587 | int ret; | ||
588 | |||
589 | printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION); | ||
590 | |||
591 | setup = socdev->codec_data; | ||
592 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
593 | if (codec == NULL) | ||
594 | return -ENOMEM; | ||
595 | |||
596 | ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL); | ||
597 | if (ak4535 == NULL) { | ||
598 | kfree(codec); | ||
599 | return -ENOMEM; | ||
600 | } | ||
601 | |||
602 | snd_soc_codec_set_drvdata(codec, ak4535); | ||
603 | socdev->card->codec = codec; | ||
604 | mutex_init(&codec->mutex); | ||
605 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
606 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
607 | |||
608 | ak4535_socdev = socdev; | ||
609 | ret = -ENODEV; | ||
610 | |||
611 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 534 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
612 | if (setup->i2c_address) { | 535 | ret = i2c_add_driver(&ak4535_i2c_driver); |
613 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
614 | ret = ak4535_add_i2c_device(pdev, setup); | ||
615 | } | ||
616 | #endif | ||
617 | |||
618 | if (ret != 0) { | 536 | if (ret != 0) { |
619 | kfree(snd_soc_codec_get_drvdata(codec)); | 537 | printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n", |
620 | kfree(codec); | 538 | ret); |
621 | } | 539 | } |
540 | #endif | ||
622 | return ret; | 541 | return ret; |
623 | } | 542 | } |
543 | module_init(ak4535_modinit); | ||
624 | 544 | ||
625 | /* power down chip */ | 545 | static void __exit ak4535_exit(void) |
626 | static int ak4535_remove(struct platform_device *pdev) | ||
627 | { | 546 | { |
628 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
629 | struct snd_soc_codec *codec = socdev->card->codec; | ||
630 | |||
631 | if (codec->control_data) | ||
632 | ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
633 | |||
634 | snd_soc_free_pcms(socdev); | ||
635 | snd_soc_dapm_free(socdev); | ||
636 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 547 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
637 | if (codec->control_data) | ||
638 | i2c_unregister_device(codec->control_data); | ||
639 | i2c_del_driver(&ak4535_i2c_driver); | 548 | i2c_del_driver(&ak4535_i2c_driver); |
640 | #endif | 549 | #endif |
641 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
642 | kfree(codec); | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | struct snd_soc_codec_device soc_codec_dev_ak4535 = { | ||
648 | .probe = ak4535_probe, | ||
649 | .remove = ak4535_remove, | ||
650 | .suspend = ak4535_suspend, | ||
651 | .resume = ak4535_resume, | ||
652 | }; | ||
653 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535); | ||
654 | |||
655 | static int __init ak4535_modinit(void) | ||
656 | { | ||
657 | return snd_soc_register_dai(&ak4535_dai); | ||
658 | } | ||
659 | module_init(ak4535_modinit); | ||
660 | |||
661 | static void __exit ak4535_exit(void) | ||
662 | { | ||
663 | snd_soc_unregister_dai(&ak4535_dai); | ||
664 | } | 550 | } |
665 | module_exit(ak4535_exit); | 551 | module_exit(ak4535_exit); |
666 | 552 | ||
diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h index c7a58703ea39..0431e5f634a2 100644 --- a/sound/soc/codecs/ak4535.h +++ b/sound/soc/codecs/ak4535.h | |||
@@ -36,12 +36,4 @@ | |||
36 | 36 | ||
37 | #define AK4535_CACHEREGNUM 0x10 | 37 | #define AK4535_CACHEREGNUM 0x10 |
38 | 38 | ||
39 | struct ak4535_setup_data { | ||
40 | int i2c_bus; | ||
41 | unsigned short i2c_address; | ||
42 | }; | ||
43 | |||
44 | extern struct snd_soc_dai ak4535_dai; | ||
45 | extern struct snd_soc_codec_device soc_codec_dev_ak4535; | ||
46 | |||
47 | #endif | 39 | #endif |
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 3d7dc55305ec..31b35e967398 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #include <sound/initval.h> | 30 | #include <sound/initval.h> |
31 | #include <sound/tlv.h> | 31 | #include <sound/tlv.h> |
32 | 32 | ||
33 | #include "ak4642.h" | ||
34 | |||
35 | #define AK4642_VERSION "0.0.1" | 33 | #define AK4642_VERSION "0.0.1" |
36 | 34 | ||
37 | #define PW_MGMT1 0x00 | 35 | #define PW_MGMT1 0x00 |
@@ -102,7 +100,6 @@ | |||
102 | #define FS3 (1 << 5) | 100 | #define FS3 (1 << 5) |
103 | #define FS_MASK (FS0 | FS1 | FS2 | FS3) | 101 | #define FS_MASK (FS0 | FS1 | FS2 | FS3) |
104 | 102 | ||
105 | struct snd_soc_codec_device soc_codec_dev_ak4642; | ||
106 | 103 | ||
107 | /* | 104 | /* |
108 | * Playback Volume (table 39) | 105 | * Playback Volume (table 39) |
@@ -123,11 +120,11 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = { | |||
123 | 120 | ||
124 | /* codec private data */ | 121 | /* codec private data */ |
125 | struct ak4642_priv { | 122 | struct ak4642_priv { |
126 | struct snd_soc_codec codec; | 123 | unsigned int sysclk; |
124 | enum snd_soc_control_type control_type; | ||
125 | void *control_data; | ||
127 | }; | 126 | }; |
128 | 127 | ||
129 | static struct snd_soc_codec *ak4642_codec; | ||
130 | |||
131 | /* | 128 | /* |
132 | * ak4642 register cache | 129 | * ak4642 register cache |
133 | */ | 130 | */ |
@@ -393,8 +390,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = { | |||
393 | .hw_params = ak4642_dai_hw_params, | 390 | .hw_params = ak4642_dai_hw_params, |
394 | }; | 391 | }; |
395 | 392 | ||
396 | struct snd_soc_dai ak4642_dai = { | 393 | static struct snd_soc_dai_driver ak4642_dai = { |
397 | .name = "AK4642", | 394 | .name = "ak4642-hifi", |
398 | .playback = { | 395 | .playback = { |
399 | .stream_name = "Playback", | 396 | .stream_name = "Playback", |
400 | .channels_min = 1, | 397 | .channels_min = 1, |
@@ -410,112 +407,63 @@ struct snd_soc_dai ak4642_dai = { | |||
410 | .ops = &ak4642_dai_ops, | 407 | .ops = &ak4642_dai_ops, |
411 | .symmetric_rates = 1, | 408 | .symmetric_rates = 1, |
412 | }; | 409 | }; |
413 | EXPORT_SYMBOL_GPL(ak4642_dai); | ||
414 | 410 | ||
415 | static int ak4642_resume(struct platform_device *pdev) | 411 | static int ak4642_resume(struct snd_soc_codec *codec) |
416 | { | 412 | { |
417 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
418 | struct snd_soc_codec *codec = socdev->card->codec; | ||
419 | |||
420 | ak4642_sync(codec); | 413 | ak4642_sync(codec); |
421 | return 0; | 414 | return 0; |
422 | } | 415 | } |
423 | 416 | ||
424 | /* | 417 | |
425 | * initialise the AK4642 driver | 418 | static int ak4642_probe(struct snd_soc_codec *codec) |
426 | * register the mixer and dsp interfaces with the kernel | ||
427 | */ | ||
428 | static int ak4642_init(struct ak4642_priv *ak4642) | ||
429 | { | 419 | { |
430 | struct snd_soc_codec *codec = &ak4642->codec; | 420 | struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec); |
431 | int ret = 0; | ||
432 | 421 | ||
433 | if (ak4642_codec) { | 422 | dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION); |
434 | dev_err(codec->dev, "Another ak4642 is registered\n"); | ||
435 | return -EINVAL; | ||
436 | } | ||
437 | 423 | ||
438 | mutex_init(&codec->mutex); | ||
439 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
440 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
441 | |||
442 | snd_soc_codec_set_drvdata(codec, ak4642); | ||
443 | codec->name = "AK4642"; | ||
444 | codec->owner = THIS_MODULE; | ||
445 | codec->read = ak4642_read_reg_cache; | ||
446 | codec->write = ak4642_write; | ||
447 | codec->dai = &ak4642_dai; | ||
448 | codec->num_dai = 1; | ||
449 | codec->hw_write = (hw_write_t)i2c_master_send; | 424 | codec->hw_write = (hw_write_t)i2c_master_send; |
450 | codec->reg_cache_size = ARRAY_SIZE(ak4642_reg); | 425 | codec->control_data = ak4642->control_data; |
451 | codec->reg_cache = kmemdup(ak4642_reg, | ||
452 | sizeof(ak4642_reg), GFP_KERNEL); | ||
453 | |||
454 | if (!codec->reg_cache) | ||
455 | return -ENOMEM; | ||
456 | |||
457 | ak4642_dai.dev = codec->dev; | ||
458 | ak4642_codec = codec; | ||
459 | |||
460 | ret = snd_soc_register_codec(codec); | ||
461 | if (ret) { | ||
462 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
463 | goto reg_cache_err; | ||
464 | } | ||
465 | 426 | ||
466 | ret = snd_soc_register_dai(&ak4642_dai); | ||
467 | if (ret) { | ||
468 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
469 | snd_soc_unregister_codec(codec); | ||
470 | goto reg_cache_err; | ||
471 | } | ||
472 | |||
473 | return ret; | ||
474 | |||
475 | reg_cache_err: | ||
476 | kfree(codec->reg_cache); | ||
477 | codec->reg_cache = NULL; | ||
478 | 427 | ||
479 | return ret; | 428 | return 0; |
480 | } | 429 | } |
481 | 430 | ||
431 | static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { | ||
432 | .probe = ak4642_probe, | ||
433 | .resume = ak4642_resume, | ||
434 | .read = ak4642_read_reg_cache, | ||
435 | .write = ak4642_write, | ||
436 | .reg_cache_size = ARRAY_SIZE(ak4642_reg), | ||
437 | .reg_word_size = sizeof(u8), | ||
438 | .reg_cache_default = ak4642_reg, | ||
439 | }; | ||
440 | |||
482 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 441 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
483 | static int ak4642_i2c_probe(struct i2c_client *i2c, | 442 | static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, |
484 | const struct i2c_device_id *id) | 443 | const struct i2c_device_id *id) |
485 | { | 444 | { |
486 | struct ak4642_priv *ak4642; | 445 | struct ak4642_priv *ak4642; |
487 | struct snd_soc_codec *codec; | ||
488 | int ret; | 446 | int ret; |
489 | 447 | ||
490 | ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); | 448 | ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); |
491 | if (!ak4642) | 449 | if (ak4642 == NULL) |
492 | return -ENOMEM; | 450 | return -ENOMEM; |
493 | 451 | ||
494 | codec = &ak4642->codec; | ||
495 | codec->dev = &i2c->dev; | ||
496 | |||
497 | i2c_set_clientdata(i2c, ak4642); | 452 | i2c_set_clientdata(i2c, ak4642); |
498 | codec->control_data = i2c; | 453 | ak4642->control_data = i2c; |
454 | ak4642->control_type = SND_SOC_I2C; | ||
499 | 455 | ||
500 | ret = ak4642_init(ak4642); | 456 | ret = snd_soc_register_codec(&i2c->dev, |
501 | if (ret < 0) { | 457 | &soc_codec_dev_ak4642, &ak4642_dai, 1); |
502 | printk(KERN_ERR "failed to initialise AK4642\n"); | 458 | if (ret < 0) |
503 | kfree(ak4642); | 459 | kfree(ak4642); |
504 | } | ||
505 | |||
506 | return ret; | 460 | return ret; |
507 | } | 461 | } |
508 | 462 | ||
509 | static int ak4642_i2c_remove(struct i2c_client *client) | 463 | static __devexit int ak4642_i2c_remove(struct i2c_client *client) |
510 | { | 464 | { |
511 | struct ak4642_priv *ak4642 = i2c_get_clientdata(client); | 465 | snd_soc_unregister_codec(&client->dev); |
512 | 466 | kfree(i2c_get_clientdata(client)); | |
513 | snd_soc_unregister_dai(&ak4642_dai); | ||
514 | snd_soc_unregister_codec(&ak4642->codec); | ||
515 | kfree(ak4642->codec.reg_cache); | ||
516 | kfree(ak4642); | ||
517 | ak4642_codec = NULL; | ||
518 | |||
519 | return 0; | 467 | return 0; |
520 | } | 468 | } |
521 | 469 | ||
@@ -528,64 +476,15 @@ MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id); | |||
528 | 476 | ||
529 | static struct i2c_driver ak4642_i2c_driver = { | 477 | static struct i2c_driver ak4642_i2c_driver = { |
530 | .driver = { | 478 | .driver = { |
531 | .name = "AK4642 I2C Codec", | 479 | .name = "ak4642-codec", |
532 | .owner = THIS_MODULE, | 480 | .owner = THIS_MODULE, |
533 | }, | 481 | }, |
534 | .probe = ak4642_i2c_probe, | 482 | .probe = ak4642_i2c_probe, |
535 | .remove = ak4642_i2c_remove, | 483 | .remove = __devexit_p(ak4642_i2c_remove), |
536 | .id_table = ak4642_i2c_id, | 484 | .id_table = ak4642_i2c_id, |
537 | }; | 485 | }; |
538 | |||
539 | #endif | 486 | #endif |
540 | 487 | ||
541 | static int ak4642_probe(struct platform_device *pdev) | ||
542 | { | ||
543 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
544 | int ret; | ||
545 | |||
546 | if (!ak4642_codec) { | ||
547 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
548 | return -ENODEV; | ||
549 | } | ||
550 | |||
551 | socdev->card->codec = ak4642_codec; | ||
552 | |||
553 | /* register pcms */ | ||
554 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
555 | if (ret < 0) { | ||
556 | printk(KERN_ERR "ak4642: failed to create pcms\n"); | ||
557 | goto pcm_err; | ||
558 | } | ||
559 | |||
560 | snd_soc_add_controls(ak4642_codec, ak4642_snd_controls, | ||
561 | ARRAY_SIZE(ak4642_snd_controls)); | ||
562 | |||
563 | dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION); | ||
564 | return ret; | ||
565 | |||
566 | pcm_err: | ||
567 | return ret; | ||
568 | |||
569 | } | ||
570 | |||
571 | /* power down chip */ | ||
572 | static int ak4642_remove(struct platform_device *pdev) | ||
573 | { | ||
574 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
575 | |||
576 | snd_soc_free_pcms(socdev); | ||
577 | snd_soc_dapm_free(socdev); | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | struct snd_soc_codec_device soc_codec_dev_ak4642 = { | ||
583 | .probe = ak4642_probe, | ||
584 | .remove = ak4642_remove, | ||
585 | .resume = ak4642_resume, | ||
586 | }; | ||
587 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642); | ||
588 | |||
589 | static int __init ak4642_modinit(void) | 488 | static int __init ak4642_modinit(void) |
590 | { | 489 | { |
591 | int ret = 0; | 490 | int ret = 0; |
diff --git a/sound/soc/codecs/ak4642.h b/sound/soc/codecs/ak4642.h deleted file mode 100644 index e476833d314e..000000000000 --- a/sound/soc/codecs/ak4642.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | /* | ||
2 | * ak4642.h -- AK4642 Soc Audio driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <morimoto.kuninori@renesas.com> | ||
6 | * | ||
7 | * Based on ak4535.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #ifndef _AK4642_H | ||
15 | #define _AK4642_H | ||
16 | |||
17 | extern struct snd_soc_dai ak4642_dai; | ||
18 | extern struct snd_soc_codec_device soc_codec_dev_ak4642; | ||
19 | |||
20 | #endif | ||
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 87566932a3b1..239f0562003c 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c | |||
@@ -23,11 +23,11 @@ | |||
23 | 23 | ||
24 | #include "ak4671.h" | 24 | #include "ak4671.h" |
25 | 25 | ||
26 | static struct snd_soc_codec *ak4671_codec; | ||
27 | 26 | ||
28 | /* codec private data */ | 27 | /* codec private data */ |
29 | struct ak4671_priv { | 28 | struct ak4671_priv { |
30 | struct snd_soc_codec codec; | 29 | enum snd_soc_control_type control_type; |
30 | void *control_data; | ||
31 | u8 reg_cache[AK4671_CACHEREGNUM]; | 31 | u8 reg_cache[AK4671_CACHEREGNUM]; |
32 | }; | 32 | }; |
33 | 33 | ||
@@ -619,8 +619,8 @@ static struct snd_soc_dai_ops ak4671_dai_ops = { | |||
619 | .set_fmt = ak4671_set_dai_fmt, | 619 | .set_fmt = ak4671_set_dai_fmt, |
620 | }; | 620 | }; |
621 | 621 | ||
622 | struct snd_soc_dai ak4671_dai = { | 622 | static struct snd_soc_dai_driver ak4671_dai = { |
623 | .name = "AK4671", | 623 | .name = "ak4671-hifi", |
624 | .playback = { | 624 | .playback = { |
625 | .stream_name = "Playback", | 625 | .stream_name = "Playback", |
626 | .channels_min = 1, | 626 | .channels_min = 1, |
@@ -635,27 +635,19 @@ struct snd_soc_dai ak4671_dai = { | |||
635 | .formats = AK4671_FORMATS,}, | 635 | .formats = AK4671_FORMATS,}, |
636 | .ops = &ak4671_dai_ops, | 636 | .ops = &ak4671_dai_ops, |
637 | }; | 637 | }; |
638 | EXPORT_SYMBOL_GPL(ak4671_dai); | ||
639 | 638 | ||
640 | static int ak4671_probe(struct platform_device *pdev) | 639 | static int ak4671_probe(struct snd_soc_codec *codec) |
641 | { | 640 | { |
642 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 641 | struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec); |
643 | struct snd_soc_codec *codec; | 642 | int ret; |
644 | int ret = 0; | ||
645 | |||
646 | if (ak4671_codec == NULL) { | ||
647 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
648 | return -ENODEV; | ||
649 | } | ||
650 | 643 | ||
651 | socdev->card->codec = ak4671_codec; | 644 | codec->hw_write = (hw_write_t)i2c_master_send; |
652 | codec = ak4671_codec; | 645 | codec->bias_level = SND_SOC_BIAS_OFF; |
653 | 646 | ||
654 | /* register pcms */ | 647 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type); |
655 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
656 | if (ret < 0) { | 648 | if (ret < 0) { |
657 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | 649 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
658 | goto pcm_err; | 650 | return ret; |
659 | } | 651 | } |
660 | 652 | ||
661 | snd_soc_add_controls(codec, ak4671_snd_controls, | 653 | snd_soc_add_controls(codec, ak4671_snd_controls, |
@@ -665,121 +657,48 @@ static int ak4671_probe(struct platform_device *pdev) | |||
665 | ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 657 | ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
666 | 658 | ||
667 | return ret; | 659 | return ret; |
668 | |||
669 | pcm_err: | ||
670 | return ret; | ||
671 | } | 660 | } |
672 | 661 | ||
673 | static int ak4671_remove(struct platform_device *pdev) | 662 | static int ak4671_remove(struct snd_soc_codec *codec) |
674 | { | 663 | { |
675 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 664 | ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF); |
676 | |||
677 | snd_soc_free_pcms(socdev); | ||
678 | snd_soc_dapm_free(socdev); | ||
679 | |||
680 | return 0; | 665 | return 0; |
681 | } | 666 | } |
682 | 667 | ||
683 | struct snd_soc_codec_device soc_codec_dev_ak4671 = { | 668 | static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { |
684 | .probe = ak4671_probe, | 669 | .probe = ak4671_probe, |
685 | .remove = ak4671_remove, | 670 | .remove = ak4671_remove, |
671 | .set_bias_level = ak4671_set_bias_level, | ||
672 | .reg_cache_size = AK4671_CACHEREGNUM, | ||
673 | .reg_word_size = sizeof(u8), | ||
674 | .reg_cache_default = ak4671_reg, | ||
686 | }; | 675 | }; |
687 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671); | ||
688 | |||
689 | static int ak4671_register(struct ak4671_priv *ak4671, | ||
690 | enum snd_soc_control_type control) | ||
691 | { | ||
692 | int ret; | ||
693 | struct snd_soc_codec *codec = &ak4671->codec; | ||
694 | |||
695 | if (ak4671_codec) { | ||
696 | dev_err(codec->dev, "Another AK4671 is registered\n"); | ||
697 | ret = -EINVAL; | ||
698 | goto err; | ||
699 | } | ||
700 | |||
701 | mutex_init(&codec->mutex); | ||
702 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
703 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
704 | |||
705 | snd_soc_codec_set_drvdata(codec, ak4671); | ||
706 | codec->name = "AK4671"; | ||
707 | codec->owner = THIS_MODULE; | ||
708 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
709 | codec->set_bias_level = ak4671_set_bias_level; | ||
710 | codec->dai = &ak4671_dai; | ||
711 | codec->num_dai = 1; | ||
712 | codec->reg_cache_size = AK4671_CACHEREGNUM; | ||
713 | codec->reg_cache = &ak4671->reg_cache; | ||
714 | |||
715 | memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg)); | ||
716 | |||
717 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, control); | ||
718 | if (ret < 0) { | ||
719 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
720 | goto err; | ||
721 | } | ||
722 | |||
723 | ak4671_dai.dev = codec->dev; | ||
724 | ak4671_codec = codec; | ||
725 | |||
726 | ret = snd_soc_register_codec(codec); | ||
727 | if (ret != 0) { | ||
728 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
729 | goto err; | ||
730 | } | ||
731 | |||
732 | ret = snd_soc_register_dai(&ak4671_dai); | ||
733 | if (ret != 0) { | ||
734 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
735 | goto err_codec; | ||
736 | } | ||
737 | |||
738 | return 0; | ||
739 | |||
740 | err_codec: | ||
741 | snd_soc_unregister_codec(codec); | ||
742 | err: | ||
743 | kfree(ak4671); | ||
744 | return ret; | ||
745 | } | ||
746 | |||
747 | static void ak4671_unregister(struct ak4671_priv *ak4671) | ||
748 | { | ||
749 | ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF); | ||
750 | snd_soc_unregister_dai(&ak4671_dai); | ||
751 | snd_soc_unregister_codec(&ak4671->codec); | ||
752 | kfree(ak4671); | ||
753 | ak4671_codec = NULL; | ||
754 | } | ||
755 | 676 | ||
756 | static int __devinit ak4671_i2c_probe(struct i2c_client *client, | 677 | static int __devinit ak4671_i2c_probe(struct i2c_client *client, |
757 | const struct i2c_device_id *id) | 678 | const struct i2c_device_id *id) |
758 | { | 679 | { |
759 | struct ak4671_priv *ak4671; | 680 | struct ak4671_priv *ak4671; |
760 | struct snd_soc_codec *codec; | 681 | int ret; |
761 | 682 | ||
762 | ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL); | 683 | ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL); |
763 | if (ak4671 == NULL) | 684 | if (ak4671 == NULL) |
764 | return -ENOMEM; | 685 | return -ENOMEM; |
765 | 686 | ||
766 | codec = &ak4671->codec; | ||
767 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
768 | |||
769 | i2c_set_clientdata(client, ak4671); | 687 | i2c_set_clientdata(client, ak4671); |
770 | codec->control_data = client; | 688 | ak4671->control_data = client; |
771 | 689 | ak4671->control_type = SND_SOC_I2C; | |
772 | codec->dev = &client->dev; | ||
773 | 690 | ||
774 | return ak4671_register(ak4671, SND_SOC_I2C); | 691 | ret = snd_soc_register_codec(&client->dev, |
692 | &soc_codec_dev_ak4671, &ak4671_dai, 1); | ||
693 | if (ret < 0) | ||
694 | kfree(ak4671); | ||
695 | return ret; | ||
775 | } | 696 | } |
776 | 697 | ||
777 | static __devexit int ak4671_i2c_remove(struct i2c_client *client) | 698 | static __devexit int ak4671_i2c_remove(struct i2c_client *client) |
778 | { | 699 | { |
779 | struct ak4671_priv *ak4671 = i2c_get_clientdata(client); | 700 | snd_soc_unregister_codec(&client->dev); |
780 | 701 | kfree(i2c_get_clientdata(client)); | |
781 | ak4671_unregister(ak4671); | ||
782 | |||
783 | return 0; | 702 | return 0; |
784 | } | 703 | } |
785 | 704 | ||
@@ -791,7 +710,7 @@ MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id); | |||
791 | 710 | ||
792 | static struct i2c_driver ak4671_i2c_driver = { | 711 | static struct i2c_driver ak4671_i2c_driver = { |
793 | .driver = { | 712 | .driver = { |
794 | .name = "ak4671", | 713 | .name = "ak4671-codec", |
795 | .owner = THIS_MODULE, | 714 | .owner = THIS_MODULE, |
796 | }, | 715 | }, |
797 | .probe = ak4671_i2c_probe, | 716 | .probe = ak4671_i2c_probe, |
diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h index e2fad964e88b..61cb7ab7552c 100644 --- a/sound/soc/codecs/ak4671.h +++ b/sound/soc/codecs/ak4671.h | |||
@@ -150,7 +150,4 @@ | |||
150 | /* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */ | 150 | /* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */ |
151 | #define AK4671_MUTEN 0x04 | 151 | #define AK4671_MUTEN 0x04 |
152 | 152 | ||
153 | extern struct snd_soc_dai ak4671_dai; | ||
154 | extern struct snd_soc_codec_device soc_codec_dev_ak4671; | ||
155 | |||
156 | #endif | 153 | #endif |
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index a320fb5a0e26..823643932dde 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/clk.h> | 31 | #include <linux/clk.h> |
32 | #include <linux/mfd/davinci_voicecodec.h> | 32 | #include <linux/mfd/davinci_voicecodec.h> |
33 | #include <linux/spi/spi.h> | ||
33 | 34 | ||
34 | #include <sound/core.h> | 35 | #include <sound/core.h> |
35 | #include <sound/pcm.h> | 36 | #include <sound/pcm.h> |
@@ -41,8 +42,6 @@ | |||
41 | 42 | ||
42 | #include <mach/dm365.h> | 43 | #include <mach/dm365.h> |
43 | 44 | ||
44 | #include "cq93vc.h" | ||
45 | |||
46 | static inline unsigned int cq93vc_read(struct snd_soc_codec *codec, | 45 | static inline unsigned int cq93vc_read(struct snd_soc_codec *codec, |
47 | unsigned int reg) | 46 | unsigned int reg) |
48 | { | 47 | { |
@@ -130,8 +129,8 @@ static struct snd_soc_dai_ops cq93vc_dai_ops = { | |||
130 | .set_sysclk = cq93vc_set_dai_sysclk, | 129 | .set_sysclk = cq93vc_set_dai_sysclk, |
131 | }; | 130 | }; |
132 | 131 | ||
133 | struct snd_soc_dai cq93vc_dai = { | 132 | static struct snd_soc_dai_driver cq93vc_dai = { |
134 | .name = "CQ93VC", | 133 | .name = "cq93vc-hifi", |
135 | .playback = { | 134 | .playback = { |
136 | .stream_name = "Playback", | 135 | .stream_name = "Playback", |
137 | .channels_min = 1, | 136 | .channels_min = 1, |
@@ -146,36 +145,20 @@ struct snd_soc_dai cq93vc_dai = { | |||
146 | .formats = CQ93VC_FORMATS,}, | 145 | .formats = CQ93VC_FORMATS,}, |
147 | .ops = &cq93vc_dai_ops, | 146 | .ops = &cq93vc_dai_ops, |
148 | }; | 147 | }; |
149 | EXPORT_SYMBOL_GPL(cq93vc_dai); | ||
150 | 148 | ||
151 | static int cq93vc_resume(struct platform_device *pdev) | 149 | static int cq93vc_resume(struct snd_soc_codec *codec) |
152 | { | 150 | { |
153 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
154 | struct snd_soc_codec *codec = socdev->card->codec; | ||
155 | |||
156 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 151 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
157 | 152 | ||
158 | return 0; | 153 | return 0; |
159 | } | 154 | } |
160 | 155 | ||
161 | static struct snd_soc_codec *cq93vc_codec; | 156 | static int cq93vc_probe(struct snd_soc_codec *codec) |
162 | |||
163 | static int cq93vc_probe(struct platform_device *pdev) | ||
164 | { | 157 | { |
165 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 158 | struct davinci_vc *davinci_vc = codec->dev->platform_data; |
166 | struct device *dev = &pdev->dev; | 159 | |
167 | struct snd_soc_codec *codec; | 160 | davinci_vc->cq93vc.codec = codec; |
168 | int ret; | 161 | codec->control_data = davinci_vc; |
169 | |||
170 | socdev->card->codec = cq93vc_codec; | ||
171 | codec = socdev->card->codec; | ||
172 | |||
173 | /* Register pcms */ | ||
174 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
175 | if (ret < 0) { | ||
176 | dev_err(dev, "%s: failed to create pcms\n", pdev->name); | ||
177 | return ret; | ||
178 | } | ||
179 | 162 | ||
180 | /* Set controls */ | 163 | /* Set controls */ |
181 | snd_soc_add_controls(codec, cq93vc_snd_controls, | 164 | snd_soc_add_controls(codec, cq93vc_snd_controls, |
@@ -187,108 +170,51 @@ static int cq93vc_probe(struct platform_device *pdev) | |||
187 | return 0; | 170 | return 0; |
188 | } | 171 | } |
189 | 172 | ||
190 | static int cq93vc_remove(struct platform_device *pdev) | 173 | static int cq93vc_remove(struct snd_soc_codec *codec) |
191 | { | 174 | { |
192 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 175 | cq93vc_set_bias_level(codec, SND_SOC_BIAS_OFF); |
193 | |||
194 | snd_soc_free_pcms(socdev); | ||
195 | snd_soc_dapm_free(socdev); | ||
196 | 176 | ||
197 | return 0; | 177 | return 0; |
198 | } | 178 | } |
199 | 179 | ||
200 | struct snd_soc_codec_device soc_codec_dev_cq93vc = { | 180 | static struct snd_soc_codec_driver soc_codec_dev_cq93vc = { |
181 | .read = cq93vc_read, | ||
182 | .write = cq93vc_write, | ||
183 | .set_bias_level = cq93vc_set_bias_level, | ||
201 | .probe = cq93vc_probe, | 184 | .probe = cq93vc_probe, |
202 | .remove = cq93vc_remove, | 185 | .remove = cq93vc_remove, |
203 | .resume = cq93vc_resume, | 186 | .resume = cq93vc_resume, |
204 | }; | 187 | }; |
205 | EXPORT_SYMBOL_GPL(soc_codec_dev_cq93vc); | ||
206 | 188 | ||
207 | static __init int cq93vc_codec_probe(struct platform_device *pdev) | 189 | static int cq93vc_platform_probe(struct platform_device *pdev) |
208 | { | 190 | { |
209 | struct davinci_vc *davinci_vc = platform_get_drvdata(pdev); | 191 | return snd_soc_register_codec(&pdev->dev, |
210 | struct snd_soc_codec *codec; | 192 | &soc_codec_dev_cq93vc, &cq93vc_dai, 1); |
211 | int ret; | ||
212 | |||
213 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
214 | if (codec == NULL) { | ||
215 | dev_dbg(davinci_vc->dev, | ||
216 | "could not allocate memory for codec data\n"); | ||
217 | return -ENOMEM; | ||
218 | } | ||
219 | |||
220 | davinci_vc->cq93vc.codec = codec; | ||
221 | |||
222 | cq93vc_dai.dev = &pdev->dev; | ||
223 | |||
224 | mutex_init(&codec->mutex); | ||
225 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
226 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
227 | codec->dev = &pdev->dev; | ||
228 | codec->name = "CQ93VC"; | ||
229 | codec->owner = THIS_MODULE; | ||
230 | codec->read = cq93vc_read; | ||
231 | codec->write = cq93vc_write; | ||
232 | codec->set_bias_level = cq93vc_set_bias_level; | ||
233 | codec->dai = &cq93vc_dai; | ||
234 | codec->num_dai = 1; | ||
235 | codec->control_data = davinci_vc; | ||
236 | |||
237 | cq93vc_codec = codec; | ||
238 | |||
239 | ret = snd_soc_register_codec(codec); | ||
240 | if (ret) { | ||
241 | dev_err(davinci_vc->dev, "failed to register codec\n"); | ||
242 | goto fail1; | ||
243 | } | ||
244 | |||
245 | ret = snd_soc_register_dai(&cq93vc_dai); | ||
246 | if (ret) { | ||
247 | dev_err(davinci_vc->dev, "could register dai\n"); | ||
248 | goto fail2; | ||
249 | } | ||
250 | return 0; | ||
251 | |||
252 | fail2: | ||
253 | snd_soc_unregister_codec(codec); | ||
254 | |||
255 | fail1: | ||
256 | kfree(codec); | ||
257 | cq93vc_codec = NULL; | ||
258 | |||
259 | return ret; | ||
260 | } | 193 | } |
261 | 194 | ||
262 | static int __devexit cq93vc_codec_remove(struct platform_device *pdev) | 195 | static int cq93vc_platform_remove(struct platform_device *pdev) |
263 | { | 196 | { |
264 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 197 | snd_soc_unregister_codec(&pdev->dev); |
265 | struct snd_soc_codec *codec = socdev->card->codec; | ||
266 | |||
267 | snd_soc_unregister_dai(&cq93vc_dai); | ||
268 | snd_soc_unregister_codec(&codec); | ||
269 | |||
270 | kfree(codec); | ||
271 | cq93vc_codec = NULL; | ||
272 | |||
273 | return 0; | 198 | return 0; |
274 | } | 199 | } |
275 | 200 | ||
276 | static struct platform_driver cq93vc_codec_driver = { | 201 | static struct platform_driver cq93vc_codec_driver = { |
277 | .driver = { | 202 | .driver = { |
278 | .name = "cq93vc", | 203 | .name = "cq93vc-codec", |
279 | .owner = THIS_MODULE, | 204 | .owner = THIS_MODULE, |
280 | }, | 205 | }, |
281 | .probe = cq93vc_codec_probe, | 206 | |
282 | .remove = __devexit_p(cq93vc_codec_remove), | 207 | .probe = cq93vc_platform_probe, |
208 | .remove = __devexit_p(cq93vc_platform_remove), | ||
283 | }; | 209 | }; |
284 | 210 | ||
285 | static __init int cq93vc_init(void) | 211 | static int __init cq93vc_init(void) |
286 | { | 212 | { |
287 | return platform_driver_probe(&cq93vc_codec_driver, cq93vc_codec_probe); | 213 | return platform_driver_register(&cq93vc_codec_driver); |
288 | } | 214 | } |
289 | module_init(cq93vc_init); | 215 | module_init(cq93vc_init); |
290 | 216 | ||
291 | static __exit void cq93vc_exit(void) | 217 | static void __exit cq93vc_exit(void) |
292 | { | 218 | { |
293 | platform_driver_unregister(&cq93vc_codec_driver); | 219 | platform_driver_unregister(&cq93vc_codec_driver); |
294 | } | 220 | } |
diff --git a/sound/soc/codecs/cq93vc.h b/sound/soc/codecs/cq93vc.h deleted file mode 100644 index 845b1968ef9c..000000000000 --- a/sound/soc/codecs/cq93vc.h +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments, Inc | ||
5 | * | ||
6 | * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #ifndef _CQ93VC_H | ||
24 | #define _CQ93VC_H | ||
25 | |||
26 | extern struct snd_soc_dai cq93vc_dai; | ||
27 | extern struct snd_soc_codec_device soc_codec_dev_cq93vc; | ||
28 | |||
29 | #endif | ||
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 30d949239def..6542dc038951 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/regulator/consumer.h> | 32 | #include <linux/regulator/consumer.h> |
33 | 33 | ||
34 | #include "cs4270.h" | ||
35 | |||
36 | /* | 34 | /* |
37 | * The codec isn't really big-endian or little-endian, since the I2S | 35 | * The codec isn't really big-endian or little-endian, since the I2S |
38 | * interface requires data to be sent serially with the MSbit first. | 36 | * interface requires data to be sent serially with the MSbit first. |
@@ -114,7 +112,8 @@ static const char *supply_names[] = { | |||
114 | 112 | ||
115 | /* Private data for the CS4270 */ | 113 | /* Private data for the CS4270 */ |
116 | struct cs4270_private { | 114 | struct cs4270_private { |
117 | struct snd_soc_codec codec; | 115 | enum snd_soc_control_type control_type; |
116 | void *control_data; | ||
118 | u8 reg_cache[CS4270_NUMREGS]; | 117 | u8 reg_cache[CS4270_NUMREGS]; |
119 | unsigned int mclk; /* Input frequency of the MCLK pin */ | 118 | unsigned int mclk; /* Input frequency of the MCLK pin */ |
120 | unsigned int mode; /* The mode (I2S or left-justified) */ | 119 | unsigned int mode; /* The mode (I2S or left-justified) */ |
@@ -212,44 +211,8 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
212 | { | 211 | { |
213 | struct snd_soc_codec *codec = codec_dai->codec; | 212 | struct snd_soc_codec *codec = codec_dai->codec; |
214 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 213 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
215 | unsigned int rates = 0; | ||
216 | unsigned int rate_min = -1; | ||
217 | unsigned int rate_max = 0; | ||
218 | unsigned int i; | ||
219 | 214 | ||
220 | cs4270->mclk = freq; | 215 | cs4270->mclk = freq; |
221 | |||
222 | if (cs4270->mclk) { | ||
223 | for (i = 0; i < NUM_MCLK_RATIOS; i++) { | ||
224 | unsigned int rate = freq / cs4270_mode_ratios[i].ratio; | ||
225 | rates |= snd_pcm_rate_to_rate_bit(rate); | ||
226 | if (rate < rate_min) | ||
227 | rate_min = rate; | ||
228 | if (rate > rate_max) | ||
229 | rate_max = rate; | ||
230 | } | ||
231 | /* FIXME: soc should support a rate list */ | ||
232 | rates &= ~SNDRV_PCM_RATE_KNOT; | ||
233 | |||
234 | if (!rates) { | ||
235 | dev_err(codec->dev, "could not find a valid sample rate\n"); | ||
236 | return -EINVAL; | ||
237 | } | ||
238 | } else { | ||
239 | /* enable all possible rates */ | ||
240 | rates = SNDRV_PCM_RATE_8000_192000; | ||
241 | rate_min = 8000; | ||
242 | rate_max = 192000; | ||
243 | } | ||
244 | |||
245 | codec_dai->playback.rates = rates; | ||
246 | codec_dai->playback.rate_min = rate_min; | ||
247 | codec_dai->playback.rate_max = rate_max; | ||
248 | |||
249 | codec_dai->capture.rates = rates; | ||
250 | codec_dai->capture.rate_min = rate_min; | ||
251 | codec_dai->capture.rate_max = rate_max; | ||
252 | |||
253 | return 0; | 216 | return 0; |
254 | } | 217 | } |
255 | 218 | ||
@@ -410,8 +373,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
410 | struct snd_soc_dai *dai) | 373 | struct snd_soc_dai *dai) |
411 | { | 374 | { |
412 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 375 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
413 | struct snd_soc_device *socdev = rtd->socdev; | 376 | struct snd_soc_codec *codec = rtd->codec; |
414 | struct snd_soc_codec *codec = socdev->card->codec; | ||
415 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 377 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
416 | int ret; | 378 | int ret; |
417 | unsigned int i; | 379 | unsigned int i; |
@@ -549,19 +511,6 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = { | |||
549 | snd_soc_get_volsw, cs4270_soc_put_mute), | 511 | snd_soc_get_volsw, cs4270_soc_put_mute), |
550 | }; | 512 | }; |
551 | 513 | ||
552 | /* | ||
553 | * cs4270_codec - global variable to store codec for the ASoC probe function | ||
554 | * | ||
555 | * If struct i2c_driver had a private_data field, we wouldn't need to use | ||
556 | * cs4270_codec. This is the only way to pass the codec structure from | ||
557 | * cs4270_i2c_probe() to cs4270_probe(). Unfortunately, there is no good | ||
558 | * way to synchronize these two functions. cs4270_i2c_probe() can be called | ||
559 | * multiple times before cs4270_probe() is called even once. So for now, we | ||
560 | * also only allow cs4270_i2c_probe() to be run once. That means that we do | ||
561 | * not support more than one cs4270 device in the system, at least for now. | ||
562 | */ | ||
563 | static struct snd_soc_codec *cs4270_codec; | ||
564 | |||
565 | static struct snd_soc_dai_ops cs4270_dai_ops = { | 514 | static struct snd_soc_dai_ops cs4270_dai_ops = { |
566 | .hw_params = cs4270_hw_params, | 515 | .hw_params = cs4270_hw_params, |
567 | .set_sysclk = cs4270_set_dai_sysclk, | 516 | .set_sysclk = cs4270_set_dai_sysclk, |
@@ -569,20 +518,24 @@ static struct snd_soc_dai_ops cs4270_dai_ops = { | |||
569 | .digital_mute = cs4270_dai_mute, | 518 | .digital_mute = cs4270_dai_mute, |
570 | }; | 519 | }; |
571 | 520 | ||
572 | struct snd_soc_dai cs4270_dai = { | 521 | struct snd_soc_dai_driver cs4270_dai = { |
573 | .name = "cs4270", | 522 | .name = "cs4270-hifi", |
574 | .playback = { | 523 | .playback = { |
575 | .stream_name = "Playback", | 524 | .stream_name = "Playback", |
576 | .channels_min = 1, | 525 | .channels_min = 1, |
577 | .channels_max = 2, | 526 | .channels_max = 2, |
578 | .rates = 0, | 527 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
528 | .rate_min = 4000, | ||
529 | .rate_max = 216000, | ||
579 | .formats = CS4270_FORMATS, | 530 | .formats = CS4270_FORMATS, |
580 | }, | 531 | }, |
581 | .capture = { | 532 | .capture = { |
582 | .stream_name = "Capture", | 533 | .stream_name = "Capture", |
583 | .channels_min = 1, | 534 | .channels_min = 1, |
584 | .channels_max = 2, | 535 | .channels_max = 2, |
585 | .rates = 0, | 536 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
537 | .rate_min = 4000, | ||
538 | .rate_max = 216000, | ||
586 | .formats = CS4270_FORMATS, | 539 | .formats = CS4270_FORMATS, |
587 | }, | 540 | }, |
588 | .ops = &cs4270_dai_ops, | 541 | .ops = &cs4270_dai_ops, |
@@ -596,153 +549,19 @@ EXPORT_SYMBOL_GPL(cs4270_dai); | |||
596 | * This function is called when ASoC has all the pieces it needs to | 549 | * This function is called when ASoC has all the pieces it needs to |
597 | * instantiate a sound driver. | 550 | * instantiate a sound driver. |
598 | */ | 551 | */ |
599 | static int cs4270_probe(struct platform_device *pdev) | 552 | static int cs4270_probe(struct snd_soc_codec *codec) |
600 | { | ||
601 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
602 | struct snd_soc_codec *codec = cs4270_codec; | ||
603 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | ||
604 | int i, ret; | ||
605 | |||
606 | /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ | ||
607 | socdev->card->codec = codec; | ||
608 | |||
609 | /* Register PCMs */ | ||
610 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
611 | if (ret < 0) { | ||
612 | dev_err(codec->dev, "failed to create pcms\n"); | ||
613 | return ret; | ||
614 | } | ||
615 | |||
616 | /* Add the non-DAPM controls */ | ||
617 | ret = snd_soc_add_controls(codec, cs4270_snd_controls, | ||
618 | ARRAY_SIZE(cs4270_snd_controls)); | ||
619 | if (ret < 0) { | ||
620 | dev_err(codec->dev, "failed to add controls\n"); | ||
621 | goto error_free_pcms; | ||
622 | } | ||
623 | |||
624 | /* get the power supply regulators */ | ||
625 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
626 | cs4270->supplies[i].supply = supply_names[i]; | ||
627 | |||
628 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), | ||
629 | cs4270->supplies); | ||
630 | if (ret < 0) | ||
631 | goto error_free_pcms; | ||
632 | |||
633 | ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), | ||
634 | cs4270->supplies); | ||
635 | if (ret < 0) | ||
636 | goto error_free_regulators; | ||
637 | |||
638 | return 0; | ||
639 | |||
640 | error_free_regulators: | ||
641 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), | ||
642 | cs4270->supplies); | ||
643 | |||
644 | error_free_pcms: | ||
645 | snd_soc_free_pcms(socdev); | ||
646 | |||
647 | return ret; | ||
648 | } | ||
649 | |||
650 | /** | ||
651 | * cs4270_remove - ASoC remove function | ||
652 | * @pdev: platform device | ||
653 | * | ||
654 | * This function is the counterpart to cs4270_probe(). | ||
655 | */ | ||
656 | static int cs4270_remove(struct platform_device *pdev) | ||
657 | { | 553 | { |
658 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
659 | struct snd_soc_codec *codec = cs4270_codec; | ||
660 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 554 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
555 | int i, ret, reg; | ||
661 | 556 | ||
662 | snd_soc_free_pcms(socdev); | 557 | codec->control_data = cs4270->control_data; |
663 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | ||
664 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | ||
665 | |||
666 | return 0; | ||
667 | }; | ||
668 | |||
669 | /** | ||
670 | * cs4270_i2c_probe - initialize the I2C interface of the CS4270 | ||
671 | * @i2c_client: the I2C client object | ||
672 | * @id: the I2C device ID (ignored) | ||
673 | * | ||
674 | * This function is called whenever the I2C subsystem finds a device that | ||
675 | * matches the device ID given via a prior call to i2c_add_driver(). | ||
676 | */ | ||
677 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, | ||
678 | const struct i2c_device_id *id) | ||
679 | { | ||
680 | struct snd_soc_codec *codec; | ||
681 | struct cs4270_private *cs4270; | ||
682 | unsigned int reg; | ||
683 | int ret; | ||
684 | |||
685 | /* For now, we only support one cs4270 device in the system. See the | ||
686 | * comment for cs4270_codec. | ||
687 | */ | ||
688 | if (cs4270_codec) { | ||
689 | dev_err(&i2c_client->dev, "ignoring CS4270 at addr %X\n", | ||
690 | i2c_client->addr); | ||
691 | dev_err(&i2c_client->dev, "only one per board allowed\n"); | ||
692 | /* Should we return something other than ENODEV here? */ | ||
693 | return -ENODEV; | ||
694 | } | ||
695 | |||
696 | /* Verify that we have a CS4270 */ | ||
697 | |||
698 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | ||
699 | if (ret < 0) { | ||
700 | dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", | ||
701 | i2c_client->addr); | ||
702 | return ret; | ||
703 | } | ||
704 | /* The top four bits of the chip ID should be 1100. */ | ||
705 | if ((ret & 0xF0) != 0xC0) { | ||
706 | dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", | ||
707 | i2c_client->addr); | ||
708 | return -ENODEV; | ||
709 | } | ||
710 | |||
711 | dev_info(&i2c_client->dev, "found device at i2c address %X\n", | ||
712 | i2c_client->addr); | ||
713 | dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); | ||
714 | |||
715 | /* Allocate enough space for the snd_soc_codec structure | ||
716 | and our private data together. */ | ||
717 | cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); | ||
718 | if (!cs4270) { | ||
719 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
720 | return -ENOMEM; | ||
721 | } | ||
722 | codec = &cs4270->codec; | ||
723 | |||
724 | mutex_init(&codec->mutex); | ||
725 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
726 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
727 | |||
728 | codec->dev = &i2c_client->dev; | ||
729 | codec->name = "CS4270"; | ||
730 | codec->owner = THIS_MODULE; | ||
731 | codec->dai = &cs4270_dai; | ||
732 | codec->num_dai = 1; | ||
733 | snd_soc_codec_set_drvdata(codec, cs4270); | ||
734 | codec->control_data = i2c_client; | ||
735 | codec->read = cs4270_read_reg_cache; | ||
736 | codec->write = cs4270_i2c_write; | ||
737 | codec->reg_cache = cs4270->reg_cache; | ||
738 | codec->reg_cache_size = CS4270_NUMREGS; | ||
739 | 558 | ||
740 | /* The I2C interface is set up, so pre-fill our register cache */ | 559 | /* The I2C interface is set up, so pre-fill our register cache */ |
741 | 560 | ||
742 | ret = cs4270_fill_cache(codec); | 561 | ret = cs4270_fill_cache(codec); |
743 | if (ret < 0) { | 562 | if (ret < 0) { |
744 | dev_err(&i2c_client->dev, "failed to fill register cache\n"); | 563 | dev_err(codec->dev, "failed to fill register cache\n"); |
745 | goto error_free_codec; | 564 | return ret; |
746 | } | 565 | } |
747 | 566 | ||
748 | /* Disable auto-mute. This feature appears to be buggy. In some | 567 | /* Disable auto-mute. This feature appears to be buggy. In some |
@@ -755,7 +574,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, | |||
755 | reg &= ~CS4270_MUTE_AUTO; | 574 | reg &= ~CS4270_MUTE_AUTO; |
756 | ret = cs4270_i2c_write(codec, CS4270_MUTE, reg); | 575 | ret = cs4270_i2c_write(codec, CS4270_MUTE, reg); |
757 | if (ret < 0) { | 576 | if (ret < 0) { |
758 | dev_err(&i2c_client->dev, "i2c write failed\n"); | 577 | dev_err(codec->dev, "i2c write failed\n"); |
759 | return ret; | 578 | return ret; |
760 | } | 579 | } |
761 | 580 | ||
@@ -769,65 +588,56 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, | |||
769 | reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); | 588 | reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); |
770 | ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); | 589 | ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); |
771 | if (ret < 0) { | 590 | if (ret < 0) { |
772 | dev_err(&i2c_client->dev, "i2c write failed\n"); | 591 | dev_err(codec->dev, "i2c write failed\n"); |
773 | return ret; | 592 | return ret; |
774 | } | 593 | } |
775 | 594 | ||
776 | /* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI | 595 | /* Add the non-DAPM controls */ |
777 | * structure for each CS4270 device, but the machine driver needs to | 596 | ret = snd_soc_add_controls(codec, cs4270_snd_controls, |
778 | * have a pointer to the DAI structure, so for now it must be a global | 597 | ARRAY_SIZE(cs4270_snd_controls)); |
779 | * variable. | ||
780 | */ | ||
781 | cs4270_dai.dev = &i2c_client->dev; | ||
782 | |||
783 | /* Register the DAI. If all the other ASoC driver have already | ||
784 | * registered, then this will call our probe function, so | ||
785 | * cs4270_codec needs to be ready. | ||
786 | */ | ||
787 | cs4270_codec = codec; | ||
788 | ret = snd_soc_register_dai(&cs4270_dai); | ||
789 | if (ret < 0) { | 598 | if (ret < 0) { |
790 | dev_err(&i2c_client->dev, "failed to register DAIe\n"); | 599 | dev_err(codec->dev, "failed to add controls\n"); |
791 | goto error_free_codec; | 600 | return ret; |
792 | } | 601 | } |
793 | 602 | ||
794 | i2c_set_clientdata(i2c_client, cs4270); | 603 | /* get the power supply regulators */ |
604 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
605 | cs4270->supplies[i].supply = supply_names[i]; | ||
606 | |||
607 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), | ||
608 | cs4270->supplies); | ||
609 | if (ret < 0) | ||
610 | return ret; | ||
611 | |||
612 | ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), | ||
613 | cs4270->supplies); | ||
614 | if (ret < 0) | ||
615 | goto error_free_regulators; | ||
795 | 616 | ||
796 | return 0; | 617 | return 0; |
797 | 618 | ||
798 | error_free_codec: | 619 | error_free_regulators: |
799 | kfree(cs4270); | 620 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), |
800 | cs4270_codec = NULL; | 621 | cs4270->supplies); |
801 | cs4270_dai.dev = NULL; | ||
802 | 622 | ||
803 | return ret; | 623 | return ret; |
804 | } | 624 | } |
805 | 625 | ||
806 | /** | 626 | /** |
807 | * cs4270_i2c_remove - remove an I2C device | 627 | * cs4270_remove - ASoC remove function |
808 | * @i2c_client: the I2C client object | 628 | * @pdev: platform device |
809 | * | 629 | * |
810 | * This function is the counterpart to cs4270_i2c_probe(). | 630 | * This function is the counterpart to cs4270_probe(). |
811 | */ | 631 | */ |
812 | static int cs4270_i2c_remove(struct i2c_client *i2c_client) | 632 | static int cs4270_remove(struct snd_soc_codec *codec) |
813 | { | 633 | { |
814 | struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); | 634 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
815 | 635 | ||
816 | kfree(cs4270); | 636 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); |
817 | cs4270_codec = NULL; | 637 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); |
818 | cs4270_dai.dev = NULL; | ||
819 | 638 | ||
820 | return 0; | 639 | return 0; |
821 | } | ||
822 | |||
823 | /* | ||
824 | * cs4270_id - I2C device IDs supported by this driver | ||
825 | */ | ||
826 | static struct i2c_device_id cs4270_id[] = { | ||
827 | {"cs4270", 0}, | ||
828 | {} | ||
829 | }; | 640 | }; |
830 | MODULE_DEVICE_TABLE(i2c, cs4270_id); | ||
831 | 641 | ||
832 | #ifdef CONFIG_PM | 642 | #ifdef CONFIG_PM |
833 | 643 | ||
@@ -840,9 +650,8 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id); | |||
840 | * and all registers are written back to the hardware when resuming. | 650 | * and all registers are written back to the hardware when resuming. |
841 | */ | 651 | */ |
842 | 652 | ||
843 | static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) | 653 | static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg) |
844 | { | 654 | { |
845 | struct snd_soc_codec *codec = cs4270_codec; | ||
846 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 655 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
847 | int reg, ret; | 656 | int reg, ret; |
848 | 657 | ||
@@ -860,9 +669,8 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
860 | return 0; | 669 | return 0; |
861 | } | 670 | } |
862 | 671 | ||
863 | static int cs4270_soc_resume(struct platform_device *pdev) | 672 | static int cs4270_soc_resume(struct snd_soc_codec *codec) |
864 | { | 673 | { |
865 | struct snd_soc_codec *codec = cs4270_codec; | ||
866 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 674 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
867 | struct i2c_client *i2c_client = codec->control_data; | 675 | struct i2c_client *i2c_client = codec->control_data; |
868 | int reg; | 676 | int reg; |
@@ -896,6 +704,95 @@ static int cs4270_soc_resume(struct platform_device *pdev) | |||
896 | #endif /* CONFIG_PM */ | 704 | #endif /* CONFIG_PM */ |
897 | 705 | ||
898 | /* | 706 | /* |
707 | * ASoC codec device structure | ||
708 | * | ||
709 | * Assign this variable to the codec_dev field of the machine driver's | ||
710 | * snd_soc_device structure. | ||
711 | */ | ||
712 | static struct snd_soc_codec_driver soc_codec_device_cs4270 = { | ||
713 | .probe = cs4270_probe, | ||
714 | .remove = cs4270_remove, | ||
715 | .suspend = cs4270_soc_suspend, | ||
716 | .resume = cs4270_soc_resume, | ||
717 | .read = cs4270_read_reg_cache, | ||
718 | .write = cs4270_i2c_write, | ||
719 | .reg_cache_size = CS4270_NUMREGS, | ||
720 | .reg_word_size = sizeof(u8), | ||
721 | }; | ||
722 | |||
723 | /** | ||
724 | * cs4270_i2c_probe - initialize the I2C interface of the CS4270 | ||
725 | * @i2c_client: the I2C client object | ||
726 | * @id: the I2C device ID (ignored) | ||
727 | * | ||
728 | * This function is called whenever the I2C subsystem finds a device that | ||
729 | * matches the device ID given via a prior call to i2c_add_driver(). | ||
730 | */ | ||
731 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, | ||
732 | const struct i2c_device_id *id) | ||
733 | { | ||
734 | struct cs4270_private *cs4270; | ||
735 | int ret; | ||
736 | |||
737 | /* Verify that we have a CS4270 */ | ||
738 | |||
739 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | ||
740 | if (ret < 0) { | ||
741 | dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", | ||
742 | i2c_client->addr); | ||
743 | return ret; | ||
744 | } | ||
745 | /* The top four bits of the chip ID should be 1100. */ | ||
746 | if ((ret & 0xF0) != 0xC0) { | ||
747 | dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", | ||
748 | i2c_client->addr); | ||
749 | return -ENODEV; | ||
750 | } | ||
751 | |||
752 | dev_info(&i2c_client->dev, "found device at i2c address %X\n", | ||
753 | i2c_client->addr); | ||
754 | dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); | ||
755 | |||
756 | cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL); | ||
757 | if (!cs4270) { | ||
758 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
759 | return -ENOMEM; | ||
760 | } | ||
761 | |||
762 | i2c_set_clientdata(i2c_client, cs4270); | ||
763 | cs4270->control_data = i2c_client; | ||
764 | cs4270->control_type = SND_SOC_I2C; | ||
765 | |||
766 | ret = snd_soc_register_codec(&i2c_client->dev, | ||
767 | &soc_codec_device_cs4270, &cs4270_dai, 1); | ||
768 | if (ret < 0) | ||
769 | kfree(cs4270); | ||
770 | return ret; | ||
771 | } | ||
772 | |||
773 | /** | ||
774 | * cs4270_i2c_remove - remove an I2C device | ||
775 | * @i2c_client: the I2C client object | ||
776 | * | ||
777 | * This function is the counterpart to cs4270_i2c_probe(). | ||
778 | */ | ||
779 | static int cs4270_i2c_remove(struct i2c_client *i2c_client) | ||
780 | { | ||
781 | snd_soc_unregister_codec(&i2c_client->dev); | ||
782 | kfree(i2c_get_clientdata(i2c_client)); | ||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | /* | ||
787 | * cs4270_id - I2C device IDs supported by this driver | ||
788 | */ | ||
789 | static struct i2c_device_id cs4270_id[] = { | ||
790 | {"cs4270", 0}, | ||
791 | {} | ||
792 | }; | ||
793 | MODULE_DEVICE_TABLE(i2c, cs4270_id); | ||
794 | |||
795 | /* | ||
899 | * cs4270_i2c_driver - I2C device identification | 796 | * cs4270_i2c_driver - I2C device identification |
900 | * | 797 | * |
901 | * This structure tells the I2C subsystem how to identify and support a | 798 | * This structure tells the I2C subsystem how to identify and support a |
@@ -903,7 +800,7 @@ static int cs4270_soc_resume(struct platform_device *pdev) | |||
903 | */ | 800 | */ |
904 | static struct i2c_driver cs4270_i2c_driver = { | 801 | static struct i2c_driver cs4270_i2c_driver = { |
905 | .driver = { | 802 | .driver = { |
906 | .name = "cs4270", | 803 | .name = "cs4270-codec", |
907 | .owner = THIS_MODULE, | 804 | .owner = THIS_MODULE, |
908 | }, | 805 | }, |
909 | .id_table = cs4270_id, | 806 | .id_table = cs4270_id, |
@@ -911,20 +808,6 @@ static struct i2c_driver cs4270_i2c_driver = { | |||
911 | .remove = cs4270_i2c_remove, | 808 | .remove = cs4270_i2c_remove, |
912 | }; | 809 | }; |
913 | 810 | ||
914 | /* | ||
915 | * ASoC codec device structure | ||
916 | * | ||
917 | * Assign this variable to the codec_dev field of the machine driver's | ||
918 | * snd_soc_device structure. | ||
919 | */ | ||
920 | struct snd_soc_codec_device soc_codec_device_cs4270 = { | ||
921 | .probe = cs4270_probe, | ||
922 | .remove = cs4270_remove, | ||
923 | .suspend = cs4270_soc_suspend, | ||
924 | .resume = cs4270_soc_resume, | ||
925 | }; | ||
926 | EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); | ||
927 | |||
928 | static int __init cs4270_init(void) | 811 | static int __init cs4270_init(void) |
929 | { | 812 | { |
930 | pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); | 813 | pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); |
diff --git a/sound/soc/codecs/cs4270.h b/sound/soc/codecs/cs4270.h deleted file mode 100644 index adc6cd9667d4..000000000000 --- a/sound/soc/codecs/cs4270.h +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | /* | ||
2 | * Cirrus Logic CS4270 ALSA SoC Codec Driver | ||
3 | * | ||
4 | * Author: Timur Tabi <timur@freescale.com> | ||
5 | * | ||
6 | * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #ifndef _CS4270_H | ||
13 | #define _CS4270_H | ||
14 | |||
15 | /* | ||
16 | * The ASoC codec DAI structure for the CS4270. Assign this structure to | ||
17 | * the .codec_dai field of your machine driver's snd_soc_dai_link structure. | ||
18 | */ | ||
19 | extern struct snd_soc_dai cs4270_dai; | ||
20 | |||
21 | /* | ||
22 | * The ASoC codec device structure for the CS4270. Assign this structure | ||
23 | * to the .codec_dev field of your machine driver's snd_soc_device | ||
24 | * structure. | ||
25 | */ | ||
26 | extern struct snd_soc_codec_device soc_codec_device_cs4270; | ||
27 | |||
28 | #endif | ||
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index dd9b8550c402..8a25743870c2 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c | |||
@@ -42,15 +42,14 @@ enum master_slave_mode { | |||
42 | }; | 42 | }; |
43 | 43 | ||
44 | struct cs42l51_private { | 44 | struct cs42l51_private { |
45 | enum snd_soc_control_type control_type; | ||
46 | void *control_data; | ||
45 | unsigned int mclk; | 47 | unsigned int mclk; |
46 | unsigned int audio_mode; /* The mode (I2S or left-justified) */ | 48 | unsigned int audio_mode; /* The mode (I2S or left-justified) */ |
47 | enum master_slave_mode func; | 49 | enum master_slave_mode func; |
48 | struct snd_soc_codec codec; | ||
49 | u8 reg_cache[CS42L51_NUMREGS]; | 50 | u8 reg_cache[CS42L51_NUMREGS]; |
50 | }; | 51 | }; |
51 | 52 | ||
52 | static struct snd_soc_codec *cs42l51_codec; | ||
53 | |||
54 | #define CS42L51_FORMATS ( \ | 53 | #define CS42L51_FORMATS ( \ |
55 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ | 54 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ |
56 | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ | 55 | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ |
@@ -75,134 +74,6 @@ static int cs42l51_fill_cache(struct snd_soc_codec *codec) | |||
75 | return 0; | 74 | return 0; |
76 | } | 75 | } |
77 | 76 | ||
78 | static int cs42l51_i2c_probe(struct i2c_client *i2c_client, | ||
79 | const struct i2c_device_id *id) | ||
80 | { | ||
81 | struct snd_soc_codec *codec; | ||
82 | struct cs42l51_private *cs42l51; | ||
83 | int ret = 0; | ||
84 | int reg; | ||
85 | |||
86 | if (cs42l51_codec) | ||
87 | return -EBUSY; | ||
88 | |||
89 | /* Verify that we have a CS42L51 */ | ||
90 | ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); | ||
91 | if (ret < 0) { | ||
92 | dev_err(&i2c_client->dev, "failed to read I2C\n"); | ||
93 | goto error; | ||
94 | } | ||
95 | |||
96 | if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && | ||
97 | (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { | ||
98 | dev_err(&i2c_client->dev, "Invalid chip id\n"); | ||
99 | ret = -ENODEV; | ||
100 | goto error; | ||
101 | } | ||
102 | |||
103 | dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", | ||
104 | ret & 7); | ||
105 | |||
106 | cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL); | ||
107 | if (!cs42l51) { | ||
108 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
109 | return -ENOMEM; | ||
110 | } | ||
111 | codec = &cs42l51->codec; | ||
112 | |||
113 | mutex_init(&codec->mutex); | ||
114 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
115 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
116 | |||
117 | codec->dev = &i2c_client->dev; | ||
118 | codec->name = "CS42L51"; | ||
119 | codec->owner = THIS_MODULE; | ||
120 | codec->dai = &cs42l51_dai; | ||
121 | codec->num_dai = 1; | ||
122 | snd_soc_codec_set_drvdata(codec, cs42l51); | ||
123 | |||
124 | codec->control_data = i2c_client; | ||
125 | codec->reg_cache = cs42l51->reg_cache; | ||
126 | codec->reg_cache_size = CS42L51_NUMREGS; | ||
127 | i2c_set_clientdata(i2c_client, codec); | ||
128 | |||
129 | ret = cs42l51_fill_cache(codec); | ||
130 | if (ret < 0) { | ||
131 | dev_err(&i2c_client->dev, "failed to fill register cache\n"); | ||
132 | goto error_alloc; | ||
133 | } | ||
134 | |||
135 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | ||
136 | if (ret < 0) { | ||
137 | dev_err(&i2c_client->dev, "Failed to set cache I/O: %d\n", ret); | ||
138 | goto error_alloc; | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * DAC configuration | ||
143 | * - Use signal processor | ||
144 | * - auto mute | ||
145 | * - vol changes immediate | ||
146 | * - no de-emphasize | ||
147 | */ | ||
148 | reg = CS42L51_DAC_CTL_DATA_SEL(1) | ||
149 | | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0); | ||
150 | ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg); | ||
151 | if (ret < 0) | ||
152 | goto error_alloc; | ||
153 | |||
154 | cs42l51_dai.dev = codec->dev; | ||
155 | cs42l51_codec = codec; | ||
156 | |||
157 | ret = snd_soc_register_codec(codec); | ||
158 | if (ret != 0) { | ||
159 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
160 | goto error_alloc; | ||
161 | } | ||
162 | |||
163 | ret = snd_soc_register_dai(&cs42l51_dai); | ||
164 | if (ret < 0) { | ||
165 | dev_err(&i2c_client->dev, "failed to register DAIe\n"); | ||
166 | goto error_reg; | ||
167 | } | ||
168 | |||
169 | return 0; | ||
170 | |||
171 | error_reg: | ||
172 | snd_soc_unregister_codec(codec); | ||
173 | error_alloc: | ||
174 | kfree(cs42l51); | ||
175 | error: | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static int cs42l51_i2c_remove(struct i2c_client *client) | ||
180 | { | ||
181 | struct cs42l51_private *cs42l51 = i2c_get_clientdata(client); | ||
182 | snd_soc_unregister_dai(&cs42l51_dai); | ||
183 | snd_soc_unregister_codec(cs42l51_codec); | ||
184 | cs42l51_codec = NULL; | ||
185 | kfree(cs42l51); | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | |||
190 | static const struct i2c_device_id cs42l51_id[] = { | ||
191 | {"cs42l51", 0}, | ||
192 | {} | ||
193 | }; | ||
194 | MODULE_DEVICE_TABLE(i2c, cs42l51_id); | ||
195 | |||
196 | static struct i2c_driver cs42l51_i2c_driver = { | ||
197 | .driver = { | ||
198 | .name = "CS42L51 I2C", | ||
199 | .owner = THIS_MODULE, | ||
200 | }, | ||
201 | .id_table = cs42l51_id, | ||
202 | .probe = cs42l51_i2c_probe, | ||
203 | .remove = cs42l51_i2c_remove, | ||
204 | }; | ||
205 | |||
206 | static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, | 77 | static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, |
207 | struct snd_ctl_elem_value *ucontrol) | 78 | struct snd_ctl_elem_value *ucontrol) |
208 | { | 79 | { |
@@ -484,51 +355,8 @@ static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
484 | { | 355 | { |
485 | struct snd_soc_codec *codec = codec_dai->codec; | 356 | struct snd_soc_codec *codec = codec_dai->codec; |
486 | struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); | 357 | struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); |
487 | struct cs42l51_ratios *ratios = NULL; | ||
488 | int nr_ratios = 0; | ||
489 | unsigned int rates = 0; | ||
490 | unsigned int rate_min = -1; | ||
491 | unsigned int rate_max = 0; | ||
492 | int i; | ||
493 | 358 | ||
494 | cs42l51->mclk = freq; | 359 | cs42l51->mclk = freq; |
495 | |||
496 | switch (cs42l51->func) { | ||
497 | case MODE_MASTER: | ||
498 | return -EINVAL; | ||
499 | case MODE_SLAVE: | ||
500 | ratios = slave_ratios; | ||
501 | nr_ratios = ARRAY_SIZE(slave_ratios); | ||
502 | break; | ||
503 | case MODE_SLAVE_AUTO: | ||
504 | ratios = slave_auto_ratios; | ||
505 | nr_ratios = ARRAY_SIZE(slave_auto_ratios); | ||
506 | break; | ||
507 | } | ||
508 | |||
509 | for (i = 0; i < nr_ratios; i++) { | ||
510 | unsigned int rate = freq / ratios[i].ratio; | ||
511 | rates |= snd_pcm_rate_to_rate_bit(rate); | ||
512 | if (rate < rate_min) | ||
513 | rate_min = rate; | ||
514 | if (rate > rate_max) | ||
515 | rate_max = rate; | ||
516 | } | ||
517 | rates &= ~SNDRV_PCM_RATE_KNOT; | ||
518 | |||
519 | if (!rates) { | ||
520 | dev_err(codec->dev, "could not find a valid sample rate\n"); | ||
521 | return -EINVAL; | ||
522 | } | ||
523 | |||
524 | codec_dai->playback.rates = rates; | ||
525 | codec_dai->playback.rate_min = rate_min; | ||
526 | codec_dai->playback.rate_max = rate_max; | ||
527 | |||
528 | codec_dai->capture.rates = rates; | ||
529 | codec_dai->capture.rate_min = rate_min; | ||
530 | codec_dai->capture.rate_max = rate_max; | ||
531 | |||
532 | return 0; | 360 | return 0; |
533 | } | 361 | } |
534 | 362 | ||
@@ -537,8 +365,7 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream, | |||
537 | struct snd_soc_dai *dai) | 365 | struct snd_soc_dai *dai) |
538 | { | 366 | { |
539 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 367 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
540 | struct snd_soc_device *socdev = rtd->socdev; | 368 | struct snd_soc_codec *codec = rtd->codec; |
541 | struct snd_soc_codec *codec = socdev->card->codec; | ||
542 | struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); | 369 | struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); |
543 | int ret; | 370 | int ret; |
544 | unsigned int i; | 371 | unsigned int i; |
@@ -670,8 +497,8 @@ static struct snd_soc_dai_ops cs42l51_dai_ops = { | |||
670 | .digital_mute = cs42l51_dai_mute, | 497 | .digital_mute = cs42l51_dai_mute, |
671 | }; | 498 | }; |
672 | 499 | ||
673 | struct snd_soc_dai cs42l51_dai = { | 500 | static struct snd_soc_dai_driver cs42l51_dai = { |
674 | .name = "CS42L51 HiFi", | 501 | .name = "cs42l51-hifi", |
675 | .playback = { | 502 | .playback = { |
676 | .stream_name = "Playback", | 503 | .stream_name = "Playback", |
677 | .channels_min = 1, | 504 | .channels_min = 1, |
@@ -688,30 +515,39 @@ struct snd_soc_dai cs42l51_dai = { | |||
688 | }, | 515 | }, |
689 | .ops = &cs42l51_dai_ops, | 516 | .ops = &cs42l51_dai_ops, |
690 | }; | 517 | }; |
691 | EXPORT_SYMBOL_GPL(cs42l51_dai); | ||
692 | |||
693 | 518 | ||
694 | static int cs42l51_probe(struct platform_device *pdev) | 519 | static int cs42l51_probe(struct snd_soc_codec *codec) |
695 | { | 520 | { |
696 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 521 | struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); |
697 | struct snd_soc_codec *codec; | 522 | int ret, reg; |
698 | int ret = 0; | ||
699 | 523 | ||
700 | if (!cs42l51_codec) { | 524 | codec->control_data = cs42l51->control_data; |
701 | dev_err(&pdev->dev, "CS42L51 codec not yet registered\n"); | ||
702 | return -EINVAL; | ||
703 | } | ||
704 | 525 | ||
705 | socdev->card->codec = cs42l51_codec; | 526 | ret = cs42l51_fill_cache(codec); |
706 | codec = socdev->card->codec; | 527 | if (ret < 0) { |
528 | dev_err(codec->dev, "failed to fill register cache\n"); | ||
529 | return ret; | ||
530 | } | ||
707 | 531 | ||
708 | /* Register PCMs */ | 532 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type); |
709 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
710 | if (ret < 0) { | 533 | if (ret < 0) { |
711 | dev_err(&pdev->dev, "failed to create PCMs\n"); | 534 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
712 | return ret; | 535 | return ret; |
713 | } | 536 | } |
714 | 537 | ||
538 | /* | ||
539 | * DAC configuration | ||
540 | * - Use signal processor | ||
541 | * - auto mute | ||
542 | * - vol changes immediate | ||
543 | * - no de-emphasize | ||
544 | */ | ||
545 | reg = CS42L51_DAC_CTL_DATA_SEL(1) | ||
546 | | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0); | ||
547 | ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg); | ||
548 | if (ret < 0) | ||
549 | return ret; | ||
550 | |||
715 | snd_soc_add_controls(codec, cs42l51_snd_controls, | 551 | snd_soc_add_controls(codec, cs42l51_snd_controls, |
716 | ARRAY_SIZE(cs42l51_snd_controls)); | 552 | ARRAY_SIZE(cs42l51_snd_controls)); |
717 | snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets, | 553 | snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets, |
@@ -722,22 +558,77 @@ static int cs42l51_probe(struct platform_device *pdev) | |||
722 | return 0; | 558 | return 0; |
723 | } | 559 | } |
724 | 560 | ||
561 | static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { | ||
562 | .probe = cs42l51_probe, | ||
563 | .reg_cache_size = CS42L51_NUMREGS, | ||
564 | .reg_word_size = sizeof(u8), | ||
565 | }; | ||
725 | 566 | ||
726 | static int cs42l51_remove(struct platform_device *pdev) | 567 | static int cs42l51_i2c_probe(struct i2c_client *i2c_client, |
568 | const struct i2c_device_id *id) | ||
727 | { | 569 | { |
728 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 570 | struct cs42l51_private *cs42l51; |
571 | int ret; | ||
729 | 572 | ||
730 | snd_soc_free_pcms(socdev); | 573 | /* Verify that we have a CS42L51 */ |
731 | snd_soc_dapm_free(socdev); | 574 | ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); |
575 | if (ret < 0) { | ||
576 | dev_err(&i2c_client->dev, "failed to read I2C\n"); | ||
577 | goto error; | ||
578 | } | ||
579 | |||
580 | if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && | ||
581 | (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { | ||
582 | dev_err(&i2c_client->dev, "Invalid chip id\n"); | ||
583 | ret = -ENODEV; | ||
584 | goto error; | ||
585 | } | ||
586 | |||
587 | dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", | ||
588 | ret & 7); | ||
589 | |||
590 | cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL); | ||
591 | if (!cs42l51) { | ||
592 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
593 | return -ENOMEM; | ||
594 | } | ||
595 | |||
596 | i2c_set_clientdata(i2c_client, cs42l51); | ||
597 | cs42l51->control_data = i2c_client; | ||
598 | cs42l51->control_type = SND_SOC_I2C; | ||
732 | 599 | ||
600 | ret = snd_soc_register_codec(&i2c_client->dev, | ||
601 | &soc_codec_device_cs42l51, &cs42l51_dai, 1); | ||
602 | if (ret < 0) | ||
603 | kfree(cs42l51); | ||
604 | error: | ||
605 | return ret; | ||
606 | } | ||
607 | |||
608 | static int cs42l51_i2c_remove(struct i2c_client *client) | ||
609 | { | ||
610 | struct cs42l51_private *cs42l51 = i2c_get_clientdata(client); | ||
611 | |||
612 | snd_soc_unregister_codec(&client->dev); | ||
613 | kfree(cs42l51); | ||
733 | return 0; | 614 | return 0; |
734 | } | 615 | } |
735 | 616 | ||
736 | struct snd_soc_codec_device soc_codec_device_cs42l51 = { | 617 | static const struct i2c_device_id cs42l51_id[] = { |
737 | .probe = cs42l51_probe, | 618 | {"cs42l51", 0}, |
738 | .remove = cs42l51_remove | 619 | {} |
620 | }; | ||
621 | MODULE_DEVICE_TABLE(i2c, cs42l51_id); | ||
622 | |||
623 | static struct i2c_driver cs42l51_i2c_driver = { | ||
624 | .driver = { | ||
625 | .name = "cs42L51-codec", | ||
626 | .owner = THIS_MODULE, | ||
627 | }, | ||
628 | .id_table = cs42l51_id, | ||
629 | .probe = cs42l51_i2c_probe, | ||
630 | .remove = cs42l51_i2c_remove, | ||
739 | }; | 631 | }; |
740 | EXPORT_SYMBOL_GPL(soc_codec_device_cs42l51); | ||
741 | 632 | ||
742 | static int __init cs42l51_init(void) | 633 | static int __init cs42l51_init(void) |
743 | { | 634 | { |
diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h index 8f0bd9786ad2..2beeb171db4b 100644 --- a/sound/soc/codecs/cs42l51.h +++ b/sound/soc/codecs/cs42l51.h | |||
@@ -158,6 +158,4 @@ | |||
158 | #define CS42L51_LASTREG 0x20 | 158 | #define CS42L51_LASTREG 0x20 |
159 | #define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1) | 159 | #define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1) |
160 | 160 | ||
161 | extern struct snd_soc_dai cs42l51_dai; | ||
162 | extern struct snd_soc_codec_device soc_codec_device_cs42l51; | ||
163 | #endif | 161 | #endif |
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index f07a415c753f..cf4323dbf9c4 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c | |||
@@ -24,7 +24,8 @@ | |||
24 | 24 | ||
25 | 25 | ||
26 | struct cx20442_priv { | 26 | struct cx20442_priv { |
27 | struct snd_soc_codec codec; | 27 | enum snd_soc_control_type control_type; |
28 | void *control_data; | ||
28 | u8 reg_cache[1]; | 29 | u8 reg_cache[1]; |
29 | }; | 30 | }; |
30 | 31 | ||
@@ -102,7 +103,7 @@ static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec, | |||
102 | { | 103 | { |
103 | u8 *reg_cache = codec->reg_cache; | 104 | u8 *reg_cache = codec->reg_cache; |
104 | 105 | ||
105 | if (reg >= codec->reg_cache_size) | 106 | if (reg >= codec->driver->reg_cache_size) |
106 | return -EINVAL; | 107 | return -EINVAL; |
107 | 108 | ||
108 | return reg_cache[reg]; | 109 | return reg_cache[reg]; |
@@ -164,16 +165,17 @@ static int cx20442_pm_to_v253_vsp(u8 value) | |||
164 | static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg, | 165 | static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg, |
165 | unsigned int value) | 166 | unsigned int value) |
166 | { | 167 | { |
168 | struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); | ||
167 | u8 *reg_cache = codec->reg_cache; | 169 | u8 *reg_cache = codec->reg_cache; |
168 | int vls, vsp, old, len; | 170 | int vls, vsp, old, len; |
169 | char buf[18]; | 171 | char buf[18]; |
170 | 172 | ||
171 | if (reg >= codec->reg_cache_size) | 173 | if (reg >= codec->driver->reg_cache_size) |
172 | return -EINVAL; | 174 | return -EINVAL; |
173 | 175 | ||
174 | /* hw_write and control_data pointers required for talking to the modem | 176 | /* hw_write and control_data pointers required for talking to the modem |
175 | * are expected to be set by the line discipline initialization code */ | 177 | * are expected to be set by the line discipline initialization code */ |
176 | if (!codec->hw_write || !codec->control_data) | 178 | if (!codec->hw_write || !cx20442->control_data) |
177 | return -EIO; | 179 | return -EIO; |
178 | 180 | ||
179 | old = reg_cache[reg]; | 181 | old = reg_cache[reg]; |
@@ -202,17 +204,13 @@ static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg, | |||
202 | return -ENOMEM; | 204 | return -ENOMEM; |
203 | 205 | ||
204 | dev_dbg(codec->dev, "%s: %s\n", __func__, buf); | 206 | dev_dbg(codec->dev, "%s: %s\n", __func__, buf); |
205 | if (codec->hw_write(codec->control_data, buf, len) != len) | 207 | if (codec->hw_write(cx20442->control_data, buf, len) != len) |
206 | return -EIO; | 208 | return -EIO; |
207 | 209 | ||
208 | return 0; | 210 | return 0; |
209 | } | 211 | } |
210 | 212 | ||
211 | 213 | ||
212 | /* Moved up here as line discipline referres it during initialization */ | ||
213 | static struct snd_soc_codec *cx20442_codec; | ||
214 | |||
215 | |||
216 | /* | 214 | /* |
217 | * Line discpline related code | 215 | * Line discpline related code |
218 | * | 216 | * |
@@ -228,15 +226,15 @@ static const char *v253_init = "ate0m0q0+fclass=8\r"; | |||
228 | /* Line discipline .open() */ | 226 | /* Line discipline .open() */ |
229 | static int v253_open(struct tty_struct *tty) | 227 | static int v253_open(struct tty_struct *tty) |
230 | { | 228 | { |
231 | struct snd_soc_codec *codec = cx20442_codec; | ||
232 | int ret, len = strlen(v253_init); | 229 | int ret, len = strlen(v253_init); |
233 | 230 | ||
234 | /* Doesn't make sense without write callback */ | 231 | /* Doesn't make sense without write callback */ |
235 | if (!tty->ops->write) | 232 | if (!tty->ops->write) |
236 | return -EINVAL; | 233 | return -EINVAL; |
237 | 234 | ||
238 | /* Pass the codec structure address for use by other ldisc callbacks */ | 235 | /* Won't work if no codec pointer has been passed by a card driver */ |
239 | tty->disc_data = codec; | 236 | if (!tty->disc_data) |
237 | return -ENODEV; | ||
240 | 238 | ||
241 | if (tty->ops->write(tty, v253_init, len) != len) { | 239 | if (tty->ops->write(tty, v253_init, len) != len) { |
242 | ret = -EIO; | 240 | ret = -EIO; |
@@ -253,15 +251,18 @@ err: | |||
253 | static void v253_close(struct tty_struct *tty) | 251 | static void v253_close(struct tty_struct *tty) |
254 | { | 252 | { |
255 | struct snd_soc_codec *codec = tty->disc_data; | 253 | struct snd_soc_codec *codec = tty->disc_data; |
254 | struct cx20442_priv *cx20442; | ||
256 | 255 | ||
257 | tty->disc_data = NULL; | 256 | tty->disc_data = NULL; |
258 | 257 | ||
259 | if (!codec) | 258 | if (!codec) |
260 | return; | 259 | return; |
261 | 260 | ||
261 | cx20442 = snd_soc_codec_get_drvdata(codec); | ||
262 | |||
262 | /* Prevent the codec driver from further accessing the modem */ | 263 | /* Prevent the codec driver from further accessing the modem */ |
263 | codec->hw_write = NULL; | 264 | codec->hw_write = NULL; |
264 | codec->control_data = NULL; | 265 | cx20442->control_data = NULL; |
265 | codec->pop_time = 0; | 266 | codec->pop_time = 0; |
266 | } | 267 | } |
267 | 268 | ||
@@ -277,15 +278,18 @@ static void v253_receive(struct tty_struct *tty, | |||
277 | const unsigned char *cp, char *fp, int count) | 278 | const unsigned char *cp, char *fp, int count) |
278 | { | 279 | { |
279 | struct snd_soc_codec *codec = tty->disc_data; | 280 | struct snd_soc_codec *codec = tty->disc_data; |
281 | struct cx20442_priv *cx20442; | ||
280 | 282 | ||
281 | if (!codec) | 283 | if (!codec) |
282 | return; | 284 | return; |
283 | 285 | ||
284 | if (!codec->control_data) { | 286 | cx20442 = snd_soc_codec_get_drvdata(codec); |
287 | |||
288 | if (!cx20442->control_data) { | ||
285 | /* First modem response, complete setup procedure */ | 289 | /* First modem response, complete setup procedure */ |
286 | 290 | ||
287 | /* Set up codec driver access to modem controls */ | 291 | /* Set up codec driver access to modem controls */ |
288 | codec->control_data = tty; | 292 | cx20442->control_data = tty; |
289 | codec->hw_write = (hw_write_t)tty->ops->write; | 293 | codec->hw_write = (hw_write_t)tty->ops->write; |
290 | codec->pop_time = 1; | 294 | codec->pop_time = 1; |
291 | } | 295 | } |
@@ -313,8 +317,8 @@ EXPORT_SYMBOL_GPL(v253_ops); | |||
313 | * Codec DAI | 317 | * Codec DAI |
314 | */ | 318 | */ |
315 | 319 | ||
316 | struct snd_soc_dai cx20442_dai = { | 320 | static struct snd_soc_dai_driver cx20442_dai = { |
317 | .name = "CX20442", | 321 | .name = "cx20442-hifi", |
318 | .playback = { | 322 | .playback = { |
319 | .stream_name = "Playback", | 323 | .stream_name = "Playback", |
320 | .channels_min = 1, | 324 | .channels_min = 1, |
@@ -330,142 +334,63 @@ struct snd_soc_dai cx20442_dai = { | |||
330 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 334 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
331 | }, | 335 | }, |
332 | }; | 336 | }; |
333 | EXPORT_SYMBOL_GPL(cx20442_dai); | ||
334 | 337 | ||
335 | static int cx20442_codec_probe(struct platform_device *pdev) | 338 | static int cx20442_codec_probe(struct snd_soc_codec *codec) |
336 | { | 339 | { |
337 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 340 | struct cx20442_priv *cx20442; |
338 | struct snd_soc_codec *codec; | ||
339 | int ret; | ||
340 | |||
341 | if (!cx20442_codec) { | ||
342 | dev_err(&pdev->dev, "cx20442 not yet discovered\n"); | ||
343 | return -ENODEV; | ||
344 | } | ||
345 | codec = cx20442_codec; | ||
346 | |||
347 | socdev->card->codec = codec; | ||
348 | 341 | ||
349 | /* register pcms */ | 342 | cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); |
350 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 343 | if (cx20442 == NULL) |
351 | if (ret < 0) { | 344 | return -ENOMEM; |
352 | dev_err(&pdev->dev, "failed to create pcms\n"); | 345 | snd_soc_codec_set_drvdata(codec, cx20442); |
353 | goto pcm_err; | ||
354 | } | ||
355 | 346 | ||
356 | cx20442_add_widgets(codec); | 347 | cx20442_add_widgets(codec); |
357 | 348 | ||
358 | pcm_err: | 349 | cx20442->control_data = NULL; |
359 | return ret; | 350 | codec->hw_write = NULL; |
351 | codec->pop_time = 0; | ||
352 | |||
353 | return 0; | ||
360 | } | 354 | } |
361 | 355 | ||
362 | /* power down chip */ | 356 | /* power down chip */ |
363 | static int cx20442_codec_remove(struct platform_device *pdev) | 357 | static int cx20442_codec_remove(struct snd_soc_codec *codec) |
364 | { | 358 | { |
365 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 359 | struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); |
366 | 360 | ||
367 | snd_soc_free_pcms(socdev); | 361 | if (cx20442->control_data) { |
368 | snd_soc_dapm_free(socdev); | 362 | struct tty_struct *tty = cx20442->control_data; |
363 | tty_hangup(tty); | ||
364 | } | ||
369 | 365 | ||
366 | kfree(cx20442); | ||
370 | return 0; | 367 | return 0; |
371 | } | 368 | } |
372 | 369 | ||
373 | struct snd_soc_codec_device cx20442_codec_dev = { | 370 | static struct snd_soc_codec_driver cx20442_codec_dev = { |
374 | .probe = cx20442_codec_probe, | 371 | .probe = cx20442_codec_probe, |
375 | .remove = cx20442_codec_remove, | 372 | .remove = cx20442_codec_remove, |
373 | .reg_cache_size = 1, | ||
374 | .reg_word_size = sizeof(u8), | ||
375 | .read = cx20442_read_reg_cache, | ||
376 | .write = cx20442_write, | ||
376 | }; | 377 | }; |
377 | EXPORT_SYMBOL_GPL(cx20442_codec_dev); | ||
378 | |||
379 | static int cx20442_register(struct cx20442_priv *cx20442) | ||
380 | { | ||
381 | struct snd_soc_codec *codec = &cx20442->codec; | ||
382 | int ret; | ||
383 | |||
384 | mutex_init(&codec->mutex); | ||
385 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
386 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
387 | |||
388 | codec->name = "CX20442"; | ||
389 | codec->owner = THIS_MODULE; | ||
390 | snd_soc_codec_set_drvdata(codec, cx20442); | ||
391 | |||
392 | codec->dai = &cx20442_dai; | ||
393 | codec->num_dai = 1; | ||
394 | |||
395 | codec->reg_cache = &cx20442->reg_cache; | ||
396 | codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache); | ||
397 | codec->read = cx20442_read_reg_cache; | ||
398 | codec->write = cx20442_write; | ||
399 | |||
400 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
401 | |||
402 | cx20442_dai.dev = codec->dev; | ||
403 | |||
404 | cx20442_codec = codec; | ||
405 | |||
406 | ret = snd_soc_register_codec(codec); | ||
407 | if (ret != 0) { | ||
408 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
409 | goto err; | ||
410 | } | ||
411 | |||
412 | ret = snd_soc_register_dai(&cx20442_dai); | ||
413 | if (ret != 0) { | ||
414 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
415 | goto err_codec; | ||
416 | } | ||
417 | |||
418 | return 0; | ||
419 | |||
420 | err_codec: | ||
421 | snd_soc_unregister_codec(codec); | ||
422 | err: | ||
423 | cx20442_codec = NULL; | ||
424 | kfree(cx20442); | ||
425 | return ret; | ||
426 | } | ||
427 | |||
428 | static void cx20442_unregister(struct cx20442_priv *cx20442) | ||
429 | { | ||
430 | snd_soc_unregister_dai(&cx20442_dai); | ||
431 | snd_soc_unregister_codec(&cx20442->codec); | ||
432 | |||
433 | cx20442_codec = NULL; | ||
434 | kfree(cx20442); | ||
435 | } | ||
436 | 378 | ||
437 | static int cx20442_platform_probe(struct platform_device *pdev) | 379 | static int cx20442_platform_probe(struct platform_device *pdev) |
438 | { | 380 | { |
439 | struct cx20442_priv *cx20442; | 381 | return snd_soc_register_codec(&pdev->dev, |
440 | struct snd_soc_codec *codec; | 382 | &cx20442_codec_dev, &cx20442_dai, 1); |
441 | |||
442 | cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); | ||
443 | if (cx20442 == NULL) | ||
444 | return -ENOMEM; | ||
445 | |||
446 | codec = &cx20442->codec; | ||
447 | |||
448 | codec->control_data = NULL; | ||
449 | codec->hw_write = NULL; | ||
450 | codec->pop_time = 0; | ||
451 | |||
452 | codec->dev = &pdev->dev; | ||
453 | platform_set_drvdata(pdev, cx20442); | ||
454 | |||
455 | return cx20442_register(cx20442); | ||
456 | } | 383 | } |
457 | 384 | ||
458 | static int __exit cx20442_platform_remove(struct platform_device *pdev) | 385 | static int __exit cx20442_platform_remove(struct platform_device *pdev) |
459 | { | 386 | { |
460 | struct cx20442_priv *cx20442 = platform_get_drvdata(pdev); | 387 | snd_soc_unregister_codec(&pdev->dev); |
461 | |||
462 | cx20442_unregister(cx20442); | ||
463 | return 0; | 388 | return 0; |
464 | } | 389 | } |
465 | 390 | ||
466 | static struct platform_driver cx20442_platform_driver = { | 391 | static struct platform_driver cx20442_platform_driver = { |
467 | .driver = { | 392 | .driver = { |
468 | .name = "cx20442", | 393 | .name = "cx20442-codec", |
469 | .owner = THIS_MODULE, | 394 | .owner = THIS_MODULE, |
470 | }, | 395 | }, |
471 | .probe = cx20442_platform_probe, | 396 | .probe = cx20442_platform_probe, |
@@ -487,4 +412,4 @@ module_exit(cx20442_exit); | |||
487 | MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver"); | 412 | MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver"); |
488 | MODULE_AUTHOR("Janusz Krzysztofik"); | 413 | MODULE_AUTHOR("Janusz Krzysztofik"); |
489 | MODULE_LICENSE("GPL"); | 414 | MODULE_LICENSE("GPL"); |
490 | MODULE_ALIAS("platform:cx20442"); | 415 | MODULE_ALIAS("platform:cx20442-codec"); |
diff --git a/sound/soc/codecs/cx20442.h b/sound/soc/codecs/cx20442.h index 688a5eb62e17..c7a7c79ef0cd 100644 --- a/sound/soc/codecs/cx20442.h +++ b/sound/soc/codecs/cx20442.h | |||
@@ -13,8 +13,6 @@ | |||
13 | #ifndef _CX20442_CODEC_H | 13 | #ifndef _CX20442_CODEC_H |
14 | #define _CX20442_CODEC_H | 14 | #define _CX20442_CODEC_H |
15 | 15 | ||
16 | extern struct snd_soc_dai cx20442_dai; | ||
17 | extern struct snd_soc_codec_device cx20442_codec_dev; | ||
18 | extern struct tty_ldisc_ops v253_ops; | 16 | extern struct tty_ldisc_ops v253_ops; |
19 | 17 | ||
20 | #endif | 18 | #endif |
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 3c51d6a57523..eabf3c062500 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c | |||
@@ -25,8 +25,6 @@ | |||
25 | #include <sound/initval.h> | 25 | #include <sound/initval.h> |
26 | #include <sound/tlv.h> | 26 | #include <sound/tlv.h> |
27 | 27 | ||
28 | #include "da7210.h" | ||
29 | |||
30 | /* DA7210 register space */ | 28 | /* DA7210 register space */ |
31 | #define DA7210_STATUS 0x02 | 29 | #define DA7210_STATUS 0x02 |
32 | #define DA7210_STARTUP1 0x03 | 30 | #define DA7210_STARTUP1 0x03 |
@@ -162,11 +160,10 @@ static const struct snd_kcontrol_new da7210_snd_controls[] = { | |||
162 | 160 | ||
163 | /* Codec private data */ | 161 | /* Codec private data */ |
164 | struct da7210_priv { | 162 | struct da7210_priv { |
165 | struct snd_soc_codec codec; | 163 | enum snd_soc_control_type control_type; |
164 | void *control_data; | ||
166 | }; | 165 | }; |
167 | 166 | ||
168 | static struct snd_soc_codec *da7210_codec; | ||
169 | |||
170 | /* | 167 | /* |
171 | * Register cache | 168 | * Register cache |
172 | */ | 169 | */ |
@@ -209,12 +206,12 @@ static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value) | |||
209 | u8 *cache = codec->reg_cache; | 206 | u8 *cache = codec->reg_cache; |
210 | u8 data[2]; | 207 | u8 data[2]; |
211 | 208 | ||
212 | BUG_ON(codec->volatile_register); | 209 | BUG_ON(codec->driver->volatile_register); |
213 | 210 | ||
214 | data[0] = reg & 0xff; | 211 | data[0] = reg & 0xff; |
215 | data[1] = value & 0xff; | 212 | data[1] = value & 0xff; |
216 | 213 | ||
217 | if (reg >= codec->reg_cache_size) | 214 | if (reg >= codec->driver->reg_cache_size) |
218 | return -EIO; | 215 | return -EIO; |
219 | 216 | ||
220 | if (2 != codec->hw_write(codec->control_data, data, 2)) | 217 | if (2 != codec->hw_write(codec->control_data, data, 2)) |
@@ -267,8 +264,7 @@ static int da7210_hw_params(struct snd_pcm_substream *substream, | |||
267 | struct snd_soc_dai *dai) | 264 | struct snd_soc_dai *dai) |
268 | { | 265 | { |
269 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 266 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
270 | struct snd_soc_device *socdev = rtd->socdev; | 267 | struct snd_soc_codec *codec = rtd->codec; |
271 | struct snd_soc_codec *codec = socdev->card->codec; | ||
272 | u32 dai_cfg1; | 268 | u32 dai_cfg1; |
273 | u32 hpf_reg, hpf_mask, hpf_value; | 269 | u32 hpf_reg, hpf_mask, hpf_value; |
274 | u32 fs, bypass; | 270 | u32 fs, bypass; |
@@ -430,9 +426,8 @@ static struct snd_soc_dai_ops da7210_dai_ops = { | |||
430 | .set_fmt = da7210_set_dai_fmt, | 426 | .set_fmt = da7210_set_dai_fmt, |
431 | }; | 427 | }; |
432 | 428 | ||
433 | struct snd_soc_dai da7210_dai = { | 429 | static struct snd_soc_dai_driver da7210_dai = { |
434 | .name = "DA7210 IIS", | 430 | .name = "da7210-hifi", |
435 | .id = 0, | ||
436 | /* playback capabilities */ | 431 | /* playback capabilities */ |
437 | .playback = { | 432 | .playback = { |
438 | .stream_name = "Playback", | 433 | .stream_name = "Playback", |
@@ -452,55 +447,15 @@ struct snd_soc_dai da7210_dai = { | |||
452 | .ops = &da7210_dai_ops, | 447 | .ops = &da7210_dai_ops, |
453 | .symmetric_rates = 1, | 448 | .symmetric_rates = 1, |
454 | }; | 449 | }; |
455 | EXPORT_SYMBOL_GPL(da7210_dai); | ||
456 | 450 | ||
457 | /* | 451 | static int da7210_probe(struct snd_soc_codec *codec) |
458 | * Initialize the DA7210 driver | ||
459 | * register the mixer and dsp interfaces with the kernel | ||
460 | */ | ||
461 | static int da7210_init(struct da7210_priv *da7210) | ||
462 | { | 452 | { |
463 | struct snd_soc_codec *codec = &da7210->codec; | 453 | struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec); |
464 | int ret = 0; | ||
465 | 454 | ||
466 | if (da7210_codec) { | 455 | dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); |
467 | dev_err(codec->dev, "Another da7210 is registered\n"); | ||
468 | return -EINVAL; | ||
469 | } | ||
470 | 456 | ||
471 | mutex_init(&codec->mutex); | 457 | codec->control_data = da7210->control_data; |
472 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
473 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
474 | |||
475 | snd_soc_codec_set_drvdata(codec, da7210); | ||
476 | codec->name = "DA7210"; | ||
477 | codec->owner = THIS_MODULE; | ||
478 | codec->read = da7210_read; | ||
479 | codec->write = da7210_write; | ||
480 | codec->dai = &da7210_dai; | ||
481 | codec->num_dai = 1; | ||
482 | codec->hw_write = (hw_write_t)i2c_master_send; | 458 | codec->hw_write = (hw_write_t)i2c_master_send; |
483 | codec->reg_cache_size = ARRAY_SIZE(da7210_reg); | ||
484 | codec->reg_cache = kmemdup(da7210_reg, | ||
485 | sizeof(da7210_reg), GFP_KERNEL); | ||
486 | |||
487 | if (!codec->reg_cache) | ||
488 | return -ENOMEM; | ||
489 | |||
490 | da7210_dai.dev = codec->dev; | ||
491 | da7210_codec = codec; | ||
492 | |||
493 | ret = snd_soc_register_codec(codec); | ||
494 | if (ret) { | ||
495 | dev_err(codec->dev, "Failed to register CODEC: %d\n", ret); | ||
496 | goto init_err; | ||
497 | } | ||
498 | |||
499 | ret = snd_soc_register_dai(&da7210_dai); | ||
500 | if (ret) { | ||
501 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
502 | goto codec_err; | ||
503 | } | ||
504 | 459 | ||
505 | /* FIXME | 460 | /* FIXME |
506 | * | 461 | * |
@@ -583,54 +538,50 @@ static int da7210_init(struct da7210_priv *da7210) | |||
583 | /* Activate all enabled subsystem */ | 538 | /* Activate all enabled subsystem */ |
584 | da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); | 539 | da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); |
585 | 540 | ||
586 | return ret; | 541 | snd_soc_add_controls(codec, da7210_snd_controls, |
587 | 542 | ARRAY_SIZE(da7210_snd_controls)); | |
588 | codec_err: | ||
589 | snd_soc_unregister_codec(codec); | ||
590 | init_err: | ||
591 | kfree(codec->reg_cache); | ||
592 | codec->reg_cache = NULL; | ||
593 | 543 | ||
594 | return ret; | 544 | dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); |
595 | 545 | ||
546 | return 0; | ||
596 | } | 547 | } |
597 | 548 | ||
549 | static struct snd_soc_codec_driver soc_codec_dev_da7210 = { | ||
550 | .probe = da7210_probe, | ||
551 | .read = da7210_read, | ||
552 | .write = da7210_write, | ||
553 | .reg_cache_size = ARRAY_SIZE(da7210_reg), | ||
554 | .reg_word_size = sizeof(u8), | ||
555 | .reg_cache_default = da7210_reg, | ||
556 | }; | ||
557 | |||
598 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 558 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
599 | static int __devinit da7210_i2c_probe(struct i2c_client *i2c, | 559 | static int __devinit da7210_i2c_probe(struct i2c_client *i2c, |
600 | const struct i2c_device_id *id) | 560 | const struct i2c_device_id *id) |
601 | { | 561 | { |
602 | struct da7210_priv *da7210; | 562 | struct da7210_priv *da7210; |
603 | struct snd_soc_codec *codec; | ||
604 | int ret; | 563 | int ret; |
605 | 564 | ||
606 | da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL); | 565 | da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL); |
607 | if (!da7210) | 566 | if (!da7210) |
608 | return -ENOMEM; | 567 | return -ENOMEM; |
609 | 568 | ||
610 | codec = &da7210->codec; | ||
611 | codec->dev = &i2c->dev; | ||
612 | |||
613 | i2c_set_clientdata(i2c, da7210); | 569 | i2c_set_clientdata(i2c, da7210); |
614 | codec->control_data = i2c; | 570 | da7210->control_data = i2c; |
571 | da7210->control_type = SND_SOC_I2C; | ||
615 | 572 | ||
616 | ret = da7210_init(da7210); | 573 | ret = snd_soc_register_codec(&i2c->dev, |
617 | if (ret < 0) { | 574 | &soc_codec_dev_da7210, &da7210_dai, 1); |
618 | pr_err("Failed to initialise da7210 audio codec\n"); | 575 | if (ret < 0) |
619 | kfree(da7210); | 576 | kfree(da7210); |
620 | } | ||
621 | 577 | ||
622 | return ret; | 578 | return ret; |
623 | } | 579 | } |
624 | 580 | ||
625 | static int __devexit da7210_i2c_remove(struct i2c_client *client) | 581 | static int __devexit da7210_i2c_remove(struct i2c_client *client) |
626 | { | 582 | { |
627 | struct da7210_priv *da7210 = i2c_get_clientdata(client); | 583 | snd_soc_unregister_codec(&client->dev); |
628 | 584 | kfree(i2c_get_clientdata(client)); | |
629 | snd_soc_unregister_dai(&da7210_dai); | ||
630 | kfree(da7210->codec.reg_cache); | ||
631 | kfree(da7210); | ||
632 | da7210_codec = NULL; | ||
633 | |||
634 | return 0; | 585 | return 0; |
635 | } | 586 | } |
636 | 587 | ||
@@ -643,7 +594,7 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id); | |||
643 | /* I2C codec control layer */ | 594 | /* I2C codec control layer */ |
644 | static struct i2c_driver da7210_i2c_driver = { | 595 | static struct i2c_driver da7210_i2c_driver = { |
645 | .driver = { | 596 | .driver = { |
646 | .name = "DA7210 I2C Codec", | 597 | .name = "da7210-codec", |
647 | .owner = THIS_MODULE, | 598 | .owner = THIS_MODULE, |
648 | }, | 599 | }, |
649 | .probe = da7210_i2c_probe, | 600 | .probe = da7210_i2c_probe, |
@@ -652,50 +603,6 @@ static struct i2c_driver da7210_i2c_driver = { | |||
652 | }; | 603 | }; |
653 | #endif | 604 | #endif |
654 | 605 | ||
655 | static int da7210_probe(struct platform_device *pdev) | ||
656 | { | ||
657 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
658 | struct snd_soc_codec *codec; | ||
659 | int ret; | ||
660 | |||
661 | if (!da7210_codec) { | ||
662 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
663 | return -ENODEV; | ||
664 | } | ||
665 | |||
666 | socdev->card->codec = da7210_codec; | ||
667 | codec = da7210_codec; | ||
668 | |||
669 | /* Register pcms */ | ||
670 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
671 | if (ret < 0) | ||
672 | goto pcm_err; | ||
673 | |||
674 | snd_soc_add_controls(da7210_codec, da7210_snd_controls, | ||
675 | ARRAY_SIZE(da7210_snd_controls)); | ||
676 | |||
677 | dev_info(&pdev->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); | ||
678 | |||
679 | pcm_err: | ||
680 | return ret; | ||
681 | } | ||
682 | |||
683 | static int da7210_remove(struct platform_device *pdev) | ||
684 | { | ||
685 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
686 | |||
687 | snd_soc_free_pcms(socdev); | ||
688 | snd_soc_dapm_free(socdev); | ||
689 | |||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | struct snd_soc_codec_device soc_codec_dev_da7210 = { | ||
694 | .probe = da7210_probe, | ||
695 | .remove = da7210_remove, | ||
696 | }; | ||
697 | EXPORT_SYMBOL_GPL(soc_codec_dev_da7210); | ||
698 | |||
699 | static int __init da7210_modinit(void) | 606 | static int __init da7210_modinit(void) |
700 | { | 607 | { |
701 | int ret = 0; | 608 | int ret = 0; |
diff --git a/sound/soc/codecs/da7210.h b/sound/soc/codecs/da7210.h deleted file mode 100644 index 390d621eb742..000000000000 --- a/sound/soc/codecs/da7210.h +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /* | ||
2 | * da7210.h -- audio driver for da7210 | ||
3 | * | ||
4 | * Copyright (c) 2009 Dialog Semiconductor | ||
5 | * Written by David Chen <Dajun.chen@diasemi.com> | ||
6 | * | ||
7 | * Copyright (C) 2009 Renesas Solutions Corp. | ||
8 | * Cleanups by Kuninori Morimoto <morimoto.kuninori@renesas.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 | #ifndef _DA7210_H | ||
18 | #define _DA7210_H | ||
19 | |||
20 | extern struct snd_soc_dai da7210_dai; | ||
21 | extern struct snd_soc_codec_device soc_codec_dev_da7210; | ||
22 | |||
23 | #endif | ||
24 | |||
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 66557de1e4fe..16253ec9b022 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c | |||
@@ -74,29 +74,22 @@ static const uint32_t jz4740_codec_regs[] = { | |||
74 | struct jz4740_codec { | 74 | struct jz4740_codec { |
75 | void __iomem *base; | 75 | void __iomem *base; |
76 | struct resource *mem; | 76 | struct resource *mem; |
77 | |||
78 | uint32_t reg_cache[2]; | ||
79 | struct snd_soc_codec codec; | ||
80 | }; | 77 | }; |
81 | 78 | ||
82 | static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec) | ||
83 | { | ||
84 | return container_of(codec, struct jz4740_codec, codec); | ||
85 | } | ||
86 | |||
87 | static unsigned int jz4740_codec_read(struct snd_soc_codec *codec, | 79 | static unsigned int jz4740_codec_read(struct snd_soc_codec *codec, |
88 | unsigned int reg) | 80 | unsigned int reg) |
89 | { | 81 | { |
90 | struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec); | 82 | struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); |
91 | return readl(jz4740_codec->base + (reg << 2)); | 83 | return readl(jz4740_codec->base + (reg << 2)); |
92 | } | 84 | } |
93 | 85 | ||
94 | static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg, | 86 | static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg, |
95 | unsigned int val) | 87 | unsigned int val) |
96 | { | 88 | { |
97 | struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec); | 89 | struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); |
90 | u32 *cache = codec->reg_cache; | ||
98 | 91 | ||
99 | jz4740_codec->reg_cache[reg] = val; | 92 | cache[reg] = val; |
100 | writel(val, jz4740_codec->base + (reg << 2)); | 93 | writel(val, jz4740_codec->base + (reg << 2)); |
101 | 94 | ||
102 | return 0; | 95 | return 0; |
@@ -172,8 +165,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream, | |||
172 | { | 165 | { |
173 | uint32_t val; | 166 | uint32_t val; |
174 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 167 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
175 | struct snd_soc_device *socdev = rtd->socdev; | 168 | struct snd_soc_codec *codec =rtd->codec; |
176 | struct snd_soc_codec *codec = socdev->card->codec; | ||
177 | 169 | ||
178 | switch (params_rate(params)) { | 170 | switch (params_rate(params)) { |
179 | case 8000: | 171 | case 8000: |
@@ -219,8 +211,8 @@ static struct snd_soc_dai_ops jz4740_codec_dai_ops = { | |||
219 | .hw_params = jz4740_codec_hw_params, | 211 | .hw_params = jz4740_codec_hw_params, |
220 | }; | 212 | }; |
221 | 213 | ||
222 | struct snd_soc_dai jz4740_codec_dai = { | 214 | static struct snd_soc_dai_driver jz4740_codec_dai = { |
223 | .name = "jz4740", | 215 | .name = "jz4740-hifi", |
224 | .playback = { | 216 | .playback = { |
225 | .stream_name = "Playback", | 217 | .stream_name = "Playback", |
226 | .channels_min = 2, | 218 | .channels_min = 2, |
@@ -238,7 +230,6 @@ struct snd_soc_dai jz4740_codec_dai = { | |||
238 | .ops = &jz4740_codec_dai_ops, | 230 | .ops = &jz4740_codec_dai_ops, |
239 | .symmetric_rates = 1, | 231 | .symmetric_rates = 1, |
240 | }; | 232 | }; |
241 | EXPORT_SYMBOL_GPL(jz4740_codec_dai); | ||
242 | 233 | ||
243 | static void jz4740_codec_wakeup(struct snd_soc_codec *codec) | 234 | static void jz4740_codec_wakeup(struct snd_soc_codec *codec) |
244 | { | 235 | { |
@@ -302,23 +293,10 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, | |||
302 | return 0; | 293 | return 0; |
303 | } | 294 | } |
304 | 295 | ||
305 | static struct snd_soc_codec *jz4740_codec_codec; | 296 | static int jz4740_codec_dev_probe(struct snd_soc_codec *codec) |
306 | |||
307 | static int jz4740_codec_dev_probe(struct platform_device *pdev) | ||
308 | { | 297 | { |
309 | int ret; | 298 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, |
310 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 299 | JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); |
311 | struct snd_soc_codec *codec = jz4740_codec_codec; | ||
312 | |||
313 | BUG_ON(!codec); | ||
314 | |||
315 | socdev->card->codec = codec; | ||
316 | |||
317 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
318 | if (ret) { | ||
319 | dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret); | ||
320 | return ret; | ||
321 | } | ||
322 | 300 | ||
323 | snd_soc_add_controls(codec, jz4740_codec_controls, | 301 | snd_soc_add_controls(codec, jz4740_codec_controls, |
324 | ARRAY_SIZE(jz4740_codec_controls)); | 302 | ARRAY_SIZE(jz4740_codec_controls)); |
@@ -331,34 +309,27 @@ static int jz4740_codec_dev_probe(struct platform_device *pdev) | |||
331 | 309 | ||
332 | snd_soc_dapm_new_widgets(codec); | 310 | snd_soc_dapm_new_widgets(codec); |
333 | 311 | ||
312 | jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
313 | |||
334 | return 0; | 314 | return 0; |
335 | } | 315 | } |
336 | 316 | ||
337 | static int jz4740_codec_dev_remove(struct platform_device *pdev) | 317 | static int jz4740_codec_dev_remove(struct snd_soc_codec *codec) |
338 | { | 318 | { |
339 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 319 | jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); |
340 | |||
341 | snd_soc_free_pcms(socdev); | ||
342 | snd_soc_dapm_free(socdev); | ||
343 | 320 | ||
344 | return 0; | 321 | return 0; |
345 | } | 322 | } |
346 | 323 | ||
347 | #ifdef CONFIG_PM_SLEEP | 324 | #ifdef CONFIG_PM_SLEEP |
348 | 325 | ||
349 | static int jz4740_codec_suspend(struct platform_device *pdev, pm_message_t state) | 326 | static int jz4740_codec_suspend(struct snd_soc_codec *codec, pm_message_t state) |
350 | { | 327 | { |
351 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
352 | struct snd_soc_codec *codec = socdev->card->codec; | ||
353 | |||
354 | return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); | 328 | return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); |
355 | } | 329 | } |
356 | 330 | ||
357 | static int jz4740_codec_resume(struct platform_device *pdev) | 331 | static int jz4740_codec_resume(struct snd_soc_codec *codec) |
358 | { | 332 | { |
359 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
360 | struct snd_soc_codec *codec = socdev->card->codec; | ||
361 | |||
362 | return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 333 | return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
363 | } | 334 | } |
364 | 335 | ||
@@ -367,19 +338,23 @@ static int jz4740_codec_resume(struct platform_device *pdev) | |||
367 | #define jz4740_codec_resume NULL | 338 | #define jz4740_codec_resume NULL |
368 | #endif | 339 | #endif |
369 | 340 | ||
370 | struct snd_soc_codec_device soc_codec_dev_jz4740_codec = { | 341 | static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = { |
371 | .probe = jz4740_codec_dev_probe, | 342 | .probe = jz4740_codec_dev_probe, |
372 | .remove = jz4740_codec_dev_remove, | 343 | .remove = jz4740_codec_dev_remove, |
373 | .suspend = jz4740_codec_suspend, | 344 | .suspend = jz4740_codec_suspend, |
374 | .resume = jz4740_codec_resume, | 345 | .resume = jz4740_codec_resume, |
346 | .read = jz4740_codec_read, | ||
347 | .write = jz4740_codec_write, | ||
348 | .set_bias_level = jz4740_codec_set_bias_level, | ||
349 | .reg_cache_default = jz4740_codec_regs, | ||
350 | .reg_word_size = sizeof(u32), | ||
351 | .reg_cache_size = 2, | ||
375 | }; | 352 | }; |
376 | EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec); | ||
377 | 353 | ||
378 | static int __devinit jz4740_codec_probe(struct platform_device *pdev) | 354 | static int __devinit jz4740_codec_probe(struct platform_device *pdev) |
379 | { | 355 | { |
380 | int ret; | 356 | int ret; |
381 | struct jz4740_codec *jz4740_codec; | 357 | struct jz4740_codec *jz4740_codec; |
382 | struct snd_soc_codec *codec; | ||
383 | struct resource *mem; | 358 | struct resource *mem; |
384 | 359 | ||
385 | jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL); | 360 | jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL); |
@@ -408,55 +383,17 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev) | |||
408 | } | 383 | } |
409 | jz4740_codec->mem = mem; | 384 | jz4740_codec->mem = mem; |
410 | 385 | ||
411 | jz4740_codec_dai.dev = &pdev->dev; | ||
412 | |||
413 | codec = &jz4740_codec->codec; | ||
414 | |||
415 | codec->dev = &pdev->dev; | ||
416 | codec->name = "jz4740"; | ||
417 | codec->owner = THIS_MODULE; | ||
418 | |||
419 | codec->read = jz4740_codec_read; | ||
420 | codec->write = jz4740_codec_write; | ||
421 | codec->set_bias_level = jz4740_codec_set_bias_level; | ||
422 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
423 | |||
424 | codec->dai = &jz4740_codec_dai; | ||
425 | codec->num_dai = 1; | ||
426 | |||
427 | codec->reg_cache = jz4740_codec->reg_cache; | ||
428 | codec->reg_cache_size = 2; | ||
429 | memcpy(codec->reg_cache, jz4740_codec_regs, sizeof(jz4740_codec_regs)); | ||
430 | |||
431 | mutex_init(&codec->mutex); | ||
432 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
433 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
434 | |||
435 | jz4740_codec_codec = codec; | ||
436 | |||
437 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, | ||
438 | JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); | ||
439 | |||
440 | platform_set_drvdata(pdev, jz4740_codec); | 386 | platform_set_drvdata(pdev, jz4740_codec); |
441 | 387 | ||
442 | ret = snd_soc_register_codec(codec); | 388 | ret = snd_soc_register_codec(&pdev->dev, |
389 | &soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1); | ||
443 | if (ret) { | 390 | if (ret) { |
444 | dev_err(&pdev->dev, "Failed to register codec\n"); | 391 | dev_err(&pdev->dev, "Failed to register codec\n"); |
445 | goto err_iounmap; | 392 | goto err_iounmap; |
446 | } | 393 | } |
447 | 394 | ||
448 | ret = snd_soc_register_dai(&jz4740_codec_dai); | ||
449 | if (ret) { | ||
450 | dev_err(&pdev->dev, "Failed to register codec dai\n"); | ||
451 | goto err_unregister_codec; | ||
452 | } | ||
453 | |||
454 | jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
455 | |||
456 | return 0; | 395 | return 0; |
457 | 396 | ||
458 | err_unregister_codec: | ||
459 | snd_soc_unregister_codec(codec); | ||
460 | err_iounmap: | 397 | err_iounmap: |
461 | iounmap(jz4740_codec->base); | 398 | iounmap(jz4740_codec->base); |
462 | err_release_mem_region: | 399 | err_release_mem_region: |
@@ -472,8 +409,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev) | |||
472 | struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev); | 409 | struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev); |
473 | struct resource *mem = jz4740_codec->mem; | 410 | struct resource *mem = jz4740_codec->mem; |
474 | 411 | ||
475 | snd_soc_unregister_dai(&jz4740_codec_dai); | 412 | snd_soc_unregister_codec(&pdev->dev); |
476 | snd_soc_unregister_codec(&jz4740_codec->codec); | ||
477 | 413 | ||
478 | iounmap(jz4740_codec->base); | 414 | iounmap(jz4740_codec->base); |
479 | release_mem_region(mem->start, resource_size(mem)); | 415 | release_mem_region(mem->start, resource_size(mem)); |
diff --git a/sound/soc/codecs/jz4740.h b/sound/soc/codecs/jz4740.h deleted file mode 100644 index b5a0691be763..000000000000 --- a/sound/soc/codecs/jz4740.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * You should have received a copy of the GNU General Public License along | ||
9 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
10 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef __SND_SOC_CODECS_JZ4740_CODEC_H__ | ||
15 | #define __SND_SOC_CODECS_JZ4740_CODEC_H__ | ||
16 | |||
17 | extern struct snd_soc_dai jz4740_codec_dai; | ||
18 | extern struct snd_soc_codec_device soc_codec_dev_jz4740_codec; | ||
19 | |||
20 | #endif | ||
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 5a5f187a2657..bd8f26e41602 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c | |||
@@ -32,8 +32,8 @@ | |||
32 | #define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | 32 | #define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ |
33 | SNDRV_PCM_RATE_48000) | 33 | SNDRV_PCM_RATE_48000) |
34 | 34 | ||
35 | struct snd_soc_dai pcm3008_dai = { | 35 | static struct snd_soc_dai_driver pcm3008_dai = { |
36 | .name = "PCM3008 HiFi", | 36 | .name = "pcm3008-hifi", |
37 | .playback = { | 37 | .playback = { |
38 | .stream_name = "PCM3008 Playback", | 38 | .stream_name = "PCM3008 Playback", |
39 | .channels_min = 1, | 39 | .channels_min = 1, |
@@ -49,7 +49,6 @@ struct snd_soc_dai pcm3008_dai = { | |||
49 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 49 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
50 | }, | 50 | }, |
51 | }; | 51 | }; |
52 | EXPORT_SYMBOL_GPL(pcm3008_dai); | ||
53 | 52 | ||
54 | static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) | 53 | static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) |
55 | { | 54 | { |
@@ -59,38 +58,13 @@ static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) | |||
59 | gpio_free(setup->pdda_pin); | 58 | gpio_free(setup->pdda_pin); |
60 | } | 59 | } |
61 | 60 | ||
62 | static int pcm3008_soc_probe(struct platform_device *pdev) | 61 | static int pcm3008_soc_probe(struct snd_soc_codec *codec) |
63 | { | 62 | { |
64 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 63 | struct pcm3008_setup_data *setup = codec->dev->platform_data; |
65 | struct snd_soc_codec *codec; | ||
66 | struct pcm3008_setup_data *setup = socdev->codec_data; | ||
67 | int ret = 0; | 64 | int ret = 0; |
68 | 65 | ||
69 | printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); | 66 | printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); |
70 | 67 | ||
71 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
72 | if (!socdev->card->codec) | ||
73 | return -ENOMEM; | ||
74 | |||
75 | codec = socdev->card->codec; | ||
76 | mutex_init(&codec->mutex); | ||
77 | |||
78 | codec->name = "PCM3008"; | ||
79 | codec->owner = THIS_MODULE; | ||
80 | codec->dai = &pcm3008_dai; | ||
81 | codec->num_dai = 1; | ||
82 | codec->write = NULL; | ||
83 | codec->read = NULL; | ||
84 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
85 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
86 | |||
87 | /* Register PCMs. */ | ||
88 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
89 | if (ret < 0) { | ||
90 | printk(KERN_ERR "pcm3008: failed to create pcms\n"); | ||
91 | goto pcm_err; | ||
92 | } | ||
93 | |||
94 | /* DEM1 DEM0 DE-EMPHASIS_MODE | 68 | /* DEM1 DEM0 DE-EMPHASIS_MODE |
95 | * Low Low De-emphasis 44.1 kHz ON | 69 | * Low Low De-emphasis 44.1 kHz ON |
96 | * Low High De-emphasis OFF | 70 | * Low High De-emphasis OFF |
@@ -130,33 +104,22 @@ static int pcm3008_soc_probe(struct platform_device *pdev) | |||
130 | 104 | ||
131 | gpio_err: | 105 | gpio_err: |
132 | pcm3008_gpio_free(setup); | 106 | pcm3008_gpio_free(setup); |
133 | pcm_err: | ||
134 | kfree(socdev->card->codec); | ||
135 | 107 | ||
136 | return ret; | 108 | return ret; |
137 | } | 109 | } |
138 | 110 | ||
139 | static int pcm3008_soc_remove(struct platform_device *pdev) | 111 | static int pcm3008_soc_remove(struct snd_soc_codec *codec) |
140 | { | 112 | { |
141 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 113 | struct pcm3008_setup_data *setup = codec->dev->platform_data; |
142 | struct snd_soc_codec *codec = socdev->card->codec; | ||
143 | struct pcm3008_setup_data *setup = socdev->codec_data; | ||
144 | |||
145 | if (!codec) | ||
146 | return 0; | ||
147 | 114 | ||
148 | pcm3008_gpio_free(setup); | 115 | pcm3008_gpio_free(setup); |
149 | snd_soc_free_pcms(socdev); | ||
150 | kfree(socdev->card->codec); | ||
151 | |||
152 | return 0; | 116 | return 0; |
153 | } | 117 | } |
154 | 118 | ||
155 | #ifdef CONFIG_PM | 119 | #ifdef CONFIG_PM |
156 | static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg) | 120 | static int pcm3008_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg) |
157 | { | 121 | { |
158 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 122 | struct pcm3008_setup_data *setup = codec->dev->platform_data; |
159 | struct pcm3008_setup_data *setup = socdev->codec_data; | ||
160 | 123 | ||
161 | gpio_set_value(setup->pdad_pin, 0); | 124 | gpio_set_value(setup->pdad_pin, 0); |
162 | gpio_set_value(setup->pdda_pin, 0); | 125 | gpio_set_value(setup->pdda_pin, 0); |
@@ -164,10 +127,9 @@ static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg) | |||
164 | return 0; | 127 | return 0; |
165 | } | 128 | } |
166 | 129 | ||
167 | static int pcm3008_soc_resume(struct platform_device *pdev) | 130 | static int pcm3008_soc_resume(struct snd_soc_codec *codec) |
168 | { | 131 | { |
169 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 132 | struct pcm3008_setup_data *setup = codec->dev->platform_data; |
170 | struct pcm3008_setup_data *setup = socdev->codec_data; | ||
171 | 133 | ||
172 | gpio_set_value(setup->pdad_pin, 1); | 134 | gpio_set_value(setup->pdad_pin, 1); |
173 | gpio_set_value(setup->pdda_pin, 1); | 135 | gpio_set_value(setup->pdda_pin, 1); |
@@ -179,23 +141,45 @@ static int pcm3008_soc_resume(struct platform_device *pdev) | |||
179 | #define pcm3008_soc_resume NULL | 141 | #define pcm3008_soc_resume NULL |
180 | #endif | 142 | #endif |
181 | 143 | ||
182 | struct snd_soc_codec_device soc_codec_dev_pcm3008 = { | 144 | static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = { |
183 | .probe = pcm3008_soc_probe, | 145 | .probe = pcm3008_soc_probe, |
184 | .remove = pcm3008_soc_remove, | 146 | .remove = pcm3008_soc_remove, |
185 | .suspend = pcm3008_soc_suspend, | 147 | .suspend = pcm3008_soc_suspend, |
186 | .resume = pcm3008_soc_resume, | 148 | .resume = pcm3008_soc_resume, |
187 | }; | 149 | }; |
188 | EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008); | ||
189 | 150 | ||
190 | static int __init pcm3008_init(void) | 151 | static int __devinit pcm3008_codec_probe(struct platform_device *pdev) |
152 | { | ||
153 | return snd_soc_register_codec(&pdev->dev, | ||
154 | &soc_codec_dev_pcm3008, &pcm3008_dai, 1); | ||
155 | } | ||
156 | |||
157 | static int __devexit pcm3008_codec_remove(struct platform_device *pdev) | ||
158 | { | ||
159 | snd_soc_unregister_codec(&pdev->dev); | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | MODULE_ALIAS("platform:pcm3008-codec"); | ||
164 | |||
165 | static struct platform_driver pcm3008_codec_driver = { | ||
166 | .probe = pcm3008_codec_probe, | ||
167 | .remove = __devexit_p(pcm3008_codec_remove), | ||
168 | .driver = { | ||
169 | .name = "pcm3008-codec", | ||
170 | .owner = THIS_MODULE, | ||
171 | }, | ||
172 | }; | ||
173 | |||
174 | static int __init pcm3008_modinit(void) | ||
191 | { | 175 | { |
192 | return snd_soc_register_dai(&pcm3008_dai); | 176 | return platform_driver_register(&pcm3008_codec_driver); |
193 | } | 177 | } |
194 | module_init(pcm3008_init); | 178 | module_init(pcm3008_modinit); |
195 | 179 | ||
196 | static void __exit pcm3008_exit(void) | 180 | static void __exit pcm3008_exit(void) |
197 | { | 181 | { |
198 | snd_soc_unregister_dai(&pcm3008_dai); | 182 | platform_driver_unregister(&pcm3008_codec_driver); |
199 | } | 183 | } |
200 | module_exit(pcm3008_exit); | 184 | module_exit(pcm3008_exit); |
201 | 185 | ||
diff --git a/sound/soc/codecs/pcm3008.h b/sound/soc/codecs/pcm3008.h index d04e87d3c060..7e5489ab4812 100644 --- a/sound/soc/codecs/pcm3008.h +++ b/sound/soc/codecs/pcm3008.h | |||
@@ -19,7 +19,4 @@ struct pcm3008_setup_data { | |||
19 | unsigned pdda_pin; | 19 | unsigned pdda_pin; |
20 | }; | 20 | }; |
21 | 21 | ||
22 | extern struct snd_soc_codec_device soc_codec_dev_pcm3008; | ||
23 | extern struct snd_soc_dai pcm3008_dai; | ||
24 | |||
25 | #endif | 22 | #endif |
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c index 9119836051a4..4c32b54913ad 100644 --- a/sound/soc/codecs/spdif_transciever.c +++ b/sound/soc/codecs/spdif_transciever.c | |||
@@ -21,57 +21,16 @@ | |||
21 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
22 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
23 | 23 | ||
24 | #include "spdif_transciever.h" | ||
25 | |||
26 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
27 | 25 | ||
28 | #define STUB_RATES SNDRV_PCM_RATE_8000_96000 | 26 | #define STUB_RATES SNDRV_PCM_RATE_8000_96000 |
29 | #define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE | 27 | #define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE |
30 | 28 | ||
31 | static struct snd_soc_codec *spdif_dit_codec; | ||
32 | |||
33 | static int spdif_dit_codec_probe(struct platform_device *pdev) | ||
34 | { | ||
35 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
36 | struct snd_soc_codec *codec; | ||
37 | int ret; | ||
38 | |||
39 | if (spdif_dit_codec == NULL) { | ||
40 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
41 | return -ENODEV; | ||
42 | } | ||
43 | |||
44 | socdev->card->codec = spdif_dit_codec; | ||
45 | codec = spdif_dit_codec; | ||
46 | |||
47 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
48 | if (ret < 0) { | ||
49 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
50 | goto err_create_pcms; | ||
51 | } | ||
52 | |||
53 | return 0; | ||
54 | |||
55 | err_create_pcms: | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | static int spdif_dit_codec_remove(struct platform_device *pdev) | ||
60 | { | ||
61 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
62 | |||
63 | snd_soc_free_pcms(socdev); | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | 29 | ||
68 | struct snd_soc_codec_device soc_codec_dev_spdif_dit = { | 30 | static struct snd_soc_codec_driver soc_codec_spdif_dit; |
69 | .probe = spdif_dit_codec_probe, | ||
70 | .remove = spdif_dit_codec_remove, | ||
71 | }; EXPORT_SYMBOL_GPL(soc_codec_dev_spdif_dit); | ||
72 | 31 | ||
73 | struct snd_soc_dai dit_stub_dai = { | 32 | static struct snd_soc_dai_driver dit_stub_dai = { |
74 | .name = "DIT", | 33 | .name = "dit-hifi", |
75 | .playback = { | 34 | .playback = { |
76 | .stream_name = "Playback", | 35 | .stream_name = "Playback", |
77 | .channels_min = 1, | 36 | .channels_min = 1, |
@@ -80,65 +39,16 @@ struct snd_soc_dai dit_stub_dai = { | |||
80 | .formats = STUB_FORMATS, | 39 | .formats = STUB_FORMATS, |
81 | }, | 40 | }, |
82 | }; | 41 | }; |
83 | EXPORT_SYMBOL_GPL(dit_stub_dai); | ||
84 | 42 | ||
85 | static int spdif_dit_probe(struct platform_device *pdev) | 43 | static int spdif_dit_probe(struct platform_device *pdev) |
86 | { | 44 | { |
87 | struct snd_soc_codec *codec; | 45 | return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit, |
88 | int ret; | 46 | &dit_stub_dai, 1); |
89 | |||
90 | if (spdif_dit_codec) { | ||
91 | dev_err(&pdev->dev, "Another Codec is registered\n"); | ||
92 | ret = -EINVAL; | ||
93 | goto err_reg_codec; | ||
94 | } | ||
95 | |||
96 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
97 | if (codec == NULL) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | codec->dev = &pdev->dev; | ||
101 | |||
102 | mutex_init(&codec->mutex); | ||
103 | |||
104 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
105 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
106 | |||
107 | codec->name = "spdif-dit"; | ||
108 | codec->owner = THIS_MODULE; | ||
109 | codec->dai = &dit_stub_dai; | ||
110 | codec->num_dai = 1; | ||
111 | |||
112 | spdif_dit_codec = codec; | ||
113 | |||
114 | ret = snd_soc_register_codec(codec); | ||
115 | if (ret < 0) { | ||
116 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
117 | goto err_reg_codec; | ||
118 | } | ||
119 | |||
120 | dit_stub_dai.dev = &pdev->dev; | ||
121 | ret = snd_soc_register_dai(&dit_stub_dai); | ||
122 | if (ret < 0) { | ||
123 | dev_err(codec->dev, "Failed to register dai: %d\n", ret); | ||
124 | goto err_reg_dai; | ||
125 | } | ||
126 | |||
127 | return 0; | ||
128 | |||
129 | err_reg_dai: | ||
130 | snd_soc_unregister_codec(codec); | ||
131 | err_reg_codec: | ||
132 | kfree(spdif_dit_codec); | ||
133 | return ret; | ||
134 | } | 47 | } |
135 | 48 | ||
136 | static int spdif_dit_remove(struct platform_device *pdev) | 49 | static int spdif_dit_remove(struct platform_device *pdev) |
137 | { | 50 | { |
138 | snd_soc_unregister_dai(&dit_stub_dai); | 51 | snd_soc_unregister_codec(&pdev->dev); |
139 | snd_soc_unregister_codec(spdif_dit_codec); | ||
140 | kfree(spdif_dit_codec); | ||
141 | spdif_dit_codec = NULL; | ||
142 | return 0; | 52 | return 0; |
143 | } | 53 | } |
144 | 54 | ||
diff --git a/sound/soc/codecs/spdif_transciever.h b/sound/soc/codecs/spdif_transciever.h deleted file mode 100644 index 1e102124f546..000000000000 --- a/sound/soc/codecs/spdif_transciever.h +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA SoC DIT/DIR driver header | ||
3 | * | ||
4 | * Author: Steve Chen, <schen@mvista.com> | ||
5 | * Copyright: (C) 2008 MontaVista Software, Inc., <source@mvista.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef CODEC_STUBS_H | ||
13 | #define CODEC_STUBS_H | ||
14 | |||
15 | extern struct snd_soc_codec_device soc_codec_dev_spdif_dit; | ||
16 | extern struct snd_soc_dai dit_stub_dai; | ||
17 | |||
18 | #endif /* CODEC_STUBS_H */ | ||
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index b47ed4f6ab20..67d8c044ca04 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -45,11 +45,11 @@ | |||
45 | 45 | ||
46 | #define SSM2602_VERSION "0.1" | 46 | #define SSM2602_VERSION "0.1" |
47 | 47 | ||
48 | struct snd_soc_codec_device soc_codec_dev_ssm2602; | ||
49 | |||
50 | /* codec private data */ | 48 | /* codec private data */ |
51 | struct ssm2602_priv { | 49 | struct ssm2602_priv { |
52 | unsigned int sysclk; | 50 | unsigned int sysclk; |
51 | enum snd_soc_control_type control_type; | ||
52 | void *control_data; | ||
53 | struct snd_pcm_substream *master_substream; | 53 | struct snd_pcm_substream *master_substream; |
54 | struct snd_pcm_substream *slave_substream; | 54 | struct snd_pcm_substream *slave_substream; |
55 | }; | 55 | }; |
@@ -276,8 +276,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
276 | { | 276 | { |
277 | u16 srate; | 277 | u16 srate; |
278 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 278 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
279 | struct snd_soc_device *socdev = rtd->socdev; | 279 | struct snd_soc_codec *codec = rtd->codec; |
280 | struct snd_soc_codec *codec = socdev->card->codec; | ||
281 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 280 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
282 | struct i2c_client *i2c = codec->control_data; | 281 | struct i2c_client *i2c = codec->control_data; |
283 | u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; | 282 | u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; |
@@ -321,8 +320,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, | |||
321 | struct snd_soc_dai *dai) | 320 | struct snd_soc_dai *dai) |
322 | { | 321 | { |
323 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 322 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
324 | struct snd_soc_device *socdev = rtd->socdev; | 323 | struct snd_soc_codec *codec = rtd->codec; |
325 | struct snd_soc_codec *codec = socdev->card->codec; | ||
326 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 324 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
327 | struct i2c_client *i2c = codec->control_data; | 325 | struct i2c_client *i2c = codec->control_data; |
328 | struct snd_pcm_runtime *master_runtime; | 326 | struct snd_pcm_runtime *master_runtime; |
@@ -360,8 +358,7 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream, | |||
360 | struct snd_soc_dai *dai) | 358 | struct snd_soc_dai *dai) |
361 | { | 359 | { |
362 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 360 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
363 | struct snd_soc_device *socdev = rtd->socdev; | 361 | struct snd_soc_codec *codec = rtd->codec; |
364 | struct snd_soc_codec *codec = socdev->card->codec; | ||
365 | /* set active */ | 362 | /* set active */ |
366 | ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); | 363 | ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); |
367 | 364 | ||
@@ -372,8 +369,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream, | |||
372 | struct snd_soc_dai *dai) | 369 | struct snd_soc_dai *dai) |
373 | { | 370 | { |
374 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 371 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
375 | struct snd_soc_device *socdev = rtd->socdev; | 372 | struct snd_soc_codec *codec = rtd->codec; |
376 | struct snd_soc_codec *codec = socdev->card->codec; | ||
377 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 373 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
378 | 374 | ||
379 | /* deactivate */ | 375 | /* deactivate */ |
@@ -518,8 +514,8 @@ static struct snd_soc_dai_ops ssm2602_dai_ops = { | |||
518 | .set_fmt = ssm2602_set_dai_fmt, | 514 | .set_fmt = ssm2602_set_dai_fmt, |
519 | }; | 515 | }; |
520 | 516 | ||
521 | struct snd_soc_dai ssm2602_dai = { | 517 | static struct snd_soc_dai_driver ssm2602_dai = { |
522 | .name = "SSM2602", | 518 | .name = "ssm2602-hifi", |
523 | .playback = { | 519 | .playback = { |
524 | .stream_name = "Playback", | 520 | .stream_name = "Playback", |
525 | .channels_min = 2, | 521 | .channels_min = 2, |
@@ -534,21 +530,15 @@ struct snd_soc_dai ssm2602_dai = { | |||
534 | .formats = SSM2602_FORMATS,}, | 530 | .formats = SSM2602_FORMATS,}, |
535 | .ops = &ssm2602_dai_ops, | 531 | .ops = &ssm2602_dai_ops, |
536 | }; | 532 | }; |
537 | EXPORT_SYMBOL_GPL(ssm2602_dai); | ||
538 | 533 | ||
539 | static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) | 534 | static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state) |
540 | { | 535 | { |
541 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
542 | struct snd_soc_codec *codec = socdev->card->codec; | ||
543 | |||
544 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); | 536 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); |
545 | return 0; | 537 | return 0; |
546 | } | 538 | } |
547 | 539 | ||
548 | static int ssm2602_resume(struct platform_device *pdev) | 540 | static int ssm2602_resume(struct snd_soc_codec *codec) |
549 | { | 541 | { |
550 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
551 | struct snd_soc_codec *codec = socdev->card->codec; | ||
552 | int i; | 542 | int i; |
553 | u8 data[2]; | 543 | u8 data[2]; |
554 | u16 *cache = codec->reg_cache; | 544 | u16 *cache = codec->reg_cache; |
@@ -563,36 +553,18 @@ static int ssm2602_resume(struct platform_device *pdev) | |||
563 | return 0; | 553 | return 0; |
564 | } | 554 | } |
565 | 555 | ||
566 | /* | 556 | static int ssm2602_probe(struct snd_soc_codec *codec) |
567 | * initialise the ssm2602 driver | ||
568 | * register the mixer and dsp interfaces with the kernel | ||
569 | */ | ||
570 | static int ssm2602_init(struct snd_soc_device *socdev) | ||
571 | { | 557 | { |
572 | struct snd_soc_codec *codec = socdev->card->codec; | 558 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
573 | int reg, ret = 0; | 559 | int ret = 0, reg; |
574 | 560 | ||
575 | codec->name = "SSM2602"; | 561 | pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); |
576 | codec->owner = THIS_MODULE; | 562 | |
577 | codec->read = ssm2602_read_reg_cache; | 563 | codec->bias_level = SND_SOC_BIAS_OFF, |
578 | codec->write = ssm2602_write; | 564 | codec->control_data = ssm2602->control_data; |
579 | codec->set_bias_level = ssm2602_set_bias_level; | ||
580 | codec->dai = &ssm2602_dai; | ||
581 | codec->num_dai = 1; | ||
582 | codec->reg_cache_size = sizeof(ssm2602_reg); | ||
583 | codec->reg_cache = kmemdup(ssm2602_reg, sizeof(ssm2602_reg), | ||
584 | GFP_KERNEL); | ||
585 | if (codec->reg_cache == NULL) | ||
586 | return -ENOMEM; | ||
587 | 565 | ||
588 | ssm2602_reset(codec); | 566 | ssm2602_reset(codec); |
589 | 567 | ||
590 | /* register pcms */ | ||
591 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
592 | if (ret < 0) { | ||
593 | pr_err("ssm2602: failed to create pcms\n"); | ||
594 | goto pcm_err; | ||
595 | } | ||
596 | /*power on device*/ | 568 | /*power on device*/ |
597 | ssm2602_write(codec, SSM2602_ACTIVE, 0); | 569 | ssm2602_write(codec, SSM2602_ACTIVE, 0); |
598 | /* set the update bits */ | 570 | /* set the update bits */ |
@@ -614,13 +586,27 @@ static int ssm2602_init(struct snd_soc_device *socdev) | |||
614 | ssm2602_add_widgets(codec); | 586 | ssm2602_add_widgets(codec); |
615 | 587 | ||
616 | return ret; | 588 | return ret; |
589 | } | ||
617 | 590 | ||
618 | pcm_err: | 591 | /* remove everything here */ |
619 | kfree(codec->reg_cache); | 592 | static int ssm2602_remove(struct snd_soc_codec *codec) |
620 | return ret; | 593 | { |
594 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
595 | return 0; | ||
621 | } | 596 | } |
622 | 597 | ||
623 | static struct snd_soc_device *ssm2602_socdev; | 598 | static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { |
599 | .probe = ssm2602_probe, | ||
600 | .remove = ssm2602_remove, | ||
601 | .suspend = ssm2602_suspend, | ||
602 | .resume = ssm2602_resume, | ||
603 | .read = ssm2602_read_reg_cache, | ||
604 | .write = ssm2602_write, | ||
605 | .set_bias_level = ssm2602_set_bias_level, | ||
606 | .reg_cache_size = sizeof(ssm2602_reg), | ||
607 | .reg_word_size = sizeof(u16), | ||
608 | .reg_cache_default = ssm2602_reg, | ||
609 | }; | ||
624 | 610 | ||
625 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 611 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
626 | /* | 612 | /* |
@@ -632,24 +618,28 @@ static struct snd_soc_device *ssm2602_socdev; | |||
632 | static int ssm2602_i2c_probe(struct i2c_client *i2c, | 618 | static int ssm2602_i2c_probe(struct i2c_client *i2c, |
633 | const struct i2c_device_id *id) | 619 | const struct i2c_device_id *id) |
634 | { | 620 | { |
635 | struct snd_soc_device *socdev = ssm2602_socdev; | 621 | struct ssm2602_priv *ssm2602; |
636 | struct snd_soc_codec *codec = socdev->card->codec; | ||
637 | int ret; | 622 | int ret; |
638 | 623 | ||
639 | i2c_set_clientdata(i2c, codec); | 624 | ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL); |
640 | codec->control_data = i2c; | 625 | if (ssm2602 == NULL) |
626 | return -ENOMEM; | ||
641 | 627 | ||
642 | ret = ssm2602_init(socdev); | 628 | i2c_set_clientdata(i2c, ssm2602); |
643 | if (ret < 0) | 629 | ssm2602->control_data = i2c; |
644 | pr_err("failed to initialise SSM2602\n"); | 630 | ssm2602->control_type = SND_SOC_I2C; |
645 | 631 | ||
632 | ret = snd_soc_register_codec(&i2c->dev, | ||
633 | &soc_codec_dev_ssm2602, &ssm2602_dai, 1); | ||
634 | if (ret < 0) | ||
635 | kfree(ssm2602); | ||
646 | return ret; | 636 | return ret; |
647 | } | 637 | } |
648 | 638 | ||
649 | static int ssm2602_i2c_remove(struct i2c_client *client) | 639 | static int ssm2602_i2c_remove(struct i2c_client *client) |
650 | { | 640 | { |
651 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 641 | snd_soc_unregister_codec(&client->dev); |
652 | kfree(codec->reg_cache); | 642 | kfree(i2c_get_clientdata(client)); |
653 | return 0; | 643 | return 0; |
654 | } | 644 | } |
655 | 645 | ||
@@ -658,130 +648,39 @@ static const struct i2c_device_id ssm2602_i2c_id[] = { | |||
658 | { } | 648 | { } |
659 | }; | 649 | }; |
660 | MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); | 650 | MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); |
651 | |||
661 | /* corgi i2c codec control layer */ | 652 | /* corgi i2c codec control layer */ |
662 | static struct i2c_driver ssm2602_i2c_driver = { | 653 | static struct i2c_driver ssm2602_i2c_driver = { |
663 | .driver = { | 654 | .driver = { |
664 | .name = "SSM2602 I2C Codec", | 655 | .name = "ssm2602-codec", |
665 | .owner = THIS_MODULE, | 656 | .owner = THIS_MODULE, |
666 | }, | 657 | }, |
667 | .probe = ssm2602_i2c_probe, | 658 | .probe = ssm2602_i2c_probe, |
668 | .remove = ssm2602_i2c_remove, | 659 | .remove = ssm2602_i2c_remove, |
669 | .id_table = ssm2602_i2c_id, | 660 | .id_table = ssm2602_i2c_id, |
670 | }; | 661 | }; |
671 | |||
672 | static int ssm2602_add_i2c_device(struct platform_device *pdev, | ||
673 | const struct ssm2602_setup_data *setup) | ||
674 | { | ||
675 | struct i2c_board_info info; | ||
676 | struct i2c_adapter *adapter; | ||
677 | struct i2c_client *client; | ||
678 | int ret; | ||
679 | |||
680 | ret = i2c_add_driver(&ssm2602_i2c_driver); | ||
681 | if (ret != 0) { | ||
682 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
683 | return ret; | ||
684 | } | ||
685 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
686 | info.addr = setup->i2c_address; | ||
687 | strlcpy(info.type, "ssm2602", I2C_NAME_SIZE); | ||
688 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
689 | if (!adapter) { | ||
690 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
691 | setup->i2c_bus); | ||
692 | goto err_driver; | ||
693 | } | ||
694 | client = i2c_new_device(adapter, &info); | ||
695 | i2c_put_adapter(adapter); | ||
696 | if (!client) { | ||
697 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
698 | (unsigned int)info.addr); | ||
699 | goto err_driver; | ||
700 | } | ||
701 | return 0; | ||
702 | err_driver: | ||
703 | i2c_del_driver(&ssm2602_i2c_driver); | ||
704 | return -ENODEV; | ||
705 | } | ||
706 | #endif | 662 | #endif |
707 | 663 | ||
708 | static int ssm2602_probe(struct platform_device *pdev) | 664 | |
665 | static int __init ssm2602_modinit(void) | ||
709 | { | 666 | { |
710 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
711 | struct ssm2602_setup_data *setup; | ||
712 | struct snd_soc_codec *codec; | ||
713 | struct ssm2602_priv *ssm2602; | ||
714 | int ret = 0; | 667 | int ret = 0; |
715 | |||
716 | pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); | ||
717 | |||
718 | setup = socdev->codec_data; | ||
719 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
720 | if (codec == NULL) | ||
721 | return -ENOMEM; | ||
722 | |||
723 | ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL); | ||
724 | if (ssm2602 == NULL) { | ||
725 | kfree(codec); | ||
726 | return -ENOMEM; | ||
727 | } | ||
728 | |||
729 | snd_soc_codec_set_drvdata(codec, ssm2602); | ||
730 | socdev->card->codec = codec; | ||
731 | mutex_init(&codec->mutex); | ||
732 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
733 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
734 | |||
735 | ssm2602_socdev = socdev; | ||
736 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 668 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
737 | if (setup->i2c_address) { | 669 | ret = i2c_add_driver(&ssm2602_i2c_driver); |
738 | codec->hw_write = (hw_write_t)i2c_master_send; | 670 | if (ret != 0) { |
739 | ret = ssm2602_add_i2c_device(pdev, setup); | 671 | printk(KERN_ERR "Failed to register SSM2602 I2C driver: %d\n", |
672 | ret); | ||
740 | } | 673 | } |
741 | #else | ||
742 | /* other interfaces */ | ||
743 | #endif | 674 | #endif |
744 | return ret; | 675 | return ret; |
745 | } | 676 | } |
677 | module_init(ssm2602_modinit); | ||
746 | 678 | ||
747 | /* remove everything here */ | 679 | static void __exit ssm2602_exit(void) |
748 | static int ssm2602_remove(struct platform_device *pdev) | ||
749 | { | 680 | { |
750 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
751 | struct snd_soc_codec *codec = socdev->card->codec; | ||
752 | |||
753 | if (codec->control_data) | ||
754 | ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
755 | |||
756 | snd_soc_free_pcms(socdev); | ||
757 | snd_soc_dapm_free(socdev); | ||
758 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 681 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
759 | i2c_unregister_device(codec->control_data); | ||
760 | i2c_del_driver(&ssm2602_i2c_driver); | 682 | i2c_del_driver(&ssm2602_i2c_driver); |
761 | #endif | 683 | #endif |
762 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
763 | kfree(codec); | ||
764 | |||
765 | return 0; | ||
766 | } | ||
767 | |||
768 | struct snd_soc_codec_device soc_codec_dev_ssm2602 = { | ||
769 | .probe = ssm2602_probe, | ||
770 | .remove = ssm2602_remove, | ||
771 | .suspend = ssm2602_suspend, | ||
772 | .resume = ssm2602_resume, | ||
773 | }; | ||
774 | EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602); | ||
775 | |||
776 | static int __init ssm2602_modinit(void) | ||
777 | { | ||
778 | return snd_soc_register_dai(&ssm2602_dai); | ||
779 | } | ||
780 | module_init(ssm2602_modinit); | ||
781 | |||
782 | static void __exit ssm2602_exit(void) | ||
783 | { | ||
784 | snd_soc_unregister_dai(&ssm2602_dai); | ||
785 | } | 684 | } |
786 | module_exit(ssm2602_exit); | 685 | module_exit(ssm2602_exit); |
787 | 686 | ||
diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h index f344e6d76e31..42a47d0f8e25 100644 --- a/sound/soc/codecs/ssm2602.h +++ b/sound/soc/codecs/ssm2602.h | |||
@@ -124,7 +124,4 @@ struct ssm2602_setup_data { | |||
124 | unsigned short i2c_address; | 124 | unsigned short i2c_address; |
125 | }; | 125 | }; |
126 | 126 | ||
127 | extern struct snd_soc_dai ssm2602_dai; | ||
128 | extern struct snd_soc_codec_device soc_codec_dev_ssm2602; | ||
129 | |||
130 | #endif | 127 | #endif |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index ee86568545c2..00d67cc8e206 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
26 | #include <sound/soc.h> | 26 | #include <sound/soc.h> |
27 | #include <sound/tlv.h> | 27 | #include <sound/tlv.h> |
28 | #include <sound/soc-of-simple.h> | ||
29 | 28 | ||
30 | #include "stac9766.h" | 29 | #include "stac9766.h" |
31 | 30 | ||
@@ -257,20 +256,15 @@ static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) | |||
257 | return 0; | 256 | return 0; |
258 | } | 257 | } |
259 | 258 | ||
260 | static int stac9766_codec_suspend(struct platform_device *pdev, | 259 | static int stac9766_codec_suspend(struct snd_soc_codec *codec, |
261 | pm_message_t state) | 260 | pm_message_t state) |
262 | { | 261 | { |
263 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
264 | struct snd_soc_codec *codec = socdev->card->codec; | ||
265 | |||
266 | stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF); | 262 | stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF); |
267 | return 0; | 263 | return 0; |
268 | } | 264 | } |
269 | 265 | ||
270 | static int stac9766_codec_resume(struct platform_device *pdev) | 266 | static int stac9766_codec_resume(struct snd_soc_codec *codec) |
271 | { | 267 | { |
272 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
273 | struct snd_soc_codec *codec = socdev->card->codec; | ||
274 | u16 id, reset; | 268 | u16 id, reset; |
275 | 269 | ||
276 | reset = 0; | 270 | reset = 0; |
@@ -300,10 +294,9 @@ static struct snd_soc_dai_ops stac9766_dai_ops_digital = { | |||
300 | .prepare = ac97_digital_prepare, | 294 | .prepare = ac97_digital_prepare, |
301 | }; | 295 | }; |
302 | 296 | ||
303 | struct snd_soc_dai stac9766_dai[] = { | 297 | static struct snd_soc_dai_driver stac9766_dai[] = { |
304 | { | 298 | { |
305 | .name = "stac9766 analog", | 299 | .name = "stac9766-hifi-analog", |
306 | .id = 0, | ||
307 | .ac97_control = 1, | 300 | .ac97_control = 1, |
308 | 301 | ||
309 | /* stream cababilities */ | 302 | /* stream cababilities */ |
@@ -325,8 +318,7 @@ struct snd_soc_dai stac9766_dai[] = { | |||
325 | .ops = &stac9766_dai_ops_analog, | 318 | .ops = &stac9766_dai_ops_analog, |
326 | }, | 319 | }, |
327 | { | 320 | { |
328 | .name = "stac9766 IEC958", | 321 | .name = "stac9766-hifi-IEC958", |
329 | .id = 1, | ||
330 | .ac97_control = 1, | 322 | .ac97_control = 1, |
331 | 323 | ||
332 | /* stream cababilities */ | 324 | /* stream cababilities */ |
@@ -342,57 +334,24 @@ struct snd_soc_dai stac9766_dai[] = { | |||
342 | .ops = &stac9766_dai_ops_digital, | 334 | .ops = &stac9766_dai_ops_digital, |
343 | } | 335 | } |
344 | }; | 336 | }; |
345 | EXPORT_SYMBOL_GPL(stac9766_dai); | ||
346 | 337 | ||
347 | static int stac9766_codec_probe(struct platform_device *pdev) | 338 | static int stac9766_codec_probe(struct snd_soc_codec *codec) |
348 | { | 339 | { |
349 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
350 | struct snd_soc_codec *codec; | ||
351 | int ret = 0; | 340 | int ret = 0; |
352 | 341 | ||
353 | printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); | 342 | printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); |
354 | 343 | ||
355 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
356 | if (socdev->card->codec == NULL) | ||
357 | return -ENOMEM; | ||
358 | codec = socdev->card->codec; | ||
359 | mutex_init(&codec->mutex); | ||
360 | |||
361 | codec->reg_cache = kmemdup(stac9766_reg, sizeof(stac9766_reg), | ||
362 | GFP_KERNEL); | ||
363 | if (codec->reg_cache == NULL) { | ||
364 | ret = -ENOMEM; | ||
365 | goto cache_err; | ||
366 | } | ||
367 | codec->reg_cache_size = sizeof(stac9766_reg); | ||
368 | codec->reg_cache_step = 2; | ||
369 | |||
370 | codec->name = "STAC9766"; | ||
371 | codec->owner = THIS_MODULE; | ||
372 | codec->dai = stac9766_dai; | ||
373 | codec->num_dai = ARRAY_SIZE(stac9766_dai); | ||
374 | codec->write = stac9766_ac97_write; | ||
375 | codec->read = stac9766_ac97_read; | ||
376 | codec->set_bias_level = stac9766_set_bias_level; | ||
377 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
378 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
379 | |||
380 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 344 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
381 | if (ret < 0) | 345 | if (ret < 0) |
382 | goto codec_err; | 346 | goto codec_err; |
383 | 347 | ||
384 | /* register pcms */ | ||
385 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
386 | if (ret < 0) | ||
387 | goto pcm_err; | ||
388 | |||
389 | /* do a cold reset for the controller and then try | 348 | /* do a cold reset for the controller and then try |
390 | * a warm reset followed by an optional cold reset for codec */ | 349 | * a warm reset followed by an optional cold reset for codec */ |
391 | stac9766_reset(codec, 0); | 350 | stac9766_reset(codec, 0); |
392 | ret = stac9766_reset(codec, 1); | 351 | ret = stac9766_reset(codec, 1); |
393 | if (ret < 0) { | 352 | if (ret < 0) { |
394 | printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n"); | 353 | printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n"); |
395 | goto reset_err; | 354 | goto codec_err; |
396 | } | 355 | } |
397 | 356 | ||
398 | stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 357 | stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -402,40 +361,63 @@ static int stac9766_codec_probe(struct platform_device *pdev) | |||
402 | 361 | ||
403 | return 0; | 362 | return 0; |
404 | 363 | ||
405 | reset_err: | ||
406 | snd_soc_free_pcms(socdev); | ||
407 | pcm_err: | ||
408 | snd_soc_free_ac97_codec(codec); | ||
409 | codec_err: | 364 | codec_err: |
410 | kfree(snd_soc_codec_get_drvdata(codec)); | 365 | snd_soc_free_ac97_codec(codec); |
411 | cache_err: | ||
412 | kfree(socdev->card->codec); | ||
413 | socdev->card->codec = NULL; | ||
414 | return ret; | 366 | return ret; |
415 | } | 367 | } |
416 | 368 | ||
417 | static int stac9766_codec_remove(struct platform_device *pdev) | 369 | static int stac9766_codec_remove(struct snd_soc_codec *codec) |
418 | { | 370 | { |
419 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
420 | struct snd_soc_codec *codec = socdev->card->codec; | ||
421 | |||
422 | if (codec == NULL) | ||
423 | return 0; | ||
424 | |||
425 | snd_soc_free_pcms(socdev); | ||
426 | snd_soc_free_ac97_codec(codec); | 371 | snd_soc_free_ac97_codec(codec); |
427 | kfree(codec->reg_cache); | ||
428 | kfree(codec); | ||
429 | return 0; | 372 | return 0; |
430 | } | 373 | } |
431 | 374 | ||
432 | struct snd_soc_codec_device soc_codec_dev_stac9766 = { | 375 | static struct snd_soc_codec_driver soc_codec_dev_stac9766 = { |
376 | .write = stac9766_ac97_write, | ||
377 | .read = stac9766_ac97_read, | ||
378 | .set_bias_level = stac9766_set_bias_level, | ||
433 | .probe = stac9766_codec_probe, | 379 | .probe = stac9766_codec_probe, |
434 | .remove = stac9766_codec_remove, | 380 | .remove = stac9766_codec_remove, |
435 | .suspend = stac9766_codec_suspend, | 381 | .suspend = stac9766_codec_suspend, |
436 | .resume = stac9766_codec_resume, | 382 | .resume = stac9766_codec_resume, |
383 | .reg_cache_size = sizeof(stac9766_reg), | ||
384 | .reg_word_size = sizeof(u16), | ||
385 | .reg_cache_step = 2, | ||
386 | }; | ||
387 | |||
388 | static __devinit int stac9766_probe(struct platform_device *pdev) | ||
389 | { | ||
390 | return snd_soc_register_codec(&pdev->dev, | ||
391 | &soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai)); | ||
392 | } | ||
393 | |||
394 | static int __devexit stac9766_remove(struct platform_device *pdev) | ||
395 | { | ||
396 | snd_soc_unregister_codec(&pdev->dev); | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static struct platform_driver stac9766_codec_driver = { | ||
401 | .driver = { | ||
402 | .name = "stac9766-codec", | ||
403 | .owner = THIS_MODULE, | ||
404 | }, | ||
405 | |||
406 | .probe = stac9766_probe, | ||
407 | .remove = __devexit_p(stac9766_remove), | ||
437 | }; | 408 | }; |
438 | EXPORT_SYMBOL_GPL(soc_codec_dev_stac9766); | 409 | |
410 | static int __init stac9766_init(void) | ||
411 | { | ||
412 | return platform_driver_register(&stac9766_codec_driver); | ||
413 | } | ||
414 | module_init(stac9766_init); | ||
415 | |||
416 | static void __exit stac9766_exit(void) | ||
417 | { | ||
418 | platform_driver_unregister(&stac9766_codec_driver); | ||
419 | } | ||
420 | module_exit(stac9766_exit); | ||
439 | 421 | ||
440 | MODULE_DESCRIPTION("ASoC stac9766 driver"); | 422 | MODULE_DESCRIPTION("ASoC stac9766 driver"); |
441 | MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>"); | 423 | MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>"); |
diff --git a/sound/soc/codecs/stac9766.h b/sound/soc/codecs/stac9766.h index 65642eb8393e..c726f907e2c0 100644 --- a/sound/soc/codecs/stac9766.h +++ b/sound/soc/codecs/stac9766.h | |||
@@ -14,8 +14,4 @@ | |||
14 | #define STAC9766_DAI_AC97_ANALOG 0 | 14 | #define STAC9766_DAI_AC97_ANALOG 0 |
15 | #define STAC9766_DAI_AC97_DIGITAL 1 | 15 | #define STAC9766_DAI_AC97_DIGITAL 1 |
16 | 16 | ||
17 | extern struct snd_soc_dai stac9766_dai[]; | ||
18 | extern struct snd_soc_codec_device soc_codec_dev_stac9766; | ||
19 | |||
20 | |||
21 | #endif | 17 | #endif |
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 0a4b0fef3355..e8652b1ae326 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -240,7 +240,8 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
240 | 240 | ||
241 | /* AIC23 driver data */ | 241 | /* AIC23 driver data */ |
242 | struct aic23 { | 242 | struct aic23 { |
243 | struct snd_soc_codec codec; | 243 | enum snd_soc_control_type control_type; |
244 | void *control_data; | ||
244 | int mclk; | 245 | int mclk; |
245 | int requested_adc; | 246 | int requested_adc; |
246 | int requested_dac; | 247 | int requested_dac; |
@@ -404,11 +405,10 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, | |||
404 | struct snd_soc_dai *dai) | 405 | struct snd_soc_dai *dai) |
405 | { | 406 | { |
406 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 407 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
407 | struct snd_soc_device *socdev = rtd->socdev; | 408 | struct snd_soc_codec *codec = rtd->codec; |
408 | struct snd_soc_codec *codec = socdev->card->codec; | ||
409 | u16 iface_reg; | 409 | u16 iface_reg; |
410 | int ret; | 410 | int ret; |
411 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | 411 | struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); |
412 | u32 sample_rate_adc = aic23->requested_adc; | 412 | u32 sample_rate_adc = aic23->requested_adc; |
413 | u32 sample_rate_dac = aic23->requested_dac; | 413 | u32 sample_rate_dac = aic23->requested_dac; |
414 | u32 sample_rate = params_rate(params); | 414 | u32 sample_rate = params_rate(params); |
@@ -452,8 +452,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream, | |||
452 | struct snd_soc_dai *dai) | 452 | struct snd_soc_dai *dai) |
453 | { | 453 | { |
454 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 454 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
455 | struct snd_soc_device *socdev = rtd->socdev; | 455 | struct snd_soc_codec *codec = rtd->codec; |
456 | struct snd_soc_codec *codec = socdev->card->codec; | ||
457 | 456 | ||
458 | /* set active */ | 457 | /* set active */ |
459 | tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); | 458 | tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); |
@@ -465,9 +464,8 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, | |||
465 | struct snd_soc_dai *dai) | 464 | struct snd_soc_dai *dai) |
466 | { | 465 | { |
467 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 466 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
468 | struct snd_soc_device *socdev = rtd->socdev; | 467 | struct snd_soc_codec *codec = rtd->codec; |
469 | struct snd_soc_codec *codec = socdev->card->codec; | 468 | struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); |
470 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | ||
471 | 469 | ||
472 | /* deactivate */ | 470 | /* deactivate */ |
473 | if (!codec->active) { | 471 | if (!codec->active) { |
@@ -546,8 +544,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
546 | static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 544 | static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
547 | int clk_id, unsigned int freq, int dir) | 545 | int clk_id, unsigned int freq, int dir) |
548 | { | 546 | { |
549 | struct snd_soc_codec *codec = codec_dai->codec; | 547 | struct aic23 *aic23 = snd_soc_dai_get_drvdata(codec_dai); |
550 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | ||
551 | aic23->mclk = freq; | 548 | aic23->mclk = freq; |
552 | return 0; | 549 | return 0; |
553 | } | 550 | } |
@@ -594,8 +591,8 @@ static struct snd_soc_dai_ops tlv320aic23_dai_ops = { | |||
594 | .set_sysclk = tlv320aic23_set_dai_sysclk, | 591 | .set_sysclk = tlv320aic23_set_dai_sysclk, |
595 | }; | 592 | }; |
596 | 593 | ||
597 | struct snd_soc_dai tlv320aic23_dai = { | 594 | static struct snd_soc_dai_driver tlv320aic23_dai = { |
598 | .name = "tlv320aic23", | 595 | .name = "tlv320aic23-hifi", |
599 | .playback = { | 596 | .playback = { |
600 | .stream_name = "Playback", | 597 | .stream_name = "Playback", |
601 | .channels_min = 2, | 598 | .channels_min = 2, |
@@ -610,23 +607,17 @@ struct snd_soc_dai tlv320aic23_dai = { | |||
610 | .formats = AIC23_FORMATS,}, | 607 | .formats = AIC23_FORMATS,}, |
611 | .ops = &tlv320aic23_dai_ops, | 608 | .ops = &tlv320aic23_dai_ops, |
612 | }; | 609 | }; |
613 | EXPORT_SYMBOL_GPL(tlv320aic23_dai); | ||
614 | 610 | ||
615 | static int tlv320aic23_suspend(struct platform_device *pdev, | 611 | static int tlv320aic23_suspend(struct snd_soc_codec *codec, |
616 | pm_message_t state) | 612 | pm_message_t state) |
617 | { | 613 | { |
618 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
619 | struct snd_soc_codec *codec = socdev->card->codec; | ||
620 | |||
621 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); | 614 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); |
622 | 615 | ||
623 | return 0; | 616 | return 0; |
624 | } | 617 | } |
625 | 618 | ||
626 | static int tlv320aic23_resume(struct platform_device *pdev) | 619 | static int tlv320aic23_resume(struct snd_soc_codec *codec) |
627 | { | 620 | { |
628 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
629 | struct snd_soc_codec *codec = socdev->card->codec; | ||
630 | u16 reg; | 621 | u16 reg; |
631 | 622 | ||
632 | /* Sync reg_cache with the hardware */ | 623 | /* Sync reg_cache with the hardware */ |
@@ -639,39 +630,19 @@ static int tlv320aic23_resume(struct platform_device *pdev) | |||
639 | return 0; | 630 | return 0; |
640 | } | 631 | } |
641 | 632 | ||
642 | /* | 633 | static int tlv320aic23_probe(struct snd_soc_codec *codec) |
643 | * initialise the AIC23 driver | ||
644 | * register the mixer and dsp interfaces with the kernel | ||
645 | */ | ||
646 | static int tlv320aic23_init(struct snd_soc_device *socdev) | ||
647 | { | 634 | { |
648 | struct snd_soc_codec *codec = socdev->card->codec; | 635 | struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); |
649 | int ret = 0; | 636 | int reg; |
650 | u16 reg; | ||
651 | 637 | ||
652 | codec->name = "tlv320aic23"; | 638 | printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); |
653 | codec->owner = THIS_MODULE; | 639 | codec->control_data = aic23->control_data; |
654 | codec->read = tlv320aic23_read_reg_cache; | 640 | codec->hw_write = (hw_write_t)i2c_master_send; |
655 | codec->write = tlv320aic23_write; | 641 | codec->hw_read = NULL; |
656 | codec->set_bias_level = tlv320aic23_set_bias_level; | ||
657 | codec->dai = &tlv320aic23_dai; | ||
658 | codec->num_dai = 1; | ||
659 | codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg); | ||
660 | codec->reg_cache = | ||
661 | kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL); | ||
662 | if (codec->reg_cache == NULL) | ||
663 | return -ENOMEM; | ||
664 | 642 | ||
665 | /* Reset codec */ | 643 | /* Reset codec */ |
666 | tlv320aic23_write(codec, TLV320AIC23_RESET, 0); | 644 | tlv320aic23_write(codec, TLV320AIC23_RESET, 0); |
667 | 645 | ||
668 | /* register pcms */ | ||
669 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
670 | if (ret < 0) { | ||
671 | printk(KERN_ERR "tlv320aic23: failed to create pcms\n"); | ||
672 | goto pcm_err; | ||
673 | } | ||
674 | |||
675 | /* power on device */ | 646 | /* power on device */ |
676 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 647 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
677 | 648 | ||
@@ -707,13 +678,27 @@ static int tlv320aic23_init(struct snd_soc_device *socdev) | |||
707 | ARRAY_SIZE(tlv320aic23_snd_controls)); | 678 | ARRAY_SIZE(tlv320aic23_snd_controls)); |
708 | tlv320aic23_add_widgets(codec); | 679 | tlv320aic23_add_widgets(codec); |
709 | 680 | ||
710 | return ret; | 681 | return 0; |
682 | } | ||
711 | 683 | ||
712 | pcm_err: | 684 | static int tlv320aic23_remove(struct snd_soc_codec *codec) |
713 | kfree(codec->reg_cache); | 685 | { |
714 | return ret; | 686 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); |
687 | return 0; | ||
715 | } | 688 | } |
716 | static struct snd_soc_device *tlv320aic23_socdev; | 689 | |
690 | static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { | ||
691 | .reg_cache_size = ARRAY_SIZE(tlv320aic23_reg), | ||
692 | .reg_word_size = sizeof(u16), | ||
693 | .reg_cache_default = tlv320aic23_reg, | ||
694 | .probe = tlv320aic23_probe, | ||
695 | .remove = tlv320aic23_remove, | ||
696 | .suspend = tlv320aic23_suspend, | ||
697 | .resume = tlv320aic23_resume, | ||
698 | .read = tlv320aic23_read_reg_cache, | ||
699 | .write = tlv320aic23_write, | ||
700 | .set_bias_level = tlv320aic23_set_bias_level, | ||
701 | }; | ||
717 | 702 | ||
718 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 703 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
719 | /* | 704 | /* |
@@ -723,31 +708,30 @@ static struct snd_soc_device *tlv320aic23_socdev; | |||
723 | static int tlv320aic23_codec_probe(struct i2c_client *i2c, | 708 | static int tlv320aic23_codec_probe(struct i2c_client *i2c, |
724 | const struct i2c_device_id *i2c_id) | 709 | const struct i2c_device_id *i2c_id) |
725 | { | 710 | { |
726 | struct snd_soc_device *socdev = tlv320aic23_socdev; | 711 | struct aic23 *aic23; |
727 | struct snd_soc_codec *codec = socdev->card->codec; | ||
728 | int ret; | 712 | int ret; |
729 | 713 | ||
730 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 714 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
731 | return -EINVAL; | 715 | return -EINVAL; |
732 | 716 | ||
733 | i2c_set_clientdata(i2c, codec); | 717 | aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL); |
734 | codec->control_data = i2c; | 718 | if (aic23 == NULL) |
719 | return -ENOMEM; | ||
735 | 720 | ||
736 | ret = tlv320aic23_init(socdev); | 721 | i2c_set_clientdata(i2c, aic23); |
737 | if (ret < 0) { | 722 | aic23->control_data = i2c; |
738 | printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n"); | 723 | aic23->control_type = SND_SOC_I2C; |
739 | goto err; | ||
740 | } | ||
741 | return ret; | ||
742 | 724 | ||
743 | err: | 725 | ret = snd_soc_register_codec(&i2c->dev, |
744 | kfree(codec); | 726 | &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); |
745 | kfree(i2c); | 727 | if (ret < 0) |
728 | kfree(aic23); | ||
746 | return ret; | 729 | return ret; |
747 | } | 730 | } |
748 | static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) | 731 | static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) |
749 | { | 732 | { |
750 | put_device(&i2c->dev); | 733 | snd_soc_unregister_codec(&i2c->dev); |
734 | kfree(i2c_get_clientdata(i2c)); | ||
751 | return 0; | 735 | return 0; |
752 | } | 736 | } |
753 | 737 | ||
@@ -760,7 +744,7 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); | |||
760 | 744 | ||
761 | static struct i2c_driver tlv320aic23_i2c_driver = { | 745 | static struct i2c_driver tlv320aic23_i2c_driver = { |
762 | .driver = { | 746 | .driver = { |
763 | .name = "tlv320aic23", | 747 | .name = "tlv320aic23-codec", |
764 | }, | 748 | }, |
765 | .probe = tlv320aic23_codec_probe, | 749 | .probe = tlv320aic23_codec_probe, |
766 | .remove = __exit_p(tlv320aic23_i2c_remove), | 750 | .remove = __exit_p(tlv320aic23_i2c_remove), |
@@ -769,71 +753,25 @@ static struct i2c_driver tlv320aic23_i2c_driver = { | |||
769 | 753 | ||
770 | #endif | 754 | #endif |
771 | 755 | ||
772 | static int tlv320aic23_probe(struct platform_device *pdev) | 756 | static int __init tlv320aic23_modinit(void) |
773 | { | 757 | { |
774 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 758 | int ret; |
775 | struct snd_soc_codec *codec; | ||
776 | struct aic23 *aic23; | ||
777 | int ret = 0; | ||
778 | |||
779 | printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); | ||
780 | |||
781 | aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL); | ||
782 | if (aic23 == NULL) | ||
783 | return -ENOMEM; | ||
784 | codec = &aic23->codec; | ||
785 | socdev->card->codec = codec; | ||
786 | mutex_init(&codec->mutex); | ||
787 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
788 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
789 | |||
790 | tlv320aic23_socdev = socdev; | ||
791 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 759 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
792 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
793 | codec->hw_read = NULL; | ||
794 | ret = i2c_add_driver(&tlv320aic23_i2c_driver); | 760 | ret = i2c_add_driver(&tlv320aic23_i2c_driver); |
795 | if (ret != 0) | 761 | if (ret != 0) { |
796 | printk(KERN_ERR "can't add i2c driver"); | 762 | printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n", |
763 | ret); | ||
764 | } | ||
797 | #endif | 765 | #endif |
798 | return ret; | 766 | return ret; |
799 | } | 767 | } |
768 | module_init(tlv320aic23_modinit); | ||
800 | 769 | ||
801 | static int tlv320aic23_remove(struct platform_device *pdev) | 770 | static void __exit tlv320aic23_exit(void) |
802 | { | 771 | { |
803 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
804 | struct snd_soc_codec *codec = socdev->card->codec; | ||
805 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | ||
806 | |||
807 | if (codec->control_data) | ||
808 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
809 | |||
810 | snd_soc_free_pcms(socdev); | ||
811 | snd_soc_dapm_free(socdev); | ||
812 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 772 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
813 | i2c_del_driver(&tlv320aic23_i2c_driver); | 773 | i2c_del_driver(&tlv320aic23_i2c_driver); |
814 | #endif | 774 | #endif |
815 | kfree(codec->reg_cache); | ||
816 | kfree(aic23); | ||
817 | |||
818 | return 0; | ||
819 | } | ||
820 | struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = { | ||
821 | .probe = tlv320aic23_probe, | ||
822 | .remove = tlv320aic23_remove, | ||
823 | .suspend = tlv320aic23_suspend, | ||
824 | .resume = tlv320aic23_resume, | ||
825 | }; | ||
826 | EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23); | ||
827 | |||
828 | static int __init tlv320aic23_modinit(void) | ||
829 | { | ||
830 | return snd_soc_register_dai(&tlv320aic23_dai); | ||
831 | } | ||
832 | module_init(tlv320aic23_modinit); | ||
833 | |||
834 | static void __exit tlv320aic23_exit(void) | ||
835 | { | ||
836 | snd_soc_unregister_dai(&tlv320aic23_dai); | ||
837 | } | 775 | } |
838 | module_exit(tlv320aic23_exit); | 776 | module_exit(tlv320aic23_exit); |
839 | 777 | ||
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h index 79d1faf8e570..e804120bd3da 100644 --- a/sound/soc/codecs/tlv320aic23.h +++ b/sound/soc/codecs/tlv320aic23.h | |||
@@ -116,7 +116,4 @@ | |||
116 | #define TLV320AIC23_SIDETONE_12 0x080 | 116 | #define TLV320AIC23_SIDETONE_12 0x080 |
117 | #define TLV320AIC23_SIDETONE_18 0x0c0 | 117 | #define TLV320AIC23_SIDETONE_18 0x0c0 |
118 | 118 | ||
119 | extern struct snd_soc_dai tlv320aic23_dai; | ||
120 | extern struct snd_soc_codec_device soc_codec_dev_tlv320aic23; | ||
121 | |||
122 | #endif /* _TLV320AIC23_H */ | 119 | #endif /* _TLV320AIC23_H */ |
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index f0e00fd4b435..6b7d71ec0004 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <sound/pcm_params.h> | 19 | #include <sound/pcm_params.h> |
20 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | #include <sound/soc-dapm.h> | 21 | #include <sound/soc-dapm.h> |
22 | #include <sound/soc-of-simple.h> | ||
23 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
24 | 23 | ||
25 | #include "tlv320aic26.h" | 24 | #include "tlv320aic26.h" |
@@ -130,8 +129,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, | |||
130 | struct snd_soc_dai *dai) | 129 | struct snd_soc_dai *dai) |
131 | { | 130 | { |
132 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 131 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
133 | struct snd_soc_device *socdev = rtd->socdev; | 132 | struct snd_soc_codec *codec = rtd->codec; |
134 | struct snd_soc_codec *codec = socdev->card->codec; | ||
135 | struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); | 133 | struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); |
136 | int fsref, divisor, wlen, pval, jval, dval, qval; | 134 | int fsref, divisor, wlen, pval, jval, dval, qval; |
137 | u16 reg; | 135 | u16 reg; |
@@ -278,8 +276,8 @@ static struct snd_soc_dai_ops aic26_dai_ops = { | |||
278 | .set_fmt = aic26_set_fmt, | 276 | .set_fmt = aic26_set_fmt, |
279 | }; | 277 | }; |
280 | 278 | ||
281 | struct snd_soc_dai aic26_dai = { | 279 | static struct snd_soc_dai_driver aic26_dai = { |
282 | .name = "tlv320aic26", | 280 | .name = "tlv320aic26-hifi", |
283 | .playback = { | 281 | .playback = { |
284 | .stream_name = "Playback", | 282 | .stream_name = "Playback", |
285 | .channels_min = 2, | 283 | .channels_min = 2, |
@@ -296,7 +294,6 @@ struct snd_soc_dai aic26_dai = { | |||
296 | }, | 294 | }, |
297 | .ops = &aic26_dai_ops, | 295 | .ops = &aic26_dai_ops, |
298 | }; | 296 | }; |
299 | EXPORT_SYMBOL_GPL(aic26_dai); | ||
300 | 297 | ||
301 | /* --------------------------------------------------------------------- | 298 | /* --------------------------------------------------------------------- |
302 | * ALSA controls | 299 | * ALSA controls |
@@ -319,61 +316,6 @@ static const struct snd_kcontrol_new aic26_snd_controls[] = { | |||
319 | }; | 316 | }; |
320 | 317 | ||
321 | /* --------------------------------------------------------------------- | 318 | /* --------------------------------------------------------------------- |
322 | * SoC CODEC portion of driver: probe and release routines | ||
323 | */ | ||
324 | static int aic26_probe(struct platform_device *pdev) | ||
325 | { | ||
326 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
327 | struct snd_soc_codec *codec; | ||
328 | struct aic26 *aic26; | ||
329 | int ret, err; | ||
330 | |||
331 | dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n"); | ||
332 | dev_dbg(&pdev->dev, "socdev=%p\n", socdev); | ||
333 | dev_dbg(&pdev->dev, "codec_data=%p\n", socdev->codec_data); | ||
334 | |||
335 | /* Fetch the relevant aic26 private data here (it's already been | ||
336 | * stored in the .codec pointer) */ | ||
337 | aic26 = socdev->codec_data; | ||
338 | if (aic26 == NULL) { | ||
339 | dev_err(&pdev->dev, "aic26: missing codec pointer\n"); | ||
340 | return -ENODEV; | ||
341 | } | ||
342 | codec = &aic26->codec; | ||
343 | socdev->card->codec = codec; | ||
344 | |||
345 | dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n", | ||
346 | &pdev->dev, socdev->dev); | ||
347 | /* register pcms */ | ||
348 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
349 | if (ret < 0) { | ||
350 | dev_err(&pdev->dev, "aic26: failed to create pcms\n"); | ||
351 | return -ENODEV; | ||
352 | } | ||
353 | |||
354 | /* register controls */ | ||
355 | dev_dbg(&pdev->dev, "Registering controls\n"); | ||
356 | err = snd_soc_add_controls(codec, aic26_snd_controls, | ||
357 | ARRAY_SIZE(aic26_snd_controls)); | ||
358 | WARN_ON(err < 0); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int aic26_remove(struct platform_device *pdev) | ||
364 | { | ||
365 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
366 | snd_soc_free_pcms(socdev); | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | struct snd_soc_codec_device aic26_soc_codec_dev = { | ||
371 | .probe = aic26_probe, | ||
372 | .remove = aic26_remove, | ||
373 | }; | ||
374 | EXPORT_SYMBOL_GPL(aic26_soc_codec_dev); | ||
375 | |||
376 | /* --------------------------------------------------------------------- | ||
377 | * SPI device portion of driver: sysfs files for debugging | 319 | * SPI device portion of driver: sysfs files for debugging |
378 | */ | 320 | */ |
379 | 321 | ||
@@ -409,95 +351,95 @@ static ssize_t aic26_keyclick_set(struct device *dev, | |||
409 | static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); | 351 | static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); |
410 | 352 | ||
411 | /* --------------------------------------------------------------------- | 353 | /* --------------------------------------------------------------------- |
412 | * SPI device portion of driver: probe and release routines and SPI | 354 | * SoC CODEC portion of driver: probe and release routines |
413 | * driver registration. | ||
414 | */ | 355 | */ |
415 | static int aic26_spi_probe(struct spi_device *spi) | 356 | static int aic26_probe(struct snd_soc_codec *codec) |
416 | { | 357 | { |
417 | struct aic26 *aic26; | 358 | struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); |
418 | int ret, i, reg; | 359 | int ret, err, i, reg; |
419 | |||
420 | dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); | ||
421 | |||
422 | /* Allocate driver data */ | ||
423 | aic26 = kzalloc(sizeof *aic26, GFP_KERNEL); | ||
424 | if (!aic26) | ||
425 | return -ENOMEM; | ||
426 | |||
427 | /* Initialize the driver data */ | ||
428 | aic26->spi = spi; | ||
429 | dev_set_drvdata(&spi->dev, aic26); | ||
430 | 360 | ||
431 | /* Setup what we can in the codec structure so that the register | 361 | dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n"); |
432 | * access functions will work as expected. More will be filled | ||
433 | * out when it is probed by the SoC CODEC part of this driver */ | ||
434 | snd_soc_codec_set_drvdata(&aic26->codec, aic26); | ||
435 | aic26->codec.name = "aic26"; | ||
436 | aic26->codec.owner = THIS_MODULE; | ||
437 | aic26->codec.dai = &aic26_dai; | ||
438 | aic26->codec.num_dai = 1; | ||
439 | aic26->codec.read = aic26_reg_read; | ||
440 | aic26->codec.write = aic26_reg_write; | ||
441 | aic26->master = 1; | ||
442 | mutex_init(&aic26->codec.mutex); | ||
443 | INIT_LIST_HEAD(&aic26->codec.dapm_widgets); | ||
444 | INIT_LIST_HEAD(&aic26->codec.dapm_paths); | ||
445 | aic26->codec.reg_cache_size = AIC26_NUM_REGS; | ||
446 | aic26->codec.reg_cache = aic26->reg_cache; | ||
447 | |||
448 | aic26_dai.dev = &spi->dev; | ||
449 | ret = snd_soc_register_dai(&aic26_dai); | ||
450 | if (ret != 0) { | ||
451 | dev_err(&spi->dev, "Failed to register DAI: %d\n", ret); | ||
452 | kfree(aic26); | ||
453 | return ret; | ||
454 | } | ||
455 | 362 | ||
456 | /* Reset the codec to power on defaults */ | 363 | /* Reset the codec to power on defaults */ |
457 | aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00); | 364 | aic26_reg_write(codec, AIC26_REG_RESET, 0xBB00); |
458 | 365 | ||
459 | /* Power up CODEC */ | 366 | /* Power up CODEC */ |
460 | aic26_reg_write(&aic26->codec, AIC26_REG_POWER_CTRL, 0); | 367 | aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0); |
461 | 368 | ||
462 | /* Audio Control 3 (master mode, fsref rate) */ | 369 | /* Audio Control 3 (master mode, fsref rate) */ |
463 | reg = aic26_reg_read(&aic26->codec, AIC26_REG_AUDIO_CTRL3); | 370 | reg = aic26_reg_read(codec, AIC26_REG_AUDIO_CTRL3); |
464 | reg &= ~0xf800; | 371 | reg &= ~0xf800; |
465 | reg |= 0x0800; /* set master mode */ | 372 | reg |= 0x0800; /* set master mode */ |
466 | aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL3, reg); | 373 | aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg); |
467 | 374 | ||
468 | /* Fill register cache */ | 375 | /* Fill register cache */ |
469 | for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++) | 376 | for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++) |
470 | aic26_reg_read(&aic26->codec, i); | 377 | aic26_reg_read(codec, i); |
471 | 378 | ||
472 | /* Register the sysfs files for debugging */ | 379 | /* Register the sysfs files for debugging */ |
473 | /* Create SysFS files */ | 380 | /* Create SysFS files */ |
474 | ret = device_create_file(&spi->dev, &dev_attr_keyclick); | 381 | ret = device_create_file(codec->dev, &dev_attr_keyclick); |
475 | if (ret) | 382 | if (ret) |
476 | dev_info(&spi->dev, "error creating sysfs files\n"); | 383 | dev_info(codec->dev, "error creating sysfs files\n"); |
477 | 384 | ||
478 | #if defined(CONFIG_SND_SOC_OF_SIMPLE) | 385 | /* register controls */ |
479 | /* Tell the of_soc helper about this codec */ | 386 | dev_dbg(codec->dev, "Registering controls\n"); |
480 | of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai, | 387 | err = snd_soc_add_controls(codec, aic26_snd_controls, |
481 | spi->dev.archdata.of_node); | 388 | ARRAY_SIZE(aic26_snd_controls)); |
482 | #endif | 389 | WARN_ON(err < 0); |
483 | 390 | ||
484 | dev_dbg(&spi->dev, "SPI device initialized\n"); | ||
485 | return 0; | 391 | return 0; |
486 | } | 392 | } |
487 | 393 | ||
488 | static int aic26_spi_remove(struct spi_device *spi) | 394 | static struct snd_soc_codec_driver aic26_soc_codec_dev = { |
395 | .probe = aic26_probe, | ||
396 | .read = aic26_reg_read, | ||
397 | .write = aic26_reg_write, | ||
398 | .reg_cache_size = AIC26_NUM_REGS, | ||
399 | .reg_word_size = sizeof(u16), | ||
400 | }; | ||
401 | |||
402 | /* --------------------------------------------------------------------- | ||
403 | * SPI device portion of driver: probe and release routines and SPI | ||
404 | * driver registration. | ||
405 | */ | ||
406 | static int aic26_spi_probe(struct spi_device *spi) | ||
489 | { | 407 | { |
490 | struct aic26 *aic26 = dev_get_drvdata(&spi->dev); | 408 | struct aic26 *aic26; |
409 | int ret; | ||
491 | 410 | ||
492 | snd_soc_unregister_dai(&aic26_dai); | 411 | dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); |
493 | kfree(aic26); | 412 | |
413 | /* Allocate driver data */ | ||
414 | aic26 = kzalloc(sizeof *aic26, GFP_KERNEL); | ||
415 | if (!aic26) | ||
416 | return -ENOMEM; | ||
494 | 417 | ||
418 | /* Initialize the driver data */ | ||
419 | aic26->spi = spi; | ||
420 | dev_set_drvdata(&spi->dev, aic26); | ||
421 | aic26->master = 1; | ||
422 | |||
423 | ret = snd_soc_register_codec(&spi->dev, | ||
424 | &aic26_soc_codec_dev, &aic26_dai, 1); | ||
425 | if (ret < 0) | ||
426 | kfree(aic26); | ||
427 | return ret; | ||
428 | |||
429 | dev_dbg(&spi->dev, "SPI device initialized\n"); | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static int aic26_spi_remove(struct spi_device *spi) | ||
434 | { | ||
435 | snd_soc_unregister_codec(&spi->dev); | ||
436 | kfree(spi_get_drvdata(spi)); | ||
495 | return 0; | 437 | return 0; |
496 | } | 438 | } |
497 | 439 | ||
498 | static struct spi_driver aic26_spi = { | 440 | static struct spi_driver aic26_spi = { |
499 | .driver = { | 441 | .driver = { |
500 | .name = "tlv320aic26", | 442 | .name = "tlv320aic26-codec", |
501 | .owner = THIS_MODULE, | 443 | .owner = THIS_MODULE, |
502 | }, | 444 | }, |
503 | .probe = aic26_spi_probe, | 445 | .probe = aic26_spi_probe, |
diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h index 786ba16c945f..62b1f2261429 100644 --- a/sound/soc/codecs/tlv320aic26.h +++ b/sound/soc/codecs/tlv320aic26.h | |||
@@ -90,7 +90,4 @@ enum aic26_wlen { | |||
90 | AIC26_WLEN_32 = 3 << 10, | 90 | AIC26_WLEN_32 = 3 << 10, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | extern struct snd_soc_dai aic26_dai; | ||
94 | extern struct snd_soc_codec_device aic26_soc_codec_dev; | ||
95 | |||
96 | #endif /* _TLV320AIC16_H_ */ | 93 | #endif /* _TLV320AIC16_H_ */ |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 71a69908ccf6..43fd9c171742 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -63,8 +63,10 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = { | |||
63 | 63 | ||
64 | /* codec private data */ | 64 | /* codec private data */ |
65 | struct aic3x_priv { | 65 | struct aic3x_priv { |
66 | struct snd_soc_codec codec; | ||
67 | struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; | 66 | struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; |
67 | enum snd_soc_control_type control_type; | ||
68 | struct aic3x_setup_data *setup; | ||
69 | void *control_data; | ||
68 | unsigned int sysclk; | 70 | unsigned int sysclk; |
69 | int master; | 71 | int master; |
70 | int gpio_reset; | 72 | int gpio_reset; |
@@ -773,8 +775,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, | |||
773 | struct snd_soc_dai *dai) | 775 | struct snd_soc_dai *dai) |
774 | { | 776 | { |
775 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 777 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
776 | struct snd_soc_device *socdev = rtd->socdev; | 778 | struct snd_soc_codec *codec =rtd->codec; |
777 | struct snd_soc_codec *codec = socdev->card->codec; | ||
778 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); | 779 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
779 | int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; | 780 | int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; |
780 | u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; | 781 | u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; |
@@ -1101,8 +1102,8 @@ static struct snd_soc_dai_ops aic3x_dai_ops = { | |||
1101 | .set_fmt = aic3x_set_dai_fmt, | 1102 | .set_fmt = aic3x_set_dai_fmt, |
1102 | }; | 1103 | }; |
1103 | 1104 | ||
1104 | struct snd_soc_dai aic3x_dai = { | 1105 | static struct snd_soc_dai_driver aic3x_dai = { |
1105 | .name = "tlv320aic3x", | 1106 | .name = "tlv320aic3x-hifi", |
1106 | .playback = { | 1107 | .playback = { |
1107 | .stream_name = "Playback", | 1108 | .stream_name = "Playback", |
1108 | .channels_min = 1, | 1109 | .channels_min = 1, |
@@ -1117,22 +1118,16 @@ struct snd_soc_dai aic3x_dai = { | |||
1117 | .formats = AIC3X_FORMATS,}, | 1118 | .formats = AIC3X_FORMATS,}, |
1118 | .ops = &aic3x_dai_ops, | 1119 | .ops = &aic3x_dai_ops, |
1119 | }; | 1120 | }; |
1120 | EXPORT_SYMBOL_GPL(aic3x_dai); | ||
1121 | 1121 | ||
1122 | static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) | 1122 | static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1123 | { | 1123 | { |
1124 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1125 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1126 | |||
1127 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1124 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1128 | 1125 | ||
1129 | return 0; | 1126 | return 0; |
1130 | } | 1127 | } |
1131 | 1128 | ||
1132 | static int aic3x_resume(struct platform_device *pdev) | 1129 | static int aic3x_resume(struct snd_soc_codec *codec) |
1133 | { | 1130 | { |
1134 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1135 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1136 | int i; | 1131 | int i; |
1137 | u8 data[2]; | 1132 | u8 data[2]; |
1138 | u8 *cache = codec->reg_cache; | 1133 | u8 *cache = codec->reg_cache; |
@@ -1157,22 +1152,6 @@ static int aic3x_init(struct snd_soc_codec *codec) | |||
1157 | { | 1152 | { |
1158 | int reg; | 1153 | int reg; |
1159 | 1154 | ||
1160 | mutex_init(&codec->mutex); | ||
1161 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1162 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1163 | |||
1164 | codec->name = "tlv320aic3x"; | ||
1165 | codec->owner = THIS_MODULE; | ||
1166 | codec->read = aic3x_read_reg_cache; | ||
1167 | codec->write = aic3x_write; | ||
1168 | codec->set_bias_level = aic3x_set_bias_level; | ||
1169 | codec->dai = &aic3x_dai; | ||
1170 | codec->num_dai = 1; | ||
1171 | codec->reg_cache_size = ARRAY_SIZE(aic3x_reg); | ||
1172 | codec->reg_cache = kmemdup(aic3x_reg, sizeof(aic3x_reg), GFP_KERNEL); | ||
1173 | if (codec->reg_cache == NULL) | ||
1174 | return -ENOMEM; | ||
1175 | |||
1176 | aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); | 1155 | aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); |
1177 | aic3x_write(codec, AIC3X_RESET, SOFT_RESET); | 1156 | aic3x_write(codec, AIC3X_RESET, SOFT_RESET); |
1178 | 1157 | ||
@@ -1245,56 +1224,50 @@ static int aic3x_init(struct snd_soc_codec *codec) | |||
1245 | return 0; | 1224 | return 0; |
1246 | } | 1225 | } |
1247 | 1226 | ||
1248 | static struct snd_soc_codec *aic3x_codec; | 1227 | static int aic3x_probe(struct snd_soc_codec *codec) |
1249 | |||
1250 | static int aic3x_register(struct snd_soc_codec *codec) | ||
1251 | { | 1228 | { |
1252 | int ret; | 1229 | struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); |
1230 | |||
1231 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1232 | codec->control_data = aic3x->control_data; | ||
1253 | 1233 | ||
1254 | ret = aic3x_init(codec); | 1234 | if (aic3x->setup) { |
1255 | if (ret < 0) { | 1235 | /* setup GPIO functions */ |
1256 | dev_err(codec->dev, "Failed to initialise device\n"); | 1236 | aic3x_write(codec, AIC3X_GPIO1_REG, |
1257 | return ret; | 1237 | (aic3x->setup->gpio_func[0] & 0xf) << 4); |
1238 | aic3x_write(codec, AIC3X_GPIO2_REG, | ||
1239 | (aic3x->setup->gpio_func[1] & 0xf) << 4); | ||
1258 | } | 1240 | } |
1259 | 1241 | ||
1260 | aic3x_codec = codec; | 1242 | aic3x_init(codec); |
1261 | 1243 | ||
1262 | ret = snd_soc_register_codec(codec); | 1244 | snd_soc_add_controls(codec, aic3x_snd_controls, |
1263 | if (ret) { | 1245 | ARRAY_SIZE(aic3x_snd_controls)); |
1264 | dev_err(codec->dev, "Failed to register codec\n"); | ||
1265 | return ret; | ||
1266 | } | ||
1267 | 1246 | ||
1268 | ret = snd_soc_register_dai(&aic3x_dai); | 1247 | aic3x_add_widgets(codec); |
1269 | if (ret) { | ||
1270 | dev_err(codec->dev, "Failed to register dai\n"); | ||
1271 | snd_soc_unregister_codec(codec); | ||
1272 | return ret; | ||
1273 | } | ||
1274 | 1248 | ||
1275 | return 0; | 1249 | return 0; |
1276 | } | 1250 | } |
1277 | 1251 | ||
1278 | static int aic3x_unregister(struct aic3x_priv *aic3x) | 1252 | static int aic3x_remove(struct snd_soc_codec *codec) |
1279 | { | 1253 | { |
1280 | aic3x_set_bias_level(&aic3x->codec, SND_SOC_BIAS_OFF); | 1254 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1281 | |||
1282 | snd_soc_unregister_dai(&aic3x_dai); | ||
1283 | snd_soc_unregister_codec(&aic3x->codec); | ||
1284 | |||
1285 | if (aic3x->gpio_reset >= 0) { | ||
1286 | gpio_set_value(aic3x->gpio_reset, 0); | ||
1287 | gpio_free(aic3x->gpio_reset); | ||
1288 | } | ||
1289 | regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | ||
1290 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | ||
1291 | |||
1292 | kfree(aic3x); | ||
1293 | aic3x_codec = NULL; | ||
1294 | |||
1295 | return 0; | 1255 | return 0; |
1296 | } | 1256 | } |
1297 | 1257 | ||
1258 | static struct snd_soc_codec_driver soc_codec_dev_aic3x = { | ||
1259 | .read = aic3x_read_reg_cache, | ||
1260 | .write = aic3x_write, | ||
1261 | .set_bias_level = aic3x_set_bias_level, | ||
1262 | .reg_cache_size = ARRAY_SIZE(aic3x_reg), | ||
1263 | .reg_word_size = sizeof(u8), | ||
1264 | .reg_cache_default = aic3x_reg, | ||
1265 | .probe = aic3x_probe, | ||
1266 | .remove = aic3x_remove, | ||
1267 | .suspend = aic3x_suspend, | ||
1268 | .resume = aic3x_resume, | ||
1269 | }; | ||
1270 | |||
1298 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1271 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1299 | /* | 1272 | /* |
1300 | * AIC3X 2 wire address can be up to 4 devices with device addresses | 1273 | * AIC3X 2 wire address can be up to 4 devices with device addresses |
@@ -1308,9 +1281,9 @@ static int aic3x_unregister(struct aic3x_priv *aic3x) | |||
1308 | static int aic3x_i2c_probe(struct i2c_client *i2c, | 1281 | static int aic3x_i2c_probe(struct i2c_client *i2c, |
1309 | const struct i2c_device_id *id) | 1282 | const struct i2c_device_id *id) |
1310 | { | 1283 | { |
1311 | struct snd_soc_codec *codec; | ||
1312 | struct aic3x_priv *aic3x; | ||
1313 | struct aic3x_pdata *pdata = i2c->dev.platform_data; | 1284 | struct aic3x_pdata *pdata = i2c->dev.platform_data; |
1285 | struct aic3x_setup_data *setup = pdata->setup; | ||
1286 | struct aic3x_priv *aic3x; | ||
1314 | int ret, i; | 1287 | int ret, i; |
1315 | 1288 | ||
1316 | aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); | 1289 | aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); |
@@ -1319,12 +1292,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1319 | return -ENOMEM; | 1292 | return -ENOMEM; |
1320 | } | 1293 | } |
1321 | 1294 | ||
1322 | codec = &aic3x->codec; | 1295 | aic3x->control_data = i2c; |
1323 | codec->dev = &i2c->dev; | 1296 | aic3x->setup = setup; |
1324 | snd_soc_codec_set_drvdata(codec, aic3x); | ||
1325 | codec->control_data = i2c; | ||
1326 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1327 | |||
1328 | i2c_set_clientdata(i2c, aic3x); | 1297 | i2c_set_clientdata(i2c, aic3x); |
1329 | 1298 | ||
1330 | aic3x->gpio_reset = -1; | 1299 | aic3x->gpio_reset = -1; |
@@ -1339,17 +1308,17 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1339 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) | 1308 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) |
1340 | aic3x->supplies[i].supply = aic3x_supply_names[i]; | 1309 | aic3x->supplies[i].supply = aic3x_supply_names[i]; |
1341 | 1310 | ||
1342 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies), | 1311 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(aic3x->supplies), |
1343 | aic3x->supplies); | 1312 | aic3x->supplies); |
1344 | if (ret != 0) { | 1313 | if (ret != 0) { |
1345 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 1314 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); |
1346 | goto err_get; | 1315 | goto err_get; |
1347 | } | 1316 | } |
1348 | 1317 | ||
1349 | ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies), | 1318 | ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies), |
1350 | aic3x->supplies); | 1319 | aic3x->supplies); |
1351 | if (ret != 0) { | 1320 | if (ret != 0) { |
1352 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | 1321 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); |
1353 | goto err_enable; | 1322 | goto err_enable; |
1354 | } | 1323 | } |
1355 | 1324 | ||
@@ -1358,7 +1327,11 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1358 | gpio_set_value(aic3x->gpio_reset, 1); | 1327 | gpio_set_value(aic3x->gpio_reset, 1); |
1359 | } | 1328 | } |
1360 | 1329 | ||
1361 | return aic3x_register(codec); | 1330 | ret = snd_soc_register_codec(&i2c->dev, |
1331 | &soc_codec_dev_aic3x, &aic3x_dai, 1); | ||
1332 | if (ret < 0) | ||
1333 | goto err_enable; | ||
1334 | return ret; | ||
1362 | 1335 | ||
1363 | err_enable: | 1336 | err_enable: |
1364 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | 1337 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); |
@@ -1374,7 +1347,16 @@ static int aic3x_i2c_remove(struct i2c_client *client) | |||
1374 | { | 1347 | { |
1375 | struct aic3x_priv *aic3x = i2c_get_clientdata(client); | 1348 | struct aic3x_priv *aic3x = i2c_get_clientdata(client); |
1376 | 1349 | ||
1377 | return aic3x_unregister(aic3x); | 1350 | if (aic3x->gpio_reset >= 0) { |
1351 | gpio_set_value(aic3x->gpio_reset, 0); | ||
1352 | gpio_free(aic3x->gpio_reset); | ||
1353 | } | ||
1354 | regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | ||
1355 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | ||
1356 | |||
1357 | snd_soc_unregister_codec(&client->dev); | ||
1358 | kfree(i2c_get_clientdata(client)); | ||
1359 | return 0; | ||
1378 | } | 1360 | } |
1379 | 1361 | ||
1380 | static const struct i2c_device_id aic3x_i2c_id[] = { | 1362 | static const struct i2c_device_id aic3x_i2c_id[] = { |
@@ -1387,7 +1369,7 @@ MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); | |||
1387 | /* machine i2c codec control layer */ | 1369 | /* machine i2c codec control layer */ |
1388 | static struct i2c_driver aic3x_i2c_driver = { | 1370 | static struct i2c_driver aic3x_i2c_driver = { |
1389 | .driver = { | 1371 | .driver = { |
1390 | .name = "aic3x I2C Codec", | 1372 | .name = "tlv320aic3x-codec", |
1391 | .owner = THIS_MODULE, | 1373 | .owner = THIS_MODULE, |
1392 | }, | 1374 | }, |
1393 | .probe = aic3x_i2c_probe, | 1375 | .probe = aic3x_i2c_probe, |
@@ -1409,90 +1391,27 @@ static inline void aic3x_i2c_exit(void) | |||
1409 | { | 1391 | { |
1410 | i2c_del_driver(&aic3x_i2c_driver); | 1392 | i2c_del_driver(&aic3x_i2c_driver); |
1411 | } | 1393 | } |
1412 | #else | ||
1413 | static inline void aic3x_i2c_init(void) { } | ||
1414 | static inline void aic3x_i2c_exit(void) { } | ||
1415 | #endif | 1394 | #endif |
1416 | 1395 | ||
1417 | static int aic3x_probe(struct platform_device *pdev) | 1396 | static int __init aic3x_modinit(void) |
1418 | { | 1397 | { |
1419 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1420 | struct aic3x_setup_data *setup; | ||
1421 | struct snd_soc_codec *codec; | ||
1422 | int ret = 0; | 1398 | int ret = 0; |
1423 | 1399 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1424 | codec = aic3x_codec; | 1400 | ret = i2c_add_driver(&aic3x_i2c_driver); |
1425 | if (!codec) { | 1401 | if (ret != 0) { |
1426 | dev_err(&pdev->dev, "Codec not registered\n"); | 1402 | printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n", |
1427 | return -ENODEV; | 1403 | ret); |
1428 | } | ||
1429 | |||
1430 | socdev->card->codec = codec; | ||
1431 | setup = socdev->codec_data; | ||
1432 | |||
1433 | if (setup) { | ||
1434 | /* setup GPIO functions */ | ||
1435 | aic3x_write(codec, AIC3X_GPIO1_REG, | ||
1436 | (setup->gpio_func[0] & 0xf) << 4); | ||
1437 | aic3x_write(codec, AIC3X_GPIO2_REG, | ||
1438 | (setup->gpio_func[1] & 0xf) << 4); | ||
1439 | } | ||
1440 | |||
1441 | /* register pcms */ | ||
1442 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1443 | if (ret < 0) { | ||
1444 | printk(KERN_ERR "aic3x: failed to create pcms\n"); | ||
1445 | goto pcm_err; | ||
1446 | } | 1404 | } |
1447 | 1405 | #endif | |
1448 | snd_soc_add_controls(codec, aic3x_snd_controls, | ||
1449 | ARRAY_SIZE(aic3x_snd_controls)); | ||
1450 | |||
1451 | aic3x_add_widgets(codec); | ||
1452 | |||
1453 | return ret; | ||
1454 | |||
1455 | pcm_err: | ||
1456 | kfree(codec->reg_cache); | ||
1457 | return ret; | 1406 | return ret; |
1458 | } | 1407 | } |
1459 | |||
1460 | static int aic3x_remove(struct platform_device *pdev) | ||
1461 | { | ||
1462 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1463 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1464 | |||
1465 | /* power down chip */ | ||
1466 | if (codec->control_data) | ||
1467 | aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1468 | |||
1469 | snd_soc_free_pcms(socdev); | ||
1470 | snd_soc_dapm_free(socdev); | ||
1471 | |||
1472 | kfree(codec->reg_cache); | ||
1473 | |||
1474 | return 0; | ||
1475 | } | ||
1476 | |||
1477 | struct snd_soc_codec_device soc_codec_dev_aic3x = { | ||
1478 | .probe = aic3x_probe, | ||
1479 | .remove = aic3x_remove, | ||
1480 | .suspend = aic3x_suspend, | ||
1481 | .resume = aic3x_resume, | ||
1482 | }; | ||
1483 | EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x); | ||
1484 | |||
1485 | static int __init aic3x_modinit(void) | ||
1486 | { | ||
1487 | aic3x_i2c_init(); | ||
1488 | |||
1489 | return 0; | ||
1490 | } | ||
1491 | module_init(aic3x_modinit); | 1408 | module_init(aic3x_modinit); |
1492 | 1409 | ||
1493 | static void __exit aic3x_exit(void) | 1410 | static void __exit aic3x_exit(void) |
1494 | { | 1411 | { |
1495 | aic3x_i2c_exit(); | 1412 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1413 | i2c_del_driver(&aic3x_i2c_driver); | ||
1414 | #endif | ||
1496 | } | 1415 | } |
1497 | module_exit(aic3x_exit); | 1416 | module_exit(aic3x_exit); |
1498 | 1417 | ||
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 9af1c886213c..f6e3d9b42daf 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h | |||
@@ -199,42 +199,6 @@ | |||
199 | /* Default input volume */ | 199 | /* Default input volume */ |
200 | #define DEFAULT_GAIN 0x20 | 200 | #define DEFAULT_GAIN 0x20 |
201 | 201 | ||
202 | /* GPIO API */ | ||
203 | enum { | ||
204 | AIC3X_GPIO1_FUNC_DISABLED = 0, | ||
205 | AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC = 1, | ||
206 | AIC3X_GPIO1_FUNC_CLOCK_MUX = 2, | ||
207 | AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2 = 3, | ||
208 | AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4 = 4, | ||
209 | AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8 = 5, | ||
210 | AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ = 6, | ||
211 | AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ = 7, | ||
212 | AIC3X_GPIO1_FUNC_INPUT = 8, | ||
213 | AIC3X_GPIO1_FUNC_OUTPUT = 9, | ||
214 | AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK = 10, | ||
215 | AIC3X_GPIO1_FUNC_AUDIO_WORDCLK = 11, | ||
216 | AIC3X_GPIO1_FUNC_BUTTON_IRQ = 12, | ||
217 | AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ = 13, | ||
218 | AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 14, | ||
219 | AIC3X_GPIO1_FUNC_ALL_IRQ = 16 | ||
220 | }; | ||
221 | |||
222 | enum { | ||
223 | AIC3X_GPIO2_FUNC_DISABLED = 0, | ||
224 | AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ = 2, | ||
225 | AIC3X_GPIO2_FUNC_INPUT = 3, | ||
226 | AIC3X_GPIO2_FUNC_OUTPUT = 4, | ||
227 | AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT = 5, | ||
228 | AIC3X_GPIO2_FUNC_AUDIO_BITCLK = 8, | ||
229 | AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9, | ||
230 | AIC3X_GPIO2_FUNC_ALL_IRQ = 10, | ||
231 | AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11, | ||
232 | AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12, | ||
233 | AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ = 13, | ||
234 | AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ = 14, | ||
235 | AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15 | ||
236 | }; | ||
237 | |||
238 | void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state); | 202 | void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state); |
239 | int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio); | 203 | int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio); |
240 | 204 | ||
@@ -281,11 +245,4 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect, | |||
281 | int aic3x_headset_detected(struct snd_soc_codec *codec); | 245 | int aic3x_headset_detected(struct snd_soc_codec *codec); |
282 | int aic3x_button_pressed(struct snd_soc_codec *codec); | 246 | int aic3x_button_pressed(struct snd_soc_codec *codec); |
283 | 247 | ||
284 | struct aic3x_setup_data { | ||
285 | unsigned int gpio_func[2]; | ||
286 | }; | ||
287 | |||
288 | extern struct snd_soc_dai aic3x_dai; | ||
289 | extern struct snd_soc_codec_device soc_codec_dev_aic3x; | ||
290 | |||
291 | #endif /* _AIC3X_H */ | 248 | #endif /* _AIC3X_H */ |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 8651b01ed223..a3c5b521da6a 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -66,8 +66,6 @@ | |||
66 | static void dac33_calculate_times(struct snd_pcm_substream *substream); | 66 | static void dac33_calculate_times(struct snd_pcm_substream *substream); |
67 | static int dac33_prepare_chip(struct snd_pcm_substream *substream); | 67 | static int dac33_prepare_chip(struct snd_pcm_substream *substream); |
68 | 68 | ||
69 | static struct snd_soc_codec *tlv320dac33_codec; | ||
70 | |||
71 | enum dac33_state { | 69 | enum dac33_state { |
72 | DAC33_IDLE = 0, | 70 | DAC33_IDLE = 0, |
73 | DAC33_PREFILL, | 71 | DAC33_PREFILL, |
@@ -93,7 +91,7 @@ struct tlv320dac33_priv { | |||
93 | struct mutex mutex; | 91 | struct mutex mutex; |
94 | struct workqueue_struct *dac33_wq; | 92 | struct workqueue_struct *dac33_wq; |
95 | struct work_struct work; | 93 | struct work_struct work; |
96 | struct snd_soc_codec codec; | 94 | struct snd_soc_codec *codec; |
97 | struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; | 95 | struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; |
98 | struct snd_pcm_substream *substream; | 96 | struct snd_pcm_substream *substream; |
99 | int power_gpio; | 97 | int power_gpio; |
@@ -128,6 +126,8 @@ struct tlv320dac33_priv { | |||
128 | unsigned int uthr; | 126 | unsigned int uthr; |
129 | 127 | ||
130 | enum dac33_state state; | 128 | enum dac33_state state; |
129 | enum snd_soc_control_type control_type; | ||
130 | void *control_data; | ||
131 | }; | 131 | }; |
132 | 132 | ||
133 | static const u8 dac33_reg[DAC33_CACHEREGNUM] = { | 133 | static const u8 dac33_reg[DAC33_CACHEREGNUM] = { |
@@ -650,9 +650,7 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec, | |||
650 | 650 | ||
651 | static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) | 651 | static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) |
652 | { | 652 | { |
653 | struct snd_soc_codec *codec; | 653 | struct snd_soc_codec *codec = dac33->codec; |
654 | |||
655 | codec = &dac33->codec; | ||
656 | 654 | ||
657 | switch (dac33->fifo_mode) { | 655 | switch (dac33->fifo_mode) { |
658 | case DAC33_FIFO_MODE1: | 656 | case DAC33_FIFO_MODE1: |
@@ -695,9 +693,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) | |||
695 | 693 | ||
696 | static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33) | 694 | static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33) |
697 | { | 695 | { |
698 | struct snd_soc_codec *codec; | 696 | struct snd_soc_codec *codec = dac33->codec; |
699 | |||
700 | codec = &dac33->codec; | ||
701 | 697 | ||
702 | switch (dac33->fifo_mode) { | 698 | switch (dac33->fifo_mode) { |
703 | case DAC33_FIFO_MODE1: | 699 | case DAC33_FIFO_MODE1: |
@@ -726,7 +722,7 @@ static void dac33_work(struct work_struct *work) | |||
726 | u8 reg; | 722 | u8 reg; |
727 | 723 | ||
728 | dac33 = container_of(work, struct tlv320dac33_priv, work); | 724 | dac33 = container_of(work, struct tlv320dac33_priv, work); |
729 | codec = &dac33->codec; | 725 | codec = dac33->codec; |
730 | 726 | ||
731 | mutex_lock(&dac33->mutex); | 727 | mutex_lock(&dac33->mutex); |
732 | switch (dac33->state) { | 728 | switch (dac33->state) { |
@@ -787,8 +783,7 @@ static int dac33_startup(struct snd_pcm_substream *substream, | |||
787 | struct snd_soc_dai *dai) | 783 | struct snd_soc_dai *dai) |
788 | { | 784 | { |
789 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 785 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
790 | struct snd_soc_device *socdev = rtd->socdev; | 786 | struct snd_soc_codec *codec = rtd->codec; |
791 | struct snd_soc_codec *codec = socdev->card->codec; | ||
792 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 787 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
793 | 788 | ||
794 | /* Stream started, save the substream pointer */ | 789 | /* Stream started, save the substream pointer */ |
@@ -801,8 +796,7 @@ static void dac33_shutdown(struct snd_pcm_substream *substream, | |||
801 | struct snd_soc_dai *dai) | 796 | struct snd_soc_dai *dai) |
802 | { | 797 | { |
803 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 798 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
804 | struct snd_soc_device *socdev = rtd->socdev; | 799 | struct snd_soc_codec *codec = rtd->codec; |
805 | struct snd_soc_codec *codec = socdev->card->codec; | ||
806 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 800 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
807 | 801 | ||
808 | dac33->substream = NULL; | 802 | dac33->substream = NULL; |
@@ -817,8 +811,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream, | |||
817 | struct snd_soc_dai *dai) | 811 | struct snd_soc_dai *dai) |
818 | { | 812 | { |
819 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 813 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
820 | struct snd_soc_device *socdev = rtd->socdev; | 814 | struct snd_soc_codec *codec = rtd->codec; |
821 | struct snd_soc_codec *codec = socdev->card->codec; | ||
822 | 815 | ||
823 | /* Check parameters for validity */ | 816 | /* Check parameters for validity */ |
824 | switch (params_rate(params)) { | 817 | switch (params_rate(params)) { |
@@ -856,8 +849,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream, | |||
856 | static int dac33_prepare_chip(struct snd_pcm_substream *substream) | 849 | static int dac33_prepare_chip(struct snd_pcm_substream *substream) |
857 | { | 850 | { |
858 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 851 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
859 | struct snd_soc_device *socdev = rtd->socdev; | 852 | struct snd_soc_codec *codec = rtd->codec; |
860 | struct snd_soc_codec *codec = socdev->card->codec; | ||
861 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 853 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
862 | unsigned int oscset, ratioset, pwr_ctrl, reg_tmp; | 854 | unsigned int oscset, ratioset, pwr_ctrl, reg_tmp; |
863 | u8 aictrl_a, aictrl_b, fifoctrl_a; | 855 | u8 aictrl_a, aictrl_b, fifoctrl_a; |
@@ -1049,8 +1041,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) | |||
1049 | static void dac33_calculate_times(struct snd_pcm_substream *substream) | 1041 | static void dac33_calculate_times(struct snd_pcm_substream *substream) |
1050 | { | 1042 | { |
1051 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1043 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1052 | struct snd_soc_device *socdev = rtd->socdev; | 1044 | struct snd_soc_codec *codec = rtd->codec; |
1053 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1054 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 1045 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
1055 | unsigned int period_size = substream->runtime->period_size; | 1046 | unsigned int period_size = substream->runtime->period_size; |
1056 | unsigned int rate = substream->runtime->rate; | 1047 | unsigned int rate = substream->runtime->rate; |
@@ -1129,8 +1120,7 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | |||
1129 | struct snd_soc_dai *dai) | 1120 | struct snd_soc_dai *dai) |
1130 | { | 1121 | { |
1131 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1122 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1132 | struct snd_soc_device *socdev = rtd->socdev; | 1123 | struct snd_soc_codec *codec = rtd->codec; |
1133 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1134 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 1124 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
1135 | int ret = 0; | 1125 | int ret = 0; |
1136 | 1126 | ||
@@ -1163,8 +1153,7 @@ static snd_pcm_sframes_t dac33_dai_delay( | |||
1163 | struct snd_soc_dai *dai) | 1153 | struct snd_soc_dai *dai) |
1164 | { | 1154 | { |
1165 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1155 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1166 | struct snd_soc_device *socdev = rtd->socdev; | 1156 | struct snd_soc_codec *codec = rtd->codec; |
1167 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1168 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 1157 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
1169 | unsigned long long t0, t1, t_now; | 1158 | unsigned long long t0, t1, t_now; |
1170 | unsigned int time_delta, uthr; | 1159 | unsigned int time_delta, uthr; |
@@ -1389,24 +1378,47 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1389 | return 0; | 1378 | return 0; |
1390 | } | 1379 | } |
1391 | 1380 | ||
1392 | static int dac33_soc_probe(struct platform_device *pdev) | 1381 | static int dac33_soc_probe(struct snd_soc_codec *codec) |
1393 | { | 1382 | { |
1394 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1383 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
1395 | struct snd_soc_codec *codec; | ||
1396 | struct tlv320dac33_priv *dac33; | ||
1397 | int ret = 0; | 1384 | int ret = 0; |
1398 | 1385 | ||
1399 | BUG_ON(!tlv320dac33_codec); | 1386 | codec->control_data = dac33->control_data; |
1387 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1388 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1389 | codec->idle_bias_off = 1; | ||
1390 | dac33->codec = codec; | ||
1400 | 1391 | ||
1401 | codec = tlv320dac33_codec; | 1392 | /* Read the tlv320dac33 ID registers */ |
1402 | socdev->card->codec = codec; | 1393 | ret = dac33_hard_power(codec, 1); |
1403 | dac33 = snd_soc_codec_get_drvdata(codec); | 1394 | if (ret != 0) { |
1395 | dev_err(codec->dev, "Failed to power up codec: %d\n", ret); | ||
1396 | goto err_power; | ||
1397 | } | ||
1398 | dac33_read_id(codec); | ||
1399 | dac33_hard_power(codec, 0); | ||
1404 | 1400 | ||
1405 | /* register pcms */ | 1401 | /* Check if the IRQ number is valid and request it */ |
1406 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1402 | if (dac33->irq >= 0) { |
1407 | if (ret < 0) { | 1403 | ret = request_irq(dac33->irq, dac33_interrupt_handler, |
1408 | dev_err(codec->dev, "failed to create pcms\n"); | 1404 | IRQF_TRIGGER_RISING | IRQF_DISABLED, |
1409 | goto pcm_err; | 1405 | codec->name, codec); |
1406 | if (ret < 0) { | ||
1407 | dev_err(codec->dev, "Could not request IRQ%d (%d)\n", | ||
1408 | dac33->irq, ret); | ||
1409 | dac33->irq = -1; | ||
1410 | } | ||
1411 | if (dac33->irq != -1) { | ||
1412 | /* Setup work queue */ | ||
1413 | dac33->dac33_wq = | ||
1414 | create_singlethread_workqueue("tlv320dac33"); | ||
1415 | if (dac33->dac33_wq == NULL) { | ||
1416 | free_irq(dac33->irq, codec); | ||
1417 | return -ENOMEM; | ||
1418 | } | ||
1419 | |||
1420 | INIT_WORK(&dac33->work, dac33_work); | ||
1421 | } | ||
1410 | } | 1422 | } |
1411 | 1423 | ||
1412 | snd_soc_add_controls(codec, dac33_snd_controls, | 1424 | snd_soc_add_controls(codec, dac33_snd_controls, |
@@ -1420,56 +1432,51 @@ static int dac33_soc_probe(struct platform_device *pdev) | |||
1420 | snd_soc_add_controls(codec, dac33_fifo_snd_controls, | 1432 | snd_soc_add_controls(codec, dac33_fifo_snd_controls, |
1421 | ARRAY_SIZE(dac33_fifo_snd_controls)); | 1433 | ARRAY_SIZE(dac33_fifo_snd_controls)); |
1422 | } | 1434 | } |
1423 | |||
1424 | dac33_add_widgets(codec); | 1435 | dac33_add_widgets(codec); |
1425 | 1436 | ||
1426 | return 0; | 1437 | err_power: |
1427 | |||
1428 | pcm_err: | ||
1429 | dac33_hard_power(codec, 0); | ||
1430 | return ret; | 1438 | return ret; |
1431 | } | 1439 | } |
1432 | 1440 | ||
1433 | static int dac33_soc_remove(struct platform_device *pdev) | 1441 | static int dac33_soc_remove(struct snd_soc_codec *codec) |
1434 | { | 1442 | { |
1435 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1443 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
1436 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1437 | 1444 | ||
1438 | dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1445 | dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1439 | 1446 | ||
1440 | snd_soc_free_pcms(socdev); | 1447 | if (dac33->irq >= 0) { |
1441 | snd_soc_dapm_free(socdev); | 1448 | free_irq(dac33->irq, dac33->codec); |
1442 | 1449 | destroy_workqueue(dac33->dac33_wq); | |
1450 | } | ||
1443 | return 0; | 1451 | return 0; |
1444 | } | 1452 | } |
1445 | 1453 | ||
1446 | static int dac33_soc_suspend(struct platform_device *pdev, pm_message_t state) | 1454 | static int dac33_soc_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1447 | { | 1455 | { |
1448 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1449 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1450 | |||
1451 | dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1456 | dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1452 | 1457 | ||
1453 | return 0; | 1458 | return 0; |
1454 | } | 1459 | } |
1455 | 1460 | ||
1456 | static int dac33_soc_resume(struct platform_device *pdev) | 1461 | static int dac33_soc_resume(struct snd_soc_codec *codec) |
1457 | { | 1462 | { |
1458 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1459 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1460 | |||
1461 | dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1463 | dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1462 | 1464 | ||
1463 | return 0; | 1465 | return 0; |
1464 | } | 1466 | } |
1465 | 1467 | ||
1466 | struct snd_soc_codec_device soc_codec_dev_tlv320dac33 = { | 1468 | static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = { |
1469 | .read = dac33_read_reg_cache, | ||
1470 | .write = dac33_write_locked, | ||
1471 | .set_bias_level = dac33_set_bias_level, | ||
1472 | .reg_cache_size = ARRAY_SIZE(dac33_reg), | ||
1473 | .reg_word_size = sizeof(u8), | ||
1474 | .reg_cache_default = dac33_reg, | ||
1467 | .probe = dac33_soc_probe, | 1475 | .probe = dac33_soc_probe, |
1468 | .remove = dac33_soc_remove, | 1476 | .remove = dac33_soc_remove, |
1469 | .suspend = dac33_soc_suspend, | 1477 | .suspend = dac33_soc_suspend, |
1470 | .resume = dac33_soc_resume, | 1478 | .resume = dac33_soc_resume, |
1471 | }; | 1479 | }; |
1472 | EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33); | ||
1473 | 1480 | ||
1474 | #define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ | 1481 | #define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ |
1475 | SNDRV_PCM_RATE_48000) | 1482 | SNDRV_PCM_RATE_48000) |
@@ -1485,8 +1492,8 @@ static struct snd_soc_dai_ops dac33_dai_ops = { | |||
1485 | .set_fmt = dac33_set_dai_fmt, | 1492 | .set_fmt = dac33_set_dai_fmt, |
1486 | }; | 1493 | }; |
1487 | 1494 | ||
1488 | struct snd_soc_dai dac33_dai = { | 1495 | static struct snd_soc_dai_driver dac33_dai = { |
1489 | .name = "tlv320dac33", | 1496 | .name = "tlv320dac33-hifi", |
1490 | .playback = { | 1497 | .playback = { |
1491 | .stream_name = "Playback", | 1498 | .stream_name = "Playback", |
1492 | .channels_min = 2, | 1499 | .channels_min = 2, |
@@ -1495,14 +1502,12 @@ struct snd_soc_dai dac33_dai = { | |||
1495 | .formats = DAC33_FORMATS,}, | 1502 | .formats = DAC33_FORMATS,}, |
1496 | .ops = &dac33_dai_ops, | 1503 | .ops = &dac33_dai_ops, |
1497 | }; | 1504 | }; |
1498 | EXPORT_SYMBOL_GPL(dac33_dai); | ||
1499 | 1505 | ||
1500 | static int __devinit dac33_i2c_probe(struct i2c_client *client, | 1506 | static int __devinit dac33_i2c_probe(struct i2c_client *client, |
1501 | const struct i2c_device_id *id) | 1507 | const struct i2c_device_id *id) |
1502 | { | 1508 | { |
1503 | struct tlv320dac33_platform_data *pdata; | 1509 | struct tlv320dac33_platform_data *pdata; |
1504 | struct tlv320dac33_priv *dac33; | 1510 | struct tlv320dac33_priv *dac33; |
1505 | struct snd_soc_codec *codec; | ||
1506 | int ret, i; | 1511 | int ret, i; |
1507 | 1512 | ||
1508 | if (client->dev.platform_data == NULL) { | 1513 | if (client->dev.platform_data == NULL) { |
@@ -1515,33 +1520,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, | |||
1515 | if (dac33 == NULL) | 1520 | if (dac33 == NULL) |
1516 | return -ENOMEM; | 1521 | return -ENOMEM; |
1517 | 1522 | ||
1518 | codec = &dac33->codec; | 1523 | dac33->control_data = client; |
1519 | snd_soc_codec_set_drvdata(codec, dac33); | ||
1520 | codec->control_data = client; | ||
1521 | |||
1522 | mutex_init(&codec->mutex); | ||
1523 | mutex_init(&dac33->mutex); | 1524 | mutex_init(&dac33->mutex); |
1524 | spin_lock_init(&dac33->lock); | 1525 | spin_lock_init(&dac33->lock); |
1525 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1526 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1527 | |||
1528 | codec->name = "tlv320dac33"; | ||
1529 | codec->owner = THIS_MODULE; | ||
1530 | codec->read = dac33_read_reg_cache; | ||
1531 | codec->write = dac33_write_locked; | ||
1532 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1533 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1534 | codec->set_bias_level = dac33_set_bias_level; | ||
1535 | codec->idle_bias_off = 1; | ||
1536 | codec->dai = &dac33_dai; | ||
1537 | codec->num_dai = 1; | ||
1538 | codec->reg_cache_size = ARRAY_SIZE(dac33_reg); | ||
1539 | codec->reg_cache = kmemdup(dac33_reg, ARRAY_SIZE(dac33_reg), | ||
1540 | GFP_KERNEL); | ||
1541 | if (codec->reg_cache == NULL) { | ||
1542 | ret = -ENOMEM; | ||
1543 | goto error_reg; | ||
1544 | } | ||
1545 | 1526 | ||
1546 | i2c_set_clientdata(client, dac33); | 1527 | i2c_set_clientdata(client, dac33); |
1547 | 1528 | ||
@@ -1561,125 +1542,59 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, | |||
1561 | /* Disable FIFO use by default */ | 1542 | /* Disable FIFO use by default */ |
1562 | dac33->fifo_mode = DAC33_FIFO_BYPASS; | 1543 | dac33->fifo_mode = DAC33_FIFO_BYPASS; |
1563 | 1544 | ||
1564 | tlv320dac33_codec = codec; | ||
1565 | |||
1566 | codec->dev = &client->dev; | ||
1567 | dac33_dai.dev = codec->dev; | ||
1568 | |||
1569 | /* Check if the reset GPIO number is valid and request it */ | 1545 | /* Check if the reset GPIO number is valid and request it */ |
1570 | if (dac33->power_gpio >= 0) { | 1546 | if (dac33->power_gpio >= 0) { |
1571 | ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset"); | 1547 | ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset"); |
1572 | if (ret < 0) { | 1548 | if (ret < 0) { |
1573 | dev_err(codec->dev, | 1549 | dev_err(&client->dev, |
1574 | "Failed to request reset GPIO (%d)\n", | 1550 | "Failed to request reset GPIO (%d)\n", |
1575 | dac33->power_gpio); | 1551 | dac33->power_gpio); |
1576 | snd_soc_unregister_dai(&dac33_dai); | 1552 | goto err_gpio; |
1577 | snd_soc_unregister_codec(codec); | ||
1578 | goto error_gpio; | ||
1579 | } | 1553 | } |
1580 | gpio_direction_output(dac33->power_gpio, 0); | 1554 | gpio_direction_output(dac33->power_gpio, 0); |
1581 | } | 1555 | } |
1582 | 1556 | ||
1583 | /* Check if the IRQ number is valid and request it */ | ||
1584 | if (dac33->irq >= 0) { | ||
1585 | ret = request_irq(dac33->irq, dac33_interrupt_handler, | ||
1586 | IRQF_TRIGGER_RISING | IRQF_DISABLED, | ||
1587 | codec->name, codec); | ||
1588 | if (ret < 0) { | ||
1589 | dev_err(codec->dev, "Could not request IRQ%d (%d)\n", | ||
1590 | dac33->irq, ret); | ||
1591 | dac33->irq = -1; | ||
1592 | } | ||
1593 | if (dac33->irq != -1) { | ||
1594 | /* Setup work queue */ | ||
1595 | dac33->dac33_wq = | ||
1596 | create_singlethread_workqueue("tlv320dac33"); | ||
1597 | if (dac33->dac33_wq == NULL) { | ||
1598 | free_irq(dac33->irq, &dac33->codec); | ||
1599 | ret = -ENOMEM; | ||
1600 | goto error_wq; | ||
1601 | } | ||
1602 | |||
1603 | INIT_WORK(&dac33->work, dac33_work); | ||
1604 | } | ||
1605 | } | ||
1606 | |||
1607 | for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++) | 1557 | for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++) |
1608 | dac33->supplies[i].supply = dac33_supply_names[i]; | 1558 | dac33->supplies[i].supply = dac33_supply_names[i]; |
1609 | 1559 | ||
1610 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(dac33->supplies), | 1560 | ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies), |
1611 | dac33->supplies); | 1561 | dac33->supplies); |
1612 | 1562 | ||
1613 | if (ret != 0) { | 1563 | if (ret != 0) { |
1614 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 1564 | dev_err(&client->dev, "Failed to request supplies: %d\n", ret); |
1615 | goto err_get; | 1565 | goto err_get; |
1616 | } | 1566 | } |
1617 | 1567 | ||
1618 | /* Read the tlv320dac33 ID registers */ | 1568 | ret = snd_soc_register_codec(&client->dev, |
1619 | ret = dac33_hard_power(codec, 1); | 1569 | &soc_codec_dev_tlv320dac33, &dac33_dai, 1); |
1620 | if (ret != 0) { | 1570 | if (ret < 0) |
1621 | dev_err(codec->dev, "Failed to power up codec: %d\n", ret); | 1571 | goto err_register; |
1622 | goto error_codec; | ||
1623 | } | ||
1624 | dac33_read_id(codec); | ||
1625 | dac33_hard_power(codec, 0); | ||
1626 | |||
1627 | ret = snd_soc_register_codec(codec); | ||
1628 | if (ret != 0) { | ||
1629 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1630 | goto error_codec; | ||
1631 | } | ||
1632 | |||
1633 | ret = snd_soc_register_dai(&dac33_dai); | ||
1634 | if (ret != 0) { | ||
1635 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1636 | snd_soc_unregister_codec(codec); | ||
1637 | goto error_codec; | ||
1638 | } | ||
1639 | 1572 | ||
1640 | return ret; | 1573 | return ret; |
1641 | 1574 | err_register: | |
1642 | error_codec: | ||
1643 | regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); | 1575 | regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); |
1644 | err_get: | 1576 | err_get: |
1645 | if (dac33->irq >= 0) { | ||
1646 | free_irq(dac33->irq, &dac33->codec); | ||
1647 | destroy_workqueue(dac33->dac33_wq); | ||
1648 | } | ||
1649 | error_wq: | ||
1650 | if (dac33->power_gpio >= 0) | 1577 | if (dac33->power_gpio >= 0) |
1651 | gpio_free(dac33->power_gpio); | 1578 | gpio_free(dac33->power_gpio); |
1652 | error_gpio: | 1579 | err_gpio: |
1653 | kfree(codec->reg_cache); | ||
1654 | error_reg: | ||
1655 | tlv320dac33_codec = NULL; | ||
1656 | kfree(dac33); | 1580 | kfree(dac33); |
1657 | |||
1658 | return ret; | 1581 | return ret; |
1659 | } | 1582 | } |
1660 | 1583 | ||
1661 | static int __devexit dac33_i2c_remove(struct i2c_client *client) | 1584 | static int __devexit dac33_i2c_remove(struct i2c_client *client) |
1662 | { | 1585 | { |
1663 | struct tlv320dac33_priv *dac33; | 1586 | struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client); |
1664 | |||
1665 | dac33 = i2c_get_clientdata(client); | ||
1666 | 1587 | ||
1667 | if (unlikely(dac33->chip_power)) | 1588 | if (unlikely(dac33->chip_power)) |
1668 | dac33_hard_power(&dac33->codec, 0); | 1589 | dac33_hard_power(dac33->codec, 0); |
1669 | 1590 | ||
1670 | if (dac33->power_gpio >= 0) | 1591 | if (dac33->power_gpio >= 0) |
1671 | gpio_free(dac33->power_gpio); | 1592 | gpio_free(dac33->power_gpio); |
1672 | if (dac33->irq >= 0) | ||
1673 | free_irq(dac33->irq, &dac33->codec); | ||
1674 | 1593 | ||
1675 | regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); | 1594 | regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); |
1676 | 1595 | ||
1677 | destroy_workqueue(dac33->dac33_wq); | 1596 | snd_soc_unregister_codec(&client->dev); |
1678 | snd_soc_unregister_dai(&dac33_dai); | ||
1679 | snd_soc_unregister_codec(&dac33->codec); | ||
1680 | kfree(dac33->codec.reg_cache); | ||
1681 | kfree(dac33); | 1597 | kfree(dac33); |
1682 | tlv320dac33_codec = NULL; | ||
1683 | 1598 | ||
1684 | return 0; | 1599 | return 0; |
1685 | } | 1600 | } |
@@ -1694,7 +1609,7 @@ static const struct i2c_device_id tlv320dac33_i2c_id[] = { | |||
1694 | 1609 | ||
1695 | static struct i2c_driver tlv320dac33_i2c_driver = { | 1610 | static struct i2c_driver tlv320dac33_i2c_driver = { |
1696 | .driver = { | 1611 | .driver = { |
1697 | .name = "tlv320dac33", | 1612 | .name = "tlv320dac33-codec", |
1698 | .owner = THIS_MODULE, | 1613 | .owner = THIS_MODULE, |
1699 | }, | 1614 | }, |
1700 | .probe = dac33_i2c_probe, | 1615 | .probe = dac33_i2c_probe, |
diff --git a/sound/soc/codecs/tlv320dac33.h b/sound/soc/codecs/tlv320dac33.h index eb8ae07f0bd2..7c318b5da437 100644 --- a/sound/soc/codecs/tlv320dac33.h +++ b/sound/soc/codecs/tlv320dac33.h | |||
@@ -261,7 +261,4 @@ | |||
261 | #define TLV320DAC33_MCLK 0 | 261 | #define TLV320DAC33_MCLK 0 |
262 | #define TLV320DAC33_SLEEPCLK 1 | 262 | #define TLV320DAC33_SLEEPCLK 1 |
263 | 263 | ||
264 | extern struct snd_soc_dai dac33_dai; | ||
265 | extern struct snd_soc_codec_device soc_codec_dev_tlv320dac33; | ||
266 | |||
267 | #endif /* __TLV320DAC33_H */ | 264 | #endif /* __TLV320DAC33_H */ |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 7b618bbff884..898430f44f9d 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -36,7 +36,16 @@ | |||
36 | #include <sound/initval.h> | 36 | #include <sound/initval.h> |
37 | #include <sound/tlv.h> | 37 | #include <sound/tlv.h> |
38 | 38 | ||
39 | #include "twl4030.h" | 39 | /* Register descriptions are here */ |
40 | #include <linux/mfd/twl4030-codec.h> | ||
41 | |||
42 | /* Shadow register used by the audio driver */ | ||
43 | #define TWL4030_REG_SW_SHADOW 0x4A | ||
44 | #define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1) | ||
45 | |||
46 | /* TWL4030_REG_SW_SHADOW (0x4A) Fields */ | ||
47 | #define TWL4030_HFL_EN 0x01 | ||
48 | #define TWL4030_HFR_EN 0x02 | ||
40 | 49 | ||
41 | /* | 50 | /* |
42 | * twl4030 register cache & default register settings | 51 | * twl4030 register cache & default register settings |
@@ -277,21 +286,19 @@ static inline void twl4030_reset_registers(struct snd_soc_codec *codec) | |||
277 | 286 | ||
278 | } | 287 | } |
279 | 288 | ||
280 | static void twl4030_init_chip(struct platform_device *pdev) | 289 | static void twl4030_init_chip(struct snd_soc_codec *codec) |
281 | { | 290 | { |
282 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 291 | struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev); |
283 | struct twl4030_setup_data *setup = socdev->codec_data; | ||
284 | struct snd_soc_codec *codec = socdev->card->codec; | ||
285 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 292 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
286 | u8 reg, byte; | 293 | u8 reg, byte; |
287 | int i = 0; | 294 | int i = 0; |
288 | 295 | ||
289 | /* Check defaults, if instructed before anything else */ | 296 | /* Check defaults, if instructed before anything else */ |
290 | if (setup && setup->check_defaults) | 297 | if (pdata && pdata->check_defaults) |
291 | twl4030_check_defaults(codec); | 298 | twl4030_check_defaults(codec); |
292 | 299 | ||
293 | /* Reset registers, if no setup data or if instructed to do so */ | 300 | /* Reset registers, if no setup data or if instructed to do so */ |
294 | if (!setup || (setup && setup->reset_registers)) | 301 | if (!pdata || (pdata && pdata->reset_registers)) |
295 | twl4030_reset_registers(codec); | 302 | twl4030_reset_registers(codec); |
296 | 303 | ||
297 | /* Refresh APLL_CTL register from HW */ | 304 | /* Refresh APLL_CTL register from HW */ |
@@ -312,20 +319,14 @@ static void twl4030_init_chip(struct platform_device *pdev) | |||
312 | twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32); | 319 | twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32); |
313 | 320 | ||
314 | /* Machine dependent setup */ | 321 | /* Machine dependent setup */ |
315 | if (!setup) | 322 | if (!pdata) |
316 | return; | 323 | return; |
317 | 324 | ||
318 | twl4030->digimic_delay = setup->digimic_delay; | 325 | twl4030->digimic_delay = pdata->digimic_delay; |
319 | |||
320 | /* Configuration for headset ramp delay from setup data */ | ||
321 | if (setup->sysclk != twl4030->sysclk) | ||
322 | dev_warn(codec->dev, | ||
323 | "Mismatch in APLL mclk: %u (configured: %u)\n", | ||
324 | setup->sysclk, twl4030->sysclk); | ||
325 | 326 | ||
326 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); | 327 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); |
327 | reg &= ~TWL4030_RAMP_DELAY; | 328 | reg &= ~TWL4030_RAMP_DELAY; |
328 | reg |= (setup->ramp_delay_value << 2); | 329 | reg |= (pdata->ramp_delay_value << 2); |
329 | twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg); | 330 | twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg); |
330 | 331 | ||
331 | /* initiate offset cancellation */ | 332 | /* initiate offset cancellation */ |
@@ -333,7 +334,7 @@ static void twl4030_init_chip(struct platform_device *pdev) | |||
333 | 334 | ||
334 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); | 335 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); |
335 | reg &= ~TWL4030_OFFSET_CNCL_SEL; | 336 | reg &= ~TWL4030_OFFSET_CNCL_SEL; |
336 | reg |= setup->offset_cncl_path; | 337 | reg |= pdata->offset_cncl_path; |
337 | twl4030_write(codec, TWL4030_REG_ANAMICL, | 338 | twl4030_write(codec, TWL4030_REG_ANAMICL, |
338 | reg | TWL4030_CNCL_OFFSET_START); | 339 | reg | TWL4030_CNCL_OFFSET_START); |
339 | 340 | ||
@@ -718,9 +719,7 @@ static int aif_event(struct snd_soc_dapm_widget *w, | |||
718 | 719 | ||
719 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) | 720 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) |
720 | { | 721 | { |
721 | struct snd_soc_device *socdev = codec->socdev; | 722 | struct twl4030_codec_audio_data *pdata = codec->dev->platform_data; |
722 | struct twl4030_setup_data *setup = socdev->codec_data; | ||
723 | |||
724 | unsigned char hs_gain, hs_pop; | 723 | unsigned char hs_gain, hs_pop; |
725 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 724 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
726 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ | 725 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ |
@@ -732,9 +731,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
732 | 731 | ||
733 | /* Enable external mute control, this dramatically reduces | 732 | /* Enable external mute control, this dramatically reduces |
734 | * the pop-noise */ | 733 | * the pop-noise */ |
735 | if (setup && setup->hs_extmute) { | 734 | if (pdata && pdata->hs_extmute) { |
736 | if (setup->set_hs_extmute) { | 735 | if (pdata->set_hs_extmute) { |
737 | setup->set_hs_extmute(1); | 736 | pdata->set_hs_extmute(1); |
738 | } else { | 737 | } else { |
739 | hs_pop |= TWL4030_EXTMUTE; | 738 | hs_pop |= TWL4030_EXTMUTE; |
740 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 739 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
@@ -772,9 +771,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
772 | } | 771 | } |
773 | 772 | ||
774 | /* Disable external mute */ | 773 | /* Disable external mute */ |
775 | if (setup && setup->hs_extmute) { | 774 | if (pdata && pdata->hs_extmute) { |
776 | if (setup->set_hs_extmute) { | 775 | if (pdata->set_hs_extmute) { |
777 | setup->set_hs_extmute(0); | 776 | pdata->set_hs_extmute(0); |
778 | } else { | 777 | } else { |
779 | hs_pop &= ~TWL4030_EXTMUTE; | 778 | hs_pop &= ~TWL4030_EXTMUTE; |
780 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 779 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
@@ -1707,8 +1706,7 @@ static int twl4030_startup(struct snd_pcm_substream *substream, | |||
1707 | struct snd_soc_dai *dai) | 1706 | struct snd_soc_dai *dai) |
1708 | { | 1707 | { |
1709 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1708 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1710 | struct snd_soc_device *socdev = rtd->socdev; | 1709 | struct snd_soc_codec *codec = rtd->codec; |
1711 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1712 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1710 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
1713 | 1711 | ||
1714 | if (twl4030->master_substream) { | 1712 | if (twl4030->master_substream) { |
@@ -1738,8 +1736,7 @@ static void twl4030_shutdown(struct snd_pcm_substream *substream, | |||
1738 | struct snd_soc_dai *dai) | 1736 | struct snd_soc_dai *dai) |
1739 | { | 1737 | { |
1740 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1738 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1741 | struct snd_soc_device *socdev = rtd->socdev; | 1739 | struct snd_soc_codec *codec = rtd->codec; |
1742 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1743 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1740 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
1744 | 1741 | ||
1745 | if (twl4030->master_substream == substream) | 1742 | if (twl4030->master_substream == substream) |
@@ -1764,8 +1761,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, | |||
1764 | struct snd_soc_dai *dai) | 1761 | struct snd_soc_dai *dai) |
1765 | { | 1762 | { |
1766 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1763 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1767 | struct snd_soc_device *socdev = rtd->socdev; | 1764 | struct snd_soc_codec *codec = rtd->codec; |
1768 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1769 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1765 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
1770 | u8 mode, old_mode, format, old_format; | 1766 | u8 mode, old_mode, format, old_format; |
1771 | 1767 | ||
@@ -1999,8 +1995,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream, | |||
1999 | struct snd_soc_dai *dai) | 1995 | struct snd_soc_dai *dai) |
2000 | { | 1996 | { |
2001 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1997 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
2002 | struct snd_soc_device *socdev = rtd->socdev; | 1998 | struct snd_soc_codec *codec = rtd->codec; |
2003 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2004 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1999 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
2005 | u8 mode; | 2000 | u8 mode; |
2006 | 2001 | ||
@@ -2033,8 +2028,7 @@ static void twl4030_voice_shutdown(struct snd_pcm_substream *substream, | |||
2033 | struct snd_soc_dai *dai) | 2028 | struct snd_soc_dai *dai) |
2034 | { | 2029 | { |
2035 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 2030 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
2036 | struct snd_soc_device *socdev = rtd->socdev; | 2031 | struct snd_soc_codec *codec = rtd->codec; |
2037 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2038 | 2032 | ||
2039 | /* Enable voice digital filters */ | 2033 | /* Enable voice digital filters */ |
2040 | twl4030_voice_enable(codec, substream->stream, 0); | 2034 | twl4030_voice_enable(codec, substream->stream, 0); |
@@ -2044,8 +2038,7 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream, | |||
2044 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 2038 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
2045 | { | 2039 | { |
2046 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 2040 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
2047 | struct snd_soc_device *socdev = rtd->socdev; | 2041 | struct snd_soc_codec *codec = rtd->codec; |
2048 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2049 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 2042 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
2050 | u8 old_mode, mode; | 2043 | u8 old_mode, mode; |
2051 | 2044 | ||
@@ -2175,7 +2168,7 @@ static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate) | |||
2175 | #define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) | 2168 | #define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) |
2176 | #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) | 2169 | #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) |
2177 | 2170 | ||
2178 | static struct snd_soc_dai_ops twl4030_dai_ops = { | 2171 | static struct snd_soc_dai_ops twl4030_dai_hifi_ops = { |
2179 | .startup = twl4030_startup, | 2172 | .startup = twl4030_startup, |
2180 | .shutdown = twl4030_shutdown, | 2173 | .shutdown = twl4030_shutdown, |
2181 | .hw_params = twl4030_hw_params, | 2174 | .hw_params = twl4030_hw_params, |
@@ -2193,9 +2186,9 @@ static struct snd_soc_dai_ops twl4030_dai_voice_ops = { | |||
2193 | .set_tristate = twl4030_voice_set_tristate, | 2186 | .set_tristate = twl4030_voice_set_tristate, |
2194 | }; | 2187 | }; |
2195 | 2188 | ||
2196 | struct snd_soc_dai twl4030_dai[] = { | 2189 | static struct snd_soc_dai_driver twl4030_dai[] = { |
2197 | { | 2190 | { |
2198 | .name = "twl4030", | 2191 | .name = "twl4030-hifi", |
2199 | .playback = { | 2192 | .playback = { |
2200 | .stream_name = "HiFi Playback", | 2193 | .stream_name = "HiFi Playback", |
2201 | .channels_min = 2, | 2194 | .channels_min = 2, |
@@ -2208,10 +2201,10 @@ struct snd_soc_dai twl4030_dai[] = { | |||
2208 | .channels_max = 4, | 2201 | .channels_max = 4, |
2209 | .rates = TWL4030_RATES, | 2202 | .rates = TWL4030_RATES, |
2210 | .formats = TWL4030_FORMATS,}, | 2203 | .formats = TWL4030_FORMATS,}, |
2211 | .ops = &twl4030_dai_ops, | 2204 | .ops = &twl4030_dai_hifi_ops, |
2212 | }, | 2205 | }, |
2213 | { | 2206 | { |
2214 | .name = "twl4030 Voice", | 2207 | .name = "twl4030-voice", |
2215 | .playback = { | 2208 | .playback = { |
2216 | .stream_name = "Voice Playback", | 2209 | .stream_name = "Voice Playback", |
2217 | .channels_min = 1, | 2210 | .channels_min = 1, |
@@ -2227,164 +2220,90 @@ struct snd_soc_dai twl4030_dai[] = { | |||
2227 | .ops = &twl4030_dai_voice_ops, | 2220 | .ops = &twl4030_dai_voice_ops, |
2228 | }, | 2221 | }, |
2229 | }; | 2222 | }; |
2230 | EXPORT_SYMBOL_GPL(twl4030_dai); | ||
2231 | 2223 | ||
2232 | static int twl4030_soc_suspend(struct platform_device *pdev, pm_message_t state) | 2224 | static int twl4030_soc_suspend(struct snd_soc_codec *codec, pm_message_t state) |
2233 | { | 2225 | { |
2234 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2235 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2236 | |||
2237 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2226 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2238 | |||
2239 | return 0; | 2227 | return 0; |
2240 | } | 2228 | } |
2241 | 2229 | ||
2242 | static int twl4030_soc_resume(struct platform_device *pdev) | 2230 | static int twl4030_soc_resume(struct snd_soc_codec *codec) |
2243 | { | 2231 | { |
2244 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2245 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2246 | |||
2247 | twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 2232 | twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
2248 | return 0; | 2233 | return 0; |
2249 | } | 2234 | } |
2250 | 2235 | ||
2251 | static struct snd_soc_codec *twl4030_codec; | 2236 | static int twl4030_soc_probe(struct snd_soc_codec *codec) |
2252 | |||
2253 | static int twl4030_soc_probe(struct platform_device *pdev) | ||
2254 | { | 2237 | { |
2255 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 2238 | struct twl4030_priv *twl4030; |
2256 | struct snd_soc_codec *codec; | ||
2257 | int ret; | ||
2258 | |||
2259 | BUG_ON(!twl4030_codec); | ||
2260 | |||
2261 | codec = twl4030_codec; | ||
2262 | socdev->card->codec = codec; | ||
2263 | |||
2264 | twl4030_init_chip(pdev); | ||
2265 | 2239 | ||
2266 | /* register pcms */ | 2240 | twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); |
2267 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 2241 | if (twl4030 == NULL) { |
2268 | if (ret < 0) { | 2242 | printk("Can not allocate memroy\n"); |
2269 | dev_err(&pdev->dev, "failed to create pcms\n"); | 2243 | return -ENOMEM; |
2270 | return ret; | ||
2271 | } | 2244 | } |
2245 | snd_soc_codec_set_drvdata(codec, twl4030); | ||
2246 | /* Set the defaults, and power up the codec */ | ||
2247 | twl4030->sysclk = twl4030_codec_get_mclk() / 1000; | ||
2248 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
2249 | codec->idle_bias_off = 1; | ||
2250 | |||
2251 | twl4030_init_chip(codec); | ||
2272 | 2252 | ||
2273 | snd_soc_add_controls(codec, twl4030_snd_controls, | 2253 | snd_soc_add_controls(codec, twl4030_snd_controls, |
2274 | ARRAY_SIZE(twl4030_snd_controls)); | 2254 | ARRAY_SIZE(twl4030_snd_controls)); |
2275 | twl4030_add_widgets(codec); | 2255 | twl4030_add_widgets(codec); |
2276 | |||
2277 | return 0; | 2256 | return 0; |
2278 | } | 2257 | } |
2279 | 2258 | ||
2280 | static int twl4030_soc_remove(struct platform_device *pdev) | 2259 | static int twl4030_soc_remove(struct snd_soc_codec *codec) |
2281 | { | 2260 | { |
2282 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2283 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2284 | |||
2285 | /* Reset registers to their chip default before leaving */ | ||
2286 | twl4030_reset_registers(codec); | ||
2287 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2261 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2288 | snd_soc_free_pcms(socdev); | ||
2289 | snd_soc_dapm_free(socdev); | ||
2290 | |||
2291 | return 0; | 2262 | return 0; |
2292 | } | 2263 | } |
2293 | 2264 | ||
2265 | static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { | ||
2266 | .probe = twl4030_soc_probe, | ||
2267 | .remove = twl4030_soc_remove, | ||
2268 | .suspend = twl4030_soc_suspend, | ||
2269 | .resume = twl4030_soc_resume, | ||
2270 | .read = twl4030_read_reg_cache, | ||
2271 | .write = twl4030_write, | ||
2272 | .set_bias_level = twl4030_set_bias_level, | ||
2273 | .reg_cache_size = sizeof(twl4030_reg), | ||
2274 | .reg_word_size = sizeof(u8), | ||
2275 | .reg_cache_default = twl4030_reg, | ||
2276 | }; | ||
2277 | |||
2294 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) | 2278 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) |
2295 | { | 2279 | { |
2296 | struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data; | 2280 | struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data; |
2297 | struct snd_soc_codec *codec; | ||
2298 | struct twl4030_priv *twl4030; | ||
2299 | int ret; | ||
2300 | 2281 | ||
2301 | if (!pdata) { | 2282 | if (!pdata) { |
2302 | dev_err(&pdev->dev, "platform_data is missing\n"); | 2283 | dev_err(&pdev->dev, "platform_data is missing\n"); |
2303 | return -EINVAL; | 2284 | return -EINVAL; |
2304 | } | 2285 | } |
2305 | 2286 | ||
2306 | twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); | 2287 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030, |
2307 | if (twl4030 == NULL) { | 2288 | twl4030_dai, ARRAY_SIZE(twl4030_dai)); |
2308 | dev_err(&pdev->dev, "Can not allocate memroy\n"); | ||
2309 | return -ENOMEM; | ||
2310 | } | ||
2311 | |||
2312 | codec = &twl4030->codec; | ||
2313 | snd_soc_codec_set_drvdata(codec, twl4030); | ||
2314 | codec->dev = &pdev->dev; | ||
2315 | twl4030_dai[0].dev = &pdev->dev; | ||
2316 | twl4030_dai[1].dev = &pdev->dev; | ||
2317 | |||
2318 | mutex_init(&codec->mutex); | ||
2319 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
2320 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
2321 | |||
2322 | codec->name = "twl4030"; | ||
2323 | codec->owner = THIS_MODULE; | ||
2324 | codec->read = twl4030_read_reg_cache; | ||
2325 | codec->write = twl4030_write; | ||
2326 | codec->set_bias_level = twl4030_set_bias_level; | ||
2327 | codec->idle_bias_off = 1; | ||
2328 | codec->dai = twl4030_dai; | ||
2329 | codec->num_dai = ARRAY_SIZE(twl4030_dai); | ||
2330 | codec->reg_cache_size = sizeof(twl4030_reg); | ||
2331 | codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg), | ||
2332 | GFP_KERNEL); | ||
2333 | if (codec->reg_cache == NULL) { | ||
2334 | ret = -ENOMEM; | ||
2335 | goto error_cache; | ||
2336 | } | ||
2337 | |||
2338 | platform_set_drvdata(pdev, twl4030); | ||
2339 | twl4030_codec = codec; | ||
2340 | |||
2341 | /* Set the defaults, and power up the codec */ | ||
2342 | twl4030->sysclk = twl4030_codec_get_mclk() / 1000; | ||
2343 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
2344 | |||
2345 | ret = snd_soc_register_codec(codec); | ||
2346 | if (ret != 0) { | ||
2347 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
2348 | goto error_codec; | ||
2349 | } | ||
2350 | |||
2351 | ret = snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); | ||
2352 | if (ret != 0) { | ||
2353 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
2354 | snd_soc_unregister_codec(codec); | ||
2355 | goto error_codec; | ||
2356 | } | ||
2357 | |||
2358 | return 0; | ||
2359 | |||
2360 | error_codec: | ||
2361 | twl4030_codec_enable(codec, 0); | ||
2362 | kfree(codec->reg_cache); | ||
2363 | error_cache: | ||
2364 | kfree(twl4030); | ||
2365 | return ret; | ||
2366 | } | 2289 | } |
2367 | 2290 | ||
2368 | static int __devexit twl4030_codec_remove(struct platform_device *pdev) | 2291 | static int __devexit twl4030_codec_remove(struct platform_device *pdev) |
2369 | { | 2292 | { |
2370 | struct twl4030_priv *twl4030 = platform_get_drvdata(pdev); | 2293 | struct twl4030_priv *twl4030 = dev_get_drvdata(&pdev->dev); |
2371 | 2294 | ||
2372 | snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); | 2295 | snd_soc_unregister_codec(&pdev->dev); |
2373 | snd_soc_unregister_codec(&twl4030->codec); | ||
2374 | kfree(twl4030->codec.reg_cache); | ||
2375 | kfree(twl4030); | 2296 | kfree(twl4030); |
2376 | |||
2377 | twl4030_codec = NULL; | ||
2378 | return 0; | 2297 | return 0; |
2379 | } | 2298 | } |
2380 | 2299 | ||
2381 | MODULE_ALIAS("platform:twl4030_codec_audio"); | 2300 | MODULE_ALIAS("platform:twl4030-codec"); |
2382 | 2301 | ||
2383 | static struct platform_driver twl4030_codec_driver = { | 2302 | static struct platform_driver twl4030_codec_driver = { |
2384 | .probe = twl4030_codec_probe, | 2303 | .probe = twl4030_codec_probe, |
2385 | .remove = __devexit_p(twl4030_codec_remove), | 2304 | .remove = __devexit_p(twl4030_codec_remove), |
2386 | .driver = { | 2305 | .driver = { |
2387 | .name = "twl4030_codec_audio", | 2306 | .name = "twl4030-codec", |
2388 | .owner = THIS_MODULE, | 2307 | .owner = THIS_MODULE, |
2389 | }, | 2308 | }, |
2390 | }; | 2309 | }; |
@@ -2401,14 +2320,6 @@ static void __exit twl4030_exit(void) | |||
2401 | } | 2320 | } |
2402 | module_exit(twl4030_exit); | 2321 | module_exit(twl4030_exit); |
2403 | 2322 | ||
2404 | struct snd_soc_codec_device soc_codec_dev_twl4030 = { | ||
2405 | .probe = twl4030_soc_probe, | ||
2406 | .remove = twl4030_soc_remove, | ||
2407 | .suspend = twl4030_soc_suspend, | ||
2408 | .resume = twl4030_soc_resume, | ||
2409 | }; | ||
2410 | EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030); | ||
2411 | |||
2412 | MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); | 2323 | MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); |
2413 | MODULE_AUTHOR("Steve Sakoman"); | 2324 | MODULE_AUTHOR("Steve Sakoman"); |
2414 | MODULE_LICENSE("GPL"); | 2325 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h deleted file mode 100644 index 6c57430f6e24..000000000000 --- a/sound/soc/codecs/twl4030.h +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | /* | ||
2 | * ALSA SoC TWL4030 codec driver | ||
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 | #ifndef __TWL4030_AUDIO_H__ | ||
23 | #define __TWL4030_AUDIO_H__ | ||
24 | |||
25 | /* Register descriptions are here */ | ||
26 | #include <linux/mfd/twl4030-codec.h> | ||
27 | |||
28 | /* Shadow register used by the audio driver */ | ||
29 | #define TWL4030_REG_SW_SHADOW 0x4A | ||
30 | #define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1) | ||
31 | |||
32 | /* TWL4030_REG_SW_SHADOW (0x4A) Fields */ | ||
33 | #define TWL4030_HFL_EN 0x01 | ||
34 | #define TWL4030_HFR_EN 0x02 | ||
35 | |||
36 | #define TWL4030_DAI_HIFI 0 | ||
37 | #define TWL4030_DAI_VOICE 1 | ||
38 | |||
39 | extern struct snd_soc_dai twl4030_dai[2]; | ||
40 | extern struct snd_soc_codec_device soc_codec_dev_twl4030; | ||
41 | |||
42 | struct twl4030_setup_data { | ||
43 | unsigned int ramp_delay_value; | ||
44 | unsigned int digimic_delay; /* in ms */ | ||
45 | unsigned int sysclk; | ||
46 | unsigned int offset_cncl_path; | ||
47 | unsigned int check_defaults:1; | ||
48 | unsigned int reset_registers:1; | ||
49 | unsigned int hs_extmute:1; | ||
50 | void (*set_hs_extmute)(int mute); | ||
51 | }; | ||
52 | |||
53 | #endif /* End of __TWL4030_AUDIO_H__ */ | ||
54 | |||
55 | |||
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 64a807f1a8a1..10f6e5214511 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -45,7 +45,6 @@ | |||
45 | 45 | ||
46 | /* codec private data */ | 46 | /* codec private data */ |
47 | struct twl6040_data { | 47 | struct twl6040_data { |
48 | struct snd_soc_codec codec; | ||
49 | int audpwron; | 48 | int audpwron; |
50 | int naudint; | 49 | int naudint; |
51 | int codec_powered; | 50 | int codec_powered; |
@@ -770,8 +769,7 @@ static int twl6040_startup(struct snd_pcm_substream *substream, | |||
770 | struct snd_soc_dai *dai) | 769 | struct snd_soc_dai *dai) |
771 | { | 770 | { |
772 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 771 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
773 | struct snd_soc_device *socdev = rtd->socdev; | 772 | struct snd_soc_codec *codec = rtd->codec; |
774 | struct snd_soc_codec *codec = socdev->card->codec; | ||
775 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | 773 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); |
776 | 774 | ||
777 | if (!priv->sysclk) { | 775 | if (!priv->sysclk) { |
@@ -803,8 +801,7 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream, | |||
803 | struct snd_soc_dai *dai) | 801 | struct snd_soc_dai *dai) |
804 | { | 802 | { |
805 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 803 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
806 | struct snd_soc_device *socdev = rtd->socdev; | 804 | struct snd_soc_codec *codec = rtd->codec; |
807 | struct snd_soc_codec *codec = socdev->card->codec; | ||
808 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | 805 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); |
809 | u8 lppllctl; | 806 | u8 lppllctl; |
810 | int rate; | 807 | int rate; |
@@ -839,8 +836,7 @@ static int twl6040_trigger(struct snd_pcm_substream *substream, | |||
839 | int cmd, struct snd_soc_dai *dai) | 836 | int cmd, struct snd_soc_dai *dai) |
840 | { | 837 | { |
841 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 838 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
842 | struct snd_soc_device *socdev = rtd->socdev; | 839 | struct snd_soc_codec *codec = rtd->codec; |
843 | struct snd_soc_codec *codec = socdev->card->codec; | ||
844 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | 840 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); |
845 | 841 | ||
846 | switch (cmd) { | 842 | switch (cmd) { |
@@ -978,8 +974,8 @@ static struct snd_soc_dai_ops twl6040_dai_ops = { | |||
978 | .set_sysclk = twl6040_set_dai_sysclk, | 974 | .set_sysclk = twl6040_set_dai_sysclk, |
979 | }; | 975 | }; |
980 | 976 | ||
981 | struct snd_soc_dai twl6040_dai = { | 977 | static struct snd_soc_dai_driver twl6040_dai = { |
982 | .name = "twl6040", | 978 | .name = "twl6040-hifi", |
983 | .playback = { | 979 | .playback = { |
984 | .stream_name = "Playback", | 980 | .stream_name = "Playback", |
985 | .channels_min = 1, | 981 | .channels_min = 1, |
@@ -996,24 +992,17 @@ struct snd_soc_dai twl6040_dai = { | |||
996 | }, | 992 | }, |
997 | .ops = &twl6040_dai_ops, | 993 | .ops = &twl6040_dai_ops, |
998 | }; | 994 | }; |
999 | EXPORT_SYMBOL_GPL(twl6040_dai); | ||
1000 | 995 | ||
1001 | #ifdef CONFIG_PM | 996 | #ifdef CONFIG_PM |
1002 | static int twl6040_suspend(struct platform_device *pdev, pm_message_t state) | 997 | static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1003 | { | 998 | { |
1004 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1005 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1006 | |||
1007 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); | 999 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1008 | 1000 | ||
1009 | return 0; | 1001 | return 0; |
1010 | } | 1002 | } |
1011 | 1003 | ||
1012 | static int twl6040_resume(struct platform_device *pdev) | 1004 | static int twl6040_resume(struct snd_soc_codec *codec) |
1013 | { | 1005 | { |
1014 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1015 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1016 | |||
1017 | twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1006 | twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1018 | 1007 | ||
1019 | return 0; | 1008 | return 0; |
@@ -1023,68 +1012,9 @@ static int twl6040_resume(struct platform_device *pdev) | |||
1023 | #define twl6040_resume NULL | 1012 | #define twl6040_resume NULL |
1024 | #endif | 1013 | #endif |
1025 | 1014 | ||
1026 | static struct snd_soc_codec *twl6040_codec; | 1015 | static int twl6040_probe(struct snd_soc_codec *codec) |
1027 | |||
1028 | static int twl6040_probe(struct platform_device *pdev) | ||
1029 | { | ||
1030 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1031 | struct snd_soc_codec *codec; | ||
1032 | int ret = 0; | ||
1033 | |||
1034 | BUG_ON(!twl6040_codec); | ||
1035 | |||
1036 | codec = twl6040_codec; | ||
1037 | socdev->card->codec = codec; | ||
1038 | |||
1039 | /* register pcms */ | ||
1040 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1041 | if (ret < 0) { | ||
1042 | dev_err(&pdev->dev, "failed to create pcms\n"); | ||
1043 | return ret; | ||
1044 | } | ||
1045 | |||
1046 | snd_soc_add_controls(codec, twl6040_snd_controls, | ||
1047 | ARRAY_SIZE(twl6040_snd_controls)); | ||
1048 | twl6040_add_widgets(codec); | ||
1049 | |||
1050 | if (ret < 0) { | ||
1051 | dev_err(&pdev->dev, "failed to register card\n"); | ||
1052 | goto card_err; | ||
1053 | } | ||
1054 | |||
1055 | return ret; | ||
1056 | |||
1057 | card_err: | ||
1058 | snd_soc_free_pcms(socdev); | ||
1059 | snd_soc_dapm_free(socdev); | ||
1060 | return ret; | ||
1061 | } | ||
1062 | |||
1063 | static int twl6040_remove(struct platform_device *pdev) | ||
1064 | { | ||
1065 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1066 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1067 | |||
1068 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1069 | snd_soc_free_pcms(socdev); | ||
1070 | snd_soc_dapm_free(socdev); | ||
1071 | kfree(codec); | ||
1072 | |||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | struct snd_soc_codec_device soc_codec_dev_twl6040 = { | ||
1077 | .probe = twl6040_probe, | ||
1078 | .remove = twl6040_remove, | ||
1079 | .suspend = twl6040_suspend, | ||
1080 | .resume = twl6040_resume, | ||
1081 | }; | ||
1082 | EXPORT_SYMBOL_GPL(soc_codec_dev_twl6040); | ||
1083 | |||
1084 | static int __devinit twl6040_codec_probe(struct platform_device *pdev) | ||
1085 | { | 1016 | { |
1086 | struct twl4030_codec_data *twl_codec = pdev->dev.platform_data; | 1017 | struct twl4030_codec_data *twl_codec = codec->dev->platform_data; |
1087 | struct snd_soc_codec *codec; | ||
1088 | struct twl6040_data *priv; | 1018 | struct twl6040_data *priv; |
1089 | int audpwron, naudint; | 1019 | int audpwron, naudint; |
1090 | int ret = 0; | 1020 | int ret = 0; |
@@ -1092,6 +1022,7 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev) | |||
1092 | priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); | 1022 | priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); |
1093 | if (priv == NULL) | 1023 | if (priv == NULL) |
1094 | return -ENOMEM; | 1024 | return -ENOMEM; |
1025 | snd_soc_codec_set_drvdata(codec, priv); | ||
1095 | 1026 | ||
1096 | if (twl_codec) { | 1027 | if (twl_codec) { |
1097 | audpwron = twl_codec->audpwron_gpio; | 1028 | audpwron = twl_codec->audpwron_gpio; |
@@ -1104,29 +1035,6 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev) | |||
1104 | priv->audpwron = audpwron; | 1035 | priv->audpwron = audpwron; |
1105 | priv->naudint = naudint; | 1036 | priv->naudint = naudint; |
1106 | 1037 | ||
1107 | codec = &priv->codec; | ||
1108 | codec->dev = &pdev->dev; | ||
1109 | twl6040_dai.dev = &pdev->dev; | ||
1110 | |||
1111 | codec->name = "twl6040"; | ||
1112 | codec->owner = THIS_MODULE; | ||
1113 | codec->read = twl6040_read_reg_cache; | ||
1114 | codec->write = twl6040_write; | ||
1115 | codec->set_bias_level = twl6040_set_bias_level; | ||
1116 | snd_soc_codec_set_drvdata(codec, priv); | ||
1117 | codec->dai = &twl6040_dai; | ||
1118 | codec->num_dai = 1; | ||
1119 | codec->reg_cache_size = ARRAY_SIZE(twl6040_reg); | ||
1120 | codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg), | ||
1121 | GFP_KERNEL); | ||
1122 | if (codec->reg_cache == NULL) { | ||
1123 | ret = -ENOMEM; | ||
1124 | goto cache_err; | ||
1125 | } | ||
1126 | |||
1127 | mutex_init(&codec->mutex); | ||
1128 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1129 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1130 | init_completion(&priv->ready); | 1038 | init_completion(&priv->ready); |
1131 | 1039 | ||
1132 | if (gpio_is_valid(audpwron)) { | 1040 | if (gpio_is_valid(audpwron)) { |
@@ -1169,23 +1077,12 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev) | |||
1169 | if (ret) | 1077 | if (ret) |
1170 | goto irq_err; | 1078 | goto irq_err; |
1171 | 1079 | ||
1172 | ret = snd_soc_register_codec(codec); | 1080 | snd_soc_add_controls(codec, twl6040_snd_controls, |
1173 | if (ret) | 1081 | ARRAY_SIZE(twl6040_snd_controls)); |
1174 | goto reg_err; | 1082 | twl6040_add_widgets(codec); |
1175 | |||
1176 | twl6040_codec = codec; | ||
1177 | |||
1178 | ret = snd_soc_register_dai(&twl6040_dai); | ||
1179 | if (ret) | ||
1180 | goto dai_err; | ||
1181 | 1083 | ||
1182 | return 0; | 1084 | return 0; |
1183 | 1085 | ||
1184 | dai_err: | ||
1185 | snd_soc_unregister_codec(codec); | ||
1186 | twl6040_codec = NULL; | ||
1187 | reg_err: | ||
1188 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1189 | irq_err: | 1086 | irq_err: |
1190 | if (naudint) | 1087 | if (naudint) |
1191 | free_irq(naudint, codec); | 1088 | free_irq(naudint, codec); |
@@ -1193,36 +1090,57 @@ gpio2_err: | |||
1193 | if (gpio_is_valid(audpwron)) | 1090 | if (gpio_is_valid(audpwron)) |
1194 | gpio_free(audpwron); | 1091 | gpio_free(audpwron); |
1195 | gpio1_err: | 1092 | gpio1_err: |
1196 | kfree(codec->reg_cache); | ||
1197 | cache_err: | ||
1198 | kfree(priv); | 1093 | kfree(priv); |
1199 | return ret; | 1094 | return ret; |
1200 | } | 1095 | } |
1201 | 1096 | ||
1202 | static int __devexit twl6040_codec_remove(struct platform_device *pdev) | 1097 | static int twl6040_remove(struct snd_soc_codec *codec) |
1203 | { | 1098 | { |
1204 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(twl6040_codec); | 1099 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); |
1205 | int audpwron = priv->audpwron; | 1100 | int audpwron = priv->audpwron; |
1206 | int naudint = priv->naudint; | 1101 | int naudint = priv->naudint; |
1207 | 1102 | ||
1103 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1104 | |||
1208 | if (gpio_is_valid(audpwron)) | 1105 | if (gpio_is_valid(audpwron)) |
1209 | gpio_free(audpwron); | 1106 | gpio_free(audpwron); |
1210 | 1107 | ||
1211 | if (naudint) | 1108 | if (naudint) |
1212 | free_irq(naudint, twl6040_codec); | 1109 | free_irq(naudint, codec); |
1213 | 1110 | ||
1214 | snd_soc_unregister_dai(&twl6040_dai); | 1111 | kfree(priv); |
1215 | snd_soc_unregister_codec(twl6040_codec); | ||
1216 | 1112 | ||
1217 | kfree(twl6040_codec); | 1113 | return 0; |
1218 | twl6040_codec = NULL; | 1114 | } |
1219 | 1115 | ||
1116 | static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { | ||
1117 | .probe = twl6040_probe, | ||
1118 | .remove = twl6040_remove, | ||
1119 | .suspend = twl6040_suspend, | ||
1120 | .resume = twl6040_resume, | ||
1121 | .read = twl6040_read_reg_cache, | ||
1122 | .write = twl6040_write, | ||
1123 | .set_bias_level = twl6040_set_bias_level, | ||
1124 | .reg_cache_size = ARRAY_SIZE(twl6040_reg), | ||
1125 | .reg_word_size = sizeof(u8), | ||
1126 | .reg_cache_default = twl6040_reg, | ||
1127 | }; | ||
1128 | |||
1129 | static int __devinit twl6040_codec_probe(struct platform_device *pdev) | ||
1130 | { | ||
1131 | return snd_soc_register_codec(&pdev->dev, | ||
1132 | &soc_codec_dev_twl6040, &twl6040_dai, 1); | ||
1133 | } | ||
1134 | |||
1135 | static int __devexit twl6040_codec_remove(struct platform_device *pdev) | ||
1136 | { | ||
1137 | snd_soc_unregister_codec(&pdev->dev); | ||
1220 | return 0; | 1138 | return 0; |
1221 | } | 1139 | } |
1222 | 1140 | ||
1223 | static struct platform_driver twl6040_codec_driver = { | 1141 | static struct platform_driver twl6040_codec_driver = { |
1224 | .driver = { | 1142 | .driver = { |
1225 | .name = "twl6040_codec", | 1143 | .name = "twl6040-codec", |
1226 | .owner = THIS_MODULE, | 1144 | .owner = THIS_MODULE, |
1227 | }, | 1145 | }, |
1228 | .probe = twl6040_codec_probe, | 1146 | .probe = twl6040_codec_probe, |
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h index c472070a1da2..f7c77fa58a3c 100644 --- a/sound/soc/codecs/twl6040.h +++ b/sound/soc/codecs/twl6040.h | |||
@@ -135,7 +135,4 @@ | |||
135 | #define TWL6040_HPPLL_ID 1 | 135 | #define TWL6040_HPPLL_ID 1 |
136 | #define TWL6040_LPPLL_ID 2 | 136 | #define TWL6040_LPPLL_ID 2 |
137 | 137 | ||
138 | extern struct snd_soc_dai twl6040_dai; | ||
139 | extern struct snd_soc_codec_device soc_codec_dev_twl6040; | ||
140 | |||
141 | #endif /* End of __TWL6040_H__ */ | 138 | #endif /* End of __TWL6040_H__ */ |
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index f3b4c1d6a82d..7540a509a6f5 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c | |||
@@ -161,8 +161,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream, | |||
161 | struct snd_soc_dai *dai) | 161 | struct snd_soc_dai *dai) |
162 | { | 162 | { |
163 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 163 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
164 | struct snd_soc_device *socdev = rtd->socdev; | 164 | struct snd_soc_codec *codec =rtd->codec; |
165 | struct snd_soc_codec *codec = socdev->card->codec; | ||
166 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); | 165 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
167 | struct snd_pcm_runtime *master_runtime; | 166 | struct snd_pcm_runtime *master_runtime; |
168 | 167 | ||
@@ -194,8 +193,7 @@ static void uda134x_shutdown(struct snd_pcm_substream *substream, | |||
194 | struct snd_soc_dai *dai) | 193 | struct snd_soc_dai *dai) |
195 | { | 194 | { |
196 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 195 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
197 | struct snd_soc_device *socdev = rtd->socdev; | 196 | struct snd_soc_codec *codec = rtd->codec; |
198 | struct snd_soc_codec *codec = socdev->card->codec; | ||
199 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); | 197 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
200 | 198 | ||
201 | if (uda134x->master_substream == substream) | 199 | if (uda134x->master_substream == substream) |
@@ -209,8 +207,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, | |||
209 | struct snd_soc_dai *dai) | 207 | struct snd_soc_dai *dai) |
210 | { | 208 | { |
211 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 209 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
212 | struct snd_soc_device *socdev = rtd->socdev; | 210 | struct snd_soc_codec *codec = rtd->codec; |
213 | struct snd_soc_codec *codec = socdev->card->codec; | ||
214 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); | 211 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
215 | u8 hw_params; | 212 | u8 hw_params; |
216 | 213 | ||
@@ -364,7 +361,7 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec, | |||
364 | pd->power(1); | 361 | pd->power(1); |
365 | /* Sync reg_cache with the hardware */ | 362 | /* Sync reg_cache with the hardware */ |
366 | for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++) | 363 | for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++) |
367 | codec->write(codec, i, *cache++); | 364 | codec->driver->write(codec, i, *cache++); |
368 | } | 365 | } |
369 | break; | 366 | break; |
370 | case SND_SOC_BIAS_STANDBY: | 367 | case SND_SOC_BIAS_STANDBY: |
@@ -465,8 +462,8 @@ static struct snd_soc_dai_ops uda134x_dai_ops = { | |||
465 | .set_fmt = uda134x_set_dai_fmt, | 462 | .set_fmt = uda134x_set_dai_fmt, |
466 | }; | 463 | }; |
467 | 464 | ||
468 | struct snd_soc_dai uda134x_dai = { | 465 | static struct snd_soc_dai_driver uda134x_dai = { |
469 | .name = "UDA134X", | 466 | .name = "uda134x-hifi", |
470 | /* playback capabilities */ | 467 | /* playback capabilities */ |
471 | .playback = { | 468 | .playback = { |
472 | .stream_name = "Playback", | 469 | .stream_name = "Playback", |
@@ -486,27 +483,21 @@ struct snd_soc_dai uda134x_dai = { | |||
486 | /* pcm operations */ | 483 | /* pcm operations */ |
487 | .ops = &uda134x_dai_ops, | 484 | .ops = &uda134x_dai_ops, |
488 | }; | 485 | }; |
489 | EXPORT_SYMBOL(uda134x_dai); | ||
490 | 486 | ||
491 | 487 | static int uda134x_soc_probe(struct snd_soc_codec *codec) | |
492 | static int uda134x_soc_probe(struct platform_device *pdev) | ||
493 | { | 488 | { |
494 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
495 | struct snd_soc_codec *codec; | ||
496 | struct uda134x_priv *uda134x; | 489 | struct uda134x_priv *uda134x; |
497 | void *codec_setup_data = socdev->codec_data; | 490 | struct uda134x_platform_data *pd = dev_get_drvdata(codec->card->dev); |
498 | int ret = -ENOMEM; | 491 | int ret; |
499 | struct uda134x_platform_data *pd; | ||
500 | 492 | ||
501 | printk(KERN_INFO "UDA134X SoC Audio Codec\n"); | 493 | printk(KERN_INFO "UDA134X SoC Audio Codec\n"); |
502 | 494 | ||
503 | if (!codec_setup_data) { | 495 | if (!pd) { |
504 | printk(KERN_ERR "UDA134X SoC codec: " | 496 | printk(KERN_ERR "UDA134X SoC codec: " |
505 | "missing L3 bitbang function\n"); | 497 | "missing L3 bitbang function\n"); |
506 | return -ENODEV; | 498 | return -ENODEV; |
507 | } | 499 | } |
508 | 500 | ||
509 | pd = codec_setup_data; | ||
510 | switch (pd->model) { | 501 | switch (pd->model) { |
511 | case UDA134X_UDA1340: | 502 | case UDA134X_UDA1340: |
512 | case UDA134X_UDA1341: | 503 | case UDA134X_UDA1341: |
@@ -520,58 +511,22 @@ static int uda134x_soc_probe(struct platform_device *pdev) | |||
520 | return -EINVAL; | 511 | return -EINVAL; |
521 | } | 512 | } |
522 | 513 | ||
523 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
524 | if (socdev->card->codec == NULL) | ||
525 | return ret; | ||
526 | |||
527 | codec = socdev->card->codec; | ||
528 | |||
529 | uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); | 514 | uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); |
530 | if (uda134x == NULL) | 515 | if (uda134x == NULL) |
531 | goto priv_err; | 516 | return -ENOMEM; |
532 | snd_soc_codec_set_drvdata(codec, uda134x); | 517 | snd_soc_codec_set_drvdata(codec, uda134x); |
533 | 518 | ||
534 | codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg), | 519 | codec->control_data = pd; |
535 | GFP_KERNEL); | ||
536 | if (codec->reg_cache == NULL) | ||
537 | goto reg_err; | ||
538 | |||
539 | mutex_init(&codec->mutex); | ||
540 | |||
541 | codec->reg_cache_size = sizeof(uda134x_reg); | ||
542 | codec->reg_cache_step = 1; | ||
543 | |||
544 | codec->name = "UDA134X"; | ||
545 | codec->owner = THIS_MODULE; | ||
546 | codec->dai = &uda134x_dai; | ||
547 | codec->num_dai = 1; | ||
548 | codec->read = uda134x_read_reg_cache; | ||
549 | codec->write = uda134x_write; | ||
550 | |||
551 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
552 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
553 | |||
554 | codec->control_data = codec_setup_data; | ||
555 | 520 | ||
556 | if (pd->power) | 521 | if (pd->power) |
557 | pd->power(1); | 522 | pd->power(1); |
558 | 523 | ||
559 | uda134x_reset(codec); | 524 | uda134x_reset(codec); |
560 | 525 | ||
561 | if (pd->is_powered_on_standby) { | 526 | if (pd->is_powered_on_standby) |
562 | codec->set_bias_level = NULL; | ||
563 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); | 527 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); |
564 | } else { | 528 | else |
565 | codec->set_bias_level = uda134x_set_bias_level; | ||
566 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 529 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
567 | } | ||
568 | |||
569 | /* register pcms */ | ||
570 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
571 | if (ret < 0) { | ||
572 | printk(KERN_ERR "UDA134X: failed to register pcms\n"); | ||
573 | goto pcm_err; | ||
574 | } | ||
575 | 530 | ||
576 | switch (pd->model) { | 531 | switch (pd->model) { |
577 | case UDA134X_UDA1340: | 532 | case UDA134X_UDA1340: |
@@ -590,61 +545,42 @@ static int uda134x_soc_probe(struct platform_device *pdev) | |||
590 | default: | 545 | default: |
591 | printk(KERN_ERR "%s unknown codec type: %d", | 546 | printk(KERN_ERR "%s unknown codec type: %d", |
592 | __func__, pd->model); | 547 | __func__, pd->model); |
593 | return -EINVAL; | 548 | kfree(uda134x); |
549 | return -EINVAL; | ||
594 | } | 550 | } |
595 | 551 | ||
596 | if (ret < 0) { | 552 | if (ret < 0) { |
597 | printk(KERN_ERR "UDA134X: failed to register controls\n"); | 553 | printk(KERN_ERR "UDA134X: failed to register controls\n"); |
598 | goto pcm_err; | 554 | kfree(uda134x); |
555 | return ret; | ||
599 | } | 556 | } |
600 | 557 | ||
601 | return 0; | 558 | return 0; |
602 | |||
603 | pcm_err: | ||
604 | kfree(codec->reg_cache); | ||
605 | reg_err: | ||
606 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
607 | priv_err: | ||
608 | kfree(codec); | ||
609 | return ret; | ||
610 | } | 559 | } |
611 | 560 | ||
612 | /* power down chip */ | 561 | /* power down chip */ |
613 | static int uda134x_soc_remove(struct platform_device *pdev) | 562 | static int uda134x_soc_remove(struct snd_soc_codec *codec) |
614 | { | 563 | { |
615 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 564 | struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); |
616 | struct snd_soc_codec *codec = socdev->card->codec; | ||
617 | 565 | ||
618 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 566 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
619 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 567 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
620 | 568 | ||
621 | snd_soc_free_pcms(socdev); | 569 | kfree(uda134x); |
622 | snd_soc_dapm_free(socdev); | ||
623 | |||
624 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
625 | kfree(codec->reg_cache); | ||
626 | kfree(codec); | ||
627 | |||
628 | return 0; | 570 | return 0; |
629 | } | 571 | } |
630 | 572 | ||
631 | #if defined(CONFIG_PM) | 573 | #if defined(CONFIG_PM) |
632 | static int uda134x_soc_suspend(struct platform_device *pdev, | 574 | static int uda134x_soc_suspend(struct snd_soc_codec *codec, |
633 | pm_message_t state) | 575 | pm_message_t state) |
634 | { | 576 | { |
635 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
636 | struct snd_soc_codec *codec = socdev->card->codec; | ||
637 | |||
638 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 577 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
639 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 578 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
640 | return 0; | 579 | return 0; |
641 | } | 580 | } |
642 | 581 | ||
643 | static int uda134x_soc_resume(struct platform_device *pdev) | 582 | static int uda134x_soc_resume(struct snd_soc_codec *codec) |
644 | { | 583 | { |
645 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
646 | struct snd_soc_codec *codec = socdev->card->codec; | ||
647 | |||
648 | uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | 584 | uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); |
649 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); | 585 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); |
650 | return 0; | 586 | return 0; |
@@ -654,25 +590,53 @@ static int uda134x_soc_resume(struct platform_device *pdev) | |||
654 | #define uda134x_soc_resume NULL | 590 | #define uda134x_soc_resume NULL |
655 | #endif /* CONFIG_PM */ | 591 | #endif /* CONFIG_PM */ |
656 | 592 | ||
657 | struct snd_soc_codec_device soc_codec_dev_uda134x = { | 593 | static struct snd_soc_codec_driver soc_codec_dev_uda134x = { |
658 | .probe = uda134x_soc_probe, | 594 | .probe = uda134x_soc_probe, |
659 | .remove = uda134x_soc_remove, | 595 | .remove = uda134x_soc_remove, |
660 | .suspend = uda134x_soc_suspend, | 596 | .suspend = uda134x_soc_suspend, |
661 | .resume = uda134x_soc_resume, | 597 | .resume = uda134x_soc_resume, |
598 | .reg_cache_size = sizeof(uda134x_reg), | ||
599 | .reg_word_size = sizeof(u8), | ||
600 | .reg_cache_step = 1, | ||
601 | .read = uda134x_read_reg_cache, | ||
602 | .write = uda134x_write, | ||
603 | #ifdef POWER_OFF_ON_STANDBY | ||
604 | .set_bias_level = uda134x_set_bias_level, | ||
605 | #endif | ||
606 | }; | ||
607 | |||
608 | static int __devinit uda134x_codec_probe(struct platform_device *pdev) | ||
609 | { | ||
610 | return snd_soc_register_codec(&pdev->dev, | ||
611 | &soc_codec_dev_uda134x, &uda134x_dai, 1); | ||
612 | } | ||
613 | |||
614 | static int __devexit uda134x_codec_remove(struct platform_device *pdev) | ||
615 | { | ||
616 | snd_soc_unregister_codec(&pdev->dev); | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | static struct platform_driver uda134x_codec_driver = { | ||
621 | .driver = { | ||
622 | .name = "uda134x-codec", | ||
623 | .owner = THIS_MODULE, | ||
624 | }, | ||
625 | .probe = uda134x_codec_probe, | ||
626 | .remove = __devexit_p(uda134x_codec_remove), | ||
662 | }; | 627 | }; |
663 | EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x); | ||
664 | 628 | ||
665 | static int __init uda134x_init(void) | 629 | static int __init uda134x_codec_init(void) |
666 | { | 630 | { |
667 | return snd_soc_register_dai(&uda134x_dai); | 631 | return platform_driver_register(&uda134x_codec_driver); |
668 | } | 632 | } |
669 | module_init(uda134x_init); | 633 | module_init(uda134x_codec_init); |
670 | 634 | ||
671 | static void __exit uda134x_exit(void) | 635 | static void __exit uda134x_codec_exit(void) |
672 | { | 636 | { |
673 | snd_soc_unregister_dai(&uda134x_dai); | 637 | platform_driver_unregister(&uda134x_codec_driver); |
674 | } | 638 | } |
675 | module_exit(uda134x_exit); | 639 | module_exit(uda134x_codec_exit); |
676 | 640 | ||
677 | MODULE_DESCRIPTION("UDA134X ALSA soc codec driver"); | 641 | MODULE_DESCRIPTION("UDA134X ALSA soc codec driver"); |
678 | MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>"); | 642 | MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>"); |
diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h index 205f03b3eaf8..9faae06972b3 100644 --- a/sound/soc/codecs/uda134x.h +++ b/sound/soc/codecs/uda134x.h | |||
@@ -31,7 +31,4 @@ | |||
31 | #define STATUS0_DAIFMT_MASK (~(7<<1)) | 31 | #define STATUS0_DAIFMT_MASK (~(7<<1)) |
32 | #define STATUS0_SYSCLK_MASK (~(3<<4)) | 32 | #define STATUS0_SYSCLK_MASK (~(3<<4)) |
33 | 33 | ||
34 | extern struct snd_soc_dai uda134x_dai; | ||
35 | extern struct snd_soc_codec_device soc_codec_dev_uda134x; | ||
36 | |||
37 | #endif | 34 | #endif |
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 2f925a27dcde..1a51c816e542 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c | |||
@@ -33,11 +33,9 @@ | |||
33 | 33 | ||
34 | #include "uda1380.h" | 34 | #include "uda1380.h" |
35 | 35 | ||
36 | static struct snd_soc_codec *uda1380_codec; | ||
37 | |||
38 | /* codec private data */ | 36 | /* codec private data */ |
39 | struct uda1380_priv { | 37 | struct uda1380_priv { |
40 | struct snd_soc_codec codec; | 38 | struct snd_soc_codec *codec; |
41 | u16 reg_cache[UDA1380_CACHEREGNUM]; | 39 | u16 reg_cache[UDA1380_CACHEREGNUM]; |
42 | unsigned int dac_clk; | 40 | unsigned int dac_clk; |
43 | struct work_struct work; | 41 | struct work_struct work; |
@@ -135,6 +133,8 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, | |||
135 | 133 | ||
136 | static void uda1380_flush_work(struct work_struct *work) | 134 | static void uda1380_flush_work(struct work_struct *work) |
137 | { | 135 | { |
136 | struct uda1380_priv *uda1380 = container_of(work, struct uda1380_priv, work); | ||
137 | struct snd_soc_codec *uda1380_codec = uda1380->codec; | ||
138 | int bit, reg; | 138 | int bit, reg; |
139 | 139 | ||
140 | for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { | 140 | for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { |
@@ -145,6 +145,7 @@ static void uda1380_flush_work(struct work_struct *work) | |||
145 | uda1380_read_reg_cache(uda1380_codec, reg)); | 145 | uda1380_read_reg_cache(uda1380_codec, reg)); |
146 | clear_bit(bit, &uda1380_cache_dirty); | 146 | clear_bit(bit, &uda1380_cache_dirty); |
147 | } | 147 | } |
148 | |||
148 | } | 149 | } |
149 | 150 | ||
150 | /* declarations of ALSA reg_elem_REAL controls */ | 151 | /* declarations of ALSA reg_elem_REAL controls */ |
@@ -474,8 +475,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, | |||
474 | struct snd_soc_dai *dai) | 475 | struct snd_soc_dai *dai) |
475 | { | 476 | { |
476 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 477 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
477 | struct snd_soc_device *socdev = rtd->socdev; | 478 | struct snd_soc_codec *codec = rtd->codec; |
478 | struct snd_soc_codec *codec = socdev->card->codec; | ||
479 | struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); | 479 | struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); |
480 | int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); | 480 | int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); |
481 | 481 | ||
@@ -501,8 +501,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, | |||
501 | struct snd_soc_dai *dai) | 501 | struct snd_soc_dai *dai) |
502 | { | 502 | { |
503 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 503 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
504 | struct snd_soc_device *socdev = rtd->socdev; | 504 | struct snd_soc_codec *codec = rtd->codec; |
505 | struct snd_soc_codec *codec = socdev->card->codec; | ||
506 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); | 505 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); |
507 | 506 | ||
508 | /* set WSPLL power and divider if running from this clock */ | 507 | /* set WSPLL power and divider if running from this clock */ |
@@ -540,8 +539,7 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, | |||
540 | struct snd_soc_dai *dai) | 539 | struct snd_soc_dai *dai) |
541 | { | 540 | { |
542 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 541 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
543 | struct snd_soc_device *socdev = rtd->socdev; | 542 | struct snd_soc_codec *codec = rtd->codec; |
544 | struct snd_soc_codec *codec = socdev->card->codec; | ||
545 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); | 543 | u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); |
546 | 544 | ||
547 | /* shut down WSPLL power if running from this clock */ | 545 | /* shut down WSPLL power if running from this clock */ |
@@ -604,9 +602,9 @@ static struct snd_soc_dai_ops uda1380_dai_ops_capture = { | |||
604 | .set_fmt = uda1380_set_dai_fmt_capture, | 602 | .set_fmt = uda1380_set_dai_fmt_capture, |
605 | }; | 603 | }; |
606 | 604 | ||
607 | struct snd_soc_dai uda1380_dai[] = { | 605 | static struct snd_soc_dai_driver uda1380_dai[] = { |
608 | { | 606 | { |
609 | .name = "UDA1380", | 607 | .name = "uda1380-hifi", |
610 | .playback = { | 608 | .playback = { |
611 | .stream_name = "Playback", | 609 | .stream_name = "Playback", |
612 | .channels_min = 1, | 610 | .channels_min = 1, |
@@ -622,7 +620,7 @@ struct snd_soc_dai uda1380_dai[] = { | |||
622 | .ops = &uda1380_dai_ops, | 620 | .ops = &uda1380_dai_ops, |
623 | }, | 621 | }, |
624 | { /* playback only - dual interface */ | 622 | { /* playback only - dual interface */ |
625 | .name = "UDA1380", | 623 | .name = "uda1380-hifi-playback", |
626 | .playback = { | 624 | .playback = { |
627 | .stream_name = "Playback", | 625 | .stream_name = "Playback", |
628 | .channels_min = 1, | 626 | .channels_min = 1, |
@@ -633,7 +631,7 @@ struct snd_soc_dai uda1380_dai[] = { | |||
633 | .ops = &uda1380_dai_ops_playback, | 631 | .ops = &uda1380_dai_ops_playback, |
634 | }, | 632 | }, |
635 | { /* capture only - dual interface*/ | 633 | { /* capture only - dual interface*/ |
636 | .name = "UDA1380", | 634 | .name = "uda1380-hifi-capture", |
637 | .capture = { | 635 | .capture = { |
638 | .stream_name = "Capture", | 636 | .stream_name = "Capture", |
639 | .channels_min = 1, | 637 | .channels_min = 1, |
@@ -644,21 +642,15 @@ struct snd_soc_dai uda1380_dai[] = { | |||
644 | .ops = &uda1380_dai_ops_capture, | 642 | .ops = &uda1380_dai_ops_capture, |
645 | }, | 643 | }, |
646 | }; | 644 | }; |
647 | EXPORT_SYMBOL_GPL(uda1380_dai); | ||
648 | 645 | ||
649 | static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) | 646 | static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state) |
650 | { | 647 | { |
651 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
652 | struct snd_soc_codec *codec = socdev->card->codec; | ||
653 | |||
654 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); | 648 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); |
655 | return 0; | 649 | return 0; |
656 | } | 650 | } |
657 | 651 | ||
658 | static int uda1380_resume(struct platform_device *pdev) | 652 | static int uda1380_resume(struct snd_soc_codec *codec) |
659 | { | 653 | { |
660 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
661 | struct snd_soc_codec *codec = socdev->card->codec; | ||
662 | int i; | 654 | int i; |
663 | u8 data[2]; | 655 | u8 data[2]; |
664 | u16 *cache = codec->reg_cache; | 656 | u16 *cache = codec->reg_cache; |
@@ -673,91 +665,20 @@ static int uda1380_resume(struct platform_device *pdev) | |||
673 | return 0; | 665 | return 0; |
674 | } | 666 | } |
675 | 667 | ||
676 | static int uda1380_probe(struct platform_device *pdev) | 668 | static int uda1380_probe(struct snd_soc_codec *codec) |
677 | { | ||
678 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
679 | struct snd_soc_codec *codec; | ||
680 | struct uda1380_platform_data *pdata; | ||
681 | int ret = 0; | ||
682 | |||
683 | if (uda1380_codec == NULL) { | ||
684 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
685 | return -ENODEV; | ||
686 | } | ||
687 | |||
688 | socdev->card->codec = uda1380_codec; | ||
689 | codec = uda1380_codec; | ||
690 | pdata = codec->dev->platform_data; | ||
691 | |||
692 | /* register pcms */ | ||
693 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
694 | if (ret < 0) { | ||
695 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
696 | goto pcm_err; | ||
697 | } | ||
698 | |||
699 | /* power on device */ | ||
700 | uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
701 | /* set clock input */ | ||
702 | switch (pdata->dac_clk) { | ||
703 | case UDA1380_DAC_CLK_SYSCLK: | ||
704 | uda1380_write(codec, UDA1380_CLK, 0); | ||
705 | break; | ||
706 | case UDA1380_DAC_CLK_WSPLL: | ||
707 | uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); | ||
708 | break; | ||
709 | } | ||
710 | |||
711 | snd_soc_add_controls(codec, uda1380_snd_controls, | ||
712 | ARRAY_SIZE(uda1380_snd_controls)); | ||
713 | uda1380_add_widgets(codec); | ||
714 | |||
715 | return ret; | ||
716 | |||
717 | pcm_err: | ||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | /* power down chip */ | ||
722 | static int uda1380_remove(struct platform_device *pdev) | ||
723 | { | ||
724 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
725 | struct snd_soc_codec *codec = socdev->card->codec; | ||
726 | |||
727 | if (codec->control_data) | ||
728 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
729 | |||
730 | snd_soc_free_pcms(socdev); | ||
731 | snd_soc_dapm_free(socdev); | ||
732 | |||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | struct snd_soc_codec_device soc_codec_dev_uda1380 = { | ||
737 | .probe = uda1380_probe, | ||
738 | .remove = uda1380_remove, | ||
739 | .suspend = uda1380_suspend, | ||
740 | .resume = uda1380_resume, | ||
741 | }; | ||
742 | EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); | ||
743 | |||
744 | static int uda1380_register(struct uda1380_priv *uda1380) | ||
745 | { | 669 | { |
746 | int ret, i; | 670 | struct uda1380_platform_data *pdata =codec->dev->platform_data; |
747 | struct snd_soc_codec *codec = &uda1380->codec; | 671 | struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); |
748 | struct uda1380_platform_data *pdata = codec->dev->platform_data; | 672 | int ret; |
749 | 673 | ||
750 | if (uda1380_codec) { | 674 | codec->hw_write = (hw_write_t)i2c_master_send; |
751 | dev_err(codec->dev, "Another UDA1380 is registered\n"); | ||
752 | return -EINVAL; | ||
753 | } | ||
754 | 675 | ||
755 | if (!pdata || !pdata->gpio_power || !pdata->gpio_reset) | 676 | if (!pdata || !pdata->gpio_power || !pdata->gpio_reset) |
756 | return -EINVAL; | 677 | return -EINVAL; |
757 | 678 | ||
758 | ret = gpio_request(pdata->gpio_power, "uda1380 power"); | 679 | ret = gpio_request(pdata->gpio_power, "uda1380 power"); |
759 | if (ret) | 680 | if (ret) |
760 | goto err_out; | 681 | return ret; |
761 | ret = gpio_request(pdata->gpio_reset, "uda1380 reset"); | 682 | ret = gpio_request(pdata->gpio_reset, "uda1380 reset"); |
762 | if (ret) | 683 | if (ret) |
763 | goto err_gpio; | 684 | goto err_gpio; |
@@ -769,25 +690,6 @@ static int uda1380_register(struct uda1380_priv *uda1380) | |||
769 | udelay(5); | 690 | udelay(5); |
770 | gpio_set_value(pdata->gpio_reset, 0); | 691 | gpio_set_value(pdata->gpio_reset, 0); |
771 | 692 | ||
772 | mutex_init(&codec->mutex); | ||
773 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
774 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
775 | |||
776 | snd_soc_codec_set_drvdata(codec, uda1380); | ||
777 | codec->name = "UDA1380"; | ||
778 | codec->owner = THIS_MODULE; | ||
779 | codec->read = uda1380_read_reg_cache; | ||
780 | codec->write = uda1380_write; | ||
781 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
782 | codec->set_bias_level = uda1380_set_bias_level; | ||
783 | codec->dai = uda1380_dai; | ||
784 | codec->num_dai = ARRAY_SIZE(uda1380_dai); | ||
785 | codec->reg_cache_size = ARRAY_SIZE(uda1380_reg); | ||
786 | codec->reg_cache = &uda1380->reg_cache; | ||
787 | codec->reg_cache_step = 1; | ||
788 | |||
789 | memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg)); | ||
790 | |||
791 | ret = uda1380_reset(codec); | 693 | ret = uda1380_reset(codec); |
792 | if (ret < 0) { | 694 | if (ret < 0) { |
793 | dev_err(codec->dev, "Failed to issue reset\n"); | 695 | dev_err(codec->dev, "Failed to issue reset\n"); |
@@ -796,83 +698,84 @@ static int uda1380_register(struct uda1380_priv *uda1380) | |||
796 | 698 | ||
797 | INIT_WORK(&uda1380->work, uda1380_flush_work); | 699 | INIT_WORK(&uda1380->work, uda1380_flush_work); |
798 | 700 | ||
799 | for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++) | 701 | /* power on device */ |
800 | uda1380_dai[i].dev = codec->dev; | 702 | uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
801 | 703 | /* set clock input */ | |
802 | uda1380_codec = codec; | 704 | switch (pdata->dac_clk) { |
803 | 705 | case UDA1380_DAC_CLK_SYSCLK: | |
804 | ret = snd_soc_register_codec(codec); | 706 | uda1380_write(codec, UDA1380_CLK, 0); |
805 | if (ret != 0) { | 707 | break; |
806 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | 708 | case UDA1380_DAC_CLK_WSPLL: |
807 | goto err_reset; | 709 | uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); |
710 | break; | ||
808 | } | 711 | } |
809 | 712 | ||
810 | ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); | 713 | snd_soc_add_controls(codec, uda1380_snd_controls, |
811 | if (ret != 0) { | 714 | ARRAY_SIZE(uda1380_snd_controls)); |
812 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | 715 | uda1380_add_widgets(codec); |
813 | goto err_dai; | ||
814 | } | ||
815 | 716 | ||
816 | return 0; | 717 | return 0; |
817 | 718 | ||
818 | err_dai: | ||
819 | snd_soc_unregister_codec(codec); | ||
820 | err_reset: | 719 | err_reset: |
821 | gpio_set_value(pdata->gpio_power, 0); | 720 | gpio_set_value(pdata->gpio_power, 0); |
822 | gpio_free(pdata->gpio_reset); | 721 | gpio_free(pdata->gpio_reset); |
823 | err_gpio: | 722 | err_gpio: |
824 | gpio_free(pdata->gpio_power); | 723 | gpio_free(pdata->gpio_power); |
825 | err_out: | ||
826 | return ret; | 724 | return ret; |
827 | } | 725 | } |
828 | 726 | ||
829 | static void uda1380_unregister(struct uda1380_priv *uda1380) | 727 | /* power down chip */ |
728 | static int uda1380_remove(struct snd_soc_codec *codec) | ||
830 | { | 729 | { |
831 | struct snd_soc_codec *codec = &uda1380->codec; | 730 | struct uda1380_platform_data *pdata =codec->dev->platform_data; |
832 | struct uda1380_platform_data *pdata = codec->dev->platform_data; | ||
833 | 731 | ||
834 | snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); | 732 | uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); |
835 | snd_soc_unregister_codec(&uda1380->codec); | ||
836 | 733 | ||
837 | gpio_set_value(pdata->gpio_power, 0); | 734 | gpio_set_value(pdata->gpio_power, 0); |
838 | gpio_free(pdata->gpio_reset); | 735 | gpio_free(pdata->gpio_reset); |
839 | gpio_free(pdata->gpio_power); | 736 | gpio_free(pdata->gpio_power); |
840 | 737 | ||
841 | kfree(uda1380); | 738 | return 0; |
842 | uda1380_codec = NULL; | ||
843 | } | 739 | } |
844 | 740 | ||
741 | static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { | ||
742 | .probe = uda1380_probe, | ||
743 | .remove = uda1380_remove, | ||
744 | .suspend = uda1380_suspend, | ||
745 | .resume = uda1380_resume, | ||
746 | .read = uda1380_read_reg_cache, | ||
747 | .write = uda1380_write, | ||
748 | .set_bias_level = uda1380_set_bias_level, | ||
749 | .reg_cache_size = ARRAY_SIZE(uda1380_reg), | ||
750 | .reg_word_size = sizeof(u16), | ||
751 | .reg_cache_default = uda1380_reg, | ||
752 | .reg_cache_step = 1, | ||
753 | }; | ||
754 | |||
845 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 755 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
846 | static __devinit int uda1380_i2c_probe(struct i2c_client *i2c, | 756 | static __devinit int uda1380_i2c_probe(struct i2c_client *i2c, |
847 | const struct i2c_device_id *id) | 757 | const struct i2c_device_id *id) |
848 | { | 758 | { |
849 | struct uda1380_priv *uda1380; | 759 | struct uda1380_priv *uda1380; |
850 | struct snd_soc_codec *codec; | ||
851 | int ret; | 760 | int ret; |
852 | 761 | ||
853 | uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL); | 762 | uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL); |
854 | if (uda1380 == NULL) | 763 | if (uda1380 == NULL) |
855 | return -ENOMEM; | 764 | return -ENOMEM; |
856 | 765 | ||
857 | codec = &uda1380->codec; | ||
858 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
859 | |||
860 | i2c_set_clientdata(i2c, uda1380); | 766 | i2c_set_clientdata(i2c, uda1380); |
861 | codec->control_data = i2c; | ||
862 | |||
863 | codec->dev = &i2c->dev; | ||
864 | 767 | ||
865 | ret = uda1380_register(uda1380); | 768 | ret = snd_soc_register_codec(&i2c->dev, |
866 | if (ret != 0) | 769 | &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai)); |
770 | if (ret < 0) | ||
867 | kfree(uda1380); | 771 | kfree(uda1380); |
868 | |||
869 | return ret; | 772 | return ret; |
870 | } | 773 | } |
871 | 774 | ||
872 | static int __devexit uda1380_i2c_remove(struct i2c_client *i2c) | 775 | static int __devexit uda1380_i2c_remove(struct i2c_client *i2c) |
873 | { | 776 | { |
874 | struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c); | 777 | snd_soc_unregister_codec(&i2c->dev); |
875 | uda1380_unregister(uda1380); | 778 | kfree(i2c_get_clientdata(i2c)); |
876 | return 0; | 779 | return 0; |
877 | } | 780 | } |
878 | 781 | ||
@@ -884,7 +787,7 @@ MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); | |||
884 | 787 | ||
885 | static struct i2c_driver uda1380_i2c_driver = { | 788 | static struct i2c_driver uda1380_i2c_driver = { |
886 | .driver = { | 789 | .driver = { |
887 | .name = "UDA1380 I2C Codec", | 790 | .name = "uda1380-codec", |
888 | .owner = THIS_MODULE, | 791 | .owner = THIS_MODULE, |
889 | }, | 792 | }, |
890 | .probe = uda1380_i2c_probe, | 793 | .probe = uda1380_i2c_probe, |
diff --git a/sound/soc/codecs/uda1380.h b/sound/soc/codecs/uda1380.h index 9cefa8a54770..942e3927c72b 100644 --- a/sound/soc/codecs/uda1380.h +++ b/sound/soc/codecs/uda1380.h | |||
@@ -76,7 +76,4 @@ | |||
76 | #define UDA1380_DAI_PLAYBACK 1 /* playback DAI */ | 76 | #define UDA1380_DAI_PLAYBACK 1 /* playback DAI */ |
77 | #define UDA1380_DAI_CAPTURE 2 /* capture DAI */ | 77 | #define UDA1380_DAI_CAPTURE 2 /* capture DAI */ |
78 | 78 | ||
79 | extern struct snd_soc_dai uda1380_dai[3]; | ||
80 | extern struct snd_soc_codec_device soc_codec_dev_uda1380; | ||
81 | |||
82 | #endif /* _UDA1380_H */ | 79 | #endif /* _UDA1380_H */ |
diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h index c18e261c3c7f..0b6f056f73cc 100644 --- a/sound/soc/codecs/wm2000.h +++ b/sound/soc/codecs/wm2000.h | |||
@@ -16,9 +16,6 @@ struct wm2000_setup_data { | |||
16 | 16 | ||
17 | extern int wm2000_add_controls(struct snd_soc_codec *codec); | 17 | extern int wm2000_add_controls(struct snd_soc_codec *codec); |
18 | 18 | ||
19 | extern struct snd_soc_dai wm2000_dai; | ||
20 | extern struct snd_soc_codec_device soc_codec_dev_wm2000; | ||
21 | |||
22 | #define WM2000_REG_SYS_START 0x8000 | 19 | #define WM2000_REG_SYS_START 0x8000 |
23 | #define WM2000_REG_SPEECH_CLARITY 0x8fef | 20 | #define WM2000_REG_SPEECH_CLARITY 0x8fef |
24 | #define WM2000_REG_SYS_WATCHDOG 0x8ff6 | 21 | #define WM2000_REG_SYS_WATCHDOG 0x8ff6 |
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 0221ca79b3ae..f4f1fba38eb9 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -1321,20 +1321,14 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec, | |||
1321 | return 0; | 1321 | return 0; |
1322 | } | 1322 | } |
1323 | 1323 | ||
1324 | static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) | 1324 | static int wm8350_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1325 | { | 1325 | { |
1326 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1327 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1328 | |||
1329 | wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1326 | wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1330 | return 0; | 1327 | return 0; |
1331 | } | 1328 | } |
1332 | 1329 | ||
1333 | static int wm8350_resume(struct platform_device *pdev) | 1330 | static int wm8350_resume(struct snd_soc_codec *codec) |
1334 | { | 1331 | { |
1335 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1336 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1337 | |||
1338 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1332 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1339 | 1333 | ||
1340 | return 0; | 1334 | return 0; |
@@ -1489,24 +1483,74 @@ int wm8350_mic_jack_detect(struct snd_soc_codec *codec, | |||
1489 | } | 1483 | } |
1490 | EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect); | 1484 | EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect); |
1491 | 1485 | ||
1492 | static struct snd_soc_codec *wm8350_codec; | 1486 | #define WM8350_RATES (SNDRV_PCM_RATE_8000_96000) |
1487 | |||
1488 | #define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ | ||
1489 | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
1490 | SNDRV_PCM_FMTBIT_S24_LE) | ||
1491 | |||
1492 | static struct snd_soc_dai_ops wm8350_dai_ops = { | ||
1493 | .hw_params = wm8350_pcm_hw_params, | ||
1494 | .digital_mute = wm8350_mute, | ||
1495 | .trigger = wm8350_pcm_trigger, | ||
1496 | .set_fmt = wm8350_set_dai_fmt, | ||
1497 | .set_sysclk = wm8350_set_dai_sysclk, | ||
1498 | .set_pll = wm8350_set_fll, | ||
1499 | .set_clkdiv = wm8350_set_clkdiv, | ||
1500 | }; | ||
1501 | |||
1502 | static struct snd_soc_dai_driver wm8350_dai = { | ||
1503 | .name = "wm8350-hifi", | ||
1504 | .playback = { | ||
1505 | .stream_name = "Playback", | ||
1506 | .channels_min = 1, | ||
1507 | .channels_max = 2, | ||
1508 | .rates = WM8350_RATES, | ||
1509 | .formats = WM8350_FORMATS, | ||
1510 | }, | ||
1511 | .capture = { | ||
1512 | .stream_name = "Capture", | ||
1513 | .channels_min = 1, | ||
1514 | .channels_max = 2, | ||
1515 | .rates = WM8350_RATES, | ||
1516 | .formats = WM8350_FORMATS, | ||
1517 | }, | ||
1518 | .ops = &wm8350_dai_ops, | ||
1519 | }; | ||
1493 | 1520 | ||
1494 | static int wm8350_probe(struct platform_device *pdev) | 1521 | static int wm8350_codec_probe(struct snd_soc_codec *codec) |
1495 | { | 1522 | { |
1496 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1523 | struct wm8350 *wm8350 = dev_get_platdata(codec->dev); |
1497 | struct snd_soc_codec *codec; | ||
1498 | struct wm8350 *wm8350; | ||
1499 | struct wm8350_data *priv; | 1524 | struct wm8350_data *priv; |
1500 | int ret; | ||
1501 | struct wm8350_output *out1; | 1525 | struct wm8350_output *out1; |
1502 | struct wm8350_output *out2; | 1526 | struct wm8350_output *out2; |
1527 | int ret, i; | ||
1503 | 1528 | ||
1504 | BUG_ON(!wm8350_codec); | 1529 | if (wm8350->codec.platform_data == NULL) { |
1530 | dev_err(codec->dev, "No audio platform data supplied\n"); | ||
1531 | return -EINVAL; | ||
1532 | } | ||
1533 | |||
1534 | priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL); | ||
1535 | if (priv == NULL) | ||
1536 | return -ENOMEM; | ||
1537 | snd_soc_codec_set_drvdata(codec, priv); | ||
1538 | |||
1539 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
1540 | priv->supplies[i].supply = supply_names[i]; | ||
1541 | |||
1542 | ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies), | ||
1543 | priv->supplies); | ||
1544 | if (ret != 0) | ||
1545 | goto err_priv; | ||
1546 | |||
1547 | wm8350->codec.codec = codec; | ||
1548 | codec->control_data = wm8350; | ||
1505 | 1549 | ||
1506 | socdev->card->codec = wm8350_codec; | 1550 | /* Put the codec into reset if it wasn't already */ |
1507 | codec = socdev->card->codec; | 1551 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
1508 | wm8350 = codec->control_data; | 1552 | |
1509 | priv = snd_soc_codec_get_drvdata(codec); | 1553 | INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work); |
1510 | 1554 | ||
1511 | /* Enable the codec */ | 1555 | /* Enable the codec */ |
1512 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1556 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
@@ -1557,11 +1601,6 @@ static int wm8350_probe(struct platform_device *pdev) | |||
1557 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD, | 1601 | wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD, |
1558 | wm8350_mic_handler, 0, "Microphone detect", priv); | 1602 | wm8350_mic_handler, 0, "Microphone detect", priv); |
1559 | 1603 | ||
1560 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1561 | if (ret < 0) { | ||
1562 | dev_err(&pdev->dev, "failed to create pcms\n"); | ||
1563 | return ret; | ||
1564 | } | ||
1565 | 1604 | ||
1566 | snd_soc_add_controls(codec, wm8350_snd_controls, | 1605 | snd_soc_add_controls(codec, wm8350_snd_controls, |
1567 | ARRAY_SIZE(wm8350_snd_controls)); | 1606 | ARRAY_SIZE(wm8350_snd_controls)); |
@@ -1570,14 +1609,16 @@ static int wm8350_probe(struct platform_device *pdev) | |||
1570 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1609 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1571 | 1610 | ||
1572 | return 0; | 1611 | return 0; |
1612 | |||
1613 | err_priv: | ||
1614 | kfree(priv); | ||
1615 | return ret; | ||
1573 | } | 1616 | } |
1574 | 1617 | ||
1575 | static int wm8350_remove(struct platform_device *pdev) | 1618 | static int wm8350_codec_remove(struct snd_soc_codec *codec) |
1576 | { | 1619 | { |
1577 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1578 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1579 | struct wm8350 *wm8350 = codec->control_data; | ||
1580 | struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); | 1620 | struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); |
1621 | struct wm8350 *wm8350 = dev_get_platdata(codec->dev); | ||
1581 | int ret; | 1622 | int ret; |
1582 | 1623 | ||
1583 | wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, | 1624 | wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, |
@@ -1607,134 +1648,30 @@ static int wm8350_remove(struct platform_device *pdev) | |||
1607 | 1648 | ||
1608 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1649 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
1609 | 1650 | ||
1651 | regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
1652 | kfree(priv); | ||
1610 | return 0; | 1653 | return 0; |
1611 | } | 1654 | } |
1612 | 1655 | ||
1613 | #define WM8350_RATES (SNDRV_PCM_RATE_8000_96000) | 1656 | static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { |
1614 | 1657 | .probe = wm8350_codec_probe, | |
1615 | #define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ | 1658 | .remove = wm8350_codec_remove, |
1616 | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
1617 | SNDRV_PCM_FMTBIT_S24_LE) | ||
1618 | |||
1619 | static struct snd_soc_dai_ops wm8350_dai_ops = { | ||
1620 | .hw_params = wm8350_pcm_hw_params, | ||
1621 | .digital_mute = wm8350_mute, | ||
1622 | .trigger = wm8350_pcm_trigger, | ||
1623 | .set_fmt = wm8350_set_dai_fmt, | ||
1624 | .set_sysclk = wm8350_set_dai_sysclk, | ||
1625 | .set_pll = wm8350_set_fll, | ||
1626 | .set_clkdiv = wm8350_set_clkdiv, | ||
1627 | }; | ||
1628 | |||
1629 | struct snd_soc_dai wm8350_dai = { | ||
1630 | .name = "WM8350", | ||
1631 | .playback = { | ||
1632 | .stream_name = "Playback", | ||
1633 | .channels_min = 1, | ||
1634 | .channels_max = 2, | ||
1635 | .rates = WM8350_RATES, | ||
1636 | .formats = WM8350_FORMATS, | ||
1637 | }, | ||
1638 | .capture = { | ||
1639 | .stream_name = "Capture", | ||
1640 | .channels_min = 1, | ||
1641 | .channels_max = 2, | ||
1642 | .rates = WM8350_RATES, | ||
1643 | .formats = WM8350_FORMATS, | ||
1644 | }, | ||
1645 | .ops = &wm8350_dai_ops, | ||
1646 | }; | ||
1647 | EXPORT_SYMBOL_GPL(wm8350_dai); | ||
1648 | |||
1649 | struct snd_soc_codec_device soc_codec_dev_wm8350 = { | ||
1650 | .probe = wm8350_probe, | ||
1651 | .remove = wm8350_remove, | ||
1652 | .suspend = wm8350_suspend, | 1659 | .suspend = wm8350_suspend, |
1653 | .resume = wm8350_resume, | 1660 | .resume = wm8350_resume, |
1661 | .read = wm8350_codec_read, | ||
1662 | .write = wm8350_codec_write, | ||
1663 | .set_bias_level = wm8350_set_bias_level, | ||
1654 | }; | 1664 | }; |
1655 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350); | ||
1656 | 1665 | ||
1657 | static __devinit int wm8350_codec_probe(struct platform_device *pdev) | 1666 | static int __devinit wm8350_probe(struct platform_device *pdev) |
1658 | { | 1667 | { |
1659 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | 1668 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8350, |
1660 | struct wm8350_data *priv; | 1669 | &wm8350_dai, 1); |
1661 | struct snd_soc_codec *codec; | ||
1662 | int ret, i; | ||
1663 | |||
1664 | if (wm8350->codec.platform_data == NULL) { | ||
1665 | dev_err(&pdev->dev, "No audio platform data supplied\n"); | ||
1666 | return -EINVAL; | ||
1667 | } | ||
1668 | |||
1669 | priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL); | ||
1670 | if (priv == NULL) | ||
1671 | return -ENOMEM; | ||
1672 | |||
1673 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
1674 | priv->supplies[i].supply = supply_names[i]; | ||
1675 | |||
1676 | ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies), | ||
1677 | priv->supplies); | ||
1678 | if (ret != 0) | ||
1679 | goto err_priv; | ||
1680 | |||
1681 | codec = &priv->codec; | ||
1682 | wm8350->codec.codec = codec; | ||
1683 | |||
1684 | wm8350_dai.dev = &pdev->dev; | ||
1685 | |||
1686 | mutex_init(&codec->mutex); | ||
1687 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1688 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1689 | codec->dev = &pdev->dev; | ||
1690 | codec->name = "WM8350"; | ||
1691 | codec->owner = THIS_MODULE; | ||
1692 | codec->read = wm8350_codec_read; | ||
1693 | codec->write = wm8350_codec_write; | ||
1694 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1695 | codec->set_bias_level = wm8350_set_bias_level; | ||
1696 | codec->dai = &wm8350_dai; | ||
1697 | codec->num_dai = 1; | ||
1698 | codec->reg_cache_size = WM8350_MAX_REGISTER; | ||
1699 | snd_soc_codec_set_drvdata(codec, priv); | ||
1700 | codec->control_data = wm8350; | ||
1701 | |||
1702 | /* Put the codec into reset if it wasn't already */ | ||
1703 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | ||
1704 | |||
1705 | INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work); | ||
1706 | ret = snd_soc_register_codec(codec); | ||
1707 | if (ret != 0) | ||
1708 | goto err_supply; | ||
1709 | |||
1710 | wm8350_codec = codec; | ||
1711 | |||
1712 | ret = snd_soc_register_dai(&wm8350_dai); | ||
1713 | if (ret != 0) | ||
1714 | goto err_codec; | ||
1715 | return 0; | ||
1716 | |||
1717 | err_codec: | ||
1718 | snd_soc_unregister_codec(codec); | ||
1719 | err_supply: | ||
1720 | regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
1721 | err_priv: | ||
1722 | kfree(priv); | ||
1723 | wm8350_codec = NULL; | ||
1724 | return ret; | ||
1725 | } | 1670 | } |
1726 | 1671 | ||
1727 | static int __devexit wm8350_codec_remove(struct platform_device *pdev) | 1672 | static int __devexit wm8350_remove(struct platform_device *pdev) |
1728 | { | 1673 | { |
1729 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | 1674 | snd_soc_unregister_codec(&pdev->dev); |
1730 | struct snd_soc_codec *codec = wm8350->codec.codec; | ||
1731 | struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); | ||
1732 | |||
1733 | snd_soc_unregister_dai(&wm8350_dai); | ||
1734 | snd_soc_unregister_codec(codec); | ||
1735 | regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
1736 | kfree(priv); | ||
1737 | wm8350_codec = NULL; | ||
1738 | return 0; | 1675 | return 0; |
1739 | } | 1676 | } |
1740 | 1677 | ||
@@ -1743,8 +1680,8 @@ static struct platform_driver wm8350_codec_driver = { | |||
1743 | .name = "wm8350-codec", | 1680 | .name = "wm8350-codec", |
1744 | .owner = THIS_MODULE, | 1681 | .owner = THIS_MODULE, |
1745 | }, | 1682 | }, |
1746 | .probe = wm8350_codec_probe, | 1683 | .probe = wm8350_probe, |
1747 | .remove = __devexit_p(wm8350_codec_remove), | 1684 | .remove = __devexit_p(wm8350_remove), |
1748 | }; | 1685 | }; |
1749 | 1686 | ||
1750 | static __init int wm8350_init(void) | 1687 | static __init int wm8350_init(void) |
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h index 9ed0467c71db..74108eb82938 100644 --- a/sound/soc/codecs/wm8350.h +++ b/sound/soc/codecs/wm8350.h | |||
@@ -15,9 +15,6 @@ | |||
15 | #include <sound/soc.h> | 15 | #include <sound/soc.h> |
16 | #include <linux/mfd/wm8350/audio.h> | 16 | #include <linux/mfd/wm8350/audio.h> |
17 | 17 | ||
18 | extern struct snd_soc_dai wm8350_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8350; | ||
20 | |||
21 | enum wm8350_jack { | 18 | enum wm8350_jack { |
22 | WM8350_JDL = 1, | 19 | WM8350_JDL = 1, |
23 | WM8350_JDR = 2, | 20 | WM8350_JDR = 2, |
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 8f294066b0ed..850299786e02 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -65,7 +65,7 @@ static struct regulator_bulk_data power[] = { | |||
65 | 65 | ||
66 | /* codec private data */ | 66 | /* codec private data */ |
67 | struct wm8400_priv { | 67 | struct wm8400_priv { |
68 | struct snd_soc_codec codec; | 68 | struct snd_soc_codec *codec; |
69 | struct wm8400 *wm8400; | 69 | struct wm8400 *wm8400; |
70 | u16 fake_register; | 70 | u16 fake_register; |
71 | unsigned int sysclk; | 71 | unsigned int sysclk; |
@@ -1163,8 +1163,7 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream, | |||
1163 | struct snd_soc_dai *dai) | 1163 | struct snd_soc_dai *dai) |
1164 | { | 1164 | { |
1165 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1165 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1166 | struct snd_soc_device *socdev = rtd->socdev; | 1166 | struct snd_soc_codec *codec = rtd->codec; |
1167 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1168 | u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); | 1167 | u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); |
1169 | 1168 | ||
1170 | audio1 &= ~WM8400_AIF_WL_MASK; | 1169 | audio1 &= ~WM8400_AIF_WL_MASK; |
@@ -1332,10 +1331,9 @@ static struct snd_soc_dai_ops wm8400_dai_ops = { | |||
1332 | * 1. ADC/DAC on Primary Interface | 1331 | * 1. ADC/DAC on Primary Interface |
1333 | * 2. ADC on Primary Interface/DAC on secondary | 1332 | * 2. ADC on Primary Interface/DAC on secondary |
1334 | */ | 1333 | */ |
1335 | struct snd_soc_dai wm8400_dai = { | 1334 | static struct snd_soc_dai_driver wm8400_dai = { |
1336 | /* ADC/DAC on primary */ | 1335 | /* ADC/DAC on primary */ |
1337 | .name = "WM8400 ADC/DAC Primary", | 1336 | .name = "wm8400-hifi", |
1338 | .id = 1, | ||
1339 | .playback = { | 1337 | .playback = { |
1340 | .stream_name = "Playback", | 1338 | .stream_name = "Playback", |
1341 | .channels_min = 1, | 1339 | .channels_min = 1, |
@@ -1352,147 +1350,53 @@ struct snd_soc_dai wm8400_dai = { | |||
1352 | }, | 1350 | }, |
1353 | .ops = &wm8400_dai_ops, | 1351 | .ops = &wm8400_dai_ops, |
1354 | }; | 1352 | }; |
1355 | EXPORT_SYMBOL_GPL(wm8400_dai); | ||
1356 | 1353 | ||
1357 | static int wm8400_suspend(struct platform_device *pdev, pm_message_t state) | 1354 | static int wm8400_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1358 | { | 1355 | { |
1359 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1360 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1361 | |||
1362 | wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1356 | wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1363 | 1357 | ||
1364 | return 0; | 1358 | return 0; |
1365 | } | 1359 | } |
1366 | 1360 | ||
1367 | static int wm8400_resume(struct platform_device *pdev) | 1361 | static int wm8400_resume(struct snd_soc_codec *codec) |
1368 | { | 1362 | { |
1369 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1370 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1371 | |||
1372 | wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1363 | wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1373 | 1364 | ||
1374 | return 0; | 1365 | return 0; |
1375 | } | 1366 | } |
1376 | 1367 | ||
1377 | static struct snd_soc_codec *wm8400_codec; | ||
1378 | |||
1379 | static int wm8400_probe(struct platform_device *pdev) | ||
1380 | { | ||
1381 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1382 | struct snd_soc_codec *codec; | ||
1383 | int ret; | ||
1384 | |||
1385 | if (!wm8400_codec) { | ||
1386 | dev_err(&pdev->dev, "wm8400 not yet discovered\n"); | ||
1387 | return -ENODEV; | ||
1388 | } | ||
1389 | codec = wm8400_codec; | ||
1390 | |||
1391 | socdev->card->codec = codec; | ||
1392 | |||
1393 | /* register pcms */ | ||
1394 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1395 | if (ret < 0) { | ||
1396 | dev_err(&pdev->dev, "failed to create pcms\n"); | ||
1397 | goto pcm_err; | ||
1398 | } | ||
1399 | |||
1400 | wm8400_add_controls(codec); | ||
1401 | wm8400_add_widgets(codec); | ||
1402 | |||
1403 | pcm_err: | ||
1404 | return ret; | ||
1405 | } | ||
1406 | |||
1407 | /* power down chip */ | ||
1408 | static int wm8400_remove(struct platform_device *pdev) | ||
1409 | { | ||
1410 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1411 | |||
1412 | snd_soc_free_pcms(socdev); | ||
1413 | snd_soc_dapm_free(socdev); | ||
1414 | |||
1415 | return 0; | ||
1416 | } | ||
1417 | |||
1418 | struct snd_soc_codec_device soc_codec_dev_wm8400 = { | ||
1419 | .probe = wm8400_probe, | ||
1420 | .remove = wm8400_remove, | ||
1421 | .suspend = wm8400_suspend, | ||
1422 | .resume = wm8400_resume, | ||
1423 | }; | ||
1424 | |||
1425 | static void wm8400_probe_deferred(struct work_struct *work) | 1368 | static void wm8400_probe_deferred(struct work_struct *work) |
1426 | { | 1369 | { |
1427 | struct wm8400_priv *priv = container_of(work, struct wm8400_priv, | 1370 | struct wm8400_priv *priv = container_of(work, struct wm8400_priv, |
1428 | work); | 1371 | work); |
1429 | struct snd_soc_codec *codec = &priv->codec; | 1372 | struct snd_soc_codec *codec = priv->codec; |
1430 | int ret; | ||
1431 | 1373 | ||
1432 | /* charge output caps */ | 1374 | /* charge output caps */ |
1433 | wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1375 | wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1434 | |||
1435 | /* We're done, tell the subsystem. */ | ||
1436 | ret = snd_soc_register_codec(codec); | ||
1437 | if (ret != 0) { | ||
1438 | dev_err(priv->wm8400->dev, | ||
1439 | "Failed to register codec: %d\n", ret); | ||
1440 | goto err; | ||
1441 | } | ||
1442 | |||
1443 | ret = snd_soc_register_dai(&wm8400_dai); | ||
1444 | if (ret != 0) { | ||
1445 | dev_err(priv->wm8400->dev, | ||
1446 | "Failed to register DAI: %d\n", ret); | ||
1447 | goto err_codec; | ||
1448 | } | ||
1449 | |||
1450 | return; | ||
1451 | |||
1452 | err_codec: | ||
1453 | snd_soc_unregister_codec(codec); | ||
1454 | err: | ||
1455 | wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1456 | } | 1376 | } |
1457 | 1377 | ||
1458 | static int wm8400_codec_probe(struct platform_device *dev) | 1378 | static int wm8400_codec_probe(struct snd_soc_codec *codec) |
1459 | { | 1379 | { |
1380 | struct wm8400 *wm8400 = dev_get_platdata(codec->dev); | ||
1460 | struct wm8400_priv *priv; | 1381 | struct wm8400_priv *priv; |
1461 | int ret; | 1382 | int ret; |
1462 | u16 reg; | 1383 | u16 reg; |
1463 | struct snd_soc_codec *codec; | ||
1464 | 1384 | ||
1465 | priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL); | 1385 | priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL); |
1466 | if (priv == NULL) | 1386 | if (priv == NULL) |
1467 | return -ENOMEM; | 1387 | return -ENOMEM; |
1468 | 1388 | ||
1469 | codec = &priv->codec; | ||
1470 | snd_soc_codec_set_drvdata(codec, priv); | 1389 | snd_soc_codec_set_drvdata(codec, priv); |
1471 | codec->control_data = dev_get_drvdata(&dev->dev); | 1390 | codec->control_data = priv->wm8400 = wm8400; |
1472 | priv->wm8400 = dev_get_drvdata(&dev->dev); | 1391 | priv->codec = codec; |
1473 | 1392 | ||
1474 | ret = regulator_bulk_get(priv->wm8400->dev, | 1393 | ret = regulator_bulk_get(wm8400->dev, |
1475 | ARRAY_SIZE(power), &power[0]); | 1394 | ARRAY_SIZE(power), &power[0]); |
1476 | if (ret != 0) { | 1395 | if (ret != 0) { |
1477 | dev_err(&dev->dev, "Failed to get regulators: %d\n", ret); | 1396 | dev_err(codec->dev, "Failed to get regulators: %d\n", ret); |
1478 | goto err; | 1397 | goto err; |
1479 | } | 1398 | } |
1480 | 1399 | ||
1481 | codec->dev = &dev->dev; | ||
1482 | wm8400_dai.dev = &dev->dev; | ||
1483 | |||
1484 | codec->name = "WM8400"; | ||
1485 | codec->owner = THIS_MODULE; | ||
1486 | codec->read = wm8400_read; | ||
1487 | codec->write = wm8400_write; | ||
1488 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1489 | codec->set_bias_level = wm8400_set_bias_level; | ||
1490 | codec->dai = &wm8400_dai; | ||
1491 | codec->num_dai = 1; | ||
1492 | codec->reg_cache_size = WM8400_REGISTER_COUNT; | ||
1493 | mutex_init(&codec->mutex); | ||
1494 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1495 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1496 | INIT_WORK(&priv->work, wm8400_probe_deferred); | 1400 | INIT_WORK(&priv->work, wm8400_probe_deferred); |
1497 | 1401 | ||
1498 | wm8400_codec_reset(codec); | 1402 | wm8400_codec_reset(codec); |
@@ -1511,65 +1415,78 @@ static int wm8400_codec_probe(struct platform_device *dev) | |||
1511 | wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1415 | wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1512 | wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1416 | wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1513 | 1417 | ||
1514 | wm8400_codec = codec; | ||
1515 | |||
1516 | if (!schedule_work(&priv->work)) { | 1418 | if (!schedule_work(&priv->work)) { |
1517 | ret = -EINVAL; | 1419 | ret = -EINVAL; |
1518 | goto err_regulator; | 1420 | goto err_regulator; |
1519 | } | 1421 | } |
1520 | 1422 | wm8400_add_controls(codec); | |
1423 | wm8400_add_widgets(codec); | ||
1521 | return 0; | 1424 | return 0; |
1522 | 1425 | ||
1523 | err_regulator: | 1426 | err_regulator: |
1524 | wm8400_codec = NULL; | ||
1525 | regulator_bulk_free(ARRAY_SIZE(power), power); | 1427 | regulator_bulk_free(ARRAY_SIZE(power), power); |
1526 | err: | 1428 | err: |
1527 | kfree(priv); | 1429 | kfree(priv); |
1528 | return ret; | 1430 | return ret; |
1529 | } | 1431 | } |
1530 | 1432 | ||
1531 | static int __exit wm8400_codec_remove(struct platform_device *dev) | 1433 | static int wm8400_codec_remove(struct snd_soc_codec *codec) |
1532 | { | 1434 | { |
1533 | struct wm8400_priv *priv = snd_soc_codec_get_drvdata(wm8400_codec); | 1435 | struct wm8400_priv *priv = snd_soc_codec_get_drvdata(codec); |
1534 | u16 reg; | 1436 | u16 reg; |
1535 | 1437 | ||
1536 | snd_soc_unregister_dai(&wm8400_dai); | 1438 | reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); |
1537 | snd_soc_unregister_codec(wm8400_codec); | 1439 | wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, |
1538 | |||
1539 | reg = wm8400_read(wm8400_codec, WM8400_POWER_MANAGEMENT_1); | ||
1540 | wm8400_write(wm8400_codec, WM8400_POWER_MANAGEMENT_1, | ||
1541 | reg & (~WM8400_CODEC_ENA)); | 1440 | reg & (~WM8400_CODEC_ENA)); |
1542 | 1441 | ||
1543 | regulator_bulk_free(ARRAY_SIZE(power), power); | 1442 | regulator_bulk_free(ARRAY_SIZE(power), power); |
1544 | kfree(priv); | 1443 | kfree(priv); |
1545 | 1444 | ||
1546 | wm8400_codec = NULL; | 1445 | return 0; |
1446 | } | ||
1447 | |||
1448 | static struct snd_soc_codec_driver soc_codec_dev_wm8400 = { | ||
1449 | .probe = wm8400_codec_probe, | ||
1450 | .remove = wm8400_codec_remove, | ||
1451 | .suspend = wm8400_suspend, | ||
1452 | .resume = wm8400_resume, | ||
1453 | .read = wm8400_read, | ||
1454 | .write = wm8400_write, | ||
1455 | .set_bias_level = wm8400_set_bias_level, | ||
1456 | }; | ||
1457 | |||
1458 | static int __devinit wm8400_probe(struct platform_device *pdev) | ||
1459 | { | ||
1460 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8400, | ||
1461 | &wm8400_dai, 1); | ||
1462 | } | ||
1547 | 1463 | ||
1464 | static int __devexit wm8400_remove(struct platform_device *pdev) | ||
1465 | { | ||
1466 | snd_soc_unregister_codec(&pdev->dev); | ||
1548 | return 0; | 1467 | return 0; |
1549 | } | 1468 | } |
1550 | 1469 | ||
1551 | static struct platform_driver wm8400_codec_driver = { | 1470 | static struct platform_driver wm8400_codec_driver = { |
1552 | .driver = { | 1471 | .driver = { |
1553 | .name = "wm8400-codec", | 1472 | .name = "wm8400-codec", |
1554 | .owner = THIS_MODULE, | 1473 | .owner = THIS_MODULE, |
1555 | }, | 1474 | }, |
1556 | .probe = wm8400_codec_probe, | 1475 | .probe = wm8400_probe, |
1557 | .remove = __exit_p(wm8400_codec_remove), | 1476 | .remove = __devexit_p(wm8400_remove), |
1558 | }; | 1477 | }; |
1559 | 1478 | ||
1560 | static int __init wm8400_codec_init(void) | 1479 | static __init int wm8400_init(void) |
1561 | { | 1480 | { |
1562 | return platform_driver_register(&wm8400_codec_driver); | 1481 | return platform_driver_register(&wm8400_codec_driver); |
1563 | } | 1482 | } |
1564 | module_init(wm8400_codec_init); | 1483 | module_init(wm8400_init); |
1565 | 1484 | ||
1566 | static void __exit wm8400_codec_exit(void) | 1485 | static __exit void wm8400_exit(void) |
1567 | { | 1486 | { |
1568 | platform_driver_unregister(&wm8400_codec_driver); | 1487 | platform_driver_unregister(&wm8400_codec_driver); |
1569 | } | 1488 | } |
1570 | module_exit(wm8400_codec_exit); | 1489 | module_exit(wm8400_exit); |
1571 | |||
1572 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8400); | ||
1573 | 1490 | ||
1574 | MODULE_DESCRIPTION("ASoC WM8400 driver"); | 1491 | MODULE_DESCRIPTION("ASoC WM8400 driver"); |
1575 | MODULE_AUTHOR("Mark Brown"); | 1492 | MODULE_AUTHOR("Mark Brown"); |
diff --git a/sound/soc/codecs/wm8400.h b/sound/soc/codecs/wm8400.h index 79c5934d4776..521adb193870 100644 --- a/sound/soc/codecs/wm8400.h +++ b/sound/soc/codecs/wm8400.h | |||
@@ -56,7 +56,4 @@ | |||
56 | #define WM8400_BCLK_DIV_44 (0xE << 1) | 56 | #define WM8400_BCLK_DIV_44 (0xE << 1) |
57 | #define WM8400_BCLK_DIV_48 (0xF << 1) | 57 | #define WM8400_BCLK_DIV_48 (0xF << 1) |
58 | 58 | ||
59 | extern struct snd_soc_dai wm8400_dai; | ||
60 | extern struct snd_soc_codec_device soc_codec_dev_wm8400; | ||
61 | |||
62 | #endif | 59 | #endif |
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 0f7bcb61071a..dbfa05d2cb92 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -31,8 +31,6 @@ | |||
31 | 31 | ||
32 | #define WM8510_VERSION "0.6" | 32 | #define WM8510_VERSION "0.6" |
33 | 33 | ||
34 | struct snd_soc_codec_device soc_codec_dev_wm8510; | ||
35 | |||
36 | /* | 34 | /* |
37 | * wm8510 register cache | 35 | * wm8510 register cache |
38 | * We can't read the WM8510 register space when we are | 36 | * We can't read the WM8510 register space when we are |
@@ -61,6 +59,12 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { | |||
61 | 59 | ||
62 | #define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0) | 60 | #define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0) |
63 | 61 | ||
62 | /* codec private data */ | ||
63 | struct wm8510_priv { | ||
64 | enum snd_soc_control_type control_type; | ||
65 | void *control_data; | ||
66 | }; | ||
67 | |||
64 | static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; | 68 | static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; |
65 | static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; | 69 | static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; |
66 | static const char *wm8510_alc[] = { "ALC", "Limiter" }; | 70 | static const char *wm8510_alc[] = { "ALC", "Limiter" }; |
@@ -403,8 +407,7 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, | |||
403 | struct snd_soc_dai *dai) | 407 | struct snd_soc_dai *dai) |
404 | { | 408 | { |
405 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 409 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
406 | struct snd_soc_device *socdev = rtd->socdev; | 410 | struct snd_soc_codec *codec = rtd->codec; |
407 | struct snd_soc_codec *codec = socdev->card->codec; | ||
408 | u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f; | 411 | u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f; |
409 | u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; | 412 | u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; |
410 | 413 | ||
@@ -514,8 +517,8 @@ static struct snd_soc_dai_ops wm8510_dai_ops = { | |||
514 | .set_pll = wm8510_set_dai_pll, | 517 | .set_pll = wm8510_set_dai_pll, |
515 | }; | 518 | }; |
516 | 519 | ||
517 | struct snd_soc_dai wm8510_dai = { | 520 | static struct snd_soc_dai_driver wm8510_dai = { |
518 | .name = "WM8510 HiFi", | 521 | .name = "wm8510-hifi", |
519 | .playback = { | 522 | .playback = { |
520 | .stream_name = "Playback", | 523 | .stream_name = "Playback", |
521 | .channels_min = 2, | 524 | .channels_min = 2, |
@@ -531,21 +534,15 @@ struct snd_soc_dai wm8510_dai = { | |||
531 | .ops = &wm8510_dai_ops, | 534 | .ops = &wm8510_dai_ops, |
532 | .symmetric_rates = 1, | 535 | .symmetric_rates = 1, |
533 | }; | 536 | }; |
534 | EXPORT_SYMBOL_GPL(wm8510_dai); | ||
535 | 537 | ||
536 | static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) | 538 | static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state) |
537 | { | 539 | { |
538 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
539 | struct snd_soc_codec *codec = socdev->card->codec; | ||
540 | |||
541 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); | 540 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); |
542 | return 0; | 541 | return 0; |
543 | } | 542 | } |
544 | 543 | ||
545 | static int wm8510_resume(struct platform_device *pdev) | 544 | static int wm8510_resume(struct snd_soc_codec *codec) |
546 | { | 545 | { |
547 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
548 | struct snd_soc_codec *codec = socdev->card->codec; | ||
549 | int i; | 546 | int i; |
550 | u8 data[2]; | 547 | u8 data[2]; |
551 | u16 *cache = codec->reg_cache; | 548 | u16 *cache = codec->reg_cache; |
@@ -561,43 +558,22 @@ static int wm8510_resume(struct platform_device *pdev) | |||
561 | return 0; | 558 | return 0; |
562 | } | 559 | } |
563 | 560 | ||
564 | /* | 561 | static int wm8510_probe(struct snd_soc_codec *codec) |
565 | * initialise the WM8510 driver | ||
566 | * register the mixer and dsp interfaces with the kernel | ||
567 | */ | ||
568 | static int wm8510_init(struct snd_soc_device *socdev, | ||
569 | enum snd_soc_control_type control) | ||
570 | { | 562 | { |
571 | struct snd_soc_codec *codec = socdev->card->codec; | 563 | struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); |
572 | int ret = 0; | 564 | int ret; |
573 | |||
574 | codec->name = "WM8510"; | ||
575 | codec->owner = THIS_MODULE; | ||
576 | codec->set_bias_level = wm8510_set_bias_level; | ||
577 | codec->dai = &wm8510_dai; | ||
578 | codec->num_dai = 1; | ||
579 | codec->reg_cache_size = ARRAY_SIZE(wm8510_reg); | ||
580 | codec->reg_cache = kmemdup(wm8510_reg, sizeof(wm8510_reg), GFP_KERNEL); | ||
581 | 565 | ||
582 | if (codec->reg_cache == NULL) | 566 | pr_info("WM8510 Audio Codec %s", WM8510_VERSION); |
583 | return -ENOMEM; | ||
584 | 567 | ||
585 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 568 | codec->control_data = wm8510->control_data; |
569 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type); | ||
586 | if (ret < 0) { | 570 | if (ret < 0) { |
587 | printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", | 571 | printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); |
588 | ret); | 572 | return ret; |
589 | goto err; | ||
590 | } | 573 | } |
591 | 574 | ||
592 | wm8510_reset(codec); | 575 | wm8510_reset(codec); |
593 | 576 | ||
594 | /* register pcms */ | ||
595 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
596 | if (ret < 0) { | ||
597 | printk(KERN_ERR "wm8510: failed to create pcms\n"); | ||
598 | goto err; | ||
599 | } | ||
600 | |||
601 | /* power on device */ | 577 | /* power on device */ |
602 | codec->bias_level = SND_SOC_BIAS_OFF; | 578 | codec->bias_level = SND_SOC_BIAS_OFF; |
603 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 579 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -606,119 +582,53 @@ static int wm8510_init(struct snd_soc_device *socdev, | |||
606 | wm8510_add_widgets(codec); | 582 | wm8510_add_widgets(codec); |
607 | 583 | ||
608 | return ret; | 584 | return ret; |
609 | |||
610 | err: | ||
611 | kfree(codec->reg_cache); | ||
612 | return ret; | ||
613 | } | 585 | } |
614 | 586 | ||
615 | static struct snd_soc_device *wm8510_socdev; | 587 | /* power down chip */ |
616 | 588 | static int wm8510_remove(struct snd_soc_codec *codec) | |
617 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
618 | |||
619 | /* | ||
620 | * WM8510 2 wire address is 0x1a | ||
621 | */ | ||
622 | |||
623 | static int wm8510_i2c_probe(struct i2c_client *i2c, | ||
624 | const struct i2c_device_id *id) | ||
625 | { | 589 | { |
626 | struct snd_soc_device *socdev = wm8510_socdev; | 590 | struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); |
627 | struct snd_soc_codec *codec = socdev->card->codec; | ||
628 | int ret; | ||
629 | |||
630 | i2c_set_clientdata(i2c, codec); | ||
631 | codec->control_data = i2c; | ||
632 | |||
633 | ret = wm8510_init(socdev, SND_SOC_I2C); | ||
634 | if (ret < 0) | ||
635 | pr_err("failed to initialise WM8510\n"); | ||
636 | |||
637 | return ret; | ||
638 | } | ||
639 | 591 | ||
640 | static int wm8510_i2c_remove(struct i2c_client *client) | 592 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); |
641 | { | 593 | kfree(wm8510); |
642 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | ||
643 | kfree(codec->reg_cache); | ||
644 | return 0; | 594 | return 0; |
645 | } | 595 | } |
646 | 596 | ||
647 | static const struct i2c_device_id wm8510_i2c_id[] = { | 597 | static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { |
648 | { "wm8510", 0 }, | 598 | .probe = wm8510_probe, |
649 | { } | 599 | .remove = wm8510_remove, |
650 | }; | 600 | .suspend = wm8510_suspend, |
651 | MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); | 601 | .resume = wm8510_resume, |
652 | 602 | .set_bias_level = wm8510_set_bias_level, | |
653 | static struct i2c_driver wm8510_i2c_driver = { | 603 | .reg_cache_size = ARRAY_SIZE(wm8510_reg), |
654 | .driver = { | 604 | .reg_word_size = sizeof(u16), |
655 | .name = "WM8510 I2C Codec", | 605 | .reg_cache_default =wm8510_reg, |
656 | .owner = THIS_MODULE, | ||
657 | }, | ||
658 | .probe = wm8510_i2c_probe, | ||
659 | .remove = wm8510_i2c_remove, | ||
660 | .id_table = wm8510_i2c_id, | ||
661 | }; | 606 | }; |
662 | 607 | ||
663 | static int wm8510_add_i2c_device(struct platform_device *pdev, | ||
664 | const struct wm8510_setup_data *setup) | ||
665 | { | ||
666 | struct i2c_board_info info; | ||
667 | struct i2c_adapter *adapter; | ||
668 | struct i2c_client *client; | ||
669 | int ret; | ||
670 | |||
671 | ret = i2c_add_driver(&wm8510_i2c_driver); | ||
672 | if (ret != 0) { | ||
673 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
674 | return ret; | ||
675 | } | ||
676 | |||
677 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
678 | info.addr = setup->i2c_address; | ||
679 | strlcpy(info.type, "wm8510", I2C_NAME_SIZE); | ||
680 | |||
681 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
682 | if (!adapter) { | ||
683 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
684 | setup->i2c_bus); | ||
685 | goto err_driver; | ||
686 | } | ||
687 | |||
688 | client = i2c_new_device(adapter, &info); | ||
689 | i2c_put_adapter(adapter); | ||
690 | if (!client) { | ||
691 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
692 | (unsigned int)info.addr); | ||
693 | goto err_driver; | ||
694 | } | ||
695 | |||
696 | return 0; | ||
697 | |||
698 | err_driver: | ||
699 | i2c_del_driver(&wm8510_i2c_driver); | ||
700 | return -ENODEV; | ||
701 | } | ||
702 | #endif | ||
703 | |||
704 | #if defined(CONFIG_SPI_MASTER) | 608 | #if defined(CONFIG_SPI_MASTER) |
705 | static int __devinit wm8510_spi_probe(struct spi_device *spi) | 609 | static int __devinit wm8510_spi_probe(struct spi_device *spi) |
706 | { | 610 | { |
707 | struct snd_soc_device *socdev = wm8510_socdev; | 611 | struct wm8510_priv *wm8510; |
708 | struct snd_soc_codec *codec = socdev->card->codec; | ||
709 | int ret; | 612 | int ret; |
710 | 613 | ||
711 | codec->control_data = spi; | 614 | wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); |
615 | if (wm8510 == NULL) | ||
616 | return -ENOMEM; | ||
617 | |||
618 | wm8510->control_data = spi; | ||
619 | wm8510->control_type = SND_SOC_SPI; | ||
620 | spi_set_drvdata(spi, wm8510); | ||
712 | 621 | ||
713 | ret = wm8510_init(socdev, SND_SOC_SPI); | 622 | ret = snd_soc_register_codec(&spi->dev, |
623 | &soc_codec_dev_wm8510, &wm8510_dai, 1); | ||
714 | if (ret < 0) | 624 | if (ret < 0) |
715 | dev_err(&spi->dev, "failed to initialise WM8510\n"); | 625 | kfree(wm8510); |
716 | |||
717 | return ret; | 626 | return ret; |
718 | } | 627 | } |
719 | 628 | ||
720 | static int __devexit wm8510_spi_remove(struct spi_device *spi) | 629 | static int __devexit wm8510_spi_remove(struct spi_device *spi) |
721 | { | 630 | { |
631 | snd_soc_unregister_codec(&spi->dev); | ||
722 | return 0; | 632 | return 0; |
723 | } | 633 | } |
724 | 634 | ||
@@ -733,84 +643,80 @@ static struct spi_driver wm8510_spi_driver = { | |||
733 | }; | 643 | }; |
734 | #endif /* CONFIG_SPI_MASTER */ | 644 | #endif /* CONFIG_SPI_MASTER */ |
735 | 645 | ||
736 | static int wm8510_probe(struct platform_device *pdev) | 646 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
647 | static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, | ||
648 | const struct i2c_device_id *id) | ||
737 | { | 649 | { |
738 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 650 | struct wm8510_priv *wm8510; |
739 | struct wm8510_setup_data *setup; | 651 | int ret; |
740 | struct snd_soc_codec *codec; | ||
741 | int ret = 0; | ||
742 | |||
743 | pr_info("WM8510 Audio Codec %s", WM8510_VERSION); | ||
744 | 652 | ||
745 | setup = socdev->codec_data; | 653 | wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); |
746 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 654 | if (wm8510 == NULL) |
747 | if (codec == NULL) | ||
748 | return -ENOMEM; | 655 | return -ENOMEM; |
749 | 656 | ||
750 | socdev->card->codec = codec; | 657 | i2c_set_clientdata(i2c, wm8510); |
751 | mutex_init(&codec->mutex); | 658 | wm8510->control_data = i2c; |
752 | INIT_LIST_HEAD(&codec->dapm_widgets); | 659 | wm8510->control_type = SND_SOC_I2C; |
753 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
754 | 660 | ||
755 | wm8510_socdev = socdev; | 661 | ret = snd_soc_register_codec(&i2c->dev, |
756 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 662 | &soc_codec_dev_wm8510, &wm8510_dai, 1); |
757 | if (setup->i2c_address) { | 663 | if (ret < 0) |
758 | ret = wm8510_add_i2c_device(pdev, setup); | 664 | kfree(wm8510); |
759 | } | ||
760 | #endif | ||
761 | #if defined(CONFIG_SPI_MASTER) | ||
762 | if (setup->spi) { | ||
763 | ret = spi_register_driver(&wm8510_spi_driver); | ||
764 | if (ret != 0) | ||
765 | printk(KERN_ERR "can't add spi driver"); | ||
766 | } | ||
767 | #endif | ||
768 | |||
769 | if (ret != 0) | ||
770 | kfree(codec); | ||
771 | return ret; | 665 | return ret; |
772 | } | 666 | } |
773 | 667 | ||
774 | /* power down chip */ | 668 | static __devexit int wm8510_i2c_remove(struct i2c_client *client) |
775 | static int wm8510_remove(struct platform_device *pdev) | ||
776 | { | 669 | { |
777 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 670 | snd_soc_unregister_codec(&client->dev); |
778 | struct snd_soc_codec *codec = socdev->card->codec; | ||
779 | |||
780 | if (codec->control_data) | ||
781 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
782 | |||
783 | snd_soc_free_pcms(socdev); | ||
784 | snd_soc_dapm_free(socdev); | ||
785 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
786 | i2c_unregister_device(codec->control_data); | ||
787 | i2c_del_driver(&wm8510_i2c_driver); | ||
788 | #endif | ||
789 | #if defined(CONFIG_SPI_MASTER) | ||
790 | spi_unregister_driver(&wm8510_spi_driver); | ||
791 | #endif | ||
792 | kfree(codec); | ||
793 | |||
794 | return 0; | 671 | return 0; |
795 | } | 672 | } |
796 | 673 | ||
797 | struct snd_soc_codec_device soc_codec_dev_wm8510 = { | 674 | static const struct i2c_device_id wm8510_i2c_id[] = { |
798 | .probe = wm8510_probe, | 675 | { "wm8510", 0 }, |
799 | .remove = wm8510_remove, | 676 | { } |
800 | .suspend = wm8510_suspend, | 677 | }; |
801 | .resume = wm8510_resume, | 678 | MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); |
679 | |||
680 | static struct i2c_driver wm8510_i2c_driver = { | ||
681 | .driver = { | ||
682 | .name = "wm8510-codec", | ||
683 | .owner = THIS_MODULE, | ||
684 | }, | ||
685 | .probe = wm8510_i2c_probe, | ||
686 | .remove = __devexit_p(wm8510_i2c_remove), | ||
687 | .id_table = wm8510_i2c_id, | ||
802 | }; | 688 | }; |
803 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510); | 689 | #endif |
804 | 690 | ||
805 | static int __init wm8510_modinit(void) | 691 | static int __init wm8510_modinit(void) |
806 | { | 692 | { |
807 | return snd_soc_register_dai(&wm8510_dai); | 693 | int ret = 0; |
694 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
695 | ret = i2c_add_driver(&wm8510_i2c_driver); | ||
696 | if (ret != 0) { | ||
697 | printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n", | ||
698 | ret); | ||
699 | } | ||
700 | #endif | ||
701 | #if defined(CONFIG_SPI_MASTER) | ||
702 | ret = spi_register_driver(&wm8510_spi_driver); | ||
703 | if (ret != 0) { | ||
704 | printk(KERN_ERR "Failed to register WM8510 SPI driver: %d\n", | ||
705 | ret); | ||
706 | } | ||
707 | #endif | ||
708 | return ret; | ||
808 | } | 709 | } |
809 | module_init(wm8510_modinit); | 710 | module_init(wm8510_modinit); |
810 | 711 | ||
811 | static void __exit wm8510_exit(void) | 712 | static void __exit wm8510_exit(void) |
812 | { | 713 | { |
813 | snd_soc_unregister_dai(&wm8510_dai); | 714 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
715 | i2c_del_driver(&wm8510_i2c_driver); | ||
716 | #endif | ||
717 | #if defined(CONFIG_SPI_MASTER) | ||
718 | spi_unregister_driver(&wm8510_spi_driver); | ||
719 | #endif | ||
814 | } | 720 | } |
815 | module_exit(wm8510_exit); | 721 | module_exit(wm8510_exit); |
816 | 722 | ||
diff --git a/sound/soc/codecs/wm8510.h b/sound/soc/codecs/wm8510.h index bdefcf5c69ff..b3e26ed9f2d0 100644 --- a/sound/soc/codecs/wm8510.h +++ b/sound/soc/codecs/wm8510.h | |||
@@ -99,7 +99,4 @@ struct wm8510_setup_data { | |||
99 | unsigned short i2c_address; | 99 | unsigned short i2c_address; |
100 | }; | 100 | }; |
101 | 101 | ||
102 | extern struct snd_soc_dai wm8510_dai; | ||
103 | extern struct snd_soc_codec_device soc_codec_dev_wm8510; | ||
104 | |||
105 | #endif | 102 | #endif |
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 0ad039b4adf5..58d411b6faaf 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -30,9 +30,6 @@ | |||
30 | 30 | ||
31 | #include "wm8523.h" | 31 | #include "wm8523.h" |
32 | 32 | ||
33 | static struct snd_soc_codec *wm8523_codec; | ||
34 | struct snd_soc_codec_device soc_codec_dev_wm8523; | ||
35 | |||
36 | #define WM8523_NUM_SUPPLIES 2 | 33 | #define WM8523_NUM_SUPPLIES 2 |
37 | static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { | 34 | static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { |
38 | "AVDD", | 35 | "AVDD", |
@@ -43,7 +40,8 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { | |||
43 | 40 | ||
44 | /* codec private data */ | 41 | /* codec private data */ |
45 | struct wm8523_priv { | 42 | struct wm8523_priv { |
46 | struct snd_soc_codec codec; | 43 | enum snd_soc_control_type control_type; |
44 | void *control_data; | ||
47 | u16 reg_cache[WM8523_REGISTER_COUNT]; | 45 | u16 reg_cache[WM8523_REGISTER_COUNT]; |
48 | struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; | 46 | struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; |
49 | unsigned int sysclk; | 47 | unsigned int sysclk; |
@@ -162,8 +160,7 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream, | |||
162 | struct snd_soc_dai *dai) | 160 | struct snd_soc_dai *dai) |
163 | { | 161 | { |
164 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 162 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
165 | struct snd_soc_device *socdev = rtd->socdev; | 163 | struct snd_soc_codec *codec = rtd->codec; |
166 | struct snd_soc_codec *codec = socdev->card->codec; | ||
167 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); | 164 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
168 | int i; | 165 | int i; |
169 | u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); | 166 | u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); |
@@ -387,8 +384,8 @@ static struct snd_soc_dai_ops wm8523_dai_ops = { | |||
387 | .set_fmt = wm8523_set_dai_fmt, | 384 | .set_fmt = wm8523_set_dai_fmt, |
388 | }; | 385 | }; |
389 | 386 | ||
390 | struct snd_soc_dai wm8523_dai = { | 387 | static struct snd_soc_dai_driver wm8523_dai = { |
391 | .name = "WM8523", | 388 | .name = "wm8523-hifi", |
392 | .playback = { | 389 | .playback = { |
393 | .stream_name = "Playback", | 390 | .stream_name = "Playback", |
394 | .channels_min = 2, /* Mono modes not yet supported */ | 391 | .channels_min = 2, /* Mono modes not yet supported */ |
@@ -398,25 +395,17 @@ struct snd_soc_dai wm8523_dai = { | |||
398 | }, | 395 | }, |
399 | .ops = &wm8523_dai_ops, | 396 | .ops = &wm8523_dai_ops, |
400 | }; | 397 | }; |
401 | EXPORT_SYMBOL_GPL(wm8523_dai); | ||
402 | 398 | ||
403 | #ifdef CONFIG_PM | 399 | #ifdef CONFIG_PM |
404 | static int wm8523_suspend(struct platform_device *pdev, pm_message_t state) | 400 | static int wm8523_suspend(struct snd_soc_codec *codec, pm_message_t state) |
405 | { | 401 | { |
406 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
407 | struct snd_soc_codec *codec = socdev->card->codec; | ||
408 | |||
409 | wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); | 402 | wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); |
410 | return 0; | 403 | return 0; |
411 | } | 404 | } |
412 | 405 | ||
413 | static int wm8523_resume(struct platform_device *pdev) | 406 | static int wm8523_resume(struct snd_soc_codec *codec) |
414 | { | 407 | { |
415 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
416 | struct snd_soc_codec *codec = socdev->card->codec; | ||
417 | |||
418 | wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 408 | wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
419 | |||
420 | return 0; | 409 | return 0; |
421 | } | 410 | } |
422 | #else | 411 | #else |
@@ -424,93 +413,21 @@ static int wm8523_resume(struct platform_device *pdev) | |||
424 | #define wm8523_resume NULL | 413 | #define wm8523_resume NULL |
425 | #endif | 414 | #endif |
426 | 415 | ||
427 | static int wm8523_probe(struct platform_device *pdev) | 416 | static int wm8523_probe(struct snd_soc_codec *codec) |
428 | { | ||
429 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
430 | struct snd_soc_codec *codec; | ||
431 | int ret = 0; | ||
432 | |||
433 | if (wm8523_codec == NULL) { | ||
434 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
435 | return -ENODEV; | ||
436 | } | ||
437 | |||
438 | socdev->card->codec = wm8523_codec; | ||
439 | codec = wm8523_codec; | ||
440 | |||
441 | /* register pcms */ | ||
442 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
443 | if (ret < 0) { | ||
444 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
445 | goto pcm_err; | ||
446 | } | ||
447 | |||
448 | snd_soc_add_controls(codec, wm8523_snd_controls, | ||
449 | ARRAY_SIZE(wm8523_snd_controls)); | ||
450 | wm8523_add_widgets(codec); | ||
451 | |||
452 | return ret; | ||
453 | |||
454 | pcm_err: | ||
455 | return ret; | ||
456 | } | ||
457 | |||
458 | static int wm8523_remove(struct platform_device *pdev) | ||
459 | { | ||
460 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
461 | |||
462 | snd_soc_free_pcms(socdev); | ||
463 | snd_soc_dapm_free(socdev); | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | struct snd_soc_codec_device soc_codec_dev_wm8523 = { | ||
469 | .probe = wm8523_probe, | ||
470 | .remove = wm8523_remove, | ||
471 | .suspend = wm8523_suspend, | ||
472 | .resume = wm8523_resume, | ||
473 | }; | ||
474 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523); | ||
475 | |||
476 | static int wm8523_register(struct wm8523_priv *wm8523, | ||
477 | enum snd_soc_control_type control) | ||
478 | { | 417 | { |
479 | int ret; | 418 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
480 | struct snd_soc_codec *codec = &wm8523->codec; | 419 | int ret, i; |
481 | int i; | ||
482 | |||
483 | if (wm8523_codec) { | ||
484 | dev_err(codec->dev, "Another WM8523 is registered\n"); | ||
485 | ret = -EINVAL; | ||
486 | goto err; | ||
487 | } | ||
488 | |||
489 | mutex_init(&codec->mutex); | ||
490 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
491 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
492 | |||
493 | snd_soc_codec_set_drvdata(codec, wm8523); | ||
494 | codec->name = "WM8523"; | ||
495 | codec->owner = THIS_MODULE; | ||
496 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
497 | codec->set_bias_level = wm8523_set_bias_level; | ||
498 | codec->dai = &wm8523_dai; | ||
499 | codec->num_dai = 1; | ||
500 | codec->reg_cache_size = WM8523_REGISTER_COUNT; | ||
501 | codec->reg_cache = &wm8523->reg_cache; | ||
502 | codec->volatile_register = wm8523_volatile_register; | ||
503 | 420 | ||
421 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
422 | codec->control_data = wm8523->control_data; | ||
504 | wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; | 423 | wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; |
505 | wm8523->rate_constraint.count = | 424 | wm8523->rate_constraint.count = |
506 | ARRAY_SIZE(wm8523->rate_constraint_list); | 425 | ARRAY_SIZE(wm8523->rate_constraint_list); |
507 | 426 | ||
508 | memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg)); | 427 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type); |
509 | |||
510 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); | ||
511 | if (ret != 0) { | 428 | if (ret != 0) { |
512 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 429 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
513 | goto err; | 430 | return ret; |
514 | } | 431 | } |
515 | 432 | ||
516 | for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) | 433 | for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) |
@@ -520,7 +437,7 @@ static int wm8523_register(struct wm8523_priv *wm8523, | |||
520 | wm8523->supplies); | 437 | wm8523->supplies); |
521 | if (ret != 0) { | 438 | if (ret != 0) { |
522 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 439 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); |
523 | goto err; | 440 | return ret; |
524 | } | 441 | } |
525 | 442 | ||
526 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), | 443 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), |
@@ -555,8 +472,6 @@ static int wm8523_register(struct wm8523_priv *wm8523, | |||
555 | goto err_enable; | 472 | goto err_enable; |
556 | } | 473 | } |
557 | 474 | ||
558 | wm8523_dai.dev = codec->dev; | ||
559 | |||
560 | /* Change some default settings - latch VU and enable ZC */ | 475 | /* Change some default settings - latch VU and enable ZC */ |
561 | wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; | 476 | wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; |
562 | wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; | 477 | wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; |
@@ -566,69 +481,68 @@ static int wm8523_register(struct wm8523_priv *wm8523, | |||
566 | /* Bias level configuration will have done an extra enable */ | 481 | /* Bias level configuration will have done an extra enable */ |
567 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | 482 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); |
568 | 483 | ||
569 | wm8523_codec = codec; | 484 | snd_soc_add_controls(codec, wm8523_snd_controls, |
570 | 485 | ARRAY_SIZE(wm8523_snd_controls)); | |
571 | ret = snd_soc_register_codec(codec); | 486 | wm8523_add_widgets(codec); |
572 | if (ret != 0) { | ||
573 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
574 | goto err_enable; | ||
575 | } | ||
576 | |||
577 | ret = snd_soc_register_dai(&wm8523_dai); | ||
578 | if (ret != 0) { | ||
579 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
580 | goto err_codec; | ||
581 | } | ||
582 | 487 | ||
583 | return 0; | 488 | return 0; |
584 | 489 | ||
585 | err_codec: | ||
586 | snd_soc_unregister_codec(codec); | ||
587 | err_enable: | 490 | err_enable: |
588 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | 491 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); |
589 | err_get: | 492 | err_get: |
590 | regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | 493 | regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); |
591 | err: | 494 | |
592 | kfree(wm8523); | ||
593 | return ret; | 495 | return ret; |
594 | } | 496 | } |
595 | 497 | ||
596 | static void wm8523_unregister(struct wm8523_priv *wm8523) | 498 | static int wm8523_remove(struct snd_soc_codec *codec) |
597 | { | 499 | { |
598 | wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF); | 500 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
501 | |||
502 | wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
599 | regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | 503 | regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); |
600 | snd_soc_unregister_dai(&wm8523_dai); | 504 | return 0; |
601 | snd_soc_unregister_codec(&wm8523->codec); | ||
602 | kfree(wm8523); | ||
603 | wm8523_codec = NULL; | ||
604 | } | 505 | } |
605 | 506 | ||
507 | static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { | ||
508 | .probe = wm8523_probe, | ||
509 | .remove = wm8523_remove, | ||
510 | .suspend = wm8523_suspend, | ||
511 | .resume = wm8523_resume, | ||
512 | .set_bias_level = wm8523_set_bias_level, | ||
513 | .reg_cache_size = WM8523_REGISTER_COUNT, | ||
514 | .reg_word_size = sizeof(u16), | ||
515 | .reg_cache_default = wm8523_reg, | ||
516 | .volatile_register = wm8523_volatile_register, | ||
517 | }; | ||
518 | |||
606 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 519 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
607 | static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, | 520 | static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, |
608 | const struct i2c_device_id *id) | 521 | const struct i2c_device_id *id) |
609 | { | 522 | { |
610 | struct wm8523_priv *wm8523; | 523 | struct wm8523_priv *wm8523; |
611 | struct snd_soc_codec *codec; | 524 | int ret; |
612 | 525 | ||
613 | wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); | 526 | wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); |
614 | if (wm8523 == NULL) | 527 | if (wm8523 == NULL) |
615 | return -ENOMEM; | 528 | return -ENOMEM; |
616 | 529 | ||
617 | codec = &wm8523->codec; | ||
618 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
619 | |||
620 | i2c_set_clientdata(i2c, wm8523); | 530 | i2c_set_clientdata(i2c, wm8523); |
621 | codec->control_data = i2c; | 531 | wm8523->control_data = i2c; |
532 | wm8523->control_type = SND_SOC_I2C; | ||
622 | 533 | ||
623 | codec->dev = &i2c->dev; | 534 | ret = snd_soc_register_codec(&i2c->dev, |
535 | &soc_codec_dev_wm8523, &wm8523_dai, 1); | ||
536 | if (ret < 0) | ||
537 | kfree(wm8523); | ||
538 | return ret; | ||
624 | 539 | ||
625 | return wm8523_register(wm8523, SND_SOC_I2C); | ||
626 | } | 540 | } |
627 | 541 | ||
628 | static __devexit int wm8523_i2c_remove(struct i2c_client *client) | 542 | static __devexit int wm8523_i2c_remove(struct i2c_client *client) |
629 | { | 543 | { |
630 | struct wm8523_priv *wm8523 = i2c_get_clientdata(client); | 544 | snd_soc_unregister_codec(&client->dev); |
631 | wm8523_unregister(wm8523); | 545 | kfree(i2c_get_clientdata(client)); |
632 | return 0; | 546 | return 0; |
633 | } | 547 | } |
634 | 548 | ||
@@ -640,7 +554,7 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id); | |||
640 | 554 | ||
641 | static struct i2c_driver wm8523_i2c_driver = { | 555 | static struct i2c_driver wm8523_i2c_driver = { |
642 | .driver = { | 556 | .driver = { |
643 | .name = "WM8523", | 557 | .name = "wm8523-codec", |
644 | .owner = THIS_MODULE, | 558 | .owner = THIS_MODULE, |
645 | }, | 559 | }, |
646 | .probe = wm8523_i2c_probe, | 560 | .probe = wm8523_i2c_probe, |
diff --git a/sound/soc/codecs/wm8523.h b/sound/soc/codecs/wm8523.h index 1aa9ce3e1357..4d5b1eb8f2fc 100644 --- a/sound/soc/codecs/wm8523.h +++ b/sound/soc/codecs/wm8523.h | |||
@@ -154,7 +154,4 @@ | |||
154 | #define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */ | 154 | #define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */ |
155 | #define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */ | 155 | #define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */ |
156 | 156 | ||
157 | extern struct snd_soc_dai wm8523_dai; | ||
158 | extern struct snd_soc_codec_device soc_codec_dev_wm8523; | ||
159 | |||
160 | #endif | 157 | #endif |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index c3571ee5c11b..cae58941a32f 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -199,7 +199,8 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { | |||
199 | 199 | ||
200 | /* codec private data */ | 200 | /* codec private data */ |
201 | struct wm8580_priv { | 201 | struct wm8580_priv { |
202 | struct snd_soc_codec codec; | 202 | enum snd_soc_control_type control_type; |
203 | void *control_data; | ||
203 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; | 204 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; |
204 | u16 reg_cache[WM8580_MAX_REGISTER + 1]; | 205 | u16 reg_cache[WM8580_MAX_REGISTER + 1]; |
205 | struct pll_state a; | 206 | struct pll_state a; |
@@ -484,9 +485,8 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | |||
484 | struct snd_soc_dai *dai) | 485 | struct snd_soc_dai *dai) |
485 | { | 486 | { |
486 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 487 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
487 | struct snd_soc_device *socdev = rtd->socdev; | 488 | struct snd_soc_codec *codec = rtd->codec; |
488 | struct snd_soc_codec *codec = socdev->card->codec; | 489 | u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->driver->id); |
489 | u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id); | ||
490 | 490 | ||
491 | paifb &= ~WM8580_AIF_LENGTH_MASK; | 491 | paifb &= ~WM8580_AIF_LENGTH_MASK; |
492 | /* bit size */ | 492 | /* bit size */ |
@@ -506,7 +506,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | |||
506 | return -EINVAL; | 506 | return -EINVAL; |
507 | } | 507 | } |
508 | 508 | ||
509 | snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb); | 509 | snd_soc_write(codec, WM8580_PAIF3 + dai->driver->id, paifb); |
510 | return 0; | 510 | return 0; |
511 | } | 511 | } |
512 | 512 | ||
@@ -518,8 +518,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, | |||
518 | unsigned int aifb; | 518 | unsigned int aifb; |
519 | int can_invert_lrclk; | 519 | int can_invert_lrclk; |
520 | 520 | ||
521 | aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id); | 521 | aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->driver->id); |
522 | aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id); | 522 | aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->driver->id); |
523 | 523 | ||
524 | aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); | 524 | aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); |
525 | 525 | ||
@@ -585,8 +585,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, | |||
585 | return -EINVAL; | 585 | return -EINVAL; |
586 | } | 586 | } |
587 | 587 | ||
588 | snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); | 588 | snd_soc_write(codec, WM8580_PAIF1 + codec_dai->driver->id, aifa); |
589 | snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); | 589 | snd_soc_write(codec, WM8580_PAIF3 + codec_dai->driver->id, aifb); |
590 | 590 | ||
591 | return 0; | 591 | return 0; |
592 | } | 592 | } |
@@ -746,10 +746,10 @@ static struct snd_soc_dai_ops wm8580_dai_ops_capture = { | |||
746 | .set_pll = wm8580_set_dai_pll, | 746 | .set_pll = wm8580_set_dai_pll, |
747 | }; | 747 | }; |
748 | 748 | ||
749 | struct snd_soc_dai wm8580_dai[] = { | 749 | static struct snd_soc_dai_driver wm8580_dai[] = { |
750 | { | 750 | { |
751 | .name = "WM8580 PAIFRX", | 751 | .name = "wm8580-hifi-playback", |
752 | .id = 0, | 752 | .id = WM8580_DAI_PAIFRX, |
753 | .playback = { | 753 | .playback = { |
754 | .stream_name = "Playback", | 754 | .stream_name = "Playback", |
755 | .channels_min = 1, | 755 | .channels_min = 1, |
@@ -760,8 +760,8 @@ struct snd_soc_dai wm8580_dai[] = { | |||
760 | .ops = &wm8580_dai_ops_playback, | 760 | .ops = &wm8580_dai_ops_playback, |
761 | }, | 761 | }, |
762 | { | 762 | { |
763 | .name = "WM8580 PAIFTX", | 763 | .name = "wm8580-hifi-capture", |
764 | .id = 1, | 764 | .id = WM8580_DAI_PAIFTX, |
765 | .capture = { | 765 | .capture = { |
766 | .stream_name = "Capture", | 766 | .stream_name = "Capture", |
767 | .channels_min = 2, | 767 | .channels_min = 2, |
@@ -772,90 +772,17 @@ struct snd_soc_dai wm8580_dai[] = { | |||
772 | .ops = &wm8580_dai_ops_capture, | 772 | .ops = &wm8580_dai_ops_capture, |
773 | }, | 773 | }, |
774 | }; | 774 | }; |
775 | EXPORT_SYMBOL_GPL(wm8580_dai); | ||
776 | 775 | ||
777 | static struct snd_soc_codec *wm8580_codec; | 776 | static int wm8580_probe(struct snd_soc_codec *codec) |
778 | |||
779 | static int wm8580_probe(struct platform_device *pdev) | ||
780 | { | 777 | { |
781 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 778 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
782 | struct snd_soc_codec *codec; | 779 | int ret = 0,i; |
783 | int ret = 0; | ||
784 | |||
785 | if (wm8580_codec == NULL) { | ||
786 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
787 | return -ENODEV; | ||
788 | } | ||
789 | |||
790 | socdev->card->codec = wm8580_codec; | ||
791 | codec = wm8580_codec; | ||
792 | |||
793 | /* register pcms */ | ||
794 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
795 | if (ret < 0) { | ||
796 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
797 | goto pcm_err; | ||
798 | } | ||
799 | |||
800 | snd_soc_add_controls(codec, wm8580_snd_controls, | ||
801 | ARRAY_SIZE(wm8580_snd_controls)); | ||
802 | wm8580_add_widgets(codec); | ||
803 | |||
804 | return ret; | ||
805 | |||
806 | pcm_err: | ||
807 | return ret; | ||
808 | } | ||
809 | |||
810 | /* power down chip */ | ||
811 | static int wm8580_remove(struct platform_device *pdev) | ||
812 | { | ||
813 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
814 | |||
815 | snd_soc_free_pcms(socdev); | ||
816 | snd_soc_dapm_free(socdev); | ||
817 | |||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | struct snd_soc_codec_device soc_codec_dev_wm8580 = { | ||
822 | .probe = wm8580_probe, | ||
823 | .remove = wm8580_remove, | ||
824 | }; | ||
825 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); | ||
826 | |||
827 | static int wm8580_register(struct wm8580_priv *wm8580, | ||
828 | enum snd_soc_control_type control) | ||
829 | { | ||
830 | int ret, i; | ||
831 | struct snd_soc_codec *codec = &wm8580->codec; | ||
832 | |||
833 | if (wm8580_codec) { | ||
834 | dev_err(codec->dev, "Another WM8580 is registered\n"); | ||
835 | ret = -EINVAL; | ||
836 | goto err; | ||
837 | } | ||
838 | |||
839 | mutex_init(&codec->mutex); | ||
840 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
841 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
842 | |||
843 | snd_soc_codec_set_drvdata(codec, wm8580); | ||
844 | codec->name = "WM8580"; | ||
845 | codec->owner = THIS_MODULE; | ||
846 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
847 | codec->set_bias_level = wm8580_set_bias_level; | ||
848 | codec->dai = wm8580_dai; | ||
849 | codec->num_dai = ARRAY_SIZE(wm8580_dai); | ||
850 | codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache); | ||
851 | codec->reg_cache = &wm8580->reg_cache; | ||
852 | |||
853 | memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); | ||
854 | 780 | ||
855 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 781 | codec->control_data = wm8580->control_data; |
782 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type); | ||
856 | if (ret < 0) { | 783 | if (ret < 0) { |
857 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 784 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
858 | goto err; | 785 | return ret; |
859 | } | 786 | } |
860 | 787 | ||
861 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) | 788 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) |
@@ -865,7 +792,7 @@ static int wm8580_register(struct wm8580_priv *wm8580, | |||
865 | wm8580->supplies); | 792 | wm8580->supplies); |
866 | if (ret != 0) { | 793 | if (ret != 0) { |
867 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 794 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); |
868 | goto err; | 795 | return ret; |
869 | } | 796 | } |
870 | 797 | ||
871 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), | 798 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), |
@@ -882,74 +809,69 @@ static int wm8580_register(struct wm8580_priv *wm8580, | |||
882 | goto err_regulator_enable; | 809 | goto err_regulator_enable; |
883 | } | 810 | } |
884 | 811 | ||
885 | for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) | ||
886 | wm8580_dai[i].dev = codec->dev; | ||
887 | |||
888 | wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 812 | wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
889 | 813 | ||
890 | wm8580_codec = codec; | 814 | snd_soc_add_controls(codec, wm8580_snd_controls, |
891 | 815 | ARRAY_SIZE(wm8580_snd_controls)); | |
892 | ret = snd_soc_register_codec(codec); | 816 | wm8580_add_widgets(codec); |
893 | if (ret != 0) { | ||
894 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
895 | goto err_regulator_enable; | ||
896 | } | ||
897 | |||
898 | ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | ||
899 | if (ret != 0) { | ||
900 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
901 | goto err_codec; | ||
902 | } | ||
903 | 817 | ||
904 | return 0; | 818 | return 0; |
905 | 819 | ||
906 | err_codec: | ||
907 | snd_soc_unregister_codec(codec); | ||
908 | err_regulator_enable: | 820 | err_regulator_enable: |
909 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 821 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
910 | err_regulator_get: | 822 | err_regulator_get: |
911 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 823 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
912 | err: | ||
913 | kfree(wm8580); | ||
914 | return ret; | 824 | return ret; |
915 | } | 825 | } |
916 | 826 | ||
917 | static void wm8580_unregister(struct wm8580_priv *wm8580) | 827 | /* power down chip */ |
828 | static int wm8580_remove(struct snd_soc_codec *codec) | ||
918 | { | 829 | { |
919 | wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); | 830 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
920 | snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | 831 | |
921 | snd_soc_unregister_codec(&wm8580->codec); | 832 | wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); |
833 | |||
922 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 834 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
923 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 835 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
924 | kfree(wm8580); | 836 | |
925 | wm8580_codec = NULL; | 837 | return 0; |
926 | } | 838 | } |
927 | 839 | ||
840 | static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { | ||
841 | .probe = wm8580_probe, | ||
842 | .remove = wm8580_remove, | ||
843 | .set_bias_level = wm8580_set_bias_level, | ||
844 | .reg_cache_size = sizeof(wm8580_reg), | ||
845 | .reg_word_size = sizeof(u16), | ||
846 | .reg_cache_default = &wm8580_reg, | ||
847 | }; | ||
848 | |||
928 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 849 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
929 | static int wm8580_i2c_probe(struct i2c_client *i2c, | 850 | static int wm8580_i2c_probe(struct i2c_client *i2c, |
930 | const struct i2c_device_id *id) | 851 | const struct i2c_device_id *id) |
931 | { | 852 | { |
932 | struct wm8580_priv *wm8580; | 853 | struct wm8580_priv *wm8580; |
933 | struct snd_soc_codec *codec; | 854 | int ret; |
934 | 855 | ||
935 | wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); | 856 | wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); |
936 | if (wm8580 == NULL) | 857 | if (wm8580 == NULL) |
937 | return -ENOMEM; | 858 | return -ENOMEM; |
938 | 859 | ||
939 | codec = &wm8580->codec; | ||
940 | |||
941 | i2c_set_clientdata(i2c, wm8580); | 860 | i2c_set_clientdata(i2c, wm8580); |
942 | codec->control_data = i2c; | 861 | wm8580->control_data = i2c; |
943 | 862 | wm8580->control_type = SND_SOC_I2C; | |
944 | codec->dev = &i2c->dev; | ||
945 | 863 | ||
946 | return wm8580_register(wm8580, SND_SOC_I2C); | 864 | ret = snd_soc_register_codec(&i2c->dev, |
865 | &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); | ||
866 | if (ret < 0) | ||
867 | kfree(wm8580); | ||
868 | return ret; | ||
947 | } | 869 | } |
948 | 870 | ||
949 | static int wm8580_i2c_remove(struct i2c_client *client) | 871 | static int wm8580_i2c_remove(struct i2c_client *client) |
950 | { | 872 | { |
951 | struct wm8580_priv *wm8580 = i2c_get_clientdata(client); | 873 | snd_soc_unregister_codec(&client->dev); |
952 | wm8580_unregister(wm8580); | 874 | kfree(i2c_get_clientdata(client)); |
953 | return 0; | 875 | return 0; |
954 | } | 876 | } |
955 | 877 | ||
@@ -961,7 +883,7 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); | |||
961 | 883 | ||
962 | static struct i2c_driver wm8580_i2c_driver = { | 884 | static struct i2c_driver wm8580_i2c_driver = { |
963 | .driver = { | 885 | .driver = { |
964 | .name = "wm8580", | 886 | .name = "wm8580-codec", |
965 | .owner = THIS_MODULE, | 887 | .owner = THIS_MODULE, |
966 | }, | 888 | }, |
967 | .probe = wm8580_i2c_probe, | 889 | .probe = wm8580_i2c_probe, |
@@ -972,7 +894,7 @@ static struct i2c_driver wm8580_i2c_driver = { | |||
972 | 894 | ||
973 | static int __init wm8580_modinit(void) | 895 | static int __init wm8580_modinit(void) |
974 | { | 896 | { |
975 | int ret; | 897 | int ret = 0; |
976 | 898 | ||
977 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 899 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
978 | ret = i2c_add_driver(&wm8580_i2c_driver); | 900 | ret = i2c_add_driver(&wm8580_i2c_driver); |
@@ -981,7 +903,7 @@ static int __init wm8580_modinit(void) | |||
981 | } | 903 | } |
982 | #endif | 904 | #endif |
983 | 905 | ||
984 | return 0; | 906 | return ret; |
985 | } | 907 | } |
986 | module_init(wm8580_modinit); | 908 | module_init(wm8580_modinit); |
987 | 909 | ||
diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h index 0dfb5ddde6a2..8328ef667593 100644 --- a/sound/soc/codecs/wm8580.h +++ b/sound/soc/codecs/wm8580.h | |||
@@ -31,8 +31,5 @@ | |||
31 | #define WM8580_DAI_PAIFRX 0 | 31 | #define WM8580_DAI_PAIFRX 0 |
32 | #define WM8580_DAI_PAIFTX 1 | 32 | #define WM8580_DAI_PAIFTX 1 |
33 | 33 | ||
34 | extern struct snd_soc_dai wm8580_dai[]; | ||
35 | extern struct snd_soc_codec_device soc_codec_dev_wm8580; | ||
36 | |||
37 | #endif | 34 | #endif |
38 | 35 | ||
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index e2dba07f0260..8d942b3b111f 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -31,11 +31,10 @@ | |||
31 | 31 | ||
32 | #include "wm8711.h" | 32 | #include "wm8711.h" |
33 | 33 | ||
34 | static struct snd_soc_codec *wm8711_codec; | ||
35 | |||
36 | /* codec private data */ | 34 | /* codec private data */ |
37 | struct wm8711_priv { | 35 | struct wm8711_priv { |
38 | struct snd_soc_codec codec; | 36 | enum snd_soc_control_type bus_type; |
37 | void *control_data; | ||
39 | u16 reg_cache[WM8711_CACHEREGNUM]; | 38 | u16 reg_cache[WM8711_CACHEREGNUM]; |
40 | unsigned int sysclk; | 39 | unsigned int sysclk; |
41 | }; | 40 | }; |
@@ -163,7 +162,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream, | |||
163 | struct snd_soc_dai *dai) | 162 | struct snd_soc_dai *dai) |
164 | { | 163 | { |
165 | struct snd_soc_codec *codec = dai->codec; | 164 | struct snd_soc_codec *codec = dai->codec; |
166 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); | 165 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); |
167 | u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc; | 166 | u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc; |
168 | int i = get_coeff(wm8711->sysclk, params_rate(params)); | 167 | int i = get_coeff(wm8711->sysclk, params_rate(params)); |
169 | u16 srate = (coeff_div[i].sr << 2) | | 168 | u16 srate = (coeff_div[i].sr << 2) | |
@@ -227,7 +226,7 @@ static int wm8711_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
227 | int clk_id, unsigned int freq, int dir) | 226 | int clk_id, unsigned int freq, int dir) |
228 | { | 227 | { |
229 | struct snd_soc_codec *codec = codec_dai->codec; | 228 | struct snd_soc_codec *codec = codec_dai->codec; |
230 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); | 229 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); |
231 | 230 | ||
232 | switch (freq) { | 231 | switch (freq) { |
233 | case 11289600: | 232 | case 11289600: |
@@ -338,8 +337,8 @@ static struct snd_soc_dai_ops wm8711_ops = { | |||
338 | .set_fmt = wm8711_set_dai_fmt, | 337 | .set_fmt = wm8711_set_dai_fmt, |
339 | }; | 338 | }; |
340 | 339 | ||
341 | struct snd_soc_dai wm8711_dai = { | 340 | static struct snd_soc_dai_driver wm8711_dai = { |
342 | .name = "WM8711", | 341 | .name = "wm8711-hifi", |
343 | .playback = { | 342 | .playback = { |
344 | .stream_name = "Playback", | 343 | .stream_name = "Playback", |
345 | .channels_min = 1, | 344 | .channels_min = 1, |
@@ -349,22 +348,16 @@ struct snd_soc_dai wm8711_dai = { | |||
349 | }, | 348 | }, |
350 | .ops = &wm8711_ops, | 349 | .ops = &wm8711_ops, |
351 | }; | 350 | }; |
352 | EXPORT_SYMBOL_GPL(wm8711_dai); | ||
353 | 351 | ||
354 | static int wm8711_suspend(struct platform_device *pdev, pm_message_t state) | 352 | static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state) |
355 | { | 353 | { |
356 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
357 | struct snd_soc_codec *codec = socdev->card->codec; | ||
358 | |||
359 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); | 354 | snd_soc_write(codec, WM8711_ACTIVE, 0x0); |
360 | wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); | 355 | wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); |
361 | return 0; | 356 | return 0; |
362 | } | 357 | } |
363 | 358 | ||
364 | static int wm8711_resume(struct platform_device *pdev) | 359 | static int wm8711_resume(struct snd_soc_codec *codec) |
365 | { | 360 | { |
366 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
367 | struct snd_soc_codec *codec = socdev->card->codec; | ||
368 | int i; | 361 | int i; |
369 | u8 data[2]; | 362 | u8 data[2]; |
370 | u16 *cache = codec->reg_cache; | 363 | u16 *cache = codec->reg_cache; |
@@ -380,99 +373,24 @@ static int wm8711_resume(struct platform_device *pdev) | |||
380 | return 0; | 373 | return 0; |
381 | } | 374 | } |
382 | 375 | ||
383 | static int wm8711_probe(struct platform_device *pdev) | 376 | static int wm8711_probe(struct snd_soc_codec *codec) |
384 | { | 377 | { |
385 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 378 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); |
386 | struct snd_soc_codec *codec; | 379 | int ret, reg; |
387 | int ret = 0; | ||
388 | |||
389 | if (wm8711_codec == NULL) { | ||
390 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
391 | return -ENODEV; | ||
392 | } | ||
393 | |||
394 | socdev->card->codec = wm8711_codec; | ||
395 | codec = wm8711_codec; | ||
396 | |||
397 | /* register pcms */ | ||
398 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
399 | if (ret < 0) { | ||
400 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
401 | goto pcm_err; | ||
402 | } | ||
403 | |||
404 | snd_soc_add_controls(codec, wm8711_snd_controls, | ||
405 | ARRAY_SIZE(wm8711_snd_controls)); | ||
406 | wm8711_add_widgets(codec); | ||
407 | |||
408 | return ret; | ||
409 | |||
410 | pcm_err: | ||
411 | return ret; | ||
412 | } | ||
413 | |||
414 | /* power down chip */ | ||
415 | static int wm8711_remove(struct platform_device *pdev) | ||
416 | { | ||
417 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
418 | |||
419 | snd_soc_free_pcms(socdev); | ||
420 | snd_soc_dapm_free(socdev); | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | struct snd_soc_codec_device soc_codec_dev_wm8711 = { | ||
426 | .probe = wm8711_probe, | ||
427 | .remove = wm8711_remove, | ||
428 | .suspend = wm8711_suspend, | ||
429 | .resume = wm8711_resume, | ||
430 | }; | ||
431 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711); | ||
432 | |||
433 | static int wm8711_register(struct wm8711_priv *wm8711, | ||
434 | enum snd_soc_control_type control) | ||
435 | { | ||
436 | int ret; | ||
437 | struct snd_soc_codec *codec = &wm8711->codec; | ||
438 | u16 reg; | ||
439 | |||
440 | if (wm8711_codec) { | ||
441 | dev_err(codec->dev, "Another WM8711 is registered\n"); | ||
442 | ret = -EINVAL; | ||
443 | goto err; | ||
444 | } | ||
445 | |||
446 | mutex_init(&codec->mutex); | ||
447 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
448 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
449 | |||
450 | snd_soc_codec_set_drvdata(codec, wm8711); | ||
451 | codec->name = "WM8711"; | ||
452 | codec->owner = THIS_MODULE; | ||
453 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
454 | codec->set_bias_level = wm8711_set_bias_level; | ||
455 | codec->dai = &wm8711_dai; | ||
456 | codec->num_dai = 1; | ||
457 | codec->reg_cache_size = WM8711_CACHEREGNUM; | ||
458 | codec->reg_cache = &wm8711->reg_cache; | ||
459 | |||
460 | memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg)); | ||
461 | 380 | ||
462 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 381 | codec->control_data = wm8711->control_data; |
382 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type); | ||
463 | if (ret < 0) { | 383 | if (ret < 0) { |
464 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 384 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
465 | goto err; | 385 | return ret; |
466 | } | 386 | } |
467 | 387 | ||
468 | ret = wm8711_reset(codec); | 388 | ret = wm8711_reset(codec); |
469 | if (ret < 0) { | 389 | if (ret < 0) { |
470 | dev_err(codec->dev, "Failed to issue reset\n"); | 390 | dev_err(codec->dev, "Failed to issue reset\n"); |
471 | goto err; | 391 | return ret; |
472 | } | 392 | } |
473 | 393 | ||
474 | wm8711_dai.dev = codec->dev; | ||
475 | |||
476 | wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 394 | wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
477 | 395 | ||
478 | /* Latch the update bits */ | 396 | /* Latch the update bits */ |
@@ -481,69 +399,63 @@ static int wm8711_register(struct wm8711_priv *wm8711, | |||
481 | reg = snd_soc_read(codec, WM8711_ROUT1V); | 399 | reg = snd_soc_read(codec, WM8711_ROUT1V); |
482 | snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100); | 400 | snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100); |
483 | 401 | ||
484 | wm8711_codec = codec; | 402 | snd_soc_add_controls(codec, wm8711_snd_controls, |
485 | 403 | ARRAY_SIZE(wm8711_snd_controls)); | |
486 | ret = snd_soc_register_codec(codec); | 404 | wm8711_add_widgets(codec); |
487 | if (ret != 0) { | ||
488 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
489 | goto err; | ||
490 | } | ||
491 | |||
492 | ret = snd_soc_register_dai(&wm8711_dai); | ||
493 | if (ret != 0) { | ||
494 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
495 | goto err_codec; | ||
496 | } | ||
497 | |||
498 | return 0; | ||
499 | 405 | ||
500 | err_codec: | ||
501 | snd_soc_unregister_codec(codec); | ||
502 | err: | ||
503 | kfree(wm8711); | ||
504 | return ret; | 406 | return ret; |
407 | |||
505 | } | 408 | } |
506 | 409 | ||
507 | static void wm8711_unregister(struct wm8711_priv *wm8711) | 410 | /* power down chip */ |
411 | static int wm8711_remove(struct snd_soc_codec *codec) | ||
508 | { | 412 | { |
509 | wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF); | 413 | wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); |
510 | snd_soc_unregister_dai(&wm8711_dai); | 414 | return 0; |
511 | snd_soc_unregister_codec(&wm8711->codec); | ||
512 | kfree(wm8711); | ||
513 | wm8711_codec = NULL; | ||
514 | } | 415 | } |
515 | 416 | ||
417 | static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { | ||
418 | .probe = wm8711_probe, | ||
419 | .remove = wm8711_remove, | ||
420 | .suspend = wm8711_suspend, | ||
421 | .resume = wm8711_resume, | ||
422 | .set_bias_level = wm8711_set_bias_level, | ||
423 | .reg_cache_size = sizeof(wm8711_reg), | ||
424 | .reg_word_size = sizeof(u16), | ||
425 | .reg_cache_default = wm8711_reg, | ||
426 | }; | ||
427 | |||
516 | #if defined(CONFIG_SPI_MASTER) | 428 | #if defined(CONFIG_SPI_MASTER) |
517 | static int __devinit wm8711_spi_probe(struct spi_device *spi) | 429 | static int __devinit wm8711_spi_probe(struct spi_device *spi) |
518 | { | 430 | { |
519 | struct snd_soc_codec *codec; | ||
520 | struct wm8711_priv *wm8711; | 431 | struct wm8711_priv *wm8711; |
432 | int ret; | ||
521 | 433 | ||
522 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); | 434 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); |
523 | if (wm8711 == NULL) | 435 | if (wm8711 == NULL) |
524 | return -ENOMEM; | 436 | return -ENOMEM; |
525 | 437 | ||
526 | codec = &wm8711->codec; | 438 | spi_set_drvdata(spi, wm8711); |
527 | codec->control_data = spi; | 439 | wm8711->control_data = spi; |
528 | codec->dev = &spi->dev; | 440 | wm8711->bus_type = SND_SOC_SPI; |
529 | 441 | ||
530 | dev_set_drvdata(&spi->dev, wm8711); | 442 | ret = snd_soc_register_codec(&spi->dev, |
531 | 443 | &soc_codec_dev_wm8711, &wm8711_dai, 1); | |
532 | return wm8711_register(wm8711, SND_SOC_SPI); | 444 | if (ret < 0) |
445 | kfree(wm8711); | ||
446 | return ret; | ||
533 | } | 447 | } |
534 | 448 | ||
535 | static int __devexit wm8711_spi_remove(struct spi_device *spi) | 449 | static int __devexit wm8711_spi_remove(struct spi_device *spi) |
536 | { | 450 | { |
537 | struct wm8711_priv *wm8711 = dev_get_drvdata(&spi->dev); | 451 | snd_soc_unregister_codec(&spi->dev); |
538 | 452 | kfree(spi_get_drvdata(spi)); | |
539 | wm8711_unregister(wm8711); | ||
540 | |||
541 | return 0; | 453 | return 0; |
542 | } | 454 | } |
543 | 455 | ||
544 | static struct spi_driver wm8711_spi_driver = { | 456 | static struct spi_driver wm8711_spi_driver = { |
545 | .driver = { | 457 | .driver = { |
546 | .name = "wm8711", | 458 | .name = "wm8711-codec", |
547 | .bus = &spi_bus_type, | 459 | .bus = &spi_bus_type, |
548 | .owner = THIS_MODULE, | 460 | .owner = THIS_MODULE, |
549 | }, | 461 | }, |
@@ -553,31 +465,31 @@ static struct spi_driver wm8711_spi_driver = { | |||
553 | #endif /* CONFIG_SPI_MASTER */ | 465 | #endif /* CONFIG_SPI_MASTER */ |
554 | 466 | ||
555 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 467 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
556 | static __devinit int wm8711_i2c_probe(struct i2c_client *i2c, | 468 | static __devinit int wm8711_i2c_probe(struct i2c_client *client, |
557 | const struct i2c_device_id *id) | 469 | const struct i2c_device_id *id) |
558 | { | 470 | { |
559 | struct wm8711_priv *wm8711; | 471 | struct wm8711_priv *wm8711; |
560 | struct snd_soc_codec *codec; | 472 | int ret; |
561 | 473 | ||
562 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); | 474 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); |
563 | if (wm8711 == NULL) | 475 | if (wm8711 == NULL) |
564 | return -ENOMEM; | 476 | return -ENOMEM; |
565 | 477 | ||
566 | codec = &wm8711->codec; | 478 | i2c_set_clientdata(client, wm8711); |
567 | codec->hw_write = (hw_write_t)i2c_master_send; | 479 | wm8711->control_data = client; |
568 | 480 | wm8711->bus_type = SND_SOC_I2C; | |
569 | i2c_set_clientdata(i2c, wm8711); | ||
570 | codec->control_data = i2c; | ||
571 | 481 | ||
572 | codec->dev = &i2c->dev; | 482 | ret = snd_soc_register_codec(&client->dev, |
573 | 483 | &soc_codec_dev_wm8711, &wm8711_dai, 1); | |
574 | return wm8711_register(wm8711, SND_SOC_I2C); | 484 | if (ret < 0) |
485 | kfree(wm8711); | ||
486 | return ret; | ||
575 | } | 487 | } |
576 | 488 | ||
577 | static __devexit int wm8711_i2c_remove(struct i2c_client *client) | 489 | static __devexit int wm8711_i2c_remove(struct i2c_client *client) |
578 | { | 490 | { |
579 | struct wm8711_priv *wm8711 = i2c_get_clientdata(client); | 491 | snd_soc_unregister_codec(&client->dev); |
580 | wm8711_unregister(wm8711); | 492 | kfree(i2c_get_clientdata(client)); |
581 | return 0; | 493 | return 0; |
582 | } | 494 | } |
583 | 495 | ||
@@ -589,7 +501,7 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); | |||
589 | 501 | ||
590 | static struct i2c_driver wm8711_i2c_driver = { | 502 | static struct i2c_driver wm8711_i2c_driver = { |
591 | .driver = { | 503 | .driver = { |
592 | .name = "WM8711 I2C Codec", | 504 | .name = "wm8711-codec", |
593 | .owner = THIS_MODULE, | 505 | .owner = THIS_MODULE, |
594 | }, | 506 | }, |
595 | .probe = wm8711_i2c_probe, | 507 | .probe = wm8711_i2c_probe, |
diff --git a/sound/soc/codecs/wm8711.h b/sound/soc/codecs/wm8711.h index 381e84a43816..a61db985499f 100644 --- a/sound/soc/codecs/wm8711.h +++ b/sound/soc/codecs/wm8711.h | |||
@@ -36,7 +36,4 @@ struct wm8711_setup_data { | |||
36 | unsigned short i2c_address; | 36 | unsigned short i2c_address; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | extern struct snd_soc_dai wm8711_dai; | ||
40 | extern struct snd_soc_codec_device soc_codec_dev_wm8711; | ||
41 | |||
42 | #endif | 39 | #endif |
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c index 9d1df2628136..6a40080ba701 100644 --- a/sound/soc/codecs/wm8727.c +++ b/sound/soc/codecs/wm8727.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <sound/initval.h> | 23 | #include <sound/initval.h> |
24 | #include <sound/soc.h> | 24 | #include <sound/soc.h> |
25 | 25 | ||
26 | #include "wm8727.h" | ||
27 | /* | 26 | /* |
28 | * Note this is a simple chip with no configuration interface, sample rate is | 27 | * Note this is a simple chip with no configuration interface, sample rate is |
29 | * determined automatically by examining the Master clock and Bit clock ratios | 28 | * determined automatically by examining the Master clock and Bit clock ratios |
@@ -33,8 +32,8 @@ | |||
33 | SNDRV_PCM_RATE_192000) | 32 | SNDRV_PCM_RATE_192000) |
34 | 33 | ||
35 | 34 | ||
36 | struct snd_soc_dai wm8727_dai = { | 35 | static struct snd_soc_dai_driver wm8727_dai = { |
37 | .name = "WM8727", | 36 | .name = "wm8727-hifi", |
38 | .playback = { | 37 | .playback = { |
39 | .stream_name = "Playback", | 38 | .stream_name = "Playback", |
40 | .channels_min = 2, | 39 | .channels_min = 2, |
@@ -43,103 +42,18 @@ struct snd_soc_dai wm8727_dai = { | |||
43 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, | 42 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, |
44 | }, | 43 | }, |
45 | }; | 44 | }; |
46 | EXPORT_SYMBOL_GPL(wm8727_dai); | ||
47 | 45 | ||
48 | static struct snd_soc_codec *wm8727_codec; | 46 | struct snd_soc_codec_driver soc_codec_dev_wm8727; |
49 | 47 | ||
50 | static int wm8727_soc_probe(struct platform_device *pdev) | 48 | static __devinit int wm8727_probe(struct platform_device *pdev) |
51 | { | 49 | { |
52 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 50 | return snd_soc_register_codec(&pdev->dev, |
53 | int ret = 0; | 51 | &soc_codec_dev_wm8727, &wm8727_dai, 1); |
54 | |||
55 | BUG_ON(!wm8727_codec); | ||
56 | |||
57 | socdev->card->codec = wm8727_codec; | ||
58 | |||
59 | /* register pcms */ | ||
60 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
61 | if (ret < 0) { | ||
62 | printk(KERN_ERR "wm8727: failed to create pcms\n"); | ||
63 | goto pcm_err; | ||
64 | } | ||
65 | |||
66 | return ret; | ||
67 | |||
68 | pcm_err: | ||
69 | kfree(socdev->card->codec); | ||
70 | socdev->card->codec = NULL; | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | static int wm8727_soc_remove(struct platform_device *pdev) | ||
75 | { | ||
76 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
77 | |||
78 | snd_soc_free_pcms(socdev); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | struct snd_soc_codec_device soc_codec_dev_wm8727 = { | ||
84 | .probe = wm8727_soc_probe, | ||
85 | .remove = wm8727_soc_remove, | ||
86 | }; | ||
87 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8727); | ||
88 | |||
89 | |||
90 | static __devinit int wm8727_platform_probe(struct platform_device *pdev) | ||
91 | { | ||
92 | struct snd_soc_codec *codec; | ||
93 | int ret; | ||
94 | |||
95 | if (wm8727_codec) { | ||
96 | dev_err(&pdev->dev, "Another WM8727 is registered\n"); | ||
97 | return -EBUSY; | ||
98 | } | ||
99 | |||
100 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
101 | if (codec == NULL) | ||
102 | return -ENOMEM; | ||
103 | wm8727_codec = codec; | ||
104 | |||
105 | platform_set_drvdata(pdev, codec); | ||
106 | |||
107 | mutex_init(&codec->mutex); | ||
108 | codec->dev = &pdev->dev; | ||
109 | codec->name = "WM8727"; | ||
110 | codec->owner = THIS_MODULE; | ||
111 | codec->dai = &wm8727_dai; | ||
112 | codec->num_dai = 1; | ||
113 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
114 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
115 | |||
116 | wm8727_dai.dev = &pdev->dev; | ||
117 | |||
118 | ret = snd_soc_register_codec(codec); | ||
119 | if (ret != 0) { | ||
120 | dev_err(&pdev->dev, "Failed to register CODEC: %d\n", ret); | ||
121 | goto err; | ||
122 | } | ||
123 | |||
124 | ret = snd_soc_register_dai(&wm8727_dai); | ||
125 | if (ret != 0) { | ||
126 | dev_err(&pdev->dev, "Failed to register DAI: %d\n", ret); | ||
127 | goto err_codec; | ||
128 | } | ||
129 | |||
130 | return 0; | ||
131 | |||
132 | err_codec: | ||
133 | snd_soc_unregister_codec(codec); | ||
134 | err: | ||
135 | kfree(codec); | ||
136 | return ret; | ||
137 | } | 52 | } |
138 | 53 | ||
139 | static int __devexit wm8727_platform_remove(struct platform_device *pdev) | 54 | static int __devexit wm8727_remove(struct platform_device *pdev) |
140 | { | 55 | { |
141 | snd_soc_unregister_dai(&wm8727_dai); | 56 | snd_soc_unregister_codec(&pdev->dev); |
142 | snd_soc_unregister_codec(platform_get_drvdata(pdev)); | ||
143 | return 0; | 57 | return 0; |
144 | } | 58 | } |
145 | 59 | ||
@@ -149,8 +63,8 @@ static struct platform_driver wm8727_codec_driver = { | |||
149 | .owner = THIS_MODULE, | 63 | .owner = THIS_MODULE, |
150 | }, | 64 | }, |
151 | 65 | ||
152 | .probe = wm8727_platform_probe, | 66 | .probe = wm8727_probe, |
153 | .remove = __devexit_p(wm8727_platform_remove), | 67 | .remove = __devexit_p(wm8727_remove), |
154 | }; | 68 | }; |
155 | 69 | ||
156 | static int __init wm8727_init(void) | 70 | static int __init wm8727_init(void) |
diff --git a/sound/soc/codecs/wm8727.h b/sound/soc/codecs/wm8727.h deleted file mode 100644 index ee19aa71bcdc..000000000000 --- a/sound/soc/codecs/wm8727.h +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | /* | ||
2 | * wm8727.h | ||
3 | * | ||
4 | * Created on: 15-Oct-2009 | ||
5 | * Author: neil.jones@imgtec.com | ||
6 | * | ||
7 | * Copyright (C) 2009 Imagination Technologies Ltd. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | */ | ||
14 | |||
15 | #ifndef WM8727_H_ | ||
16 | #define WM8727_H_ | ||
17 | |||
18 | extern struct snd_soc_dai wm8727_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8727; | ||
20 | |||
21 | #endif /* WM8727_H_ */ | ||
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 34be2d2b69ef..ae2292444783 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -29,8 +29,6 @@ | |||
29 | 29 | ||
30 | #include "wm8728.h" | 30 | #include "wm8728.h" |
31 | 31 | ||
32 | struct snd_soc_codec_device soc_codec_dev_wm8728; | ||
33 | |||
34 | /* | 32 | /* |
35 | * We can't read the WM8728 register space so we cache them instead. | 33 | * We can't read the WM8728 register space so we cache them instead. |
36 | * Note that the defaults here aren't the physical defaults, we latch | 34 | * Note that the defaults here aren't the physical defaults, we latch |
@@ -44,6 +42,12 @@ static const u16 wm8728_reg_defaults[] = { | |||
44 | 0x100, | 42 | 0x100, |
45 | }; | 43 | }; |
46 | 44 | ||
45 | /* codec private data */ | ||
46 | struct wm8728_priv { | ||
47 | enum snd_soc_control_type control_type; | ||
48 | void *control_data; | ||
49 | }; | ||
50 | |||
47 | static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); | 51 | static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); |
48 | 52 | ||
49 | static const struct snd_kcontrol_new wm8728_snd_controls[] = { | 53 | static const struct snd_kcontrol_new wm8728_snd_controls[] = { |
@@ -96,8 +100,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, | |||
96 | struct snd_soc_dai *dai) | 100 | struct snd_soc_dai *dai) |
97 | { | 101 | { |
98 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 102 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
99 | struct snd_soc_device *socdev = rtd->socdev; | 103 | struct snd_soc_codec *codec = rtd->codec; |
100 | struct snd_soc_codec *codec = socdev->card->codec; | ||
101 | u16 dac = snd_soc_read(codec, WM8728_DACCTL); | 104 | u16 dac = snd_soc_read(codec, WM8728_DACCTL); |
102 | 105 | ||
103 | dac &= ~0x18; | 106 | dac &= ~0x18; |
@@ -210,8 +213,8 @@ static struct snd_soc_dai_ops wm8728_dai_ops = { | |||
210 | .set_fmt = wm8728_set_dai_fmt, | 213 | .set_fmt = wm8728_set_dai_fmt, |
211 | }; | 214 | }; |
212 | 215 | ||
213 | struct snd_soc_dai wm8728_dai = { | 216 | static struct snd_soc_dai_driver wm8728_dai = { |
214 | .name = "WM8728", | 217 | .name = "wm8728-hifi", |
215 | .playback = { | 218 | .playback = { |
216 | .stream_name = "Playback", | 219 | .stream_name = "Playback", |
217 | .channels_min = 2, | 220 | .channels_min = 2, |
@@ -221,63 +224,32 @@ struct snd_soc_dai wm8728_dai = { | |||
221 | }, | 224 | }, |
222 | .ops = &wm8728_dai_ops, | 225 | .ops = &wm8728_dai_ops, |
223 | }; | 226 | }; |
224 | EXPORT_SYMBOL_GPL(wm8728_dai); | ||
225 | 227 | ||
226 | static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) | 228 | static int wm8728_suspend(struct snd_soc_codec *codec, pm_message_t state) |
227 | { | 229 | { |
228 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
229 | struct snd_soc_codec *codec = socdev->card->codec; | ||
230 | |||
231 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); | 230 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); |
232 | 231 | ||
233 | return 0; | 232 | return 0; |
234 | } | 233 | } |
235 | 234 | ||
236 | static int wm8728_resume(struct platform_device *pdev) | 235 | static int wm8728_resume(struct snd_soc_codec *codec) |
237 | { | 236 | { |
238 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
239 | struct snd_soc_codec *codec = socdev->card->codec; | ||
240 | |||
241 | wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 237 | wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
242 | 238 | ||
243 | return 0; | 239 | return 0; |
244 | } | 240 | } |
245 | 241 | ||
246 | /* | 242 | static int wm8728_probe(struct snd_soc_codec *codec) |
247 | * initialise the WM8728 driver | ||
248 | * register the mixer and dsp interfaces with the kernel | ||
249 | */ | ||
250 | static int wm8728_init(struct snd_soc_device *socdev, | ||
251 | enum snd_soc_control_type control) | ||
252 | { | 243 | { |
253 | struct snd_soc_codec *codec = socdev->card->codec; | 244 | struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); |
254 | int ret = 0; | 245 | int ret; |
255 | |||
256 | codec->name = "WM8728"; | ||
257 | codec->owner = THIS_MODULE; | ||
258 | codec->set_bias_level = wm8728_set_bias_level; | ||
259 | codec->dai = &wm8728_dai; | ||
260 | codec->num_dai = 1; | ||
261 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
262 | codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults); | ||
263 | codec->reg_cache = kmemdup(wm8728_reg_defaults, | ||
264 | sizeof(wm8728_reg_defaults), | ||
265 | GFP_KERNEL); | ||
266 | if (codec->reg_cache == NULL) | ||
267 | return -ENOMEM; | ||
268 | 246 | ||
269 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 247 | codec->control_data = wm8728->control_data; |
248 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type); | ||
270 | if (ret < 0) { | 249 | if (ret < 0) { |
271 | printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", | 250 | printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", |
272 | ret); | 251 | ret); |
273 | goto err; | 252 | return ret; |
274 | } | ||
275 | |||
276 | /* register pcms */ | ||
277 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
278 | if (ret < 0) { | ||
279 | printk(KERN_ERR "wm8728: failed to create pcms\n"); | ||
280 | goto err; | ||
281 | } | 253 | } |
282 | 254 | ||
283 | /* power on device */ | 255 | /* power on device */ |
@@ -288,128 +260,56 @@ static int wm8728_init(struct snd_soc_device *socdev, | |||
288 | wm8728_add_widgets(codec); | 260 | wm8728_add_widgets(codec); |
289 | 261 | ||
290 | return ret; | 262 | return ret; |
291 | |||
292 | err: | ||
293 | kfree(codec->reg_cache); | ||
294 | return ret; | ||
295 | } | 263 | } |
296 | 264 | ||
297 | static struct snd_soc_device *wm8728_socdev; | 265 | static int wm8728_remove(struct snd_soc_codec *codec) |
298 | |||
299 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
300 | |||
301 | /* | ||
302 | * WM8728 2 wire address is determined by GPIO5 | ||
303 | * state during powerup. | ||
304 | * low = 0x1a | ||
305 | * high = 0x1b | ||
306 | */ | ||
307 | |||
308 | static int wm8728_i2c_probe(struct i2c_client *i2c, | ||
309 | const struct i2c_device_id *id) | ||
310 | { | 266 | { |
311 | struct snd_soc_device *socdev = wm8728_socdev; | 267 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); |
312 | struct snd_soc_codec *codec = socdev->card->codec; | ||
313 | int ret; | ||
314 | |||
315 | i2c_set_clientdata(i2c, codec); | ||
316 | codec->control_data = i2c; | ||
317 | |||
318 | ret = wm8728_init(socdev, SND_SOC_I2C); | ||
319 | if (ret < 0) | ||
320 | pr_err("failed to initialise WM8728\n"); | ||
321 | |||
322 | return ret; | ||
323 | } | ||
324 | |||
325 | static int wm8728_i2c_remove(struct i2c_client *client) | ||
326 | { | ||
327 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | ||
328 | kfree(codec->reg_cache); | ||
329 | return 0; | 268 | return 0; |
330 | } | 269 | } |
331 | 270 | ||
332 | static const struct i2c_device_id wm8728_i2c_id[] = { | 271 | static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { |
333 | { "wm8728", 0 }, | 272 | .probe = wm8728_probe, |
334 | { } | 273 | .remove = wm8728_remove, |
335 | }; | 274 | .suspend = wm8728_suspend, |
336 | MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); | 275 | .resume = wm8728_resume, |
337 | 276 | .set_bias_level = wm8728_set_bias_level, | |
338 | static struct i2c_driver wm8728_i2c_driver = { | 277 | .reg_cache_size = sizeof(wm8728_reg_defaults), |
339 | .driver = { | 278 | .reg_word_size = sizeof(u16), |
340 | .name = "WM8728 I2C Codec", | 279 | .reg_cache_default = wm8728_reg_defaults, |
341 | .owner = THIS_MODULE, | ||
342 | }, | ||
343 | .probe = wm8728_i2c_probe, | ||
344 | .remove = wm8728_i2c_remove, | ||
345 | .id_table = wm8728_i2c_id, | ||
346 | }; | 280 | }; |
347 | 281 | ||
348 | static int wm8728_add_i2c_device(struct platform_device *pdev, | ||
349 | const struct wm8728_setup_data *setup) | ||
350 | { | ||
351 | struct i2c_board_info info; | ||
352 | struct i2c_adapter *adapter; | ||
353 | struct i2c_client *client; | ||
354 | int ret; | ||
355 | |||
356 | ret = i2c_add_driver(&wm8728_i2c_driver); | ||
357 | if (ret != 0) { | ||
358 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
359 | return ret; | ||
360 | } | ||
361 | |||
362 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
363 | info.addr = setup->i2c_address; | ||
364 | strlcpy(info.type, "wm8728", I2C_NAME_SIZE); | ||
365 | |||
366 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
367 | if (!adapter) { | ||
368 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
369 | setup->i2c_bus); | ||
370 | goto err_driver; | ||
371 | } | ||
372 | |||
373 | client = i2c_new_device(adapter, &info); | ||
374 | i2c_put_adapter(adapter); | ||
375 | if (!client) { | ||
376 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
377 | (unsigned int)info.addr); | ||
378 | goto err_driver; | ||
379 | } | ||
380 | |||
381 | return 0; | ||
382 | |||
383 | err_driver: | ||
384 | i2c_del_driver(&wm8728_i2c_driver); | ||
385 | return -ENODEV; | ||
386 | } | ||
387 | #endif | ||
388 | |||
389 | #if defined(CONFIG_SPI_MASTER) | 282 | #if defined(CONFIG_SPI_MASTER) |
390 | static int __devinit wm8728_spi_probe(struct spi_device *spi) | 283 | static int __devinit wm8728_spi_probe(struct spi_device *spi) |
391 | { | 284 | { |
392 | struct snd_soc_device *socdev = wm8728_socdev; | 285 | struct wm8728_priv *wm8728; |
393 | struct snd_soc_codec *codec = socdev->card->codec; | ||
394 | int ret; | 286 | int ret; |
395 | 287 | ||
396 | codec->control_data = spi; | 288 | wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); |
289 | if (wm8728 == NULL) | ||
290 | return -ENOMEM; | ||
397 | 291 | ||
398 | ret = wm8728_init(socdev, SND_SOC_SPI); | 292 | wm8728->control_data = spi; |
399 | if (ret < 0) | 293 | wm8728->control_type = SND_SOC_SPI; |
400 | dev_err(&spi->dev, "failed to initialise WM8728\n"); | 294 | spi_set_drvdata(spi, wm8728); |
401 | 295 | ||
296 | ret = snd_soc_register_codec(&spi->dev, | ||
297 | &soc_codec_dev_wm8728, &wm8728_dai, 1); | ||
298 | if (ret < 0) | ||
299 | kfree(wm8728); | ||
402 | return ret; | 300 | return ret; |
403 | } | 301 | } |
404 | 302 | ||
405 | static int __devexit wm8728_spi_remove(struct spi_device *spi) | 303 | static int __devexit wm8728_spi_remove(struct spi_device *spi) |
406 | { | 304 | { |
305 | snd_soc_unregister_codec(&spi->dev); | ||
306 | kfree(spi_get_drvdata(spi)); | ||
407 | return 0; | 307 | return 0; |
408 | } | 308 | } |
409 | 309 | ||
410 | static struct spi_driver wm8728_spi_driver = { | 310 | static struct spi_driver wm8728_spi_driver = { |
411 | .driver = { | 311 | .driver = { |
412 | .name = "wm8728", | 312 | .name = "wm8728-codec", |
413 | .bus = &spi_bus_type, | 313 | .bus = &spi_bus_type, |
414 | .owner = THIS_MODULE, | 314 | .owner = THIS_MODULE, |
415 | }, | 315 | }, |
@@ -418,85 +318,81 @@ static struct spi_driver wm8728_spi_driver = { | |||
418 | }; | 318 | }; |
419 | #endif /* CONFIG_SPI_MASTER */ | 319 | #endif /* CONFIG_SPI_MASTER */ |
420 | 320 | ||
421 | static int wm8728_probe(struct platform_device *pdev) | 321 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
322 | static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, | ||
323 | const struct i2c_device_id *id) | ||
422 | { | 324 | { |
423 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 325 | struct wm8728_priv *wm8728; |
424 | struct wm8728_setup_data *setup; | 326 | int ret; |
425 | struct snd_soc_codec *codec; | ||
426 | int ret = 0; | ||
427 | 327 | ||
428 | setup = socdev->codec_data; | 328 | wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); |
429 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 329 | if (wm8728 == NULL) |
430 | if (codec == NULL) | ||
431 | return -ENOMEM; | 330 | return -ENOMEM; |
432 | 331 | ||
433 | socdev->card->codec = codec; | 332 | i2c_set_clientdata(i2c, wm8728); |
434 | mutex_init(&codec->mutex); | 333 | wm8728->control_data = i2c; |
435 | INIT_LIST_HEAD(&codec->dapm_widgets); | 334 | wm8728->control_type = SND_SOC_I2C; |
436 | INIT_LIST_HEAD(&codec->dapm_paths); | 335 | |
336 | ret = snd_soc_register_codec(&i2c->dev, | ||
337 | &soc_codec_dev_wm8728, &wm8728_dai, 1); | ||
338 | if (ret < 0) | ||
339 | kfree(wm8728); | ||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | static __devexit int wm8728_i2c_remove(struct i2c_client *client) | ||
344 | { | ||
345 | snd_soc_unregister_codec(&client->dev); | ||
346 | kfree(i2c_get_clientdata(client)); | ||
347 | return 0; | ||
348 | } | ||
437 | 349 | ||
438 | wm8728_socdev = socdev; | 350 | static const struct i2c_device_id wm8728_i2c_id[] = { |
439 | ret = -ENODEV; | 351 | { "wm8728", 0 }, |
352 | { } | ||
353 | }; | ||
354 | MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); | ||
355 | |||
356 | static struct i2c_driver wm8728_i2c_driver = { | ||
357 | .driver = { | ||
358 | .name = "wm8728-codec", | ||
359 | .owner = THIS_MODULE, | ||
360 | }, | ||
361 | .probe = wm8728_i2c_probe, | ||
362 | .remove = __devexit_p(wm8728_i2c_remove), | ||
363 | .id_table = wm8728_i2c_id, | ||
364 | }; | ||
365 | #endif | ||
440 | 366 | ||
367 | static int __init wm8728_modinit(void) | ||
368 | { | ||
369 | int ret = 0; | ||
441 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 370 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
442 | if (setup->i2c_address) { | 371 | ret = i2c_add_driver(&wm8728_i2c_driver); |
443 | ret = wm8728_add_i2c_device(pdev, setup); | 372 | if (ret != 0) { |
373 | printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n", | ||
374 | ret); | ||
444 | } | 375 | } |
445 | #endif | 376 | #endif |
446 | #if defined(CONFIG_SPI_MASTER) | 377 | #if defined(CONFIG_SPI_MASTER) |
447 | if (setup->spi) { | 378 | ret = spi_register_driver(&wm8728_spi_driver); |
448 | ret = spi_register_driver(&wm8728_spi_driver); | 379 | if (ret != 0) { |
449 | if (ret != 0) | 380 | printk(KERN_ERR "Failed to register wm8728 SPI driver: %d\n", |
450 | printk(KERN_ERR "can't add spi driver"); | 381 | ret); |
451 | } | 382 | } |
452 | #endif | 383 | #endif |
453 | |||
454 | if (ret != 0) | ||
455 | kfree(codec); | ||
456 | |||
457 | return ret; | 384 | return ret; |
458 | } | 385 | } |
386 | module_init(wm8728_modinit); | ||
459 | 387 | ||
460 | /* power down chip */ | 388 | static void __exit wm8728_exit(void) |
461 | static int wm8728_remove(struct platform_device *pdev) | ||
462 | { | 389 | { |
463 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
464 | struct snd_soc_codec *codec = socdev->card->codec; | ||
465 | |||
466 | if (codec->control_data) | ||
467 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
468 | |||
469 | snd_soc_free_pcms(socdev); | ||
470 | snd_soc_dapm_free(socdev); | ||
471 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 390 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
472 | i2c_unregister_device(codec->control_data); | ||
473 | i2c_del_driver(&wm8728_i2c_driver); | 391 | i2c_del_driver(&wm8728_i2c_driver); |
474 | #endif | 392 | #endif |
475 | #if defined(CONFIG_SPI_MASTER) | 393 | #if defined(CONFIG_SPI_MASTER) |
476 | spi_unregister_driver(&wm8728_spi_driver); | 394 | spi_unregister_driver(&wm8728_spi_driver); |
477 | #endif | 395 | #endif |
478 | kfree(codec); | ||
479 | |||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | struct snd_soc_codec_device soc_codec_dev_wm8728 = { | ||
484 | .probe = wm8728_probe, | ||
485 | .remove = wm8728_remove, | ||
486 | .suspend = wm8728_suspend, | ||
487 | .resume = wm8728_resume, | ||
488 | }; | ||
489 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728); | ||
490 | |||
491 | static int __init wm8728_modinit(void) | ||
492 | { | ||
493 | return snd_soc_register_dai(&wm8728_dai); | ||
494 | } | ||
495 | module_init(wm8728_modinit); | ||
496 | |||
497 | static void __exit wm8728_exit(void) | ||
498 | { | ||
499 | snd_soc_unregister_dai(&wm8728_dai); | ||
500 | } | 396 | } |
501 | module_exit(wm8728_exit); | 397 | module_exit(wm8728_exit); |
502 | 398 | ||
diff --git a/sound/soc/codecs/wm8728.h b/sound/soc/codecs/wm8728.h index d269c132474b..8aea362ffd47 100644 --- a/sound/soc/codecs/wm8728.h +++ b/sound/soc/codecs/wm8728.h | |||
@@ -18,13 +18,4 @@ | |||
18 | #define WM8728_DACCTL 0x02 | 18 | #define WM8728_DACCTL 0x02 |
19 | #define WM8728_IFCTL 0x03 | 19 | #define WM8728_IFCTL 0x03 |
20 | 20 | ||
21 | struct wm8728_setup_data { | ||
22 | int spi; | ||
23 | int i2c_bus; | ||
24 | unsigned short i2c_address; | ||
25 | }; | ||
26 | |||
27 | extern struct snd_soc_dai wm8728_dai; | ||
28 | extern struct snd_soc_codec_device soc_codec_dev_wm8728; | ||
29 | |||
30 | #endif | 21 | #endif |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 0ab9b6355297..7da360ee1fee 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -32,9 +32,6 @@ | |||
32 | 32 | ||
33 | #include "wm8731.h" | 33 | #include "wm8731.h" |
34 | 34 | ||
35 | static struct snd_soc_codec *wm8731_codec; | ||
36 | struct snd_soc_codec_device soc_codec_dev_wm8731; | ||
37 | |||
38 | #define WM8731_NUM_SUPPLIES 4 | 35 | #define WM8731_NUM_SUPPLIES 4 |
39 | static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { | 36 | static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { |
40 | "AVDD", | 37 | "AVDD", |
@@ -45,7 +42,8 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { | |||
45 | 42 | ||
46 | /* codec private data */ | 43 | /* codec private data */ |
47 | struct wm8731_priv { | 44 | struct wm8731_priv { |
48 | struct snd_soc_codec codec; | 45 | enum snd_soc_control_type control_type; |
46 | void *control_data; | ||
49 | struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; | 47 | struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; |
50 | u16 reg_cache[WM8731_CACHEREGNUM]; | 48 | u16 reg_cache[WM8731_CACHEREGNUM]; |
51 | unsigned int sysclk; | 49 | unsigned int sysclk; |
@@ -222,9 +220,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, | |||
222 | struct snd_pcm_hw_params *params, | 220 | struct snd_pcm_hw_params *params, |
223 | struct snd_soc_dai *dai) | 221 | struct snd_soc_dai *dai) |
224 | { | 222 | { |
225 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 223 | struct snd_soc_codec *codec = dai->codec; |
226 | struct snd_soc_device *socdev = rtd->socdev; | ||
227 | struct snd_soc_codec *codec = socdev->card->codec; | ||
228 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); | 224 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); |
229 | u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3; | 225 | u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3; |
230 | int i = get_coeff(wm8731->sysclk, params_rate(params)); | 226 | int i = get_coeff(wm8731->sysclk, params_rate(params)); |
@@ -252,9 +248,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, | |||
252 | static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, | 248 | static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, |
253 | struct snd_soc_dai *dai) | 249 | struct snd_soc_dai *dai) |
254 | { | 250 | { |
255 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 251 | struct snd_soc_codec *codec = dai->codec; |
256 | struct snd_soc_device *socdev = rtd->socdev; | ||
257 | struct snd_soc_codec *codec = socdev->card->codec; | ||
258 | 252 | ||
259 | /* set active */ | 253 | /* set active */ |
260 | snd_soc_write(codec, WM8731_ACTIVE, 0x0001); | 254 | snd_soc_write(codec, WM8731_ACTIVE, 0x0001); |
@@ -265,9 +259,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, | |||
265 | static void wm8731_shutdown(struct snd_pcm_substream *substream, | 259 | static void wm8731_shutdown(struct snd_pcm_substream *substream, |
266 | struct snd_soc_dai *dai) | 260 | struct snd_soc_dai *dai) |
267 | { | 261 | { |
268 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 262 | struct snd_soc_codec *codec = dai->codec; |
269 | struct snd_soc_device *socdev = rtd->socdev; | ||
270 | struct snd_soc_codec *codec = socdev->card->codec; | ||
271 | 263 | ||
272 | /* deactivate */ | 264 | /* deactivate */ |
273 | if (!codec->active) { | 265 | if (!codec->active) { |
@@ -428,8 +420,8 @@ static struct snd_soc_dai_ops wm8731_dai_ops = { | |||
428 | .set_fmt = wm8731_set_dai_fmt, | 420 | .set_fmt = wm8731_set_dai_fmt, |
429 | }; | 421 | }; |
430 | 422 | ||
431 | struct snd_soc_dai wm8731_dai = { | 423 | static struct snd_soc_dai_driver wm8731_dai = { |
432 | .name = "WM8731", | 424 | .name = "wm8731-hifi", |
433 | .playback = { | 425 | .playback = { |
434 | .stream_name = "Playback", | 426 | .stream_name = "Playback", |
435 | .channels_min = 1, | 427 | .channels_min = 1, |
@@ -445,24 +437,17 @@ struct snd_soc_dai wm8731_dai = { | |||
445 | .ops = &wm8731_dai_ops, | 437 | .ops = &wm8731_dai_ops, |
446 | .symmetric_rates = 1, | 438 | .symmetric_rates = 1, |
447 | }; | 439 | }; |
448 | EXPORT_SYMBOL_GPL(wm8731_dai); | ||
449 | 440 | ||
450 | #ifdef CONFIG_PM | 441 | #ifdef CONFIG_PM |
451 | static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) | 442 | static int wm8731_suspend(struct snd_soc_codec *codec, pm_message_t state) |
452 | { | 443 | { |
453 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
454 | struct snd_soc_codec *codec = socdev->card->codec; | ||
455 | |||
456 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); | 444 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); |
457 | 445 | ||
458 | return 0; | 446 | return 0; |
459 | } | 447 | } |
460 | 448 | ||
461 | static int wm8731_resume(struct platform_device *pdev) | 449 | static int wm8731_resume(struct snd_soc_codec *codec) |
462 | { | 450 | { |
463 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
464 | struct snd_soc_codec *codec = socdev->card->codec; | ||
465 | |||
466 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 451 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
467 | 452 | ||
468 | return 0; | 453 | return 0; |
@@ -472,88 +457,18 @@ static int wm8731_resume(struct platform_device *pdev) | |||
472 | #define wm8731_resume NULL | 457 | #define wm8731_resume NULL |
473 | #endif | 458 | #endif |
474 | 459 | ||
475 | static int wm8731_probe(struct platform_device *pdev) | 460 | static int wm8731_probe(struct snd_soc_codec *codec) |
476 | { | ||
477 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
478 | struct snd_soc_codec *codec; | ||
479 | int ret = 0; | ||
480 | |||
481 | if (wm8731_codec == NULL) { | ||
482 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
483 | return -ENODEV; | ||
484 | } | ||
485 | |||
486 | socdev->card->codec = wm8731_codec; | ||
487 | codec = wm8731_codec; | ||
488 | |||
489 | /* register pcms */ | ||
490 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
491 | if (ret < 0) { | ||
492 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
493 | goto pcm_err; | ||
494 | } | ||
495 | |||
496 | snd_soc_add_controls(codec, wm8731_snd_controls, | ||
497 | ARRAY_SIZE(wm8731_snd_controls)); | ||
498 | wm8731_add_widgets(codec); | ||
499 | |||
500 | return ret; | ||
501 | |||
502 | pcm_err: | ||
503 | return ret; | ||
504 | } | ||
505 | |||
506 | /* power down chip */ | ||
507 | static int wm8731_remove(struct platform_device *pdev) | ||
508 | { | 461 | { |
509 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 462 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); |
510 | 463 | int ret = 0, i; | |
511 | snd_soc_free_pcms(socdev); | ||
512 | snd_soc_dapm_free(socdev); | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | struct snd_soc_codec_device soc_codec_dev_wm8731 = { | ||
518 | .probe = wm8731_probe, | ||
519 | .remove = wm8731_remove, | ||
520 | .suspend = wm8731_suspend, | ||
521 | .resume = wm8731_resume, | ||
522 | }; | ||
523 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); | ||
524 | |||
525 | static int wm8731_register(struct wm8731_priv *wm8731, | ||
526 | enum snd_soc_control_type control) | ||
527 | { | ||
528 | int ret, i; | ||
529 | struct snd_soc_codec *codec = &wm8731->codec; | ||
530 | |||
531 | if (wm8731_codec) { | ||
532 | dev_err(codec->dev, "Another WM8731 is registered\n"); | ||
533 | ret = -EINVAL; | ||
534 | goto err; | ||
535 | } | ||
536 | |||
537 | mutex_init(&codec->mutex); | ||
538 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
539 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
540 | |||
541 | snd_soc_codec_set_drvdata(codec, wm8731); | ||
542 | codec->name = "WM8731"; | ||
543 | codec->owner = THIS_MODULE; | ||
544 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
545 | codec->set_bias_level = wm8731_set_bias_level; | ||
546 | codec->dai = &wm8731_dai; | ||
547 | codec->num_dai = 1; | ||
548 | codec->reg_cache_size = WM8731_CACHEREGNUM; | ||
549 | codec->reg_cache = &wm8731->reg_cache; | ||
550 | 464 | ||
551 | memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); | 465 | codec->bias_level = SND_SOC_BIAS_OFF, |
466 | codec->control_data = wm8731->control_data; | ||
552 | 467 | ||
553 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 468 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type); |
554 | if (ret < 0) { | 469 | if (ret < 0) { |
555 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 470 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
556 | goto err; | 471 | return ret; |
557 | } | 472 | } |
558 | 473 | ||
559 | for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) | 474 | for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) |
@@ -563,7 +478,7 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
563 | wm8731->supplies); | 478 | wm8731->supplies); |
564 | if (ret != 0) { | 479 | if (ret != 0) { |
565 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 480 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); |
566 | goto err; | 481 | return ret; |
567 | } | 482 | } |
568 | 483 | ||
569 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), | 484 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), |
@@ -579,8 +494,6 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
579 | goto err_regulator_enable; | 494 | goto err_regulator_enable; |
580 | } | 495 | } |
581 | 496 | ||
582 | wm8731_dai.dev = codec->dev; | ||
583 | |||
584 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 497 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
585 | 498 | ||
586 | /* Latch the update bits */ | 499 | /* Latch the update bits */ |
@@ -592,78 +505,79 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
592 | /* Disable bypass path by default */ | 505 | /* Disable bypass path by default */ |
593 | snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0); | 506 | snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0); |
594 | 507 | ||
595 | wm8731_codec = codec; | 508 | snd_soc_add_controls(codec, wm8731_snd_controls, |
596 | 509 | ARRAY_SIZE(wm8731_snd_controls)); | |
597 | ret = snd_soc_register_codec(codec); | 510 | wm8731_add_widgets(codec); |
598 | if (ret != 0) { | ||
599 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
600 | goto err_regulator_enable; | ||
601 | } | ||
602 | |||
603 | ret = snd_soc_register_dai(&wm8731_dai); | ||
604 | if (ret != 0) { | ||
605 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
606 | snd_soc_unregister_codec(codec); | ||
607 | goto err_codec; | ||
608 | } | ||
609 | 511 | ||
610 | /* Regulators will have been enabled by bias management */ | 512 | /* Regulators will have been enabled by bias management */ |
611 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | 513 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); |
612 | 514 | ||
613 | return 0; | 515 | return 0; |
614 | 516 | ||
615 | err_codec: | ||
616 | snd_soc_unregister_codec(codec); | ||
617 | err_regulator_enable: | 517 | err_regulator_enable: |
618 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | 518 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); |
619 | err_regulator_get: | 519 | err_regulator_get: |
620 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | 520 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); |
621 | err: | 521 | |
622 | kfree(wm8731); | 522 | kfree(wm8731); |
623 | return ret; | 523 | return ret; |
624 | } | 524 | } |
625 | 525 | ||
626 | static void wm8731_unregister(struct wm8731_priv *wm8731) | 526 | /* power down chip */ |
527 | static int wm8731_remove(struct snd_soc_codec *codec) | ||
627 | { | 528 | { |
628 | wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); | 529 | struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); |
629 | snd_soc_unregister_dai(&wm8731_dai); | 530 | |
630 | snd_soc_unregister_codec(&wm8731->codec); | 531 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); |
532 | |||
533 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
631 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | 534 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); |
632 | kfree(wm8731); | 535 | |
633 | wm8731_codec = NULL; | 536 | return 0; |
634 | } | 537 | } |
635 | 538 | ||
539 | static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { | ||
540 | .probe = wm8731_probe, | ||
541 | .remove = wm8731_remove, | ||
542 | .suspend = wm8731_suspend, | ||
543 | .resume = wm8731_resume, | ||
544 | .set_bias_level = wm8731_set_bias_level, | ||
545 | .reg_cache_size = sizeof(wm8731_reg), | ||
546 | .reg_word_size = sizeof(u16), | ||
547 | .reg_cache_default = wm8731_reg, | ||
548 | }; | ||
549 | |||
636 | #if defined(CONFIG_SPI_MASTER) | 550 | #if defined(CONFIG_SPI_MASTER) |
637 | static int __devinit wm8731_spi_probe(struct spi_device *spi) | 551 | static int __devinit wm8731_spi_probe(struct spi_device *spi) |
638 | { | 552 | { |
639 | struct snd_soc_codec *codec; | ||
640 | struct wm8731_priv *wm8731; | 553 | struct wm8731_priv *wm8731; |
554 | int ret; | ||
641 | 555 | ||
642 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); | 556 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); |
643 | if (wm8731 == NULL) | 557 | if (wm8731 == NULL) |
644 | return -ENOMEM; | 558 | return -ENOMEM; |
645 | 559 | ||
646 | codec = &wm8731->codec; | 560 | wm8731->control_data = spi; |
647 | codec->control_data = spi; | 561 | wm8731->control_type = SND_SOC_SPI; |
648 | codec->dev = &spi->dev; | 562 | spi_set_drvdata(spi, wm8731); |
649 | |||
650 | dev_set_drvdata(&spi->dev, wm8731); | ||
651 | 563 | ||
652 | return wm8731_register(wm8731, SND_SOC_SPI); | 564 | ret = snd_soc_register_codec(&spi->dev, |
565 | &soc_codec_dev_wm8731, &wm8731_dai, 1); | ||
566 | if (ret < 0) | ||
567 | kfree(wm8731); | ||
568 | return ret; | ||
653 | } | 569 | } |
654 | 570 | ||
655 | static int __devexit wm8731_spi_remove(struct spi_device *spi) | 571 | static int __devexit wm8731_spi_remove(struct spi_device *spi) |
656 | { | 572 | { |
657 | struct wm8731_priv *wm8731 = dev_get_drvdata(&spi->dev); | 573 | snd_soc_unregister_codec(&spi->dev); |
658 | 574 | kfree(spi_get_drvdata(spi)); | |
659 | wm8731_unregister(wm8731); | ||
660 | |||
661 | return 0; | 575 | return 0; |
662 | } | 576 | } |
663 | 577 | ||
664 | static struct spi_driver wm8731_spi_driver = { | 578 | static struct spi_driver wm8731_spi_driver = { |
665 | .driver = { | 579 | .driver = { |
666 | .name = "wm8731", | 580 | .name = "wm8731-codec", |
667 | .bus = &spi_bus_type, | 581 | .bus = &spi_bus_type, |
668 | .owner = THIS_MODULE, | 582 | .owner = THIS_MODULE, |
669 | }, | 583 | }, |
@@ -677,26 +591,27 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c, | |||
677 | const struct i2c_device_id *id) | 591 | const struct i2c_device_id *id) |
678 | { | 592 | { |
679 | struct wm8731_priv *wm8731; | 593 | struct wm8731_priv *wm8731; |
680 | struct snd_soc_codec *codec; | 594 | int ret; |
681 | 595 | ||
682 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); | 596 | wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); |
683 | if (wm8731 == NULL) | 597 | if (wm8731 == NULL) |
684 | return -ENOMEM; | 598 | return -ENOMEM; |
685 | 599 | ||
686 | codec = &wm8731->codec; | ||
687 | |||
688 | i2c_set_clientdata(i2c, wm8731); | 600 | i2c_set_clientdata(i2c, wm8731); |
689 | codec->control_data = i2c; | 601 | wm8731->control_data = i2c; |
602 | wm8731->control_type = SND_SOC_I2C; | ||
690 | 603 | ||
691 | codec->dev = &i2c->dev; | 604 | ret = snd_soc_register_codec(&i2c->dev, |
692 | 605 | &soc_codec_dev_wm8731, &wm8731_dai, 1); | |
693 | return wm8731_register(wm8731, SND_SOC_I2C); | 606 | if (ret < 0) |
607 | kfree(wm8731); | ||
608 | return ret; | ||
694 | } | 609 | } |
695 | 610 | ||
696 | static __devexit int wm8731_i2c_remove(struct i2c_client *client) | 611 | static __devexit int wm8731_i2c_remove(struct i2c_client *client) |
697 | { | 612 | { |
698 | struct wm8731_priv *wm8731 = i2c_get_clientdata(client); | 613 | snd_soc_unregister_codec(&client->dev); |
699 | wm8731_unregister(wm8731); | 614 | kfree(i2c_get_clientdata(client)); |
700 | return 0; | 615 | return 0; |
701 | } | 616 | } |
702 | 617 | ||
@@ -708,7 +623,7 @@ MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); | |||
708 | 623 | ||
709 | static struct i2c_driver wm8731_i2c_driver = { | 624 | static struct i2c_driver wm8731_i2c_driver = { |
710 | .driver = { | 625 | .driver = { |
711 | .name = "wm8731", | 626 | .name = "wm8731-codec", |
712 | .owner = THIS_MODULE, | 627 | .owner = THIS_MODULE, |
713 | }, | 628 | }, |
714 | .probe = wm8731_i2c_probe, | 629 | .probe = wm8731_i2c_probe, |
@@ -719,7 +634,7 @@ static struct i2c_driver wm8731_i2c_driver = { | |||
719 | 634 | ||
720 | static int __init wm8731_modinit(void) | 635 | static int __init wm8731_modinit(void) |
721 | { | 636 | { |
722 | int ret; | 637 | int ret = 0; |
723 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 638 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
724 | ret = i2c_add_driver(&wm8731_i2c_driver); | 639 | ret = i2c_add_driver(&wm8731_i2c_driver); |
725 | if (ret != 0) { | 640 | if (ret != 0) { |
@@ -734,7 +649,7 @@ static int __init wm8731_modinit(void) | |||
734 | ret); | 649 | ret); |
735 | } | 650 | } |
736 | #endif | 651 | #endif |
737 | return 0; | 652 | return ret; |
738 | } | 653 | } |
739 | module_init(wm8731_modinit); | 654 | module_init(wm8731_modinit); |
740 | 655 | ||
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h index cd7b806e8ad0..73a70e206ba9 100644 --- a/sound/soc/codecs/wm8731.h +++ b/sound/soc/codecs/wm8731.h | |||
@@ -34,7 +34,4 @@ | |||
34 | #define WM8731_SYSCLK 0 | 34 | #define WM8731_SYSCLK 0 |
35 | #define WM8731_DAI 0 | 35 | #define WM8731_DAI 0 |
36 | 36 | ||
37 | extern struct snd_soc_dai wm8731_dai; | ||
38 | extern struct snd_soc_codec_device soc_codec_dev_wm8731; | ||
39 | |||
40 | #endif | 37 | #endif |
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index b9ea8904ad4b..0c6d59e4d226 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -30,9 +30,6 @@ | |||
30 | 30 | ||
31 | #include "wm8741.h" | 31 | #include "wm8741.h" |
32 | 32 | ||
33 | static struct snd_soc_codec *wm8741_codec; | ||
34 | struct snd_soc_codec_device soc_codec_dev_wm8741; | ||
35 | |||
36 | #define WM8741_NUM_SUPPLIES 2 | 33 | #define WM8741_NUM_SUPPLIES 2 |
37 | static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { | 34 | static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { |
38 | "AVDD", | 35 | "AVDD", |
@@ -43,7 +40,8 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { | |||
43 | 40 | ||
44 | /* codec private data */ | 41 | /* codec private data */ |
45 | struct wm8741_priv { | 42 | struct wm8741_priv { |
46 | struct snd_soc_codec codec; | 43 | enum snd_soc_control_type control_type; |
44 | void *control_data; | ||
47 | u16 reg_cache[WM8741_REGISTER_COUNT]; | 45 | u16 reg_cache[WM8741_REGISTER_COUNT]; |
48 | struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; | 46 | struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; |
49 | unsigned int sysclk; | 47 | unsigned int sysclk; |
@@ -145,8 +143,7 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream, | |||
145 | struct snd_soc_dai *dai) | 143 | struct snd_soc_dai *dai) |
146 | { | 144 | { |
147 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 145 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
148 | struct snd_soc_device *socdev = rtd->socdev; | 146 | struct snd_soc_codec *codec = rtd->codec; |
149 | struct snd_soc_codec *codec = socdev->card->codec; | ||
150 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | 147 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
151 | u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC; | 148 | u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC; |
152 | int i; | 149 | int i; |
@@ -314,7 +311,7 @@ static struct snd_soc_dai_ops wm8741_dai_ops = { | |||
314 | .set_fmt = wm8741_set_dai_fmt, | 311 | .set_fmt = wm8741_set_dai_fmt, |
315 | }; | 312 | }; |
316 | 313 | ||
317 | struct snd_soc_dai wm8741_dai = { | 314 | static struct snd_soc_dai_driver wm8741_dai = { |
318 | .name = "WM8741", | 315 | .name = "WM8741", |
319 | .playback = { | 316 | .playback = { |
320 | .stream_name = "Playback", | 317 | .stream_name = "Playback", |
@@ -325,13 +322,10 @@ struct snd_soc_dai wm8741_dai = { | |||
325 | }, | 322 | }, |
326 | .ops = &wm8741_dai_ops, | 323 | .ops = &wm8741_dai_ops, |
327 | }; | 324 | }; |
328 | EXPORT_SYMBOL_GPL(wm8741_dai); | ||
329 | 325 | ||
330 | #ifdef CONFIG_PM | 326 | #ifdef CONFIG_PM |
331 | static int wm8741_resume(struct platform_device *pdev) | 327 | static int wm8741_resume(struct snd_soc_codec *codec) |
332 | { | 328 | { |
333 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
334 | struct snd_soc_codec *codec = socdev->card->codec; | ||
335 | u16 *cache = codec->reg_cache; | 329 | u16 *cache = codec->reg_cache; |
336 | int i; | 330 | int i; |
337 | 331 | ||
@@ -348,189 +342,105 @@ static int wm8741_resume(struct platform_device *pdev) | |||
348 | #define wm8741_resume NULL | 342 | #define wm8741_resume NULL |
349 | #endif | 343 | #endif |
350 | 344 | ||
351 | static int wm8741_probe(struct platform_device *pdev) | 345 | static int wm8741_probe(struct snd_soc_codec *codec) |
352 | { | 346 | { |
353 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 347 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
354 | struct snd_soc_codec *codec; | ||
355 | int ret = 0; | 348 | int ret = 0; |
356 | 349 | ||
357 | if (wm8741_codec == NULL) { | 350 | codec->control_data = wm8741->control_data; |
358 | dev_err(&pdev->dev, "Codec device not registered\n"); | 351 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); |
359 | return -ENODEV; | 352 | if (ret != 0) { |
353 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
354 | return ret; | ||
360 | } | 355 | } |
361 | 356 | ||
362 | socdev->card->codec = wm8741_codec; | 357 | ret = wm8741_reset(codec); |
363 | codec = wm8741_codec; | ||
364 | |||
365 | /* register pcms */ | ||
366 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
367 | if (ret < 0) { | 358 | if (ret < 0) { |
368 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | 359 | dev_err(codec->dev, "Failed to issue reset\n"); |
369 | goto pcm_err; | 360 | return ret; |
370 | } | 361 | } |
371 | 362 | ||
363 | /* Change some default settings - latch VU */ | ||
364 | wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; | ||
365 | wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; | ||
366 | wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; | ||
367 | wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; | ||
368 | |||
372 | snd_soc_add_controls(codec, wm8741_snd_controls, | 369 | snd_soc_add_controls(codec, wm8741_snd_controls, |
373 | ARRAY_SIZE(wm8741_snd_controls)); | 370 | ARRAY_SIZE(wm8741_snd_controls)); |
374 | wm8741_add_widgets(codec); | 371 | wm8741_add_widgets(codec); |
375 | 372 | ||
373 | dev_dbg(codec->dev, "Successful registration\n"); | ||
376 | return ret; | 374 | return ret; |
377 | |||
378 | pcm_err: | ||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | static int wm8741_remove(struct platform_device *pdev) | ||
383 | { | ||
384 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
385 | |||
386 | snd_soc_free_pcms(socdev); | ||
387 | snd_soc_dapm_free(socdev); | ||
388 | |||
389 | return 0; | ||
390 | } | 375 | } |
391 | 376 | ||
392 | struct snd_soc_codec_device soc_codec_dev_wm8741 = { | 377 | static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { |
393 | .probe = wm8741_probe, | 378 | .probe = wm8741_probe, |
394 | .remove = wm8741_remove, | ||
395 | .resume = wm8741_resume, | 379 | .resume = wm8741_resume, |
380 | .reg_cache_size = sizeof(wm8741_reg_defaults), | ||
381 | .reg_word_size = sizeof(u16), | ||
382 | .reg_cache_default = &wm8741_reg_defaults, | ||
396 | }; | 383 | }; |
397 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8741); | ||
398 | 384 | ||
399 | static int wm8741_register(struct wm8741_priv *wm8741, | 385 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
400 | enum snd_soc_control_type control) | 386 | static int wm8741_i2c_probe(struct i2c_client *i2c, |
387 | const struct i2c_device_id *id) | ||
401 | { | 388 | { |
402 | int ret; | 389 | struct wm8741_priv *wm8741; |
403 | struct snd_soc_codec *codec = &wm8741->codec; | 390 | int ret, i; |
404 | int i; | ||
405 | |||
406 | if (wm8741_codec) { | ||
407 | dev_err(codec->dev, "Another WM8741 is registered\n"); | ||
408 | return -EINVAL; | ||
409 | } | ||
410 | |||
411 | mutex_init(&codec->mutex); | ||
412 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
413 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
414 | 391 | ||
415 | snd_soc_codec_set_drvdata(codec, wm8741); | 392 | wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); |
416 | codec->name = "WM8741"; | 393 | if (wm8741 == NULL) |
417 | codec->owner = THIS_MODULE; | 394 | return -ENOMEM; |
418 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
419 | codec->set_bias_level = NULL; | ||
420 | codec->dai = &wm8741_dai; | ||
421 | codec->num_dai = 1; | ||
422 | codec->reg_cache_size = WM8741_REGISTER_COUNT; | ||
423 | codec->reg_cache = &wm8741->reg_cache; | ||
424 | 395 | ||
425 | wm8741->rate_constraint.list = &wm8741->rate_constraint_list[0]; | 396 | wm8741->rate_constraint.list = &wm8741->rate_constraint_list[0]; |
426 | wm8741->rate_constraint.count = | 397 | wm8741->rate_constraint.count = |
427 | ARRAY_SIZE(wm8741->rate_constraint_list); | 398 | ARRAY_SIZE(wm8741->rate_constraint_list); |
428 | 399 | ||
429 | memcpy(codec->reg_cache, wm8741_reg_defaults, | ||
430 | sizeof(wm8741->reg_cache)); | ||
431 | |||
432 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
433 | if (ret != 0) { | ||
434 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
435 | goto err; | ||
436 | } | ||
437 | |||
438 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) | 400 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) |
439 | wm8741->supplies[i].supply = wm8741_supply_names[i]; | 401 | wm8741->supplies[i].supply = wm8741_supply_names[i]; |
440 | 402 | ||
441 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), | 403 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), |
442 | wm8741->supplies); | 404 | wm8741->supplies); |
443 | if (ret != 0) { | 405 | if (ret != 0) { |
444 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 406 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); |
445 | goto err; | 407 | goto err; |
446 | } | 408 | } |
447 | 409 | ||
448 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), | 410 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), |
449 | wm8741->supplies); | 411 | wm8741->supplies); |
450 | if (ret != 0) { | 412 | if (ret != 0) { |
451 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | 413 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); |
452 | goto err_get; | 414 | goto err_get; |
453 | } | 415 | } |
454 | 416 | ||
455 | ret = wm8741_reset(codec); | 417 | i2c_set_clientdata(i2c, wm8741); |
456 | if (ret < 0) { | 418 | wm8741->control_data = i2c; |
457 | dev_err(codec->dev, "Failed to issue reset\n"); | 419 | wm8741->control_type = SND_SOC_I2C; |
458 | goto err_enable; | ||
459 | } | ||
460 | |||
461 | wm8741_dai.dev = codec->dev; | ||
462 | |||
463 | /* Change some default settings - latch VU */ | ||
464 | wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; | ||
465 | wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; | ||
466 | wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; | ||
467 | wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; | ||
468 | |||
469 | wm8741_codec = codec; | ||
470 | |||
471 | ret = snd_soc_register_codec(codec); | ||
472 | if (ret != 0) { | ||
473 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
474 | return ret; | ||
475 | } | ||
476 | |||
477 | ret = snd_soc_register_dai(&wm8741_dai); | ||
478 | if (ret != 0) { | ||
479 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
480 | snd_soc_unregister_codec(codec); | ||
481 | return ret; | ||
482 | } | ||
483 | 420 | ||
484 | dev_dbg(codec->dev, "Successful registration\n"); | 421 | ret = snd_soc_register_codec(&i2c->dev, |
485 | return 0; | 422 | &soc_codec_dev_wm8741, &wm8741_dai, 1); |
423 | if (ret < 0) | ||
424 | goto err_enable; | ||
425 | return ret; | ||
486 | 426 | ||
487 | err_enable: | 427 | err_enable: |
488 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | 428 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); |
489 | 429 | ||
490 | err_get: | 430 | err_get: |
491 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | 431 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); |
492 | |||
493 | err: | 432 | err: |
494 | kfree(wm8741); | 433 | kfree(wm8741); |
495 | return ret; | 434 | return ret; |
496 | } | 435 | } |
497 | 436 | ||
498 | static void wm8741_unregister(struct wm8741_priv *wm8741) | 437 | static int wm8741_i2c_remove(struct i2c_client *client) |
499 | { | ||
500 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
501 | |||
502 | snd_soc_unregister_dai(&wm8741_dai); | ||
503 | snd_soc_unregister_codec(&wm8741->codec); | ||
504 | kfree(wm8741); | ||
505 | wm8741_codec = NULL; | ||
506 | } | ||
507 | |||
508 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
509 | static __devinit int wm8741_i2c_probe(struct i2c_client *i2c, | ||
510 | const struct i2c_device_id *id) | ||
511 | { | ||
512 | struct wm8741_priv *wm8741; | ||
513 | struct snd_soc_codec *codec; | ||
514 | |||
515 | wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); | ||
516 | if (wm8741 == NULL) | ||
517 | return -ENOMEM; | ||
518 | |||
519 | codec = &wm8741->codec; | ||
520 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
521 | |||
522 | i2c_set_clientdata(i2c, wm8741); | ||
523 | codec->control_data = i2c; | ||
524 | |||
525 | codec->dev = &i2c->dev; | ||
526 | |||
527 | return wm8741_register(wm8741, SND_SOC_I2C); | ||
528 | } | ||
529 | |||
530 | static __devexit int wm8741_i2c_remove(struct i2c_client *client) | ||
531 | { | 438 | { |
532 | struct wm8741_priv *wm8741 = i2c_get_clientdata(client); | 439 | struct wm8741_priv *wm8741 = i2c_get_clientdata(client); |
533 | wm8741_unregister(wm8741); | 440 | |
441 | snd_soc_unregister_codec(&client->dev); | ||
442 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
443 | kfree(i2c_get_clientdata(client)); | ||
534 | return 0; | 444 | return 0; |
535 | } | 445 | } |
536 | 446 | ||
@@ -540,29 +450,29 @@ static const struct i2c_device_id wm8741_i2c_id[] = { | |||
540 | }; | 450 | }; |
541 | MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); | 451 | MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); |
542 | 452 | ||
543 | |||
544 | static struct i2c_driver wm8741_i2c_driver = { | 453 | static struct i2c_driver wm8741_i2c_driver = { |
545 | .driver = { | 454 | .driver = { |
546 | .name = "WM8741", | 455 | .name = "wm8741-codec", |
547 | .owner = THIS_MODULE, | 456 | .owner = THIS_MODULE, |
548 | }, | 457 | }, |
549 | .probe = wm8741_i2c_probe, | 458 | .probe = wm8741_i2c_probe, |
550 | .remove = __devexit_p(wm8741_i2c_remove), | 459 | .remove = wm8741_i2c_remove, |
551 | .id_table = wm8741_i2c_id, | 460 | .id_table = wm8741_i2c_id, |
552 | }; | 461 | }; |
553 | #endif | 462 | #endif |
554 | 463 | ||
555 | static int __init wm8741_modinit(void) | 464 | static int __init wm8741_modinit(void) |
556 | { | 465 | { |
557 | int ret; | 466 | int ret = 0; |
467 | |||
558 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 468 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
559 | ret = i2c_add_driver(&wm8741_i2c_driver); | 469 | ret = i2c_add_driver(&wm8741_i2c_driver); |
560 | if (ret != 0) { | 470 | if (ret != 0) { |
561 | printk(KERN_ERR "Failed to register WM8741 I2C driver: %d\n", | 471 | pr_err("Failed to register WM8741 I2C driver: %d\n", ret); |
562 | ret); | ||
563 | } | 472 | } |
564 | #endif | 473 | #endif |
565 | return 0; | 474 | |
475 | return ret; | ||
566 | } | 476 | } |
567 | module_init(wm8741_modinit); | 477 | module_init(wm8741_modinit); |
568 | 478 | ||
diff --git a/sound/soc/codecs/wm8741.h b/sound/soc/codecs/wm8741.h index fdef6ecd1f6f..56c1b1d4a681 100644 --- a/sound/soc/codecs/wm8741.h +++ b/sound/soc/codecs/wm8741.h | |||
@@ -208,7 +208,4 @@ | |||
208 | 208 | ||
209 | #define WM8741_SYSCLK 0 | 209 | #define WM8741_SYSCLK 0 |
210 | 210 | ||
211 | extern struct snd_soc_dai wm8741_dai; | ||
212 | extern struct snd_soc_codec_device soc_codec_dev_wm8741; | ||
213 | |||
214 | #endif | 211 | #endif |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index e2c05e3e323a..89863a5bc830 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -52,7 +52,8 @@ static const u16 wm8750_reg[] = { | |||
52 | /* codec private data */ | 52 | /* codec private data */ |
53 | struct wm8750_priv { | 53 | struct wm8750_priv { |
54 | unsigned int sysclk; | 54 | unsigned int sysclk; |
55 | struct snd_soc_codec codec; | 55 | enum snd_soc_control_type control_type; |
56 | void *control_data; | ||
56 | u16 reg_cache[ARRAY_SIZE(wm8750_reg)]; | 57 | u16 reg_cache[ARRAY_SIZE(wm8750_reg)]; |
57 | }; | 58 | }; |
58 | 59 | ||
@@ -560,8 +561,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, | |||
560 | struct snd_soc_dai *dai) | 561 | struct snd_soc_dai *dai) |
561 | { | 562 | { |
562 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 563 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
563 | struct snd_soc_device *socdev = rtd->socdev; | 564 | struct snd_soc_codec *codec = rtd->codec; |
564 | struct snd_soc_codec *codec = socdev->card->codec; | ||
565 | struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); | 565 | struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); |
566 | u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3; | 566 | u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3; |
567 | u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0; | 567 | u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0; |
@@ -649,8 +649,8 @@ static struct snd_soc_dai_ops wm8750_dai_ops = { | |||
649 | .set_sysclk = wm8750_set_dai_sysclk, | 649 | .set_sysclk = wm8750_set_dai_sysclk, |
650 | }; | 650 | }; |
651 | 651 | ||
652 | struct snd_soc_dai wm8750_dai = { | 652 | static struct snd_soc_dai_driver wm8750_dai = { |
653 | .name = "WM8750", | 653 | .name = "wm8750-hifi", |
654 | .playback = { | 654 | .playback = { |
655 | .stream_name = "Playback", | 655 | .stream_name = "Playback", |
656 | .channels_min = 1, | 656 | .channels_min = 1, |
@@ -665,21 +665,15 @@ struct snd_soc_dai wm8750_dai = { | |||
665 | .formats = WM8750_FORMATS,}, | 665 | .formats = WM8750_FORMATS,}, |
666 | .ops = &wm8750_dai_ops, | 666 | .ops = &wm8750_dai_ops, |
667 | }; | 667 | }; |
668 | EXPORT_SYMBOL_GPL(wm8750_dai); | ||
669 | 668 | ||
670 | static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) | 669 | static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state) |
671 | { | 670 | { |
672 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
673 | struct snd_soc_codec *codec = socdev->card->codec; | ||
674 | |||
675 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); | 671 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); |
676 | return 0; | 672 | return 0; |
677 | } | 673 | } |
678 | 674 | ||
679 | static int wm8750_resume(struct platform_device *pdev) | 675 | static int wm8750_resume(struct snd_soc_codec *codec) |
680 | { | 676 | { |
681 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
682 | struct snd_soc_codec *codec = socdev->card->codec; | ||
683 | int i; | 677 | int i; |
684 | u8 data[2]; | 678 | u8 data[2]; |
685 | u16 *cache = codec->reg_cache; | 679 | u16 *cache = codec->reg_cache; |
@@ -698,100 +692,22 @@ static int wm8750_resume(struct platform_device *pdev) | |||
698 | return 0; | 692 | return 0; |
699 | } | 693 | } |
700 | 694 | ||
701 | static struct snd_soc_codec *wm8750_codec; | 695 | static int wm8750_probe(struct snd_soc_codec *codec) |
702 | |||
703 | static int wm8750_probe(struct platform_device *pdev) | ||
704 | { | 696 | { |
705 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 697 | struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); |
706 | struct snd_soc_codec *codec; | 698 | int reg, ret; |
707 | int ret = 0; | ||
708 | |||
709 | if (!wm8750_codec) { | ||
710 | dev_err(&pdev->dev, "WM8750 codec not yet registered\n"); | ||
711 | return -EINVAL; | ||
712 | } | ||
713 | |||
714 | socdev->card->codec = wm8750_codec; | ||
715 | codec = wm8750_codec; | ||
716 | |||
717 | /* register pcms */ | ||
718 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
719 | if (ret < 0) { | ||
720 | printk(KERN_ERR "wm8750: failed to create pcms\n"); | ||
721 | goto err; | ||
722 | } | ||
723 | |||
724 | snd_soc_add_controls(codec, wm8750_snd_controls, | ||
725 | ARRAY_SIZE(wm8750_snd_controls)); | ||
726 | wm8750_add_widgets(codec); | ||
727 | |||
728 | return 0; | ||
729 | |||
730 | err: | ||
731 | return ret; | ||
732 | } | ||
733 | |||
734 | /* power down chip */ | ||
735 | static int wm8750_remove(struct platform_device *pdev) | ||
736 | { | ||
737 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
738 | |||
739 | snd_soc_free_pcms(socdev); | ||
740 | snd_soc_dapm_free(socdev); | ||
741 | |||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | struct snd_soc_codec_device soc_codec_dev_wm8750 = { | ||
746 | .probe = wm8750_probe, | ||
747 | .remove = wm8750_remove, | ||
748 | .suspend = wm8750_suspend, | ||
749 | .resume = wm8750_resume, | ||
750 | }; | ||
751 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750); | ||
752 | |||
753 | /* | ||
754 | * initialise the WM8750 driver | ||
755 | * register the mixer and dsp interfaces with the kernel | ||
756 | */ | ||
757 | static int wm8750_register(struct wm8750_priv *wm8750, | ||
758 | enum snd_soc_control_type control) | ||
759 | { | ||
760 | struct snd_soc_codec *codec = &wm8750->codec; | ||
761 | int reg, ret = 0; | ||
762 | |||
763 | if (wm8750_codec) { | ||
764 | dev_err(codec->dev, "Multiple WM8750 devices not supported\n"); | ||
765 | ret = -EINVAL; | ||
766 | goto err; | ||
767 | } | ||
768 | |||
769 | mutex_init(&codec->mutex); | ||
770 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
771 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
772 | |||
773 | codec->name = "WM8750"; | ||
774 | codec->owner = THIS_MODULE; | ||
775 | codec->bias_level = SND_SOC_BIAS_STANDBY; | ||
776 | codec->set_bias_level = wm8750_set_bias_level; | ||
777 | codec->dai = &wm8750_dai; | ||
778 | codec->num_dai = 1; | ||
779 | codec->reg_cache_size = ARRAY_SIZE(wm8750->reg_cache) + 1; | ||
780 | codec->reg_cache = &wm8750->reg_cache; | ||
781 | snd_soc_codec_set_drvdata(codec, wm8750); | ||
782 | |||
783 | memcpy(codec->reg_cache, wm8750_reg, sizeof(wm8750->reg_cache)); | ||
784 | 699 | ||
785 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 700 | codec->control_data = wm8750->control_data; |
701 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type); | ||
786 | if (ret < 0) { | 702 | if (ret < 0) { |
787 | printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); | 703 | printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); |
788 | goto err; | 704 | return ret; |
789 | } | 705 | } |
790 | 706 | ||
791 | ret = wm8750_reset(codec); | 707 | ret = wm8750_reset(codec); |
792 | if (ret < 0) { | 708 | if (ret < 0) { |
793 | printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); | 709 | printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); |
794 | goto err; | 710 | return ret; |
795 | } | 711 | } |
796 | 712 | ||
797 | /* charge output caps */ | 713 | /* charge output caps */ |
@@ -815,150 +731,133 @@ static int wm8750_register(struct wm8750_priv *wm8750, | |||
815 | reg = snd_soc_read(codec, WM8750_RINVOL); | 731 | reg = snd_soc_read(codec, WM8750_RINVOL); |
816 | snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); | 732 | snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); |
817 | 733 | ||
818 | wm8750_codec = codec; | 734 | snd_soc_add_controls(codec, wm8750_snd_controls, |
819 | 735 | ARRAY_SIZE(wm8750_snd_controls)); | |
820 | ret = snd_soc_register_codec(codec); | 736 | wm8750_add_widgets(codec); |
821 | if (ret != 0) { | ||
822 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
823 | goto err; | ||
824 | } | ||
825 | |||
826 | ret = snd_soc_register_dais(&wm8750_dai, 1); | ||
827 | if (ret != 0) { | ||
828 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
829 | goto err_codec; | ||
830 | } | ||
831 | |||
832 | return 0; | ||
833 | |||
834 | err_codec: | ||
835 | snd_soc_unregister_codec(codec); | ||
836 | err: | ||
837 | kfree(wm8750); | ||
838 | return ret; | 737 | return ret; |
839 | } | 738 | } |
840 | 739 | ||
841 | static void wm8750_unregister(struct wm8750_priv *wm8750) | 740 | static int wm8750_remove(struct snd_soc_codec *codec) |
842 | { | 741 | { |
843 | wm8750_set_bias_level(&wm8750->codec, SND_SOC_BIAS_OFF); | 742 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); |
844 | snd_soc_unregister_dais(&wm8750_dai, 1); | 743 | return 0; |
845 | snd_soc_unregister_codec(&wm8750->codec); | ||
846 | kfree(wm8750); | ||
847 | wm8750_codec = NULL; | ||
848 | } | 744 | } |
849 | 745 | ||
850 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 746 | static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { |
851 | 747 | .probe = wm8750_probe, | |
852 | /* | 748 | .remove = wm8750_remove, |
853 | * WM8750 2 wire address is determined by GPIO5 | 749 | .suspend = wm8750_suspend, |
854 | * state during powerup. | 750 | .resume = wm8750_resume, |
855 | * low = 0x1a | 751 | .set_bias_level = wm8750_set_bias_level, |
856 | * high = 0x1b | 752 | .reg_cache_size = sizeof(wm8750_reg), |
857 | */ | 753 | .reg_word_size = sizeof(u16), |
754 | .reg_cache_default = wm8750_reg, | ||
755 | }; | ||
858 | 756 | ||
859 | static int wm8750_i2c_probe(struct i2c_client *i2c, | 757 | #if defined(CONFIG_SPI_MASTER) |
860 | const struct i2c_device_id *id) | 758 | static int __devinit wm8750_spi_probe(struct spi_device *spi) |
861 | { | 759 | { |
862 | struct snd_soc_codec *codec; | ||
863 | struct wm8750_priv *wm8750; | 760 | struct wm8750_priv *wm8750; |
761 | int ret; | ||
864 | 762 | ||
865 | wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); | 763 | wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); |
866 | if (wm8750 == NULL) | 764 | if (wm8750 == NULL) |
867 | return -ENOMEM; | 765 | return -ENOMEM; |
868 | 766 | ||
869 | codec = &wm8750->codec; | 767 | wm8750->control_data = spi; |
870 | codec->control_data = i2c; | 768 | wm8750->control_type = SND_SOC_SPI; |
871 | i2c_set_clientdata(i2c, wm8750); | 769 | spi_set_drvdata(spi, wm8750); |
872 | |||
873 | codec->dev = &i2c->dev; | ||
874 | 770 | ||
875 | return wm8750_register(wm8750, SND_SOC_I2C); | 771 | ret = snd_soc_register_codec(&spi->dev, |
772 | &soc_codec_dev_wm8750, &wm8750_dai, 1); | ||
773 | if (ret < 0) | ||
774 | kfree(wm8750); | ||
775 | return ret; | ||
876 | } | 776 | } |
877 | 777 | ||
878 | static int wm8750_i2c_remove(struct i2c_client *client) | 778 | static int __devexit wm8750_spi_remove(struct spi_device *spi) |
879 | { | 779 | { |
880 | struct wm8750_priv *wm8750 = i2c_get_clientdata(client); | 780 | snd_soc_unregister_codec(&spi->dev); |
881 | wm8750_unregister(wm8750); | 781 | kfree(spi_get_drvdata(spi)); |
882 | return 0; | 782 | return 0; |
883 | } | 783 | } |
884 | 784 | ||
885 | static const struct i2c_device_id wm8750_i2c_id[] = { | 785 | static struct spi_driver wm8750_spi_driver = { |
886 | { "wm8750", 0 }, | ||
887 | { "wm8987", 0 }, /* WM8987 is register compatible with WM8750 */ | ||
888 | { } | ||
889 | }; | ||
890 | MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); | ||
891 | |||
892 | static struct i2c_driver wm8750_i2c_driver = { | ||
893 | .driver = { | 786 | .driver = { |
894 | .name = "WM8750 I2C Codec", | 787 | .name = "wm8750-codec", |
895 | .owner = THIS_MODULE, | 788 | .bus = &spi_bus_type, |
789 | .owner = THIS_MODULE, | ||
896 | }, | 790 | }, |
897 | .probe = wm8750_i2c_probe, | 791 | .probe = wm8750_spi_probe, |
898 | .remove = wm8750_i2c_remove, | 792 | .remove = __devexit_p(wm8750_spi_remove), |
899 | .id_table = wm8750_i2c_id, | ||
900 | }; | 793 | }; |
901 | #endif | 794 | #endif /* CONFIG_SPI_MASTER */ |
902 | 795 | ||
903 | #if defined(CONFIG_SPI_MASTER) | 796 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
904 | static int __devinit wm8750_spi_probe(struct spi_device *spi) | 797 | static __devinit int wm8750_i2c_probe(struct i2c_client *i2c, |
798 | const struct i2c_device_id *id) | ||
905 | { | 799 | { |
906 | struct snd_soc_codec *codec; | ||
907 | struct wm8750_priv *wm8750; | 800 | struct wm8750_priv *wm8750; |
801 | int ret; | ||
908 | 802 | ||
909 | wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); | 803 | wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); |
910 | if (wm8750 == NULL) | 804 | if (wm8750 == NULL) |
911 | return -ENOMEM; | 805 | return -ENOMEM; |
912 | 806 | ||
913 | codec = &wm8750->codec; | 807 | i2c_set_clientdata(i2c, wm8750); |
914 | codec->control_data = spi; | 808 | wm8750->control_data = i2c; |
915 | codec->dev = &spi->dev; | 809 | wm8750->control_type = SND_SOC_I2C; |
916 | |||
917 | dev_set_drvdata(&spi->dev, wm8750); | ||
918 | 810 | ||
919 | return wm8750_register(wm8750, SND_SOC_SPI); | 811 | ret = snd_soc_register_codec(&i2c->dev, |
812 | &soc_codec_dev_wm8750, &wm8750_dai, 1); | ||
813 | if (ret < 0) | ||
814 | kfree(wm8750); | ||
815 | return ret; | ||
920 | } | 816 | } |
921 | 817 | ||
922 | static int __devexit wm8750_spi_remove(struct spi_device *spi) | 818 | static __devexit int wm8750_i2c_remove(struct i2c_client *client) |
923 | { | 819 | { |
924 | struct wm8750_priv *wm8750 = dev_get_drvdata(&spi->dev); | 820 | snd_soc_unregister_codec(&client->dev); |
925 | wm8750_unregister(wm8750); | 821 | kfree(i2c_get_clientdata(client)); |
926 | return 0; | 822 | return 0; |
927 | } | 823 | } |
928 | 824 | ||
929 | static const struct spi_device_id wm8750_spi_id[] = { | 825 | static const struct i2c_device_id wm8750_i2c_id[] = { |
930 | { "wm8750", 0 }, | 826 | { "wm8750", 0 }, |
931 | { "wm8987", 0 }, | 827 | { "wm8987", 0 }, |
932 | { } | 828 | { } |
933 | }; | 829 | }; |
934 | MODULE_DEVICE_TABLE(spi, wm8750_spi_id); | 830 | MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); |
935 | 831 | ||
936 | static struct spi_driver wm8750_spi_driver = { | 832 | static struct i2c_driver wm8750_i2c_driver = { |
937 | .driver = { | 833 | .driver = { |
938 | .name = "WM8750 SPI Codec", | 834 | .name = "wm8750-codec", |
939 | .bus = &spi_bus_type, | 835 | .owner = THIS_MODULE, |
940 | .owner = THIS_MODULE, | ||
941 | }, | 836 | }, |
942 | .probe = wm8750_spi_probe, | 837 | .probe = wm8750_i2c_probe, |
943 | .remove = __devexit_p(wm8750_spi_remove), | 838 | .remove = __devexit_p(wm8750_i2c_remove), |
944 | .id_table = wm8750_spi_id, | 839 | .id_table = wm8750_i2c_id, |
945 | }; | 840 | }; |
946 | #endif | 841 | #endif |
947 | 842 | ||
948 | static int __init wm8750_modinit(void) | 843 | static int __init wm8750_modinit(void) |
949 | { | 844 | { |
950 | int ret; | 845 | int ret = 0; |
951 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 846 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
952 | ret = i2c_add_driver(&wm8750_i2c_driver); | 847 | ret = i2c_add_driver(&wm8750_i2c_driver); |
953 | if (ret != 0) | 848 | if (ret != 0) { |
954 | pr_err("Failed to register WM8750 I2C driver: %d\n", ret); | 849 | printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n", |
850 | ret); | ||
851 | } | ||
955 | #endif | 852 | #endif |
956 | #if defined(CONFIG_SPI_MASTER) | 853 | #if defined(CONFIG_SPI_MASTER) |
957 | ret = spi_register_driver(&wm8750_spi_driver); | 854 | ret = spi_register_driver(&wm8750_spi_driver); |
958 | if (ret != 0) | 855 | if (ret != 0) { |
959 | pr_err("Failed to register WM8750 SPI driver: %d\n", ret); | 856 | printk(KERN_ERR "Failed to register wm8750 SPI driver: %d\n", |
857 | ret); | ||
858 | } | ||
960 | #endif | 859 | #endif |
961 | return 0; | 860 | return ret; |
962 | } | 861 | } |
963 | module_init(wm8750_modinit); | 862 | module_init(wm8750_modinit); |
964 | 863 | ||
diff --git a/sound/soc/codecs/wm8750.h b/sound/soc/codecs/wm8750.h index 1dc100e19cfe..121427c047fb 100644 --- a/sound/soc/codecs/wm8750.h +++ b/sound/soc/codecs/wm8750.h | |||
@@ -57,13 +57,4 @@ | |||
57 | 57 | ||
58 | #define WM8750_SYSCLK 0 | 58 | #define WM8750_SYSCLK 0 |
59 | 59 | ||
60 | struct wm8750_setup_data { | ||
61 | int spi; | ||
62 | int i2c_bus; | ||
63 | unsigned short i2c_address; | ||
64 | }; | ||
65 | |||
66 | extern struct snd_soc_dai wm8750_dai; | ||
67 | extern struct snd_soc_codec_device soc_codec_dev_wm8750; | ||
68 | |||
69 | #endif | 60 | #endif |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index b59f349c5218..976e408b3616 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -57,7 +57,7 @@ module_param(caps_charge, int, 0); | |||
57 | MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); | 57 | MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); |
58 | 58 | ||
59 | static void wm8753_set_dai_mode(struct snd_soc_codec *codec, | 59 | static void wm8753_set_dai_mode(struct snd_soc_codec *codec, |
60 | unsigned int mode); | 60 | struct snd_soc_dai *dai, unsigned int hifi); |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * wm8753 register cache | 63 | * wm8753 register cache |
@@ -85,10 +85,12 @@ static const u16 wm8753_reg[] = { | |||
85 | 85 | ||
86 | /* codec private data */ | 86 | /* codec private data */ |
87 | struct wm8753_priv { | 87 | struct wm8753_priv { |
88 | enum snd_soc_control_type control_type; | ||
89 | void *control_data; | ||
88 | unsigned int sysclk; | 90 | unsigned int sysclk; |
89 | unsigned int pcmclk; | 91 | unsigned int pcmclk; |
90 | struct snd_soc_codec codec; | ||
91 | u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; | 92 | u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; |
93 | int dai_func; | ||
92 | }; | 94 | }; |
93 | 95 | ||
94 | /* | 96 | /* |
@@ -228,6 +230,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, | |||
228 | { | 230 | { |
229 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 231 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
230 | int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); | 232 | int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); |
233 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | ||
231 | 234 | ||
232 | if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) | 235 | if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) |
233 | return 0; | 236 | return 0; |
@@ -235,8 +238,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, | |||
235 | mode &= 0xfff3; | 238 | mode &= 0xfff3; |
236 | mode |= (ucontrol->value.integer.value[0] << 2); | 239 | mode |= (ucontrol->value.integer.value[0] << 2); |
237 | 240 | ||
238 | wm8753_write(codec, WM8753_IOCTL, mode); | 241 | wm8753->dai_func = ucontrol->value.integer.value[0]; |
239 | wm8753_set_dai_mode(codec, ucontrol->value.integer.value[0]); | ||
240 | return 1; | 242 | return 1; |
241 | } | 243 | } |
242 | 244 | ||
@@ -904,6 +906,13 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
904 | return 0; | 906 | return 0; |
905 | } | 907 | } |
906 | 908 | ||
909 | static int wm8753_pcm_startup(struct snd_pcm_substream *substream, | ||
910 | struct snd_soc_dai *dai) | ||
911 | { | ||
912 | wm8753_set_dai_mode(dai->codec, dai, 0); | ||
913 | return 0; | ||
914 | } | ||
915 | |||
907 | /* | 916 | /* |
908 | * Set PCM DAI bit size and sample rate. | 917 | * Set PCM DAI bit size and sample rate. |
909 | */ | 918 | */ |
@@ -912,8 +921,7 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, | |||
912 | struct snd_soc_dai *dai) | 921 | struct snd_soc_dai *dai) |
913 | { | 922 | { |
914 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 923 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
915 | struct snd_soc_device *socdev = rtd->socdev; | 924 | struct snd_soc_codec *codec = rtd->codec; |
916 | struct snd_soc_codec *codec = socdev->card->codec; | ||
917 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | 925 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
918 | u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; | 926 | u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; |
919 | u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; | 927 | u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; |
@@ -1138,6 +1146,13 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1138 | return 0; | 1146 | return 0; |
1139 | } | 1147 | } |
1140 | 1148 | ||
1149 | static int wm8753_i2s_startup(struct snd_pcm_substream *substream, | ||
1150 | struct snd_soc_dai *dai) | ||
1151 | { | ||
1152 | wm8753_set_dai_mode(dai->codec, dai, 1); | ||
1153 | return 0; | ||
1154 | } | ||
1155 | |||
1141 | /* | 1156 | /* |
1142 | * Set PCM DAI bit size and sample rate. | 1157 | * Set PCM DAI bit size and sample rate. |
1143 | */ | 1158 | */ |
@@ -1146,8 +1161,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, | |||
1146 | struct snd_soc_dai *dai) | 1161 | struct snd_soc_dai *dai) |
1147 | { | 1162 | { |
1148 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1163 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1149 | struct snd_soc_device *socdev = rtd->socdev; | 1164 | struct snd_soc_codec *codec = rtd->codec; |
1150 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1151 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | 1165 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
1152 | u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; | 1166 | u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; |
1153 | u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; | 1167 | u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; |
@@ -1240,12 +1254,12 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) | |||
1240 | { | 1254 | { |
1241 | struct snd_soc_codec *codec = dai->codec; | 1255 | struct snd_soc_codec *codec = dai->codec; |
1242 | u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; | 1256 | u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; |
1257 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | ||
1243 | 1258 | ||
1244 | /* the digital mute covers the HiFi and Voice DAC's on the WM8753. | 1259 | /* the digital mute covers the HiFi and Voice DAC's on the WM8753. |
1245 | * make sure we check if they are not both active when we mute */ | 1260 | * make sure we check if they are not both active when we mute */ |
1246 | if (mute && dai->id == 1) { | 1261 | if (mute && wm8753->dai_func == 1) { |
1247 | if (!wm8753_dai[WM8753_DAI_VOICE].playback.active || | 1262 | if (!codec->active) |
1248 | !wm8753_dai[WM8753_DAI_HIFI].playback.active) | ||
1249 | wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); | 1263 | wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); |
1250 | } else { | 1264 | } else { |
1251 | if (mute) | 1265 | if (mute) |
@@ -1303,6 +1317,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec, | |||
1303 | * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture | 1317 | * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture |
1304 | */ | 1318 | */ |
1305 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { | 1319 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { |
1320 | .startup = wm8753_i2s_startup, | ||
1306 | .hw_params = wm8753_i2s_hw_params, | 1321 | .hw_params = wm8753_i2s_hw_params, |
1307 | .digital_mute = wm8753_mute, | 1322 | .digital_mute = wm8753_mute, |
1308 | .set_fmt = wm8753_mode1h_set_dai_fmt, | 1323 | .set_fmt = wm8753_mode1h_set_dai_fmt, |
@@ -1312,6 +1327,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { | |||
1312 | }; | 1327 | }; |
1313 | 1328 | ||
1314 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { | 1329 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { |
1330 | .startup = wm8753_pcm_startup, | ||
1315 | .hw_params = wm8753_pcm_hw_params, | 1331 | .hw_params = wm8753_pcm_hw_params, |
1316 | .digital_mute = wm8753_mute, | 1332 | .digital_mute = wm8753_mute, |
1317 | .set_fmt = wm8753_mode1v_set_dai_fmt, | 1333 | .set_fmt = wm8753_mode1v_set_dai_fmt, |
@@ -1321,6 +1337,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { | |||
1321 | }; | 1337 | }; |
1322 | 1338 | ||
1323 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { | 1339 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { |
1340 | .startup = wm8753_pcm_startup, | ||
1324 | .hw_params = wm8753_pcm_hw_params, | 1341 | .hw_params = wm8753_pcm_hw_params, |
1325 | .digital_mute = wm8753_mute, | 1342 | .digital_mute = wm8753_mute, |
1326 | .set_fmt = wm8753_mode2_set_dai_fmt, | 1343 | .set_fmt = wm8753_mode2_set_dai_fmt, |
@@ -1330,6 +1347,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { | |||
1330 | }; | 1347 | }; |
1331 | 1348 | ||
1332 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = { | 1349 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = { |
1350 | .startup = wm8753_i2s_startup, | ||
1333 | .hw_params = wm8753_i2s_hw_params, | 1351 | .hw_params = wm8753_i2s_hw_params, |
1334 | .digital_mute = wm8753_mute, | 1352 | .digital_mute = wm8753_mute, |
1335 | .set_fmt = wm8753_mode3_4_set_dai_fmt, | 1353 | .set_fmt = wm8753_mode3_4_set_dai_fmt, |
@@ -1339,6 +1357,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = { | |||
1339 | }; | 1357 | }; |
1340 | 1358 | ||
1341 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = { | 1359 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = { |
1360 | .startup = wm8753_i2s_startup, | ||
1342 | .hw_params = wm8753_i2s_hw_params, | 1361 | .hw_params = wm8753_i2s_hw_params, |
1343 | .digital_mute = wm8753_mute, | 1362 | .digital_mute = wm8753_mute, |
1344 | .set_fmt = wm8753_mode3_4_set_dai_fmt, | 1363 | .set_fmt = wm8753_mode3_4_set_dai_fmt, |
@@ -1347,10 +1366,9 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = { | |||
1347 | .set_sysclk = wm8753_set_dai_sysclk, | 1366 | .set_sysclk = wm8753_set_dai_sysclk, |
1348 | }; | 1367 | }; |
1349 | 1368 | ||
1350 | static const struct snd_soc_dai wm8753_all_dai[] = { | 1369 | static struct snd_soc_dai_driver wm8753_all_dai[] = { |
1351 | /* DAI HiFi mode 1 */ | 1370 | /* DAI HiFi mode 1 */ |
1352 | { .name = "WM8753 HiFi", | 1371 | { .name = "wm8753-hifi", |
1353 | .id = 1, | ||
1354 | .playback = { | 1372 | .playback = { |
1355 | .stream_name = "HiFi Playback", | 1373 | .stream_name = "HiFi Playback", |
1356 | .channels_min = 1, | 1374 | .channels_min = 1, |
@@ -1366,8 +1384,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1366 | .ops = &wm8753_dai_ops_hifi_mode1, | 1384 | .ops = &wm8753_dai_ops_hifi_mode1, |
1367 | }, | 1385 | }, |
1368 | /* DAI Voice mode 1 */ | 1386 | /* DAI Voice mode 1 */ |
1369 | { .name = "WM8753 Voice", | 1387 | { .name = "wm8753-voice", |
1370 | .id = 1, | ||
1371 | .playback = { | 1388 | .playback = { |
1372 | .stream_name = "Voice Playback", | 1389 | .stream_name = "Voice Playback", |
1373 | .channels_min = 1, | 1390 | .channels_min = 1, |
@@ -1383,12 +1400,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1383 | .ops = &wm8753_dai_ops_voice_mode1, | 1400 | .ops = &wm8753_dai_ops_voice_mode1, |
1384 | }, | 1401 | }, |
1385 | /* DAI HiFi mode 2 - dummy */ | 1402 | /* DAI HiFi mode 2 - dummy */ |
1386 | { .name = "WM8753 HiFi", | 1403 | { .name = "wm8753-hifi", |
1387 | .id = 2, | ||
1388 | }, | 1404 | }, |
1389 | /* DAI Voice mode 2 */ | 1405 | /* DAI Voice mode 2 */ |
1390 | { .name = "WM8753 Voice", | 1406 | { .name = "wm8753-voice", |
1391 | .id = 2, | ||
1392 | .playback = { | 1407 | .playback = { |
1393 | .stream_name = "Voice Playback", | 1408 | .stream_name = "Voice Playback", |
1394 | .channels_min = 1, | 1409 | .channels_min = 1, |
@@ -1404,8 +1419,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1404 | .ops = &wm8753_dai_ops_voice_mode2, | 1419 | .ops = &wm8753_dai_ops_voice_mode2, |
1405 | }, | 1420 | }, |
1406 | /* DAI HiFi mode 3 */ | 1421 | /* DAI HiFi mode 3 */ |
1407 | { .name = "WM8753 HiFi", | 1422 | { .name = "wm8753-hifi", |
1408 | .id = 3, | ||
1409 | .playback = { | 1423 | .playback = { |
1410 | .stream_name = "HiFi Playback", | 1424 | .stream_name = "HiFi Playback", |
1411 | .channels_min = 1, | 1425 | .channels_min = 1, |
@@ -1421,12 +1435,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1421 | .ops = &wm8753_dai_ops_hifi_mode3, | 1435 | .ops = &wm8753_dai_ops_hifi_mode3, |
1422 | }, | 1436 | }, |
1423 | /* DAI Voice mode 3 - dummy */ | 1437 | /* DAI Voice mode 3 - dummy */ |
1424 | { .name = "WM8753 Voice", | 1438 | { .name = "wm8753-voice", |
1425 | .id = 3, | ||
1426 | }, | 1439 | }, |
1427 | /* DAI HiFi mode 4 */ | 1440 | /* DAI HiFi mode 4 */ |
1428 | { .name = "WM8753 HiFi", | 1441 | { .name = "wm8753-hifi", |
1429 | .id = 4, | ||
1430 | .playback = { | 1442 | .playback = { |
1431 | .stream_name = "HiFi Playback", | 1443 | .stream_name = "HiFi Playback", |
1432 | .channels_min = 1, | 1444 | .channels_min = 1, |
@@ -1442,58 +1454,31 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1442 | .ops = &wm8753_dai_ops_hifi_mode4, | 1454 | .ops = &wm8753_dai_ops_hifi_mode4, |
1443 | }, | 1455 | }, |
1444 | /* DAI Voice mode 4 - dummy */ | 1456 | /* DAI Voice mode 4 - dummy */ |
1445 | { .name = "WM8753 Voice", | 1457 | { .name = "wm8753-voice", |
1446 | .id = 4, | ||
1447 | }, | 1458 | }, |
1448 | }; | 1459 | }; |
1449 | 1460 | ||
1450 | struct snd_soc_dai wm8753_dai[] = { | 1461 | static struct snd_soc_dai_driver wm8753_dai[] = { |
1451 | { | 1462 | { |
1452 | .name = "WM8753 DAI 0", | 1463 | .name = "wm8753-aif0", |
1453 | }, | 1464 | }, |
1454 | { | 1465 | { |
1455 | .name = "WM8753 DAI 1", | 1466 | .name = "wm8753-aif1", |
1456 | }, | 1467 | }, |
1457 | }; | 1468 | }; |
1458 | EXPORT_SYMBOL_GPL(wm8753_dai); | ||
1459 | 1469 | ||
1460 | static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode) | 1470 | static void wm8753_set_dai_mode(struct snd_soc_codec *codec, |
1471 | struct snd_soc_dai *dai, unsigned int hifi) | ||
1461 | { | 1472 | { |
1462 | if (mode < 4) { | 1473 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
1463 | int playback_active, capture_active, codec_active, pop_wait; | 1474 | |
1464 | void *private_data; | 1475 | if (wm8753->dai_func < 4) { |
1465 | struct list_head list; | 1476 | if (hifi) |
1466 | 1477 | dai->driver = &wm8753_all_dai[wm8753->dai_func << 1]; | |
1467 | playback_active = wm8753_dai[0].playback.active; | 1478 | else |
1468 | capture_active = wm8753_dai[0].capture.active; | 1479 | dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1]; |
1469 | codec_active = wm8753_dai[0].active; | ||
1470 | private_data = wm8753_dai[0].private_data; | ||
1471 | pop_wait = wm8753_dai[0].pop_wait; | ||
1472 | list = wm8753_dai[0].list; | ||
1473 | wm8753_dai[0] = wm8753_all_dai[mode << 1]; | ||
1474 | wm8753_dai[0].playback.active = playback_active; | ||
1475 | wm8753_dai[0].capture.active = capture_active; | ||
1476 | wm8753_dai[0].active = codec_active; | ||
1477 | wm8753_dai[0].private_data = private_data; | ||
1478 | wm8753_dai[0].pop_wait = pop_wait; | ||
1479 | wm8753_dai[0].list = list; | ||
1480 | |||
1481 | playback_active = wm8753_dai[1].playback.active; | ||
1482 | capture_active = wm8753_dai[1].capture.active; | ||
1483 | codec_active = wm8753_dai[1].active; | ||
1484 | private_data = wm8753_dai[1].private_data; | ||
1485 | pop_wait = wm8753_dai[1].pop_wait; | ||
1486 | list = wm8753_dai[1].list; | ||
1487 | wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1]; | ||
1488 | wm8753_dai[1].playback.active = playback_active; | ||
1489 | wm8753_dai[1].capture.active = capture_active; | ||
1490 | wm8753_dai[1].active = codec_active; | ||
1491 | wm8753_dai[1].private_data = private_data; | ||
1492 | wm8753_dai[1].pop_wait = pop_wait; | ||
1493 | wm8753_dai[1].list = list; | ||
1494 | } | 1480 | } |
1495 | wm8753_dai[0].codec = codec; | 1481 | wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func); |
1496 | wm8753_dai[1].codec = codec; | ||
1497 | } | 1482 | } |
1498 | 1483 | ||
1499 | static void wm8753_work(struct work_struct *work) | 1484 | static void wm8753_work(struct work_struct *work) |
@@ -1503,19 +1488,14 @@ static void wm8753_work(struct work_struct *work) | |||
1503 | wm8753_set_bias_level(codec, codec->bias_level); | 1488 | wm8753_set_bias_level(codec, codec->bias_level); |
1504 | } | 1489 | } |
1505 | 1490 | ||
1506 | static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) | 1491 | static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1507 | { | 1492 | { |
1508 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1509 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1510 | |||
1511 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1493 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1512 | return 0; | 1494 | return 0; |
1513 | } | 1495 | } |
1514 | 1496 | ||
1515 | static int wm8753_resume(struct platform_device *pdev) | 1497 | static int wm8753_resume(struct snd_soc_codec *codec) |
1516 | { | 1498 | { |
1517 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1518 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1519 | int i; | 1499 | int i; |
1520 | u8 data[2]; | 1500 | u8 data[2]; |
1521 | u16 *cache = codec->reg_cache; | 1501 | u16 *cache = codec->reg_cache; |
@@ -1547,41 +1527,6 @@ static int wm8753_resume(struct platform_device *pdev) | |||
1547 | return 0; | 1527 | return 0; |
1548 | } | 1528 | } |
1549 | 1529 | ||
1550 | static struct snd_soc_codec *wm8753_codec; | ||
1551 | |||
1552 | static int wm8753_probe(struct platform_device *pdev) | ||
1553 | { | ||
1554 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1555 | struct snd_soc_codec *codec; | ||
1556 | int ret = 0; | ||
1557 | |||
1558 | if (!wm8753_codec) { | ||
1559 | dev_err(&pdev->dev, "WM8753 codec not yet registered\n"); | ||
1560 | return -EINVAL; | ||
1561 | } | ||
1562 | |||
1563 | socdev->card->codec = wm8753_codec; | ||
1564 | codec = wm8753_codec; | ||
1565 | |||
1566 | wm8753_set_dai_mode(codec, 0); | ||
1567 | |||
1568 | /* register pcms */ | ||
1569 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1570 | if (ret < 0) { | ||
1571 | printk(KERN_ERR "wm8753: failed to create pcms\n"); | ||
1572 | goto pcm_err; | ||
1573 | } | ||
1574 | |||
1575 | snd_soc_add_controls(codec, wm8753_snd_controls, | ||
1576 | ARRAY_SIZE(wm8753_snd_controls)); | ||
1577 | wm8753_add_widgets(codec); | ||
1578 | |||
1579 | return 0; | ||
1580 | |||
1581 | pcm_err: | ||
1582 | return ret; | ||
1583 | } | ||
1584 | |||
1585 | /* | 1530 | /* |
1586 | * This function forces any delayed work to be queued and run. | 1531 | * This function forces any delayed work to be queued and run. |
1587 | */ | 1532 | */ |
@@ -1601,62 +1546,30 @@ static int run_delayed_work(struct delayed_work *dwork) | |||
1601 | return ret; | 1546 | return ret; |
1602 | } | 1547 | } |
1603 | 1548 | ||
1604 | /* power down chip */ | 1549 | static int wm8753_probe(struct snd_soc_codec *codec) |
1605 | static int wm8753_remove(struct platform_device *pdev) | ||
1606 | { | 1550 | { |
1607 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1551 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
1608 | 1552 | int ret = 0, reg; | |
1609 | snd_soc_free_pcms(socdev); | ||
1610 | snd_soc_dapm_free(socdev); | ||
1611 | |||
1612 | return 0; | ||
1613 | } | ||
1614 | |||
1615 | struct snd_soc_codec_device soc_codec_dev_wm8753 = { | ||
1616 | .probe = wm8753_probe, | ||
1617 | .remove = wm8753_remove, | ||
1618 | .suspend = wm8753_suspend, | ||
1619 | .resume = wm8753_resume, | ||
1620 | }; | ||
1621 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753); | ||
1622 | 1553 | ||
1623 | static int wm8753_register(struct wm8753_priv *wm8753) | 1554 | codec->bias_level = SND_SOC_BIAS_OFF, |
1624 | { | 1555 | codec->control_data = wm8753->control_data; |
1625 | int ret, i; | 1556 | INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); |
1626 | struct snd_soc_codec *codec = &wm8753->codec; | ||
1627 | u16 reg; | ||
1628 | 1557 | ||
1629 | if (wm8753_codec) { | 1558 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type); |
1630 | dev_err(codec->dev, "Multiple WM8753 devices not supported\n"); | 1559 | if (ret < 0) { |
1631 | ret = -EINVAL; | 1560 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1632 | goto err; | 1561 | return ret; |
1633 | } | 1562 | } |
1634 | 1563 | ||
1635 | mutex_init(&codec->mutex); | ||
1636 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1637 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1638 | |||
1639 | codec->name = "WM8753"; | ||
1640 | codec->owner = THIS_MODULE; | ||
1641 | codec->read = wm8753_read_reg_cache; | ||
1642 | codec->write = wm8753_write; | ||
1643 | codec->bias_level = SND_SOC_BIAS_STANDBY; | ||
1644 | codec->set_bias_level = wm8753_set_bias_level; | ||
1645 | codec->dai = wm8753_dai; | ||
1646 | codec->num_dai = 2; | ||
1647 | codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1; | ||
1648 | codec->reg_cache = &wm8753->reg_cache; | ||
1649 | snd_soc_codec_set_drvdata(codec, wm8753); | ||
1650 | |||
1651 | memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache)); | ||
1652 | INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); | ||
1653 | |||
1654 | ret = wm8753_reset(codec); | 1564 | ret = wm8753_reset(codec); |
1655 | if (ret < 0) { | 1565 | if (ret < 0) { |
1656 | dev_err(codec->dev, "Failed to issue reset\n"); | 1566 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
1657 | goto err; | 1567 | return ret; |
1658 | } | 1568 | } |
1659 | 1569 | ||
1570 | wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1571 | wm8753->dai_func = 0; | ||
1572 | |||
1660 | /* charge output caps */ | 1573 | /* charge output caps */ |
1661 | wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | 1574 | wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); |
1662 | schedule_delayed_work(&codec->delayed_work, | 1575 | schedule_delayed_work(&codec->delayed_work, |
@@ -1684,165 +1597,139 @@ static int wm8753_register(struct wm8753_priv *wm8753) | |||
1684 | reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); | 1597 | reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); |
1685 | wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); | 1598 | wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); |
1686 | 1599 | ||
1687 | wm8753_codec = codec; | 1600 | snd_soc_add_controls(codec, wm8753_snd_controls, |
1688 | 1601 | ARRAY_SIZE(wm8753_snd_controls)); | |
1689 | for (i = 0; i < ARRAY_SIZE(wm8753_dai); i++) | 1602 | wm8753_add_widgets(codec); |
1690 | wm8753_dai[i].dev = codec->dev; | ||
1691 | |||
1692 | ret = snd_soc_register_codec(codec); | ||
1693 | if (ret != 0) { | ||
1694 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1695 | goto err; | ||
1696 | } | ||
1697 | |||
1698 | ret = snd_soc_register_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai)); | ||
1699 | if (ret != 0) { | ||
1700 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
1701 | goto err_codec; | ||
1702 | } | ||
1703 | 1603 | ||
1704 | return 0; | 1604 | return 0; |
1705 | 1605 | ||
1706 | err_codec: | ||
1707 | run_delayed_work(&codec->delayed_work); | 1606 | run_delayed_work(&codec->delayed_work); |
1708 | snd_soc_unregister_codec(codec); | ||
1709 | err: | ||
1710 | kfree(wm8753); | ||
1711 | return ret; | 1607 | return ret; |
1712 | } | 1608 | } |
1713 | 1609 | ||
1714 | static void wm8753_unregister(struct wm8753_priv *wm8753) | 1610 | /* power down chip */ |
1611 | static int wm8753_remove(struct snd_soc_codec *codec) | ||
1715 | { | 1612 | { |
1716 | wm8753_set_bias_level(&wm8753->codec, SND_SOC_BIAS_OFF); | 1613 | run_delayed_work(&codec->delayed_work); |
1717 | run_delayed_work(&wm8753->codec.delayed_work); | 1614 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1718 | snd_soc_unregister_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai)); | 1615 | |
1719 | snd_soc_unregister_codec(&wm8753->codec); | 1616 | return 0; |
1720 | kfree(wm8753); | ||
1721 | wm8753_codec = NULL; | ||
1722 | } | 1617 | } |
1723 | 1618 | ||
1724 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1619 | static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { |
1620 | .probe = wm8753_probe, | ||
1621 | .remove = wm8753_remove, | ||
1622 | .suspend = wm8753_suspend, | ||
1623 | .resume = wm8753_resume, | ||
1624 | .set_bias_level = wm8753_set_bias_level, | ||
1625 | .reg_cache_size = sizeof(wm8753_reg), | ||
1626 | .reg_word_size = sizeof(u16), | ||
1627 | .reg_cache_default = wm8753_reg, | ||
1628 | }; | ||
1725 | 1629 | ||
1726 | static int wm8753_i2c_probe(struct i2c_client *i2c, | 1630 | #if defined(CONFIG_SPI_MASTER) |
1727 | const struct i2c_device_id *id) | 1631 | static int __devinit wm8753_spi_probe(struct spi_device *spi) |
1728 | { | 1632 | { |
1729 | struct snd_soc_codec *codec; | ||
1730 | struct wm8753_priv *wm8753; | 1633 | struct wm8753_priv *wm8753; |
1634 | int ret; | ||
1731 | 1635 | ||
1732 | wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); | 1636 | wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); |
1733 | if (wm8753 == NULL) | 1637 | if (wm8753 == NULL) |
1734 | return -ENOMEM; | 1638 | return -ENOMEM; |
1735 | 1639 | ||
1736 | codec = &wm8753->codec; | 1640 | wm8753->control_data = spi; |
1737 | codec->hw_write = (hw_write_t)i2c_master_send; | 1641 | wm8753->control_type = SND_SOC_SPI; |
1738 | codec->control_data = i2c; | 1642 | spi_set_drvdata(spi, wm8753); |
1739 | i2c_set_clientdata(i2c, wm8753); | ||
1740 | |||
1741 | codec->dev = &i2c->dev; | ||
1742 | 1643 | ||
1743 | return wm8753_register(wm8753); | 1644 | ret = snd_soc_register_codec(&spi->dev, |
1645 | &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai)); | ||
1646 | if (ret < 0) | ||
1647 | kfree(wm8753); | ||
1648 | return ret; | ||
1744 | } | 1649 | } |
1745 | 1650 | ||
1746 | static int wm8753_i2c_remove(struct i2c_client *client) | 1651 | static int __devexit wm8753_spi_remove(struct spi_device *spi) |
1747 | { | 1652 | { |
1748 | struct wm8753_priv *wm8753 = i2c_get_clientdata(client); | 1653 | snd_soc_unregister_codec(&spi->dev); |
1749 | wm8753_unregister(wm8753); | 1654 | kfree(spi_get_drvdata(spi)); |
1750 | return 0; | 1655 | return 0; |
1751 | } | 1656 | } |
1752 | 1657 | ||
1753 | static const struct i2c_device_id wm8753_i2c_id[] = { | 1658 | static struct spi_driver wm8753_spi_driver = { |
1754 | { "wm8753", 0 }, | ||
1755 | { } | ||
1756 | }; | ||
1757 | MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); | ||
1758 | |||
1759 | static struct i2c_driver wm8753_i2c_driver = { | ||
1760 | .driver = { | 1659 | .driver = { |
1761 | .name = "wm8753", | 1660 | .name = "wm8753-codec", |
1762 | .owner = THIS_MODULE, | 1661 | .bus = &spi_bus_type, |
1662 | .owner = THIS_MODULE, | ||
1763 | }, | 1663 | }, |
1764 | .probe = wm8753_i2c_probe, | 1664 | .probe = wm8753_spi_probe, |
1765 | .remove = wm8753_i2c_remove, | 1665 | .remove = __devexit_p(wm8753_spi_remove), |
1766 | .id_table = wm8753_i2c_id, | ||
1767 | }; | 1666 | }; |
1768 | #endif | 1667 | #endif /* CONFIG_SPI_MASTER */ |
1769 | |||
1770 | #if defined(CONFIG_SPI_MASTER) | ||
1771 | static int wm8753_spi_write(struct spi_device *spi, const char *data, int len) | ||
1772 | { | ||
1773 | struct spi_transfer t; | ||
1774 | struct spi_message m; | ||
1775 | u8 msg[2]; | ||
1776 | |||
1777 | if (len <= 0) | ||
1778 | return 0; | ||
1779 | |||
1780 | msg[0] = data[0]; | ||
1781 | msg[1] = data[1]; | ||
1782 | 1668 | ||
1783 | spi_message_init(&m); | 1669 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1784 | memset(&t, 0, (sizeof t)); | 1670 | static __devinit int wm8753_i2c_probe(struct i2c_client *i2c, |
1785 | 1671 | const struct i2c_device_id *id) | |
1786 | t.tx_buf = &msg[0]; | ||
1787 | t.len = len; | ||
1788 | |||
1789 | spi_message_add_tail(&t, &m); | ||
1790 | spi_sync(spi, &m); | ||
1791 | |||
1792 | return len; | ||
1793 | } | ||
1794 | |||
1795 | static int __devinit wm8753_spi_probe(struct spi_device *spi) | ||
1796 | { | 1672 | { |
1797 | struct snd_soc_codec *codec; | ||
1798 | struct wm8753_priv *wm8753; | 1673 | struct wm8753_priv *wm8753; |
1674 | int ret; | ||
1799 | 1675 | ||
1800 | wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); | 1676 | wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); |
1801 | if (wm8753 == NULL) | 1677 | if (wm8753 == NULL) |
1802 | return -ENOMEM; | 1678 | return -ENOMEM; |
1803 | 1679 | ||
1804 | codec = &wm8753->codec; | 1680 | i2c_set_clientdata(i2c, wm8753); |
1805 | codec->control_data = spi; | 1681 | wm8753->control_data = i2c; |
1806 | codec->hw_write = (hw_write_t)wm8753_spi_write; | 1682 | wm8753->control_type = SND_SOC_I2C; |
1807 | codec->dev = &spi->dev; | ||
1808 | |||
1809 | dev_set_drvdata(&spi->dev, wm8753); | ||
1810 | 1683 | ||
1811 | return wm8753_register(wm8753); | 1684 | ret = snd_soc_register_codec(&i2c->dev, |
1685 | &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai)); | ||
1686 | if (ret < 0) | ||
1687 | kfree(wm8753); | ||
1688 | return ret; | ||
1812 | } | 1689 | } |
1813 | 1690 | ||
1814 | static int __devexit wm8753_spi_remove(struct spi_device *spi) | 1691 | static __devexit int wm8753_i2c_remove(struct i2c_client *client) |
1815 | { | 1692 | { |
1816 | struct wm8753_priv *wm8753 = dev_get_drvdata(&spi->dev); | 1693 | snd_soc_unregister_codec(&client->dev); |
1817 | wm8753_unregister(wm8753); | 1694 | kfree(i2c_get_clientdata(client)); |
1818 | return 0; | 1695 | return 0; |
1819 | } | 1696 | } |
1820 | 1697 | ||
1821 | static struct spi_driver wm8753_spi_driver = { | 1698 | static const struct i2c_device_id wm8753_i2c_id[] = { |
1699 | { "wm8753", 0 }, | ||
1700 | { } | ||
1701 | }; | ||
1702 | MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); | ||
1703 | |||
1704 | static struct i2c_driver wm8753_i2c_driver = { | ||
1822 | .driver = { | 1705 | .driver = { |
1823 | .name = "wm8753", | 1706 | .name = "wm8753-codec", |
1824 | .bus = &spi_bus_type, | 1707 | .owner = THIS_MODULE, |
1825 | .owner = THIS_MODULE, | ||
1826 | }, | 1708 | }, |
1827 | .probe = wm8753_spi_probe, | 1709 | .probe = wm8753_i2c_probe, |
1828 | .remove = __devexit_p(wm8753_spi_remove), | 1710 | .remove = __devexit_p(wm8753_i2c_remove), |
1711 | .id_table = wm8753_i2c_id, | ||
1829 | }; | 1712 | }; |
1830 | #endif | 1713 | #endif |
1831 | 1714 | ||
1832 | static int __init wm8753_modinit(void) | 1715 | static int __init wm8753_modinit(void) |
1833 | { | 1716 | { |
1834 | int ret; | 1717 | int ret = 0; |
1835 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1718 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1836 | ret = i2c_add_driver(&wm8753_i2c_driver); | 1719 | ret = i2c_add_driver(&wm8753_i2c_driver); |
1837 | if (ret != 0) | 1720 | if (ret != 0) { |
1838 | pr_err("Failed to register WM8753 I2C driver: %d\n", ret); | 1721 | printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n", |
1722 | ret); | ||
1723 | } | ||
1839 | #endif | 1724 | #endif |
1840 | #if defined(CONFIG_SPI_MASTER) | 1725 | #if defined(CONFIG_SPI_MASTER) |
1841 | ret = spi_register_driver(&wm8753_spi_driver); | 1726 | ret = spi_register_driver(&wm8753_spi_driver); |
1842 | if (ret != 0) | 1727 | if (ret != 0) { |
1843 | pr_err("Failed to register WM8753 SPI driver: %d\n", ret); | 1728 | printk(KERN_ERR "Failed to register wm8753 SPI driver: %d\n", |
1729 | ret); | ||
1730 | } | ||
1844 | #endif | 1731 | #endif |
1845 | return 0; | 1732 | return ret; |
1846 | } | 1733 | } |
1847 | module_init(wm8753_modinit); | 1734 | module_init(wm8753_modinit); |
1848 | 1735 | ||
diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h index 57b2ba244040..94edac144bcb 100644 --- a/sound/soc/codecs/wm8753.h +++ b/sound/soc/codecs/wm8753.h | |||
@@ -115,7 +115,4 @@ | |||
115 | #define WM8753_DAI_HIFI 0 | 115 | #define WM8753_DAI_HIFI 0 |
116 | #define WM8753_DAI_VOICE 1 | 116 | #define WM8753_DAI_VOICE 1 |
117 | 117 | ||
118 | extern struct snd_soc_dai wm8753_dai[2]; | ||
119 | extern struct snd_soc_codec_device soc_codec_dev_wm8753; | ||
120 | |||
121 | #endif | 118 | #endif |
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 4e212ed62ea6..51a2d265d40e 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
@@ -31,20 +31,14 @@ | |||
31 | 31 | ||
32 | #include "wm8776.h" | 32 | #include "wm8776.h" |
33 | 33 | ||
34 | static struct snd_soc_codec *wm8776_codec; | ||
35 | struct snd_soc_codec_device soc_codec_dev_wm8776; | ||
36 | |||
37 | /* codec private data */ | 34 | /* codec private data */ |
38 | struct wm8776_priv { | 35 | struct wm8776_priv { |
39 | struct snd_soc_codec codec; | 36 | enum snd_soc_control_type control_type; |
37 | void *control_data; | ||
40 | u16 reg_cache[WM8776_CACHEREGNUM]; | 38 | u16 reg_cache[WM8776_CACHEREGNUM]; |
41 | int sysclk[2]; | 39 | int sysclk[2]; |
42 | }; | 40 | }; |
43 | 41 | ||
44 | #ifdef CONFIG_SPI_MASTER | ||
45 | static int wm8776_spi_write(struct spi_device *spi, const char *data, int len); | ||
46 | #endif | ||
47 | |||
48 | static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { | 42 | static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { |
49 | 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ | 43 | 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ |
50 | 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ | 44 | 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ |
@@ -144,7 +138,7 @@ static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
144 | struct snd_soc_codec *codec = dai->codec; | 138 | struct snd_soc_codec *codec = dai->codec; |
145 | int reg, iface, master; | 139 | int reg, iface, master; |
146 | 140 | ||
147 | switch (dai->id) { | 141 | switch (dai->driver->id) { |
148 | case WM8776_DAI_DAC: | 142 | case WM8776_DAI_DAC: |
149 | reg = WM8776_DACIFCTRL; | 143 | reg = WM8776_DACIFCTRL; |
150 | master = 0x80; | 144 | master = 0x80; |
@@ -233,7 +227,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, | |||
233 | 227 | ||
234 | iface = 0; | 228 | iface = 0; |
235 | 229 | ||
236 | switch (dai->id) { | 230 | switch (dai->driver->id) { |
237 | case WM8776_DAI_DAC: | 231 | case WM8776_DAI_DAC: |
238 | iface_reg = WM8776_DACIFCTRL; | 232 | iface_reg = WM8776_DACIFCTRL; |
239 | master = 0x80; | 233 | master = 0x80; |
@@ -267,7 +261,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, | |||
267 | /* Only need to set MCLK/LRCLK ratio if we're master */ | 261 | /* Only need to set MCLK/LRCLK ratio if we're master */ |
268 | if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) { | 262 | if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) { |
269 | for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { | 263 | for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { |
270 | if (wm8776->sysclk[dai->id] / params_rate(params) | 264 | if (wm8776->sysclk[dai->driver->id] / params_rate(params) |
271 | == mclk_ratios[i]) | 265 | == mclk_ratios[i]) |
272 | break; | 266 | break; |
273 | } | 267 | } |
@@ -275,7 +269,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, | |||
275 | if (i == ARRAY_SIZE(mclk_ratios)) { | 269 | if (i == ARRAY_SIZE(mclk_ratios)) { |
276 | dev_err(codec->dev, | 270 | dev_err(codec->dev, |
277 | "Unable to configure MCLK ratio %d/%d\n", | 271 | "Unable to configure MCLK ratio %d/%d\n", |
278 | wm8776->sysclk[dai->id], params_rate(params)); | 272 | wm8776->sysclk[dai->driver->id], params_rate(params)); |
279 | return -EINVAL; | 273 | return -EINVAL; |
280 | } | 274 | } |
281 | 275 | ||
@@ -305,9 +299,9 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai, | |||
305 | struct snd_soc_codec *codec = dai->codec; | 299 | struct snd_soc_codec *codec = dai->codec; |
306 | struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); | 300 | struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); |
307 | 301 | ||
308 | BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk)); | 302 | BUG_ON(dai->driver->id >= ARRAY_SIZE(wm8776->sysclk)); |
309 | 303 | ||
310 | wm8776->sysclk[dai->id] = freq; | 304 | wm8776->sysclk[dai->driver->id] = freq; |
311 | 305 | ||
312 | return 0; | 306 | return 0; |
313 | } | 307 | } |
@@ -357,10 +351,10 @@ static struct snd_soc_dai_ops wm8776_adc_ops = { | |||
357 | .set_sysclk = wm8776_set_sysclk, | 351 | .set_sysclk = wm8776_set_sysclk, |
358 | }; | 352 | }; |
359 | 353 | ||
360 | struct snd_soc_dai wm8776_dai[] = { | 354 | static struct snd_soc_dai_driver wm8776_dai[] = { |
361 | { | 355 | { |
362 | .name = "WM8776 Playback", | 356 | .name = "wm8776-hifi-playback", |
363 | .id = WM8776_DAI_DAC, | 357 | .id = WM8776_DAI_DAC, |
364 | .playback = { | 358 | .playback = { |
365 | .stream_name = "Playback", | 359 | .stream_name = "Playback", |
366 | .channels_min = 2, | 360 | .channels_min = 2, |
@@ -371,8 +365,8 @@ struct snd_soc_dai wm8776_dai[] = { | |||
371 | .ops = &wm8776_dac_ops, | 365 | .ops = &wm8776_dac_ops, |
372 | }, | 366 | }, |
373 | { | 367 | { |
374 | .name = "WM8776 Capture", | 368 | .name = "wm8776-hifi-capture", |
375 | .id = WM8776_DAI_ADC, | 369 | .id = WM8776_DAI_ADC, |
376 | .capture = { | 370 | .capture = { |
377 | .stream_name = "Capture", | 371 | .stream_name = "Capture", |
378 | .channels_min = 2, | 372 | .channels_min = 2, |
@@ -383,23 +377,17 @@ struct snd_soc_dai wm8776_dai[] = { | |||
383 | .ops = &wm8776_adc_ops, | 377 | .ops = &wm8776_adc_ops, |
384 | }, | 378 | }, |
385 | }; | 379 | }; |
386 | EXPORT_SYMBOL_GPL(wm8776_dai); | ||
387 | 380 | ||
388 | #ifdef CONFIG_PM | 381 | #ifdef CONFIG_PM |
389 | static int wm8776_suspend(struct platform_device *pdev, pm_message_t state) | 382 | static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state) |
390 | { | 383 | { |
391 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
392 | struct snd_soc_codec *codec = socdev->card->codec; | ||
393 | |||
394 | wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); | 384 | wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); |
395 | 385 | ||
396 | return 0; | 386 | return 0; |
397 | } | 387 | } |
398 | 388 | ||
399 | static int wm8776_resume(struct platform_device *pdev) | 389 | static int wm8776_resume(struct snd_soc_codec *codec) |
400 | { | 390 | { |
401 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
402 | struct snd_soc_codec *codec = socdev->card->codec; | ||
403 | int i; | 391 | int i; |
404 | u8 data[2]; | 392 | u8 data[2]; |
405 | u16 *cache = codec->reg_cache; | 393 | u16 *cache = codec->reg_cache; |
@@ -422,27 +410,31 @@ static int wm8776_resume(struct platform_device *pdev) | |||
422 | #define wm8776_resume NULL | 410 | #define wm8776_resume NULL |
423 | #endif | 411 | #endif |
424 | 412 | ||
425 | static int wm8776_probe(struct platform_device *pdev) | 413 | static int wm8776_probe(struct snd_soc_codec *codec) |
426 | { | 414 | { |
427 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 415 | struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); |
428 | struct snd_soc_codec *codec; | ||
429 | int ret = 0; | 416 | int ret = 0; |
430 | 417 | ||
431 | if (wm8776_codec == NULL) { | 418 | codec->control_data = wm8776->control_data; |
432 | dev_err(&pdev->dev, "Codec device not registered\n"); | 419 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type); |
433 | return -ENODEV; | 420 | if (ret < 0) { |
421 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
422 | return ret; | ||
434 | } | 423 | } |
435 | 424 | ||
436 | socdev->card->codec = wm8776_codec; | 425 | ret = wm8776_reset(codec); |
437 | codec = wm8776_codec; | ||
438 | |||
439 | /* register pcms */ | ||
440 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
441 | if (ret < 0) { | 426 | if (ret < 0) { |
442 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | 427 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
443 | goto pcm_err; | 428 | return ret; |
444 | } | 429 | } |
445 | 430 | ||
431 | wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
432 | |||
433 | /* Latch the update bits; right channel only since we always | ||
434 | * update both. */ | ||
435 | snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); | ||
436 | snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); | ||
437 | |||
446 | snd_soc_add_controls(codec, wm8776_snd_controls, | 438 | snd_soc_add_controls(codec, wm8776_snd_controls, |
447 | ARRAY_SIZE(wm8776_snd_controls)); | 439 | ARRAY_SIZE(wm8776_snd_controls)); |
448 | snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets, | 440 | snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets, |
@@ -450,168 +442,57 @@ static int wm8776_probe(struct platform_device *pdev) | |||
450 | snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); | 442 | snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); |
451 | 443 | ||
452 | return ret; | 444 | return ret; |
453 | |||
454 | pcm_err: | ||
455 | return ret; | ||
456 | } | 445 | } |
457 | 446 | ||
458 | /* power down chip */ | 447 | /* power down chip */ |
459 | static int wm8776_remove(struct platform_device *pdev) | 448 | static int wm8776_remove(struct snd_soc_codec *codec) |
460 | { | 449 | { |
461 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 450 | wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); |
462 | |||
463 | snd_soc_free_pcms(socdev); | ||
464 | snd_soc_dapm_free(socdev); | ||
465 | |||
466 | return 0; | 451 | return 0; |
467 | } | 452 | } |
468 | 453 | ||
469 | struct snd_soc_codec_device soc_codec_dev_wm8776 = { | 454 | static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { |
470 | .probe = wm8776_probe, | 455 | .probe = wm8776_probe, |
471 | .remove = wm8776_remove, | 456 | .remove = wm8776_remove, |
472 | .suspend = wm8776_suspend, | 457 | .suspend = wm8776_suspend, |
473 | .resume = wm8776_resume, | 458 | .resume = wm8776_resume, |
459 | .set_bias_level = wm8776_set_bias_level, | ||
460 | .reg_cache_size = sizeof(wm8776_reg), | ||
461 | .reg_word_size = sizeof(u16), | ||
462 | .reg_cache_default = wm8776_reg, | ||
474 | }; | 463 | }; |
475 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776); | ||
476 | |||
477 | static int wm8776_register(struct wm8776_priv *wm8776, | ||
478 | enum snd_soc_control_type control) | ||
479 | { | ||
480 | int ret, i; | ||
481 | struct snd_soc_codec *codec = &wm8776->codec; | ||
482 | |||
483 | if (wm8776_codec) { | ||
484 | dev_err(codec->dev, "Another WM8776 is registered\n"); | ||
485 | ret = -EINVAL; | ||
486 | goto err; | ||
487 | } | ||
488 | |||
489 | mutex_init(&codec->mutex); | ||
490 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
491 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
492 | |||
493 | snd_soc_codec_set_drvdata(codec, wm8776); | ||
494 | codec->name = "WM8776"; | ||
495 | codec->owner = THIS_MODULE; | ||
496 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
497 | codec->set_bias_level = wm8776_set_bias_level; | ||
498 | codec->dai = wm8776_dai; | ||
499 | codec->num_dai = ARRAY_SIZE(wm8776_dai); | ||
500 | codec->reg_cache_size = WM8776_CACHEREGNUM; | ||
501 | codec->reg_cache = &wm8776->reg_cache; | ||
502 | |||
503 | memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg)); | ||
504 | |||
505 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
506 | if (ret < 0) { | ||
507 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
508 | goto err; | ||
509 | } | ||
510 | |||
511 | for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++) | ||
512 | wm8776_dai[i].dev = codec->dev; | ||
513 | |||
514 | ret = wm8776_reset(codec); | ||
515 | if (ret < 0) { | ||
516 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | ||
517 | goto err; | ||
518 | } | ||
519 | |||
520 | wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
521 | |||
522 | /* Latch the update bits; right channel only since we always | ||
523 | * update both. */ | ||
524 | snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); | ||
525 | snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); | ||
526 | |||
527 | wm8776_codec = codec; | ||
528 | |||
529 | ret = snd_soc_register_codec(codec); | ||
530 | if (ret != 0) { | ||
531 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
532 | goto err; | ||
533 | } | ||
534 | |||
535 | ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); | ||
536 | if (ret != 0) { | ||
537 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
538 | goto err_codec; | ||
539 | } | ||
540 | |||
541 | return 0; | ||
542 | |||
543 | err_codec: | ||
544 | snd_soc_unregister_codec(codec); | ||
545 | err: | ||
546 | kfree(wm8776); | ||
547 | return ret; | ||
548 | } | ||
549 | |||
550 | static void wm8776_unregister(struct wm8776_priv *wm8776) | ||
551 | { | ||
552 | wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF); | ||
553 | snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); | ||
554 | snd_soc_unregister_codec(&wm8776->codec); | ||
555 | kfree(wm8776); | ||
556 | wm8776_codec = NULL; | ||
557 | } | ||
558 | 464 | ||
559 | #if defined(CONFIG_SPI_MASTER) | 465 | #if defined(CONFIG_SPI_MASTER) |
560 | static int wm8776_spi_write(struct spi_device *spi, const char *data, int len) | ||
561 | { | ||
562 | struct spi_transfer t; | ||
563 | struct spi_message m; | ||
564 | u8 msg[2]; | ||
565 | |||
566 | if (len <= 0) | ||
567 | return 0; | ||
568 | |||
569 | msg[0] = data[0]; | ||
570 | msg[1] = data[1]; | ||
571 | |||
572 | spi_message_init(&m); | ||
573 | memset(&t, 0, (sizeof t)); | ||
574 | |||
575 | t.tx_buf = &msg[0]; | ||
576 | t.len = len; | ||
577 | |||
578 | spi_message_add_tail(&t, &m); | ||
579 | spi_sync(spi, &m); | ||
580 | |||
581 | return len; | ||
582 | } | ||
583 | |||
584 | static int __devinit wm8776_spi_probe(struct spi_device *spi) | 466 | static int __devinit wm8776_spi_probe(struct spi_device *spi) |
585 | { | 467 | { |
586 | struct snd_soc_codec *codec; | ||
587 | struct wm8776_priv *wm8776; | 468 | struct wm8776_priv *wm8776; |
469 | int ret; | ||
588 | 470 | ||
589 | wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); | 471 | wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); |
590 | if (wm8776 == NULL) | 472 | if (wm8776 == NULL) |
591 | return -ENOMEM; | 473 | return -ENOMEM; |
592 | 474 | ||
593 | codec = &wm8776->codec; | 475 | wm8776->control_data = spi; |
594 | codec->control_data = spi; | 476 | wm8776->control_type = SND_SOC_SPI; |
595 | codec->hw_write = (hw_write_t)wm8776_spi_write; | 477 | spi_set_drvdata(spi, wm8776); |
596 | codec->dev = &spi->dev; | ||
597 | 478 | ||
598 | dev_set_drvdata(&spi->dev, wm8776); | 479 | ret = snd_soc_register_codec(&spi->dev, |
599 | 480 | &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); | |
600 | return wm8776_register(wm8776, SND_SOC_SPI); | 481 | if (ret < 0) |
482 | kfree(wm8776); | ||
483 | return ret; | ||
601 | } | 484 | } |
602 | 485 | ||
603 | static int __devexit wm8776_spi_remove(struct spi_device *spi) | 486 | static int __devexit wm8776_spi_remove(struct spi_device *spi) |
604 | { | 487 | { |
605 | struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev); | 488 | snd_soc_unregister_codec(&spi->dev); |
606 | 489 | kfree(spi_get_drvdata(spi)); | |
607 | wm8776_unregister(wm8776); | ||
608 | |||
609 | return 0; | 490 | return 0; |
610 | } | 491 | } |
611 | 492 | ||
612 | static struct spi_driver wm8776_spi_driver = { | 493 | static struct spi_driver wm8776_spi_driver = { |
613 | .driver = { | 494 | .driver = { |
614 | .name = "wm8776", | 495 | .name = "wm8776-codec", |
615 | .bus = &spi_bus_type, | 496 | .bus = &spi_bus_type, |
616 | .owner = THIS_MODULE, | 497 | .owner = THIS_MODULE, |
617 | }, | 498 | }, |
@@ -625,27 +506,27 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c, | |||
625 | const struct i2c_device_id *id) | 506 | const struct i2c_device_id *id) |
626 | { | 507 | { |
627 | struct wm8776_priv *wm8776; | 508 | struct wm8776_priv *wm8776; |
628 | struct snd_soc_codec *codec; | 509 | int ret; |
629 | 510 | ||
630 | wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); | 511 | wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); |
631 | if (wm8776 == NULL) | 512 | if (wm8776 == NULL) |
632 | return -ENOMEM; | 513 | return -ENOMEM; |
633 | 514 | ||
634 | codec = &wm8776->codec; | ||
635 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
636 | |||
637 | i2c_set_clientdata(i2c, wm8776); | 515 | i2c_set_clientdata(i2c, wm8776); |
638 | codec->control_data = i2c; | 516 | wm8776->control_data = i2c; |
639 | 517 | wm8776->control_type = SND_SOC_I2C; | |
640 | codec->dev = &i2c->dev; | ||
641 | 518 | ||
642 | return wm8776_register(wm8776, SND_SOC_I2C); | 519 | ret = snd_soc_register_codec(&i2c->dev, |
520 | &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); | ||
521 | if (ret < 0) | ||
522 | kfree(wm8776); | ||
523 | return ret; | ||
643 | } | 524 | } |
644 | 525 | ||
645 | static __devexit int wm8776_i2c_remove(struct i2c_client *client) | 526 | static __devexit int wm8776_i2c_remove(struct i2c_client *client) |
646 | { | 527 | { |
647 | struct wm8776_priv *wm8776 = i2c_get_clientdata(client); | 528 | snd_soc_unregister_codec(&client->dev); |
648 | wm8776_unregister(wm8776); | 529 | kfree(i2c_get_clientdata(client)); |
649 | return 0; | 530 | return 0; |
650 | } | 531 | } |
651 | 532 | ||
@@ -657,7 +538,7 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id); | |||
657 | 538 | ||
658 | static struct i2c_driver wm8776_i2c_driver = { | 539 | static struct i2c_driver wm8776_i2c_driver = { |
659 | .driver = { | 540 | .driver = { |
660 | .name = "wm8776", | 541 | .name = "wm8776-codec", |
661 | .owner = THIS_MODULE, | 542 | .owner = THIS_MODULE, |
662 | }, | 543 | }, |
663 | .probe = wm8776_i2c_probe, | 544 | .probe = wm8776_i2c_probe, |
@@ -668,22 +549,22 @@ static struct i2c_driver wm8776_i2c_driver = { | |||
668 | 549 | ||
669 | static int __init wm8776_modinit(void) | 550 | static int __init wm8776_modinit(void) |
670 | { | 551 | { |
671 | int ret; | 552 | int ret = 0; |
672 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 553 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
673 | ret = i2c_add_driver(&wm8776_i2c_driver); | 554 | ret = i2c_add_driver(&wm8776_i2c_driver); |
674 | if (ret != 0) { | 555 | if (ret != 0) { |
675 | printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n", | 556 | printk(KERN_ERR "Failed to register wm8776 I2C driver: %d\n", |
676 | ret); | 557 | ret); |
677 | } | 558 | } |
678 | #endif | 559 | #endif |
679 | #if defined(CONFIG_SPI_MASTER) | 560 | #if defined(CONFIG_SPI_MASTER) |
680 | ret = spi_register_driver(&wm8776_spi_driver); | 561 | ret = spi_register_driver(&wm8776_spi_driver); |
681 | if (ret != 0) { | 562 | if (ret != 0) { |
682 | printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n", | 563 | printk(KERN_ERR "Failed to register wm8776 SPI driver: %d\n", |
683 | ret); | 564 | ret); |
684 | } | 565 | } |
685 | #endif | 566 | #endif |
686 | return 0; | 567 | return ret; |
687 | } | 568 | } |
688 | module_init(wm8776_modinit); | 569 | module_init(wm8776_modinit); |
689 | 570 | ||
diff --git a/sound/soc/codecs/wm8776.h b/sound/soc/codecs/wm8776.h index 6606d25d2d83..4cf1c8e0bfc9 100644 --- a/sound/soc/codecs/wm8776.h +++ b/sound/soc/codecs/wm8776.h | |||
@@ -45,7 +45,4 @@ | |||
45 | #define WM8776_DAI_DAC 0 | 45 | #define WM8776_DAI_DAC 0 |
46 | #define WM8776_DAI_ADC 1 | 46 | #define WM8776_DAI_ADC 1 |
47 | 47 | ||
48 | extern struct snd_soc_dai wm8776_dai[]; | ||
49 | extern struct snd_soc_codec_device soc_codec_dev_wm8776; | ||
50 | |||
51 | #endif | 48 | #endif |
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5da17a704e5a..33c3b57f3f66 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/spi/spi.h> | ||
26 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
@@ -137,11 +138,9 @@ | |||
137 | 138 | ||
138 | #define WM8900_LRC_MASK 0xfc00 | 139 | #define WM8900_LRC_MASK 0xfc00 |
139 | 140 | ||
140 | struct snd_soc_codec_device soc_codec_dev_wm8900; | ||
141 | |||
142 | struct wm8900_priv { | 141 | struct wm8900_priv { |
143 | struct snd_soc_codec codec; | 142 | enum snd_soc_control_type control_type; |
144 | 143 | void *control_data; | |
145 | u16 reg_cache[WM8900_MAXREG]; | 144 | u16 reg_cache[WM8900_MAXREG]; |
146 | 145 | ||
147 | u32 fll_in; /* FLL input frequency */ | 146 | u32 fll_in; /* FLL input frequency */ |
@@ -627,8 +626,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, | |||
627 | struct snd_soc_dai *dai) | 626 | struct snd_soc_dai *dai) |
628 | { | 627 | { |
629 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 628 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
630 | struct snd_soc_device *socdev = rtd->socdev; | 629 | struct snd_soc_codec *codec = rtd->codec; |
631 | struct snd_soc_codec *codec = socdev->card->codec; | ||
632 | u16 reg; | 630 | u16 reg; |
633 | 631 | ||
634 | reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; | 632 | reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; |
@@ -1015,8 +1013,8 @@ static struct snd_soc_dai_ops wm8900_dai_ops = { | |||
1015 | .digital_mute = wm8900_digital_mute, | 1013 | .digital_mute = wm8900_digital_mute, |
1016 | }; | 1014 | }; |
1017 | 1015 | ||
1018 | struct snd_soc_dai wm8900_dai = { | 1016 | static struct snd_soc_dai_driver wm8900_dai = { |
1019 | .name = "WM8900 HiFi", | 1017 | .name = "wm8900-hifi", |
1020 | .playback = { | 1018 | .playback = { |
1021 | .stream_name = "HiFi Playback", | 1019 | .stream_name = "HiFi Playback", |
1022 | .channels_min = 1, | 1020 | .channels_min = 1, |
@@ -1033,7 +1031,6 @@ struct snd_soc_dai wm8900_dai = { | |||
1033 | }, | 1031 | }, |
1034 | .ops = &wm8900_dai_ops, | 1032 | .ops = &wm8900_dai_ops, |
1035 | }; | 1033 | }; |
1036 | EXPORT_SYMBOL_GPL(wm8900_dai); | ||
1037 | 1034 | ||
1038 | static int wm8900_set_bias_level(struct snd_soc_codec *codec, | 1035 | static int wm8900_set_bias_level(struct snd_soc_codec *codec, |
1039 | enum snd_soc_bias_level level) | 1036 | enum snd_soc_bias_level level) |
@@ -1128,10 +1125,8 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec, | |||
1128 | return 0; | 1125 | return 0; |
1129 | } | 1126 | } |
1130 | 1127 | ||
1131 | static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) | 1128 | static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1132 | { | 1129 | { |
1133 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1134 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1135 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); | 1130 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); |
1136 | int fll_out = wm8900->fll_out; | 1131 | int fll_out = wm8900->fll_out; |
1137 | int fll_in = wm8900->fll_in; | 1132 | int fll_in = wm8900->fll_in; |
@@ -1140,7 +1135,7 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) | |||
1140 | /* Stop the FLL in an orderly fashion */ | 1135 | /* Stop the FLL in an orderly fashion */ |
1141 | ret = wm8900_set_fll(codec, 0, 0, 0); | 1136 | ret = wm8900_set_fll(codec, 0, 0, 0); |
1142 | if (ret != 0) { | 1137 | if (ret != 0) { |
1143 | dev_err(&pdev->dev, "Failed to stop FLL\n"); | 1138 | dev_err(codec->dev, "Failed to stop FLL\n"); |
1144 | return ret; | 1139 | return ret; |
1145 | } | 1140 | } |
1146 | 1141 | ||
@@ -1152,10 +1147,8 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) | |||
1152 | return 0; | 1147 | return 0; |
1153 | } | 1148 | } |
1154 | 1149 | ||
1155 | static int wm8900_resume(struct platform_device *pdev) | 1150 | static int wm8900_resume(struct snd_soc_codec *codec) |
1156 | { | 1151 | { |
1157 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1158 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1159 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); | 1152 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); |
1160 | u16 *cache; | 1153 | u16 *cache; |
1161 | int i, ret; | 1154 | int i, ret; |
@@ -1176,7 +1169,7 @@ static int wm8900_resume(struct platform_device *pdev) | |||
1176 | 1169 | ||
1177 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); | 1170 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); |
1178 | if (ret != 0) { | 1171 | if (ret != 0) { |
1179 | dev_err(&pdev->dev, "Failed to restart FLL\n"); | 1172 | dev_err(codec->dev, "Failed to restart FLL\n"); |
1180 | return ret; | 1173 | return ret; |
1181 | } | 1174 | } |
1182 | } | 1175 | } |
@@ -1186,60 +1179,33 @@ static int wm8900_resume(struct platform_device *pdev) | |||
1186 | snd_soc_write(codec, i, cache[i]); | 1179 | snd_soc_write(codec, i, cache[i]); |
1187 | kfree(cache); | 1180 | kfree(cache); |
1188 | } else | 1181 | } else |
1189 | dev_err(&pdev->dev, "Unable to allocate register cache\n"); | 1182 | dev_err(codec->dev, "Unable to allocate register cache\n"); |
1190 | 1183 | ||
1191 | return 0; | 1184 | return 0; |
1192 | } | 1185 | } |
1193 | 1186 | ||
1194 | static struct snd_soc_codec *wm8900_codec; | 1187 | static int wm8900_probe(struct snd_soc_codec *codec) |
1195 | |||
1196 | static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, | ||
1197 | const struct i2c_device_id *id) | ||
1198 | { | 1188 | { |
1199 | struct wm8900_priv *wm8900; | 1189 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); |
1200 | struct snd_soc_codec *codec; | 1190 | int ret = 0, reg; |
1201 | unsigned int reg; | ||
1202 | int ret; | ||
1203 | |||
1204 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1205 | if (wm8900 == NULL) | ||
1206 | return -ENOMEM; | ||
1207 | 1191 | ||
1208 | codec = &wm8900->codec; | 1192 | codec->control_data = wm8900->control_data; |
1209 | snd_soc_codec_set_drvdata(codec, wm8900); | 1193 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type); |
1210 | codec->reg_cache = &wm8900->reg_cache[0]; | ||
1211 | codec->reg_cache_size = WM8900_MAXREG; | ||
1212 | |||
1213 | mutex_init(&codec->mutex); | ||
1214 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1215 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1216 | |||
1217 | codec->name = "WM8900"; | ||
1218 | codec->owner = THIS_MODULE; | ||
1219 | codec->dai = &wm8900_dai; | ||
1220 | codec->num_dai = 1; | ||
1221 | codec->control_data = i2c; | ||
1222 | codec->set_bias_level = wm8900_set_bias_level; | ||
1223 | codec->volatile_register = wm8900_volatile_register; | ||
1224 | codec->dev = &i2c->dev; | ||
1225 | |||
1226 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | ||
1227 | if (ret != 0) { | 1194 | if (ret != 0) { |
1228 | dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); | 1195 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1229 | goto err; | 1196 | return ret; |
1230 | } | 1197 | } |
1231 | 1198 | ||
1232 | reg = snd_soc_read(codec, WM8900_REG_ID); | 1199 | reg = snd_soc_read(codec, WM8900_REG_ID); |
1233 | if (reg != 0x8900) { | 1200 | if (reg != 0x8900) { |
1234 | dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg); | 1201 | dev_err(codec->dev, "Device is not a WM8900 - ID %x\n", reg); |
1235 | ret = -ENODEV; | 1202 | return -ENODEV; |
1236 | goto err; | ||
1237 | } | 1203 | } |
1238 | 1204 | ||
1239 | /* Read back from the chip */ | 1205 | /* Read back from the chip */ |
1240 | reg = snd_soc_read(codec, WM8900_REG_POWER1); | 1206 | reg = snd_soc_read(codec, WM8900_REG_POWER1); |
1241 | reg = (reg >> 12) & 0xf; | 1207 | reg = (reg >> 12) & 0xf; |
1242 | dev_info(&i2c->dev, "WM8900 revision %d\n", reg); | 1208 | dev_info(codec->dev, "WM8900 revision %d\n", reg); |
1243 | 1209 | ||
1244 | wm8900_reset(codec); | 1210 | wm8900_reset(codec); |
1245 | 1211 | ||
@@ -1271,43 +1237,97 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, | |||
1271 | /* Set the DAC and mixer output bias */ | 1237 | /* Set the DAC and mixer output bias */ |
1272 | snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81); | 1238 | snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81); |
1273 | 1239 | ||
1274 | wm8900_dai.dev = &i2c->dev; | 1240 | snd_soc_add_controls(codec, wm8900_snd_controls, |
1241 | ARRAY_SIZE(wm8900_snd_controls)); | ||
1242 | wm8900_add_widgets(codec); | ||
1275 | 1243 | ||
1276 | wm8900_codec = codec; | 1244 | return 0; |
1245 | } | ||
1277 | 1246 | ||
1278 | ret = snd_soc_register_codec(codec); | 1247 | /* power down chip */ |
1279 | if (ret != 0) { | 1248 | static int wm8900_remove(struct snd_soc_codec *codec) |
1280 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); | 1249 | { |
1281 | goto err; | 1250 | wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1282 | } | 1251 | return 0; |
1252 | } | ||
1283 | 1253 | ||
1284 | ret = snd_soc_register_dai(&wm8900_dai); | 1254 | static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { |
1285 | if (ret != 0) { | 1255 | .probe = wm8900_probe, |
1286 | dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); | 1256 | .remove = wm8900_remove, |
1287 | goto err_codec; | 1257 | .suspend = wm8900_suspend, |
1288 | } | 1258 | .resume = wm8900_resume, |
1259 | .set_bias_level = wm8900_set_bias_level, | ||
1260 | .volatile_register = wm8900_volatile_register, | ||
1261 | .reg_cache_size = sizeof(wm8900_reg_defaults), | ||
1262 | .reg_word_size = sizeof(u16), | ||
1263 | .reg_cache_default = wm8900_reg_defaults, | ||
1264 | }; | ||
1289 | 1265 | ||
1290 | return ret; | 1266 | #if defined(CONFIG_SPI_MASTER) |
1267 | static int __devinit wm8900_spi_probe(struct spi_device *spi) | ||
1268 | { | ||
1269 | struct wm8900_priv *wm8900; | ||
1270 | int ret; | ||
1271 | |||
1272 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1273 | if (wm8900 == NULL) | ||
1274 | return -ENOMEM; | ||
1291 | 1275 | ||
1292 | err_codec: | 1276 | wm8900->control_data = spi; |
1293 | snd_soc_unregister_codec(codec); | 1277 | wm8900->control_type = SND_SOC_SPI; |
1294 | err: | 1278 | spi_set_drvdata(spi, wm8900); |
1295 | kfree(wm8900); | 1279 | |
1296 | wm8900_codec = NULL; | 1280 | ret = snd_soc_register_codec(&spi->dev, |
1281 | &soc_codec_dev_wm8900, &wm8900_dai, 1); | ||
1282 | if (ret < 0) | ||
1283 | kfree(wm8900); | ||
1297 | return ret; | 1284 | return ret; |
1298 | } | 1285 | } |
1299 | 1286 | ||
1300 | static __devexit int wm8900_i2c_remove(struct i2c_client *client) | 1287 | static int __devexit wm8900_spi_remove(struct spi_device *spi) |
1301 | { | 1288 | { |
1302 | snd_soc_unregister_dai(&wm8900_dai); | 1289 | snd_soc_unregister_codec(&spi->dev); |
1303 | snd_soc_unregister_codec(wm8900_codec); | 1290 | kfree(spi_get_drvdata(spi)); |
1291 | return 0; | ||
1292 | } | ||
1304 | 1293 | ||
1305 | wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF); | 1294 | static struct spi_driver wm8900_spi_driver = { |
1295 | .driver = { | ||
1296 | .name = "wm8900-codec", | ||
1297 | .bus = &spi_bus_type, | ||
1298 | .owner = THIS_MODULE, | ||
1299 | }, | ||
1300 | .probe = wm8900_spi_probe, | ||
1301 | .remove = __devexit_p(wm8900_spi_remove), | ||
1302 | }; | ||
1303 | #endif /* CONFIG_SPI_MASTER */ | ||
1304 | |||
1305 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1306 | static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, | ||
1307 | const struct i2c_device_id *id) | ||
1308 | { | ||
1309 | struct wm8900_priv *wm8900; | ||
1310 | int ret; | ||
1311 | |||
1312 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1313 | if (wm8900 == NULL) | ||
1314 | return -ENOMEM; | ||
1315 | |||
1316 | i2c_set_clientdata(i2c, wm8900); | ||
1317 | wm8900->control_data = i2c; | ||
1318 | wm8900->control_type = SND_SOC_I2C; | ||
1306 | 1319 | ||
1307 | wm8900_dai.dev = NULL; | 1320 | ret = snd_soc_register_codec(&i2c->dev, |
1308 | kfree(snd_soc_codec_get_drvdata(wm8900_codec)); | 1321 | &soc_codec_dev_wm8900, &wm8900_dai, 1); |
1309 | wm8900_codec = NULL; | 1322 | if (ret < 0) |
1323 | kfree(wm8900); | ||
1324 | return ret; | ||
1325 | } | ||
1310 | 1326 | ||
1327 | static __devexit int wm8900_i2c_remove(struct i2c_client *client) | ||
1328 | { | ||
1329 | snd_soc_unregister_codec(&client->dev); | ||
1330 | kfree(i2c_get_clientdata(client)); | ||
1311 | return 0; | 1331 | return 0; |
1312 | } | 1332 | } |
1313 | 1333 | ||
@@ -1319,71 +1339,44 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id); | |||
1319 | 1339 | ||
1320 | static struct i2c_driver wm8900_i2c_driver = { | 1340 | static struct i2c_driver wm8900_i2c_driver = { |
1321 | .driver = { | 1341 | .driver = { |
1322 | .name = "WM8900", | 1342 | .name = "wm8900-codec", |
1323 | .owner = THIS_MODULE, | 1343 | .owner = THIS_MODULE, |
1324 | }, | 1344 | }, |
1325 | .probe = wm8900_i2c_probe, | 1345 | .probe = wm8900_i2c_probe, |
1326 | .remove = __devexit_p(wm8900_i2c_remove), | 1346 | .remove = __devexit_p(wm8900_i2c_remove), |
1327 | .id_table = wm8900_i2c_id, | 1347 | .id_table = wm8900_i2c_id, |
1328 | }; | 1348 | }; |
1349 | #endif | ||
1329 | 1350 | ||
1330 | static int wm8900_probe(struct platform_device *pdev) | 1351 | static int __init wm8900_modinit(void) |
1331 | { | 1352 | { |
1332 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1333 | struct snd_soc_codec *codec; | ||
1334 | int ret = 0; | 1353 | int ret = 0; |
1335 | 1354 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1336 | if (!wm8900_codec) { | 1355 | ret = i2c_add_driver(&wm8900_i2c_driver); |
1337 | dev_err(&pdev->dev, "I2C client not yet instantiated\n"); | 1356 | if (ret != 0) { |
1338 | return -ENODEV; | 1357 | printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n", |
1358 | ret); | ||
1339 | } | 1359 | } |
1340 | 1360 | #endif | |
1341 | codec = wm8900_codec; | 1361 | #if defined(CONFIG_SPI_MASTER) |
1342 | socdev->card->codec = codec; | 1362 | ret = spi_register_driver(&wm8900_spi_driver); |
1343 | 1363 | if (ret != 0) { | |
1344 | /* Register pcms */ | 1364 | printk(KERN_ERR "Failed to register wm8900 SPI driver: %d\n", |
1345 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1365 | ret); |
1346 | if (ret < 0) { | ||
1347 | dev_err(&pdev->dev, "Failed to register new PCMs\n"); | ||
1348 | goto pcm_err; | ||
1349 | } | 1366 | } |
1350 | 1367 | #endif | |
1351 | snd_soc_add_controls(codec, wm8900_snd_controls, | ||
1352 | ARRAY_SIZE(wm8900_snd_controls)); | ||
1353 | wm8900_add_widgets(codec); | ||
1354 | |||
1355 | pcm_err: | ||
1356 | return ret; | 1368 | return ret; |
1357 | } | 1369 | } |
1358 | |||
1359 | /* power down chip */ | ||
1360 | static int wm8900_remove(struct platform_device *pdev) | ||
1361 | { | ||
1362 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1363 | |||
1364 | snd_soc_free_pcms(socdev); | ||
1365 | snd_soc_dapm_free(socdev); | ||
1366 | |||
1367 | return 0; | ||
1368 | } | ||
1369 | |||
1370 | struct snd_soc_codec_device soc_codec_dev_wm8900 = { | ||
1371 | .probe = wm8900_probe, | ||
1372 | .remove = wm8900_remove, | ||
1373 | .suspend = wm8900_suspend, | ||
1374 | .resume = wm8900_resume, | ||
1375 | }; | ||
1376 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900); | ||
1377 | |||
1378 | static int __init wm8900_modinit(void) | ||
1379 | { | ||
1380 | return i2c_add_driver(&wm8900_i2c_driver); | ||
1381 | } | ||
1382 | module_init(wm8900_modinit); | 1370 | module_init(wm8900_modinit); |
1383 | 1371 | ||
1384 | static void __exit wm8900_exit(void) | 1372 | static void __exit wm8900_exit(void) |
1385 | { | 1373 | { |
1374 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1386 | i2c_del_driver(&wm8900_i2c_driver); | 1375 | i2c_del_driver(&wm8900_i2c_driver); |
1376 | #endif | ||
1377 | #if defined(CONFIG_SPI_MASTER) | ||
1378 | spi_unregister_driver(&wm8900_spi_driver); | ||
1379 | #endif | ||
1387 | } | 1380 | } |
1388 | module_exit(wm8900_exit); | 1381 | module_exit(wm8900_exit); |
1389 | 1382 | ||
diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h index fd15007d10c7..583f257e799b 100644 --- a/sound/soc/codecs/wm8900.h +++ b/sound/soc/codecs/wm8900.h | |||
@@ -52,7 +52,4 @@ | |||
52 | #define WM8900_DAC_CLKDIV_5_5 0x14 | 52 | #define WM8900_DAC_CLKDIV_5_5 0x14 |
53 | #define WM8900_DAC_CLKDIV_6 0x18 | 53 | #define WM8900_DAC_CLKDIV_6 0x18 |
54 | 54 | ||
55 | extern struct snd_soc_dai wm8900_dai; | ||
56 | extern struct snd_soc_codec_device soc_codec_dev_wm8900; | ||
57 | |||
58 | #endif | 55 | #endif |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index bf08282d5ee5..f5d73ed72cbd 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -213,10 +213,12 @@ static u16 wm8903_reg_defaults[] = { | |||
213 | }; | 213 | }; |
214 | 214 | ||
215 | struct wm8903_priv { | 215 | struct wm8903_priv { |
216 | struct snd_soc_codec codec; | 216 | |
217 | u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)]; | 217 | u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)]; |
218 | 218 | ||
219 | int sysclk; | 219 | int sysclk; |
220 | struct i2c_client *control_data; | ||
221 | int irq; | ||
220 | 222 | ||
221 | /* Reference counts */ | 223 | /* Reference counts */ |
222 | int class_w_users; | 224 | int class_w_users; |
@@ -252,7 +254,6 @@ static int wm8903_volatile_register(unsigned int reg) | |||
252 | static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) | 254 | static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) |
253 | { | 255 | { |
254 | u16 reg[5]; | 256 | u16 reg[5]; |
255 | struct i2c_client *i2c = codec->control_data; | ||
256 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 257 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
257 | 258 | ||
258 | BUG_ON(start > 48); | 259 | BUG_ON(start > 48); |
@@ -262,7 +263,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) | |||
262 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, | 263 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, |
263 | reg[0] | WM8903_WSEQ_ENA); | 264 | reg[0] | WM8903_WSEQ_ENA); |
264 | 265 | ||
265 | dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); | 266 | dev_dbg(codec->dev, "Starting sequence at %d\n", start); |
266 | 267 | ||
267 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3, | 268 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3, |
268 | start | WM8903_WSEQ_START); | 269 | start | WM8903_WSEQ_START); |
@@ -277,7 +278,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) | |||
277 | reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); | 278 | reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); |
278 | } while (reg[4] & WM8903_WSEQ_BUSY); | 279 | } while (reg[4] & WM8903_WSEQ_BUSY); |
279 | 280 | ||
280 | dev_dbg(&i2c->dev, "Sequence complete\n"); | 281 | dev_dbg(codec->dev, "Sequence complete\n"); |
281 | 282 | ||
282 | /* Disable the sequencer again if we enabled it */ | 283 | /* Disable the sequencer again if we enabled it */ |
283 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); | 284 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); |
@@ -422,7 +423,6 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, | |||
422 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 423 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); |
423 | struct snd_soc_codec *codec = widget->codec; | 424 | struct snd_soc_codec *codec = widget->codec; |
424 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 425 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
425 | struct i2c_client *i2c = codec->control_data; | ||
426 | u16 reg; | 426 | u16 reg; |
427 | int ret; | 427 | int ret; |
428 | 428 | ||
@@ -431,7 +431,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, | |||
431 | /* Turn it off if we're about to enable bypass */ | 431 | /* Turn it off if we're about to enable bypass */ |
432 | if (ucontrol->value.integer.value[0]) { | 432 | if (ucontrol->value.integer.value[0]) { |
433 | if (wm8903->class_w_users == 0) { | 433 | if (wm8903->class_w_users == 0) { |
434 | dev_dbg(&i2c->dev, "Disabling Class W\n"); | 434 | dev_dbg(codec->dev, "Disabling Class W\n"); |
435 | snd_soc_write(codec, WM8903_CLASS_W_0, reg & | 435 | snd_soc_write(codec, WM8903_CLASS_W_0, reg & |
436 | ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V)); | 436 | ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V)); |
437 | } | 437 | } |
@@ -444,14 +444,14 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, | |||
444 | /* If we've just disabled the last bypass path turn Class W on */ | 444 | /* If we've just disabled the last bypass path turn Class W on */ |
445 | if (!ucontrol->value.integer.value[0]) { | 445 | if (!ucontrol->value.integer.value[0]) { |
446 | if (wm8903->class_w_users == 1) { | 446 | if (wm8903->class_w_users == 1) { |
447 | dev_dbg(&i2c->dev, "Enabling Class W\n"); | 447 | dev_dbg(codec->dev, "Enabling Class W\n"); |
448 | snd_soc_write(codec, WM8903_CLASS_W_0, reg | | 448 | snd_soc_write(codec, WM8903_CLASS_W_0, reg | |
449 | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); | 449 | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); |
450 | } | 450 | } |
451 | wm8903->class_w_users--; | 451 | wm8903->class_w_users--; |
452 | } | 452 | } |
453 | 453 | ||
454 | dev_dbg(&i2c->dev, "Bypass use count now %d\n", | 454 | dev_dbg(codec->dev, "Bypass use count now %d\n", |
455 | wm8903->class_w_users); | 455 | wm8903->class_w_users); |
456 | 456 | ||
457 | return ret; | 457 | return ret; |
@@ -935,7 +935,6 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec) | |||
935 | static int wm8903_set_bias_level(struct snd_soc_codec *codec, | 935 | static int wm8903_set_bias_level(struct snd_soc_codec *codec, |
936 | enum snd_soc_bias_level level) | 936 | enum snd_soc_bias_level level) |
937 | { | 937 | { |
938 | struct i2c_client *i2c = codec->control_data; | ||
939 | u16 reg, reg2; | 938 | u16 reg, reg2; |
940 | 939 | ||
941 | switch (level) { | 940 | switch (level) { |
@@ -974,7 +973,7 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, | |||
974 | /* By default no bypass paths are enabled so | 973 | /* By default no bypass paths are enabled so |
975 | * enable Class W support. | 974 | * enable Class W support. |
976 | */ | 975 | */ |
977 | dev_dbg(&i2c->dev, "Enabling Class W\n"); | 976 | dev_dbg(codec->dev, "Enabling Class W\n"); |
978 | snd_soc_write(codec, WM8903_CLASS_W_0, reg | | 977 | snd_soc_write(codec, WM8903_CLASS_W_0, reg | |
979 | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); | 978 | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); |
980 | } | 979 | } |
@@ -1228,10 +1227,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream, | |||
1228 | struct snd_soc_dai *dai) | 1227 | struct snd_soc_dai *dai) |
1229 | { | 1228 | { |
1230 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1229 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1231 | struct snd_soc_device *socdev = rtd->socdev; | 1230 | struct snd_soc_codec *codec = rtd->codec; |
1232 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1233 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 1231 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1234 | struct i2c_client *i2c = codec->control_data; | ||
1235 | struct snd_pcm_runtime *master_runtime; | 1232 | struct snd_pcm_runtime *master_runtime; |
1236 | 1233 | ||
1237 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1234 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -1245,7 +1242,7 @@ static int wm8903_startup(struct snd_pcm_substream *substream, | |||
1245 | if (wm8903->master_substream) { | 1242 | if (wm8903->master_substream) { |
1246 | master_runtime = wm8903->master_substream->runtime; | 1243 | master_runtime = wm8903->master_substream->runtime; |
1247 | 1244 | ||
1248 | dev_dbg(&i2c->dev, "Constraining to %d bits\n", | 1245 | dev_dbg(codec->dev, "Constraining to %d bits\n", |
1249 | master_runtime->sample_bits); | 1246 | master_runtime->sample_bits); |
1250 | 1247 | ||
1251 | snd_pcm_hw_constraint_minmax(substream->runtime, | 1248 | snd_pcm_hw_constraint_minmax(substream->runtime, |
@@ -1264,8 +1261,7 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream, | |||
1264 | struct snd_soc_dai *dai) | 1261 | struct snd_soc_dai *dai) |
1265 | { | 1262 | { |
1266 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1263 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1267 | struct snd_soc_device *socdev = rtd->socdev; | 1264 | struct snd_soc_codec *codec = rtd->codec; |
1268 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1269 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 1265 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1270 | 1266 | ||
1271 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1267 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -1284,10 +1280,8 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1284 | struct snd_soc_dai *dai) | 1280 | struct snd_soc_dai *dai) |
1285 | { | 1281 | { |
1286 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1282 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1287 | struct snd_soc_device *socdev = rtd->socdev; | 1283 | struct snd_soc_codec *codec =rtd->codec; |
1288 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1289 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | 1284 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1290 | struct i2c_client *i2c = codec->control_data; | ||
1291 | int fs = params_rate(params); | 1285 | int fs = params_rate(params); |
1292 | int bclk; | 1286 | int bclk; |
1293 | int bclk_div; | 1287 | int bclk_div; |
@@ -1306,7 +1300,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1306 | u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); | 1300 | u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); |
1307 | 1301 | ||
1308 | if (substream == wm8903->slave_substream) { | 1302 | if (substream == wm8903->slave_substream) { |
1309 | dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); | 1303 | dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n"); |
1310 | return 0; | 1304 | return 0; |
1311 | } | 1305 | } |
1312 | 1306 | ||
@@ -1332,7 +1326,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1332 | switch (sample_rates[dsp_config].rate) { | 1326 | switch (sample_rates[dsp_config].rate) { |
1333 | case 88200: | 1327 | case 88200: |
1334 | case 96000: | 1328 | case 96000: |
1335 | dev_err(&i2c->dev, "%dHz unsupported by ADC\n", | 1329 | dev_err(codec->dev, "%dHz unsupported by ADC\n", |
1336 | fs); | 1330 | fs); |
1337 | return -EINVAL; | 1331 | return -EINVAL; |
1338 | 1332 | ||
@@ -1340,7 +1334,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1340 | break; | 1334 | break; |
1341 | } | 1335 | } |
1342 | 1336 | ||
1343 | dev_dbg(&i2c->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate); | 1337 | dev_dbg(codec->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate); |
1344 | clock1 &= ~WM8903_SAMPLE_RATE_MASK; | 1338 | clock1 &= ~WM8903_SAMPLE_RATE_MASK; |
1345 | clock1 |= sample_rates[dsp_config].value; | 1339 | clock1 |= sample_rates[dsp_config].value; |
1346 | 1340 | ||
@@ -1366,7 +1360,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1366 | return -EINVAL; | 1360 | return -EINVAL; |
1367 | } | 1361 | } |
1368 | 1362 | ||
1369 | dev_dbg(&i2c->dev, "MCLK = %dHz, target sample rate = %dHz\n", | 1363 | dev_dbg(codec->dev, "MCLK = %dHz, target sample rate = %dHz\n", |
1370 | wm8903->sysclk, fs); | 1364 | wm8903->sysclk, fs); |
1371 | 1365 | ||
1372 | /* We may not have an MCLK which allows us to generate exactly | 1366 | /* We may not have an MCLK which allows us to generate exactly |
@@ -1401,12 +1395,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1401 | clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT; | 1395 | clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT; |
1402 | clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT; | 1396 | clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT; |
1403 | 1397 | ||
1404 | dev_dbg(&i2c->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n", | 1398 | dev_dbg(codec->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n", |
1405 | clk_sys_ratios[clk_config].rate, | 1399 | clk_sys_ratios[clk_config].rate, |
1406 | clk_sys_ratios[clk_config].mode, | 1400 | clk_sys_ratios[clk_config].mode, |
1407 | clk_sys_ratios[clk_config].div); | 1401 | clk_sys_ratios[clk_config].div); |
1408 | 1402 | ||
1409 | dev_dbg(&i2c->dev, "Actual CLK_SYS = %dHz\n", clk_sys); | 1403 | dev_dbg(codec->dev, "Actual CLK_SYS = %dHz\n", clk_sys); |
1410 | 1404 | ||
1411 | /* We may not get quite the right frequency if using | 1405 | /* We may not get quite the right frequency if using |
1412 | * approximate clocks so look for the closest match that is | 1406 | * approximate clocks so look for the closest match that is |
@@ -1428,7 +1422,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1428 | aif2 &= ~WM8903_BCLK_DIV_MASK; | 1422 | aif2 &= ~WM8903_BCLK_DIV_MASK; |
1429 | aif3 &= ~WM8903_LRCLK_RATE_MASK; | 1423 | aif3 &= ~WM8903_LRCLK_RATE_MASK; |
1430 | 1424 | ||
1431 | dev_dbg(&i2c->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", | 1425 | dev_dbg(codec->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", |
1432 | bclk_divs[bclk_div].ratio / 10, bclk, | 1426 | bclk_divs[bclk_div].ratio / 10, bclk, |
1433 | (clk_sys * 10) / bclk_divs[bclk_div].ratio); | 1427 | (clk_sys * 10) / bclk_divs[bclk_div].ratio); |
1434 | 1428 | ||
@@ -1504,8 +1498,8 @@ EXPORT_SYMBOL_GPL(wm8903_mic_detect); | |||
1504 | 1498 | ||
1505 | static irqreturn_t wm8903_irq(int irq, void *data) | 1499 | static irqreturn_t wm8903_irq(int irq, void *data) |
1506 | { | 1500 | { |
1507 | struct wm8903_priv *wm8903 = data; | 1501 | struct snd_soc_codec *codec = data; |
1508 | struct snd_soc_codec *codec = &wm8903->codec; | 1502 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1509 | int mic_report; | 1503 | int mic_report; |
1510 | int int_pol; | 1504 | int int_pol; |
1511 | int int_val = 0; | 1505 | int int_val = 0; |
@@ -1586,8 +1580,8 @@ static struct snd_soc_dai_ops wm8903_dai_ops = { | |||
1586 | .set_sysclk = wm8903_set_dai_sysclk, | 1580 | .set_sysclk = wm8903_set_dai_sysclk, |
1587 | }; | 1581 | }; |
1588 | 1582 | ||
1589 | struct snd_soc_dai wm8903_dai = { | 1583 | static struct snd_soc_dai_driver wm8903_dai = { |
1590 | .name = "WM8903", | 1584 | .name = "wm8903-hifi", |
1591 | .playback = { | 1585 | .playback = { |
1592 | .stream_name = "Playback", | 1586 | .stream_name = "Playback", |
1593 | .channels_min = 2, | 1587 | .channels_min = 2, |
@@ -1605,23 +1599,16 @@ struct snd_soc_dai wm8903_dai = { | |||
1605 | .ops = &wm8903_dai_ops, | 1599 | .ops = &wm8903_dai_ops, |
1606 | .symmetric_rates = 1, | 1600 | .symmetric_rates = 1, |
1607 | }; | 1601 | }; |
1608 | EXPORT_SYMBOL_GPL(wm8903_dai); | ||
1609 | 1602 | ||
1610 | static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) | 1603 | static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1611 | { | 1604 | { |
1612 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1613 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1614 | |||
1615 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1605 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1616 | 1606 | ||
1617 | return 0; | 1607 | return 0; |
1618 | } | 1608 | } |
1619 | 1609 | ||
1620 | static int wm8903_resume(struct platform_device *pdev) | 1610 | static int wm8903_resume(struct snd_soc_codec *codec) |
1621 | { | 1611 | { |
1622 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1623 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1624 | struct i2c_client *i2c = codec->control_data; | ||
1625 | int i; | 1612 | int i; |
1626 | u16 *reg_cache = codec->reg_cache; | 1613 | u16 *reg_cache = codec->reg_cache; |
1627 | u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults), | 1614 | u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults), |
@@ -1637,65 +1624,38 @@ static int wm8903_resume(struct platform_device *pdev) | |||
1637 | snd_soc_write(codec, i, tmp_cache[i]); | 1624 | snd_soc_write(codec, i, tmp_cache[i]); |
1638 | kfree(tmp_cache); | 1625 | kfree(tmp_cache); |
1639 | } else { | 1626 | } else { |
1640 | dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); | 1627 | dev_err(codec->dev, "Failed to allocate temporary cache\n"); |
1641 | } | 1628 | } |
1642 | 1629 | ||
1643 | return 0; | 1630 | return 0; |
1644 | } | 1631 | } |
1645 | 1632 | ||
1646 | static struct snd_soc_codec *wm8903_codec; | 1633 | static int wm8903_probe(struct snd_soc_codec *codec) |
1647 | |||
1648 | static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | ||
1649 | const struct i2c_device_id *id) | ||
1650 | { | 1634 | { |
1651 | struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); | 1635 | struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); |
1652 | struct wm8903_priv *wm8903; | 1636 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1653 | struct snd_soc_codec *codec; | ||
1654 | int ret, i; | 1637 | int ret, i; |
1655 | int trigger, irq_pol; | 1638 | int trigger, irq_pol; |
1656 | u16 val; | 1639 | u16 val; |
1657 | 1640 | ||
1658 | wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); | ||
1659 | if (wm8903 == NULL) | ||
1660 | return -ENOMEM; | ||
1661 | |||
1662 | codec = &wm8903->codec; | ||
1663 | |||
1664 | mutex_init(&codec->mutex); | ||
1665 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1666 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1667 | |||
1668 | codec->dev = &i2c->dev; | ||
1669 | codec->name = "WM8903"; | ||
1670 | codec->owner = THIS_MODULE; | ||
1671 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1672 | codec->set_bias_level = wm8903_set_bias_level; | ||
1673 | codec->dai = &wm8903_dai; | ||
1674 | codec->num_dai = 1; | ||
1675 | codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache); | ||
1676 | codec->reg_cache = &wm8903->reg_cache[0]; | ||
1677 | snd_soc_codec_set_drvdata(codec, wm8903); | ||
1678 | codec->volatile_register = wm8903_volatile_register; | ||
1679 | init_completion(&wm8903->wseq); | 1641 | init_completion(&wm8903->wseq); |
1680 | 1642 | codec->control_data = wm8903->control_data; | |
1681 | i2c_set_clientdata(i2c, codec); | ||
1682 | codec->control_data = i2c; | ||
1683 | 1643 | ||
1684 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1644 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
1685 | if (ret != 0) { | 1645 | if (ret != 0) { |
1686 | dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); | 1646 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1687 | goto err; | 1647 | return ret; |
1688 | } | 1648 | } |
1689 | 1649 | ||
1690 | val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID); | 1650 | val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID); |
1691 | if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { | 1651 | if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { |
1692 | dev_err(&i2c->dev, | 1652 | dev_err(codec->dev, |
1693 | "Device with ID register %x is not a WM8903\n", val); | 1653 | "Device with ID register %x is not a WM8903\n", val); |
1694 | return -ENODEV; | 1654 | return -ENODEV; |
1695 | } | 1655 | } |
1696 | 1656 | ||
1697 | val = snd_soc_read(codec, WM8903_REVISION_NUMBER); | 1657 | val = snd_soc_read(codec, WM8903_REVISION_NUMBER); |
1698 | dev_info(&i2c->dev, "WM8903 revision %d\n", | 1658 | dev_info(codec->dev, "WM8903 revision %d\n", |
1699 | val & WM8903_CHIP_REV_MASK); | 1659 | val & WM8903_CHIP_REV_MASK); |
1700 | 1660 | ||
1701 | wm8903_reset(codec); | 1661 | wm8903_reset(codec); |
@@ -1721,7 +1681,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
1721 | wm8903->mic_delay = pdata->micdet_delay; | 1681 | wm8903->mic_delay = pdata->micdet_delay; |
1722 | } | 1682 | } |
1723 | 1683 | ||
1724 | if (i2c->irq) { | 1684 | if (wm8903->irq) { |
1725 | if (pdata && pdata->irq_active_low) { | 1685 | if (pdata && pdata->irq_active_low) { |
1726 | trigger = IRQF_TRIGGER_LOW; | 1686 | trigger = IRQF_TRIGGER_LOW; |
1727 | irq_pol = WM8903_IRQ_POL; | 1687 | irq_pol = WM8903_IRQ_POL; |
@@ -1733,13 +1693,13 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
1733 | snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL, | 1693 | snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL, |
1734 | WM8903_IRQ_POL, irq_pol); | 1694 | WM8903_IRQ_POL, irq_pol); |
1735 | 1695 | ||
1736 | ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq, | 1696 | ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq, |
1737 | trigger | IRQF_ONESHOT, | 1697 | trigger | IRQF_ONESHOT, |
1738 | "wm8903", wm8903); | 1698 | "wm8903", codec); |
1739 | if (ret != 0) { | 1699 | if (ret != 0) { |
1740 | dev_err(&i2c->dev, "Failed to request IRQ: %d\n", | 1700 | dev_err(codec->dev, "Failed to request IRQ: %d\n", |
1741 | ret); | 1701 | ret); |
1742 | goto err; | 1702 | return ret; |
1743 | } | 1703 | } |
1744 | 1704 | ||
1745 | /* Enable write sequencer interrupts */ | 1705 | /* Enable write sequencer interrupts */ |
@@ -1781,133 +1741,97 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
1781 | val |= WM8903_DAC_MUTEMODE; | 1741 | val |= WM8903_DAC_MUTEMODE; |
1782 | snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val); | 1742 | snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val); |
1783 | 1743 | ||
1784 | wm8903_dai.dev = &i2c->dev; | 1744 | snd_soc_add_controls(codec, wm8903_snd_controls, |
1785 | wm8903_codec = codec; | 1745 | ARRAY_SIZE(wm8903_snd_controls)); |
1786 | 1746 | wm8903_add_widgets(codec); | |
1787 | ret = snd_soc_register_codec(codec); | ||
1788 | if (ret != 0) { | ||
1789 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); | ||
1790 | goto err_irq; | ||
1791 | } | ||
1792 | |||
1793 | ret = snd_soc_register_dai(&wm8903_dai); | ||
1794 | if (ret != 0) { | ||
1795 | dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); | ||
1796 | goto err_codec; | ||
1797 | } | ||
1798 | |||
1799 | return ret; | ||
1800 | 1747 | ||
1801 | err_codec: | ||
1802 | snd_soc_unregister_codec(codec); | ||
1803 | err_irq: | ||
1804 | if (i2c->irq) | ||
1805 | free_irq(i2c->irq, wm8903); | ||
1806 | err: | ||
1807 | wm8903_codec = NULL; | ||
1808 | kfree(wm8903); | ||
1809 | return ret; | 1748 | return ret; |
1810 | } | 1749 | } |
1811 | 1750 | ||
1812 | static __devexit int wm8903_i2c_remove(struct i2c_client *client) | 1751 | /* power down chip */ |
1752 | static int wm8903_remove(struct snd_soc_codec *codec) | ||
1813 | { | 1753 | { |
1814 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 1754 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1815 | struct wm8903_priv *priv = snd_soc_codec_get_drvdata(codec); | 1755 | return 0; |
1756 | } | ||
1816 | 1757 | ||
1817 | snd_soc_unregister_dai(&wm8903_dai); | 1758 | static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { |
1818 | snd_soc_unregister_codec(codec); | 1759 | .probe = wm8903_probe, |
1760 | .remove = wm8903_remove, | ||
1761 | .suspend = wm8903_suspend, | ||
1762 | .resume = wm8903_resume, | ||
1763 | .set_bias_level = wm8903_set_bias_level, | ||
1764 | .reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults), | ||
1765 | .reg_word_size = sizeof(u16), | ||
1766 | .reg_cache_default = wm8903_reg_defaults, | ||
1767 | .volatile_register = wm8903_volatile_register, | ||
1768 | }; | ||
1819 | 1769 | ||
1820 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1770 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1771 | static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | ||
1772 | const struct i2c_device_id *id) | ||
1773 | { | ||
1774 | struct wm8903_priv *wm8903; | ||
1775 | int ret; | ||
1821 | 1776 | ||
1822 | if (client->irq) | 1777 | wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); |
1823 | free_irq(client->irq, priv); | 1778 | if (wm8903 == NULL) |
1779 | return -ENOMEM; | ||
1824 | 1780 | ||
1825 | kfree(priv); | 1781 | i2c_set_clientdata(i2c, wm8903); |
1782 | wm8903->control_data = i2c; | ||
1783 | wm8903->irq = i2c->irq; | ||
1826 | 1784 | ||
1827 | wm8903_codec = NULL; | 1785 | ret = snd_soc_register_codec(&i2c->dev, |
1828 | wm8903_dai.dev = NULL; | 1786 | &soc_codec_dev_wm8903, &wm8903_dai, 1); |
1787 | if (ret < 0) | ||
1788 | kfree(wm8903); | ||
1789 | return ret; | ||
1790 | } | ||
1829 | 1791 | ||
1792 | static __devexit int wm8903_i2c_remove(struct i2c_client *client) | ||
1793 | { | ||
1794 | snd_soc_unregister_codec(&client->dev); | ||
1795 | kfree(i2c_get_clientdata(client)); | ||
1830 | return 0; | 1796 | return 0; |
1831 | } | 1797 | } |
1832 | 1798 | ||
1833 | /* i2c codec control layer */ | ||
1834 | static const struct i2c_device_id wm8903_i2c_id[] = { | 1799 | static const struct i2c_device_id wm8903_i2c_id[] = { |
1835 | { "wm8903", 0 }, | 1800 | { "wm8903", 0 }, |
1836 | { } | 1801 | { } |
1837 | }; | 1802 | }; |
1838 | MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); | 1803 | MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); |
1839 | 1804 | ||
1840 | static struct i2c_driver wm8903_i2c_driver = { | 1805 | static struct i2c_driver wm8903_i2c_driver = { |
1841 | .driver = { | 1806 | .driver = { |
1842 | .name = "WM8903", | 1807 | .name = "wm8903-codec", |
1843 | .owner = THIS_MODULE, | 1808 | .owner = THIS_MODULE, |
1844 | }, | 1809 | }, |
1845 | .probe = wm8903_i2c_probe, | 1810 | .probe = wm8903_i2c_probe, |
1846 | .remove = __devexit_p(wm8903_i2c_remove), | 1811 | .remove = __devexit_p(wm8903_i2c_remove), |
1847 | .id_table = wm8903_i2c_id, | 1812 | .id_table = wm8903_i2c_id, |
1848 | }; | 1813 | }; |
1814 | #endif | ||
1849 | 1815 | ||
1850 | static int wm8903_probe(struct platform_device *pdev) | 1816 | static int __init wm8903_modinit(void) |
1851 | { | 1817 | { |
1852 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1853 | int ret = 0; | 1818 | int ret = 0; |
1854 | 1819 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1855 | if (!wm8903_codec) { | 1820 | ret = i2c_add_driver(&wm8903_i2c_driver); |
1856 | dev_err(&pdev->dev, "I2C device not yet probed\n"); | 1821 | if (ret != 0) { |
1857 | goto err; | 1822 | printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n", |
1858 | } | 1823 | ret); |
1859 | |||
1860 | socdev->card->codec = wm8903_codec; | ||
1861 | |||
1862 | /* register pcms */ | ||
1863 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1864 | if (ret < 0) { | ||
1865 | dev_err(&pdev->dev, "failed to create pcms\n"); | ||
1866 | goto err; | ||
1867 | } | 1824 | } |
1868 | 1825 | #endif | |
1869 | snd_soc_add_controls(socdev->card->codec, wm8903_snd_controls, | ||
1870 | ARRAY_SIZE(wm8903_snd_controls)); | ||
1871 | wm8903_add_widgets(socdev->card->codec); | ||
1872 | |||
1873 | return ret; | 1826 | return ret; |
1874 | |||
1875 | err: | ||
1876 | return ret; | ||
1877 | } | ||
1878 | |||
1879 | /* power down chip */ | ||
1880 | static int wm8903_remove(struct platform_device *pdev) | ||
1881 | { | ||
1882 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1883 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1884 | |||
1885 | if (codec->control_data) | ||
1886 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1887 | |||
1888 | snd_soc_free_pcms(socdev); | ||
1889 | snd_soc_dapm_free(socdev); | ||
1890 | |||
1891 | return 0; | ||
1892 | } | ||
1893 | |||
1894 | struct snd_soc_codec_device soc_codec_dev_wm8903 = { | ||
1895 | .probe = wm8903_probe, | ||
1896 | .remove = wm8903_remove, | ||
1897 | .suspend = wm8903_suspend, | ||
1898 | .resume = wm8903_resume, | ||
1899 | }; | ||
1900 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903); | ||
1901 | |||
1902 | static int __init wm8903_modinit(void) | ||
1903 | { | ||
1904 | return i2c_add_driver(&wm8903_i2c_driver); | ||
1905 | } | 1827 | } |
1906 | module_init(wm8903_modinit); | 1828 | module_init(wm8903_modinit); |
1907 | 1829 | ||
1908 | static void __exit wm8903_exit(void) | 1830 | static void __exit wm8903_exit(void) |
1909 | { | 1831 | { |
1832 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1910 | i2c_del_driver(&wm8903_i2c_driver); | 1833 | i2c_del_driver(&wm8903_i2c_driver); |
1834 | #endif | ||
1911 | } | 1835 | } |
1912 | module_exit(wm8903_exit); | 1836 | module_exit(wm8903_exit); |
1913 | 1837 | ||
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h index ce384a2ad820..996435e681e5 100644 --- a/sound/soc/codecs/wm8903.h +++ b/sound/soc/codecs/wm8903.h | |||
@@ -15,9 +15,6 @@ | |||
15 | 15 | ||
16 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
17 | 17 | ||
18 | extern struct snd_soc_dai wm8903_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8903; | ||
20 | |||
21 | extern int wm8903_mic_detect(struct snd_soc_codec *codec, | 18 | extern int wm8903_mic_detect(struct snd_soc_codec *codec, |
22 | struct snd_soc_jack *jack, | 19 | struct snd_soc_jack *jack, |
23 | int det, int shrt); | 20 | int det, int shrt); |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index f7dcabf6283c..33be84e506ea 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -31,9 +31,6 @@ | |||
31 | 31 | ||
32 | #include "wm8904.h" | 32 | #include "wm8904.h" |
33 | 33 | ||
34 | static struct snd_soc_codec *wm8904_codec; | ||
35 | struct snd_soc_codec_device soc_codec_dev_wm8904; | ||
36 | |||
37 | enum wm8904_type { | 34 | enum wm8904_type { |
38 | WM8904, | 35 | WM8904, |
39 | WM8912, | 36 | WM8912, |
@@ -52,10 +49,11 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = { | |||
52 | 49 | ||
53 | /* codec private data */ | 50 | /* codec private data */ |
54 | struct wm8904_priv { | 51 | struct wm8904_priv { |
55 | struct snd_soc_codec codec; | 52 | |
56 | u16 reg_cache[WM8904_MAX_REGISTER + 1]; | 53 | u16 reg_cache[WM8904_MAX_REGISTER + 1]; |
57 | 54 | ||
58 | enum wm8904_type devtype; | 55 | enum wm8904_type devtype; |
56 | void *control_data; | ||
59 | 57 | ||
60 | struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; | 58 | struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; |
61 | 59 | ||
@@ -689,7 +687,7 @@ static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol, | |||
689 | struct snd_ctl_elem_value *ucontrol) | 687 | struct snd_ctl_elem_value *ucontrol) |
690 | { | 688 | { |
691 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 689 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
692 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | 690 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
693 | struct wm8904_pdata *pdata = wm8904->pdata; | 691 | struct wm8904_pdata *pdata = wm8904->pdata; |
694 | int value = ucontrol->value.integer.value[0]; | 692 | int value = ucontrol->value.integer.value[0]; |
695 | 693 | ||
@@ -760,7 +758,7 @@ static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, | |||
760 | struct snd_ctl_elem_value *ucontrol) | 758 | struct snd_ctl_elem_value *ucontrol) |
761 | { | 759 | { |
762 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 760 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
763 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | 761 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
764 | struct wm8904_pdata *pdata = wm8904->pdata; | 762 | struct wm8904_pdata *pdata = wm8904->pdata; |
765 | int value = ucontrol->value.integer.value[0]; | 763 | int value = ucontrol->value.integer.value[0]; |
766 | 764 | ||
@@ -2218,8 +2216,8 @@ static struct snd_soc_dai_ops wm8904_dai_ops = { | |||
2218 | .digital_mute = wm8904_digital_mute, | 2216 | .digital_mute = wm8904_digital_mute, |
2219 | }; | 2217 | }; |
2220 | 2218 | ||
2221 | struct snd_soc_dai wm8904_dai = { | 2219 | static struct snd_soc_dai_driver wm8904_dai = { |
2222 | .name = "WM8904", | 2220 | .name = "wm8904-hifi", |
2223 | .playback = { | 2221 | .playback = { |
2224 | .stream_name = "Playback", | 2222 | .stream_name = "Playback", |
2225 | .channels_min = 2, | 2223 | .channels_min = 2, |
@@ -2237,24 +2235,17 @@ struct snd_soc_dai wm8904_dai = { | |||
2237 | .ops = &wm8904_dai_ops, | 2235 | .ops = &wm8904_dai_ops, |
2238 | .symmetric_rates = 1, | 2236 | .symmetric_rates = 1, |
2239 | }; | 2237 | }; |
2240 | EXPORT_SYMBOL_GPL(wm8904_dai); | ||
2241 | 2238 | ||
2242 | #ifdef CONFIG_PM | 2239 | #ifdef CONFIG_PM |
2243 | static int wm8904_suspend(struct platform_device *pdev, pm_message_t state) | 2240 | static int wm8904_suspend(struct snd_soc_codec *codec, pm_message_t state) |
2244 | { | 2241 | { |
2245 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2246 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2247 | |||
2248 | wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2242 | wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2249 | 2243 | ||
2250 | return 0; | 2244 | return 0; |
2251 | } | 2245 | } |
2252 | 2246 | ||
2253 | static int wm8904_resume(struct platform_device *pdev) | 2247 | static int wm8904_resume(struct snd_soc_codec *codec) |
2254 | { | 2248 | { |
2255 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2256 | struct snd_soc_codec *codec = socdev->card->codec; | ||
2257 | |||
2258 | wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 2249 | wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
2259 | 2250 | ||
2260 | return 0; | 2251 | return 0; |
@@ -2264,9 +2255,9 @@ static int wm8904_resume(struct platform_device *pdev) | |||
2264 | #define wm8904_resume NULL | 2255 | #define wm8904_resume NULL |
2265 | #endif | 2256 | #endif |
2266 | 2257 | ||
2267 | static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904) | 2258 | static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec) |
2268 | { | 2259 | { |
2269 | struct snd_soc_codec *codec = &wm8904->codec; | 2260 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
2270 | struct wm8904_pdata *pdata = wm8904->pdata; | 2261 | struct wm8904_pdata *pdata = wm8904->pdata; |
2271 | struct snd_kcontrol_new control = | 2262 | struct snd_kcontrol_new control = |
2272 | SOC_ENUM_EXT("EQ Mode", | 2263 | SOC_ENUM_EXT("EQ Mode", |
@@ -2315,20 +2306,20 @@ static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904) | |||
2315 | wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; | 2306 | wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; |
2316 | wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; | 2307 | wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; |
2317 | 2308 | ||
2318 | ret = snd_soc_add_controls(&wm8904->codec, &control, 1); | 2309 | ret = snd_soc_add_controls(codec, &control, 1); |
2319 | if (ret != 0) | 2310 | if (ret != 0) |
2320 | dev_err(wm8904->codec.dev, | 2311 | dev_err(codec->dev, |
2321 | "Failed to add ReTune Mobile control: %d\n", ret); | 2312 | "Failed to add ReTune Mobile control: %d\n", ret); |
2322 | } | 2313 | } |
2323 | 2314 | ||
2324 | static void wm8904_handle_pdata(struct wm8904_priv *wm8904) | 2315 | static void wm8904_handle_pdata(struct snd_soc_codec *codec) |
2325 | { | 2316 | { |
2326 | struct snd_soc_codec *codec = &wm8904->codec; | 2317 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
2327 | struct wm8904_pdata *pdata = wm8904->pdata; | 2318 | struct wm8904_pdata *pdata = wm8904->pdata; |
2328 | int ret, i; | 2319 | int ret, i; |
2329 | 2320 | ||
2330 | if (!pdata) { | 2321 | if (!pdata) { |
2331 | snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, | 2322 | snd_soc_add_controls(codec, wm8904_eq_controls, |
2332 | ARRAY_SIZE(wm8904_eq_controls)); | 2323 | ARRAY_SIZE(wm8904_eq_controls)); |
2333 | return; | 2324 | return; |
2334 | } | 2325 | } |
@@ -2344,7 +2335,7 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904) | |||
2344 | wm8904->drc_texts = kmalloc(sizeof(char *) | 2335 | wm8904->drc_texts = kmalloc(sizeof(char *) |
2345 | * pdata->num_drc_cfgs, GFP_KERNEL); | 2336 | * pdata->num_drc_cfgs, GFP_KERNEL); |
2346 | if (!wm8904->drc_texts) { | 2337 | if (!wm8904->drc_texts) { |
2347 | dev_err(wm8904->codec.dev, | 2338 | dev_err(codec->dev, |
2348 | "Failed to allocate %d DRC config texts\n", | 2339 | "Failed to allocate %d DRC config texts\n", |
2349 | pdata->num_drc_cfgs); | 2340 | pdata->num_drc_cfgs); |
2350 | return; | 2341 | return; |
@@ -2356,9 +2347,9 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904) | |||
2356 | wm8904->drc_enum.max = pdata->num_drc_cfgs; | 2347 | wm8904->drc_enum.max = pdata->num_drc_cfgs; |
2357 | wm8904->drc_enum.texts = wm8904->drc_texts; | 2348 | wm8904->drc_enum.texts = wm8904->drc_texts; |
2358 | 2349 | ||
2359 | ret = snd_soc_add_controls(&wm8904->codec, &control, 1); | 2350 | ret = snd_soc_add_controls(codec, &control, 1); |
2360 | if (ret != 0) | 2351 | if (ret != 0) |
2361 | dev_err(wm8904->codec.dev, | 2352 | dev_err(codec->dev, |
2362 | "Failed to add DRC mode control: %d\n", ret); | 2353 | "Failed to add DRC mode control: %d\n", ret); |
2363 | 2354 | ||
2364 | wm8904_set_drc(codec); | 2355 | wm8904_set_drc(codec); |
@@ -2368,89 +2359,19 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904) | |||
2368 | pdata->num_retune_mobile_cfgs); | 2359 | pdata->num_retune_mobile_cfgs); |
2369 | 2360 | ||
2370 | if (pdata->num_retune_mobile_cfgs) | 2361 | if (pdata->num_retune_mobile_cfgs) |
2371 | wm8904_handle_retune_mobile_pdata(wm8904); | 2362 | wm8904_handle_retune_mobile_pdata(codec); |
2372 | else | 2363 | else |
2373 | snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, | 2364 | snd_soc_add_controls(codec, wm8904_eq_controls, |
2374 | ARRAY_SIZE(wm8904_eq_controls)); | 2365 | ARRAY_SIZE(wm8904_eq_controls)); |
2375 | } | 2366 | } |
2376 | 2367 | ||
2377 | static int wm8904_probe(struct platform_device *pdev) | ||
2378 | { | ||
2379 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2380 | struct snd_soc_codec *codec; | ||
2381 | int ret = 0; | ||
2382 | |||
2383 | if (wm8904_codec == NULL) { | ||
2384 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
2385 | return -ENODEV; | ||
2386 | } | ||
2387 | 2368 | ||
2388 | socdev->card->codec = wm8904_codec; | 2369 | static int wm8904_probe(struct snd_soc_codec *codec) |
2389 | codec = wm8904_codec; | ||
2390 | |||
2391 | /* register pcms */ | ||
2392 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
2393 | if (ret < 0) { | ||
2394 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
2395 | goto pcm_err; | ||
2396 | } | ||
2397 | |||
2398 | wm8904_handle_pdata(snd_soc_codec_get_drvdata(codec)); | ||
2399 | |||
2400 | wm8904_add_widgets(codec); | ||
2401 | |||
2402 | return ret; | ||
2403 | |||
2404 | pcm_err: | ||
2405 | return ret; | ||
2406 | } | ||
2407 | |||
2408 | static int wm8904_remove(struct platform_device *pdev) | ||
2409 | { | ||
2410 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
2411 | |||
2412 | snd_soc_free_pcms(socdev); | ||
2413 | snd_soc_dapm_free(socdev); | ||
2414 | |||
2415 | return 0; | ||
2416 | } | ||
2417 | |||
2418 | struct snd_soc_codec_device soc_codec_dev_wm8904 = { | ||
2419 | .probe = wm8904_probe, | ||
2420 | .remove = wm8904_remove, | ||
2421 | .suspend = wm8904_suspend, | ||
2422 | .resume = wm8904_resume, | ||
2423 | }; | ||
2424 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8904); | ||
2425 | |||
2426 | static int wm8904_register(struct wm8904_priv *wm8904, | ||
2427 | enum snd_soc_control_type control) | ||
2428 | { | 2370 | { |
2371 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); | ||
2429 | struct wm8904_pdata *pdata = wm8904->pdata; | 2372 | struct wm8904_pdata *pdata = wm8904->pdata; |
2430 | int ret; | 2373 | int ret, i; |
2431 | struct snd_soc_codec *codec = &wm8904->codec; | ||
2432 | int i; | ||
2433 | |||
2434 | if (wm8904_codec) { | ||
2435 | dev_err(codec->dev, "Another WM8904 is registered\n"); | ||
2436 | ret = -EINVAL; | ||
2437 | goto err; | ||
2438 | } | ||
2439 | 2374 | ||
2440 | mutex_init(&codec->mutex); | ||
2441 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
2442 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
2443 | |||
2444 | snd_soc_codec_set_drvdata(codec, wm8904); | ||
2445 | codec->name = "WM8904"; | ||
2446 | codec->owner = THIS_MODULE; | ||
2447 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
2448 | codec->set_bias_level = wm8904_set_bias_level; | ||
2449 | codec->dai = &wm8904_dai; | ||
2450 | codec->num_dai = 1; | ||
2451 | codec->reg_cache_size = WM8904_MAX_REGISTER; | ||
2452 | codec->reg_cache = &wm8904->reg_cache; | ||
2453 | codec->volatile_register = wm8904_volatile_register; | ||
2454 | codec->cache_sync = 1; | 2375 | codec->cache_sync = 1; |
2455 | codec->idle_bias_off = 1; | 2376 | codec->idle_bias_off = 1; |
2456 | 2377 | ||
@@ -2463,16 +2384,13 @@ static int wm8904_register(struct wm8904_priv *wm8904, | |||
2463 | default: | 2384 | default: |
2464 | dev_err(codec->dev, "Unknown device type %d\n", | 2385 | dev_err(codec->dev, "Unknown device type %d\n", |
2465 | wm8904->devtype); | 2386 | wm8904->devtype); |
2466 | ret = -EINVAL; | 2387 | return -EINVAL; |
2467 | goto err; | ||
2468 | } | 2388 | } |
2469 | 2389 | ||
2470 | memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg)); | 2390 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
2471 | |||
2472 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); | ||
2473 | if (ret != 0) { | 2391 | if (ret != 0) { |
2474 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 2392 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
2475 | goto err; | 2393 | return ret; |
2476 | } | 2394 | } |
2477 | 2395 | ||
2478 | for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) | 2396 | for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) |
@@ -2482,7 +2400,7 @@ static int wm8904_register(struct wm8904_priv *wm8904, | |||
2482 | wm8904->supplies); | 2400 | wm8904->supplies); |
2483 | if (ret != 0) { | 2401 | if (ret != 0) { |
2484 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 2402 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); |
2485 | goto err; | 2403 | return ret; |
2486 | } | 2404 | } |
2487 | 2405 | ||
2488 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), | 2406 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), |
@@ -2517,8 +2435,6 @@ static int wm8904_register(struct wm8904_priv *wm8904, | |||
2517 | goto err_enable; | 2435 | goto err_enable; |
2518 | } | 2436 | } |
2519 | 2437 | ||
2520 | wm8904_dai.dev = codec->dev; | ||
2521 | |||
2522 | /* Change some default settings - latch VU and enable ZC */ | 2438 | /* Change some default settings - latch VU and enable ZC */ |
2523 | wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; | 2439 | wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; |
2524 | wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; | 2440 | wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; |
@@ -2563,72 +2479,68 @@ static int wm8904_register(struct wm8904_priv *wm8904, | |||
2563 | /* Bias level configuration will have done an extra enable */ | 2479 | /* Bias level configuration will have done an extra enable */ |
2564 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | 2480 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); |
2565 | 2481 | ||
2566 | wm8904_codec = codec; | 2482 | wm8904_handle_pdata(codec); |
2567 | 2483 | ||
2568 | ret = snd_soc_register_codec(codec); | 2484 | wm8904_add_widgets(codec); |
2569 | if (ret != 0) { | ||
2570 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
2571 | goto err_enable; | ||
2572 | } | ||
2573 | |||
2574 | ret = snd_soc_register_dai(&wm8904_dai); | ||
2575 | if (ret != 0) { | ||
2576 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
2577 | goto err_codec; | ||
2578 | } | ||
2579 | 2485 | ||
2580 | return 0; | 2486 | return 0; |
2581 | 2487 | ||
2582 | err_codec: | ||
2583 | snd_soc_unregister_codec(codec); | ||
2584 | err_enable: | 2488 | err_enable: |
2585 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | 2489 | regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); |
2586 | err_get: | 2490 | err_get: |
2587 | regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | 2491 | regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); |
2588 | err: | ||
2589 | kfree(wm8904); | ||
2590 | return ret; | 2492 | return ret; |
2591 | } | 2493 | } |
2592 | 2494 | ||
2593 | static void wm8904_unregister(struct wm8904_priv *wm8904) | 2495 | static int wm8904_remove(struct snd_soc_codec *codec) |
2594 | { | 2496 | { |
2595 | wm8904_set_bias_level(&wm8904->codec, SND_SOC_BIAS_OFF); | 2497 | struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); |
2498 | |||
2499 | wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
2596 | regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); | 2500 | regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); |
2597 | snd_soc_unregister_dai(&wm8904_dai); | 2501 | |
2598 | snd_soc_unregister_codec(&wm8904->codec); | 2502 | return 0; |
2599 | kfree(wm8904); | ||
2600 | wm8904_codec = NULL; | ||
2601 | } | 2503 | } |
2602 | 2504 | ||
2505 | static struct snd_soc_codec_driver soc_codec_dev_wm8904 = { | ||
2506 | .probe = wm8904_probe, | ||
2507 | .remove = wm8904_remove, | ||
2508 | .suspend = wm8904_suspend, | ||
2509 | .resume = wm8904_resume, | ||
2510 | .set_bias_level = wm8904_set_bias_level, | ||
2511 | .reg_cache_size = ARRAY_SIZE(wm8904_reg), | ||
2512 | .reg_word_size = sizeof(u16), | ||
2513 | .reg_cache_default = wm8904_reg, | ||
2514 | .volatile_register = wm8904_volatile_register, | ||
2515 | }; | ||
2516 | |||
2603 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 2517 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
2604 | static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, | 2518 | static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, |
2605 | const struct i2c_device_id *id) | 2519 | const struct i2c_device_id *id) |
2606 | { | 2520 | { |
2607 | struct wm8904_priv *wm8904; | 2521 | struct wm8904_priv *wm8904; |
2608 | struct snd_soc_codec *codec; | 2522 | int ret; |
2609 | 2523 | ||
2610 | wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL); | 2524 | wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL); |
2611 | if (wm8904 == NULL) | 2525 | if (wm8904 == NULL) |
2612 | return -ENOMEM; | 2526 | return -ENOMEM; |
2613 | 2527 | ||
2614 | codec = &wm8904->codec; | ||
2615 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
2616 | |||
2617 | wm8904->devtype = id->driver_data; | 2528 | wm8904->devtype = id->driver_data; |
2618 | |||
2619 | i2c_set_clientdata(i2c, wm8904); | 2529 | i2c_set_clientdata(i2c, wm8904); |
2620 | codec->control_data = i2c; | 2530 | wm8904->control_data = i2c; |
2621 | wm8904->pdata = i2c->dev.platform_data; | 2531 | wm8904->pdata = i2c->dev.platform_data; |
2622 | 2532 | ||
2623 | codec->dev = &i2c->dev; | 2533 | ret = snd_soc_register_codec(&i2c->dev, |
2624 | 2534 | &soc_codec_dev_wm8904, &wm8904_dai, 1); | |
2625 | return wm8904_register(wm8904, SND_SOC_I2C); | 2535 | if (ret < 0) |
2536 | kfree(wm8904); | ||
2537 | return ret; | ||
2626 | } | 2538 | } |
2627 | 2539 | ||
2628 | static __devexit int wm8904_i2c_remove(struct i2c_client *client) | 2540 | static __devexit int wm8904_i2c_remove(struct i2c_client *client) |
2629 | { | 2541 | { |
2630 | struct wm8904_priv *wm8904 = i2c_get_clientdata(client); | 2542 | snd_soc_unregister_codec(&client->dev); |
2631 | wm8904_unregister(wm8904); | 2543 | kfree(i2c_get_clientdata(client)); |
2632 | return 0; | 2544 | return 0; |
2633 | } | 2545 | } |
2634 | 2546 | ||
@@ -2641,7 +2553,7 @@ MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); | |||
2641 | 2553 | ||
2642 | static struct i2c_driver wm8904_i2c_driver = { | 2554 | static struct i2c_driver wm8904_i2c_driver = { |
2643 | .driver = { | 2555 | .driver = { |
2644 | .name = "WM8904", | 2556 | .name = "wm8904-codec", |
2645 | .owner = THIS_MODULE, | 2557 | .owner = THIS_MODULE, |
2646 | }, | 2558 | }, |
2647 | .probe = wm8904_i2c_probe, | 2559 | .probe = wm8904_i2c_probe, |
@@ -2652,15 +2564,15 @@ static struct i2c_driver wm8904_i2c_driver = { | |||
2652 | 2564 | ||
2653 | static int __init wm8904_modinit(void) | 2565 | static int __init wm8904_modinit(void) |
2654 | { | 2566 | { |
2655 | int ret; | 2567 | int ret = 0; |
2656 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 2568 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
2657 | ret = i2c_add_driver(&wm8904_i2c_driver); | 2569 | ret = i2c_add_driver(&wm8904_i2c_driver); |
2658 | if (ret != 0) { | 2570 | if (ret != 0) { |
2659 | printk(KERN_ERR "Failed to register WM8904 I2C driver: %d\n", | 2571 | printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n", |
2660 | ret); | 2572 | ret); |
2661 | } | 2573 | } |
2662 | #endif | 2574 | #endif |
2663 | return 0; | 2575 | return ret; |
2664 | } | 2576 | } |
2665 | module_init(wm8904_modinit); | 2577 | module_init(wm8904_modinit); |
2666 | 2578 | ||
diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h index abe5059b3004..9e8c84188ba7 100644 --- a/sound/soc/codecs/wm8904.h +++ b/sound/soc/codecs/wm8904.h | |||
@@ -21,9 +21,6 @@ | |||
21 | #define WM8904_FLL_LRCLK 3 | 21 | #define WM8904_FLL_LRCLK 3 |
22 | #define WM8904_FLL_FREE_RUNNING 4 | 22 | #define WM8904_FLL_FREE_RUNNING 4 |
23 | 23 | ||
24 | extern struct snd_soc_dai wm8904_dai; | ||
25 | extern struct snd_soc_codec_device soc_codec_dev_wm8904; | ||
26 | |||
27 | /* | 24 | /* |
28 | * Register values. | 25 | * Register values. |
29 | */ | 26 | */ |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index f0c11138e610..d28bf0dfdb1d 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -44,7 +44,8 @@ | |||
44 | struct wm8940_priv { | 44 | struct wm8940_priv { |
45 | unsigned int sysclk; | 45 | unsigned int sysclk; |
46 | u16 reg_cache[WM8940_CACHEREGNUM]; | 46 | u16 reg_cache[WM8940_CACHEREGNUM]; |
47 | struct snd_soc_codec codec; | 47 | enum snd_soc_control_type control_type; |
48 | void *control_data; | ||
48 | }; | 49 | }; |
49 | 50 | ||
50 | static u16 wm8940_reg_defaults[] = { | 51 | static u16 wm8940_reg_defaults[] = { |
@@ -365,8 +366,7 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, | |||
365 | struct snd_soc_dai *dai) | 366 | struct snd_soc_dai *dai) |
366 | { | 367 | { |
367 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 368 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
368 | struct snd_soc_device *socdev = rtd->socdev; | 369 | struct snd_soc_codec *codec = rtd->codec; |
369 | struct snd_soc_codec *codec = socdev->card->codec; | ||
370 | u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F; | 370 | u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F; |
371 | u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1; | 371 | u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1; |
372 | u16 companding = snd_soc_read(codec, | 372 | u16 companding = snd_soc_read(codec, |
@@ -636,8 +636,8 @@ static struct snd_soc_dai_ops wm8940_dai_ops = { | |||
636 | .set_pll = wm8940_set_dai_pll, | 636 | .set_pll = wm8940_set_dai_pll, |
637 | }; | 637 | }; |
638 | 638 | ||
639 | struct snd_soc_dai wm8940_dai = { | 639 | static struct snd_soc_dai_driver wm8940_dai = { |
640 | .name = "WM8940", | 640 | .name = "wm8940-hifi", |
641 | .playback = { | 641 | .playback = { |
642 | .stream_name = "Playback", | 642 | .stream_name = "Playback", |
643 | .channels_min = 1, | 643 | .channels_min = 1, |
@@ -655,20 +655,14 @@ struct snd_soc_dai wm8940_dai = { | |||
655 | .ops = &wm8940_dai_ops, | 655 | .ops = &wm8940_dai_ops, |
656 | .symmetric_rates = 1, | 656 | .symmetric_rates = 1, |
657 | }; | 657 | }; |
658 | EXPORT_SYMBOL_GPL(wm8940_dai); | ||
659 | 658 | ||
660 | static int wm8940_suspend(struct platform_device *pdev, pm_message_t state) | 659 | static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state) |
661 | { | 660 | { |
662 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
663 | struct snd_soc_codec *codec = socdev->card->codec; | ||
664 | |||
665 | return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); | 661 | return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); |
666 | } | 662 | } |
667 | 663 | ||
668 | static int wm8940_resume(struct platform_device *pdev) | 664 | static int wm8940_resume(struct snd_soc_codec *codec) |
669 | { | 665 | { |
670 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
671 | struct snd_soc_codec *codec = socdev->card->codec; | ||
672 | int i; | 666 | int i; |
673 | int ret; | 667 | int ret; |
674 | u8 data[3]; | 668 | u8 data[3]; |
@@ -697,108 +691,26 @@ error_ret: | |||
697 | return ret; | 691 | return ret; |
698 | } | 692 | } |
699 | 693 | ||
700 | static struct snd_soc_codec *wm8940_codec; | 694 | static int wm8940_probe(struct snd_soc_codec *codec) |
701 | |||
702 | static int wm8940_probe(struct platform_device *pdev) | ||
703 | { | ||
704 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
705 | struct snd_soc_codec *codec; | ||
706 | |||
707 | int ret = 0; | ||
708 | |||
709 | if (wm8940_codec == NULL) { | ||
710 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
711 | return -ENODEV; | ||
712 | } | ||
713 | |||
714 | socdev->card->codec = wm8940_codec; | ||
715 | codec = wm8940_codec; | ||
716 | |||
717 | mutex_init(&codec->mutex); | ||
718 | /* register pcms */ | ||
719 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
720 | if (ret < 0) { | ||
721 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
722 | goto pcm_err; | ||
723 | } | ||
724 | |||
725 | ret = snd_soc_add_controls(codec, wm8940_snd_controls, | ||
726 | ARRAY_SIZE(wm8940_snd_controls)); | ||
727 | if (ret) | ||
728 | goto error_free_pcms; | ||
729 | ret = wm8940_add_widgets(codec); | ||
730 | if (ret) | ||
731 | goto error_free_pcms; | ||
732 | |||
733 | return ret; | ||
734 | |||
735 | error_free_pcms: | ||
736 | snd_soc_free_pcms(socdev); | ||
737 | snd_soc_dapm_free(socdev); | ||
738 | pcm_err: | ||
739 | return ret; | ||
740 | } | ||
741 | |||
742 | static int wm8940_remove(struct platform_device *pdev) | ||
743 | { | ||
744 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
745 | |||
746 | snd_soc_free_pcms(socdev); | ||
747 | snd_soc_dapm_free(socdev); | ||
748 | |||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | struct snd_soc_codec_device soc_codec_dev_wm8940 = { | ||
753 | .probe = wm8940_probe, | ||
754 | .remove = wm8940_remove, | ||
755 | .suspend = wm8940_suspend, | ||
756 | .resume = wm8940_resume, | ||
757 | }; | ||
758 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940); | ||
759 | |||
760 | static int wm8940_register(struct wm8940_priv *wm8940, | ||
761 | enum snd_soc_control_type control) | ||
762 | { | 695 | { |
763 | struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data; | 696 | struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec); |
764 | struct snd_soc_codec *codec = &wm8940->codec; | 697 | struct wm8940_setup_data *pdata = codec->dev->platform_data; |
765 | int ret; | 698 | int ret; |
766 | u16 reg; | 699 | u16 reg; |
767 | if (wm8940_codec) { | ||
768 | dev_err(codec->dev, "Another WM8940 is registered\n"); | ||
769 | return -EINVAL; | ||
770 | } | ||
771 | |||
772 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
773 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
774 | |||
775 | snd_soc_codec_set_drvdata(codec, wm8940); | ||
776 | codec->name = "WM8940"; | ||
777 | codec->owner = THIS_MODULE; | ||
778 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
779 | codec->set_bias_level = wm8940_set_bias_level; | ||
780 | codec->dai = &wm8940_dai; | ||
781 | codec->num_dai = 1; | ||
782 | codec->reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults); | ||
783 | codec->reg_cache = &wm8940->reg_cache; | ||
784 | 700 | ||
785 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); | 701 | codec->control_data = wm8940->control_data; |
702 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type); | ||
786 | if (ret < 0) { | 703 | if (ret < 0) { |
787 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 704 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
788 | return ret; | 705 | return ret; |
789 | } | 706 | } |
790 | 707 | ||
791 | memcpy(codec->reg_cache, wm8940_reg_defaults, | ||
792 | sizeof(wm8940_reg_defaults)); | ||
793 | |||
794 | ret = wm8940_reset(codec); | 708 | ret = wm8940_reset(codec); |
795 | if (ret < 0) { | 709 | if (ret < 0) { |
796 | dev_err(codec->dev, "Failed to issue reset\n"); | 710 | dev_err(codec->dev, "Failed to issue reset\n"); |
797 | return ret; | 711 | return ret; |
798 | } | 712 | } |
799 | 713 | ||
800 | wm8940_dai.dev = codec->dev; | ||
801 | |||
802 | wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 714 | wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
803 | 715 | ||
804 | ret = snd_soc_write(codec, WM8940_POWER1, 0x180); | 716 | ret = snd_soc_write(codec, WM8940_POWER1, 0x180); |
@@ -814,64 +726,60 @@ static int wm8940_register(struct wm8940_priv *wm8940, | |||
814 | return ret; | 726 | return ret; |
815 | } | 727 | } |
816 | 728 | ||
817 | 729 | ret = snd_soc_add_controls(codec, wm8940_snd_controls, | |
818 | wm8940_codec = codec; | 730 | ARRAY_SIZE(wm8940_snd_controls)); |
819 | 731 | if (ret) | |
820 | ret = snd_soc_register_codec(codec); | ||
821 | if (ret) { | ||
822 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
823 | return ret; | 732 | return ret; |
824 | } | 733 | ret = wm8940_add_widgets(codec); |
825 | 734 | if (ret) | |
826 | ret = snd_soc_register_dai(&wm8940_dai); | ||
827 | if (ret) { | ||
828 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
829 | snd_soc_unregister_codec(codec); | ||
830 | return ret; | 735 | return ret; |
831 | } | ||
832 | 736 | ||
833 | return 0; | 737 | return ret; |
738 | ; | ||
834 | } | 739 | } |
835 | 740 | ||
836 | static void wm8940_unregister(struct wm8940_priv *wm8940) | 741 | static int wm8940_remove(struct snd_soc_codec *codec) |
837 | { | 742 | { |
838 | wm8940_set_bias_level(&wm8940->codec, SND_SOC_BIAS_OFF); | 743 | wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); |
839 | snd_soc_unregister_dai(&wm8940_dai); | 744 | return 0; |
840 | snd_soc_unregister_codec(&wm8940->codec); | ||
841 | kfree(wm8940); | ||
842 | wm8940_codec = NULL; | ||
843 | } | 745 | } |
844 | 746 | ||
845 | static int wm8940_i2c_probe(struct i2c_client *i2c, | 747 | static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { |
846 | const struct i2c_device_id *id) | 748 | .probe = wm8940_probe, |
749 | .remove = wm8940_remove, | ||
750 | .suspend = wm8940_suspend, | ||
751 | .resume = wm8940_resume, | ||
752 | .set_bias_level = wm8940_set_bias_level, | ||
753 | .reg_cache_size = sizeof(wm8940_reg_defaults), | ||
754 | .reg_word_size = sizeof(u16), | ||
755 | .reg_cache_default = wm8940_reg_defaults, | ||
756 | }; | ||
757 | |||
758 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
759 | static __devinit int wm8940_i2c_probe(struct i2c_client *i2c, | ||
760 | const struct i2c_device_id *id) | ||
847 | { | 761 | { |
848 | int ret; | ||
849 | struct wm8940_priv *wm8940; | 762 | struct wm8940_priv *wm8940; |
850 | struct snd_soc_codec *codec; | 763 | int ret; |
851 | 764 | ||
852 | wm8940 = kzalloc(sizeof *wm8940, GFP_KERNEL); | 765 | wm8940 = kzalloc(sizeof(struct wm8940_priv), GFP_KERNEL); |
853 | if (wm8940 == NULL) | 766 | if (wm8940 == NULL) |
854 | return -ENOMEM; | 767 | return -ENOMEM; |
855 | 768 | ||
856 | codec = &wm8940->codec; | ||
857 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
858 | i2c_set_clientdata(i2c, wm8940); | 769 | i2c_set_clientdata(i2c, wm8940); |
859 | codec->control_data = i2c; | 770 | wm8940->control_data = i2c; |
860 | codec->dev = &i2c->dev; | ||
861 | 771 | ||
862 | ret = wm8940_register(wm8940, SND_SOC_I2C); | 772 | ret = snd_soc_register_codec(&i2c->dev, |
773 | &soc_codec_dev_wm8940, &wm8940_dai, 1); | ||
863 | if (ret < 0) | 774 | if (ret < 0) |
864 | kfree(wm8940); | 775 | kfree(wm8940); |
865 | |||
866 | return ret; | 776 | return ret; |
867 | } | 777 | } |
868 | 778 | ||
869 | static int __devexit wm8940_i2c_remove(struct i2c_client *client) | 779 | static __devexit int wm8940_i2c_remove(struct i2c_client *client) |
870 | { | 780 | { |
871 | struct wm8940_priv *wm8940 = i2c_get_clientdata(client); | 781 | snd_soc_unregister_codec(&client->dev); |
872 | 782 | kfree(i2c_get_clientdata(client)); | |
873 | wm8940_unregister(wm8940); | ||
874 | |||
875 | return 0; | 783 | return 0; |
876 | } | 784 | } |
877 | 785 | ||
@@ -883,29 +791,34 @@ MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id); | |||
883 | 791 | ||
884 | static struct i2c_driver wm8940_i2c_driver = { | 792 | static struct i2c_driver wm8940_i2c_driver = { |
885 | .driver = { | 793 | .driver = { |
886 | .name = "WM8940 I2C Codec", | 794 | .name = "wm8940-codec", |
887 | .owner = THIS_MODULE, | 795 | .owner = THIS_MODULE, |
888 | }, | 796 | }, |
889 | .probe = wm8940_i2c_probe, | 797 | .probe = wm8940_i2c_probe, |
890 | .remove = __devexit_p(wm8940_i2c_remove), | 798 | .remove = __devexit_p(wm8940_i2c_remove), |
891 | .id_table = wm8940_i2c_id, | 799 | .id_table = wm8940_i2c_id, |
892 | }; | 800 | }; |
801 | #endif | ||
893 | 802 | ||
894 | static int __init wm8940_modinit(void) | 803 | static int __init wm8940_modinit(void) |
895 | { | 804 | { |
896 | int ret; | 805 | int ret = 0; |
897 | 806 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
898 | ret = i2c_add_driver(&wm8940_i2c_driver); | 807 | ret = i2c_add_driver(&wm8940_i2c_driver); |
899 | if (ret) | 808 | if (ret != 0) { |
900 | printk(KERN_ERR "Failed to register WM8940 I2C driver: %d\n", | 809 | printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n", |
901 | ret); | 810 | ret); |
811 | } | ||
812 | #endif | ||
902 | return ret; | 813 | return ret; |
903 | } | 814 | } |
904 | module_init(wm8940_modinit); | 815 | module_init(wm8940_modinit); |
905 | 816 | ||
906 | static void __exit wm8940_exit(void) | 817 | static void __exit wm8940_exit(void) |
907 | { | 818 | { |
819 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
908 | i2c_del_driver(&wm8940_i2c_driver); | 820 | i2c_del_driver(&wm8940_i2c_driver); |
821 | #endif | ||
909 | } | 822 | } |
910 | module_exit(wm8940_exit); | 823 | module_exit(wm8940_exit); |
911 | 824 | ||
diff --git a/sound/soc/codecs/wm8940.h b/sound/soc/codecs/wm8940.h index 8410eed3ef84..907fe192e9e0 100644 --- a/sound/soc/codecs/wm8940.h +++ b/sound/soc/codecs/wm8940.h | |||
@@ -15,8 +15,6 @@ struct wm8940_setup_data { | |||
15 | #define WM8940_VROI_30K 1 | 15 | #define WM8940_VROI_30K 1 |
16 | unsigned int vroi:1; | 16 | unsigned int vroi:1; |
17 | }; | 17 | }; |
18 | extern struct snd_soc_dai wm8940_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8940; | ||
20 | 18 | ||
21 | /* WM8940 register space */ | 19 | /* WM8940 register space */ |
22 | #define WM8940_SOFTRESET 0x00 | 20 | #define WM8940_SOFTRESET 0x00 |
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 5f025593d84d..a5a9f8ef5771 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -30,9 +30,6 @@ | |||
30 | 30 | ||
31 | #include "wm8955.h" | 31 | #include "wm8955.h" |
32 | 32 | ||
33 | static struct snd_soc_codec *wm8955_codec; | ||
34 | struct snd_soc_codec_device soc_codec_dev_wm8955; | ||
35 | |||
36 | #define WM8955_NUM_SUPPLIES 4 | 33 | #define WM8955_NUM_SUPPLIES 4 |
37 | static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { | 34 | static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { |
38 | "DCVDD", | 35 | "DCVDD", |
@@ -43,7 +40,9 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { | |||
43 | 40 | ||
44 | /* codec private data */ | 41 | /* codec private data */ |
45 | struct wm8955_priv { | 42 | struct wm8955_priv { |
46 | struct snd_soc_codec codec; | 43 | enum snd_soc_control_type control_type; |
44 | void *control_data; | ||
45 | |||
47 | u16 reg_cache[WM8955_MAX_REGISTER + 1]; | 46 | u16 reg_cache[WM8955_MAX_REGISTER + 1]; |
48 | 47 | ||
49 | unsigned int mclk_rate; | 48 | unsigned int mclk_rate; |
@@ -52,8 +51,6 @@ struct wm8955_priv { | |||
52 | int fs; | 51 | int fs; |
53 | 52 | ||
54 | struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; | 53 | struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; |
55 | |||
56 | struct wm8955_pdata *pdata; | ||
57 | }; | 54 | }; |
58 | 55 | ||
59 | static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = { | 56 | static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = { |
@@ -870,8 +867,8 @@ static struct snd_soc_dai_ops wm8955_dai_ops = { | |||
870 | .digital_mute = wm8955_digital_mute, | 867 | .digital_mute = wm8955_digital_mute, |
871 | }; | 868 | }; |
872 | 869 | ||
873 | struct snd_soc_dai wm8955_dai = { | 870 | static struct snd_soc_dai_driver wm8955_dai = { |
874 | .name = "WM8955", | 871 | .name = "wm8955-hifi", |
875 | .playback = { | 872 | .playback = { |
876 | .stream_name = "Playback", | 873 | .stream_name = "Playback", |
877 | .channels_min = 2, | 874 | .channels_min = 2, |
@@ -881,24 +878,17 @@ struct snd_soc_dai wm8955_dai = { | |||
881 | }, | 878 | }, |
882 | .ops = &wm8955_dai_ops, | 879 | .ops = &wm8955_dai_ops, |
883 | }; | 880 | }; |
884 | EXPORT_SYMBOL_GPL(wm8955_dai); | ||
885 | 881 | ||
886 | #ifdef CONFIG_PM | 882 | #ifdef CONFIG_PM |
887 | static int wm8955_suspend(struct platform_device *pdev, pm_message_t state) | 883 | static int wm8955_suspend(struct snd_soc_codec *codec, pm_message_t state) |
888 | { | 884 | { |
889 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
890 | struct snd_soc_codec *codec = socdev->card->codec; | ||
891 | |||
892 | wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); | 885 | wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); |
893 | 886 | ||
894 | return 0; | 887 | return 0; |
895 | } | 888 | } |
896 | 889 | ||
897 | static int wm8955_resume(struct platform_device *pdev) | 890 | static int wm8955_resume(struct snd_soc_codec *codec) |
898 | { | 891 | { |
899 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
900 | struct snd_soc_codec *codec = socdev->card->codec; | ||
901 | |||
902 | wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 892 | wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
903 | 893 | ||
904 | return 0; | 894 | return 0; |
@@ -908,86 +898,17 @@ static int wm8955_resume(struct platform_device *pdev) | |||
908 | #define wm8955_resume NULL | 898 | #define wm8955_resume NULL |
909 | #endif | 899 | #endif |
910 | 900 | ||
911 | static int wm8955_probe(struct platform_device *pdev) | 901 | static int wm8955_probe(struct snd_soc_codec *codec) |
912 | { | ||
913 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
914 | struct snd_soc_codec *codec; | ||
915 | int ret = 0; | ||
916 | |||
917 | if (wm8955_codec == NULL) { | ||
918 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
919 | return -ENODEV; | ||
920 | } | ||
921 | |||
922 | socdev->card->codec = wm8955_codec; | ||
923 | codec = wm8955_codec; | ||
924 | |||
925 | /* register pcms */ | ||
926 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
927 | if (ret < 0) { | ||
928 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
929 | goto pcm_err; | ||
930 | } | ||
931 | |||
932 | wm8955_add_widgets(codec); | ||
933 | |||
934 | return ret; | ||
935 | |||
936 | pcm_err: | ||
937 | return ret; | ||
938 | } | ||
939 | |||
940 | static int wm8955_remove(struct platform_device *pdev) | ||
941 | { | 902 | { |
942 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 903 | struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); |
943 | 904 | struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); | |
944 | snd_soc_free_pcms(socdev); | 905 | int ret, i; |
945 | snd_soc_dapm_free(socdev); | ||
946 | |||
947 | return 0; | ||
948 | } | ||
949 | |||
950 | struct snd_soc_codec_device soc_codec_dev_wm8955 = { | ||
951 | .probe = wm8955_probe, | ||
952 | .remove = wm8955_remove, | ||
953 | .suspend = wm8955_suspend, | ||
954 | .resume = wm8955_resume, | ||
955 | }; | ||
956 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8955); | ||
957 | |||
958 | static int wm8955_register(struct wm8955_priv *wm8955, | ||
959 | enum snd_soc_control_type control) | ||
960 | { | ||
961 | int ret; | ||
962 | struct snd_soc_codec *codec = &wm8955->codec; | ||
963 | int i; | ||
964 | |||
965 | if (wm8955_codec) { | ||
966 | dev_err(codec->dev, "Another WM8955 is registered\n"); | ||
967 | ret = -EINVAL; | ||
968 | goto err; | ||
969 | } | ||
970 | |||
971 | mutex_init(&codec->mutex); | ||
972 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
973 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
974 | |||
975 | snd_soc_codec_set_drvdata(codec, wm8955); | ||
976 | codec->name = "WM8955"; | ||
977 | codec->owner = THIS_MODULE; | ||
978 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
979 | codec->set_bias_level = wm8955_set_bias_level; | ||
980 | codec->dai = &wm8955_dai; | ||
981 | codec->num_dai = 1; | ||
982 | codec->reg_cache_size = WM8955_MAX_REGISTER; | ||
983 | codec->reg_cache = &wm8955->reg_cache; | ||
984 | |||
985 | memcpy(codec->reg_cache, wm8955_reg, sizeof(wm8955_reg)); | ||
986 | 906 | ||
987 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 907 | codec->control_data = wm8955->control_data; |
908 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type); | ||
988 | if (ret != 0) { | 909 | if (ret != 0) { |
989 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 910 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
990 | goto err; | 911 | return ret; |
991 | } | 912 | } |
992 | 913 | ||
993 | for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) | 914 | for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) |
@@ -997,7 +918,7 @@ static int wm8955_register(struct wm8955_priv *wm8955, | |||
997 | wm8955->supplies); | 918 | wm8955->supplies); |
998 | if (ret != 0) { | 919 | if (ret != 0) { |
999 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | 920 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); |
1000 | goto err; | 921 | return ret; |
1001 | } | 922 | } |
1002 | 923 | ||
1003 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), | 924 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), |
@@ -1013,8 +934,6 @@ static int wm8955_register(struct wm8955_priv *wm8955, | |||
1013 | goto err_enable; | 934 | goto err_enable; |
1014 | } | 935 | } |
1015 | 936 | ||
1016 | wm8955_dai.dev = codec->dev; | ||
1017 | |||
1018 | /* Change some default settings - latch VU and enable ZC */ | 937 | /* Change some default settings - latch VU and enable ZC */ |
1019 | wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; | 938 | wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; |
1020 | wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; | 939 | wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; |
@@ -1028,12 +947,12 @@ static int wm8955_register(struct wm8955_priv *wm8955, | |||
1028 | wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; | 947 | wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; |
1029 | 948 | ||
1030 | /* Set platform data values */ | 949 | /* Set platform data values */ |
1031 | if (wm8955->pdata) { | 950 | if (pdata) { |
1032 | if (wm8955->pdata->out2_speaker) | 951 | if (pdata->out2_speaker) |
1033 | wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] | 952 | wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] |
1034 | |= WM8955_ROUT2INV; | 953 | |= WM8955_ROUT2INV; |
1035 | 954 | ||
1036 | if (wm8955->pdata->monoin_diff) | 955 | if (pdata->monoin_diff) |
1037 | wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] | 956 | wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] |
1038 | |= WM8955_DMEN; | 957 | |= WM8955_DMEN; |
1039 | } | 958 | } |
@@ -1043,70 +962,61 @@ static int wm8955_register(struct wm8955_priv *wm8955, | |||
1043 | /* Bias level configuration will have done an extra enable */ | 962 | /* Bias level configuration will have done an extra enable */ |
1044 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | 963 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); |
1045 | 964 | ||
1046 | wm8955_codec = codec; | 965 | wm8955_add_widgets(codec); |
1047 | |||
1048 | ret = snd_soc_register_codec(codec); | ||
1049 | if (ret != 0) { | ||
1050 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1051 | goto err_enable; | ||
1052 | } | ||
1053 | |||
1054 | ret = snd_soc_register_dai(&wm8955_dai); | ||
1055 | if (ret != 0) { | ||
1056 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1057 | goto err_codec; | ||
1058 | } | ||
1059 | |||
1060 | return 0; | 966 | return 0; |
1061 | 967 | ||
1062 | err_codec: | ||
1063 | snd_soc_unregister_codec(codec); | ||
1064 | err_enable: | 968 | err_enable: |
1065 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | 969 | regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); |
1066 | err_get: | 970 | err_get: |
1067 | regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | 971 | regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); |
1068 | err: | ||
1069 | kfree(wm8955); | ||
1070 | return ret; | 972 | return ret; |
1071 | } | 973 | } |
1072 | 974 | ||
1073 | static void wm8955_unregister(struct wm8955_priv *wm8955) | 975 | static int wm8955_remove(struct snd_soc_codec *codec) |
1074 | { | 976 | { |
1075 | wm8955_set_bias_level(&wm8955->codec, SND_SOC_BIAS_OFF); | 977 | struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); |
978 | |||
979 | wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1076 | regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); | 980 | regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); |
1077 | snd_soc_unregister_dai(&wm8955_dai); | 981 | return 0; |
1078 | snd_soc_unregister_codec(&wm8955->codec); | ||
1079 | kfree(wm8955); | ||
1080 | wm8955_codec = NULL; | ||
1081 | } | 982 | } |
1082 | 983 | ||
984 | static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { | ||
985 | .probe = wm8955_probe, | ||
986 | .remove = wm8955_remove, | ||
987 | .suspend = wm8955_suspend, | ||
988 | .resume = wm8955_resume, | ||
989 | .set_bias_level = wm8955_set_bias_level, | ||
990 | .reg_cache_size = ARRAY_SIZE(wm8955_reg), | ||
991 | .reg_word_size = sizeof(u16), | ||
992 | .reg_cache_default = wm8955_reg, | ||
993 | }; | ||
994 | |||
1083 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 995 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1084 | static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, | 996 | static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, |
1085 | const struct i2c_device_id *id) | 997 | const struct i2c_device_id *id) |
1086 | { | 998 | { |
1087 | struct wm8955_priv *wm8955; | 999 | struct wm8955_priv *wm8955; |
1088 | struct snd_soc_codec *codec; | 1000 | int ret; |
1089 | 1001 | ||
1090 | wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL); | 1002 | wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL); |
1091 | if (wm8955 == NULL) | 1003 | if (wm8955 == NULL) |
1092 | return -ENOMEM; | 1004 | return -ENOMEM; |
1093 | 1005 | ||
1094 | codec = &wm8955->codec; | ||
1095 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1096 | |||
1097 | i2c_set_clientdata(i2c, wm8955); | 1006 | i2c_set_clientdata(i2c, wm8955); |
1098 | codec->control_data = i2c; | 1007 | wm8955->control_data = i2c; |
1099 | wm8955->pdata = i2c->dev.platform_data; | ||
1100 | |||
1101 | codec->dev = &i2c->dev; | ||
1102 | 1008 | ||
1103 | return wm8955_register(wm8955, SND_SOC_I2C); | 1009 | ret = snd_soc_register_codec(&i2c->dev, |
1010 | &soc_codec_dev_wm8955, &wm8955_dai, 1); | ||
1011 | if (ret < 0) | ||
1012 | kfree(wm8955); | ||
1013 | return ret; | ||
1104 | } | 1014 | } |
1105 | 1015 | ||
1106 | static __devexit int wm8955_i2c_remove(struct i2c_client *client) | 1016 | static __devexit int wm8955_i2c_remove(struct i2c_client *client) |
1107 | { | 1017 | { |
1108 | struct wm8955_priv *wm8955 = i2c_get_clientdata(client); | 1018 | snd_soc_unregister_codec(&client->dev); |
1109 | wm8955_unregister(wm8955); | 1019 | kfree(i2c_get_clientdata(client)); |
1110 | return 0; | 1020 | return 0; |
1111 | } | 1021 | } |
1112 | 1022 | ||
@@ -1118,7 +1028,7 @@ MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id); | |||
1118 | 1028 | ||
1119 | static struct i2c_driver wm8955_i2c_driver = { | 1029 | static struct i2c_driver wm8955_i2c_driver = { |
1120 | .driver = { | 1030 | .driver = { |
1121 | .name = "wm8955", | 1031 | .name = "wm8955-codec", |
1122 | .owner = THIS_MODULE, | 1032 | .owner = THIS_MODULE, |
1123 | }, | 1033 | }, |
1124 | .probe = wm8955_i2c_probe, | 1034 | .probe = wm8955_i2c_probe, |
@@ -1129,7 +1039,7 @@ static struct i2c_driver wm8955_i2c_driver = { | |||
1129 | 1039 | ||
1130 | static int __init wm8955_modinit(void) | 1040 | static int __init wm8955_modinit(void) |
1131 | { | 1041 | { |
1132 | int ret; | 1042 | int ret = 0; |
1133 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1043 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1134 | ret = i2c_add_driver(&wm8955_i2c_driver); | 1044 | ret = i2c_add_driver(&wm8955_i2c_driver); |
1135 | if (ret != 0) { | 1045 | if (ret != 0) { |
@@ -1137,7 +1047,7 @@ static int __init wm8955_modinit(void) | |||
1137 | ret); | 1047 | ret); |
1138 | } | 1048 | } |
1139 | #endif | 1049 | #endif |
1140 | return 0; | 1050 | return ret; |
1141 | } | 1051 | } |
1142 | module_init(wm8955_modinit); | 1052 | module_init(wm8955_modinit); |
1143 | 1053 | ||
diff --git a/sound/soc/codecs/wm8955.h b/sound/soc/codecs/wm8955.h index ae349c8531f6..d13fd5c5fa63 100644 --- a/sound/soc/codecs/wm8955.h +++ b/sound/soc/codecs/wm8955.h | |||
@@ -15,9 +15,6 @@ | |||
15 | 15 | ||
16 | #define WM8955_CLK_MCLK 1 | 16 | #define WM8955_CLK_MCLK 1 |
17 | 17 | ||
18 | extern struct snd_soc_dai wm8955_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8955; | ||
20 | |||
21 | /* | 18 | /* |
22 | * Register values. | 19 | * Register values. |
23 | */ | 20 | */ |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 3c6ee61f6c95..8d5efb333c33 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -29,8 +29,6 @@ | |||
29 | 29 | ||
30 | #define AUDIO_NAME "wm8960" | 30 | #define AUDIO_NAME "wm8960" |
31 | 31 | ||
32 | struct snd_soc_codec_device soc_codec_dev_wm8960; | ||
33 | |||
34 | /* R25 - Power 1 */ | 32 | /* R25 - Power 1 */ |
35 | #define WM8960_VMID_MASK 0x180 | 33 | #define WM8960_VMID_MASK 0x180 |
36 | #define WM8960_VREF 0x40 | 34 | #define WM8960_VREF 0x40 |
@@ -75,7 +73,10 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { | |||
75 | 73 | ||
76 | struct wm8960_priv { | 74 | struct wm8960_priv { |
77 | u16 reg_cache[WM8960_CACHEREGNUM]; | 75 | u16 reg_cache[WM8960_CACHEREGNUM]; |
78 | struct snd_soc_codec codec; | 76 | enum snd_soc_control_type control_type; |
77 | void *control_data; | ||
78 | int (*set_bias_level)(struct snd_soc_codec *, | ||
79 | enum snd_soc_bias_level level); | ||
79 | struct snd_soc_dapm_widget *lout1; | 80 | struct snd_soc_dapm_widget *lout1; |
80 | struct snd_soc_dapm_widget *rout1; | 81 | struct snd_soc_dapm_widget *rout1; |
81 | struct snd_soc_dapm_widget *out3; | 82 | struct snd_soc_dapm_widget *out3; |
@@ -507,8 +508,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
507 | struct snd_soc_dai *dai) | 508 | struct snd_soc_dai *dai) |
508 | { | 509 | { |
509 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 510 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
510 | struct snd_soc_device *socdev = rtd->socdev; | 511 | struct snd_soc_codec *codec = rtd->codec; |
511 | struct snd_soc_codec *codec = socdev->card->codec; | ||
512 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 512 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
513 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; | 513 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; |
514 | int i; | 514 | int i; |
@@ -849,6 +849,14 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | |||
849 | return 0; | 849 | return 0; |
850 | } | 850 | } |
851 | 851 | ||
852 | static int wm8960_set_bias_level(struct snd_soc_codec *codec, | ||
853 | enum snd_soc_bias_level level) | ||
854 | { | ||
855 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
856 | |||
857 | return wm8960->set_bias_level(codec, level); | ||
858 | } | ||
859 | |||
852 | #define WM8960_RATES SNDRV_PCM_RATE_8000_48000 | 860 | #define WM8960_RATES SNDRV_PCM_RATE_8000_48000 |
853 | 861 | ||
854 | #define WM8960_FORMATS \ | 862 | #define WM8960_FORMATS \ |
@@ -863,8 +871,8 @@ static struct snd_soc_dai_ops wm8960_dai_ops = { | |||
863 | .set_pll = wm8960_set_dai_pll, | 871 | .set_pll = wm8960_set_dai_pll, |
864 | }; | 872 | }; |
865 | 873 | ||
866 | struct snd_soc_dai wm8960_dai = { | 874 | static struct snd_soc_dai_driver wm8960_dai = { |
867 | .name = "WM8960", | 875 | .name = "wm8960-hifi", |
868 | .playback = { | 876 | .playback = { |
869 | .stream_name = "Playback", | 877 | .stream_name = "Playback", |
870 | .channels_min = 1, | 878 | .channels_min = 1, |
@@ -880,21 +888,18 @@ struct snd_soc_dai wm8960_dai = { | |||
880 | .ops = &wm8960_dai_ops, | 888 | .ops = &wm8960_dai_ops, |
881 | .symmetric_rates = 1, | 889 | .symmetric_rates = 1, |
882 | }; | 890 | }; |
883 | EXPORT_SYMBOL_GPL(wm8960_dai); | ||
884 | 891 | ||
885 | static int wm8960_suspend(struct platform_device *pdev, pm_message_t state) | 892 | static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state) |
886 | { | 893 | { |
887 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 894 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
888 | struct snd_soc_codec *codec = socdev->card->codec; | ||
889 | 895 | ||
890 | codec->set_bias_level(codec, SND_SOC_BIAS_OFF); | 896 | wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF); |
891 | return 0; | 897 | return 0; |
892 | } | 898 | } |
893 | 899 | ||
894 | static int wm8960_resume(struct platform_device *pdev) | 900 | static int wm8960_resume(struct snd_soc_codec *codec) |
895 | { | 901 | { |
896 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 902 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
897 | struct snd_soc_codec *codec = socdev->card->codec; | ||
898 | int i; | 903 | int i; |
899 | u8 data[2]; | 904 | u8 data[2]; |
900 | u16 *cache = codec->reg_cache; | 905 | u16 *cache = codec->reg_cache; |
@@ -906,78 +911,19 @@ static int wm8960_resume(struct platform_device *pdev) | |||
906 | codec->hw_write(codec->control_data, data, 2); | 911 | codec->hw_write(codec->control_data, data, 2); |
907 | } | 912 | } |
908 | 913 | ||
909 | codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 914 | wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
910 | |||
911 | return 0; | 915 | return 0; |
912 | } | 916 | } |
913 | 917 | ||
914 | static struct snd_soc_codec *wm8960_codec; | 918 | static int wm8960_probe(struct snd_soc_codec *codec) |
915 | |||
916 | static int wm8960_probe(struct platform_device *pdev) | ||
917 | { | ||
918 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
919 | struct snd_soc_codec *codec; | ||
920 | int ret = 0; | ||
921 | |||
922 | if (wm8960_codec == NULL) { | ||
923 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
924 | return -ENODEV; | ||
925 | } | ||
926 | |||
927 | socdev->card->codec = wm8960_codec; | ||
928 | codec = wm8960_codec; | ||
929 | |||
930 | /* register pcms */ | ||
931 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
932 | if (ret < 0) { | ||
933 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
934 | goto pcm_err; | ||
935 | } | ||
936 | |||
937 | snd_soc_add_controls(codec, wm8960_snd_controls, | ||
938 | ARRAY_SIZE(wm8960_snd_controls)); | ||
939 | wm8960_add_widgets(codec); | ||
940 | |||
941 | return ret; | ||
942 | |||
943 | pcm_err: | ||
944 | return ret; | ||
945 | } | ||
946 | |||
947 | /* power down chip */ | ||
948 | static int wm8960_remove(struct platform_device *pdev) | ||
949 | { | ||
950 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
951 | |||
952 | snd_soc_free_pcms(socdev); | ||
953 | snd_soc_dapm_free(socdev); | ||
954 | |||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | struct snd_soc_codec_device soc_codec_dev_wm8960 = { | ||
959 | .probe = wm8960_probe, | ||
960 | .remove = wm8960_remove, | ||
961 | .suspend = wm8960_suspend, | ||
962 | .resume = wm8960_resume, | ||
963 | }; | ||
964 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960); | ||
965 | |||
966 | static int wm8960_register(struct wm8960_priv *wm8960, | ||
967 | enum snd_soc_control_type control) | ||
968 | { | 919 | { |
969 | struct wm8960_data *pdata = wm8960->codec.dev->platform_data; | 920 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
970 | struct snd_soc_codec *codec = &wm8960->codec; | 921 | struct wm8960_data *pdata = dev_get_platdata(codec->dev); |
971 | int ret; | 922 | int ret; |
972 | u16 reg; | 923 | u16 reg; |
973 | 924 | ||
974 | if (wm8960_codec) { | 925 | wm8960->set_bias_level = wm8960_set_bias_level_out3; |
975 | dev_err(codec->dev, "Another WM8960 is registered\n"); | 926 | codec->control_data = wm8960->control_data; |
976 | ret = -EINVAL; | ||
977 | goto err; | ||
978 | } | ||
979 | |||
980 | codec->set_bias_level = wm8960_set_bias_level_out3; | ||
981 | 927 | ||
982 | if (!pdata) { | 928 | if (!pdata) { |
983 | dev_warn(codec->dev, "No platform data supplied\n"); | 929 | dev_warn(codec->dev, "No platform data supplied\n"); |
@@ -988,39 +934,22 @@ static int wm8960_register(struct wm8960_priv *wm8960, | |||
988 | } | 934 | } |
989 | 935 | ||
990 | if (pdata->capless) | 936 | if (pdata->capless) |
991 | codec->set_bias_level = wm8960_set_bias_level_capless; | 937 | wm8960->set_bias_level = wm8960_set_bias_level_capless; |
992 | } | 938 | } |
993 | 939 | ||
994 | mutex_init(&codec->mutex); | 940 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8960->control_type); |
995 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
996 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
997 | |||
998 | snd_soc_codec_set_drvdata(codec, wm8960); | ||
999 | codec->name = "WM8960"; | ||
1000 | codec->owner = THIS_MODULE; | ||
1001 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1002 | codec->dai = &wm8960_dai; | ||
1003 | codec->num_dai = 1; | ||
1004 | codec->reg_cache_size = WM8960_CACHEREGNUM; | ||
1005 | codec->reg_cache = &wm8960->reg_cache; | ||
1006 | |||
1007 | memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg)); | ||
1008 | |||
1009 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
1010 | if (ret < 0) { | 941 | if (ret < 0) { |
1011 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 942 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1012 | goto err; | 943 | return ret; |
1013 | } | 944 | } |
1014 | 945 | ||
1015 | ret = wm8960_reset(codec); | 946 | ret = wm8960_reset(codec); |
1016 | if (ret < 0) { | 947 | if (ret < 0) { |
1017 | dev_err(codec->dev, "Failed to issue reset\n"); | 948 | dev_err(codec->dev, "Failed to issue reset\n"); |
1018 | goto err; | 949 | return ret; |
1019 | } | 950 | } |
1020 | 951 | ||
1021 | wm8960_dai.dev = codec->dev; | 952 | wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1022 | |||
1023 | codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1024 | 953 | ||
1025 | /* Latch the update bits */ | 954 | /* Latch the update bits */ |
1026 | reg = snd_soc_read(codec, WM8960_LINVOL); | 955 | reg = snd_soc_read(codec, WM8960_LINVOL); |
@@ -1044,62 +973,58 @@ static int wm8960_register(struct wm8960_priv *wm8960, | |||
1044 | reg = snd_soc_read(codec, WM8960_ROUT2); | 973 | reg = snd_soc_read(codec, WM8960_ROUT2); |
1045 | snd_soc_write(codec, WM8960_ROUT2, reg | 0x100); | 974 | snd_soc_write(codec, WM8960_ROUT2, reg | 0x100); |
1046 | 975 | ||
1047 | wm8960_codec = codec; | 976 | snd_soc_add_controls(codec, wm8960_snd_controls, |
1048 | 977 | ARRAY_SIZE(wm8960_snd_controls)); | |
1049 | ret = snd_soc_register_codec(codec); | 978 | wm8960_add_widgets(codec); |
1050 | if (ret != 0) { | ||
1051 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1052 | goto err; | ||
1053 | } | ||
1054 | |||
1055 | ret = snd_soc_register_dai(&wm8960_dai); | ||
1056 | if (ret != 0) { | ||
1057 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1058 | goto err_codec; | ||
1059 | } | ||
1060 | 979 | ||
1061 | return 0; | 980 | return 0; |
1062 | |||
1063 | err_codec: | ||
1064 | snd_soc_unregister_codec(codec); | ||
1065 | err: | ||
1066 | kfree(wm8960); | ||
1067 | return ret; | ||
1068 | } | 981 | } |
1069 | 982 | ||
1070 | static void wm8960_unregister(struct wm8960_priv *wm8960) | 983 | /* power down chip */ |
984 | static int wm8960_remove(struct snd_soc_codec *codec) | ||
1071 | { | 985 | { |
1072 | wm8960->codec.set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF); | 986 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
1073 | snd_soc_unregister_dai(&wm8960_dai); | 987 | |
1074 | snd_soc_unregister_codec(&wm8960->codec); | 988 | wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF); |
1075 | kfree(wm8960); | 989 | return 0; |
1076 | wm8960_codec = NULL; | ||
1077 | } | 990 | } |
1078 | 991 | ||
992 | static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { | ||
993 | .probe = wm8960_probe, | ||
994 | .remove = wm8960_remove, | ||
995 | .suspend = wm8960_suspend, | ||
996 | .resume = wm8960_resume, | ||
997 | .set_bias_level = wm8960_set_bias_level, | ||
998 | .reg_cache_size = ARRAY_SIZE(wm8960_reg), | ||
999 | .reg_word_size = sizeof(u16), | ||
1000 | .reg_cache_default = wm8960_reg, | ||
1001 | }; | ||
1002 | |||
1003 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1079 | static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, | 1004 | static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, |
1080 | const struct i2c_device_id *id) | 1005 | const struct i2c_device_id *id) |
1081 | { | 1006 | { |
1082 | struct wm8960_priv *wm8960; | 1007 | struct wm8960_priv *wm8960; |
1083 | struct snd_soc_codec *codec; | 1008 | int ret; |
1084 | 1009 | ||
1085 | wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL); | 1010 | wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL); |
1086 | if (wm8960 == NULL) | 1011 | if (wm8960 == NULL) |
1087 | return -ENOMEM; | 1012 | return -ENOMEM; |
1088 | 1013 | ||
1089 | codec = &wm8960->codec; | ||
1090 | |||
1091 | i2c_set_clientdata(i2c, wm8960); | 1014 | i2c_set_clientdata(i2c, wm8960); |
1092 | codec->control_data = i2c; | 1015 | wm8960->control_data = i2c; |
1093 | |||
1094 | codec->dev = &i2c->dev; | ||
1095 | 1016 | ||
1096 | return wm8960_register(wm8960, SND_SOC_I2C); | 1017 | ret = snd_soc_register_codec(&i2c->dev, |
1018 | &soc_codec_dev_wm8960, &wm8960_dai, 1); | ||
1019 | if (ret < 0) | ||
1020 | kfree(wm8960); | ||
1021 | return ret; | ||
1097 | } | 1022 | } |
1098 | 1023 | ||
1099 | static __devexit int wm8960_i2c_remove(struct i2c_client *client) | 1024 | static __devexit int wm8960_i2c_remove(struct i2c_client *client) |
1100 | { | 1025 | { |
1101 | struct wm8960_priv *wm8960 = i2c_get_clientdata(client); | 1026 | snd_soc_unregister_codec(&client->dev); |
1102 | wm8960_unregister(wm8960); | 1027 | kfree(i2c_get_clientdata(client)); |
1103 | return 0; | 1028 | return 0; |
1104 | } | 1029 | } |
1105 | 1030 | ||
@@ -1111,35 +1036,37 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id); | |||
1111 | 1036 | ||
1112 | static struct i2c_driver wm8960_i2c_driver = { | 1037 | static struct i2c_driver wm8960_i2c_driver = { |
1113 | .driver = { | 1038 | .driver = { |
1114 | .name = "wm8960", | 1039 | .name = "wm8960-codec", |
1115 | .owner = THIS_MODULE, | 1040 | .owner = THIS_MODULE, |
1116 | }, | 1041 | }, |
1117 | .probe = wm8960_i2c_probe, | 1042 | .probe = wm8960_i2c_probe, |
1118 | .remove = __devexit_p(wm8960_i2c_remove), | 1043 | .remove = __devexit_p(wm8960_i2c_remove), |
1119 | .id_table = wm8960_i2c_id, | 1044 | .id_table = wm8960_i2c_id, |
1120 | }; | 1045 | }; |
1046 | #endif | ||
1121 | 1047 | ||
1122 | static int __init wm8960_modinit(void) | 1048 | static int __init wm8960_modinit(void) |
1123 | { | 1049 | { |
1124 | int ret; | 1050 | int ret = 0; |
1125 | 1051 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1126 | ret = i2c_add_driver(&wm8960_i2c_driver); | 1052 | ret = i2c_add_driver(&wm8960_i2c_driver); |
1127 | if (ret != 0) { | 1053 | if (ret != 0) { |
1128 | printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", | 1054 | printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", |
1129 | ret); | 1055 | ret); |
1130 | } | 1056 | } |
1131 | 1057 | #endif | |
1132 | return ret; | 1058 | return ret; |
1133 | } | 1059 | } |
1134 | module_init(wm8960_modinit); | 1060 | module_init(wm8960_modinit); |
1135 | 1061 | ||
1136 | static void __exit wm8960_exit(void) | 1062 | static void __exit wm8960_exit(void) |
1137 | { | 1063 | { |
1064 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1138 | i2c_del_driver(&wm8960_i2c_driver); | 1065 | i2c_del_driver(&wm8960_i2c_driver); |
1066 | #endif | ||
1139 | } | 1067 | } |
1140 | module_exit(wm8960_exit); | 1068 | module_exit(wm8960_exit); |
1141 | 1069 | ||
1142 | |||
1143 | MODULE_DESCRIPTION("ASoC WM8960 driver"); | 1070 | MODULE_DESCRIPTION("ASoC WM8960 driver"); |
1144 | MODULE_AUTHOR("Liam Girdwood"); | 1071 | MODULE_AUTHOR("Liam Girdwood"); |
1145 | MODULE_LICENSE("GPL"); | 1072 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h index a5ef65481b86..2d8163d7004b 100644 --- a/sound/soc/codecs/wm8960.h +++ b/sound/soc/codecs/wm8960.h | |||
@@ -110,7 +110,4 @@ | |||
110 | #define WM8960_OPCLK_DIV_5_5 (4 << 0) | 110 | #define WM8960_OPCLK_DIV_5_5 (4 << 0) |
111 | #define WM8960_OPCLK_DIV_6 (5 << 0) | 111 | #define WM8960_OPCLK_DIV_6 (5 << 0) |
112 | 112 | ||
113 | extern struct snd_soc_dai wm8960_dai; | ||
114 | extern struct snd_soc_codec_device soc_codec_dev_wm8960; | ||
115 | |||
116 | #endif | 113 | #endif |
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 2549d3a297ab..5ebe2c04e5cf 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -288,7 +288,8 @@ static u16 wm8961_reg_defaults[] = { | |||
288 | }; | 288 | }; |
289 | 289 | ||
290 | struct wm8961_priv { | 290 | struct wm8961_priv { |
291 | struct snd_soc_codec codec; | 291 | enum snd_soc_control_type control_type; |
292 | void *control_data; | ||
292 | int sysclk; | 293 | int sysclk; |
293 | u16 reg_cache[WM8961_MAX_REGISTER]; | 294 | u16 reg_cache[WM8961_MAX_REGISTER]; |
294 | }; | 295 | }; |
@@ -940,8 +941,8 @@ static struct snd_soc_dai_ops wm8961_dai_ops = { | |||
940 | .set_clkdiv = wm8961_set_clkdiv, | 941 | .set_clkdiv = wm8961_set_clkdiv, |
941 | }; | 942 | }; |
942 | 943 | ||
943 | struct snd_soc_dai wm8961_dai = { | 944 | static struct snd_soc_dai_driver wm8961_dai = { |
944 | .name = "WM8961", | 945 | .name = "wm8961-hifi", |
945 | .playback = { | 946 | .playback = { |
946 | .stream_name = "HiFi Playback", | 947 | .stream_name = "HiFi Playback", |
947 | .channels_min = 1, | 948 | .channels_min = 1, |
@@ -956,140 +957,24 @@ struct snd_soc_dai wm8961_dai = { | |||
956 | .formats = WM8961_FORMATS,}, | 957 | .formats = WM8961_FORMATS,}, |
957 | .ops = &wm8961_dai_ops, | 958 | .ops = &wm8961_dai_ops, |
958 | }; | 959 | }; |
959 | EXPORT_SYMBOL_GPL(wm8961_dai); | ||
960 | 960 | ||
961 | 961 | static int wm8961_probe(struct snd_soc_codec *codec) | |
962 | static struct snd_soc_codec *wm8961_codec; | ||
963 | |||
964 | static int wm8961_probe(struct platform_device *pdev) | ||
965 | { | 962 | { |
966 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 963 | struct wm8961_priv *wm8961 = snd_soc_codec_get_drvdata(codec); |
967 | struct snd_soc_codec *codec; | ||
968 | int ret = 0; | 964 | int ret = 0; |
969 | |||
970 | if (wm8961_codec == NULL) { | ||
971 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
972 | return -ENODEV; | ||
973 | } | ||
974 | |||
975 | socdev->card->codec = wm8961_codec; | ||
976 | codec = wm8961_codec; | ||
977 | |||
978 | /* register pcms */ | ||
979 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
980 | if (ret < 0) { | ||
981 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
982 | goto pcm_err; | ||
983 | } | ||
984 | |||
985 | snd_soc_add_controls(codec, wm8961_snd_controls, | ||
986 | ARRAY_SIZE(wm8961_snd_controls)); | ||
987 | snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, | ||
988 | ARRAY_SIZE(wm8961_dapm_widgets)); | ||
989 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | ||
990 | |||
991 | return ret; | ||
992 | |||
993 | pcm_err: | ||
994 | return ret; | ||
995 | } | ||
996 | |||
997 | static int wm8961_remove(struct platform_device *pdev) | ||
998 | { | ||
999 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1000 | |||
1001 | snd_soc_free_pcms(socdev); | ||
1002 | snd_soc_dapm_free(socdev); | ||
1003 | |||
1004 | return 0; | ||
1005 | } | ||
1006 | |||
1007 | #ifdef CONFIG_PM | ||
1008 | static int wm8961_suspend(struct platform_device *pdev, pm_message_t state) | ||
1009 | { | ||
1010 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1011 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1012 | |||
1013 | wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1014 | |||
1015 | return 0; | ||
1016 | } | ||
1017 | |||
1018 | static int wm8961_resume(struct platform_device *pdev) | ||
1019 | { | ||
1020 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1021 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1022 | u16 *reg_cache = codec->reg_cache; | ||
1023 | int i; | ||
1024 | |||
1025 | for (i = 0; i < codec->reg_cache_size; i++) { | ||
1026 | if (reg_cache[i] == wm8961_reg_defaults[i]) | ||
1027 | continue; | ||
1028 | |||
1029 | if (i == WM8961_SOFTWARE_RESET) | ||
1030 | continue; | ||
1031 | |||
1032 | snd_soc_write(codec, i, reg_cache[i]); | ||
1033 | } | ||
1034 | |||
1035 | wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1036 | |||
1037 | return 0; | ||
1038 | } | ||
1039 | #else | ||
1040 | #define wm8961_suspend NULL | ||
1041 | #define wm8961_resume NULL | ||
1042 | #endif | ||
1043 | |||
1044 | struct snd_soc_codec_device soc_codec_dev_wm8961 = { | ||
1045 | .probe = wm8961_probe, | ||
1046 | .remove = wm8961_remove, | ||
1047 | .suspend = wm8961_suspend, | ||
1048 | .resume = wm8961_resume, | ||
1049 | }; | ||
1050 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8961); | ||
1051 | |||
1052 | static int wm8961_register(struct wm8961_priv *wm8961) | ||
1053 | { | ||
1054 | struct snd_soc_codec *codec = &wm8961->codec; | ||
1055 | int ret; | ||
1056 | u16 reg; | 965 | u16 reg; |
1057 | 966 | ||
1058 | if (wm8961_codec) { | 967 | codec->control_data = wm8961->control_data; |
1059 | dev_err(codec->dev, "Another WM8961 is registered\n"); | ||
1060 | ret = -EINVAL; | ||
1061 | goto err; | ||
1062 | } | ||
1063 | |||
1064 | mutex_init(&codec->mutex); | ||
1065 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1066 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1067 | |||
1068 | snd_soc_codec_set_drvdata(codec, wm8961); | ||
1069 | codec->name = "WM8961"; | ||
1070 | codec->owner = THIS_MODULE; | ||
1071 | codec->dai = &wm8961_dai; | ||
1072 | codec->num_dai = 1; | ||
1073 | codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache); | ||
1074 | codec->reg_cache = &wm8961->reg_cache; | ||
1075 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1076 | codec->set_bias_level = wm8961_set_bias_level; | ||
1077 | codec->volatile_register = wm8961_volatile_register; | ||
1078 | |||
1079 | memcpy(codec->reg_cache, wm8961_reg_defaults, | ||
1080 | sizeof(wm8961_reg_defaults)); | ||
1081 | |||
1082 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 968 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
1083 | if (ret != 0) { | 969 | if (ret != 0) { |
1084 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 970 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1085 | goto err; | 971 | return ret; |
1086 | } | 972 | } |
1087 | 973 | ||
1088 | reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); | 974 | reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); |
1089 | if (reg != 0x1801) { | 975 | if (reg != 0x1801) { |
1090 | dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); | 976 | dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); |
1091 | ret = -EINVAL; | 977 | return -EINVAL; |
1092 | goto err; | ||
1093 | } | 978 | } |
1094 | 979 | ||
1095 | /* This isn't volatile - readback doesn't correspond to write */ | 980 | /* This isn't volatile - readback doesn't correspond to write */ |
@@ -1102,7 +987,7 @@ static int wm8961_register(struct wm8961_priv *wm8961) | |||
1102 | ret = wm8961_reset(codec); | 987 | ret = wm8961_reset(codec); |
1103 | if (ret < 0) { | 988 | if (ret < 0) { |
1104 | dev_err(codec->dev, "Failed to issue reset\n"); | 989 | dev_err(codec->dev, "Failed to issue reset\n"); |
1105 | goto err; | 990 | return ret; |
1106 | } | 991 | } |
1107 | 992 | ||
1108 | /* Enable class W */ | 993 | /* Enable class W */ |
@@ -1140,64 +1025,90 @@ static int wm8961_register(struct wm8961_priv *wm8961) | |||
1140 | 1025 | ||
1141 | wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1026 | wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1142 | 1027 | ||
1143 | wm8961_dai.dev = codec->dev; | 1028 | snd_soc_add_controls(codec, wm8961_snd_controls, |
1029 | ARRAY_SIZE(wm8961_snd_controls)); | ||
1030 | snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, | ||
1031 | ARRAY_SIZE(wm8961_dapm_widgets)); | ||
1032 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | ||
1144 | 1033 | ||
1145 | wm8961_codec = codec; | 1034 | return 0; |
1035 | } | ||
1146 | 1036 | ||
1147 | ret = snd_soc_register_codec(codec); | 1037 | static int wm8961_remove(struct snd_soc_codec *codec) |
1148 | if (ret != 0) { | 1038 | { |
1149 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | 1039 | wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1150 | goto err; | 1040 | return 0; |
1151 | } | 1041 | } |
1152 | 1042 | ||
1153 | ret = snd_soc_register_dai(&wm8961_dai); | 1043 | #ifdef CONFIG_PM |
1154 | if (ret != 0) { | 1044 | static int wm8961_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1155 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | 1045 | { |
1156 | goto err_codec; | 1046 | wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1157 | } | ||
1158 | 1047 | ||
1159 | return 0; | 1048 | return 0; |
1160 | |||
1161 | err_codec: | ||
1162 | snd_soc_unregister_codec(codec); | ||
1163 | err: | ||
1164 | kfree(wm8961); | ||
1165 | return ret; | ||
1166 | } | 1049 | } |
1167 | 1050 | ||
1168 | static void wm8961_unregister(struct wm8961_priv *wm8961) | 1051 | static int wm8961_resume(struct snd_soc_codec *codec) |
1169 | { | 1052 | { |
1170 | wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF); | 1053 | u16 *reg_cache = codec->reg_cache; |
1171 | snd_soc_unregister_dai(&wm8961_dai); | 1054 | int i; |
1172 | snd_soc_unregister_codec(&wm8961->codec); | 1055 | |
1173 | kfree(wm8961); | 1056 | for (i = 0; i < codec->driver->reg_cache_size; i++) { |
1174 | wm8961_codec = NULL; | 1057 | if (reg_cache[i] == wm8961_reg_defaults[i]) |
1058 | continue; | ||
1059 | |||
1060 | if (i == WM8961_SOFTWARE_RESET) | ||
1061 | continue; | ||
1062 | |||
1063 | snd_soc_write(codec, i, reg_cache[i]); | ||
1064 | } | ||
1065 | |||
1066 | wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1067 | |||
1068 | return 0; | ||
1175 | } | 1069 | } |
1070 | #else | ||
1071 | #define wm8961_suspend NULL | ||
1072 | #define wm8961_resume NULL | ||
1073 | #endif | ||
1176 | 1074 | ||
1075 | static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { | ||
1076 | .probe = wm8961_probe, | ||
1077 | .remove = wm8961_remove, | ||
1078 | .suspend = wm8961_suspend, | ||
1079 | .resume = wm8961_resume, | ||
1080 | .set_bias_level = wm8961_set_bias_level, | ||
1081 | .reg_cache_size = sizeof(wm8961_reg_defaults), | ||
1082 | .reg_word_size = sizeof(u16), | ||
1083 | .reg_cache_default = wm8961_reg_defaults, | ||
1084 | .volatile_register = wm8961_volatile_register, | ||
1085 | }; | ||
1086 | |||
1087 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1177 | static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, | 1088 | static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, |
1178 | const struct i2c_device_id *id) | 1089 | const struct i2c_device_id *id) |
1179 | { | 1090 | { |
1180 | struct wm8961_priv *wm8961; | 1091 | struct wm8961_priv *wm8961; |
1181 | struct snd_soc_codec *codec; | 1092 | int ret; |
1182 | 1093 | ||
1183 | wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL); | 1094 | wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL); |
1184 | if (wm8961 == NULL) | 1095 | if (wm8961 == NULL) |
1185 | return -ENOMEM; | 1096 | return -ENOMEM; |
1186 | 1097 | ||
1187 | codec = &wm8961->codec; | ||
1188 | |||
1189 | i2c_set_clientdata(i2c, wm8961); | 1098 | i2c_set_clientdata(i2c, wm8961); |
1190 | codec->control_data = i2c; | 1099 | wm8961->control_data = i2c; |
1191 | |||
1192 | codec->dev = &i2c->dev; | ||
1193 | 1100 | ||
1194 | return wm8961_register(wm8961); | 1101 | ret = snd_soc_register_codec(&i2c->dev, |
1102 | &soc_codec_dev_wm8961, &wm8961_dai, 1); | ||
1103 | if (ret < 0) | ||
1104 | kfree(wm8961); | ||
1105 | return ret; | ||
1195 | } | 1106 | } |
1196 | 1107 | ||
1197 | static __devexit int wm8961_i2c_remove(struct i2c_client *client) | 1108 | static __devexit int wm8961_i2c_remove(struct i2c_client *client) |
1198 | { | 1109 | { |
1199 | struct wm8961_priv *wm8961 = i2c_get_clientdata(client); | 1110 | snd_soc_unregister_codec(&client->dev); |
1200 | wm8961_unregister(wm8961); | 1111 | kfree(i2c_get_clientdata(client)); |
1201 | return 0; | 1112 | return 0; |
1202 | } | 1113 | } |
1203 | 1114 | ||
@@ -1209,35 +1120,37 @@ MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id); | |||
1209 | 1120 | ||
1210 | static struct i2c_driver wm8961_i2c_driver = { | 1121 | static struct i2c_driver wm8961_i2c_driver = { |
1211 | .driver = { | 1122 | .driver = { |
1212 | .name = "wm8961", | 1123 | .name = "wm8961-codec", |
1213 | .owner = THIS_MODULE, | 1124 | .owner = THIS_MODULE, |
1214 | }, | 1125 | }, |
1215 | .probe = wm8961_i2c_probe, | 1126 | .probe = wm8961_i2c_probe, |
1216 | .remove = __devexit_p(wm8961_i2c_remove), | 1127 | .remove = __devexit_p(wm8961_i2c_remove), |
1217 | .id_table = wm8961_i2c_id, | 1128 | .id_table = wm8961_i2c_id, |
1218 | }; | 1129 | }; |
1130 | #endif | ||
1219 | 1131 | ||
1220 | static int __init wm8961_modinit(void) | 1132 | static int __init wm8961_modinit(void) |
1221 | { | 1133 | { |
1222 | int ret; | 1134 | int ret = 0; |
1223 | 1135 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1224 | ret = i2c_add_driver(&wm8961_i2c_driver); | 1136 | ret = i2c_add_driver(&wm8961_i2c_driver); |
1225 | if (ret != 0) { | 1137 | if (ret != 0) { |
1226 | printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n", | 1138 | printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n", |
1227 | ret); | 1139 | ret); |
1228 | } | 1140 | } |
1229 | 1141 | #endif | |
1230 | return ret; | 1142 | return ret; |
1231 | } | 1143 | } |
1232 | module_init(wm8961_modinit); | 1144 | module_init(wm8961_modinit); |
1233 | 1145 | ||
1234 | static void __exit wm8961_exit(void) | 1146 | static void __exit wm8961_exit(void) |
1235 | { | 1147 | { |
1148 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1236 | i2c_del_driver(&wm8961_i2c_driver); | 1149 | i2c_del_driver(&wm8961_i2c_driver); |
1150 | #endif | ||
1237 | } | 1151 | } |
1238 | module_exit(wm8961_exit); | 1152 | module_exit(wm8961_exit); |
1239 | 1153 | ||
1240 | |||
1241 | MODULE_DESCRIPTION("ASoC WM8961 driver"); | 1154 | MODULE_DESCRIPTION("ASoC WM8961 driver"); |
1242 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 1155 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
1243 | MODULE_LICENSE("GPL"); | 1156 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8961.h b/sound/soc/codecs/wm8961.h index 5513bfd720d6..1d736e5701c8 100644 --- a/sound/soc/codecs/wm8961.h +++ b/sound/soc/codecs/wm8961.h | |||
@@ -11,9 +11,6 @@ | |||
11 | 11 | ||
12 | #include <sound/soc.h> | 12 | #include <sound/soc.h> |
13 | 13 | ||
14 | extern struct snd_soc_codec_device soc_codec_dev_wm8961; | ||
15 | extern struct snd_soc_dai wm8961_dai; | ||
16 | |||
17 | #define WM8961_BCLK 1 | 14 | #define WM8961_BCLK 1 |
18 | #define WM8961_LRCLK 2 | 15 | #define WM8961_LRCLK 2 |
19 | 16 | ||
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index a99620f335d2..ad2692afbb31 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -38,6 +38,8 @@ static struct workqueue_struct *wm8971_workq = NULL; | |||
38 | 38 | ||
39 | /* codec private data */ | 39 | /* codec private data */ |
40 | struct wm8971_priv { | 40 | struct wm8971_priv { |
41 | enum snd_soc_control_type control_type; | ||
42 | void *control_data; | ||
41 | unsigned int sysclk; | 43 | unsigned int sysclk; |
42 | }; | 44 | }; |
43 | 45 | ||
@@ -492,8 +494,7 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, | |||
492 | struct snd_soc_dai *dai) | 494 | struct snd_soc_dai *dai) |
493 | { | 495 | { |
494 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 496 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
495 | struct snd_soc_device *socdev = rtd->socdev; | 497 | struct snd_soc_codec *codec = rtd->codec; |
496 | struct snd_soc_codec *codec = socdev->card->codec; | ||
497 | struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); | 498 | struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); |
498 | u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3; | 499 | u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3; |
499 | u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0; | 500 | u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0; |
@@ -573,8 +574,8 @@ static struct snd_soc_dai_ops wm8971_dai_ops = { | |||
573 | .set_sysclk = wm8971_set_dai_sysclk, | 574 | .set_sysclk = wm8971_set_dai_sysclk, |
574 | }; | 575 | }; |
575 | 576 | ||
576 | struct snd_soc_dai wm8971_dai = { | 577 | static struct snd_soc_dai_driver wm8971_dai = { |
577 | .name = "WM8971", | 578 | .name = "wm8971-hifi", |
578 | .playback = { | 579 | .playback = { |
579 | .stream_name = "Playback", | 580 | .stream_name = "Playback", |
580 | .channels_min = 1, | 581 | .channels_min = 1, |
@@ -589,7 +590,6 @@ struct snd_soc_dai wm8971_dai = { | |||
589 | .formats = WM8971_FORMATS,}, | 590 | .formats = WM8971_FORMATS,}, |
590 | .ops = &wm8971_dai_ops, | 591 | .ops = &wm8971_dai_ops, |
591 | }; | 592 | }; |
592 | EXPORT_SYMBOL_GPL(wm8971_dai); | ||
593 | 593 | ||
594 | static void wm8971_work(struct work_struct *work) | 594 | static void wm8971_work(struct work_struct *work) |
595 | { | 595 | { |
@@ -598,19 +598,14 @@ static void wm8971_work(struct work_struct *work) | |||
598 | wm8971_set_bias_level(codec, codec->bias_level); | 598 | wm8971_set_bias_level(codec, codec->bias_level); |
599 | } | 599 | } |
600 | 600 | ||
601 | static int wm8971_suspend(struct platform_device *pdev, pm_message_t state) | 601 | static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state) |
602 | { | 602 | { |
603 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
604 | struct snd_soc_codec *codec = socdev->card->codec; | ||
605 | |||
606 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); | 603 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); |
607 | return 0; | 604 | return 0; |
608 | } | 605 | } |
609 | 606 | ||
610 | static int wm8971_resume(struct platform_device *pdev) | 607 | static int wm8971_resume(struct snd_soc_codec *codec) |
611 | { | 608 | { |
612 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
613 | struct snd_soc_codec *codec = socdev->card->codec; | ||
614 | int i; | 609 | int i; |
615 | u8 data[2]; | 610 | u8 data[2]; |
616 | u16 *cache = codec->reg_cache; | 611 | u16 *cache = codec->reg_cache; |
@@ -639,37 +634,27 @@ static int wm8971_resume(struct platform_device *pdev) | |||
639 | return 0; | 634 | return 0; |
640 | } | 635 | } |
641 | 636 | ||
642 | static int wm8971_init(struct snd_soc_device *socdev, | 637 | static int wm8971_probe(struct snd_soc_codec *codec) |
643 | enum snd_soc_control_type control) | ||
644 | { | 638 | { |
645 | struct snd_soc_codec *codec = socdev->card->codec; | 639 | struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); |
646 | int reg, ret = 0; | 640 | int ret = 0; |
647 | 641 | u16 reg; | |
648 | codec->name = "WM8971"; | 642 | |
649 | codec->owner = THIS_MODULE; | 643 | pr_info("WM8971 Audio Codec %s", WM8971_VERSION); |
650 | codec->set_bias_level = wm8971_set_bias_level; | ||
651 | codec->dai = &wm8971_dai; | ||
652 | codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); | ||
653 | codec->num_dai = 1; | ||
654 | codec->reg_cache = kmemdup(wm8971_reg, sizeof(wm8971_reg), GFP_KERNEL); | ||
655 | |||
656 | if (codec->reg_cache == NULL) | ||
657 | return -ENOMEM; | ||
658 | 644 | ||
659 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 645 | codec->control_data = wm8971->control_data; |
646 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type); | ||
660 | if (ret < 0) { | 647 | if (ret < 0) { |
661 | printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); | 648 | printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); |
662 | goto err; | 649 | return ret; |
663 | } | 650 | } |
664 | 651 | ||
665 | wm8971_reset(codec); | 652 | INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work); |
653 | wm8971_workq = create_workqueue("wm8971"); | ||
654 | if (wm8971_workq == NULL) | ||
655 | return -ENOMEM; | ||
666 | 656 | ||
667 | /* register pcms */ | 657 | wm8971_reset(codec); |
668 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
669 | if (ret < 0) { | ||
670 | printk(KERN_ERR "wm8971: failed to create pcms\n"); | ||
671 | goto err; | ||
672 | } | ||
673 | 658 | ||
674 | /* charge output caps - set vmid to 5k for quick power up */ | 659 | /* charge output caps - set vmid to 5k for quick power up */ |
675 | reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; | 660 | reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; |
@@ -704,40 +689,55 @@ static int wm8971_init(struct snd_soc_device *socdev, | |||
704 | wm8971_add_widgets(codec); | 689 | wm8971_add_widgets(codec); |
705 | 690 | ||
706 | return ret; | 691 | return ret; |
707 | |||
708 | err: | ||
709 | kfree(codec->reg_cache); | ||
710 | return ret; | ||
711 | } | 692 | } |
712 | 693 | ||
713 | /* If the i2c layer weren't so broken, we could pass this kind of data | ||
714 | around */ | ||
715 | static struct snd_soc_device *wm8971_socdev; | ||
716 | 694 | ||
717 | #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) | 695 | /* power down chip */ |
696 | static int wm8971_remove(struct snd_soc_codec *codec) | ||
697 | { | ||
698 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
699 | |||
700 | if (wm8971_workq) | ||
701 | destroy_workqueue(wm8971_workq); | ||
702 | return 0; | ||
703 | } | ||
704 | |||
705 | static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { | ||
706 | .probe = wm8971_probe, | ||
707 | .remove = wm8971_remove, | ||
708 | .suspend = wm8971_suspend, | ||
709 | .resume = wm8971_resume, | ||
710 | .set_bias_level = wm8971_set_bias_level, | ||
711 | .reg_cache_size = ARRAY_SIZE(wm8971_reg), | ||
712 | .reg_word_size = sizeof(u16), | ||
713 | .reg_cache_default = wm8971_reg, | ||
714 | }; | ||
718 | 715 | ||
719 | static int wm8971_i2c_probe(struct i2c_client *i2c, | 716 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
720 | const struct i2c_device_id *id) | 717 | static __devinit int wm8971_i2c_probe(struct i2c_client *i2c, |
718 | const struct i2c_device_id *id) | ||
721 | { | 719 | { |
722 | struct snd_soc_device *socdev = wm8971_socdev; | 720 | struct wm8971_priv *wm8971; |
723 | struct snd_soc_codec *codec = socdev->card->codec; | ||
724 | int ret; | 721 | int ret; |
725 | 722 | ||
726 | i2c_set_clientdata(i2c, codec); | 723 | wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL); |
724 | if (wm8971 == NULL) | ||
725 | return -ENOMEM; | ||
727 | 726 | ||
728 | codec->control_data = i2c; | 727 | i2c_set_clientdata(i2c, wm8971); |
728 | wm8971->control_data = i2c; | ||
729 | 729 | ||
730 | ret = wm8971_init(socdev, SND_SOC_I2C); | 730 | ret = snd_soc_register_codec(&i2c->dev, |
731 | &soc_codec_dev_wm8971, &wm8971_dai, 1); | ||
731 | if (ret < 0) | 732 | if (ret < 0) |
732 | pr_err("failed to initialise WM8971\n"); | 733 | kfree(wm8971); |
733 | |||
734 | return ret; | 734 | return ret; |
735 | } | 735 | } |
736 | 736 | ||
737 | static int wm8971_i2c_remove(struct i2c_client *client) | 737 | static __devexit int wm8971_i2c_remove(struct i2c_client *client) |
738 | { | 738 | { |
739 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 739 | snd_soc_unregister_codec(&client->dev); |
740 | kfree(codec->reg_cache); | 740 | kfree(i2c_get_clientdata(client)); |
741 | return 0; | 741 | return 0; |
742 | } | 742 | } |
743 | 743 | ||
@@ -749,148 +749,34 @@ MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id); | |||
749 | 749 | ||
750 | static struct i2c_driver wm8971_i2c_driver = { | 750 | static struct i2c_driver wm8971_i2c_driver = { |
751 | .driver = { | 751 | .driver = { |
752 | .name = "WM8971 I2C Codec", | 752 | .name = "wm8971-codec", |
753 | .owner = THIS_MODULE, | 753 | .owner = THIS_MODULE, |
754 | }, | 754 | }, |
755 | .probe = wm8971_i2c_probe, | 755 | .probe = wm8971_i2c_probe, |
756 | .remove = wm8971_i2c_remove, | 756 | .remove = __devexit_p(wm8971_i2c_remove), |
757 | .id_table = wm8971_i2c_id, | 757 | .id_table = wm8971_i2c_id, |
758 | }; | 758 | }; |
759 | |||
760 | static int wm8971_add_i2c_device(struct platform_device *pdev, | ||
761 | const struct wm8971_setup_data *setup) | ||
762 | { | ||
763 | struct i2c_board_info info; | ||
764 | struct i2c_adapter *adapter; | ||
765 | struct i2c_client *client; | ||
766 | int ret; | ||
767 | |||
768 | ret = i2c_add_driver(&wm8971_i2c_driver); | ||
769 | if (ret != 0) { | ||
770 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
771 | return ret; | ||
772 | } | ||
773 | |||
774 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
775 | info.addr = setup->i2c_address; | ||
776 | strlcpy(info.type, "wm8971", I2C_NAME_SIZE); | ||
777 | |||
778 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
779 | if (!adapter) { | ||
780 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
781 | setup->i2c_bus); | ||
782 | goto err_driver; | ||
783 | } | ||
784 | |||
785 | client = i2c_new_device(adapter, &info); | ||
786 | i2c_put_adapter(adapter); | ||
787 | if (!client) { | ||
788 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
789 | (unsigned int)info.addr); | ||
790 | goto err_driver; | ||
791 | } | ||
792 | |||
793 | return 0; | ||
794 | |||
795 | err_driver: | ||
796 | i2c_del_driver(&wm8971_i2c_driver); | ||
797 | return -ENODEV; | ||
798 | } | ||
799 | |||
800 | #endif | 759 | #endif |
801 | 760 | ||
802 | static int wm8971_probe(struct platform_device *pdev) | 761 | static int __init wm8971_modinit(void) |
803 | { | 762 | { |
804 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
805 | struct wm8971_setup_data *setup; | ||
806 | struct snd_soc_codec *codec; | ||
807 | struct wm8971_priv *wm8971; | ||
808 | int ret = 0; | 763 | int ret = 0; |
809 | 764 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
810 | pr_info("WM8971 Audio Codec %s", WM8971_VERSION); | 765 | ret = i2c_add_driver(&wm8971_i2c_driver); |
811 | |||
812 | setup = socdev->codec_data; | ||
813 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
814 | if (codec == NULL) | ||
815 | return -ENOMEM; | ||
816 | |||
817 | wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL); | ||
818 | if (wm8971 == NULL) { | ||
819 | kfree(codec); | ||
820 | return -ENOMEM; | ||
821 | } | ||
822 | |||
823 | snd_soc_codec_set_drvdata(codec, wm8971); | ||
824 | socdev->card->codec = codec; | ||
825 | mutex_init(&codec->mutex); | ||
826 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
827 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
828 | wm8971_socdev = socdev; | ||
829 | |||
830 | INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work); | ||
831 | wm8971_workq = create_workqueue("wm8971"); | ||
832 | if (wm8971_workq == NULL) { | ||
833 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
834 | kfree(codec); | ||
835 | return -ENOMEM; | ||
836 | } | ||
837 | |||
838 | #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) | ||
839 | if (setup->i2c_address) { | ||
840 | ret = wm8971_add_i2c_device(pdev, setup); | ||
841 | } | ||
842 | #endif | ||
843 | /* Add other interfaces here */ | ||
844 | |||
845 | if (ret != 0) { | 766 | if (ret != 0) { |
846 | destroy_workqueue(wm8971_workq); | 767 | printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n", |
847 | kfree(snd_soc_codec_get_drvdata(codec)); | 768 | ret); |
848 | kfree(codec); | ||
849 | } | 769 | } |
850 | |||
851 | return ret; | ||
852 | } | ||
853 | |||
854 | /* power down chip */ | ||
855 | static int wm8971_remove(struct platform_device *pdev) | ||
856 | { | ||
857 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
858 | struct snd_soc_codec *codec = socdev->card->codec; | ||
859 | |||
860 | if (codec->control_data) | ||
861 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
862 | if (wm8971_workq) | ||
863 | destroy_workqueue(wm8971_workq); | ||
864 | snd_soc_free_pcms(socdev); | ||
865 | snd_soc_dapm_free(socdev); | ||
866 | #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) | ||
867 | i2c_unregister_device(codec->control_data); | ||
868 | i2c_del_driver(&wm8971_i2c_driver); | ||
869 | #endif | 770 | #endif |
870 | kfree(snd_soc_codec_get_drvdata(codec)); | 771 | return ret; |
871 | kfree(codec); | ||
872 | |||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | struct snd_soc_codec_device soc_codec_dev_wm8971 = { | ||
877 | .probe = wm8971_probe, | ||
878 | .remove = wm8971_remove, | ||
879 | .suspend = wm8971_suspend, | ||
880 | .resume = wm8971_resume, | ||
881 | }; | ||
882 | |||
883 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971); | ||
884 | |||
885 | static int __init wm8971_modinit(void) | ||
886 | { | ||
887 | return snd_soc_register_dai(&wm8971_dai); | ||
888 | } | 772 | } |
889 | module_init(wm8971_modinit); | 773 | module_init(wm8971_modinit); |
890 | 774 | ||
891 | static void __exit wm8971_exit(void) | 775 | static void __exit wm8971_exit(void) |
892 | { | 776 | { |
893 | snd_soc_unregister_dai(&wm8971_dai); | 777 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
778 | i2c_del_driver(&wm8971_i2c_driver); | ||
779 | #endif | ||
894 | } | 780 | } |
895 | module_exit(wm8971_exit); | 781 | module_exit(wm8971_exit); |
896 | 782 | ||
diff --git a/sound/soc/codecs/wm8971.h b/sound/soc/codecs/wm8971.h index ef4f08f9f344..f31c38fddfc4 100644 --- a/sound/soc/codecs/wm8971.h +++ b/sound/soc/codecs/wm8971.h | |||
@@ -53,12 +53,4 @@ | |||
53 | 53 | ||
54 | #define WM8971_SYSCLK 0 | 54 | #define WM8971_SYSCLK 0 |
55 | 55 | ||
56 | struct wm8971_setup_data { | ||
57 | int i2c_bus; | ||
58 | unsigned short i2c_address; | ||
59 | }; | ||
60 | |||
61 | extern struct snd_soc_dai wm8971_dai; | ||
62 | extern struct snd_soc_codec_device soc_codec_dev_wm8971; | ||
63 | |||
64 | #endif | 56 | #endif |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 1468fe10cbbe..52f631c62e29 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -51,12 +51,11 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = { | |||
51 | #define WM8974_POWER1_BUFIOEN 0x04 | 51 | #define WM8974_POWER1_BUFIOEN 0x04 |
52 | 52 | ||
53 | struct wm8974_priv { | 53 | struct wm8974_priv { |
54 | struct snd_soc_codec codec; | 54 | enum snd_soc_control_type control_type; |
55 | void *control_data; | ||
55 | u16 reg_cache[WM8974_CACHEREGNUM]; | 56 | u16 reg_cache[WM8974_CACHEREGNUM]; |
56 | }; | 57 | }; |
57 | 58 | ||
58 | static struct snd_soc_codec *wm8974_codec; | ||
59 | |||
60 | #define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0) | 59 | #define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0) |
61 | 60 | ||
62 | static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" }; | 61 | static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" }; |
@@ -566,8 +565,8 @@ static struct snd_soc_dai_ops wm8974_ops = { | |||
566 | .set_pll = wm8974_set_dai_pll, | 565 | .set_pll = wm8974_set_dai_pll, |
567 | }; | 566 | }; |
568 | 567 | ||
569 | struct snd_soc_dai wm8974_dai = { | 568 | static struct snd_soc_dai_driver wm8974_dai = { |
570 | .name = "WM8974 HiFi", | 569 | .name = "wm8974-hifi", |
571 | .playback = { | 570 | .playback = { |
572 | .stream_name = "Playback", | 571 | .stream_name = "Playback", |
573 | .channels_min = 1, | 572 | .channels_min = 1, |
@@ -583,21 +582,15 @@ struct snd_soc_dai wm8974_dai = { | |||
583 | .ops = &wm8974_ops, | 582 | .ops = &wm8974_ops, |
584 | .symmetric_rates = 1, | 583 | .symmetric_rates = 1, |
585 | }; | 584 | }; |
586 | EXPORT_SYMBOL_GPL(wm8974_dai); | ||
587 | 585 | ||
588 | static int wm8974_suspend(struct platform_device *pdev, pm_message_t state) | 586 | static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state) |
589 | { | 587 | { |
590 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
591 | struct snd_soc_codec *codec = socdev->card->codec; | ||
592 | |||
593 | wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); | 588 | wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); |
594 | return 0; | 589 | return 0; |
595 | } | 590 | } |
596 | 591 | ||
597 | static int wm8974_resume(struct platform_device *pdev) | 592 | static int wm8974_resume(struct snd_soc_codec *codec) |
598 | { | 593 | { |
599 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
600 | struct snd_soc_codec *codec = socdev->card->codec; | ||
601 | int i; | 594 | int i; |
602 | u8 data[2]; | 595 | u8 data[2]; |
603 | u16 *cache = codec->reg_cache; | 596 | u16 *cache = codec->reg_cache; |
@@ -613,156 +606,75 @@ static int wm8974_resume(struct platform_device *pdev) | |||
613 | return 0; | 606 | return 0; |
614 | } | 607 | } |
615 | 608 | ||
616 | static int wm8974_probe(struct platform_device *pdev) | 609 | static int wm8974_probe(struct snd_soc_codec *codec) |
617 | { | 610 | { |
618 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 611 | struct wm8974_priv *wm8974 = snd_soc_codec_get_drvdata(codec); |
619 | struct snd_soc_codec *codec; | ||
620 | int ret = 0; | 612 | int ret = 0; |
621 | 613 | ||
622 | if (wm8974_codec == NULL) { | 614 | codec->control_data = wm8974->control_data; |
623 | dev_err(&pdev->dev, "Codec device not registered\n"); | 615 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); |
624 | return -ENODEV; | 616 | if (ret < 0) { |
617 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
618 | return ret; | ||
625 | } | 619 | } |
626 | 620 | ||
627 | socdev->card->codec = wm8974_codec; | 621 | ret = wm8974_reset(codec); |
628 | codec = wm8974_codec; | ||
629 | |||
630 | /* register pcms */ | ||
631 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
632 | if (ret < 0) { | 622 | if (ret < 0) { |
633 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | 623 | dev_err(codec->dev, "Failed to issue reset\n"); |
634 | goto pcm_err; | 624 | return ret; |
635 | } | 625 | } |
636 | 626 | ||
627 | wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
637 | snd_soc_add_controls(codec, wm8974_snd_controls, | 628 | snd_soc_add_controls(codec, wm8974_snd_controls, |
638 | ARRAY_SIZE(wm8974_snd_controls)); | 629 | ARRAY_SIZE(wm8974_snd_controls)); |
639 | wm8974_add_widgets(codec); | 630 | wm8974_add_widgets(codec); |
640 | 631 | ||
641 | return ret; | 632 | return ret; |
642 | |||
643 | pcm_err: | ||
644 | return ret; | ||
645 | } | 633 | } |
646 | 634 | ||
647 | /* power down chip */ | 635 | /* power down chip */ |
648 | static int wm8974_remove(struct platform_device *pdev) | 636 | static int wm8974_remove(struct snd_soc_codec *codec) |
649 | { | 637 | { |
650 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 638 | wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); |
651 | |||
652 | snd_soc_free_pcms(socdev); | ||
653 | snd_soc_dapm_free(socdev); | ||
654 | |||
655 | return 0; | 639 | return 0; |
656 | } | 640 | } |
657 | 641 | ||
658 | struct snd_soc_codec_device soc_codec_dev_wm8974 = { | 642 | static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { |
659 | .probe = wm8974_probe, | 643 | .probe = wm8974_probe, |
660 | .remove = wm8974_remove, | 644 | .remove = wm8974_remove, |
661 | .suspend = wm8974_suspend, | 645 | .suspend = wm8974_suspend, |
662 | .resume = wm8974_resume, | 646 | .resume = wm8974_resume, |
647 | .set_bias_level = wm8974_set_bias_level, | ||
648 | .reg_cache_size = ARRAY_SIZE(wm8974_reg), | ||
649 | .reg_word_size = sizeof(u16), | ||
650 | .reg_cache_default = wm8974_reg, | ||
663 | }; | 651 | }; |
664 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8974); | ||
665 | |||
666 | static __devinit int wm8974_register(struct wm8974_priv *wm8974) | ||
667 | { | ||
668 | int ret; | ||
669 | struct snd_soc_codec *codec = &wm8974->codec; | ||
670 | |||
671 | if (wm8974_codec) { | ||
672 | dev_err(codec->dev, "Another WM8974 is registered\n"); | ||
673 | ret = -EINVAL; | ||
674 | goto err; | ||
675 | } | ||
676 | |||
677 | mutex_init(&codec->mutex); | ||
678 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
679 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
680 | |||
681 | snd_soc_codec_set_drvdata(codec, wm8974); | ||
682 | codec->name = "WM8974"; | ||
683 | codec->owner = THIS_MODULE; | ||
684 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
685 | codec->set_bias_level = wm8974_set_bias_level; | ||
686 | codec->dai = &wm8974_dai; | ||
687 | codec->num_dai = 1; | ||
688 | codec->reg_cache_size = WM8974_CACHEREGNUM; | ||
689 | codec->reg_cache = &wm8974->reg_cache; | ||
690 | |||
691 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); | ||
692 | if (ret < 0) { | ||
693 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
694 | goto err; | ||
695 | } | ||
696 | |||
697 | memcpy(codec->reg_cache, wm8974_reg, sizeof(wm8974_reg)); | ||
698 | |||
699 | ret = wm8974_reset(codec); | ||
700 | if (ret < 0) { | ||
701 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
702 | goto err; | ||
703 | } | ||
704 | |||
705 | wm8974_dai.dev = codec->dev; | ||
706 | |||
707 | wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
708 | |||
709 | wm8974_codec = codec; | ||
710 | |||
711 | ret = snd_soc_register_codec(codec); | ||
712 | if (ret != 0) { | ||
713 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
714 | goto err; | ||
715 | } | ||
716 | |||
717 | ret = snd_soc_register_dai(&wm8974_dai); | ||
718 | if (ret != 0) { | ||
719 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
720 | goto err_codec; | ||
721 | } | ||
722 | |||
723 | return 0; | ||
724 | |||
725 | err_codec: | ||
726 | snd_soc_unregister_codec(codec); | ||
727 | err: | ||
728 | kfree(wm8974); | ||
729 | return ret; | ||
730 | } | ||
731 | |||
732 | static __devexit void wm8974_unregister(struct wm8974_priv *wm8974) | ||
733 | { | ||
734 | wm8974_set_bias_level(&wm8974->codec, SND_SOC_BIAS_OFF); | ||
735 | snd_soc_unregister_dai(&wm8974_dai); | ||
736 | snd_soc_unregister_codec(&wm8974->codec); | ||
737 | kfree(wm8974); | ||
738 | wm8974_codec = NULL; | ||
739 | } | ||
740 | 652 | ||
653 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
741 | static __devinit int wm8974_i2c_probe(struct i2c_client *i2c, | 654 | static __devinit int wm8974_i2c_probe(struct i2c_client *i2c, |
742 | const struct i2c_device_id *id) | 655 | const struct i2c_device_id *id) |
743 | { | 656 | { |
744 | struct wm8974_priv *wm8974; | 657 | struct wm8974_priv *wm8974; |
745 | struct snd_soc_codec *codec; | 658 | int ret; |
746 | 659 | ||
747 | wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL); | 660 | wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL); |
748 | if (wm8974 == NULL) | 661 | if (wm8974 == NULL) |
749 | return -ENOMEM; | 662 | return -ENOMEM; |
750 | 663 | ||
751 | codec = &wm8974->codec; | ||
752 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
753 | |||
754 | i2c_set_clientdata(i2c, wm8974); | 664 | i2c_set_clientdata(i2c, wm8974); |
755 | codec->control_data = i2c; | 665 | wm8974->control_data = i2c; |
756 | |||
757 | codec->dev = &i2c->dev; | ||
758 | 666 | ||
759 | return wm8974_register(wm8974); | 667 | ret = snd_soc_register_codec(&i2c->dev, |
668 | &soc_codec_dev_wm8974, &wm8974_dai, 1); | ||
669 | if (ret < 0) | ||
670 | kfree(wm8974); | ||
671 | return ret; | ||
760 | } | 672 | } |
761 | 673 | ||
762 | static __devexit int wm8974_i2c_remove(struct i2c_client *client) | 674 | static __devexit int wm8974_i2c_remove(struct i2c_client *client) |
763 | { | 675 | { |
764 | struct wm8974_priv *wm8974 = i2c_get_clientdata(client); | 676 | snd_soc_unregister_codec(&client->dev); |
765 | wm8974_unregister(wm8974); | 677 | kfree(i2c_get_clientdata(client)); |
766 | return 0; | 678 | return 0; |
767 | } | 679 | } |
768 | 680 | ||
@@ -774,23 +686,34 @@ MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id); | |||
774 | 686 | ||
775 | static struct i2c_driver wm8974_i2c_driver = { | 687 | static struct i2c_driver wm8974_i2c_driver = { |
776 | .driver = { | 688 | .driver = { |
777 | .name = "WM8974", | 689 | .name = "wm8974-codec", |
778 | .owner = THIS_MODULE, | 690 | .owner = THIS_MODULE, |
779 | }, | 691 | }, |
780 | .probe = wm8974_i2c_probe, | 692 | .probe = wm8974_i2c_probe, |
781 | .remove = __devexit_p(wm8974_i2c_remove), | 693 | .remove = __devexit_p(wm8974_i2c_remove), |
782 | .id_table = wm8974_i2c_id, | 694 | .id_table = wm8974_i2c_id, |
783 | }; | 695 | }; |
696 | #endif | ||
784 | 697 | ||
785 | static int __init wm8974_modinit(void) | 698 | static int __init wm8974_modinit(void) |
786 | { | 699 | { |
787 | return i2c_add_driver(&wm8974_i2c_driver); | 700 | int ret = 0; |
701 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
702 | ret = i2c_add_driver(&wm8974_i2c_driver); | ||
703 | if (ret != 0) { | ||
704 | printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n", | ||
705 | ret); | ||
706 | } | ||
707 | #endif | ||
708 | return ret; | ||
788 | } | 709 | } |
789 | module_init(wm8974_modinit); | 710 | module_init(wm8974_modinit); |
790 | 711 | ||
791 | static void __exit wm8974_exit(void) | 712 | static void __exit wm8974_exit(void) |
792 | { | 713 | { |
714 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
793 | i2c_del_driver(&wm8974_i2c_driver); | 715 | i2c_del_driver(&wm8974_i2c_driver); |
716 | #endif | ||
794 | } | 717 | } |
795 | module_exit(wm8974_exit); | 718 | module_exit(wm8974_exit); |
796 | 719 | ||
diff --git a/sound/soc/codecs/wm8974.h b/sound/soc/codecs/wm8974.h index 896a7f0f3fc4..3c94e7bb55a6 100644 --- a/sound/soc/codecs/wm8974.h +++ b/sound/soc/codecs/wm8974.h | |||
@@ -83,7 +83,4 @@ | |||
83 | #define WM8974_MCLKDIV_8 (6 << 5) | 83 | #define WM8974_MCLKDIV_8 (6 << 5) |
84 | #define WM8974_MCLKDIV_12 (7 << 5) | 84 | #define WM8974_MCLKDIV_12 (7 << 5) |
85 | 85 | ||
86 | extern struct snd_soc_dai wm8974_dai; | ||
87 | extern struct snd_soc_codec_device soc_codec_dev_wm8974; | ||
88 | |||
89 | #endif | 86 | #endif |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 8a1ad778e7e3..676a4306cc87 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -31,8 +31,6 @@ | |||
31 | 31 | ||
32 | #include "wm8978.h" | 32 | #include "wm8978.h" |
33 | 33 | ||
34 | static struct snd_soc_codec *wm8978_codec; | ||
35 | |||
36 | /* wm8978 register cache. Note that register 0 is not included in the cache. */ | 34 | /* wm8978 register cache. Note that register 0 is not included in the cache. */ |
37 | static const u16 wm8978_reg[WM8978_CACHEREGNUM] = { | 35 | static const u16 wm8978_reg[WM8978_CACHEREGNUM] = { |
38 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */ | 36 | 0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */ |
@@ -54,7 +52,8 @@ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = { | |||
54 | 52 | ||
55 | /* codec private data */ | 53 | /* codec private data */ |
56 | struct wm8978_priv { | 54 | struct wm8978_priv { |
57 | struct snd_soc_codec codec; | 55 | enum snd_soc_control_type control_type; |
56 | void *control_data; | ||
58 | unsigned int f_pllout; | 57 | unsigned int f_pllout; |
59 | unsigned int f_mclk; | 58 | unsigned int f_mclk; |
60 | unsigned int f_256fs; | 59 | unsigned int f_256fs; |
@@ -374,8 +373,8 @@ struct wm8978_pll_div { | |||
374 | 373 | ||
375 | #define FIXED_PLL_SIZE (1 << 24) | 374 | #define FIXED_PLL_SIZE (1 << 24) |
376 | 375 | ||
377 | static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target, | 376 | static void pll_factors(struct snd_soc_codec *codec, |
378 | unsigned int source) | 377 | struct wm8978_pll_div *pll_div, unsigned int target, unsigned int source) |
379 | { | 378 | { |
380 | u64 k_part; | 379 | u64 k_part; |
381 | unsigned int k, n_div, n_mod; | 380 | unsigned int k, n_div, n_mod; |
@@ -390,7 +389,7 @@ static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target, | |||
390 | } | 389 | } |
391 | 390 | ||
392 | if (n_div < 6 || n_div > 12) | 391 | if (n_div < 6 || n_div > 12) |
393 | dev_warn(wm8978_codec->dev, | 392 | dev_warn(codec->dev, |
394 | "WM8978 N value exceeds recommended range! N = %u\n", | 393 | "WM8978 N value exceeds recommended range! N = %u\n", |
395 | n_div); | 394 | n_div); |
396 | 395 | ||
@@ -505,7 +504,7 @@ static int wm8978_configure_pll(struct snd_soc_codec *codec) | |||
505 | dev_dbg(codec->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__, | 504 | dev_dbg(codec->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__, |
506 | wm8978->f_mclk, wm8978->f_pllout); | 505 | wm8978->f_mclk, wm8978->f_pllout); |
507 | 506 | ||
508 | pll_factors(&pll_div, f2, wm8978->f_mclk); | 507 | pll_factors(codec, &pll_div, f2, wm8978->f_mclk); |
509 | 508 | ||
510 | dev_dbg(codec->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n", | 509 | dev_dbg(codec->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n", |
511 | __func__, pll_div.n, pll_div.k, pll_div.div2); | 510 | __func__, pll_div.n, pll_div.k, pll_div.div2); |
@@ -690,8 +689,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, | |||
690 | struct snd_soc_dai *dai) | 689 | struct snd_soc_dai *dai) |
691 | { | 690 | { |
692 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 691 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
693 | struct snd_soc_device *socdev = rtd->socdev; | 692 | struct snd_soc_codec *codec = rtd->codec; |
694 | struct snd_soc_codec *codec = socdev->card->codec; | ||
695 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); | 693 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); |
696 | /* Word length mask = 0x60 */ | 694 | /* Word length mask = 0x60 */ |
697 | u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60; | 695 | u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60; |
@@ -875,9 +873,8 @@ static struct snd_soc_dai_ops wm8978_dai_ops = { | |||
875 | }; | 873 | }; |
876 | 874 | ||
877 | /* Also supports 12kHz */ | 875 | /* Also supports 12kHz */ |
878 | struct snd_soc_dai wm8978_dai = { | 876 | static struct snd_soc_dai_driver wm8978_dai = { |
879 | .name = "WM8978 HiFi", | 877 | .name = "wm8978-hifi", |
880 | .id = 1, | ||
881 | .playback = { | 878 | .playback = { |
882 | .stream_name = "Playback", | 879 | .stream_name = "Playback", |
883 | .channels_min = 1, | 880 | .channels_min = 1, |
@@ -894,13 +891,9 @@ struct snd_soc_dai wm8978_dai = { | |||
894 | }, | 891 | }, |
895 | .ops = &wm8978_dai_ops, | 892 | .ops = &wm8978_dai_ops, |
896 | }; | 893 | }; |
897 | EXPORT_SYMBOL_GPL(wm8978_dai); | ||
898 | 894 | ||
899 | static int wm8978_suspend(struct platform_device *pdev, pm_message_t state) | 895 | static int wm8978_suspend(struct snd_soc_codec *codec, pm_message_t state) |
900 | { | 896 | { |
901 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
902 | struct snd_soc_codec *codec = socdev->card->codec; | ||
903 | |||
904 | wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); | 897 | wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); |
905 | /* Also switch PLL off */ | 898 | /* Also switch PLL off */ |
906 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0); | 899 | snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0); |
@@ -908,10 +901,8 @@ static int wm8978_suspend(struct platform_device *pdev, pm_message_t state) | |||
908 | return 0; | 901 | return 0; |
909 | } | 902 | } |
910 | 903 | ||
911 | static int wm8978_resume(struct platform_device *pdev) | 904 | static int wm8978_resume(struct snd_soc_codec *codec) |
912 | { | 905 | { |
913 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
914 | struct snd_soc_codec *codec = socdev->card->codec; | ||
915 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); | 906 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); |
916 | int i; | 907 | int i; |
917 | u16 *cache = codec->reg_cache; | 908 | u16 *cache = codec->reg_cache; |
@@ -933,54 +924,6 @@ static int wm8978_resume(struct platform_device *pdev) | |||
933 | return 0; | 924 | return 0; |
934 | } | 925 | } |
935 | 926 | ||
936 | static int wm8978_probe(struct platform_device *pdev) | ||
937 | { | ||
938 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
939 | struct snd_soc_codec *codec; | ||
940 | int ret = 0; | ||
941 | |||
942 | if (wm8978_codec == NULL) { | ||
943 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
944 | return -ENODEV; | ||
945 | } | ||
946 | |||
947 | socdev->card->codec = wm8978_codec; | ||
948 | codec = wm8978_codec; | ||
949 | |||
950 | /* register pcms */ | ||
951 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
952 | if (ret < 0) { | ||
953 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
954 | goto pcm_err; | ||
955 | } | ||
956 | |||
957 | snd_soc_add_controls(codec, wm8978_snd_controls, | ||
958 | ARRAY_SIZE(wm8978_snd_controls)); | ||
959 | wm8978_add_widgets(codec); | ||
960 | |||
961 | pcm_err: | ||
962 | return ret; | ||
963 | } | ||
964 | |||
965 | /* power down chip */ | ||
966 | static int wm8978_remove(struct platform_device *pdev) | ||
967 | { | ||
968 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
969 | |||
970 | snd_soc_free_pcms(socdev); | ||
971 | snd_soc_dapm_free(socdev); | ||
972 | |||
973 | return 0; | ||
974 | } | ||
975 | |||
976 | struct snd_soc_codec_device soc_codec_dev_wm8978 = { | ||
977 | .probe = wm8978_probe, | ||
978 | .remove = wm8978_remove, | ||
979 | .suspend = wm8978_suspend, | ||
980 | .resume = wm8978_resume, | ||
981 | }; | ||
982 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8978); | ||
983 | |||
984 | /* | 927 | /* |
985 | * These registers contain an "update" bit - bit 8. This means, for example, | 928 | * These registers contain an "update" bit - bit 8. This means, for example, |
986 | * that one can write new DAC digital volume for both channels, but only when | 929 | * that one can write new DAC digital volume for both channels, but only when |
@@ -1000,44 +943,23 @@ static const int update_reg[] = { | |||
1000 | WM8978_ROUT2_SPK_CONTROL, | 943 | WM8978_ROUT2_SPK_CONTROL, |
1001 | }; | 944 | }; |
1002 | 945 | ||
1003 | static __devinit int wm8978_register(struct wm8978_priv *wm8978) | 946 | static int wm8978_probe(struct snd_soc_codec *codec) |
1004 | { | 947 | { |
1005 | int ret, i; | 948 | struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); |
1006 | struct snd_soc_codec *codec = &wm8978->codec; | 949 | int ret = 0, i; |
1007 | |||
1008 | if (wm8978_codec) { | ||
1009 | dev_err(codec->dev, "Another WM8978 is registered\n"); | ||
1010 | return -EINVAL; | ||
1011 | } | ||
1012 | 950 | ||
1013 | /* | 951 | /* |
1014 | * Set default system clock to PLL, it is more precise, this is also the | 952 | * Set default system clock to PLL, it is more precise, this is also the |
1015 | * default hardware setting | 953 | * default hardware setting |
1016 | */ | 954 | */ |
1017 | wm8978->sysclk = WM8978_PLL; | 955 | wm8978->sysclk = WM8978_PLL; |
1018 | 956 | codec->control_data = wm8978->control_data; | |
1019 | mutex_init(&codec->mutex); | ||
1020 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1021 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1022 | |||
1023 | snd_soc_codec_set_drvdata(codec, wm8978); | ||
1024 | codec->name = "WM8978"; | ||
1025 | codec->owner = THIS_MODULE; | ||
1026 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1027 | codec->set_bias_level = wm8978_set_bias_level; | ||
1028 | codec->dai = &wm8978_dai; | ||
1029 | codec->num_dai = 1; | ||
1030 | codec->reg_cache_size = WM8978_CACHEREGNUM; | ||
1031 | codec->reg_cache = &wm8978->reg_cache; | ||
1032 | |||
1033 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); | 957 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); |
1034 | if (ret < 0) { | 958 | if (ret < 0) { |
1035 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 959 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1036 | goto err; | 960 | return ret; |
1037 | } | 961 | } |
1038 | 962 | ||
1039 | memcpy(codec->reg_cache, wm8978_reg, sizeof(wm8978_reg)); | ||
1040 | |||
1041 | /* | 963 | /* |
1042 | * Set the update bit in all registers, that have one. This way all | 964 | * Set the update bit in all registers, that have one. This way all |
1043 | * writes to those registers will also cause the update bit to be | 965 | * writes to those registers will also cause the update bit to be |
@@ -1050,74 +972,61 @@ static __devinit int wm8978_register(struct wm8978_priv *wm8978) | |||
1050 | ret = snd_soc_write(codec, WM8978_RESET, 0); | 972 | ret = snd_soc_write(codec, WM8978_RESET, 0); |
1051 | if (ret < 0) { | 973 | if (ret < 0) { |
1052 | dev_err(codec->dev, "Failed to issue reset\n"); | 974 | dev_err(codec->dev, "Failed to issue reset\n"); |
1053 | goto err; | 975 | return ret; |
1054 | } | 976 | } |
1055 | 977 | ||
1056 | wm8978_dai.dev = codec->dev; | ||
1057 | |||
1058 | wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 978 | wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1059 | 979 | ||
1060 | wm8978_codec = codec; | 980 | snd_soc_add_controls(codec, wm8978_snd_controls, |
1061 | 981 | ARRAY_SIZE(wm8978_snd_controls)); | |
1062 | ret = snd_soc_register_codec(codec); | 982 | wm8978_add_widgets(codec); |
1063 | if (ret != 0) { | ||
1064 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1065 | goto err; | ||
1066 | } | ||
1067 | |||
1068 | ret = snd_soc_register_dai(&wm8978_dai); | ||
1069 | if (ret != 0) { | ||
1070 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1071 | goto err_codec; | ||
1072 | } | ||
1073 | 983 | ||
1074 | return 0; | 984 | return 0; |
1075 | |||
1076 | err_codec: | ||
1077 | snd_soc_unregister_codec(codec); | ||
1078 | err: | ||
1079 | return ret; | ||
1080 | } | 985 | } |
1081 | 986 | ||
1082 | static __devexit void wm8978_unregister(struct wm8978_priv *wm8978) | 987 | /* power down chip */ |
988 | static int wm8978_remove(struct snd_soc_codec *codec) | ||
1083 | { | 989 | { |
1084 | wm8978_set_bias_level(&wm8978->codec, SND_SOC_BIAS_OFF); | 990 | wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1085 | snd_soc_unregister_dai(&wm8978_dai); | 991 | return 0; |
1086 | snd_soc_unregister_codec(&wm8978->codec); | ||
1087 | wm8978_codec = NULL; | ||
1088 | } | 992 | } |
1089 | 993 | ||
994 | static struct snd_soc_codec_driver soc_codec_dev_wm8978 = { | ||
995 | .probe = wm8978_probe, | ||
996 | .remove = wm8978_remove, | ||
997 | .suspend = wm8978_suspend, | ||
998 | .resume = wm8978_resume, | ||
999 | .set_bias_level = wm8978_set_bias_level, | ||
1000 | .reg_cache_size = ARRAY_SIZE(wm8978_reg), | ||
1001 | .reg_word_size = sizeof(u16), | ||
1002 | .reg_cache_default = wm8978_reg, | ||
1003 | }; | ||
1004 | |||
1005 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1090 | static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, | 1006 | static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, |
1091 | const struct i2c_device_id *id) | 1007 | const struct i2c_device_id *id) |
1092 | { | 1008 | { |
1093 | int ret; | ||
1094 | struct wm8978_priv *wm8978; | 1009 | struct wm8978_priv *wm8978; |
1095 | struct snd_soc_codec *codec; | 1010 | int ret; |
1096 | 1011 | ||
1097 | wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL); | 1012 | wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL); |
1098 | if (wm8978 == NULL) | 1013 | if (wm8978 == NULL) |
1099 | return -ENOMEM; | 1014 | return -ENOMEM; |
1100 | 1015 | ||
1101 | codec = &wm8978->codec; | ||
1102 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1103 | |||
1104 | i2c_set_clientdata(i2c, wm8978); | 1016 | i2c_set_clientdata(i2c, wm8978); |
1105 | codec->control_data = i2c; | 1017 | wm8978->control_data = i2c; |
1106 | |||
1107 | codec->dev = &i2c->dev; | ||
1108 | 1018 | ||
1109 | ret = wm8978_register(wm8978); | 1019 | ret = snd_soc_register_codec(&i2c->dev, |
1020 | &soc_codec_dev_wm8978, &wm8978_dai, 1); | ||
1110 | if (ret < 0) | 1021 | if (ret < 0) |
1111 | kfree(wm8978); | 1022 | kfree(wm8978); |
1112 | |||
1113 | return ret; | 1023 | return ret; |
1114 | } | 1024 | } |
1115 | 1025 | ||
1116 | static __devexit int wm8978_i2c_remove(struct i2c_client *client) | 1026 | static __devexit int wm8978_i2c_remove(struct i2c_client *client) |
1117 | { | 1027 | { |
1118 | struct wm8978_priv *wm8978 = i2c_get_clientdata(client); | 1028 | snd_soc_unregister_codec(&client->dev); |
1119 | wm8978_unregister(wm8978); | 1029 | kfree(i2c_get_clientdata(client)); |
1120 | kfree(wm8978); | ||
1121 | return 0; | 1030 | return 0; |
1122 | } | 1031 | } |
1123 | 1032 | ||
@@ -1129,23 +1038,34 @@ MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id); | |||
1129 | 1038 | ||
1130 | static struct i2c_driver wm8978_i2c_driver = { | 1039 | static struct i2c_driver wm8978_i2c_driver = { |
1131 | .driver = { | 1040 | .driver = { |
1132 | .name = "WM8978", | 1041 | .name = "WM8978-codec", |
1133 | .owner = THIS_MODULE, | 1042 | .owner = THIS_MODULE, |
1134 | }, | 1043 | }, |
1135 | .probe = wm8978_i2c_probe, | 1044 | .probe = wm8978_i2c_probe, |
1136 | .remove = __devexit_p(wm8978_i2c_remove), | 1045 | .remove = __devexit_p(wm8978_i2c_remove), |
1137 | .id_table = wm8978_i2c_id, | 1046 | .id_table = wm8978_i2c_id, |
1138 | }; | 1047 | }; |
1048 | #endif | ||
1139 | 1049 | ||
1140 | static int __init wm8978_modinit(void) | 1050 | static int __init wm8978_modinit(void) |
1141 | { | 1051 | { |
1142 | return i2c_add_driver(&wm8978_i2c_driver); | 1052 | int ret = 0; |
1053 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1054 | ret = i2c_add_driver(&wm8978_i2c_driver); | ||
1055 | if (ret != 0) { | ||
1056 | printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n", | ||
1057 | ret); | ||
1058 | } | ||
1059 | #endif | ||
1060 | return ret; | ||
1143 | } | 1061 | } |
1144 | module_init(wm8978_modinit); | 1062 | module_init(wm8978_modinit); |
1145 | 1063 | ||
1146 | static void __exit wm8978_exit(void) | 1064 | static void __exit wm8978_exit(void) |
1147 | { | 1065 | { |
1066 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1148 | i2c_del_driver(&wm8978_i2c_driver); | 1067 | i2c_del_driver(&wm8978_i2c_driver); |
1068 | #endif | ||
1149 | } | 1069 | } |
1150 | module_exit(wm8978_exit); | 1070 | module_exit(wm8978_exit); |
1151 | 1071 | ||
diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h index 56ec83270917..c75525b7f154 100644 --- a/sound/soc/codecs/wm8978.h +++ b/sound/soc/codecs/wm8978.h | |||
@@ -80,7 +80,4 @@ enum wm8978_sysclk_src { | |||
80 | WM8978_MCLK | 80 | WM8978_MCLK |
81 | }; | 81 | }; |
82 | 82 | ||
83 | extern struct snd_soc_dai wm8978_dai; | ||
84 | extern struct snd_soc_codec_device soc_codec_dev_wm8978; | ||
85 | |||
86 | #endif /* __WM8978_H__ */ | 83 | #endif /* __WM8978_H__ */ |
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 19ad590ca0b3..ecbffcea71db 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c | |||
@@ -52,7 +52,8 @@ static const u16 wm8988_reg[] = { | |||
52 | /* codec private data */ | 52 | /* codec private data */ |
53 | struct wm8988_priv { | 53 | struct wm8988_priv { |
54 | unsigned int sysclk; | 54 | unsigned int sysclk; |
55 | struct snd_soc_codec codec; | 55 | enum snd_soc_control_type control_type; |
56 | void *control_data; | ||
56 | struct snd_pcm_hw_constraint_list *sysclk_constraints; | 57 | struct snd_pcm_hw_constraint_list *sysclk_constraints; |
57 | u16 reg_cache[WM8988_NUM_REG]; | 58 | u16 reg_cache[WM8988_NUM_REG]; |
58 | }; | 59 | }; |
@@ -608,8 +609,7 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, | |||
608 | struct snd_soc_dai *dai) | 609 | struct snd_soc_dai *dai) |
609 | { | 610 | { |
610 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 611 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
611 | struct snd_soc_device *socdev = rtd->socdev; | 612 | struct snd_soc_codec *codec = rtd->codec; |
612 | struct snd_soc_codec *codec = socdev->card->codec; | ||
613 | struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); | 613 | struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); |
614 | u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3; | 614 | u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3; |
615 | u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180; | 615 | u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180; |
@@ -711,8 +711,8 @@ static struct snd_soc_dai_ops wm8988_ops = { | |||
711 | .digital_mute = wm8988_mute, | 711 | .digital_mute = wm8988_mute, |
712 | }; | 712 | }; |
713 | 713 | ||
714 | struct snd_soc_dai wm8988_dai = { | 714 | static struct snd_soc_dai_driver wm8988_dai = { |
715 | .name = "WM8988", | 715 | .name = "wm8988-hifi", |
716 | .playback = { | 716 | .playback = { |
717 | .stream_name = "Playback", | 717 | .stream_name = "Playback", |
718 | .channels_min = 1, | 718 | .channels_min = 1, |
@@ -730,21 +730,15 @@ struct snd_soc_dai wm8988_dai = { | |||
730 | .ops = &wm8988_ops, | 730 | .ops = &wm8988_ops, |
731 | .symmetric_rates = 1, | 731 | .symmetric_rates = 1, |
732 | }; | 732 | }; |
733 | EXPORT_SYMBOL_GPL(wm8988_dai); | ||
734 | 733 | ||
735 | static int wm8988_suspend(struct platform_device *pdev, pm_message_t state) | 734 | static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state) |
736 | { | 735 | { |
737 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
738 | struct snd_soc_codec *codec = socdev->card->codec; | ||
739 | |||
740 | wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); | 736 | wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); |
741 | return 0; | 737 | return 0; |
742 | } | 738 | } |
743 | 739 | ||
744 | static int wm8988_resume(struct platform_device *pdev) | 740 | static int wm8988_resume(struct snd_soc_codec *codec) |
745 | { | 741 | { |
746 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
747 | struct snd_soc_codec *codec = socdev->card->codec; | ||
748 | int i; | 742 | int i; |
749 | u8 data[2]; | 743 | u8 data[2]; |
750 | u16 *cache = codec->reg_cache; | 744 | u16 *cache = codec->reg_cache; |
@@ -763,99 +757,23 @@ static int wm8988_resume(struct platform_device *pdev) | |||
763 | return 0; | 757 | return 0; |
764 | } | 758 | } |
765 | 759 | ||
766 | static struct snd_soc_codec *wm8988_codec; | 760 | static int wm8988_probe(struct snd_soc_codec *codec) |
767 | |||
768 | static int wm8988_probe(struct platform_device *pdev) | ||
769 | { | 761 | { |
770 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 762 | struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); |
771 | struct snd_soc_codec *codec; | ||
772 | int ret = 0; | 763 | int ret = 0; |
773 | |||
774 | if (wm8988_codec == NULL) { | ||
775 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
776 | return -ENODEV; | ||
777 | } | ||
778 | |||
779 | socdev->card->codec = wm8988_codec; | ||
780 | codec = wm8988_codec; | ||
781 | |||
782 | /* register pcms */ | ||
783 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
784 | if (ret < 0) { | ||
785 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
786 | goto pcm_err; | ||
787 | } | ||
788 | |||
789 | snd_soc_add_controls(codec, wm8988_snd_controls, | ||
790 | ARRAY_SIZE(wm8988_snd_controls)); | ||
791 | snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets, | ||
792 | ARRAY_SIZE(wm8988_dapm_widgets)); | ||
793 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
794 | |||
795 | return ret; | ||
796 | |||
797 | pcm_err: | ||
798 | return ret; | ||
799 | } | ||
800 | |||
801 | static int wm8988_remove(struct platform_device *pdev) | ||
802 | { | ||
803 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
804 | |||
805 | snd_soc_free_pcms(socdev); | ||
806 | snd_soc_dapm_free(socdev); | ||
807 | |||
808 | return 0; | ||
809 | } | ||
810 | |||
811 | struct snd_soc_codec_device soc_codec_dev_wm8988 = { | ||
812 | .probe = wm8988_probe, | ||
813 | .remove = wm8988_remove, | ||
814 | .suspend = wm8988_suspend, | ||
815 | .resume = wm8988_resume, | ||
816 | }; | ||
817 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988); | ||
818 | |||
819 | static int wm8988_register(struct wm8988_priv *wm8988, | ||
820 | enum snd_soc_control_type control) | ||
821 | { | ||
822 | struct snd_soc_codec *codec = &wm8988->codec; | ||
823 | int ret; | ||
824 | u16 reg; | 764 | u16 reg; |
825 | 765 | ||
826 | if (wm8988_codec) { | 766 | codec->control_data = wm8988->control_data; |
827 | dev_err(codec->dev, "Another WM8988 is registered\n"); | 767 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type); |
828 | ret = -EINVAL; | ||
829 | goto err; | ||
830 | } | ||
831 | |||
832 | mutex_init(&codec->mutex); | ||
833 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
834 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
835 | |||
836 | snd_soc_codec_set_drvdata(codec, wm8988); | ||
837 | codec->name = "WM8988"; | ||
838 | codec->owner = THIS_MODULE; | ||
839 | codec->dai = &wm8988_dai; | ||
840 | codec->num_dai = 1; | ||
841 | codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache); | ||
842 | codec->reg_cache = &wm8988->reg_cache; | ||
843 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
844 | codec->set_bias_level = wm8988_set_bias_level; | ||
845 | |||
846 | memcpy(codec->reg_cache, wm8988_reg, | ||
847 | sizeof(wm8988_reg)); | ||
848 | |||
849 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
850 | if (ret < 0) { | 768 | if (ret < 0) { |
851 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 769 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
852 | goto err; | 770 | return ret; |
853 | } | 771 | } |
854 | 772 | ||
855 | ret = wm8988_reset(codec); | 773 | ret = wm8988_reset(codec); |
856 | if (ret < 0) { | 774 | if (ret < 0) { |
857 | dev_err(codec->dev, "Failed to issue reset\n"); | 775 | dev_err(codec->dev, "Failed to issue reset\n"); |
858 | goto err; | 776 | return ret; |
859 | } | 777 | } |
860 | 778 | ||
861 | /* set the update bits (we always update left then right) */ | 779 | /* set the update bits (we always update left then right) */ |
@@ -870,139 +788,135 @@ static int wm8988_register(struct wm8988_priv *wm8988, | |||
870 | reg = snd_soc_read(codec, WM8988_RINVOL); | 788 | reg = snd_soc_read(codec, WM8988_RINVOL); |
871 | snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100); | 789 | snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100); |
872 | 790 | ||
873 | wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY); | 791 | wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
874 | |||
875 | wm8988_dai.dev = codec->dev; | ||
876 | |||
877 | wm8988_codec = codec; | ||
878 | |||
879 | ret = snd_soc_register_codec(codec); | ||
880 | if (ret != 0) { | ||
881 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
882 | goto err; | ||
883 | } | ||
884 | 792 | ||
885 | ret = snd_soc_register_dai(&wm8988_dai); | 793 | snd_soc_add_controls(codec, wm8988_snd_controls, |
886 | if (ret != 0) { | 794 | ARRAY_SIZE(wm8988_snd_controls)); |
887 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | 795 | snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets, |
888 | goto err_codec; | 796 | ARRAY_SIZE(wm8988_dapm_widgets)); |
889 | } | 797 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
890 | 798 | ||
891 | return 0; | 799 | return 0; |
892 | |||
893 | err_codec: | ||
894 | snd_soc_unregister_codec(codec); | ||
895 | err: | ||
896 | kfree(wm8988); | ||
897 | return ret; | ||
898 | } | 800 | } |
899 | 801 | ||
900 | static void wm8988_unregister(struct wm8988_priv *wm8988) | 802 | static int wm8988_remove(struct snd_soc_codec *codec) |
901 | { | 803 | { |
902 | wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_OFF); | 804 | wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); |
903 | snd_soc_unregister_dai(&wm8988_dai); | 805 | return 0; |
904 | snd_soc_unregister_codec(&wm8988->codec); | ||
905 | kfree(wm8988); | ||
906 | wm8988_codec = NULL; | ||
907 | } | 806 | } |
908 | 807 | ||
909 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 808 | static struct snd_soc_codec_driver soc_codec_dev_wm8988 = { |
910 | static int wm8988_i2c_probe(struct i2c_client *i2c, | 809 | .probe = wm8988_probe, |
911 | const struct i2c_device_id *id) | 810 | .remove = wm8988_remove, |
811 | .suspend = wm8988_suspend, | ||
812 | .resume = wm8988_resume, | ||
813 | .set_bias_level = wm8988_set_bias_level, | ||
814 | .reg_cache_size = sizeof(wm8988_reg), | ||
815 | .reg_word_size = sizeof(u16), | ||
816 | .reg_cache_default = wm8988_reg, | ||
817 | }; | ||
818 | |||
819 | #if defined(CONFIG_SPI_MASTER) | ||
820 | static int __devinit wm8988_spi_probe(struct spi_device *spi) | ||
912 | { | 821 | { |
913 | struct wm8988_priv *wm8988; | 822 | struct wm8988_priv *wm8988; |
914 | struct snd_soc_codec *codec; | 823 | int ret; |
915 | 824 | ||
916 | wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); | 825 | wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); |
917 | if (wm8988 == NULL) | 826 | if (wm8988 == NULL) |
918 | return -ENOMEM; | 827 | return -ENOMEM; |
919 | 828 | ||
920 | codec = &wm8988->codec; | 829 | wm8988->control_data = spi; |
921 | 830 | wm8988->control_type = SND_SOC_SPI; | |
922 | i2c_set_clientdata(i2c, wm8988); | 831 | spi_set_drvdata(spi, wm8988); |
923 | codec->control_data = i2c; | ||
924 | |||
925 | codec->dev = &i2c->dev; | ||
926 | 832 | ||
927 | return wm8988_register(wm8988, SND_SOC_I2C); | 833 | ret = snd_soc_register_codec(&spi->dev, |
834 | &soc_codec_dev_wm8988, &wm8988_dai, 1); | ||
835 | if (ret < 0) | ||
836 | kfree(wm8988); | ||
837 | return ret; | ||
928 | } | 838 | } |
929 | 839 | ||
930 | static int wm8988_i2c_remove(struct i2c_client *client) | 840 | static int __devexit wm8988_spi_remove(struct spi_device *spi) |
931 | { | 841 | { |
932 | struct wm8988_priv *wm8988 = i2c_get_clientdata(client); | 842 | snd_soc_unregister_codec(&spi->dev); |
933 | wm8988_unregister(wm8988); | 843 | kfree(spi_get_drvdata(spi)); |
934 | return 0; | 844 | return 0; |
935 | } | 845 | } |
936 | 846 | ||
937 | static const struct i2c_device_id wm8988_i2c_id[] = { | 847 | static struct spi_driver wm8988_spi_driver = { |
938 | { "wm8988", 0 }, | ||
939 | { } | ||
940 | }; | ||
941 | MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id); | ||
942 | |||
943 | static struct i2c_driver wm8988_i2c_driver = { | ||
944 | .driver = { | 848 | .driver = { |
945 | .name = "WM8988", | 849 | .name = "wm8988-codec", |
946 | .owner = THIS_MODULE, | 850 | .bus = &spi_bus_type, |
851 | .owner = THIS_MODULE, | ||
947 | }, | 852 | }, |
948 | .probe = wm8988_i2c_probe, | 853 | .probe = wm8988_spi_probe, |
949 | .remove = wm8988_i2c_remove, | 854 | .remove = __devexit_p(wm8988_spi_remove), |
950 | .id_table = wm8988_i2c_id, | ||
951 | }; | 855 | }; |
952 | #endif | 856 | #endif /* CONFIG_SPI_MASTER */ |
953 | 857 | ||
954 | #if defined(CONFIG_SPI_MASTER) | 858 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
955 | static int __devinit wm8988_spi_probe(struct spi_device *spi) | 859 | static __devinit int wm8988_i2c_probe(struct i2c_client *i2c, |
860 | const struct i2c_device_id *id) | ||
956 | { | 861 | { |
957 | struct wm8988_priv *wm8988; | 862 | struct wm8988_priv *wm8988; |
958 | struct snd_soc_codec *codec; | 863 | int ret; |
959 | 864 | ||
960 | wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); | 865 | wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); |
961 | if (wm8988 == NULL) | 866 | if (wm8988 == NULL) |
962 | return -ENOMEM; | 867 | return -ENOMEM; |
963 | 868 | ||
964 | codec = &wm8988->codec; | 869 | i2c_set_clientdata(i2c, wm8988); |
965 | codec->control_data = spi; | 870 | wm8988->control_data = i2c; |
966 | codec->dev = &spi->dev; | 871 | wm8988->control_type = SND_SOC_I2C; |
967 | |||
968 | dev_set_drvdata(&spi->dev, wm8988); | ||
969 | 872 | ||
970 | return wm8988_register(wm8988, SND_SOC_SPI); | 873 | ret = snd_soc_register_codec(&i2c->dev, |
874 | &soc_codec_dev_wm8988, &wm8988_dai, 1); | ||
875 | if (ret < 0) | ||
876 | kfree(wm8988); | ||
877 | return ret; | ||
971 | } | 878 | } |
972 | 879 | ||
973 | static int __devexit wm8988_spi_remove(struct spi_device *spi) | 880 | static __devexit int wm8988_i2c_remove(struct i2c_client *client) |
974 | { | 881 | { |
975 | struct wm8988_priv *wm8988 = dev_get_drvdata(&spi->dev); | 882 | snd_soc_unregister_codec(&client->dev); |
976 | 883 | kfree(i2c_get_clientdata(client)); | |
977 | wm8988_unregister(wm8988); | ||
978 | |||
979 | return 0; | 884 | return 0; |
980 | } | 885 | } |
981 | 886 | ||
982 | static struct spi_driver wm8988_spi_driver = { | 887 | static const struct i2c_device_id wm8988_i2c_id[] = { |
888 | { "wm8988", 0 }, | ||
889 | { } | ||
890 | }; | ||
891 | MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id); | ||
892 | |||
893 | static struct i2c_driver wm8988_i2c_driver = { | ||
983 | .driver = { | 894 | .driver = { |
984 | .name = "wm8988", | 895 | .name = "wm8988-codec", |
985 | .bus = &spi_bus_type, | 896 | .owner = THIS_MODULE, |
986 | .owner = THIS_MODULE, | ||
987 | }, | 897 | }, |
988 | .probe = wm8988_spi_probe, | 898 | .probe = wm8988_i2c_probe, |
989 | .remove = __devexit_p(wm8988_spi_remove), | 899 | .remove = __devexit_p(wm8988_i2c_remove), |
900 | .id_table = wm8988_i2c_id, | ||
990 | }; | 901 | }; |
991 | #endif | 902 | #endif |
992 | 903 | ||
993 | static int __init wm8988_modinit(void) | 904 | static int __init wm8988_modinit(void) |
994 | { | 905 | { |
995 | int ret; | 906 | int ret = 0; |
996 | |||
997 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 907 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
998 | ret = i2c_add_driver(&wm8988_i2c_driver); | 908 | ret = i2c_add_driver(&wm8988_i2c_driver); |
999 | if (ret != 0) | 909 | if (ret != 0) { |
1000 | pr_err("WM8988: Unable to register I2C driver: %d\n", ret); | 910 | printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n", |
911 | ret); | ||
912 | } | ||
1001 | #endif | 913 | #endif |
1002 | #if defined(CONFIG_SPI_MASTER) | 914 | #if defined(CONFIG_SPI_MASTER) |
1003 | ret = spi_register_driver(&wm8988_spi_driver); | 915 | ret = spi_register_driver(&wm8988_spi_driver); |
1004 | if (ret != 0) | 916 | if (ret != 0) { |
1005 | pr_err("WM8988: Unable to register SPI driver: %d\n", ret); | 917 | printk(KERN_ERR "Failed to register WM8988 SPI driver: %d\n", |
918 | ret); | ||
919 | } | ||
1006 | #endif | 920 | #endif |
1007 | return ret; | 921 | return ret; |
1008 | } | 922 | } |
diff --git a/sound/soc/codecs/wm8988.h b/sound/soc/codecs/wm8988.h index 4552d37fdd41..5c04024e5f9f 100644 --- a/sound/soc/codecs/wm8988.h +++ b/sound/soc/codecs/wm8988.h | |||
@@ -54,7 +54,4 @@ | |||
54 | 54 | ||
55 | #define WM8988_SYSCLK 0 | 55 | #define WM8988_SYSCLK 0 |
56 | 56 | ||
57 | extern struct snd_soc_dai wm8988_dai; | ||
58 | extern struct snd_soc_codec_device soc_codec_dev_wm8988; | ||
59 | |||
60 | #endif | 57 | #endif |
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index dd8d909788c1..b25243382966 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -32,6 +32,8 @@ | |||
32 | 32 | ||
33 | /* codec private data */ | 33 | /* codec private data */ |
34 | struct wm8990_priv { | 34 | struct wm8990_priv { |
35 | enum snd_soc_control_type control_type; | ||
36 | void *control_data; | ||
35 | unsigned int sysclk; | 37 | unsigned int sysclk; |
36 | unsigned int pcmclk; | 38 | unsigned int pcmclk; |
37 | }; | 39 | }; |
@@ -1114,8 +1116,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, | |||
1114 | struct snd_soc_dai *dai) | 1116 | struct snd_soc_dai *dai) |
1115 | { | 1117 | { |
1116 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1118 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1117 | struct snd_soc_device *socdev = rtd->socdev; | 1119 | struct snd_soc_codec *codec = rtd->codec; |
1118 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1119 | u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1); | 1120 | u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1); |
1120 | 1121 | ||
1121 | audio1 &= ~WM8990_AIF_WL_MASK; | 1122 | audio1 &= ~WM8990_AIF_WL_MASK; |
@@ -1293,10 +1294,9 @@ static struct snd_soc_dai_ops wm8990_dai_ops = { | |||
1293 | .set_sysclk = wm8990_set_dai_sysclk, | 1294 | .set_sysclk = wm8990_set_dai_sysclk, |
1294 | }; | 1295 | }; |
1295 | 1296 | ||
1296 | struct snd_soc_dai wm8990_dai = { | 1297 | static struct snd_soc_dai_driver wm8990_dai = { |
1297 | /* ADC/DAC on primary */ | 1298 | /* ADC/DAC on primary */ |
1298 | .name = "WM8990 ADC/DAC Primary", | 1299 | .name = "wm8990-hifi", |
1299 | .id = 1, | ||
1300 | .playback = { | 1300 | .playback = { |
1301 | .stream_name = "Playback", | 1301 | .stream_name = "Playback", |
1302 | .channels_min = 1, | 1302 | .channels_min = 1, |
@@ -1311,21 +1311,15 @@ struct snd_soc_dai wm8990_dai = { | |||
1311 | .formats = WM8990_FORMATS,}, | 1311 | .formats = WM8990_FORMATS,}, |
1312 | .ops = &wm8990_dai_ops, | 1312 | .ops = &wm8990_dai_ops, |
1313 | }; | 1313 | }; |
1314 | EXPORT_SYMBOL_GPL(wm8990_dai); | ||
1315 | 1314 | ||
1316 | static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) | 1315 | static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1317 | { | 1316 | { |
1318 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1319 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1320 | |||
1321 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1317 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1322 | return 0; | 1318 | return 0; |
1323 | } | 1319 | } |
1324 | 1320 | ||
1325 | static int wm8990_resume(struct platform_device *pdev) | 1321 | static int wm8990_resume(struct snd_soc_codec *codec) |
1326 | { | 1322 | { |
1327 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1328 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1329 | int i; | 1323 | int i; |
1330 | u8 data[2]; | 1324 | u8 data[2]; |
1331 | u16 *cache = codec->reg_cache; | 1325 | u16 *cache = codec->reg_cache; |
@@ -1347,38 +1341,21 @@ static int wm8990_resume(struct platform_device *pdev) | |||
1347 | * initialise the WM8990 driver | 1341 | * initialise the WM8990 driver |
1348 | * register the mixer and dsp interfaces with the kernel | 1342 | * register the mixer and dsp interfaces with the kernel |
1349 | */ | 1343 | */ |
1350 | static int wm8990_init(struct snd_soc_device *socdev) | 1344 | static int wm8990_probe(struct snd_soc_codec *codec) |
1351 | { | 1345 | { |
1352 | struct snd_soc_codec *codec = socdev->card->codec; | 1346 | struct wm8990_priv *wm8990 = snd_soc_codec_get_drvdata(codec); |
1347 | int ret; | ||
1353 | u16 reg; | 1348 | u16 reg; |
1354 | int ret = 0; | ||
1355 | |||
1356 | codec->name = "WM8990"; | ||
1357 | codec->owner = THIS_MODULE; | ||
1358 | codec->set_bias_level = wm8990_set_bias_level; | ||
1359 | codec->dai = &wm8990_dai; | ||
1360 | codec->num_dai = 2; | ||
1361 | codec->reg_cache_size = ARRAY_SIZE(wm8990_reg); | ||
1362 | codec->reg_cache = kmemdup(wm8990_reg, sizeof(wm8990_reg), GFP_KERNEL); | ||
1363 | |||
1364 | if (codec->reg_cache == NULL) | ||
1365 | return -ENOMEM; | ||
1366 | 1349 | ||
1350 | codec->control_data = wm8990->control_data; | ||
1367 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1351 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
1368 | if (ret < 0) { | 1352 | if (ret < 0) { |
1369 | printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); | 1353 | printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); |
1370 | goto pcm_err; | 1354 | return ret; |
1371 | } | 1355 | } |
1372 | 1356 | ||
1373 | wm8990_reset(codec); | 1357 | wm8990_reset(codec); |
1374 | 1358 | ||
1375 | /* register pcms */ | ||
1376 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1377 | if (ret < 0) { | ||
1378 | printk(KERN_ERR "wm8990: failed to create pcms\n"); | ||
1379 | goto pcm_err; | ||
1380 | } | ||
1381 | |||
1382 | /* charge output caps */ | 1359 | /* charge output caps */ |
1383 | codec->bias_level = SND_SOC_BIAS_OFF; | 1360 | codec->bias_level = SND_SOC_BIAS_OFF; |
1384 | wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1361 | wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -1400,47 +1377,52 @@ static int wm8990_init(struct snd_soc_device *socdev) | |||
1400 | ARRAY_SIZE(wm8990_snd_controls)); | 1377 | ARRAY_SIZE(wm8990_snd_controls)); |
1401 | wm8990_add_widgets(codec); | 1378 | wm8990_add_widgets(codec); |
1402 | 1379 | ||
1403 | return ret; | 1380 | return 0; |
1381 | } | ||
1404 | 1382 | ||
1405 | pcm_err: | 1383 | /* power down chip */ |
1406 | kfree(codec->reg_cache); | 1384 | static int wm8990_remove(struct snd_soc_codec *codec) |
1407 | return ret; | 1385 | { |
1386 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1387 | return 0; | ||
1408 | } | 1388 | } |
1409 | 1389 | ||
1410 | /* If the i2c layer weren't so broken, we could pass this kind of data | 1390 | static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { |
1411 | around */ | 1391 | .probe = wm8990_probe, |
1412 | static struct snd_soc_device *wm8990_socdev; | 1392 | .remove = wm8990_remove, |
1393 | .suspend = wm8990_suspend, | ||
1394 | .resume = wm8990_resume, | ||
1395 | .set_bias_level = wm8990_set_bias_level, | ||
1396 | .reg_cache_size = ARRAY_SIZE(wm8990_reg), | ||
1397 | .reg_word_size = sizeof(u16), | ||
1398 | .reg_cache_default = wm8990_reg, | ||
1399 | }; | ||
1413 | 1400 | ||
1414 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1401 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1415 | 1402 | static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, | |
1416 | /* | 1403 | const struct i2c_device_id *id) |
1417 | * WM891 2 wire address is determined by GPIO5 | ||
1418 | * state during powerup. | ||
1419 | * low = 0x34 | ||
1420 | * high = 0x36 | ||
1421 | */ | ||
1422 | |||
1423 | static int wm8990_i2c_probe(struct i2c_client *i2c, | ||
1424 | const struct i2c_device_id *id) | ||
1425 | { | 1404 | { |
1426 | struct snd_soc_device *socdev = wm8990_socdev; | 1405 | struct wm8990_priv *wm8990; |
1427 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1428 | int ret; | 1406 | int ret; |
1429 | 1407 | ||
1430 | i2c_set_clientdata(i2c, codec); | 1408 | wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); |
1431 | codec->control_data = i2c; | 1409 | if (wm8990 == NULL) |
1410 | return -ENOMEM; | ||
1432 | 1411 | ||
1433 | ret = wm8990_init(socdev); | 1412 | i2c_set_clientdata(i2c, wm8990); |
1434 | if (ret < 0) | 1413 | wm8990->control_data = i2c; |
1435 | pr_err("failed to initialise WM8990\n"); | ||
1436 | 1414 | ||
1415 | ret = snd_soc_register_codec(&i2c->dev, | ||
1416 | &soc_codec_dev_wm8990, &wm8990_dai, 1); | ||
1417 | if (ret < 0) | ||
1418 | kfree(wm8990); | ||
1437 | return ret; | 1419 | return ret; |
1438 | } | 1420 | } |
1439 | 1421 | ||
1440 | static int wm8990_i2c_remove(struct i2c_client *client) | 1422 | static __devexit int wm8990_i2c_remove(struct i2c_client *client) |
1441 | { | 1423 | { |
1442 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 1424 | snd_soc_unregister_codec(&client->dev); |
1443 | kfree(codec->reg_cache); | 1425 | kfree(i2c_get_clientdata(client)); |
1444 | return 0; | 1426 | return 0; |
1445 | } | 1427 | } |
1446 | 1428 | ||
@@ -1452,134 +1434,34 @@ MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id); | |||
1452 | 1434 | ||
1453 | static struct i2c_driver wm8990_i2c_driver = { | 1435 | static struct i2c_driver wm8990_i2c_driver = { |
1454 | .driver = { | 1436 | .driver = { |
1455 | .name = "WM8990 I2C Codec", | 1437 | .name = "wm8990-codec", |
1456 | .owner = THIS_MODULE, | 1438 | .owner = THIS_MODULE, |
1457 | }, | 1439 | }, |
1458 | .probe = wm8990_i2c_probe, | 1440 | .probe = wm8990_i2c_probe, |
1459 | .remove = wm8990_i2c_remove, | 1441 | .remove = __devexit_p(wm8990_i2c_remove), |
1460 | .id_table = wm8990_i2c_id, | 1442 | .id_table = wm8990_i2c_id, |
1461 | }; | 1443 | }; |
1462 | |||
1463 | static int wm8990_add_i2c_device(struct platform_device *pdev, | ||
1464 | const struct wm8990_setup_data *setup) | ||
1465 | { | ||
1466 | struct i2c_board_info info; | ||
1467 | struct i2c_adapter *adapter; | ||
1468 | struct i2c_client *client; | ||
1469 | int ret; | ||
1470 | |||
1471 | ret = i2c_add_driver(&wm8990_i2c_driver); | ||
1472 | if (ret != 0) { | ||
1473 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
1474 | return ret; | ||
1475 | } | ||
1476 | |||
1477 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
1478 | info.addr = setup->i2c_address; | ||
1479 | strlcpy(info.type, "wm8990", I2C_NAME_SIZE); | ||
1480 | |||
1481 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
1482 | if (!adapter) { | ||
1483 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
1484 | setup->i2c_bus); | ||
1485 | goto err_driver; | ||
1486 | } | ||
1487 | |||
1488 | client = i2c_new_device(adapter, &info); | ||
1489 | i2c_put_adapter(adapter); | ||
1490 | if (!client) { | ||
1491 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
1492 | (unsigned int)info.addr); | ||
1493 | goto err_driver; | ||
1494 | } | ||
1495 | |||
1496 | return 0; | ||
1497 | |||
1498 | err_driver: | ||
1499 | i2c_del_driver(&wm8990_i2c_driver); | ||
1500 | return -ENODEV; | ||
1501 | } | ||
1502 | #endif | 1444 | #endif |
1503 | 1445 | ||
1504 | static int wm8990_probe(struct platform_device *pdev) | 1446 | static int __init wm8990_modinit(void) |
1505 | { | 1447 | { |
1506 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1448 | int ret = 0; |
1507 | struct wm8990_setup_data *setup; | ||
1508 | struct snd_soc_codec *codec; | ||
1509 | struct wm8990_priv *wm8990; | ||
1510 | int ret; | ||
1511 | |||
1512 | setup = socdev->codec_data; | ||
1513 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
1514 | if (codec == NULL) | ||
1515 | return -ENOMEM; | ||
1516 | |||
1517 | wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); | ||
1518 | if (wm8990 == NULL) { | ||
1519 | kfree(codec); | ||
1520 | return -ENOMEM; | ||
1521 | } | ||
1522 | |||
1523 | snd_soc_codec_set_drvdata(codec, wm8990); | ||
1524 | socdev->card->codec = codec; | ||
1525 | mutex_init(&codec->mutex); | ||
1526 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1527 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1528 | wm8990_socdev = socdev; | ||
1529 | |||
1530 | ret = -ENODEV; | ||
1531 | |||
1532 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1449 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1533 | if (setup->i2c_address) { | 1450 | ret = i2c_add_driver(&wm8990_i2c_driver); |
1534 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1535 | ret = wm8990_add_i2c_device(pdev, setup); | ||
1536 | } | ||
1537 | #endif | ||
1538 | |||
1539 | if (ret != 0) { | 1451 | if (ret != 0) { |
1540 | kfree(snd_soc_codec_get_drvdata(codec)); | 1452 | printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n", |
1541 | kfree(codec); | 1453 | ret); |
1542 | } | 1454 | } |
1455 | #endif | ||
1543 | return ret; | 1456 | return ret; |
1544 | } | 1457 | } |
1458 | module_init(wm8990_modinit); | ||
1545 | 1459 | ||
1546 | /* power down chip */ | 1460 | static void __exit wm8990_exit(void) |
1547 | static int wm8990_remove(struct platform_device *pdev) | ||
1548 | { | 1461 | { |
1549 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1550 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1551 | |||
1552 | if (codec->control_data) | ||
1553 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1554 | snd_soc_free_pcms(socdev); | ||
1555 | snd_soc_dapm_free(socdev); | ||
1556 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1462 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1557 | i2c_unregister_device(codec->control_data); | ||
1558 | i2c_del_driver(&wm8990_i2c_driver); | 1463 | i2c_del_driver(&wm8990_i2c_driver); |
1559 | #endif | 1464 | #endif |
1560 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
1561 | kfree(codec); | ||
1562 | |||
1563 | return 0; | ||
1564 | } | ||
1565 | |||
1566 | struct snd_soc_codec_device soc_codec_dev_wm8990 = { | ||
1567 | .probe = wm8990_probe, | ||
1568 | .remove = wm8990_remove, | ||
1569 | .suspend = wm8990_suspend, | ||
1570 | .resume = wm8990_resume, | ||
1571 | }; | ||
1572 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990); | ||
1573 | |||
1574 | static int __init wm8990_modinit(void) | ||
1575 | { | ||
1576 | return snd_soc_register_dai(&wm8990_dai); | ||
1577 | } | ||
1578 | module_init(wm8990_modinit); | ||
1579 | |||
1580 | static void __exit wm8990_exit(void) | ||
1581 | { | ||
1582 | snd_soc_unregister_dai(&wm8990_dai); | ||
1583 | } | 1465 | } |
1584 | module_exit(wm8990_exit); | 1466 | module_exit(wm8990_exit); |
1585 | 1467 | ||
diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h index 7114ddc88b4b..77c98a4bfe9c 100644 --- a/sound/soc/codecs/wm8990.h +++ b/sound/soc/codecs/wm8990.h | |||
@@ -826,18 +826,10 @@ | |||
826 | #define WM8990_INMIXR_PWR_BIT 2 | 826 | #define WM8990_INMIXR_PWR_BIT 2 |
827 | #define WM8990_AINRMUX_PWR_BIT 3 | 827 | #define WM8990_AINRMUX_PWR_BIT 3 |
828 | 828 | ||
829 | struct wm8990_setup_data { | ||
830 | unsigned i2c_bus; | ||
831 | unsigned short i2c_address; | ||
832 | }; | ||
833 | |||
834 | #define WM8990_MCLK_DIV 0 | 829 | #define WM8990_MCLK_DIV 0 |
835 | #define WM8990_DACCLK_DIV 1 | 830 | #define WM8990_DACCLK_DIV 1 |
836 | #define WM8990_ADCCLK_DIV 2 | 831 | #define WM8990_ADCCLK_DIV 2 |
837 | #define WM8990_BCLK_DIV 3 | 832 | #define WM8990_BCLK_DIV 3 |
838 | 833 | ||
839 | extern struct snd_soc_dai wm8990_dai; | ||
840 | extern struct snd_soc_codec_device soc_codec_dev_wm8990; | ||
841 | |||
842 | #endif /* __WM8990REGISTERDEFS_H__ */ | 834 | #endif /* __WM8990REGISTERDEFS_H__ */ |
843 | /*------------------------------ END OF FILE ---------------------------------*/ | 835 | /*------------------------------ END OF FILE ---------------------------------*/ |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index d8d300c6175f..1d9e1837a2df 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -229,7 +229,8 @@ struct wm8993_priv { | |||
229 | u16 reg_cache[WM8993_REGISTER_COUNT]; | 229 | u16 reg_cache[WM8993_REGISTER_COUNT]; |
230 | struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES]; | 230 | struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES]; |
231 | struct wm8993_platform_data pdata; | 231 | struct wm8993_platform_data pdata; |
232 | struct snd_soc_codec codec; | 232 | enum snd_soc_control_type control_type; |
233 | void *control_data; | ||
233 | int master; | 234 | int master; |
234 | int sysclk_source; | 235 | int sysclk_source; |
235 | int tdm_slots; | 236 | int tdm_slots; |
@@ -367,10 +368,9 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, | |||
367 | return 0; | 368 | return 0; |
368 | } | 369 | } |
369 | 370 | ||
370 | static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | 371 | static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source, |
371 | unsigned int Fref, unsigned int Fout) | 372 | unsigned int Fref, unsigned int Fout) |
372 | { | 373 | { |
373 | struct snd_soc_codec *codec = dai->codec; | ||
374 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 374 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
375 | u16 reg1, reg4, reg5; | 375 | u16 reg1, reg4, reg5; |
376 | struct _fll_div fll_div; | 376 | struct _fll_div fll_div; |
@@ -456,6 +456,12 @@ static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | |||
456 | return 0; | 456 | return 0; |
457 | } | 457 | } |
458 | 458 | ||
459 | static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | ||
460 | unsigned int Fref, unsigned int Fout) | ||
461 | { | ||
462 | return _wm8993_set_fll(dai->codec, fll_id, source, Fref, Fout); | ||
463 | } | ||
464 | |||
459 | static int configure_clock(struct snd_soc_codec *codec) | 465 | static int configure_clock(struct snd_soc_codec *codec) |
460 | { | 466 | { |
461 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 467 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
@@ -1394,8 +1400,8 @@ static struct snd_soc_dai_ops wm8993_ops = { | |||
1394 | SNDRV_PCM_FMTBIT_S24_LE |\ | 1400 | SNDRV_PCM_FMTBIT_S24_LE |\ |
1395 | SNDRV_PCM_FMTBIT_S32_LE) | 1401 | SNDRV_PCM_FMTBIT_S32_LE) |
1396 | 1402 | ||
1397 | struct snd_soc_dai wm8993_dai = { | 1403 | static struct snd_soc_dai_driver wm8993_dai = { |
1398 | .name = "WM8993", | 1404 | .name = "wm8993-hifi", |
1399 | .playback = { | 1405 | .playback = { |
1400 | .stream_name = "Playback", | 1406 | .stream_name = "Playback", |
1401 | .channels_min = 1, | 1407 | .channels_min = 1, |
@@ -1413,32 +1419,82 @@ struct snd_soc_dai wm8993_dai = { | |||
1413 | .ops = &wm8993_ops, | 1419 | .ops = &wm8993_ops, |
1414 | .symmetric_rates = 1, | 1420 | .symmetric_rates = 1, |
1415 | }; | 1421 | }; |
1416 | EXPORT_SYMBOL_GPL(wm8993_dai); | ||
1417 | |||
1418 | static struct snd_soc_codec *wm8993_codec; | ||
1419 | 1422 | ||
1420 | static int wm8993_probe(struct platform_device *pdev) | 1423 | static int wm8993_probe(struct snd_soc_codec *codec) |
1421 | { | 1424 | { |
1422 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1425 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1423 | struct snd_soc_codec *codec; | 1426 | int ret, i, val; |
1424 | struct wm8993_priv *wm8993; | 1427 | |
1425 | int ret = 0; | 1428 | codec->control_data = wm8993->control_data; |
1429 | wm8993->hubs_data.hp_startup_mode = 1; | ||
1430 | wm8993->hubs_data.dcs_codes = -2; | ||
1431 | |||
1432 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | ||
1433 | if (ret != 0) { | ||
1434 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1435 | return ret; | ||
1436 | } | ||
1437 | |||
1438 | for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) | ||
1439 | wm8993->supplies[i].supply = wm8993_supply_names[i]; | ||
1426 | 1440 | ||
1427 | if (!wm8993_codec) { | 1441 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies), |
1428 | dev_err(&pdev->dev, "I2C device not yet probed\n"); | 1442 | wm8993->supplies); |
1429 | goto err; | 1443 | if (ret != 0) { |
1444 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
1445 | return ret; | ||
1430 | } | 1446 | } |
1431 | 1447 | ||
1432 | socdev->card->codec = wm8993_codec; | 1448 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), |
1433 | codec = wm8993_codec; | 1449 | wm8993->supplies); |
1434 | wm8993 = snd_soc_codec_get_drvdata(codec); | 1450 | if (ret != 0) { |
1451 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
1452 | goto err_get; | ||
1453 | } | ||
1435 | 1454 | ||
1436 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1455 | val = snd_soc_read(codec, WM8993_SOFTWARE_RESET); |
1437 | if (ret < 0) { | 1456 | if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { |
1438 | dev_err(codec->dev, "failed to create pcms\n"); | 1457 | dev_err(codec->dev, "Invalid ID register value %x\n", val); |
1439 | goto err; | 1458 | ret = -EINVAL; |
1459 | goto err_enable; | ||
1440 | } | 1460 | } |
1441 | 1461 | ||
1462 | ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff); | ||
1463 | if (ret != 0) | ||
1464 | goto err_enable; | ||
1465 | |||
1466 | codec->cache_only = 1; | ||
1467 | |||
1468 | /* By default we're using the output mixers */ | ||
1469 | wm8993->class_w_users = 2; | ||
1470 | |||
1471 | /* Latch volume update bits and default ZC on */ | ||
1472 | snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, | ||
1473 | WM8993_DAC_VU, WM8993_DAC_VU); | ||
1474 | snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, | ||
1475 | WM8993_ADC_VU, WM8993_ADC_VU); | ||
1476 | |||
1477 | /* Manualy manage the HPOUT sequencing for independent stereo | ||
1478 | * control. */ | ||
1479 | snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, | ||
1480 | WM8993_HPOUT1_AUTO_PU, 0); | ||
1481 | |||
1482 | /* Use automatic clock configuration */ | ||
1483 | snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); | ||
1484 | |||
1485 | wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff, | ||
1486 | wm8993->pdata.lineout2_diff, | ||
1487 | wm8993->pdata.lineout1fb, | ||
1488 | wm8993->pdata.lineout2fb, | ||
1489 | wm8993->pdata.jd_scthr, | ||
1490 | wm8993->pdata.jd_thr, | ||
1491 | wm8993->pdata.micbias1_lvl, | ||
1492 | wm8993->pdata.micbias2_lvl); | ||
1493 | |||
1494 | ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1495 | if (ret != 0) | ||
1496 | goto err_enable; | ||
1497 | |||
1442 | snd_soc_add_controls(codec, wm8993_snd_controls, | 1498 | snd_soc_add_controls(codec, wm8993_snd_controls, |
1443 | ARRAY_SIZE(wm8993_snd_controls)); | 1499 | ARRAY_SIZE(wm8993_snd_controls)); |
1444 | if (wm8993->pdata.num_retune_configs != 0) { | 1500 | if (wm8993->pdata.num_retune_configs != 0) { |
@@ -1457,36 +1513,36 @@ static int wm8993_probe(struct platform_device *pdev) | |||
1457 | wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, | 1513 | wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, |
1458 | wm8993->pdata.lineout2_diff); | 1514 | wm8993->pdata.lineout2_diff); |
1459 | 1515 | ||
1460 | return ret; | 1516 | return 0; |
1461 | 1517 | ||
1462 | err: | 1518 | err_enable: |
1519 | regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1520 | err_get: | ||
1521 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1463 | return ret; | 1522 | return ret; |
1464 | } | 1523 | } |
1465 | 1524 | ||
1466 | static int wm8993_remove(struct platform_device *pdev) | 1525 | static int wm8993_remove(struct snd_soc_codec *codec) |
1467 | { | 1526 | { |
1468 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1527 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1469 | |||
1470 | snd_soc_free_pcms(socdev); | ||
1471 | snd_soc_dapm_free(socdev); | ||
1472 | 1528 | ||
1529 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1530 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1473 | return 0; | 1531 | return 0; |
1474 | } | 1532 | } |
1475 | 1533 | ||
1476 | #ifdef CONFIG_PM | 1534 | #ifdef CONFIG_PM |
1477 | static int wm8993_suspend(struct platform_device *pdev, pm_message_t state) | 1535 | static int wm8993_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1478 | { | 1536 | { |
1479 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1480 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1481 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 1537 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1482 | int fll_fout = wm8993->fll_fout; | 1538 | int fll_fout = wm8993->fll_fout; |
1483 | int fll_fref = wm8993->fll_fref; | 1539 | int fll_fref = wm8993->fll_fref; |
1484 | int ret; | 1540 | int ret; |
1485 | 1541 | ||
1486 | /* Stop the FLL in an orderly fashion */ | 1542 | /* Stop the FLL in an orderly fashion */ |
1487 | ret = wm8993_set_fll(codec->dai, 0, 0, 0, 0); | 1543 | ret = _wm8993_set_fll(codec, 0, 0, 0, 0); |
1488 | if (ret != 0) { | 1544 | if (ret != 0) { |
1489 | dev_err(&pdev->dev, "Failed to stop FLL\n"); | 1545 | dev_err(codec->dev, "Failed to stop FLL\n"); |
1490 | return ret; | 1546 | return ret; |
1491 | } | 1547 | } |
1492 | 1548 | ||
@@ -1498,10 +1554,8 @@ static int wm8993_suspend(struct platform_device *pdev, pm_message_t state) | |||
1498 | return 0; | 1554 | return 0; |
1499 | } | 1555 | } |
1500 | 1556 | ||
1501 | static int wm8993_resume(struct platform_device *pdev) | 1557 | static int wm8993_resume(struct snd_soc_codec *codec) |
1502 | { | 1558 | { |
1503 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1504 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1505 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); | 1559 | struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); |
1506 | int ret; | 1560 | int ret; |
1507 | 1561 | ||
@@ -1515,7 +1569,7 @@ static int wm8993_resume(struct platform_device *pdev) | |||
1515 | wm8993->fll_fref = 0; | 1569 | wm8993->fll_fref = 0; |
1516 | wm8993->fll_fout = 0; | 1570 | wm8993->fll_fout = 0; |
1517 | 1571 | ||
1518 | ret = wm8993_set_fll(codec->dai, 0, wm8993->fll_src, | 1572 | ret = _wm8993_set_fll(codec, 0, wm8993->fll_src, |
1519 | fll_fref, fll_fout); | 1573 | fll_fref, fll_fout); |
1520 | if (ret != 0) | 1574 | if (ret != 0) |
1521 | dev_err(codec->dev, "Failed to restart FLL\n"); | 1575 | dev_err(codec->dev, "Failed to restart FLL\n"); |
@@ -1528,162 +1582,43 @@ static int wm8993_resume(struct platform_device *pdev) | |||
1528 | #define wm8993_resume NULL | 1582 | #define wm8993_resume NULL |
1529 | #endif | 1583 | #endif |
1530 | 1584 | ||
1531 | struct snd_soc_codec_device soc_codec_dev_wm8993 = { | 1585 | static struct snd_soc_codec_driver soc_codec_dev_wm8993 = { |
1532 | .probe = wm8993_probe, | 1586 | .probe = wm8993_probe, |
1533 | .remove = wm8993_remove, | 1587 | .remove = wm8993_remove, |
1534 | .suspend = wm8993_suspend, | 1588 | .suspend = wm8993_suspend, |
1535 | .resume = wm8993_resume, | 1589 | .resume = wm8993_resume, |
1590 | .set_bias_level = wm8993_set_bias_level, | ||
1591 | .reg_cache_size = sizeof(wm8993_reg_defaults), | ||
1592 | .reg_word_size = sizeof(u16), | ||
1593 | .reg_cache_default = wm8993_reg_defaults, | ||
1594 | .volatile_register = wm8993_volatile, | ||
1536 | }; | 1595 | }; |
1537 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993); | ||
1538 | 1596 | ||
1539 | static int wm8993_i2c_probe(struct i2c_client *i2c, | 1597 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1540 | const struct i2c_device_id *id) | 1598 | static __devinit int wm8993_i2c_probe(struct i2c_client *i2c, |
1599 | const struct i2c_device_id *id) | ||
1541 | { | 1600 | { |
1542 | struct wm8993_priv *wm8993; | 1601 | struct wm8993_priv *wm8993; |
1543 | struct snd_soc_codec *codec; | ||
1544 | unsigned int val; | ||
1545 | int ret; | 1602 | int ret; |
1546 | int i; | ||
1547 | |||
1548 | if (wm8993_codec) { | ||
1549 | dev_err(&i2c->dev, "A WM8993 is already registered\n"); | ||
1550 | return -EINVAL; | ||
1551 | } | ||
1552 | 1603 | ||
1553 | wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL); | 1604 | wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL); |
1554 | if (wm8993 == NULL) | 1605 | if (wm8993 == NULL) |
1555 | return -ENOMEM; | 1606 | return -ENOMEM; |
1556 | 1607 | ||
1557 | codec = &wm8993->codec; | ||
1558 | if (i2c->dev.platform_data) | ||
1559 | memcpy(&wm8993->pdata, i2c->dev.platform_data, | ||
1560 | sizeof(wm8993->pdata)); | ||
1561 | |||
1562 | mutex_init(&codec->mutex); | ||
1563 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1564 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1565 | |||
1566 | codec->name = "WM8993"; | ||
1567 | codec->volatile_register = wm8993_volatile; | ||
1568 | codec->reg_cache = wm8993->reg_cache; | ||
1569 | codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache); | ||
1570 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1571 | codec->set_bias_level = wm8993_set_bias_level; | ||
1572 | codec->dai = &wm8993_dai; | ||
1573 | codec->num_dai = 1; | ||
1574 | snd_soc_codec_set_drvdata(codec, wm8993); | ||
1575 | |||
1576 | wm8993->hubs_data.hp_startup_mode = 1; | ||
1577 | wm8993->hubs_data.dcs_codes = -2; | ||
1578 | |||
1579 | memcpy(wm8993->reg_cache, wm8993_reg_defaults, | ||
1580 | sizeof(wm8993->reg_cache)); | ||
1581 | |||
1582 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | ||
1583 | if (ret != 0) { | ||
1584 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1585 | goto err; | ||
1586 | } | ||
1587 | |||
1588 | i2c_set_clientdata(i2c, wm8993); | 1608 | i2c_set_clientdata(i2c, wm8993); |
1589 | codec->control_data = i2c; | 1609 | wm8993->control_data = i2c; |
1590 | wm8993_codec = codec; | ||
1591 | |||
1592 | codec->dev = &i2c->dev; | ||
1593 | |||
1594 | for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) | ||
1595 | wm8993->supplies[i].supply = wm8993_supply_names[i]; | ||
1596 | |||
1597 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies), | ||
1598 | wm8993->supplies); | ||
1599 | if (ret != 0) { | ||
1600 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
1601 | goto err; | ||
1602 | } | ||
1603 | |||
1604 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), | ||
1605 | wm8993->supplies); | ||
1606 | if (ret != 0) { | ||
1607 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
1608 | goto err_get; | ||
1609 | } | ||
1610 | |||
1611 | val = snd_soc_read(codec, WM8993_SOFTWARE_RESET); | ||
1612 | if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { | ||
1613 | dev_err(codec->dev, "Invalid ID register value %x\n", val); | ||
1614 | ret = -EINVAL; | ||
1615 | goto err_enable; | ||
1616 | } | ||
1617 | |||
1618 | ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff); | ||
1619 | if (ret != 0) | ||
1620 | goto err_enable; | ||
1621 | |||
1622 | codec->cache_only = 1; | ||
1623 | |||
1624 | /* By default we're using the output mixers */ | ||
1625 | wm8993->class_w_users = 2; | ||
1626 | |||
1627 | /* Latch volume update bits and default ZC on */ | ||
1628 | snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, | ||
1629 | WM8993_DAC_VU, WM8993_DAC_VU); | ||
1630 | snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, | ||
1631 | WM8993_ADC_VU, WM8993_ADC_VU); | ||
1632 | 1610 | ||
1633 | /* Manualy manage the HPOUT sequencing for independent stereo | 1611 | ret = snd_soc_register_codec(&i2c->dev, |
1634 | * control. */ | 1612 | &soc_codec_dev_wm8993, &wm8993_dai, 1); |
1635 | snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, | 1613 | if (ret < 0) |
1636 | WM8993_HPOUT1_AUTO_PU, 0); | 1614 | kfree(wm8993); |
1637 | |||
1638 | /* Use automatic clock configuration */ | ||
1639 | snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); | ||
1640 | |||
1641 | wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff, | ||
1642 | wm8993->pdata.lineout2_diff, | ||
1643 | wm8993->pdata.lineout1fb, | ||
1644 | wm8993->pdata.lineout2fb, | ||
1645 | wm8993->pdata.jd_scthr, | ||
1646 | wm8993->pdata.jd_thr, | ||
1647 | wm8993->pdata.micbias1_lvl, | ||
1648 | wm8993->pdata.micbias2_lvl); | ||
1649 | |||
1650 | ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1651 | if (ret != 0) | ||
1652 | goto err_enable; | ||
1653 | |||
1654 | wm8993_dai.dev = codec->dev; | ||
1655 | |||
1656 | ret = snd_soc_register_dai(&wm8993_dai); | ||
1657 | if (ret != 0) | ||
1658 | goto err_bias; | ||
1659 | |||
1660 | ret = snd_soc_register_codec(codec); | ||
1661 | |||
1662 | return 0; | ||
1663 | |||
1664 | err_bias: | ||
1665 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1666 | err_enable: | ||
1667 | regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1668 | err_get: | ||
1669 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1670 | err: | ||
1671 | wm8993_codec = NULL; | ||
1672 | kfree(wm8993); | ||
1673 | return ret; | 1615 | return ret; |
1674 | } | 1616 | } |
1675 | 1617 | ||
1676 | static int wm8993_i2c_remove(struct i2c_client *client) | 1618 | static __devexit int wm8993_i2c_remove(struct i2c_client *client) |
1677 | { | 1619 | { |
1678 | struct wm8993_priv *wm8993 = i2c_get_clientdata(client); | 1620 | snd_soc_unregister_codec(&client->dev); |
1679 | 1621 | kfree(i2c_get_clientdata(client)); | |
1680 | snd_soc_unregister_codec(&wm8993->codec); | ||
1681 | snd_soc_unregister_dai(&wm8993_dai); | ||
1682 | |||
1683 | wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF); | ||
1684 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1685 | kfree(wm8993); | ||
1686 | |||
1687 | return 0; | 1622 | return 0; |
1688 | } | 1623 | } |
1689 | 1624 | ||
@@ -1695,30 +1630,34 @@ MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id); | |||
1695 | 1630 | ||
1696 | static struct i2c_driver wm8993_i2c_driver = { | 1631 | static struct i2c_driver wm8993_i2c_driver = { |
1697 | .driver = { | 1632 | .driver = { |
1698 | .name = "WM8993", | 1633 | .name = "wm8993-codec", |
1699 | .owner = THIS_MODULE, | 1634 | .owner = THIS_MODULE, |
1700 | }, | 1635 | }, |
1701 | .probe = wm8993_i2c_probe, | 1636 | .probe = wm8993_i2c_probe, |
1702 | .remove = wm8993_i2c_remove, | 1637 | .remove = __devexit_p(wm8993_i2c_remove), |
1703 | .id_table = wm8993_i2c_id, | 1638 | .id_table = wm8993_i2c_id, |
1704 | }; | 1639 | }; |
1705 | 1640 | #endif | |
1706 | 1641 | ||
1707 | static int __init wm8993_modinit(void) | 1642 | static int __init wm8993_modinit(void) |
1708 | { | 1643 | { |
1709 | int ret; | 1644 | int ret = 0; |
1710 | 1645 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1711 | ret = i2c_add_driver(&wm8993_i2c_driver); | 1646 | ret = i2c_add_driver(&wm8993_i2c_driver); |
1712 | if (ret != 0) | 1647 | if (ret != 0) { |
1713 | pr_err("WM8993: Unable to register I2C driver: %d\n", ret); | 1648 | pr_err("WM8993: Unable to register I2C driver: %d\n", |
1714 | 1649 | ret); | |
1650 | } | ||
1651 | #endif | ||
1715 | return ret; | 1652 | return ret; |
1716 | } | 1653 | } |
1717 | module_init(wm8993_modinit); | 1654 | module_init(wm8993_modinit); |
1718 | 1655 | ||
1719 | static void __exit wm8993_exit(void) | 1656 | static void __exit wm8993_exit(void) |
1720 | { | 1657 | { |
1658 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1721 | i2c_del_driver(&wm8993_i2c_driver); | 1659 | i2c_del_driver(&wm8993_i2c_driver); |
1660 | #endif | ||
1722 | } | 1661 | } |
1723 | module_exit(wm8993_exit); | 1662 | module_exit(wm8993_exit); |
1724 | 1663 | ||
diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h index 30e71ca88dad..2184617b9611 100644 --- a/sound/soc/codecs/wm8993.h +++ b/sound/soc/codecs/wm8993.h | |||
@@ -1,9 +1,6 @@ | |||
1 | #ifndef WM8993_H | 1 | #ifndef WM8993_H |
2 | #define WM8993_H | 2 | #define WM8993_H |
3 | 3 | ||
4 | extern struct snd_soc_dai wm8993_dai; | ||
5 | extern struct snd_soc_codec_device soc_codec_dev_wm8993; | ||
6 | |||
7 | #define WM8993_SYSCLK_MCLK 1 | 4 | #define WM8993_SYSCLK_MCLK 1 |
8 | #define WM8993_SYSCLK_FLL 2 | 5 | #define WM8993_SYSCLK_FLL 2 |
9 | 6 | ||
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index a87046a96f2a..7823f92413f3 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -36,9 +36,6 @@ | |||
36 | #include "wm8994.h" | 36 | #include "wm8994.h" |
37 | #include "wm_hubs.h" | 37 | #include "wm_hubs.h" |
38 | 38 | ||
39 | static struct snd_soc_codec *wm8994_codec; | ||
40 | struct snd_soc_codec_device soc_codec_dev_wm8994; | ||
41 | |||
42 | struct fll_config { | 39 | struct fll_config { |
43 | int src; | 40 | int src; |
44 | int in; | 41 | int in; |
@@ -71,7 +68,9 @@ struct wm8994_micdet { | |||
71 | /* codec private data */ | 68 | /* codec private data */ |
72 | struct wm8994_priv { | 69 | struct wm8994_priv { |
73 | struct wm_hubs_data hubs; | 70 | struct wm_hubs_data hubs; |
74 | struct snd_soc_codec codec; | 71 | enum snd_soc_control_type control_type; |
72 | void *control_data; | ||
73 | struct snd_soc_codec *codec; | ||
75 | u16 reg_cache[WM8994_REG_CACHE_SIZE + 1]; | 74 | u16 reg_cache[WM8994_REG_CACHE_SIZE + 1]; |
76 | int sysclk[2]; | 75 | int sysclk[2]; |
77 | int sysclk_rate[2]; | 76 | int sysclk_rate[2]; |
@@ -1901,8 +1900,6 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, | |||
1901 | return snd_soc_put_volsw(kcontrol, ucontrol); | 1900 | return snd_soc_put_volsw(kcontrol, ucontrol); |
1902 | } | 1901 | } |
1903 | 1902 | ||
1904 | |||
1905 | |||
1906 | static void wm8994_set_drc(struct snd_soc_codec *codec, int drc) | 1903 | static void wm8994_set_drc(struct snd_soc_codec *codec, int drc) |
1907 | { | 1904 | { |
1908 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1905 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
@@ -1941,7 +1938,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol, | |||
1941 | struct snd_ctl_elem_value *ucontrol) | 1938 | struct snd_ctl_elem_value *ucontrol) |
1942 | { | 1939 | { |
1943 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 1940 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
1944 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1941 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
1945 | struct wm8994_pdata *pdata = wm8994->pdata; | 1942 | struct wm8994_pdata *pdata = wm8994->pdata; |
1946 | int drc = wm8994_get_drc(kcontrol->id.name); | 1943 | int drc = wm8994_get_drc(kcontrol->id.name); |
1947 | int value = ucontrol->value.integer.value[0]; | 1944 | int value = ucontrol->value.integer.value[0]; |
@@ -2044,7 +2041,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, | |||
2044 | struct snd_ctl_elem_value *ucontrol) | 2041 | struct snd_ctl_elem_value *ucontrol) |
2045 | { | 2042 | { |
2046 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2043 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2047 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2044 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2048 | struct wm8994_pdata *pdata = wm8994->pdata; | 2045 | struct wm8994_pdata *pdata = wm8994->pdata; |
2049 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); | 2046 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); |
2050 | int value = ucontrol->value.integer.value[0]; | 2047 | int value = ucontrol->value.integer.value[0]; |
@@ -2066,7 +2063,7 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, | |||
2066 | struct snd_ctl_elem_value *ucontrol) | 2063 | struct snd_ctl_elem_value *ucontrol) |
2067 | { | 2064 | { |
2068 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2065 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2069 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2066 | struct wm8994_priv *wm8994 =snd_soc_codec_get_drvdata(codec); |
2070 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); | 2067 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); |
2071 | 2068 | ||
2072 | ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; | 2069 | ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; |
@@ -2880,10 +2877,9 @@ static int wm8994_get_fll_config(struct fll_div *fll, | |||
2880 | return 0; | 2877 | return 0; |
2881 | } | 2878 | } |
2882 | 2879 | ||
2883 | static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, | 2880 | static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, |
2884 | unsigned int freq_in, unsigned int freq_out) | 2881 | unsigned int freq_in, unsigned int freq_out) |
2885 | { | 2882 | { |
2886 | struct snd_soc_codec *codec = dai->codec; | ||
2887 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2883 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2888 | int reg_offset, ret; | 2884 | int reg_offset, ret; |
2889 | struct fll_div fll; | 2885 | struct fll_div fll; |
@@ -2994,8 +2990,15 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, | |||
2994 | return 0; | 2990 | return 0; |
2995 | } | 2991 | } |
2996 | 2992 | ||
2993 | |||
2997 | static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; | 2994 | static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; |
2998 | 2995 | ||
2996 | static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, | ||
2997 | unsigned int freq_in, unsigned int freq_out) | ||
2998 | { | ||
2999 | return _wm8994_set_fll(dai->codec, id, src, freq_in, freq_out); | ||
3000 | } | ||
3001 | |||
2999 | static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, | 3002 | static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, |
3000 | int clk_id, unsigned int freq, int dir) | 3003 | int clk_id, unsigned int freq, int dir) |
3001 | { | 3004 | { |
@@ -3507,10 +3510,9 @@ static struct snd_soc_dai_ops wm8994_aif3_dai_ops = { | |||
3507 | .set_tristate = wm8994_set_tristate, | 3510 | .set_tristate = wm8994_set_tristate, |
3508 | }; | 3511 | }; |
3509 | 3512 | ||
3510 | struct snd_soc_dai wm8994_dai[] = { | 3513 | static struct snd_soc_dai_driver wm8994_dai[] = { |
3511 | { | 3514 | { |
3512 | .name = "WM8994 AIF1", | 3515 | .name = "wm8994-aif1", |
3513 | .id = 1, | ||
3514 | .playback = { | 3516 | .playback = { |
3515 | .stream_name = "AIF1 Playback", | 3517 | .stream_name = "AIF1 Playback", |
3516 | .channels_min = 2, | 3518 | .channels_min = 2, |
@@ -3528,8 +3530,7 @@ struct snd_soc_dai wm8994_dai[] = { | |||
3528 | .ops = &wm8994_aif1_dai_ops, | 3530 | .ops = &wm8994_aif1_dai_ops, |
3529 | }, | 3531 | }, |
3530 | { | 3532 | { |
3531 | .name = "WM8994 AIF2", | 3533 | .name = "wm8994-aif2", |
3532 | .id = 2, | ||
3533 | .playback = { | 3534 | .playback = { |
3534 | .stream_name = "AIF2 Playback", | 3535 | .stream_name = "AIF2 Playback", |
3535 | .channels_min = 2, | 3536 | .channels_min = 2, |
@@ -3547,8 +3548,7 @@ struct snd_soc_dai wm8994_dai[] = { | |||
3547 | .ops = &wm8994_aif2_dai_ops, | 3548 | .ops = &wm8994_aif2_dai_ops, |
3548 | }, | 3549 | }, |
3549 | { | 3550 | { |
3550 | .name = "WM8994 AIF3", | 3551 | .name = "wm8994-aif3", |
3551 | .id = 3, | ||
3552 | .playback = { | 3552 | .playback = { |
3553 | .stream_name = "AIF3 Playback", | 3553 | .stream_name = "AIF3 Playback", |
3554 | .channels_min = 2, | 3554 | .channels_min = 2, |
@@ -3566,20 +3566,17 @@ struct snd_soc_dai wm8994_dai[] = { | |||
3566 | .ops = &wm8994_aif3_dai_ops, | 3566 | .ops = &wm8994_aif3_dai_ops, |
3567 | } | 3567 | } |
3568 | }; | 3568 | }; |
3569 | EXPORT_SYMBOL_GPL(wm8994_dai); | ||
3570 | 3569 | ||
3571 | #ifdef CONFIG_PM | 3570 | #ifdef CONFIG_PM |
3572 | static int wm8994_suspend(struct platform_device *pdev, pm_message_t state) | 3571 | static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state) |
3573 | { | 3572 | { |
3574 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3575 | struct snd_soc_codec *codec = socdev->card->codec; | ||
3576 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3573 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3577 | int i, ret; | 3574 | int i, ret; |
3578 | 3575 | ||
3579 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { | 3576 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { |
3580 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], | 3577 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], |
3581 | sizeof(struct fll_config)); | 3578 | sizeof(struct fll_config)); |
3582 | ret = wm8994_set_fll(&codec->dai[0], i + 1, 0, 0, 0); | 3579 | ret = _wm8994_set_fll(codec, i + 1, 0, 0, 0); |
3583 | if (ret < 0) | 3580 | if (ret < 0) |
3584 | dev_warn(codec->dev, "Failed to stop FLL%d: %d\n", | 3581 | dev_warn(codec->dev, "Failed to stop FLL%d: %d\n", |
3585 | i + 1, ret); | 3582 | i + 1, ret); |
@@ -3590,10 +3587,8 @@ static int wm8994_suspend(struct platform_device *pdev, pm_message_t state) | |||
3590 | return 0; | 3587 | return 0; |
3591 | } | 3588 | } |
3592 | 3589 | ||
3593 | static int wm8994_resume(struct platform_device *pdev) | 3590 | static int wm8994_resume(struct snd_soc_codec *codec) |
3594 | { | 3591 | { |
3595 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3596 | struct snd_soc_codec *codec = socdev->card->codec; | ||
3597 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3592 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3598 | u16 *reg_cache = codec->reg_cache; | 3593 | u16 *reg_cache = codec->reg_cache; |
3599 | int i, ret; | 3594 | int i, ret; |
@@ -3622,7 +3617,7 @@ static int wm8994_resume(struct platform_device *pdev) | |||
3622 | if (!wm8994->fll_suspend[i].out) | 3617 | if (!wm8994->fll_suspend[i].out) |
3623 | continue; | 3618 | continue; |
3624 | 3619 | ||
3625 | ret = wm8994_set_fll(&codec->dai[0], i + 1, | 3620 | ret = _wm8994_set_fll(codec, i + 1, |
3626 | wm8994->fll_suspend[i].src, | 3621 | wm8994->fll_suspend[i].src, |
3627 | wm8994->fll_suspend[i].in, | 3622 | wm8994->fll_suspend[i].in, |
3628 | wm8994->fll_suspend[i].out); | 3623 | wm8994->fll_suspend[i].out); |
@@ -3640,7 +3635,7 @@ static int wm8994_resume(struct platform_device *pdev) | |||
3640 | 3635 | ||
3641 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | 3636 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) |
3642 | { | 3637 | { |
3643 | struct snd_soc_codec *codec = &wm8994->codec; | 3638 | struct snd_soc_codec *codec = wm8994->codec; |
3644 | struct wm8994_pdata *pdata = wm8994->pdata; | 3639 | struct wm8994_pdata *pdata = wm8994->pdata; |
3645 | struct snd_kcontrol_new controls[] = { | 3640 | struct snd_kcontrol_new controls[] = { |
3646 | SOC_ENUM_EXT("AIF1.1 EQ Mode", | 3641 | SOC_ENUM_EXT("AIF1.1 EQ Mode", |
@@ -3698,16 +3693,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | |||
3698 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; | 3693 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; |
3699 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; | 3694 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; |
3700 | 3695 | ||
3701 | ret = snd_soc_add_controls(&wm8994->codec, controls, | 3696 | ret = snd_soc_add_controls(wm8994->codec, controls, |
3702 | ARRAY_SIZE(controls)); | 3697 | ARRAY_SIZE(controls)); |
3703 | if (ret != 0) | 3698 | if (ret != 0) |
3704 | dev_err(wm8994->codec.dev, | 3699 | dev_err(wm8994->codec->dev, |
3705 | "Failed to add ReTune Mobile controls: %d\n", ret); | 3700 | "Failed to add ReTune Mobile controls: %d\n", ret); |
3706 | } | 3701 | } |
3707 | 3702 | ||
3708 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | 3703 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) |
3709 | { | 3704 | { |
3710 | struct snd_soc_codec *codec = &wm8994->codec; | 3705 | struct snd_soc_codec *codec = wm8994->codec; |
3711 | struct wm8994_pdata *pdata = wm8994->pdata; | 3706 | struct wm8994_pdata *pdata = wm8994->pdata; |
3712 | int ret, i; | 3707 | int ret, i; |
3713 | 3708 | ||
@@ -3739,7 +3734,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3739 | wm8994->drc_texts = kmalloc(sizeof(char *) | 3734 | wm8994->drc_texts = kmalloc(sizeof(char *) |
3740 | * pdata->num_drc_cfgs, GFP_KERNEL); | 3735 | * pdata->num_drc_cfgs, GFP_KERNEL); |
3741 | if (!wm8994->drc_texts) { | 3736 | if (!wm8994->drc_texts) { |
3742 | dev_err(wm8994->codec.dev, | 3737 | dev_err(wm8994->codec->dev, |
3743 | "Failed to allocate %d DRC config texts\n", | 3738 | "Failed to allocate %d DRC config texts\n", |
3744 | pdata->num_drc_cfgs); | 3739 | pdata->num_drc_cfgs); |
3745 | return; | 3740 | return; |
@@ -3751,10 +3746,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3751 | wm8994->drc_enum.max = pdata->num_drc_cfgs; | 3746 | wm8994->drc_enum.max = pdata->num_drc_cfgs; |
3752 | wm8994->drc_enum.texts = wm8994->drc_texts; | 3747 | wm8994->drc_enum.texts = wm8994->drc_texts; |
3753 | 3748 | ||
3754 | ret = snd_soc_add_controls(&wm8994->codec, controls, | 3749 | ret = snd_soc_add_controls(wm8994->codec, controls, |
3755 | ARRAY_SIZE(controls)); | 3750 | ARRAY_SIZE(controls)); |
3756 | if (ret != 0) | 3751 | if (ret != 0) |
3757 | dev_err(wm8994->codec.dev, | 3752 | dev_err(wm8994->codec->dev, |
3758 | "Failed to add DRC mode controls: %d\n", ret); | 3753 | "Failed to add DRC mode controls: %d\n", ret); |
3759 | 3754 | ||
3760 | for (i = 0; i < WM8994_NUM_DRC; i++) | 3755 | for (i = 0; i < WM8994_NUM_DRC; i++) |
@@ -3767,62 +3762,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3767 | if (pdata->num_retune_mobile_cfgs) | 3762 | if (pdata->num_retune_mobile_cfgs) |
3768 | wm8994_handle_retune_mobile_pdata(wm8994); | 3763 | wm8994_handle_retune_mobile_pdata(wm8994); |
3769 | else | 3764 | else |
3770 | snd_soc_add_controls(&wm8994->codec, wm8994_eq_controls, | 3765 | snd_soc_add_controls(wm8994->codec, wm8994_eq_controls, |
3771 | ARRAY_SIZE(wm8994_eq_controls)); | 3766 | ARRAY_SIZE(wm8994_eq_controls)); |
3772 | } | 3767 | } |
3773 | 3768 | ||
3774 | static int wm8994_probe(struct platform_device *pdev) | ||
3775 | { | ||
3776 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3777 | struct snd_soc_codec *codec; | ||
3778 | int ret = 0; | ||
3779 | |||
3780 | if (wm8994_codec == NULL) { | ||
3781 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
3782 | return -ENODEV; | ||
3783 | } | ||
3784 | |||
3785 | socdev->card->codec = wm8994_codec; | ||
3786 | codec = wm8994_codec; | ||
3787 | |||
3788 | /* register pcms */ | ||
3789 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
3790 | if (ret < 0) { | ||
3791 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
3792 | return ret; | ||
3793 | } | ||
3794 | |||
3795 | wm8994_handle_pdata(snd_soc_codec_get_drvdata(codec)); | ||
3796 | |||
3797 | wm_hubs_add_analogue_controls(codec); | ||
3798 | snd_soc_add_controls(codec, wm8994_snd_controls, | ||
3799 | ARRAY_SIZE(wm8994_snd_controls)); | ||
3800 | snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets, | ||
3801 | ARRAY_SIZE(wm8994_dapm_widgets)); | ||
3802 | wm_hubs_add_analogue_routes(codec, 0, 0); | ||
3803 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
3804 | |||
3805 | return 0; | ||
3806 | } | ||
3807 | |||
3808 | static int wm8994_remove(struct platform_device *pdev) | ||
3809 | { | ||
3810 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3811 | |||
3812 | snd_soc_free_pcms(socdev); | ||
3813 | snd_soc_dapm_free(socdev); | ||
3814 | |||
3815 | return 0; | ||
3816 | } | ||
3817 | |||
3818 | struct snd_soc_codec_device soc_codec_dev_wm8994 = { | ||
3819 | .probe = wm8994_probe, | ||
3820 | .remove = wm8994_remove, | ||
3821 | .suspend = wm8994_suspend, | ||
3822 | .resume = wm8994_resume, | ||
3823 | }; | ||
3824 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994); | ||
3825 | |||
3826 | /** | 3769 | /** |
3827 | * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ | 3770 | * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ |
3828 | * | 3771 | * |
@@ -3881,7 +3824,7 @@ EXPORT_SYMBOL_GPL(wm8994_mic_detect); | |||
3881 | static irqreturn_t wm8994_mic_irq(int irq, void *data) | 3824 | static irqreturn_t wm8994_mic_irq(int irq, void *data) |
3882 | { | 3825 | { |
3883 | struct wm8994_priv *priv = data; | 3826 | struct wm8994_priv *priv = data; |
3884 | struct snd_soc_codec *codec = &priv->codec; | 3827 | struct snd_soc_codec *codec = priv->codec; |
3885 | int reg; | 3828 | int reg; |
3886 | int report; | 3829 | int report; |
3887 | 3830 | ||
@@ -3913,47 +3856,20 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) | |||
3913 | return IRQ_HANDLED; | 3856 | return IRQ_HANDLED; |
3914 | } | 3857 | } |
3915 | 3858 | ||
3916 | static int wm8994_codec_probe(struct platform_device *pdev) | 3859 | static int wm8994_codec_probe(struct snd_soc_codec *codec) |
3917 | { | 3860 | { |
3918 | int ret; | ||
3919 | struct wm8994_priv *wm8994; | 3861 | struct wm8994_priv *wm8994; |
3920 | struct snd_soc_codec *codec; | 3862 | int ret, i, rev; |
3921 | int i; | ||
3922 | u16 rev; | ||
3923 | 3863 | ||
3924 | if (wm8994_codec) { | 3864 | codec->control_data = dev_get_drvdata(codec->dev->parent); |
3925 | dev_err(&pdev->dev, "Another WM8994 is registered\n"); | ||
3926 | return -EINVAL; | ||
3927 | } | ||
3928 | 3865 | ||
3929 | wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL); | 3866 | wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL); |
3930 | if (!wm8994) { | 3867 | if (wm8994 == NULL) |
3931 | dev_err(&pdev->dev, "Failed to allocate private data\n"); | ||
3932 | return -ENOMEM; | 3868 | return -ENOMEM; |
3933 | } | ||
3934 | |||
3935 | codec = &wm8994->codec; | ||
3936 | |||
3937 | mutex_init(&codec->mutex); | ||
3938 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
3939 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
3940 | |||
3941 | snd_soc_codec_set_drvdata(codec, wm8994); | 3869 | snd_soc_codec_set_drvdata(codec, wm8994); |
3942 | codec->control_data = dev_get_drvdata(pdev->dev.parent); | 3870 | |
3943 | codec->name = "WM8994"; | 3871 | wm8994->pdata = dev_get_platdata(codec->dev->parent); |
3944 | codec->owner = THIS_MODULE; | 3872 | wm8994->codec = codec; |
3945 | codec->read = wm8994_read; | ||
3946 | codec->write = wm8994_write; | ||
3947 | codec->readable_register = wm8994_readable; | ||
3948 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
3949 | codec->set_bias_level = wm8994_set_bias_level; | ||
3950 | codec->dai = &wm8994_dai[0]; | ||
3951 | codec->num_dai = 3; | ||
3952 | codec->reg_cache_size = WM8994_MAX_REGISTER; | ||
3953 | codec->reg_cache = &wm8994->reg_cache; | ||
3954 | codec->dev = &pdev->dev; | ||
3955 | |||
3956 | wm8994->pdata = pdev->dev.parent->platform_data; | ||
3957 | 3873 | ||
3958 | /* Fill the cache with physical values we inherited; don't reset */ | 3874 | /* Fill the cache with physical values we inherited; don't reset */ |
3959 | ret = wm8994_bulk_read(codec->control_data, 0, | 3875 | ret = wm8994_bulk_read(codec->control_data, 0, |
@@ -3989,25 +3905,25 @@ static int wm8994_codec_probe(struct platform_device *pdev) | |||
3989 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET, | 3905 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET, |
3990 | wm8994_mic_irq, "Mic 1 detect", wm8994); | 3906 | wm8994_mic_irq, "Mic 1 detect", wm8994); |
3991 | if (ret != 0) | 3907 | if (ret != 0) |
3992 | dev_warn(&pdev->dev, | 3908 | dev_warn(codec->dev, |
3993 | "Failed to request Mic1 detect IRQ: %d\n", ret); | 3909 | "Failed to request Mic1 detect IRQ: %d\n", ret); |
3994 | 3910 | ||
3995 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, | 3911 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, |
3996 | wm8994_mic_irq, "Mic 1 short", wm8994); | 3912 | wm8994_mic_irq, "Mic 1 short", wm8994); |
3997 | if (ret != 0) | 3913 | if (ret != 0) |
3998 | dev_warn(&pdev->dev, | 3914 | dev_warn(codec->dev, |
3999 | "Failed to request Mic1 short IRQ: %d\n", ret); | 3915 | "Failed to request Mic1 short IRQ: %d\n", ret); |
4000 | 3916 | ||
4001 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET, | 3917 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET, |
4002 | wm8994_mic_irq, "Mic 2 detect", wm8994); | 3918 | wm8994_mic_irq, "Mic 2 detect", wm8994); |
4003 | if (ret != 0) | 3919 | if (ret != 0) |
4004 | dev_warn(&pdev->dev, | 3920 | dev_warn(codec->dev, |
4005 | "Failed to request Mic2 detect IRQ: %d\n", ret); | 3921 | "Failed to request Mic2 detect IRQ: %d\n", ret); |
4006 | 3922 | ||
4007 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, | 3923 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, |
4008 | wm8994_mic_irq, "Mic 2 short", wm8994); | 3924 | wm8994_mic_irq, "Mic 2 short", wm8994); |
4009 | if (ret != 0) | 3925 | if (ret != 0) |
4010 | dev_warn(&pdev->dev, | 3926 | dev_warn(codec->dev, |
4011 | "Failed to request Mic2 short IRQ: %d\n", ret); | 3927 | "Failed to request Mic2 short IRQ: %d\n", ret); |
4012 | 3928 | ||
4013 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be | 3929 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be |
@@ -4038,13 +3954,8 @@ static int wm8994_codec_probe(struct platform_device *pdev) | |||
4038 | wm8994->lrclk_shared[1] = 0; | 3954 | wm8994->lrclk_shared[1] = 0; |
4039 | } | 3955 | } |
4040 | 3956 | ||
4041 | for (i = 0; i < ARRAY_SIZE(wm8994_dai); i++) | ||
4042 | wm8994_dai[i].dev = codec->dev; | ||
4043 | |||
4044 | wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 3957 | wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
4045 | 3958 | ||
4046 | wm8994_codec = codec; | ||
4047 | |||
4048 | /* Latch volume updates (right only; we always do left then right). */ | 3959 | /* Latch volume updates (right only; we always do left then right). */ |
4049 | snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, | 3960 | snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, |
4050 | WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); | 3961 | WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); |
@@ -4081,24 +3992,18 @@ static int wm8994_codec_probe(struct platform_device *pdev) | |||
4081 | 3992 | ||
4082 | wm8994_update_class_w(codec); | 3993 | wm8994_update_class_w(codec); |
4083 | 3994 | ||
4084 | ret = snd_soc_register_codec(codec); | 3995 | wm8994_handle_pdata(wm8994); |
4085 | if (ret != 0) { | ||
4086 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
4087 | goto err_irq; | ||
4088 | } | ||
4089 | |||
4090 | ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); | ||
4091 | if (ret != 0) { | ||
4092 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
4093 | goto err_codec; | ||
4094 | } | ||
4095 | 3996 | ||
4096 | platform_set_drvdata(pdev, wm8994); | 3997 | wm_hubs_add_analogue_controls(codec); |
3998 | snd_soc_add_controls(codec, wm8994_snd_controls, | ||
3999 | ARRAY_SIZE(wm8994_snd_controls)); | ||
4000 | snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets, | ||
4001 | ARRAY_SIZE(wm8994_dapm_widgets)); | ||
4002 | wm_hubs_add_analogue_routes(codec, 0, 0); | ||
4003 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
4097 | 4004 | ||
4098 | return 0; | 4005 | return 0; |
4099 | 4006 | ||
4100 | err_codec: | ||
4101 | snd_soc_unregister_codec(codec); | ||
4102 | err_irq: | 4007 | err_irq: |
4103 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); | 4008 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); |
4104 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); | 4009 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); |
@@ -4109,31 +4014,50 @@ err: | |||
4109 | return ret; | 4014 | return ret; |
4110 | } | 4015 | } |
4111 | 4016 | ||
4112 | static int __devexit wm8994_codec_remove(struct platform_device *pdev) | 4017 | static int wm8994_codec_remove(struct snd_soc_codec *codec) |
4113 | { | 4018 | { |
4114 | struct wm8994_priv *wm8994 = platform_get_drvdata(pdev); | 4019 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
4115 | struct snd_soc_codec *codec = &wm8994->codec; | ||
4116 | 4020 | ||
4117 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); | 4021 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); |
4118 | snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); | 4022 | |
4119 | snd_soc_unregister_codec(&wm8994->codec); | ||
4120 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); | 4023 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); |
4121 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); | 4024 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); |
4122 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); | 4025 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); |
4123 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994); | 4026 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994); |
4124 | kfree(wm8994); | 4027 | kfree(wm8994); |
4125 | wm8994_codec = NULL; | ||
4126 | 4028 | ||
4127 | return 0; | 4029 | return 0; |
4128 | } | 4030 | } |
4129 | 4031 | ||
4032 | static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { | ||
4033 | .probe = wm8994_codec_probe, | ||
4034 | .remove = wm8994_codec_remove, | ||
4035 | .suspend = wm8994_suspend, | ||
4036 | .resume = wm8994_resume, | ||
4037 | .read = wm8994_read, | ||
4038 | .write = wm8994_write, | ||
4039 | .set_bias_level = wm8994_set_bias_level, | ||
4040 | }; | ||
4041 | |||
4042 | static int __devinit wm8994_probe(struct platform_device *pdev) | ||
4043 | { | ||
4044 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994, | ||
4045 | wm8994_dai, ARRAY_SIZE(wm8994_dai)); | ||
4046 | } | ||
4047 | |||
4048 | static int __devexit wm8994_remove(struct platform_device *pdev) | ||
4049 | { | ||
4050 | snd_soc_unregister_codec(&pdev->dev); | ||
4051 | return 0; | ||
4052 | } | ||
4053 | |||
4130 | static struct platform_driver wm8994_codec_driver = { | 4054 | static struct platform_driver wm8994_codec_driver = { |
4131 | .driver = { | 4055 | .driver = { |
4132 | .name = "wm8994-codec", | 4056 | .name = "wm8994-codec", |
4133 | .owner = THIS_MODULE, | 4057 | .owner = THIS_MODULE, |
4134 | }, | 4058 | }, |
4135 | .probe = wm8994_codec_probe, | 4059 | .probe = wm8994_probe, |
4136 | .remove = __devexit_p(wm8994_codec_remove), | 4060 | .remove = __devexit_p(wm8994_remove), |
4137 | }; | 4061 | }; |
4138 | 4062 | ||
4139 | static __init int wm8994_init(void) | 4063 | static __init int wm8994_init(void) |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 2e0ca67a8df7..d8dce260c430 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -11,9 +11,6 @@ | |||
11 | 11 | ||
12 | #include <sound/soc.h> | 12 | #include <sound/soc.h> |
13 | 13 | ||
14 | extern struct snd_soc_codec_device soc_codec_dev_wm8994; | ||
15 | extern struct snd_soc_dai wm8994_dai[]; | ||
16 | |||
17 | /* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */ | 14 | /* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */ |
18 | #define WM8994_SYSCLK_MCLK1 1 | 15 | #define WM8994_SYSCLK_MCLK1 1 |
19 | #define WM8994_SYSCLK_MCLK2 2 | 16 | #define WM8994_SYSCLK_MCLK2 2 |
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 76b37ff6c264..00249d5b6793 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -156,7 +156,8 @@ static struct { | |||
156 | }; | 156 | }; |
157 | 157 | ||
158 | struct wm9081_priv { | 158 | struct wm9081_priv { |
159 | struct snd_soc_codec codec; | 159 | enum snd_soc_control_type control_type; |
160 | void *control_data; | ||
160 | u16 reg_cache[WM9081_MAX_REGISTER + 1]; | 161 | u16 reg_cache[WM9081_MAX_REGISTER + 1]; |
161 | int sysclk_source; | 162 | int sysclk_source; |
162 | int mclk_rate; | 163 | int mclk_rate; |
@@ -1212,8 +1213,8 @@ static struct snd_soc_dai_ops wm9081_dai_ops = { | |||
1212 | /* We report two channels because the CODEC processes a stereo signal, even | 1213 | /* We report two channels because the CODEC processes a stereo signal, even |
1213 | * though it is only capable of handling a mono output. | 1214 | * though it is only capable of handling a mono output. |
1214 | */ | 1215 | */ |
1215 | struct snd_soc_dai wm9081_dai = { | 1216 | static struct snd_soc_dai_driver wm9081_dai = { |
1216 | .name = "WM9081", | 1217 | .name = "wm9081-hifi", |
1217 | .playback = { | 1218 | .playback = { |
1218 | .stream_name = "HiFi Playback", | 1219 | .stream_name = "HiFi Playback", |
1219 | .channels_min = 1, | 1220 | .channels_min = 1, |
@@ -1223,34 +1224,42 @@ struct snd_soc_dai wm9081_dai = { | |||
1223 | }, | 1224 | }, |
1224 | .ops = &wm9081_dai_ops, | 1225 | .ops = &wm9081_dai_ops, |
1225 | }; | 1226 | }; |
1226 | EXPORT_SYMBOL_GPL(wm9081_dai); | ||
1227 | 1227 | ||
1228 | 1228 | static int wm9081_probe(struct snd_soc_codec *codec) | |
1229 | static struct snd_soc_codec *wm9081_codec; | ||
1230 | |||
1231 | static int wm9081_probe(struct platform_device *pdev) | ||
1232 | { | 1229 | { |
1233 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1230 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); |
1234 | struct snd_soc_codec *codec; | 1231 | int ret; |
1235 | struct wm9081_priv *wm9081; | 1232 | u16 reg; |
1236 | int ret = 0; | ||
1237 | 1233 | ||
1238 | if (wm9081_codec == NULL) { | 1234 | codec->control_data = wm9081->control_data; |
1239 | dev_err(&pdev->dev, "Codec device not registered\n"); | 1235 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type); |
1240 | return -ENODEV; | 1236 | if (ret != 0) { |
1237 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1238 | return ret; | ||
1241 | } | 1239 | } |
1242 | 1240 | ||
1243 | socdev->card->codec = wm9081_codec; | 1241 | reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET); |
1244 | codec = wm9081_codec; | 1242 | if (reg != 0x9081) { |
1245 | wm9081 = snd_soc_codec_get_drvdata(codec); | 1243 | dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg); |
1244 | ret = -EINVAL; | ||
1245 | return ret; | ||
1246 | } | ||
1246 | 1247 | ||
1247 | /* register pcms */ | 1248 | ret = wm9081_reset(codec); |
1248 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1249 | if (ret < 0) { | 1249 | if (ret < 0) { |
1250 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | 1250 | dev_err(codec->dev, "Failed to issue reset\n"); |
1251 | goto pcm_err; | 1251 | return ret; |
1252 | } | 1252 | } |
1253 | 1253 | ||
1254 | wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1255 | |||
1256 | /* Enable zero cross by default */ | ||
1257 | reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT); | ||
1258 | snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC); | ||
1259 | reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA); | ||
1260 | snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA, | ||
1261 | reg | WM9081_SPKPGAZC); | ||
1262 | |||
1254 | snd_soc_add_controls(codec, wm9081_snd_controls, | 1263 | snd_soc_add_controls(codec, wm9081_snd_controls, |
1255 | ARRAY_SIZE(wm9081_snd_controls)); | 1264 | ARRAY_SIZE(wm9081_snd_controls)); |
1256 | if (!wm9081->retune) { | 1265 | if (!wm9081->retune) { |
@@ -1265,40 +1274,28 @@ static int wm9081_probe(struct platform_device *pdev) | |||
1265 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 1274 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
1266 | 1275 | ||
1267 | return ret; | 1276 | return ret; |
1268 | |||
1269 | pcm_err: | ||
1270 | return ret; | ||
1271 | } | 1277 | } |
1272 | 1278 | ||
1273 | static int wm9081_remove(struct platform_device *pdev) | 1279 | static int wm9081_remove(struct snd_soc_codec *codec) |
1274 | { | 1280 | { |
1275 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1281 | wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1276 | |||
1277 | snd_soc_free_pcms(socdev); | ||
1278 | snd_soc_dapm_free(socdev); | ||
1279 | |||
1280 | return 0; | 1282 | return 0; |
1281 | } | 1283 | } |
1282 | 1284 | ||
1283 | #ifdef CONFIG_PM | 1285 | #ifdef CONFIG_PM |
1284 | static int wm9081_suspend(struct platform_device *pdev, pm_message_t state) | 1286 | static int wm9081_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1285 | { | 1287 | { |
1286 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1287 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1288 | |||
1289 | wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1288 | wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1290 | 1289 | ||
1291 | return 0; | 1290 | return 0; |
1292 | } | 1291 | } |
1293 | 1292 | ||
1294 | static int wm9081_resume(struct platform_device *pdev) | 1293 | static int wm9081_resume(struct snd_soc_codec *codec) |
1295 | { | 1294 | { |
1296 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1297 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1298 | u16 *reg_cache = codec->reg_cache; | 1295 | u16 *reg_cache = codec->reg_cache; |
1299 | int i; | 1296 | int i; |
1300 | 1297 | ||
1301 | for (i = 0; i < codec->reg_cache_size; i++) { | 1298 | for (i = 0; i < codec->driver->reg_cache_size; i++) { |
1302 | if (i == WM9081_SOFTWARE_RESET) | 1299 | if (i == WM9081_SOFTWARE_RESET) |
1303 | continue; | 1300 | continue; |
1304 | 1301 | ||
@@ -1314,133 +1311,43 @@ static int wm9081_resume(struct platform_device *pdev) | |||
1314 | #define wm9081_resume NULL | 1311 | #define wm9081_resume NULL |
1315 | #endif | 1312 | #endif |
1316 | 1313 | ||
1317 | struct snd_soc_codec_device soc_codec_dev_wm9081 = { | 1314 | static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { |
1318 | .probe = wm9081_probe, | 1315 | .probe = wm9081_probe, |
1319 | .remove = wm9081_remove, | 1316 | .remove = wm9081_remove, |
1320 | .suspend = wm9081_suspend, | 1317 | .suspend = wm9081_suspend, |
1321 | .resume = wm9081_resume, | 1318 | .resume = wm9081_resume, |
1319 | .set_bias_level = wm9081_set_bias_level, | ||
1320 | .reg_cache_size = sizeof(wm9081_reg_defaults), | ||
1321 | .reg_word_size = sizeof(u16), | ||
1322 | .reg_cache_default = wm9081_reg_defaults, | ||
1323 | .volatile_register = wm9081_volatile_register, | ||
1322 | }; | 1324 | }; |
1323 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081); | ||
1324 | |||
1325 | static int wm9081_register(struct wm9081_priv *wm9081, | ||
1326 | enum snd_soc_control_type control) | ||
1327 | { | ||
1328 | struct snd_soc_codec *codec = &wm9081->codec; | ||
1329 | int ret; | ||
1330 | u16 reg; | ||
1331 | |||
1332 | if (wm9081_codec) { | ||
1333 | dev_err(codec->dev, "Another WM9081 is registered\n"); | ||
1334 | ret = -EINVAL; | ||
1335 | goto err; | ||
1336 | } | ||
1337 | |||
1338 | mutex_init(&codec->mutex); | ||
1339 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1340 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1341 | |||
1342 | snd_soc_codec_set_drvdata(codec, wm9081); | ||
1343 | codec->name = "WM9081"; | ||
1344 | codec->owner = THIS_MODULE; | ||
1345 | codec->dai = &wm9081_dai; | ||
1346 | codec->num_dai = 1; | ||
1347 | codec->reg_cache_size = ARRAY_SIZE(wm9081->reg_cache); | ||
1348 | codec->reg_cache = &wm9081->reg_cache; | ||
1349 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1350 | codec->set_bias_level = wm9081_set_bias_level; | ||
1351 | codec->volatile_register = wm9081_volatile_register; | ||
1352 | |||
1353 | memcpy(codec->reg_cache, wm9081_reg_defaults, | ||
1354 | sizeof(wm9081_reg_defaults)); | ||
1355 | |||
1356 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); | ||
1357 | if (ret != 0) { | ||
1358 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1359 | goto err; | ||
1360 | } | ||
1361 | |||
1362 | reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET); | ||
1363 | if (reg != 0x9081) { | ||
1364 | dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg); | ||
1365 | ret = -EINVAL; | ||
1366 | goto err; | ||
1367 | } | ||
1368 | |||
1369 | ret = wm9081_reset(codec); | ||
1370 | if (ret < 0) { | ||
1371 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
1372 | goto err; | ||
1373 | } | ||
1374 | |||
1375 | wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1376 | |||
1377 | /* Enable zero cross by default */ | ||
1378 | reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT); | ||
1379 | snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC); | ||
1380 | reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA); | ||
1381 | snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA, | ||
1382 | reg | WM9081_SPKPGAZC); | ||
1383 | |||
1384 | wm9081_dai.dev = codec->dev; | ||
1385 | |||
1386 | wm9081_codec = codec; | ||
1387 | |||
1388 | ret = snd_soc_register_codec(codec); | ||
1389 | if (ret != 0) { | ||
1390 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
1391 | goto err; | ||
1392 | } | ||
1393 | |||
1394 | ret = snd_soc_register_dai(&wm9081_dai); | ||
1395 | if (ret != 0) { | ||
1396 | dev_err(codec->dev, "Failed to register DAI: %d\n", ret); | ||
1397 | goto err_codec; | ||
1398 | } | ||
1399 | |||
1400 | return 0; | ||
1401 | |||
1402 | err_codec: | ||
1403 | snd_soc_unregister_codec(codec); | ||
1404 | err: | ||
1405 | kfree(wm9081); | ||
1406 | return ret; | ||
1407 | } | ||
1408 | |||
1409 | static void wm9081_unregister(struct wm9081_priv *wm9081) | ||
1410 | { | ||
1411 | wm9081_set_bias_level(&wm9081->codec, SND_SOC_BIAS_OFF); | ||
1412 | snd_soc_unregister_dai(&wm9081_dai); | ||
1413 | snd_soc_unregister_codec(&wm9081->codec); | ||
1414 | kfree(wm9081); | ||
1415 | wm9081_codec = NULL; | ||
1416 | } | ||
1417 | 1325 | ||
1326 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1418 | static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, | 1327 | static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, |
1419 | const struct i2c_device_id *id) | 1328 | const struct i2c_device_id *id) |
1420 | { | 1329 | { |
1421 | struct wm9081_priv *wm9081; | 1330 | struct wm9081_priv *wm9081; |
1422 | struct snd_soc_codec *codec; | 1331 | int ret; |
1423 | 1332 | ||
1424 | wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL); | 1333 | wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL); |
1425 | if (wm9081 == NULL) | 1334 | if (wm9081 == NULL) |
1426 | return -ENOMEM; | 1335 | return -ENOMEM; |
1427 | 1336 | ||
1428 | codec = &wm9081->codec; | ||
1429 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1430 | wm9081->retune = i2c->dev.platform_data; | ||
1431 | |||
1432 | i2c_set_clientdata(i2c, wm9081); | 1337 | i2c_set_clientdata(i2c, wm9081); |
1433 | codec->control_data = i2c; | 1338 | wm9081->control_data = i2c; |
1434 | |||
1435 | codec->dev = &i2c->dev; | ||
1436 | 1339 | ||
1437 | return wm9081_register(wm9081, SND_SOC_I2C); | 1340 | ret = snd_soc_register_codec(&i2c->dev, |
1341 | &soc_codec_dev_wm9081, &wm9081_dai, 1); | ||
1342 | if (ret < 0) | ||
1343 | kfree(wm9081); | ||
1344 | return ret; | ||
1438 | } | 1345 | } |
1439 | 1346 | ||
1440 | static __devexit int wm9081_i2c_remove(struct i2c_client *client) | 1347 | static __devexit int wm9081_i2c_remove(struct i2c_client *client) |
1441 | { | 1348 | { |
1442 | struct wm9081_priv *wm9081 = i2c_get_clientdata(client); | 1349 | snd_soc_unregister_codec(&client->dev); |
1443 | wm9081_unregister(wm9081); | 1350 | kfree(i2c_get_clientdata(client)); |
1444 | return 0; | 1351 | return 0; |
1445 | } | 1352 | } |
1446 | 1353 | ||
@@ -1452,31 +1359,34 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id); | |||
1452 | 1359 | ||
1453 | static struct i2c_driver wm9081_i2c_driver = { | 1360 | static struct i2c_driver wm9081_i2c_driver = { |
1454 | .driver = { | 1361 | .driver = { |
1455 | .name = "wm9081", | 1362 | .name = "wm9081-codec", |
1456 | .owner = THIS_MODULE, | 1363 | .owner = THIS_MODULE, |
1457 | }, | 1364 | }, |
1458 | .probe = wm9081_i2c_probe, | 1365 | .probe = wm9081_i2c_probe, |
1459 | .remove = __devexit_p(wm9081_i2c_remove), | 1366 | .remove = __devexit_p(wm9081_i2c_remove), |
1460 | .id_table = wm9081_i2c_id, | 1367 | .id_table = wm9081_i2c_id, |
1461 | }; | 1368 | }; |
1369 | #endif | ||
1462 | 1370 | ||
1463 | static int __init wm9081_modinit(void) | 1371 | static int __init wm9081_modinit(void) |
1464 | { | 1372 | { |
1465 | int ret; | 1373 | int ret = 0; |
1466 | 1374 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1467 | ret = i2c_add_driver(&wm9081_i2c_driver); | 1375 | ret = i2c_add_driver(&wm9081_i2c_driver); |
1468 | if (ret != 0) { | 1376 | if (ret != 0) { |
1469 | printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n", | 1377 | printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n", |
1470 | ret); | 1378 | ret); |
1471 | } | 1379 | } |
1472 | 1380 | #endif | |
1473 | return ret; | 1381 | return ret; |
1474 | } | 1382 | } |
1475 | module_init(wm9081_modinit); | 1383 | module_init(wm9081_modinit); |
1476 | 1384 | ||
1477 | static void __exit wm9081_exit(void) | 1385 | static void __exit wm9081_exit(void) |
1478 | { | 1386 | { |
1387 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1479 | i2c_del_driver(&wm9081_i2c_driver); | 1388 | i2c_del_driver(&wm9081_i2c_driver); |
1389 | #endif | ||
1480 | } | 1390 | } |
1481 | module_exit(wm9081_exit); | 1391 | module_exit(wm9081_exit); |
1482 | 1392 | ||
diff --git a/sound/soc/codecs/wm9081.h b/sound/soc/codecs/wm9081.h index 42d3bc757021..871cccb066dc 100644 --- a/sound/soc/codecs/wm9081.h +++ b/sound/soc/codecs/wm9081.h | |||
@@ -15,9 +15,6 @@ | |||
15 | 15 | ||
16 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
17 | 17 | ||
18 | extern struct snd_soc_dai wm9081_dai; | ||
19 | extern struct snd_soc_codec_device soc_codec_dev_wm9081; | ||
20 | |||
21 | /* | 18 | /* |
22 | * SYSCLK sources | 19 | * SYSCLK sources |
23 | */ | 20 | */ |
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 1592250daec0..7a1825418ee4 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -34,8 +34,6 @@ | |||
34 | 34 | ||
35 | #include "wm9090.h" | 35 | #include "wm9090.h" |
36 | 36 | ||
37 | static struct snd_soc_codec *wm9090_codec; | ||
38 | |||
39 | static const u16 wm9090_reg_defaults[] = { | 37 | static const u16 wm9090_reg_defaults[] = { |
40 | 0x9093, /* R0 - Software Reset */ | 38 | 0x9093, /* R0 - Software Reset */ |
41 | 0x0006, /* R1 - Power Management (1) */ | 39 | 0x0006, /* R1 - Power Management (1) */ |
@@ -142,15 +140,10 @@ static const u16 wm9090_reg_defaults[] = { | |||
142 | 140 | ||
143 | /* This struct is used to save the context */ | 141 | /* This struct is used to save the context */ |
144 | struct wm9090_priv { | 142 | struct wm9090_priv { |
145 | /* We're not really registering as a CODEC since ASoC core | ||
146 | * does not yet support multiple CODECs but having the CODEC | ||
147 | * structure means we can reuse some of the ASoC core | ||
148 | * features. | ||
149 | */ | ||
150 | struct snd_soc_codec codec; | ||
151 | struct mutex mutex; | 143 | struct mutex mutex; |
152 | u16 reg_cache[WM9090_MAX_REGISTER + 1]; | 144 | u16 reg_cache[WM9090_MAX_REGISTER + 1]; |
153 | struct wm9090_platform_data pdata; | 145 | struct wm9090_platform_data pdata; |
146 | void *control_data; | ||
154 | }; | 147 | }; |
155 | 148 | ||
156 | static int wm9090_volatile(unsigned int reg) | 149 | static int wm9090_volatile(unsigned int reg) |
@@ -523,7 +516,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, | |||
523 | case SND_SOC_BIAS_STANDBY: | 516 | case SND_SOC_BIAS_STANDBY: |
524 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 517 | if (codec->bias_level == SND_SOC_BIAS_OFF) { |
525 | /* Restore the register cache */ | 518 | /* Restore the register cache */ |
526 | for (i = 1; i < codec->reg_cache_size; i++) { | 519 | for (i = 1; i < codec->driver->reg_cache_size; i++) { |
527 | if (reg_cache[i] == wm9090_reg_defaults[i]) | 520 | if (reg_cache[i] == wm9090_reg_defaults[i]) |
528 | continue; | 521 | continue; |
529 | if (wm9090_volatile(i)) | 522 | if (wm9090_volatile(i)) |
@@ -556,51 +549,67 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, | |||
556 | return 0; | 549 | return 0; |
557 | } | 550 | } |
558 | 551 | ||
559 | static int wm9090_probe(struct platform_device *pdev) | 552 | static int wm9090_probe(struct snd_soc_codec *codec) |
560 | { | 553 | { |
561 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 554 | struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); |
562 | struct snd_soc_codec *codec; | 555 | int ret; |
563 | int ret = 0; | ||
564 | 556 | ||
565 | if (wm9090_codec == NULL) { | 557 | codec->control_data = wm9090->control_data; |
566 | dev_err(&pdev->dev, "Codec device not registered\n"); | 558 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
567 | return -ENODEV; | 559 | if (ret != 0) { |
560 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
561 | return ret; | ||
568 | } | 562 | } |
569 | 563 | ||
570 | socdev->card->codec = wm9090_codec; | 564 | ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET); |
571 | codec = wm9090_codec; | 565 | if (ret < 0) |
572 | 566 | return ret; | |
573 | /* register pcms */ | 567 | if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) { |
574 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 568 | dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret); |
575 | if (ret < 0) { | 569 | return -EINVAL; |
576 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
577 | goto pcm_err; | ||
578 | } | 570 | } |
579 | 571 | ||
572 | ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0); | ||
573 | if (ret < 0) | ||
574 | return ret; | ||
575 | |||
576 | /* Configure some defaults; they will be written out when we | ||
577 | * bring the bias up. | ||
578 | */ | ||
579 | wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU | ||
580 | | WM9090_IN1A_ZC; | ||
581 | wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU | ||
582 | | WM9090_IN1B_ZC; | ||
583 | wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU | ||
584 | | WM9090_IN2A_ZC; | ||
585 | wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU | ||
586 | | WM9090_IN2B_ZC; | ||
587 | wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= | ||
588 | WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; | ||
589 | wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= | ||
590 | WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; | ||
591 | wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= | ||
592 | WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; | ||
593 | |||
594 | wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; | ||
595 | |||
596 | wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
597 | |||
580 | wm9090_add_controls(codec); | 598 | wm9090_add_controls(codec); |
581 | 599 | ||
582 | return 0; | 600 | return 0; |
583 | |||
584 | pcm_err: | ||
585 | return ret; | ||
586 | } | 601 | } |
587 | 602 | ||
588 | #ifdef CONFIG_PM | 603 | #ifdef CONFIG_PM |
589 | static int wm9090_suspend(struct platform_device *pdev, pm_message_t state) | 604 | static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state) |
590 | { | 605 | { |
591 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
592 | struct snd_soc_codec *codec = socdev->card->codec; | ||
593 | |||
594 | wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); | 606 | wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); |
595 | 607 | ||
596 | return 0; | 608 | return 0; |
597 | } | 609 | } |
598 | 610 | ||
599 | static int wm9090_resume(struct platform_device *pdev) | 611 | static int wm9090_resume(struct snd_soc_codec *codec) |
600 | { | 612 | { |
601 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
602 | struct snd_soc_codec *codec = socdev->card->codec; | ||
603 | |||
604 | wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 613 | wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
605 | 614 | ||
606 | return 0; | 615 | return 0; |
@@ -610,29 +619,29 @@ static int wm9090_resume(struct platform_device *pdev) | |||
610 | #define wm9090_resume NULL | 619 | #define wm9090_resume NULL |
611 | #endif | 620 | #endif |
612 | 621 | ||
613 | static int wm9090_remove(struct platform_device *pdev) | 622 | static int wm9090_remove(struct snd_soc_codec *codec) |
614 | { | 623 | { |
615 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 624 | wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); |
616 | |||
617 | snd_soc_free_pcms(socdev); | ||
618 | snd_soc_dapm_free(socdev); | ||
619 | 625 | ||
620 | return 0; | 626 | return 0; |
621 | } | 627 | } |
622 | 628 | ||
623 | struct snd_soc_codec_device soc_codec_dev_wm9090 = { | 629 | static struct snd_soc_codec_driver soc_codec_dev_wm9090 = { |
624 | .probe = wm9090_probe, | 630 | .probe = wm9090_probe, |
625 | .remove = wm9090_remove, | 631 | .remove = wm9090_remove, |
626 | .suspend = wm9090_suspend, | 632 | .suspend = wm9090_suspend, |
627 | .resume = wm9090_resume, | 633 | .resume = wm9090_resume, |
634 | .set_bias_level = wm9090_set_bias_level, | ||
635 | .reg_cache_size = (WM9090_MAX_REGISTER + 1), | ||
636 | .reg_word_size = sizeof(u16), | ||
637 | .reg_cache_default = wm9090_reg_defaults, | ||
638 | .volatile_register = wm9090_volatile, | ||
628 | }; | 639 | }; |
629 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm9090); | ||
630 | 640 | ||
631 | static int wm9090_i2c_probe(struct i2c_client *i2c, | 641 | static int wm9090_i2c_probe(struct i2c_client *i2c, |
632 | const struct i2c_device_id *id) | 642 | const struct i2c_device_id *id) |
633 | { | 643 | { |
634 | struct wm9090_priv *wm9090; | 644 | struct wm9090_priv *wm9090; |
635 | struct snd_soc_codec *codec; | ||
636 | int ret; | 645 | int ret; |
637 | 646 | ||
638 | wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL); | 647 | wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL); |
@@ -640,102 +649,28 @@ static int wm9090_i2c_probe(struct i2c_client *i2c, | |||
640 | dev_err(&i2c->dev, "Can not allocate memory\n"); | 649 | dev_err(&i2c->dev, "Can not allocate memory\n"); |
641 | return -ENOMEM; | 650 | return -ENOMEM; |
642 | } | 651 | } |
643 | codec = &wm9090->codec; | ||
644 | 652 | ||
645 | if (i2c->dev.platform_data) | 653 | if (i2c->dev.platform_data) |
646 | memcpy(&wm9090->pdata, i2c->dev.platform_data, | 654 | memcpy(&wm9090->pdata, i2c->dev.platform_data, |
647 | sizeof(wm9090->pdata)); | 655 | sizeof(wm9090->pdata)); |
648 | 656 | ||
649 | wm9090_codec = codec; | ||
650 | |||
651 | i2c_set_clientdata(i2c, wm9090); | 657 | i2c_set_clientdata(i2c, wm9090); |
658 | wm9090->control_data = i2c; | ||
659 | mutex_init(&wm9090->mutex); | ||
652 | 660 | ||
653 | mutex_init(&codec->mutex); | 661 | ret = snd_soc_register_codec(&i2c->dev, |
654 | INIT_LIST_HEAD(&codec->dapm_widgets); | 662 | &soc_codec_dev_wm9090, NULL, 0); |
655 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
656 | |||
657 | codec->control_data = i2c; | ||
658 | snd_soc_codec_set_drvdata(codec, wm9090); | ||
659 | codec->dev = &i2c->dev; | ||
660 | codec->name = "WM9090"; | ||
661 | codec->owner = THIS_MODULE; | ||
662 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
663 | codec->set_bias_level = wm9090_set_bias_level, | ||
664 | codec->reg_cache_size = WM9090_MAX_REGISTER + 1; | ||
665 | codec->reg_cache = &wm9090->reg_cache; | ||
666 | codec->volatile_register = wm9090_volatile; | ||
667 | |||
668 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | ||
669 | if (ret != 0) { | ||
670 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
671 | goto err; | ||
672 | } | ||
673 | |||
674 | memcpy(&wm9090->reg_cache, wm9090_reg_defaults, | ||
675 | sizeof(wm9090->reg_cache)); | ||
676 | |||
677 | ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET); | ||
678 | if (ret < 0) | ||
679 | goto err; | ||
680 | if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) { | ||
681 | dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", ret); | ||
682 | ret = -EINVAL; | ||
683 | goto err; | ||
684 | } | ||
685 | |||
686 | ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0); | ||
687 | if (ret < 0) | 663 | if (ret < 0) |
688 | goto err; | 664 | kfree(wm9090); |
689 | |||
690 | /* Configure some defaults; they will be written out when we | ||
691 | * bring the bias up. | ||
692 | */ | ||
693 | wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU | ||
694 | | WM9090_IN1A_ZC; | ||
695 | wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU | ||
696 | | WM9090_IN1B_ZC; | ||
697 | wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU | ||
698 | | WM9090_IN2A_ZC; | ||
699 | wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU | ||
700 | | WM9090_IN2B_ZC; | ||
701 | wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= | ||
702 | WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; | ||
703 | wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= | ||
704 | WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; | ||
705 | wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= | ||
706 | WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; | ||
707 | |||
708 | wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; | ||
709 | |||
710 | wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
711 | |||
712 | ret = snd_soc_register_codec(codec); | ||
713 | if (ret != 0) { | ||
714 | dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); | ||
715 | goto err_bias; | ||
716 | } | ||
717 | |||
718 | return 0; | ||
719 | |||
720 | err_bias: | ||
721 | wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
722 | err: | ||
723 | kfree(wm9090); | ||
724 | i2c_set_clientdata(i2c, NULL); | ||
725 | wm9090_codec = NULL; | ||
726 | |||
727 | return ret; | 665 | return ret; |
728 | } | 666 | } |
729 | 667 | ||
730 | static int wm9090_i2c_remove(struct i2c_client *i2c) | 668 | static int wm9090_i2c_remove(struct i2c_client *i2c) |
731 | { | 669 | { |
732 | struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c); | 670 | struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c); |
733 | struct snd_soc_codec *codec = &wm9090->codec; | ||
734 | 671 | ||
735 | snd_soc_unregister_codec(codec); | 672 | snd_soc_unregister_codec(&i2c->dev); |
736 | wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
737 | kfree(wm9090); | 673 | kfree(wm9090); |
738 | wm9090_codec = NULL; | ||
739 | 674 | ||
740 | return 0; | 675 | return 0; |
741 | } | 676 | } |
@@ -748,7 +683,7 @@ MODULE_DEVICE_TABLE(i2c, wm9090_id); | |||
748 | 683 | ||
749 | static struct i2c_driver wm9090_i2c_driver = { | 684 | static struct i2c_driver wm9090_i2c_driver = { |
750 | .driver = { | 685 | .driver = { |
751 | .name = "wm9090", | 686 | .name = "wm9090-codec", |
752 | .owner = THIS_MODULE, | 687 | .owner = THIS_MODULE, |
753 | }, | 688 | }, |
754 | .probe = wm9090_i2c_probe, | 689 | .probe = wm9090_i2c_probe, |
diff --git a/sound/soc/codecs/wm9090.h b/sound/soc/codecs/wm9090.h index b08eab932a5b..29b9d9fc70b4 100644 --- a/sound/soc/codecs/wm9090.h +++ b/sound/soc/codecs/wm9090.h | |||
@@ -23,8 +23,6 @@ | |||
23 | #ifndef __WM9090_H | 23 | #ifndef __WM9090_H |
24 | #define __WM9090_H | 24 | #define __WM9090_H |
25 | 25 | ||
26 | extern struct snd_soc_codec_device soc_codec_dev_wm9090; | ||
27 | |||
28 | /* | 26 | /* |
29 | * Register values. | 27 | * Register values. |
30 | */ | 28 | */ |
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 8793341849d1..e4d8f5339c51 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
@@ -248,8 +248,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
248 | { | 248 | { |
249 | struct snd_pcm_runtime *runtime = substream->runtime; | 249 | struct snd_pcm_runtime *runtime = substream->runtime; |
250 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 250 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
251 | struct snd_soc_device *socdev = rtd->socdev; | 251 | struct snd_soc_codec *codec = rtd->codec; |
252 | struct snd_soc_codec *codec = socdev->card->codec; | ||
253 | int reg; | 252 | int reg; |
254 | u16 vra; | 253 | u16 vra; |
255 | 254 | ||
@@ -273,9 +272,9 @@ static struct snd_soc_dai_ops wm9705_dai_ops = { | |||
273 | .prepare = ac97_prepare, | 272 | .prepare = ac97_prepare, |
274 | }; | 273 | }; |
275 | 274 | ||
276 | struct snd_soc_dai wm9705_dai[] = { | 275 | static struct snd_soc_dai_driver wm9705_dai[] = { |
277 | { | 276 | { |
278 | .name = "AC97 HiFi", | 277 | .name = "wm9705-hifi", |
279 | .ac97_control = 1, | 278 | .ac97_control = 1, |
280 | .playback = { | 279 | .playback = { |
281 | .stream_name = "HiFi Playback", | 280 | .stream_name = "HiFi Playback", |
@@ -294,7 +293,7 @@ struct snd_soc_dai wm9705_dai[] = { | |||
294 | .ops = &wm9705_dai_ops, | 293 | .ops = &wm9705_dai_ops, |
295 | }, | 294 | }, |
296 | { | 295 | { |
297 | .name = "AC97 Aux", | 296 | .name = "wm9705-aux", |
298 | .playback = { | 297 | .playback = { |
299 | .stream_name = "Aux Playback", | 298 | .stream_name = "Aux Playback", |
300 | .channels_min = 1, | 299 | .channels_min = 1, |
@@ -304,7 +303,6 @@ struct snd_soc_dai wm9705_dai[] = { | |||
304 | }, | 303 | }, |
305 | } | 304 | } |
306 | }; | 305 | }; |
307 | EXPORT_SYMBOL_GPL(wm9705_dai); | ||
308 | 306 | ||
309 | static int wm9705_reset(struct snd_soc_codec *codec) | 307 | static int wm9705_reset(struct snd_soc_codec *codec) |
310 | { | 308 | { |
@@ -318,20 +316,15 @@ static int wm9705_reset(struct snd_soc_codec *codec) | |||
318 | } | 316 | } |
319 | 317 | ||
320 | #ifdef CONFIG_PM | 318 | #ifdef CONFIG_PM |
321 | static int wm9705_soc_suspend(struct platform_device *pdev, pm_message_t msg) | 319 | static int wm9705_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg) |
322 | { | 320 | { |
323 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
324 | struct snd_soc_codec *codec = socdev->card->codec; | ||
325 | |||
326 | soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff); | 321 | soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff); |
327 | 322 | ||
328 | return 0; | 323 | return 0; |
329 | } | 324 | } |
330 | 325 | ||
331 | static int wm9705_soc_resume(struct platform_device *pdev) | 326 | static int wm9705_soc_resume(struct snd_soc_codec *codec) |
332 | { | 327 | { |
333 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
334 | struct snd_soc_codec *codec = socdev->card->codec; | ||
335 | int i, ret; | 328 | int i, ret; |
336 | u16 *cache = codec->reg_cache; | 329 | u16 *cache = codec->reg_cache; |
337 | 330 | ||
@@ -352,49 +345,18 @@ static int wm9705_soc_resume(struct platform_device *pdev) | |||
352 | #define wm9705_soc_resume NULL | 345 | #define wm9705_soc_resume NULL |
353 | #endif | 346 | #endif |
354 | 347 | ||
355 | static int wm9705_soc_probe(struct platform_device *pdev) | 348 | static int wm9705_soc_probe(struct snd_soc_codec *codec) |
356 | { | 349 | { |
357 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
358 | struct snd_soc_codec *codec; | ||
359 | int ret = 0; | 350 | int ret = 0; |
360 | 351 | ||
361 | printk(KERN_INFO "WM9705 SoC Audio Codec\n"); | 352 | printk(KERN_INFO "WM9705 SoC Audio Codec\n"); |
362 | 353 | ||
363 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), | ||
364 | GFP_KERNEL); | ||
365 | if (socdev->card->codec == NULL) | ||
366 | return -ENOMEM; | ||
367 | codec = socdev->card->codec; | ||
368 | mutex_init(&codec->mutex); | ||
369 | |||
370 | codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL); | ||
371 | if (codec->reg_cache == NULL) { | ||
372 | ret = -ENOMEM; | ||
373 | goto cache_err; | ||
374 | } | ||
375 | codec->reg_cache_size = sizeof(wm9705_reg); | ||
376 | codec->reg_cache_step = 2; | ||
377 | |||
378 | codec->name = "WM9705"; | ||
379 | codec->owner = THIS_MODULE; | ||
380 | codec->dai = wm9705_dai; | ||
381 | codec->num_dai = ARRAY_SIZE(wm9705_dai); | ||
382 | codec->write = ac97_write; | ||
383 | codec->read = ac97_read; | ||
384 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
385 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
386 | |||
387 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 354 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
388 | if (ret < 0) { | 355 | if (ret < 0) { |
389 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); | 356 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); |
390 | goto codec_err; | 357 | return ret; |
391 | } | 358 | } |
392 | 359 | ||
393 | /* register pcms */ | ||
394 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
395 | if (ret < 0) | ||
396 | goto pcm_err; | ||
397 | |||
398 | ret = wm9705_reset(codec); | 360 | ret = wm9705_reset(codec); |
399 | if (ret) | 361 | if (ret) |
400 | goto reset_err; | 362 | goto reset_err; |
@@ -406,40 +368,62 @@ static int wm9705_soc_probe(struct platform_device *pdev) | |||
406 | return 0; | 368 | return 0; |
407 | 369 | ||
408 | reset_err: | 370 | reset_err: |
409 | snd_soc_free_pcms(socdev); | ||
410 | pcm_err: | ||
411 | snd_soc_free_ac97_codec(codec); | 371 | snd_soc_free_ac97_codec(codec); |
412 | codec_err: | ||
413 | kfree(codec->reg_cache); | ||
414 | cache_err: | ||
415 | kfree(socdev->card->codec); | ||
416 | socdev->card->codec = NULL; | ||
417 | return ret; | 372 | return ret; |
418 | } | 373 | } |
419 | 374 | ||
420 | static int wm9705_soc_remove(struct platform_device *pdev) | 375 | static int wm9705_soc_remove(struct snd_soc_codec *codec) |
421 | { | 376 | { |
422 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
423 | struct snd_soc_codec *codec = socdev->card->codec; | ||
424 | |||
425 | if (codec == NULL) | ||
426 | return 0; | ||
427 | |||
428 | snd_soc_dapm_free(socdev); | ||
429 | snd_soc_free_pcms(socdev); | ||
430 | snd_soc_free_ac97_codec(codec); | 377 | snd_soc_free_ac97_codec(codec); |
431 | kfree(codec->reg_cache); | ||
432 | kfree(codec); | ||
433 | return 0; | 378 | return 0; |
434 | } | 379 | } |
435 | 380 | ||
436 | struct snd_soc_codec_device soc_codec_dev_wm9705 = { | 381 | static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { |
437 | .probe = wm9705_soc_probe, | 382 | .probe = wm9705_soc_probe, |
438 | .remove = wm9705_soc_remove, | 383 | .remove = wm9705_soc_remove, |
439 | .suspend = wm9705_soc_suspend, | 384 | .suspend = wm9705_soc_suspend, |
440 | .resume = wm9705_soc_resume, | 385 | .resume = wm9705_soc_resume, |
386 | .read = ac97_read, | ||
387 | .write = ac97_write, | ||
388 | .reg_cache_size = sizeof(wm9705_reg), | ||
389 | .reg_word_size = sizeof(u16), | ||
390 | .reg_cache_step = 2, | ||
391 | .reg_cache_default = wm9705_reg, | ||
392 | }; | ||
393 | |||
394 | static __devinit int wm9705_probe(struct platform_device *pdev) | ||
395 | { | ||
396 | return snd_soc_register_codec(&pdev->dev, | ||
397 | &soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai)); | ||
398 | } | ||
399 | |||
400 | static int __devexit wm9705_remove(struct platform_device *pdev) | ||
401 | { | ||
402 | snd_soc_unregister_codec(&pdev->dev); | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static struct platform_driver wm9705_codec_driver = { | ||
407 | .driver = { | ||
408 | .name = "wm9705-codec", | ||
409 | .owner = THIS_MODULE, | ||
410 | }, | ||
411 | |||
412 | .probe = wm9705_probe, | ||
413 | .remove = __devexit_p(wm9705_remove), | ||
441 | }; | 414 | }; |
442 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705); | 415 | |
416 | static int __init wm9705_init(void) | ||
417 | { | ||
418 | return platform_driver_register(&wm9705_codec_driver); | ||
419 | } | ||
420 | module_init(wm9705_init); | ||
421 | |||
422 | static void __exit wm9705_exit(void) | ||
423 | { | ||
424 | platform_driver_unregister(&wm9705_codec_driver); | ||
425 | } | ||
426 | module_exit(wm9705_exit); | ||
443 | 427 | ||
444 | MODULE_DESCRIPTION("ASoC WM9705 driver"); | 428 | MODULE_DESCRIPTION("ASoC WM9705 driver"); |
445 | MODULE_AUTHOR("Ian Molton"); | 429 | MODULE_AUTHOR("Ian Molton"); |
diff --git a/sound/soc/codecs/wm9705.h b/sound/soc/codecs/wm9705.h index d380f110f9e2..23ea9ce47359 100644 --- a/sound/soc/codecs/wm9705.h +++ b/sound/soc/codecs/wm9705.h | |||
@@ -8,7 +8,4 @@ | |||
8 | #define WM9705_DAI_AC97_HIFI 0 | 8 | #define WM9705_DAI_AC97_HIFI 0 |
9 | #define WM9705_DAI_AC97_AUX 1 | 9 | #define WM9705_DAI_AC97_AUX 1 |
10 | 10 | ||
11 | extern struct snd_soc_dai wm9705_dai[2]; | ||
12 | extern struct snd_soc_codec_device soc_codec_dev_wm9705; | ||
13 | |||
14 | #endif | 11 | #endif |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 28790a2ffe8d..f8f37ae30910 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -478,8 +478,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
478 | { | 478 | { |
479 | struct snd_pcm_runtime *runtime = substream->runtime; | 479 | struct snd_pcm_runtime *runtime = substream->runtime; |
480 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 480 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
481 | struct snd_soc_device *socdev = rtd->socdev; | 481 | struct snd_soc_codec *codec =rtd->codec; |
482 | struct snd_soc_codec *codec = socdev->card->codec; | ||
483 | int reg; | 482 | int reg; |
484 | u16 vra; | 483 | u16 vra; |
485 | 484 | ||
@@ -499,8 +498,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream, | |||
499 | { | 498 | { |
500 | struct snd_pcm_runtime *runtime = substream->runtime; | 499 | struct snd_pcm_runtime *runtime = substream->runtime; |
501 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 500 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
502 | struct snd_soc_device *socdev = rtd->socdev; | 501 | struct snd_soc_codec *codec = rtd->codec; |
503 | struct snd_soc_codec *codec = socdev->card->codec; | ||
504 | u16 vra, xsle; | 502 | u16 vra, xsle; |
505 | 503 | ||
506 | vra = ac97_read(codec, AC97_EXTENDED_STATUS); | 504 | vra = ac97_read(codec, AC97_EXTENDED_STATUS); |
@@ -526,9 +524,9 @@ static struct snd_soc_dai_ops wm9712_dai_ops_aux = { | |||
526 | .prepare = ac97_aux_prepare, | 524 | .prepare = ac97_aux_prepare, |
527 | }; | 525 | }; |
528 | 526 | ||
529 | struct snd_soc_dai wm9712_dai[] = { | 527 | struct snd_soc_dai_driver wm9712_dai[] = { |
530 | { | 528 | { |
531 | .name = "AC97 HiFi", | 529 | .name = "wm9712-hifi", |
532 | .ac97_control = 1, | 530 | .ac97_control = 1, |
533 | .playback = { | 531 | .playback = { |
534 | .stream_name = "HiFi Playback", | 532 | .stream_name = "HiFi Playback", |
@@ -545,7 +543,7 @@ struct snd_soc_dai wm9712_dai[] = { | |||
545 | .ops = &wm9712_dai_ops_hifi, | 543 | .ops = &wm9712_dai_ops_hifi, |
546 | }, | 544 | }, |
547 | { | 545 | { |
548 | .name = "AC97 Aux", | 546 | .name = "wm9712-aux", |
549 | .playback = { | 547 | .playback = { |
550 | .stream_name = "Aux Playback", | 548 | .stream_name = "Aux Playback", |
551 | .channels_min = 1, | 549 | .channels_min = 1, |
@@ -555,7 +553,6 @@ struct snd_soc_dai wm9712_dai[] = { | |||
555 | .ops = &wm9712_dai_ops_aux, | 553 | .ops = &wm9712_dai_ops_aux, |
556 | } | 554 | } |
557 | }; | 555 | }; |
558 | EXPORT_SYMBOL_GPL(wm9712_dai); | ||
559 | 556 | ||
560 | static int wm9712_set_bias_level(struct snd_soc_codec *codec, | 557 | static int wm9712_set_bias_level(struct snd_soc_codec *codec, |
561 | enum snd_soc_bias_level level) | 558 | enum snd_soc_bias_level level) |
@@ -597,20 +594,15 @@ err: | |||
597 | return -EIO; | 594 | return -EIO; |
598 | } | 595 | } |
599 | 596 | ||
600 | static int wm9712_soc_suspend(struct platform_device *pdev, | 597 | static int wm9712_soc_suspend(struct snd_soc_codec *codec, |
601 | pm_message_t state) | 598 | pm_message_t state) |
602 | { | 599 | { |
603 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
604 | struct snd_soc_codec *codec = socdev->card->codec; | ||
605 | |||
606 | wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF); | 600 | wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF); |
607 | return 0; | 601 | return 0; |
608 | } | 602 | } |
609 | 603 | ||
610 | static int wm9712_soc_resume(struct platform_device *pdev) | 604 | static int wm9712_soc_resume(struct snd_soc_codec *codec) |
611 | { | 605 | { |
612 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
613 | struct snd_soc_codec *codec = socdev->card->codec; | ||
614 | int i, ret; | 606 | int i, ret; |
615 | u16 *cache = codec->reg_cache; | 607 | u16 *cache = codec->reg_cache; |
616 | 608 | ||
@@ -635,51 +627,18 @@ static int wm9712_soc_resume(struct platform_device *pdev) | |||
635 | return ret; | 627 | return ret; |
636 | } | 628 | } |
637 | 629 | ||
638 | static int wm9712_soc_probe(struct platform_device *pdev) | 630 | static int wm9712_soc_probe(struct snd_soc_codec *codec) |
639 | { | 631 | { |
640 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
641 | struct snd_soc_codec *codec; | ||
642 | int ret = 0; | 632 | int ret = 0; |
643 | 633 | ||
644 | printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION); | 634 | printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION); |
645 | 635 | ||
646 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), | ||
647 | GFP_KERNEL); | ||
648 | if (socdev->card->codec == NULL) | ||
649 | return -ENOMEM; | ||
650 | codec = socdev->card->codec; | ||
651 | mutex_init(&codec->mutex); | ||
652 | |||
653 | codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL); | ||
654 | |||
655 | if (codec->reg_cache == NULL) { | ||
656 | ret = -ENOMEM; | ||
657 | goto cache_err; | ||
658 | } | ||
659 | codec->reg_cache_size = sizeof(wm9712_reg); | ||
660 | codec->reg_cache_step = 2; | ||
661 | |||
662 | codec->name = "WM9712"; | ||
663 | codec->owner = THIS_MODULE; | ||
664 | codec->dai = wm9712_dai; | ||
665 | codec->num_dai = ARRAY_SIZE(wm9712_dai); | ||
666 | codec->write = ac97_write; | ||
667 | codec->read = ac97_read; | ||
668 | codec->set_bias_level = wm9712_set_bias_level; | ||
669 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
670 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
671 | |||
672 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 636 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
673 | if (ret < 0) { | 637 | if (ret < 0) { |
674 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); | 638 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); |
675 | goto codec_err; | 639 | return ret; |
676 | } | 640 | } |
677 | 641 | ||
678 | /* register pcms */ | ||
679 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
680 | if (ret < 0) | ||
681 | goto pcm_err; | ||
682 | |||
683 | ret = wm9712_reset(codec, 0); | 642 | ret = wm9712_reset(codec, 0); |
684 | if (ret < 0) { | 643 | if (ret < 0) { |
685 | printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); | 644 | printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); |
@@ -697,42 +656,63 @@ static int wm9712_soc_probe(struct platform_device *pdev) | |||
697 | return 0; | 656 | return 0; |
698 | 657 | ||
699 | reset_err: | 658 | reset_err: |
700 | snd_soc_free_pcms(socdev); | ||
701 | pcm_err: | ||
702 | snd_soc_free_ac97_codec(codec); | 659 | snd_soc_free_ac97_codec(codec); |
703 | |||
704 | codec_err: | ||
705 | kfree(codec->reg_cache); | ||
706 | |||
707 | cache_err: | ||
708 | kfree(socdev->card->codec); | ||
709 | socdev->card->codec = NULL; | ||
710 | return ret; | 660 | return ret; |
711 | } | 661 | } |
712 | 662 | ||
713 | static int wm9712_soc_remove(struct platform_device *pdev) | 663 | static int wm9712_soc_remove(struct snd_soc_codec *codec) |
714 | { | 664 | { |
715 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
716 | struct snd_soc_codec *codec = socdev->card->codec; | ||
717 | |||
718 | if (codec == NULL) | ||
719 | return 0; | ||
720 | |||
721 | snd_soc_dapm_free(socdev); | ||
722 | snd_soc_free_pcms(socdev); | ||
723 | snd_soc_free_ac97_codec(codec); | 665 | snd_soc_free_ac97_codec(codec); |
724 | kfree(codec->reg_cache); | ||
725 | kfree(codec); | ||
726 | return 0; | 666 | return 0; |
727 | } | 667 | } |
728 | 668 | ||
729 | struct snd_soc_codec_device soc_codec_dev_wm9712 = { | 669 | static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { |
730 | .probe = wm9712_soc_probe, | 670 | .probe = wm9712_soc_probe, |
731 | .remove = wm9712_soc_remove, | 671 | .remove = wm9712_soc_remove, |
732 | .suspend = wm9712_soc_suspend, | 672 | .suspend = wm9712_soc_suspend, |
733 | .resume = wm9712_soc_resume, | 673 | .resume = wm9712_soc_resume, |
674 | .read = ac97_read, | ||
675 | .write = ac97_write, | ||
676 | .set_bias_level = wm9712_set_bias_level, | ||
677 | .reg_cache_size = sizeof(wm9712_reg), | ||
678 | .reg_word_size = sizeof(u16), | ||
679 | .reg_cache_step = 2, | ||
680 | .reg_cache_default = wm9712_reg, | ||
734 | }; | 681 | }; |
735 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712); | 682 | |
683 | static __devinit int wm9712_probe(struct platform_device *pdev) | ||
684 | { | ||
685 | return snd_soc_register_codec(&pdev->dev, | ||
686 | &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai)); | ||
687 | } | ||
688 | |||
689 | static int __devexit wm9712_remove(struct platform_device *pdev) | ||
690 | { | ||
691 | snd_soc_unregister_codec(&pdev->dev); | ||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | static struct platform_driver wm9712_codec_driver = { | ||
696 | .driver = { | ||
697 | .name = "wm9712-codec", | ||
698 | .owner = THIS_MODULE, | ||
699 | }, | ||
700 | |||
701 | .probe = wm9712_probe, | ||
702 | .remove = __devexit_p(wm9712_remove), | ||
703 | }; | ||
704 | |||
705 | static int __init wm9712_init(void) | ||
706 | { | ||
707 | return platform_driver_register(&wm9712_codec_driver); | ||
708 | } | ||
709 | module_init(wm9712_init); | ||
710 | |||
711 | static void __exit wm9712_exit(void) | ||
712 | { | ||
713 | platform_driver_unregister(&wm9712_codec_driver); | ||
714 | } | ||
715 | module_exit(wm9712_exit); | ||
736 | 716 | ||
737 | MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver"); | 717 | MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver"); |
738 | MODULE_AUTHOR("Liam Girdwood"); | 718 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/wm9712.h b/sound/soc/codecs/wm9712.h index d29e8a18ca6d..fb69c3aa4ed0 100644 --- a/sound/soc/codecs/wm9712.h +++ b/sound/soc/codecs/wm9712.h | |||
@@ -8,7 +8,4 @@ | |||
8 | #define WM9712_DAI_AC97_HIFI 0 | 8 | #define WM9712_DAI_AC97_HIFI 0 |
9 | #define WM9712_DAI_AC97_AUX 1 | 9 | #define WM9712_DAI_AC97_AUX 1 |
10 | 10 | ||
11 | extern struct snd_soc_dai wm9712_dai[2]; | ||
12 | extern struct snd_soc_codec_device soc_codec_dev_wm9712; | ||
13 | |||
14 | #endif | 11 | #endif |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 34e0c91092fa..463917e762b5 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -1057,9 +1057,9 @@ static struct snd_soc_dai_ops wm9713_dai_ops_voice = { | |||
1057 | .set_tristate = wm9713_set_dai_tristate, | 1057 | .set_tristate = wm9713_set_dai_tristate, |
1058 | }; | 1058 | }; |
1059 | 1059 | ||
1060 | struct snd_soc_dai wm9713_dai[] = { | 1060 | static struct snd_soc_dai_driver wm9713_dai[] = { |
1061 | { | 1061 | { |
1062 | .name = "AC97 HiFi", | 1062 | .name = "wm9713-hifi", |
1063 | .ac97_control = 1, | 1063 | .ac97_control = 1, |
1064 | .playback = { | 1064 | .playback = { |
1065 | .stream_name = "HiFi Playback", | 1065 | .stream_name = "HiFi Playback", |
@@ -1076,7 +1076,7 @@ struct snd_soc_dai wm9713_dai[] = { | |||
1076 | .ops = &wm9713_dai_ops_hifi, | 1076 | .ops = &wm9713_dai_ops_hifi, |
1077 | }, | 1077 | }, |
1078 | { | 1078 | { |
1079 | .name = "AC97 Aux", | 1079 | .name = "wm9713-aux", |
1080 | .playback = { | 1080 | .playback = { |
1081 | .stream_name = "Aux Playback", | 1081 | .stream_name = "Aux Playback", |
1082 | .channels_min = 1, | 1082 | .channels_min = 1, |
@@ -1086,7 +1086,7 @@ struct snd_soc_dai wm9713_dai[] = { | |||
1086 | .ops = &wm9713_dai_ops_aux, | 1086 | .ops = &wm9713_dai_ops_aux, |
1087 | }, | 1087 | }, |
1088 | { | 1088 | { |
1089 | .name = "WM9713 Voice", | 1089 | .name = "wm9713-voice", |
1090 | .playback = { | 1090 | .playback = { |
1091 | .stream_name = "Voice Playback", | 1091 | .stream_name = "Voice Playback", |
1092 | .channels_min = 1, | 1092 | .channels_min = 1, |
@@ -1103,7 +1103,6 @@ struct snd_soc_dai wm9713_dai[] = { | |||
1103 | .symmetric_rates = 1, | 1103 | .symmetric_rates = 1, |
1104 | }, | 1104 | }, |
1105 | }; | 1105 | }; |
1106 | EXPORT_SYMBOL_GPL(wm9713_dai); | ||
1107 | 1106 | ||
1108 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) | 1107 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) |
1109 | { | 1108 | { |
@@ -1152,11 +1151,9 @@ static int wm9713_set_bias_level(struct snd_soc_codec *codec, | |||
1152 | return 0; | 1151 | return 0; |
1153 | } | 1152 | } |
1154 | 1153 | ||
1155 | static int wm9713_soc_suspend(struct platform_device *pdev, | 1154 | static int wm9713_soc_suspend(struct snd_soc_codec *codec, |
1156 | pm_message_t state) | 1155 | pm_message_t state) |
1157 | { | 1156 | { |
1158 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1159 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1160 | u16 reg; | 1157 | u16 reg; |
1161 | 1158 | ||
1162 | /* Disable everything except touchpanel - that will be handled | 1159 | /* Disable everything except touchpanel - that will be handled |
@@ -1171,10 +1168,8 @@ static int wm9713_soc_suspend(struct platform_device *pdev, | |||
1171 | return 0; | 1168 | return 0; |
1172 | } | 1169 | } |
1173 | 1170 | ||
1174 | static int wm9713_soc_resume(struct platform_device *pdev) | 1171 | static int wm9713_soc_resume(struct snd_soc_codec *codec) |
1175 | { | 1172 | { |
1176 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1177 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1178 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | 1173 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
1179 | int i, ret; | 1174 | int i, ret; |
1180 | u16 *cache = codec->reg_cache; | 1175 | u16 *cache = codec->reg_cache; |
@@ -1204,53 +1199,20 @@ static int wm9713_soc_resume(struct platform_device *pdev) | |||
1204 | return ret; | 1199 | return ret; |
1205 | } | 1200 | } |
1206 | 1201 | ||
1207 | static int wm9713_soc_probe(struct platform_device *pdev) | 1202 | static int wm9713_soc_probe(struct snd_soc_codec *codec) |
1208 | { | 1203 | { |
1209 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1204 | struct wm9713_priv *wm9713; |
1210 | struct snd_soc_codec *codec; | ||
1211 | int ret = 0, reg; | 1205 | int ret = 0, reg; |
1212 | 1206 | ||
1213 | socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), | 1207 | wm9713 = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL); |
1214 | GFP_KERNEL); | 1208 | if (wm9713 == NULL) |
1215 | if (socdev->card->codec == NULL) | ||
1216 | return -ENOMEM; | 1209 | return -ENOMEM; |
1217 | codec = socdev->card->codec; | 1210 | snd_soc_codec_set_drvdata(codec, wm9713); |
1218 | mutex_init(&codec->mutex); | ||
1219 | |||
1220 | codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL); | ||
1221 | if (codec->reg_cache == NULL) { | ||
1222 | ret = -ENOMEM; | ||
1223 | goto cache_err; | ||
1224 | } | ||
1225 | codec->reg_cache_size = sizeof(wm9713_reg); | ||
1226 | codec->reg_cache_step = 2; | ||
1227 | |||
1228 | snd_soc_codec_set_drvdata(codec, kzalloc(sizeof(struct wm9713_priv), | ||
1229 | GFP_KERNEL)); | ||
1230 | if (snd_soc_codec_get_drvdata(codec) == NULL) { | ||
1231 | ret = -ENOMEM; | ||
1232 | goto priv_err; | ||
1233 | } | ||
1234 | |||
1235 | codec->name = "WM9713"; | ||
1236 | codec->owner = THIS_MODULE; | ||
1237 | codec->dai = wm9713_dai; | ||
1238 | codec->num_dai = ARRAY_SIZE(wm9713_dai); | ||
1239 | codec->write = ac97_write; | ||
1240 | codec->read = ac97_read; | ||
1241 | codec->set_bias_level = wm9713_set_bias_level; | ||
1242 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1243 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1244 | 1211 | ||
1245 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 1212 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
1246 | if (ret < 0) | 1213 | if (ret < 0) |
1247 | goto codec_err; | 1214 | goto codec_err; |
1248 | 1215 | ||
1249 | /* register pcms */ | ||
1250 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1251 | if (ret < 0) | ||
1252 | goto pcm_err; | ||
1253 | |||
1254 | /* do a cold reset for the controller and then try | 1216 | /* do a cold reset for the controller and then try |
1255 | * a warm reset followed by an optional cold reset for codec */ | 1217 | * a warm reset followed by an optional cold reset for codec */ |
1256 | wm9713_reset(codec, 0); | 1218 | wm9713_reset(codec, 0); |
@@ -1273,46 +1235,67 @@ static int wm9713_soc_probe(struct platform_device *pdev) | |||
1273 | return 0; | 1235 | return 0; |
1274 | 1236 | ||
1275 | reset_err: | 1237 | reset_err: |
1276 | snd_soc_free_pcms(socdev); | ||
1277 | pcm_err: | ||
1278 | snd_soc_free_ac97_codec(codec); | 1238 | snd_soc_free_ac97_codec(codec); |
1279 | |||
1280 | codec_err: | 1239 | codec_err: |
1281 | kfree(snd_soc_codec_get_drvdata(codec)); | 1240 | kfree(wm9713); |
1282 | |||
1283 | priv_err: | ||
1284 | kfree(codec->reg_cache); | ||
1285 | |||
1286 | cache_err: | ||
1287 | kfree(socdev->card->codec); | ||
1288 | socdev->card->codec = NULL; | ||
1289 | return ret; | 1241 | return ret; |
1290 | } | 1242 | } |
1291 | 1243 | ||
1292 | static int wm9713_soc_remove(struct platform_device *pdev) | 1244 | static int wm9713_soc_remove(struct snd_soc_codec *codec) |
1293 | { | 1245 | { |
1294 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1246 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
1295 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1296 | |||
1297 | if (codec == NULL) | ||
1298 | return 0; | ||
1299 | |||
1300 | snd_soc_dapm_free(socdev); | ||
1301 | snd_soc_free_pcms(socdev); | ||
1302 | snd_soc_free_ac97_codec(codec); | 1247 | snd_soc_free_ac97_codec(codec); |
1303 | kfree(snd_soc_codec_get_drvdata(codec)); | 1248 | kfree(wm9713); |
1304 | kfree(codec->reg_cache); | ||
1305 | kfree(codec); | ||
1306 | return 0; | 1249 | return 0; |
1307 | } | 1250 | } |
1308 | 1251 | ||
1309 | struct snd_soc_codec_device soc_codec_dev_wm9713 = { | 1252 | static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { |
1310 | .probe = wm9713_soc_probe, | 1253 | .probe = wm9713_soc_probe, |
1311 | .remove = wm9713_soc_remove, | 1254 | .remove = wm9713_soc_remove, |
1312 | .suspend = wm9713_soc_suspend, | 1255 | .suspend = wm9713_soc_suspend, |
1313 | .resume = wm9713_soc_resume, | 1256 | .resume = wm9713_soc_resume, |
1257 | .read = ac97_read, | ||
1258 | .write = ac97_write, | ||
1259 | .set_bias_level = wm9713_set_bias_level, | ||
1260 | .reg_cache_size = sizeof(wm9713_reg), | ||
1261 | .reg_word_size = sizeof(u16), | ||
1262 | .reg_cache_step = 2, | ||
1263 | .reg_cache_default = wm9713_reg, | ||
1264 | }; | ||
1265 | |||
1266 | static __devinit int wm9713_probe(struct platform_device *pdev) | ||
1267 | { | ||
1268 | return snd_soc_register_codec(&pdev->dev, | ||
1269 | &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai)); | ||
1270 | } | ||
1271 | |||
1272 | static int __devexit wm9713_remove(struct platform_device *pdev) | ||
1273 | { | ||
1274 | snd_soc_unregister_codec(&pdev->dev); | ||
1275 | return 0; | ||
1276 | } | ||
1277 | |||
1278 | static struct platform_driver wm9713_codec_driver = { | ||
1279 | .driver = { | ||
1280 | .name = "wm9713-codec", | ||
1281 | .owner = THIS_MODULE, | ||
1282 | }, | ||
1283 | |||
1284 | .probe = wm9713_probe, | ||
1285 | .remove = __devexit_p(wm9713_remove), | ||
1314 | }; | 1286 | }; |
1315 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm9713); | 1287 | |
1288 | static int __init wm9713_init(void) | ||
1289 | { | ||
1290 | return platform_driver_register(&wm9713_codec_driver); | ||
1291 | } | ||
1292 | module_init(wm9713_init); | ||
1293 | |||
1294 | static void __exit wm9713_exit(void) | ||
1295 | { | ||
1296 | platform_driver_unregister(&wm9713_codec_driver); | ||
1297 | } | ||
1298 | module_exit(wm9713_exit); | ||
1316 | 1299 | ||
1317 | MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver"); | 1300 | MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver"); |
1318 | MODULE_AUTHOR("Liam Girdwood"); | 1301 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h index 63b8d81756e3..793da863a03d 100644 --- a/sound/soc/codecs/wm9713.h +++ b/sound/soc/codecs/wm9713.h | |||
@@ -45,9 +45,6 @@ | |||
45 | #define WM9713_DAI_AC97_AUX 1 | 45 | #define WM9713_DAI_AC97_AUX 1 |
46 | #define WM9713_DAI_PCM_VOICE 2 | 46 | #define WM9713_DAI_PCM_VOICE 2 |
47 | 47 | ||
48 | extern struct snd_soc_codec_device soc_codec_dev_wm9713; | ||
49 | extern struct snd_soc_dai wm9713_dai[3]; | ||
50 | |||
51 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm); | 48 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm); |
52 | 49 | ||
53 | #endif | 50 | #endif |