diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2011-03-07 02:04:58 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-03-07 07:19:50 -0500 |
commit | f5c4ffbd65892829f7ec503a89ea24eb0fc952dc (patch) | |
tree | 321eb2c61af4a7adc27d86f1ccd3c6323110fe67 /sound/soc/samsung/neo1973_wm8753.c | |
parent | b7874e4490aa201be2f904ffd8bb88a7b9970c6a (diff) |
ASoC: Samsung: Merge neo1937_wm8753 and neo1973_gta02_wm8753 sound board driver
The neo1973(GTA01) and neo1973_gta02(GTA02) have a very similar audio hardware
setup. They both use the same codec with the same routing to the gsm modem and
bluetooth chip. But they do use different AMPs though and there are some minor
differences in the speaker setup.
As a result most of the code of those two drivers is identical.
So from a maintenance point of view it makes sense to merge them into a single
driver. It also reduces the size of kernel images supporting both the GTA01 and
GTA02.
As a side-effect of this merge the GTA01 for example gains support for routing
audio to and from the bluetooth DAI.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Acked-by: Liam Girdwood <lrg@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/samsung/neo1973_wm8753.c')
-rw-r--r-- | sound/soc/samsung/neo1973_wm8753.c | 262 |
1 files changed, 191 insertions, 71 deletions
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 7761827314b2..37cfbb8ca39f 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c | |||
@@ -1,41 +1,32 @@ | |||
1 | /* | 1 | /* |
2 | * neo1973_wm8753.c -- SoC audio for Neo1973 | 2 | * neo1973_wm8753.c -- SoC audio for Openmoko Neo1973 and Freerunner devices |
3 | * | 3 | * |
4 | * Copyright 2007 Openmoko Inc | ||
5 | * Author: Graeme Gregory <graeme@openmoko.org> | ||
4 | * Copyright 2007 Wolfson Microelectronics PLC. | 6 | * Copyright 2007 Wolfson Microelectronics PLC. |
5 | * Author: Graeme Gregory | 7 | * Author: Graeme Gregory |
6 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | 8 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com |
9 | * Copyright 2009 Wolfson Microelectronics | ||
7 | * | 10 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 11 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms of the GNU General Public License as published by the | 12 | * under the terms of the GNU General Public License as published by the |
10 | * Free Software Foundation; either version 2 of the License, or (at your | 13 | * Free Software Foundation; either version 2 of the License, or (at your |
11 | * option) any later version. | 14 | * option) any later version. |
12 | * | ||
13 | */ | 15 | */ |
14 | 16 | ||
15 | #include <linux/module.h> | 17 | #include <linux/module.h> |
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/timer.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
20 | #include <sound/core.h> | 19 | #include <linux/gpio.h> |
21 | #include <sound/pcm.h> | 20 | |
22 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
23 | 22 | ||
24 | #include <asm/mach-types.h> | 23 | #include <asm/mach-types.h> |
25 | #include <mach/regs-clock.h> | ||
26 | #include <mach/regs-gpio.h> | ||
27 | #include <mach/hardware.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <mach/spi-gpio.h> | ||
30 | |||
31 | #include <plat/regs-iis.h> | 24 | #include <plat/regs-iis.h> |
25 | #include <mach/gta02.h> | ||
32 | 26 | ||
33 | #include "../codecs/wm8753.h" | 27 | #include "../codecs/wm8753.h" |
34 | #include "dma.h" | ||
35 | #include "s3c24xx-i2s.h" | 28 | #include "s3c24xx-i2s.h" |
36 | 29 | ||
37 | static struct snd_soc_card neo1973; | ||
38 | |||
39 | static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, | 30 | static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, |
40 | struct snd_pcm_hw_params *params) | 31 | struct snd_pcm_hw_params *params) |
41 | { | 32 | { |
@@ -46,8 +37,6 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, | |||
46 | int ret = 0; | 37 | int ret = 0; |
47 | unsigned long iis_clkrate; | 38 | unsigned long iis_clkrate; |
48 | 39 | ||
49 | pr_debug("Entered %s\n", __func__); | ||
50 | |||
51 | iis_clkrate = s3c24xx_i2s_get_clockrate(); | 40 | iis_clkrate = s3c24xx_i2s_get_clockrate(); |
52 | 41 | ||
53 | switch (params_rate(params)) { | 42 | switch (params_rate(params)) { |
@@ -132,8 +121,6 @@ static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) | |||
132 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 121 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
133 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 122 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
134 | 123 | ||
135 | pr_debug("Entered %s\n", __func__); | ||
136 | |||
137 | /* disable the PLL */ | 124 | /* disable the PLL */ |
138 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); | 125 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); |
139 | } | 126 | } |
@@ -155,8 +142,6 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, | |||
155 | int ret = 0; | 142 | int ret = 0; |
156 | unsigned long iis_clkrate; | 143 | unsigned long iis_clkrate; |
157 | 144 | ||
158 | pr_debug("Entered %s\n", __func__); | ||
159 | |||
160 | iis_clkrate = s3c24xx_i2s_get_clockrate(); | 145 | iis_clkrate = s3c24xx_i2s_get_clockrate(); |
161 | 146 | ||
162 | if (params_rate(params) != 8000) | 147 | if (params_rate(params) != 8000) |
@@ -198,8 +183,6 @@ static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) | |||
198 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 183 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
199 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 184 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
200 | 185 | ||
201 | pr_debug("Entered %s\n", __func__); | ||
202 | |||
203 | /* disable the PLL */ | 186 | /* disable the PLL */ |
204 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); | 187 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); |
205 | } | 188 | } |
@@ -209,14 +192,15 @@ static struct snd_soc_ops neo1973_voice_ops = { | |||
209 | .hw_free = neo1973_voice_hw_free, | 192 | .hw_free = neo1973_voice_hw_free, |
210 | }; | 193 | }; |
211 | 194 | ||
212 | static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = { | 195 | /* Shared routes and controls */ |
196 | |||
197 | static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = { | ||
213 | SND_SOC_DAPM_LINE("GSM Line Out", NULL), | 198 | SND_SOC_DAPM_LINE("GSM Line Out", NULL), |
214 | SND_SOC_DAPM_LINE("GSM Line In", NULL), | 199 | SND_SOC_DAPM_LINE("GSM Line In", NULL), |
215 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | 200 | SND_SOC_DAPM_MIC("Headset Mic", NULL), |
216 | SND_SOC_DAPM_MIC("Call Mic", NULL), | 201 | SND_SOC_DAPM_MIC("Handset Mic", NULL), |
217 | }; | 202 | }; |
218 | 203 | ||
219 | |||
220 | static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { | 204 | static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { |
221 | /* Connections to the GSM Module */ | 205 | /* Connections to the GSM Module */ |
222 | {"GSM Line Out", NULL, "MONO1"}, | 206 | {"GSM Line Out", NULL, "MONO1"}, |
@@ -231,7 +215,7 @@ static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { | |||
231 | /* Call Mic */ | 215 | /* Call Mic */ |
232 | {"MIC2", NULL, "Mic Bias"}, | 216 | {"MIC2", NULL, "Mic Bias"}, |
233 | {"MIC2N", NULL, "Mic Bias"}, | 217 | {"MIC2N", NULL, "Mic Bias"}, |
234 | {"Mic Bias", NULL, "Call Mic"}, | 218 | {"Mic Bias", NULL, "Handset Mic"}, |
235 | 219 | ||
236 | /* Connect the ALC pins */ | 220 | /* Connect the ALC pins */ |
237 | {"ACIN", NULL, "ACOP"}, | 221 | {"ACIN", NULL, "ACOP"}, |
@@ -241,55 +225,157 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { | |||
241 | SOC_DAPM_PIN_SWITCH("GSM Line Out"), | 225 | SOC_DAPM_PIN_SWITCH("GSM Line Out"), |
242 | SOC_DAPM_PIN_SWITCH("GSM Line In"), | 226 | SOC_DAPM_PIN_SWITCH("GSM Line In"), |
243 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | 227 | SOC_DAPM_PIN_SWITCH("Headset Mic"), |
244 | SOC_DAPM_PIN_SWITCH("Call Mic"), | 228 | SOC_DAPM_PIN_SWITCH("Handset Mic"), |
245 | }; | 229 | }; |
246 | 230 | ||
231 | /* GTA02 specific routes and controlls */ | ||
232 | |||
233 | #ifdef CONFIG_MACH_NEO1973_GTA02 | ||
234 | |||
235 | static int gta02_speaker_enabled; | ||
236 | |||
237 | static int lm4853_set_spk(struct snd_kcontrol *kcontrol, | ||
238 | struct snd_ctl_elem_value *ucontrol) | ||
239 | { | ||
240 | gta02_speaker_enabled = ucontrol->value.integer.value[0]; | ||
241 | |||
242 | gpio_set_value(GTA02_GPIO_HP_IN, !gta02_speaker_enabled); | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static int lm4853_get_spk(struct snd_kcontrol *kcontrol, | ||
248 | struct snd_ctl_elem_value *ucontrol) | ||
249 | { | ||
250 | ucontrol->value.integer.value[0] = gta02_speaker_enabled; | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int lm4853_event(struct snd_soc_dapm_widget *w, | ||
255 | struct snd_kcontrol *k, int event) | ||
256 | { | ||
257 | gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event)); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static const struct snd_soc_dapm_route neo1973_gta02_routes[] = { | ||
263 | /* Connections to the amp */ | ||
264 | {"Stereo Out", NULL, "LOUT1"}, | ||
265 | {"Stereo Out", NULL, "ROUT1"}, | ||
266 | |||
267 | /* Call Speaker */ | ||
268 | {"Handset Spk", NULL, "LOUT2"}, | ||
269 | {"Handset Spk", NULL, "ROUT2"}, | ||
270 | }; | ||
271 | |||
272 | static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = { | ||
273 | SOC_DAPM_PIN_SWITCH("Handset Spk"), | ||
274 | SOC_DAPM_PIN_SWITCH("Stereo Out"), | ||
275 | |||
276 | SOC_SINGLE_BOOL_EXT("Amp Spk Switch", 0, | ||
277 | lm4853_get_spk, | ||
278 | lm4853_set_spk), | ||
279 | }; | ||
280 | |||
281 | static const struct snd_soc_dapm_widget neo1973_gta02_wm8753_dapm_widgets[] = { | ||
282 | SND_SOC_DAPM_SPK("Handset Spk", NULL), | ||
283 | SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), | ||
284 | }; | ||
285 | |||
286 | static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) | ||
287 | { | ||
288 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
289 | int ret; | ||
290 | |||
291 | ret = snd_soc_dapm_new_controls(dapm, neo1973_gta02_wm8753_dapm_widgets, | ||
292 | ARRAY_SIZE(neo1973_gta02_wm8753_dapm_widgets)); | ||
293 | if (ret) | ||
294 | return ret; | ||
295 | |||
296 | ret = snd_soc_dapm_add_routes(dapm, neo1973_gta02_routes, | ||
297 | ARRAY_SIZE(neo1973_gta02_routes)); | ||
298 | if (ret) | ||
299 | return ret; | ||
300 | |||
301 | ret = snd_soc_add_controls(codec, neo1973_gta02_wm8753_controls, | ||
302 | ARRAY_SIZE(neo1973_gta02_wm8753_controls)); | ||
303 | if (ret) | ||
304 | return ret; | ||
305 | |||
306 | snd_soc_dapm_disable_pin(dapm, "Stereo Out"); | ||
307 | snd_soc_dapm_disable_pin(dapm, "Handset Spk"); | ||
308 | snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); | ||
309 | snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | #else | ||
315 | static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; } | ||
316 | #endif | ||
247 | 317 | ||
248 | /* | ||
249 | * This is an example machine initialisation for a wm8753 connected to a | ||
250 | * neo1973 II. It is missing logic to detect hp/mic insertions and logic | ||
251 | * to re-route the audio in such an event. | ||
252 | */ | ||
253 | static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) | 318 | static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) |
254 | { | 319 | { |
255 | struct snd_soc_codec *codec = rtd->codec; | 320 | struct snd_soc_codec *codec = rtd->codec; |
256 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 321 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
257 | int err; | 322 | int ret; |
258 | |||
259 | pr_debug("Entered %s\n", __func__); | ||
260 | 323 | ||
261 | /* set up NC codec pins */ | 324 | /* set up NC codec pins */ |
262 | snd_soc_dapm_nc_pin(dapm, "LOUT2"); | 325 | if (machine_is_neo1973_gta01()) { |
263 | snd_soc_dapm_nc_pin(dapm, "ROUT2"); | 326 | snd_soc_dapm_nc_pin(dapm, "LOUT2"); |
327 | snd_soc_dapm_nc_pin(dapm, "ROUT2"); | ||
328 | } | ||
264 | snd_soc_dapm_nc_pin(dapm, "OUT3"); | 329 | snd_soc_dapm_nc_pin(dapm, "OUT3"); |
265 | snd_soc_dapm_nc_pin(dapm, "OUT4"); | 330 | snd_soc_dapm_nc_pin(dapm, "OUT4"); |
266 | snd_soc_dapm_nc_pin(dapm, "LINE1"); | 331 | snd_soc_dapm_nc_pin(dapm, "LINE1"); |
267 | snd_soc_dapm_nc_pin(dapm, "LINE2"); | 332 | snd_soc_dapm_nc_pin(dapm, "LINE2"); |
268 | 333 | ||
269 | /* Add neo1973 specific widgets */ | 334 | /* Add neo1973 specific widgets */ |
270 | snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets, | 335 | ret = snd_soc_dapm_new_controls(dapm, neo1973_wm8753_dapm_widgets, |
271 | ARRAY_SIZE(wm8753_dapm_widgets)); | 336 | ARRAY_SIZE(neo1973_wm8753_dapm_widgets)); |
272 | 337 | if (ret) | |
273 | /* set endpoints to default mode */ | 338 | return ret; |
274 | snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); | ||
275 | snd_soc_dapm_disable_pin(dapm, "GSM Line In"); | ||
276 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | ||
277 | snd_soc_dapm_disable_pin(dapm, "Call Mic"); | ||
278 | 339 | ||
279 | /* add neo1973 specific controls */ | 340 | /* add neo1973 specific controls */ |
280 | err = snd_soc_add_controls(codec, neo1973_wm8753_controls, | 341 | ret = snd_soc_add_controls(codec, neo1973_wm8753_controls, |
281 | ARRAY_SIZE(neo1973_wm8753_controls)); | 342 | ARRAY_SIZE(neo1973_wm8753_controls)); |
282 | if (err < 0) | 343 | if (ret) |
283 | return err; | 344 | return ret; |
284 | 345 | ||
285 | /* set up neo1973 specific audio routes */ | 346 | /* set up neo1973 specific audio routes */ |
286 | err = snd_soc_dapm_add_routes(dapm, neo1973_wm8753_routes, | 347 | ret = snd_soc_dapm_add_routes(dapm, neo1973_wm8753_routes, |
287 | ARRAY_SIZE(neo1973_wm8753_routes)); | 348 | ARRAY_SIZE(neo1973_wm8753_routes)); |
349 | if (ret) | ||
350 | return ret; | ||
351 | |||
352 | /* set endpoints to default off mode */ | ||
353 | snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); | ||
354 | snd_soc_dapm_disable_pin(dapm, "GSM Line In"); | ||
355 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | ||
356 | snd_soc_dapm_disable_pin(dapm, "Handset Mic"); | ||
357 | |||
358 | /* allow audio paths from the GSM modem to run during suspend */ | ||
359 | snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out"); | ||
360 | snd_soc_dapm_ignore_suspend(dapm, "GSM Line In"); | ||
361 | snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); | ||
362 | snd_soc_dapm_ignore_suspend(dapm, "Handset Mic"); | ||
363 | |||
364 | if (machine_is_neo1973_gta02()) { | ||
365 | ret = neo1973_gta02_wm8753_init(codec); | ||
366 | if (ret) | ||
367 | return ret; | ||
368 | } | ||
288 | 369 | ||
289 | snd_soc_dapm_sync(dapm); | 370 | snd_soc_dapm_sync(dapm); |
371 | |||
290 | return 0; | 372 | return 0; |
291 | } | 373 | } |
292 | 374 | ||
375 | /* GTA01 specific controlls */ | ||
376 | |||
377 | #ifdef CONFIG_MACH_NEO1973_GTA01 | ||
378 | |||
293 | static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = { | 379 | static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = { |
294 | {"Amp IN", NULL, "ROUT1"}, | 380 | {"Amp IN", NULL, "ROUT1"}, |
295 | {"Amp IN", NULL, "LOUT1"}, | 381 | {"Amp IN", NULL, "LOUT1"}, |
@@ -328,10 +414,14 @@ static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) | |||
328 | return 0; | 414 | return 0; |
329 | } | 415 | } |
330 | 416 | ||
417 | #else | ||
418 | static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; }; | ||
419 | #endif | ||
420 | |||
331 | /* | 421 | /* |
332 | * BT Codec DAI | 422 | * BT Codec DAI |
333 | */ | 423 | */ |
334 | static struct snd_soc_dai bt_dai = { | 424 | static struct snd_soc_dai_driver bt_dai = { |
335 | .name = "bluetooth-dai", | 425 | .name = "bluetooth-dai", |
336 | .playback = { | 426 | .playback = { |
337 | .channels_min = 1, | 427 | .channels_min = 1, |
@@ -382,6 +472,15 @@ static struct snd_soc_codec_conf neo1973_codec_conf[] = { | |||
382 | }, | 472 | }, |
383 | }; | 473 | }; |
384 | 474 | ||
475 | #ifdef CONFIG_MACH_NEO1973_GTA02 | ||
476 | static const struct gpio neo1973_gta02_gpios[] = { | ||
477 | { GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" }, | ||
478 | { GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" }, | ||
479 | }; | ||
480 | #else | ||
481 | static const struct gpio neo1973_gta02_gpios[] = {}; | ||
482 | #endif | ||
483 | |||
385 | static struct snd_soc_card neo1973 = { | 484 | static struct snd_soc_card neo1973 = { |
386 | .name = "neo1973", | 485 | .name = "neo1973", |
387 | .dai_link = neo1973_dai, | 486 | .dai_link = neo1973_dai, |
@@ -398,43 +497,64 @@ static int __init neo1973_init(void) | |||
398 | { | 497 | { |
399 | int ret; | 498 | int ret; |
400 | 499 | ||
401 | pr_debug("Entered %s\n", __func__); | 500 | if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02()) |
402 | |||
403 | if (!machine_is_neo1973_gta01()) { | ||
404 | printk(KERN_INFO | ||
405 | "Only GTA01 hardware supported by ASoC driver\n"); | ||
406 | return -ENODEV; | 501 | return -ENODEV; |
502 | |||
503 | if (machine_is_neo1973_gta02()) { | ||
504 | neo1973.name = "neo1973gta02"; | ||
505 | neo1973.num_aux_devs = 0; | ||
506 | |||
507 | ret = gpio_request_array(neo1973_gta02_gpios, | ||
508 | ARRAY_SIZE(neo1973_gta02_gpios)); | ||
509 | if (ret) | ||
510 | return ret; | ||
407 | } | 511 | } |
408 | 512 | ||
409 | neo1973_snd_device = platform_device_alloc("soc-audio", -1); | 513 | neo1973_snd_device = platform_device_alloc("soc-audio", -1); |
410 | if (!neo1973_snd_device) | 514 | if (!neo1973_snd_device) { |
411 | return -ENOMEM; | 515 | ret = -ENOMEM; |
516 | goto err_gpio_free; | ||
517 | } | ||
518 | |||
519 | /* register bluetooth DAI here */ | ||
520 | ret = snd_soc_register_dai(&neo1973_snd_device->dev, &bt_dai); | ||
521 | if (ret) | ||
522 | goto err_put_device; | ||
412 | 523 | ||
413 | platform_set_drvdata(neo1973_snd_device, &neo1973); | 524 | platform_set_drvdata(neo1973_snd_device, &neo1973); |
414 | ret = platform_device_add(neo1973_snd_device); | 525 | ret = platform_device_add(neo1973_snd_device); |
415 | 526 | ||
416 | if (ret) { | 527 | if (ret) |
417 | platform_device_put(neo1973_snd_device); | 528 | goto err_unregister_dai; |
418 | return ret; | ||
419 | } | ||
420 | 529 | ||
421 | if (ret != 0) | 530 | return 0; |
422 | platform_device_unregister(neo1973_snd_device); | ||
423 | 531 | ||
532 | err_unregister_dai: | ||
533 | snd_soc_unregister_dai(&neo1973_snd_device->dev); | ||
534 | err_put_device: | ||
535 | platform_device_put(neo1973_snd_device); | ||
536 | err_gpio_free: | ||
537 | if (machine_is_neo1973_gta02()) { | ||
538 | gpio_free_array(neo1973_gta02_gpios, | ||
539 | ARRAY_SIZE(neo1973_gta02_gpios)); | ||
540 | } | ||
424 | return ret; | 541 | return ret; |
425 | } | 542 | } |
543 | module_init(neo1973_init); | ||
426 | 544 | ||
427 | static void __exit neo1973_exit(void) | 545 | static void __exit neo1973_exit(void) |
428 | { | 546 | { |
429 | pr_debug("Entered %s\n", __func__); | 547 | snd_soc_unregister_dai(&neo1973_snd_device->dev); |
430 | |||
431 | platform_device_unregister(neo1973_snd_device); | 548 | platform_device_unregister(neo1973_snd_device); |
432 | } | ||
433 | 549 | ||
434 | module_init(neo1973_init); | 550 | if (machine_is_neo1973_gta02()) { |
551 | gpio_free_array(neo1973_gta02_gpios, | ||
552 | ARRAY_SIZE(neo1973_gta02_gpios)); | ||
553 | } | ||
554 | } | ||
435 | module_exit(neo1973_exit); | 555 | module_exit(neo1973_exit); |
436 | 556 | ||
437 | /* Module information */ | 557 | /* Module information */ |
438 | MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org"); | 558 | MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org"); |
439 | MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973"); | 559 | MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 and Frerunner"); |
440 | MODULE_LICENSE("GPL"); | 560 | MODULE_LICENSE("GPL"); |