[3.5.y.z,extended,stable] Patch "ALSA: pxa27x: fix ac97 warm reset" has been added to staging queue

Submitted by Herton Ronaldo Krzesinski on Jan. 23, 2013, 4:42 a.m.


Message ID 1358916174-23037-1-git-send-email-herton.krzesinski@canonical.com
State New
Headers show

Commit Message

Herton Ronaldo Krzesinski Jan. 23, 2013, 4:42 a.m.
This is a note to let you know that I have just added a patch titled

    ALSA: pxa27x: fix ac97 warm reset

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:


If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see



From b510b3ba41aa829cbc6b6f6d45da8dc6fb42748a Mon Sep 17 00:00:00 2001
From: Mike Dunn <mikedunn@newsguy.com>
Date: Mon, 7 Jan 2013 13:55:13 -0800
Subject: [PATCH] ALSA: pxa27x: fix ac97 warm reset

commit 3b4bc7bccc7857274705b05cf81a0c72cfd0b0dd upstream.

This patch fixes some code that implements a work-around to a hardware bug in
the ac97 controller on the pxa27x.  A bug in the controller's warm reset
functionality requires that the mfp used by the controller as the AC97_nRESET
line be temporarily reconfigured as a generic output gpio (AF0) and manually
held high for the duration of the warm reset cycle.  This is what was done in
the original code, but it was broken long ago by commit fb1bf8cd
    ([ARM] pxa: introduce processor specific pxa27x_assert_ac97reset())
which changed the mfp to a GPIO input instead of a high output.

The fix requires the ac97 controller to obtain the gpio via gpio_request_one(),
with arguments that configure the gpio as an output initially driven high.

Tested on a palm treo 680 machine.  Reportedly, this broken code only prevents a
warm reset on hardware that lacks a pull-up on the line, which appears to be the
case for me.

Signed-off-by: Mike Dunn <mikedunn@newsguy.com>
Signed-off-by: Igor Grinberg <grinberg@compulab.co.il>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
 arch/arm/mach-pxa/include/mach/mfp-pxa27x.h |    3 +++
 arch/arm/mach-pxa/pxa27x.c                  |    4 ++--
 sound/arm/pxa2xx-ac97-lib.c                 |   18 +++++++++++++++++-
 3 files changed, 22 insertions(+), 3 deletions(-)


Patch hide | download patch | download mbox

diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
index a611ad3..b6132aa 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 @@ 

+/* these enable a work-around for a hw bug in pxa27x during ac97 warm reset */

 extern int keypad_set_wake(unsigned int on);
 #endif /* __ASM_ARCH_MFP_PXA27X_H */
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 4726c24..a2fe795 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -47,9 +47,9 @@  void pxa27x_clear_otgph(void)

 static unsigned long ac97_reset_config[] = {

diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 8cfb2c0..bd3ba88 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -18,6 +18,7 @@ 
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/gpio.h>

 #include <sound/ac97_codec.h>
 #include <sound/pxa2xx-lib.h>
@@ -344,8 +345,21 @@  int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)

 	if (cpu_is_pxa27x()) {
-		/* Use GPIO 113 as AC97 Reset on Bulverde */
+		/*
+		 * This gpio is needed for a work-around to a bug in the ac97
+		 * controller during warm reset.  The direction and level is set
+		 * here so that it is an output driven high when switching from
+		 * AC97_nRESET alt function to generic gpio.
+		 */
+		ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH,
+				       "pxa27x ac97 reset");
+		if (ret < 0) {
+			pr_err("%s: gpio_request_one() failed: %d\n",
+			       __func__, ret);
+			goto err_conf;
+		}
 		pxa27x_assert_ac97reset(reset_gpio, 0);
 		ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
 		if (IS_ERR(ac97conf_clk)) {
 			ret = PTR_ERR(ac97conf_clk);
@@ -388,6 +402,8 @@  EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);

 void pxa2xx_ac97_hw_remove(struct platform_device *dev)
+	if (cpu_is_pxa27x())
+		gpio_free(reset_gpio);
 	free_irq(IRQ_AC97, NULL);
 	if (ac97conf_clk) {