diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2014-11-10 16:41:46 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-11-18 10:26:06 -0500 |
commit | 336b8423e285174ebecf02a743d69913b83bbc48 (patch) | |
tree | 68df16c040d0624e6e6c7979e0d9de8db51bafee | |
parent | 70f3af3ca15affaef3d026a5aa6e44c4627ea6c7 (diff) |
ASoC: Move AC'97 support to its own file
Currently the AC'97 support is splattered all throughout soc-core.c. Some
parts are #ifdef'd some parts are not. This patch moves the AC'97 support to
its own file, this should make the code a bit more clearer and also makes it
possible to easily not compile it into the kernel when not needed.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | include/sound/soc.h | 28 | ||||
-rw-r--r-- | sound/soc/Makefile | 4 | ||||
-rw-r--r-- | sound/soc/soc-ac97.c | 382 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 352 |
4 files changed, 416 insertions, 350 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h index 7ba7130037a0..adef34fa5209 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -366,8 +366,6 @@ struct snd_soc_jack_gpio; | |||
366 | 366 | ||
367 | typedef int (*hw_write_t)(void *,const char* ,int); | 367 | typedef int (*hw_write_t)(void *,const char* ,int); |
368 | 368 | ||
369 | extern struct snd_ac97_bus_ops *soc_ac97_ops; | ||
370 | |||
371 | enum snd_soc_pcm_subclass { | 369 | enum snd_soc_pcm_subclass { |
372 | SND_SOC_PCM_CLASS_PCM = 0, | 370 | SND_SOC_PCM_CLASS_PCM = 0, |
373 | SND_SOC_PCM_CLASS_BE = 1, | 371 | SND_SOC_PCM_CLASS_BE = 1, |
@@ -500,6 +498,7 @@ int snd_soc_update_bits_locked(struct snd_soc_codec *codec, | |||
500 | int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg, | 498 | int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg, |
501 | unsigned int mask, unsigned int value); | 499 | unsigned int mask, unsigned int value); |
502 | 500 | ||
501 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
503 | int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | 502 | int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, |
504 | struct snd_ac97_bus_ops *ops, int num); | 503 | struct snd_ac97_bus_ops *ops, int num); |
505 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); | 504 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); |
@@ -508,6 +507,31 @@ int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops); | |||
508 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | 507 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, |
509 | struct platform_device *pdev); | 508 | struct platform_device *pdev); |
510 | 509 | ||
510 | extern struct snd_ac97_bus_ops *soc_ac97_ops; | ||
511 | |||
512 | int snd_soc_ac97_register_dai_links(struct snd_soc_card *card); | ||
513 | void snd_soc_ac97_add_pdata(struct snd_soc_pcm_runtime *rtd); | ||
514 | #else | ||
515 | |||
516 | static inline int snd_soc_ac97_register_dai_links(struct snd_soc_card *card) | ||
517 | { | ||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | static inline void snd_soc_ac97_add_pdata(struct snd_soc_pcm_runtime *rtd) {} | ||
522 | |||
523 | static inline int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | ||
524 | struct platform_device *pdev) | ||
525 | { | ||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | static inline int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | ||
530 | { | ||
531 | return 0; | ||
532 | } | ||
533 | #endif | ||
534 | |||
511 | /* | 535 | /* |
512 | *Controls | 536 | *Controls |
513 | */ | 537 | */ |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 534714a1ca44..0fded1bb613f 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -5,6 +5,10 @@ ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) | |||
5 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o | 5 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o |
6 | endif | 6 | endif |
7 | 7 | ||
8 | ifneq ($(CONFIG_SND_SOC_AC97_BUS),) | ||
9 | snd-soc-core-objs += soc-ac97.o | ||
10 | endif | ||
11 | |||
8 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o | 12 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o |
9 | obj-$(CONFIG_SND_SOC) += codecs/ | 13 | obj-$(CONFIG_SND_SOC) += codecs/ |
10 | obj-$(CONFIG_SND_SOC) += generic/ | 14 | obj-$(CONFIG_SND_SOC) += generic/ |
diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c new file mode 100644 index 000000000000..da7b031a6eea --- /dev/null +++ b/sound/soc/soc-ac97.c | |||
@@ -0,0 +1,382 @@ | |||
1 | /* | ||
2 | * soc-ac97.c -- ALSA SoC Audio Layer AC97 support | ||
3 | * | ||
4 | * Copyright 2005 Wolfson Microelectronics PLC. | ||
5 | * Copyright 2005 Openedhand Ltd. | ||
6 | * Copyright (C) 2010 Slimlogic Ltd. | ||
7 | * Copyright (C) 2010 Texas Instruments Inc. | ||
8 | * | ||
9 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> | ||
10 | * with code, comments and ideas from :- | ||
11 | * Richard Purdie <richard@openedhand.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | */ | ||
18 | |||
19 | #include <linux/ctype.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/export.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/of_gpio.h> | ||
25 | #include <linux/of.h> | ||
26 | #include <linux/pinctrl/consumer.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <sound/ac97_codec.h> | ||
29 | #include <sound/soc.h> | ||
30 | |||
31 | struct snd_ac97_reset_cfg { | ||
32 | struct pinctrl *pctl; | ||
33 | struct pinctrl_state *pstate_reset; | ||
34 | struct pinctrl_state *pstate_warm_reset; | ||
35 | struct pinctrl_state *pstate_run; | ||
36 | int gpio_sdata; | ||
37 | int gpio_sync; | ||
38 | int gpio_reset; | ||
39 | }; | ||
40 | |||
41 | /* unregister ac97 codec */ | ||
42 | static int soc_ac97_dev_unregister(struct snd_soc_codec *codec) | ||
43 | { | ||
44 | if (codec->ac97->dev.bus) | ||
45 | device_del(&codec->ac97->dev); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | /* register ac97 codec to bus */ | ||
50 | static int soc_ac97_dev_register(struct snd_soc_codec *codec) | ||
51 | { | ||
52 | int err; | ||
53 | |||
54 | codec->ac97->dev.bus = &ac97_bus_type; | ||
55 | codec->ac97->dev.parent = codec->component.card->dev; | ||
56 | |||
57 | dev_set_name(&codec->ac97->dev, "%d-%d:%s", | ||
58 | codec->component.card->snd_card->number, 0, | ||
59 | codec->component.name); | ||
60 | err = device_add(&codec->ac97->dev); | ||
61 | if (err < 0) { | ||
62 | dev_err(codec->dev, "ASoC: Can't register ac97 bus\n"); | ||
63 | codec->ac97->dev.bus = NULL; | ||
64 | return err; | ||
65 | } | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static int soc_register_ac97_codec(struct snd_soc_codec *codec, | ||
70 | struct snd_soc_dai *codec_dai) | ||
71 | { | ||
72 | int ret; | ||
73 | |||
74 | /* Only instantiate AC97 if not already done by the adaptor | ||
75 | * for the generic AC97 subsystem. | ||
76 | */ | ||
77 | if (codec_dai->driver->ac97_control && !codec->ac97_registered) { | ||
78 | /* | ||
79 | * It is possible that the AC97 device is already registered to | ||
80 | * the device subsystem. This happens when the device is created | ||
81 | * via snd_ac97_mixer(). Currently only SoC codec that does so | ||
82 | * is the generic AC97 glue but others migh emerge. | ||
83 | * | ||
84 | * In those cases we don't try to register the device again. | ||
85 | */ | ||
86 | if (!codec->ac97_created) | ||
87 | return 0; | ||
88 | |||
89 | ret = soc_ac97_dev_register(codec); | ||
90 | if (ret < 0) { | ||
91 | dev_err(codec->dev, | ||
92 | "ASoC: AC97 device register failed: %d\n", ret); | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | codec->ac97_registered = 1; | ||
97 | } | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) | ||
102 | { | ||
103 | if (codec->ac97_registered) { | ||
104 | soc_ac97_dev_unregister(codec); | ||
105 | codec->ac97_registered = 0; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | ||
110 | { | ||
111 | int i, ret; | ||
112 | |||
113 | for (i = 0; i < rtd->num_codecs; i++) { | ||
114 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
115 | |||
116 | ret = soc_register_ac97_codec(codec_dai->codec, codec_dai); | ||
117 | if (ret) { | ||
118 | while (--i >= 0) | ||
119 | soc_unregister_ac97_codec(codec_dai->codec); | ||
120 | return ret; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | ||
128 | { | ||
129 | int i; | ||
130 | |||
131 | for (i = 0; i < rtd->num_codecs; i++) | ||
132 | soc_unregister_ac97_codec(rtd->codec_dais[i]->codec); | ||
133 | } | ||
134 | |||
135 | static void soc_ac97_device_release(struct device *dev) | ||
136 | { | ||
137 | kfree(to_ac97_t(dev)); | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * snd_soc_new_ac97_codec - initailise AC97 device | ||
142 | * @codec: audio codec | ||
143 | * @ops: AC97 bus operations | ||
144 | * @num: AC97 codec number | ||
145 | * | ||
146 | * Initialises AC97 codec resources for use by ad-hoc devices only. | ||
147 | */ | ||
148 | int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | ||
149 | struct snd_ac97_bus_ops *ops, int num) | ||
150 | { | ||
151 | codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); | ||
152 | if (codec->ac97 == NULL) | ||
153 | return -ENOMEM; | ||
154 | |||
155 | codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL); | ||
156 | if (codec->ac97->bus == NULL) { | ||
157 | kfree(codec->ac97); | ||
158 | codec->ac97 = NULL; | ||
159 | return -ENOMEM; | ||
160 | } | ||
161 | |||
162 | codec->ac97->bus->ops = ops; | ||
163 | codec->ac97->num = num; | ||
164 | codec->ac97->dev.release = soc_ac97_device_release; | ||
165 | |||
166 | /* | ||
167 | * Mark the AC97 device to be created by us. This way we ensure that the | ||
168 | * device will be registered with the device subsystem later on. | ||
169 | */ | ||
170 | codec->ac97_created = 1; | ||
171 | device_initialize(&codec->ac97->dev); | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | ||
176 | |||
177 | /** | ||
178 | * snd_soc_free_ac97_codec - free AC97 codec device | ||
179 | * @codec: audio codec | ||
180 | * | ||
181 | * Frees AC97 codec device resources. | ||
182 | */ | ||
183 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) | ||
184 | { | ||
185 | soc_unregister_ac97_codec(codec); | ||
186 | kfree(codec->ac97->bus); | ||
187 | codec->ac97->bus = NULL; | ||
188 | put_device(&codec->ac97->dev); | ||
189 | codec->ac97 = NULL; | ||
190 | codec->ac97_created = 0; | ||
191 | } | ||
192 | EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); | ||
193 | |||
194 | static struct snd_ac97_reset_cfg snd_ac97_rst_cfg; | ||
195 | |||
196 | static void snd_soc_ac97_warm_reset(struct snd_ac97 *ac97) | ||
197 | { | ||
198 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
199 | |||
200 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_warm_reset); | ||
201 | |||
202 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 1); | ||
203 | |||
204 | udelay(10); | ||
205 | |||
206 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
207 | |||
208 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
209 | msleep(2); | ||
210 | } | ||
211 | |||
212 | static void snd_soc_ac97_reset(struct snd_ac97 *ac97) | ||
213 | { | ||
214 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
215 | |||
216 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_reset); | ||
217 | |||
218 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
219 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sdata, 0); | ||
220 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 0); | ||
221 | |||
222 | udelay(10); | ||
223 | |||
224 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 1); | ||
225 | |||
226 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
227 | msleep(2); | ||
228 | } | ||
229 | |||
230 | static int snd_soc_ac97_parse_pinctl(struct device *dev, | ||
231 | struct snd_ac97_reset_cfg *cfg) | ||
232 | { | ||
233 | struct pinctrl *p; | ||
234 | struct pinctrl_state *state; | ||
235 | int gpio; | ||
236 | int ret; | ||
237 | |||
238 | p = devm_pinctrl_get(dev); | ||
239 | if (IS_ERR(p)) { | ||
240 | dev_err(dev, "Failed to get pinctrl\n"); | ||
241 | return PTR_ERR(p); | ||
242 | } | ||
243 | cfg->pctl = p; | ||
244 | |||
245 | state = pinctrl_lookup_state(p, "ac97-reset"); | ||
246 | if (IS_ERR(state)) { | ||
247 | dev_err(dev, "Can't find pinctrl state ac97-reset\n"); | ||
248 | return PTR_ERR(state); | ||
249 | } | ||
250 | cfg->pstate_reset = state; | ||
251 | |||
252 | state = pinctrl_lookup_state(p, "ac97-warm-reset"); | ||
253 | if (IS_ERR(state)) { | ||
254 | dev_err(dev, "Can't find pinctrl state ac97-warm-reset\n"); | ||
255 | return PTR_ERR(state); | ||
256 | } | ||
257 | cfg->pstate_warm_reset = state; | ||
258 | |||
259 | state = pinctrl_lookup_state(p, "ac97-running"); | ||
260 | if (IS_ERR(state)) { | ||
261 | dev_err(dev, "Can't find pinctrl state ac97-running\n"); | ||
262 | return PTR_ERR(state); | ||
263 | } | ||
264 | cfg->pstate_run = state; | ||
265 | |||
266 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 0); | ||
267 | if (gpio < 0) { | ||
268 | dev_err(dev, "Can't find ac97-sync gpio\n"); | ||
269 | return gpio; | ||
270 | } | ||
271 | ret = devm_gpio_request(dev, gpio, "AC97 link sync"); | ||
272 | if (ret) { | ||
273 | dev_err(dev, "Failed requesting ac97-sync gpio\n"); | ||
274 | return ret; | ||
275 | } | ||
276 | cfg->gpio_sync = gpio; | ||
277 | |||
278 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 1); | ||
279 | if (gpio < 0) { | ||
280 | dev_err(dev, "Can't find ac97-sdata gpio %d\n", gpio); | ||
281 | return gpio; | ||
282 | } | ||
283 | ret = devm_gpio_request(dev, gpio, "AC97 link sdata"); | ||
284 | if (ret) { | ||
285 | dev_err(dev, "Failed requesting ac97-sdata gpio\n"); | ||
286 | return ret; | ||
287 | } | ||
288 | cfg->gpio_sdata = gpio; | ||
289 | |||
290 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 2); | ||
291 | if (gpio < 0) { | ||
292 | dev_err(dev, "Can't find ac97-reset gpio\n"); | ||
293 | return gpio; | ||
294 | } | ||
295 | ret = devm_gpio_request(dev, gpio, "AC97 link reset"); | ||
296 | if (ret) { | ||
297 | dev_err(dev, "Failed requesting ac97-reset gpio\n"); | ||
298 | return ret; | ||
299 | } | ||
300 | cfg->gpio_reset = gpio; | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | struct snd_ac97_bus_ops *soc_ac97_ops; | ||
306 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
307 | |||
308 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | ||
309 | { | ||
310 | if (ops == soc_ac97_ops) | ||
311 | return 0; | ||
312 | |||
313 | if (soc_ac97_ops && ops) | ||
314 | return -EBUSY; | ||
315 | |||
316 | soc_ac97_ops = ops; | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); | ||
321 | |||
322 | /** | ||
323 | * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions | ||
324 | * | ||
325 | * This function sets the reset and warm_reset properties of ops and parses | ||
326 | * the device node of pdev to get pinctrl states and gpio numbers to use. | ||
327 | */ | ||
328 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | ||
329 | struct platform_device *pdev) | ||
330 | { | ||
331 | struct device *dev = &pdev->dev; | ||
332 | struct snd_ac97_reset_cfg cfg; | ||
333 | int ret; | ||
334 | |||
335 | ret = snd_soc_ac97_parse_pinctl(dev, &cfg); | ||
336 | if (ret) | ||
337 | return ret; | ||
338 | |||
339 | ret = snd_soc_set_ac97_ops(ops); | ||
340 | if (ret) | ||
341 | return ret; | ||
342 | |||
343 | ops->warm_reset = snd_soc_ac97_warm_reset; | ||
344 | ops->reset = snd_soc_ac97_reset; | ||
345 | |||
346 | snd_ac97_rst_cfg = cfg; | ||
347 | return 0; | ||
348 | } | ||
349 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset); | ||
350 | |||
351 | int snd_soc_ac97_register_dai_links(struct snd_soc_card *card) | ||
352 | { | ||
353 | int i; | ||
354 | int ret; | ||
355 | |||
356 | /* register any AC97 codecs */ | ||
357 | for (i = 0; i < card->num_rtd; i++) { | ||
358 | ret = soc_register_ac97_dai_link(&card->rtd[i]); | ||
359 | if (ret < 0) | ||
360 | goto err; | ||
361 | } | ||
362 | |||
363 | return 0; | ||
364 | err: | ||
365 | dev_err(card->dev, | ||
366 | "ASoC: failed to register AC97: %d\n", ret); | ||
367 | while (--i >= 0) | ||
368 | soc_unregister_ac97_dai_link(&card->rtd[i]); | ||
369 | return ret; | ||
370 | } | ||
371 | |||
372 | void snd_soc_ac97_add_pdata(struct snd_soc_pcm_runtime *rtd) | ||
373 | { | ||
374 | unsigned int i; | ||
375 | |||
376 | /* add platform data for AC97 devices */ | ||
377 | for (i = 0; i < rtd->num_codecs; i++) { | ||
378 | if (rtd->codec_dais[i]->driver->ac97_control) | ||
379 | snd_ac97_dev_add_pdata(rtd->codec_dais[i]->codec->ac97, | ||
380 | rtd->cpu_dai->ac97_pdata); | ||
381 | } | ||
382 | } | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 7084c6f1285a..026722f5ebf4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -34,9 +34,6 @@ | |||
34 | #include <linux/ctype.h> | 34 | #include <linux/ctype.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/of.h> | 36 | #include <linux/of.h> |
37 | #include <linux/gpio.h> | ||
38 | #include <linux/of_gpio.h> | ||
39 | #include <sound/ac97_codec.h> | ||
40 | #include <sound/core.h> | 37 | #include <sound/core.h> |
41 | #include <sound/jack.h> | 38 | #include <sound/jack.h> |
42 | #include <sound/pcm.h> | 39 | #include <sound/pcm.h> |
@@ -69,16 +66,6 @@ static int pmdown_time = 5000; | |||
69 | module_param(pmdown_time, int, 0); | 66 | module_param(pmdown_time, int, 0); |
70 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 67 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
71 | 68 | ||
72 | struct snd_ac97_reset_cfg { | ||
73 | struct pinctrl *pctl; | ||
74 | struct pinctrl_state *pstate_reset; | ||
75 | struct pinctrl_state *pstate_warm_reset; | ||
76 | struct pinctrl_state *pstate_run; | ||
77 | int gpio_sdata; | ||
78 | int gpio_sync; | ||
79 | int gpio_reset; | ||
80 | }; | ||
81 | |||
82 | /* returns the minimum number of bytes needed to represent | 69 | /* returns the minimum number of bytes needed to represent |
83 | * a particular given value */ | 70 | * a particular given value */ |
84 | static int min_bytes_needed(unsigned long val) | 71 | static int min_bytes_needed(unsigned long val) |
@@ -499,36 +486,6 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, | |||
499 | } | 486 | } |
500 | EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime); | 487 | EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime); |
501 | 488 | ||
502 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
503 | /* unregister ac97 codec */ | ||
504 | static int soc_ac97_dev_unregister(struct snd_soc_codec *codec) | ||
505 | { | ||
506 | if (codec->ac97->dev.bus) | ||
507 | device_del(&codec->ac97->dev); | ||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | /* register ac97 codec to bus */ | ||
512 | static int soc_ac97_dev_register(struct snd_soc_codec *codec) | ||
513 | { | ||
514 | int err; | ||
515 | |||
516 | codec->ac97->dev.bus = &ac97_bus_type; | ||
517 | codec->ac97->dev.parent = codec->component.card->dev; | ||
518 | |||
519 | dev_set_name(&codec->ac97->dev, "%d-%d:%s", | ||
520 | codec->component.card->snd_card->number, 0, | ||
521 | codec->component.name); | ||
522 | err = device_add(&codec->ac97->dev); | ||
523 | if (err < 0) { | ||
524 | dev_err(codec->dev, "ASoC: Can't register ac97 bus\n"); | ||
525 | codec->ac97->dev.bus = NULL; | ||
526 | return err; | ||
527 | } | ||
528 | return 0; | ||
529 | } | ||
530 | #endif | ||
531 | |||
532 | static void codec2codec_close_delayed_work(struct work_struct *work) | 489 | static void codec2codec_close_delayed_work(struct work_struct *work) |
533 | { | 490 | { |
534 | /* Currently nothing to do for c2c links | 491 | /* Currently nothing to do for c2c links |
@@ -1418,84 +1375,11 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1418 | } | 1375 | } |
1419 | } | 1376 | } |
1420 | 1377 | ||
1421 | /* add platform data for AC97 devices */ | 1378 | snd_soc_ac97_add_pdata(rtd); |
1422 | for (i = 0; i < rtd->num_codecs; i++) { | ||
1423 | if (rtd->codec_dais[i]->driver->ac97_control) | ||
1424 | snd_ac97_dev_add_pdata(rtd->codec_dais[i]->codec->ac97, | ||
1425 | rtd->cpu_dai->ac97_pdata); | ||
1426 | } | ||
1427 | |||
1428 | return 0; | ||
1429 | } | ||
1430 | |||
1431 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
1432 | static int soc_register_ac97_codec(struct snd_soc_codec *codec, | ||
1433 | struct snd_soc_dai *codec_dai) | ||
1434 | { | ||
1435 | int ret; | ||
1436 | |||
1437 | /* Only instantiate AC97 if not already done by the adaptor | ||
1438 | * for the generic AC97 subsystem. | ||
1439 | */ | ||
1440 | if (codec_dai->driver->ac97_control && !codec->ac97_registered) { | ||
1441 | /* | ||
1442 | * It is possible that the AC97 device is already registered to | ||
1443 | * the device subsystem. This happens when the device is created | ||
1444 | * via snd_ac97_mixer(). Currently only SoC codec that does so | ||
1445 | * is the generic AC97 glue but others migh emerge. | ||
1446 | * | ||
1447 | * In those cases we don't try to register the device again. | ||
1448 | */ | ||
1449 | if (!codec->ac97_created) | ||
1450 | return 0; | ||
1451 | |||
1452 | ret = soc_ac97_dev_register(codec); | ||
1453 | if (ret < 0) { | ||
1454 | dev_err(codec->dev, | ||
1455 | "ASoC: AC97 device register failed: %d\n", ret); | ||
1456 | return ret; | ||
1457 | } | ||
1458 | |||
1459 | codec->ac97_registered = 1; | ||
1460 | } | ||
1461 | return 0; | ||
1462 | } | ||
1463 | |||
1464 | static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) | ||
1465 | { | ||
1466 | if (codec->ac97_registered) { | ||
1467 | soc_ac97_dev_unregister(codec); | ||
1468 | codec->ac97_registered = 0; | ||
1469 | } | ||
1470 | } | ||
1471 | |||
1472 | static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | ||
1473 | { | ||
1474 | int i, ret; | ||
1475 | |||
1476 | for (i = 0; i < rtd->num_codecs; i++) { | ||
1477 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
1478 | |||
1479 | ret = soc_register_ac97_codec(codec_dai->codec, codec_dai); | ||
1480 | if (ret) { | ||
1481 | while (--i >= 0) | ||
1482 | soc_unregister_ac97_codec(codec_dai->codec); | ||
1483 | return ret; | ||
1484 | } | ||
1485 | } | ||
1486 | 1379 | ||
1487 | return 0; | 1380 | return 0; |
1488 | } | 1381 | } |
1489 | 1382 | ||
1490 | static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | ||
1491 | { | ||
1492 | int i; | ||
1493 | |||
1494 | for (i = 0; i < rtd->num_codecs; i++) | ||
1495 | soc_unregister_ac97_codec(rtd->codec_dais[i]->codec); | ||
1496 | } | ||
1497 | #endif | ||
1498 | |||
1499 | static int soc_bind_aux_dev(struct snd_soc_card *card, int num) | 1383 | static int soc_bind_aux_dev(struct snd_soc_card *card, int num) |
1500 | { | 1384 | { |
1501 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | 1385 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; |
@@ -1789,19 +1673,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1789 | goto probe_aux_dev_err; | 1673 | goto probe_aux_dev_err; |
1790 | } | 1674 | } |
1791 | 1675 | ||
1792 | #ifdef CONFIG_SND_SOC_AC97_BUS | 1676 | ret = snd_soc_ac97_register_dai_links(card); |
1793 | /* register any AC97 codecs */ | 1677 | if (ret < 0) |
1794 | for (i = 0; i < card->num_rtd; i++) { | 1678 | goto probe_aux_dev_err; |
1795 | ret = soc_register_ac97_dai_link(&card->rtd[i]); | ||
1796 | if (ret < 0) { | ||
1797 | dev_err(card->dev, | ||
1798 | "ASoC: failed to register AC97: %d\n", ret); | ||
1799 | while (--i >= 0) | ||
1800 | soc_unregister_ac97_dai_link(&card->rtd[i]); | ||
1801 | goto probe_aux_dev_err; | ||
1802 | } | ||
1803 | } | ||
1804 | #endif | ||
1805 | 1679 | ||
1806 | card->instantiated = 1; | 1680 | card->instantiated = 1; |
1807 | snd_soc_dapm_sync(&card->dapm); | 1681 | snd_soc_dapm_sync(&card->dapm); |
@@ -1944,224 +1818,6 @@ static struct platform_driver soc_driver = { | |||
1944 | .remove = soc_remove, | 1818 | .remove = soc_remove, |
1945 | }; | 1819 | }; |
1946 | 1820 | ||
1947 | static void soc_ac97_device_release(struct device *dev) | ||
1948 | { | ||
1949 | kfree(to_ac97_t(dev)); | ||
1950 | } | ||
1951 | |||
1952 | /** | ||
1953 | * snd_soc_new_ac97_codec - initailise AC97 device | ||
1954 | * @codec: audio codec | ||
1955 | * @ops: AC97 bus operations | ||
1956 | * @num: AC97 codec number | ||
1957 | * | ||
1958 | * Initialises AC97 codec resources for use by ad-hoc devices only. | ||
1959 | */ | ||
1960 | int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | ||
1961 | struct snd_ac97_bus_ops *ops, int num) | ||
1962 | { | ||
1963 | codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); | ||
1964 | if (codec->ac97 == NULL) | ||
1965 | return -ENOMEM; | ||
1966 | |||
1967 | codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL); | ||
1968 | if (codec->ac97->bus == NULL) { | ||
1969 | kfree(codec->ac97); | ||
1970 | codec->ac97 = NULL; | ||
1971 | return -ENOMEM; | ||
1972 | } | ||
1973 | |||
1974 | codec->ac97->bus->ops = ops; | ||
1975 | codec->ac97->num = num; | ||
1976 | codec->ac97->dev.release = soc_ac97_device_release; | ||
1977 | |||
1978 | /* | ||
1979 | * Mark the AC97 device to be created by us. This way we ensure that the | ||
1980 | * device will be registered with the device subsystem later on. | ||
1981 | */ | ||
1982 | codec->ac97_created = 1; | ||
1983 | device_initialize(&codec->ac97->dev); | ||
1984 | |||
1985 | return 0; | ||
1986 | } | ||
1987 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | ||
1988 | |||
1989 | static struct snd_ac97_reset_cfg snd_ac97_rst_cfg; | ||
1990 | |||
1991 | static void snd_soc_ac97_warm_reset(struct snd_ac97 *ac97) | ||
1992 | { | ||
1993 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
1994 | |||
1995 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_warm_reset); | ||
1996 | |||
1997 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 1); | ||
1998 | |||
1999 | udelay(10); | ||
2000 | |||
2001 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
2002 | |||
2003 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
2004 | msleep(2); | ||
2005 | } | ||
2006 | |||
2007 | static void snd_soc_ac97_reset(struct snd_ac97 *ac97) | ||
2008 | { | ||
2009 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
2010 | |||
2011 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_reset); | ||
2012 | |||
2013 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
2014 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sdata, 0); | ||
2015 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 0); | ||
2016 | |||
2017 | udelay(10); | ||
2018 | |||
2019 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 1); | ||
2020 | |||
2021 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
2022 | msleep(2); | ||
2023 | } | ||
2024 | |||
2025 | static int snd_soc_ac97_parse_pinctl(struct device *dev, | ||
2026 | struct snd_ac97_reset_cfg *cfg) | ||
2027 | { | ||
2028 | struct pinctrl *p; | ||
2029 | struct pinctrl_state *state; | ||
2030 | int gpio; | ||
2031 | int ret; | ||
2032 | |||
2033 | p = devm_pinctrl_get(dev); | ||
2034 | if (IS_ERR(p)) { | ||
2035 | dev_err(dev, "Failed to get pinctrl\n"); | ||
2036 | return PTR_ERR(p); | ||
2037 | } | ||
2038 | cfg->pctl = p; | ||
2039 | |||
2040 | state = pinctrl_lookup_state(p, "ac97-reset"); | ||
2041 | if (IS_ERR(state)) { | ||
2042 | dev_err(dev, "Can't find pinctrl state ac97-reset\n"); | ||
2043 | return PTR_ERR(state); | ||
2044 | } | ||
2045 | cfg->pstate_reset = state; | ||
2046 | |||
2047 | state = pinctrl_lookup_state(p, "ac97-warm-reset"); | ||
2048 | if (IS_ERR(state)) { | ||
2049 | dev_err(dev, "Can't find pinctrl state ac97-warm-reset\n"); | ||
2050 | return PTR_ERR(state); | ||
2051 | } | ||
2052 | cfg->pstate_warm_reset = state; | ||
2053 | |||
2054 | state = pinctrl_lookup_state(p, "ac97-running"); | ||
2055 | if (IS_ERR(state)) { | ||
2056 | dev_err(dev, "Can't find pinctrl state ac97-running\n"); | ||
2057 | return PTR_ERR(state); | ||
2058 | } | ||
2059 | cfg->pstate_run = state; | ||
2060 | |||
2061 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 0); | ||
2062 | if (gpio < 0) { | ||
2063 | dev_err(dev, "Can't find ac97-sync gpio\n"); | ||
2064 | return gpio; | ||
2065 | } | ||
2066 | ret = devm_gpio_request(dev, gpio, "AC97 link sync"); | ||
2067 | if (ret) { | ||
2068 | dev_err(dev, "Failed requesting ac97-sync gpio\n"); | ||
2069 | return ret; | ||
2070 | } | ||
2071 | cfg->gpio_sync = gpio; | ||
2072 | |||
2073 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 1); | ||
2074 | if (gpio < 0) { | ||
2075 | dev_err(dev, "Can't find ac97-sdata gpio %d\n", gpio); | ||
2076 | return gpio; | ||
2077 | } | ||
2078 | ret = devm_gpio_request(dev, gpio, "AC97 link sdata"); | ||
2079 | if (ret) { | ||
2080 | dev_err(dev, "Failed requesting ac97-sdata gpio\n"); | ||
2081 | return ret; | ||
2082 | } | ||
2083 | cfg->gpio_sdata = gpio; | ||
2084 | |||
2085 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 2); | ||
2086 | if (gpio < 0) { | ||
2087 | dev_err(dev, "Can't find ac97-reset gpio\n"); | ||
2088 | return gpio; | ||
2089 | } | ||
2090 | ret = devm_gpio_request(dev, gpio, "AC97 link reset"); | ||
2091 | if (ret) { | ||
2092 | dev_err(dev, "Failed requesting ac97-reset gpio\n"); | ||
2093 | return ret; | ||
2094 | } | ||
2095 | cfg->gpio_reset = gpio; | ||
2096 | |||
2097 | return 0; | ||
2098 | } | ||
2099 | |||
2100 | struct snd_ac97_bus_ops *soc_ac97_ops; | ||
2101 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
2102 | |||
2103 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | ||
2104 | { | ||
2105 | if (ops == soc_ac97_ops) | ||
2106 | return 0; | ||
2107 | |||
2108 | if (soc_ac97_ops && ops) | ||
2109 | return -EBUSY; | ||
2110 | |||
2111 | soc_ac97_ops = ops; | ||
2112 | |||
2113 | return 0; | ||
2114 | } | ||
2115 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); | ||
2116 | |||
2117 | /** | ||
2118 | * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions | ||
2119 | * | ||
2120 | * This function sets the reset and warm_reset properties of ops and parses | ||
2121 | * the device node of pdev to get pinctrl states and gpio numbers to use. | ||
2122 | */ | ||
2123 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | ||
2124 | struct platform_device *pdev) | ||
2125 | { | ||
2126 | struct device *dev = &pdev->dev; | ||
2127 | struct snd_ac97_reset_cfg cfg; | ||
2128 | int ret; | ||
2129 | |||
2130 | ret = snd_soc_ac97_parse_pinctl(dev, &cfg); | ||
2131 | if (ret) | ||
2132 | return ret; | ||
2133 | |||
2134 | ret = snd_soc_set_ac97_ops(ops); | ||
2135 | if (ret) | ||
2136 | return ret; | ||
2137 | |||
2138 | ops->warm_reset = snd_soc_ac97_warm_reset; | ||
2139 | ops->reset = snd_soc_ac97_reset; | ||
2140 | |||
2141 | snd_ac97_rst_cfg = cfg; | ||
2142 | return 0; | ||
2143 | } | ||
2144 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset); | ||
2145 | |||
2146 | /** | ||
2147 | * snd_soc_free_ac97_codec - free AC97 codec device | ||
2148 | * @codec: audio codec | ||
2149 | * | ||
2150 | * Frees AC97 codec device resources. | ||
2151 | */ | ||
2152 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) | ||
2153 | { | ||
2154 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
2155 | soc_unregister_ac97_codec(codec); | ||
2156 | #endif | ||
2157 | kfree(codec->ac97->bus); | ||
2158 | codec->ac97->bus = NULL; | ||
2159 | put_device(&codec->ac97->dev); | ||
2160 | codec->ac97 = NULL; | ||
2161 | codec->ac97_created = 0; | ||
2162 | } | ||
2163 | EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); | ||
2164 | |||
2165 | /** | 1821 | /** |
2166 | * snd_soc_cnew - create new control | 1822 | * snd_soc_cnew - create new control |
2167 | * @_template: control template | 1823 | * @_template: control template |