diff options
Diffstat (limited to 'sound/arm/pxa2xx-ac97-lib.c')
-rw-r--r-- | sound/arm/pxa2xx-ac97-lib.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 6fc0ae90e5b1..fff7753e35c1 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/gpio.h> | ||
21 | 22 | ||
22 | #include <sound/ac97_codec.h> | 23 | #include <sound/ac97_codec.h> |
23 | #include <sound/pxa2xx-lib.h> | 24 | #include <sound/pxa2xx-lib.h> |
@@ -148,6 +149,8 @@ static inline void pxa_ac97_warm_pxa27x(void) | |||
148 | 149 | ||
149 | static inline void pxa_ac97_cold_pxa27x(void) | 150 | static inline void pxa_ac97_cold_pxa27x(void) |
150 | { | 151 | { |
152 | unsigned int timeout; | ||
153 | |||
151 | GCR &= GCR_COLD_RST; /* clear everything but nCRST */ | 154 | GCR &= GCR_COLD_RST; /* clear everything but nCRST */ |
152 | GCR &= ~GCR_COLD_RST; /* then assert nCRST */ | 155 | GCR &= ~GCR_COLD_RST; /* then assert nCRST */ |
153 | 156 | ||
@@ -157,8 +160,10 @@ static inline void pxa_ac97_cold_pxa27x(void) | |||
157 | clk_enable(ac97conf_clk); | 160 | clk_enable(ac97conf_clk); |
158 | udelay(5); | 161 | udelay(5); |
159 | clk_disable(ac97conf_clk); | 162 | clk_disable(ac97conf_clk); |
160 | GCR = GCR_COLD_RST; | 163 | GCR = GCR_COLD_RST | GCR_WARM_RST; |
161 | udelay(50); | 164 | timeout = 100; /* wait for the codec-ready bit to be set */ |
165 | while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) | ||
166 | mdelay(1); | ||
162 | } | 167 | } |
163 | #endif | 168 | #endif |
164 | 169 | ||
@@ -340,8 +345,21 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev) | |||
340 | } | 345 | } |
341 | 346 | ||
342 | if (cpu_is_pxa27x()) { | 347 | if (cpu_is_pxa27x()) { |
343 | /* Use GPIO 113 as AC97 Reset on Bulverde */ | 348 | /* |
349 | * This gpio is needed for a work-around to a bug in the ac97 | ||
350 | * controller during warm reset. The direction and level is set | ||
351 | * here so that it is an output driven high when switching from | ||
352 | * AC97_nRESET alt function to generic gpio. | ||
353 | */ | ||
354 | ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH, | ||
355 | "pxa27x ac97 reset"); | ||
356 | if (ret < 0) { | ||
357 | pr_err("%s: gpio_request_one() failed: %d\n", | ||
358 | __func__, ret); | ||
359 | goto err_conf; | ||
360 | } | ||
344 | pxa27x_assert_ac97reset(reset_gpio, 0); | 361 | pxa27x_assert_ac97reset(reset_gpio, 0); |
362 | |||
345 | ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); | 363 | ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); |
346 | if (IS_ERR(ac97conf_clk)) { | 364 | if (IS_ERR(ac97conf_clk)) { |
347 | ret = PTR_ERR(ac97conf_clk); | 365 | ret = PTR_ERR(ac97conf_clk); |
@@ -384,6 +402,8 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe); | |||
384 | 402 | ||
385 | void pxa2xx_ac97_hw_remove(struct platform_device *dev) | 403 | void pxa2xx_ac97_hw_remove(struct platform_device *dev) |
386 | { | 404 | { |
405 | if (cpu_is_pxa27x()) | ||
406 | gpio_free(reset_gpio); | ||
387 | GCR |= GCR_ACLINK_OFF; | 407 | GCR |= GCR_ACLINK_OFF; |
388 | free_irq(IRQ_AC97, NULL); | 408 | free_irq(IRQ_AC97, NULL); |
389 | if (ac97conf_clk) { | 409 | if (ac97conf_clk) { |