diff options
-rw-r--r-- | arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 4 | ||||
-rw-r--r-- | sound/arm/pxa2xx-ac97-lib.c | 26 |
3 files changed, 28 insertions, 5 deletions
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h index a611ad3153c7..b6132aa95dc0 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | |||
@@ -463,6 +463,9 @@ | |||
463 | GPIO76_LCD_PCLK, \ | 463 | GPIO76_LCD_PCLK, \ |
464 | GPIO77_LCD_BIAS | 464 | GPIO77_LCD_BIAS |
465 | 465 | ||
466 | /* these enable a work-around for a hw bug in pxa27x during ac97 warm reset */ | ||
467 | #define GPIO113_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO113, AF0, DEFAULT) | ||
468 | #define GPIO95_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO95, AF0, DEFAULT) | ||
466 | 469 | ||
467 | extern int keypad_set_wake(unsigned int on); | 470 | extern int keypad_set_wake(unsigned int on); |
468 | #endif /* __ASM_ARCH_MFP_PXA27X_H */ | 471 | #endif /* __ASM_ARCH_MFP_PXA27X_H */ |
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 8047ee0effc5..616cb87b6179 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c | |||
@@ -47,9 +47,9 @@ void pxa27x_clear_otgph(void) | |||
47 | EXPORT_SYMBOL(pxa27x_clear_otgph); | 47 | EXPORT_SYMBOL(pxa27x_clear_otgph); |
48 | 48 | ||
49 | static unsigned long ac97_reset_config[] = { | 49 | static unsigned long ac97_reset_config[] = { |
50 | GPIO113_GPIO, | 50 | GPIO113_AC97_nRESET_GPIO_HIGH, |
51 | GPIO113_AC97_nRESET, | 51 | GPIO113_AC97_nRESET, |
52 | GPIO95_GPIO, | 52 | GPIO95_AC97_nRESET_GPIO_HIGH, |
53 | GPIO95_AC97_nRESET, | 53 | GPIO95_AC97_nRESET, |
54 | }; | 54 | }; |
55 | 55 | ||
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) { |