diff options
Diffstat (limited to 'sound/arm')
-rw-r--r-- | sound/arm/pxa2xx-ac97.c | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index 5d86e6809752..fd7bc865e672 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/wait.h> | 18 | #include <linux/wait.h> |
19 | #include <linux/clk.h> | ||
19 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
20 | 21 | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
@@ -35,6 +36,10 @@ | |||
35 | static DEFINE_MUTEX(car_mutex); | 36 | static DEFINE_MUTEX(car_mutex); |
36 | static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); | 37 | static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); |
37 | static volatile long gsr_bits; | 38 | static volatile long gsr_bits; |
39 | static struct clk *ac97_clk; | ||
40 | #ifdef CONFIG_PXA27x | ||
41 | static struct clk *ac97conf_clk; | ||
42 | #endif | ||
38 | 43 | ||
39 | /* | 44 | /* |
40 | * Beware PXA27x bugs: | 45 | * Beware PXA27x bugs: |
@@ -112,9 +117,9 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97) | |||
112 | gsr_bits = 0; | 117 | gsr_bits = 0; |
113 | #ifdef CONFIG_PXA27x | 118 | #ifdef CONFIG_PXA27x |
114 | /* PXA27x Developers Manual section 13.5.2.2.1 */ | 119 | /* PXA27x Developers Manual section 13.5.2.2.1 */ |
115 | pxa_set_cken(CKEN_AC97CONF, 1); | 120 | clk_enable(ac97conf_clk); |
116 | udelay(5); | 121 | udelay(5); |
117 | pxa_set_cken(CKEN_AC97CONF, 0); | 122 | clk_disable(ac97conf_clk); |
118 | GCR = GCR_COLD_RST; | 123 | GCR = GCR_COLD_RST; |
119 | udelay(50); | 124 | udelay(50); |
120 | #else | 125 | #else |
@@ -259,7 +264,7 @@ static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state) | |||
259 | if (platform_ops && platform_ops->suspend) | 264 | if (platform_ops && platform_ops->suspend) |
260 | platform_ops->suspend(platform_ops->priv); | 265 | platform_ops->suspend(platform_ops->priv); |
261 | GCR |= GCR_ACLINK_OFF; | 266 | GCR |= GCR_ACLINK_OFF; |
262 | pxa_set_cken(CKEN_AC97, 0); | 267 | clk_disable(ac97_clk); |
263 | 268 | ||
264 | return 0; | 269 | return 0; |
265 | } | 270 | } |
@@ -268,7 +273,7 @@ static int pxa2xx_ac97_do_resume(struct snd_card *card) | |||
268 | { | 273 | { |
269 | pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; | 274 | pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; |
270 | 275 | ||
271 | pxa_set_cken(CKEN_AC97, 1); | 276 | clk_enable(ac97_clk); |
272 | if (platform_ops && platform_ops->resume) | 277 | if (platform_ops && platform_ops->resume) |
273 | platform_ops->resume(platform_ops->priv); | 278 | platform_ops->resume(platform_ops->priv); |
274 | snd_ac97_resume(pxa2xx_ac97_ac97); | 279 | snd_ac97_resume(pxa2xx_ac97_ac97); |
@@ -335,8 +340,21 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) | |||
335 | #ifdef CONFIG_PXA27x | 340 | #ifdef CONFIG_PXA27x |
336 | /* Use GPIO 113 as AC97 Reset on Bulverde */ | 341 | /* Use GPIO 113 as AC97 Reset on Bulverde */ |
337 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | 342 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); |
343 | ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); | ||
344 | if (IS_ERR(ac97conf_clk)) { | ||
345 | ret = PTR_ERR(ac97conf_clk); | ||
346 | ac97conf_clk = NULL; | ||
347 | goto err; | ||
348 | } | ||
338 | #endif | 349 | #endif |
339 | pxa_set_cken(CKEN_AC97, 1); | 350 | |
351 | ac97_clk = clk_get(&dev->dev, "AC97CLK"); | ||
352 | if (IS_ERR(ac97_clk)) { | ||
353 | ret = PTR_ERR(ac97_clk); | ||
354 | ac97_clk = NULL; | ||
355 | goto err; | ||
356 | } | ||
357 | clk_enable(ac97_clk); | ||
340 | 358 | ||
341 | ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus); | 359 | ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus); |
342 | if (ret) | 360 | if (ret) |
@@ -361,11 +379,19 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) | |||
361 | err: | 379 | err: |
362 | if (card) | 380 | if (card) |
363 | snd_card_free(card); | 381 | snd_card_free(card); |
364 | if (CKEN & (1 << CKEN_AC97)) { | 382 | if (ac97_clk) { |
365 | GCR |= GCR_ACLINK_OFF; | 383 | GCR |= GCR_ACLINK_OFF; |
366 | free_irq(IRQ_AC97, NULL); | 384 | free_irq(IRQ_AC97, NULL); |
367 | pxa_set_cken(CKEN_AC97, 0); | 385 | clk_disable(ac97_clk); |
386 | clk_put(ac97_clk); | ||
387 | ac97_clk = NULL; | ||
388 | } | ||
389 | #ifdef CONFIG_PXA27x | ||
390 | if (ac97conf_clk) { | ||
391 | clk_put(ac97conf_clk); | ||
392 | ac97conf_clk = NULL; | ||
368 | } | 393 | } |
394 | #endif | ||
369 | return ret; | 395 | return ret; |
370 | } | 396 | } |
371 | 397 | ||
@@ -378,7 +404,13 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev) | |||
378 | platform_set_drvdata(dev, NULL); | 404 | platform_set_drvdata(dev, NULL); |
379 | GCR |= GCR_ACLINK_OFF; | 405 | GCR |= GCR_ACLINK_OFF; |
380 | free_irq(IRQ_AC97, NULL); | 406 | free_irq(IRQ_AC97, NULL); |
381 | pxa_set_cken(CKEN_AC97, 0); | 407 | clk_disable(ac97_clk); |
408 | clk_put(ac97_clk); | ||
409 | ac97_clk = NULL; | ||
410 | #ifdef CONFIG_PXA27x | ||
411 | clk_put(ac97conf_clk); | ||
412 | ac97conf_clk = NULL; | ||
413 | #endif | ||
382 | } | 414 | } |
383 | 415 | ||
384 | return 0; | 416 | return 0; |