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