From 125d842fbf3f080c6242f283827a11bf5761e0f4 Mon Sep 17 00:00:00 2001 From: wahsu Date: Mon, 14 Jul 2014 16:55:06 +0800 Subject: [PATCH] ASoc: rt5639: Set audio CODEC IRQ as a wake up pin 1. Enable wake attribute for audio CODEC IRQ. 2. Disable GPIO interrupt before entering Lp0 for those GPIOs are not Lp0 wake source. Bug 200009793 Change-Id: Ie772c3784e652c8d7b2ce0a7e5edcd22f1bba138 Signed-off-by: wahsu Reviewed-on: http://git-master/r/437644 (cherry picked from commit 238e6a62ff84e57b4f9887f4aef25a5cb6a62974) Reviewed-on: http://git-master/r/447470 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Pierre Gervais --- arch/arm/mach-tegra/pm.c | 2 +- arch/arm/mach-tegra/pmc.h | 8 +------- drivers/gpio/gpio-tegra.c | 18 ++++++++++++++---- include/linux/tegra-pm.h | 11 ++++++++++- sound/soc/tegra/tegra_rt5639.c | 1 + 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 463db1152d6..13bc1e85ec1 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -229,7 +229,7 @@ static struct clk *tegra_dfll; static struct clk *tegra_pclk; static struct clk *tegra_clk_m; static struct tegra_suspend_platform_data *pdata; -static enum tegra_suspend_mode current_suspend_mode = TEGRA_SUSPEND_NONE; +enum tegra_suspend_mode current_suspend_mode = TEGRA_SUSPEND_NONE; #if defined(CONFIG_TEGRA_CLUSTER_CONTROL) && INSTRUMENT_CLUSTER_SWITCH static unsigned long diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h index fa3787f8e3c..231b4e8f300 100644 --- a/arch/arm/mach-tegra/pmc.h +++ b/arch/arm/mach-tegra/pmc.h @@ -18,13 +18,7 @@ #ifndef __MACH_TEGRA_PMC_H #define __MACH_TEGRA_PMC_H -enum tegra_suspend_mode { - TEGRA_SUSPEND_NONE = 0, - TEGRA_SUSPEND_LP2, /* CPU voltage off */ - TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */ - TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */ - TEGRA_MAX_SUSPEND_MODE, -}; +#include #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) && defined(CONFIG_PM_SLEEP) void set_power_timers(unsigned long us_on, unsigned long us_off); diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 3f35036e1f3..ddee2fc38b8 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -6,7 +6,7 @@ * Author: * Erik Gilling * - * Copyright (c) 2011-2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -36,6 +36,7 @@ #include #include #include +#include #define GPIO_BANK(x) ((x) >> 5) #define GPIO_PORT(x) (((x) >> 3) & 0x3) @@ -79,6 +80,7 @@ struct tegra_gpio_bank { u32 int_lvl[4]; u32 wake_enb[4]; int wake_depth; + int wake_lp0_cap[4]; #endif }; @@ -371,6 +373,7 @@ static int tegra_gpio_suspend(void) for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { unsigned int gpio = (b<<5) | (p<<3); + unsigned int wake_enb; bank->cnf[p] = tegra_gpio_readl(GPIO_CNF(gpio)); bank->out[p] = tegra_gpio_readl(GPIO_OUT(gpio)); bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio)); @@ -378,7 +381,10 @@ static int tegra_gpio_suspend(void) bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio)); /* disable gpio interrupts that are not wake sources */ - tegra_gpio_writel(bank->wake_enb[p], GPIO_INT_ENB(gpio)); + wake_enb = (current_suspend_mode == TEGRA_SUSPEND_LP0) ? + (bank->wake_enb[p] & bank->wake_lp0_cap[p]) : + bank->wake_enb[p]; + tegra_gpio_writel(wake_enb, GPIO_INT_ENB(gpio)); } } local_irq_restore(flags); @@ -386,7 +392,7 @@ static int tegra_gpio_suspend(void) return 0; } -static int tegra_update_lp1_gpio_wake(struct irq_data *d, bool enable) +static int tegra_update_lp1_gpio_wake(struct irq_data *d, bool enable, int wake) { #ifdef CONFIG_PM_SLEEP struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); @@ -406,6 +412,10 @@ static int tegra_update_lp1_gpio_wake(struct irq_data *d, bool enable) bank->wake_enb[port_index] |= mask; else bank->wake_enb[port_index] &= ~mask; + + /* Enable GPIO interrupt in Lp0 when GPIO is a Lp0 wake up source */ + if (wake >= 0) + bank->wake_lp0_cap[port_index] |= mask; #endif return 0; @@ -421,7 +431,7 @@ static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable) * update LP1 mask for gpio port/pin interrupt * LP1 enable independent of LP0 wake support */ - ret = tegra_update_lp1_gpio_wake(d, enable); + ret = tegra_update_lp1_gpio_wake(d, enable, wake); if (ret) { pr_err("Failed gpio lp1 %s for irq=%d, error=%d\n", (enable ? "enable" : "disable"), d->irq, ret); diff --git a/include/linux/tegra-pm.h b/include/linux/tegra-pm.h index 37ccc88cbbf..171a91de648 100644 --- a/include/linux/tegra-pm.h +++ b/include/linux/tegra-pm.h @@ -1,7 +1,7 @@ /* * include/linux/tegra-pm.h * - * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,7 +23,16 @@ #define TEGRA_PM_SUSPEND 0x0001 #define TEGRA_PM_RESUME 0x0002 +enum tegra_suspend_mode { + TEGRA_SUSPEND_NONE = 0, + TEGRA_SUSPEND_LP2, /* CPU voltage off */ + TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */ + TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */ + TEGRA_MAX_SUSPEND_MODE, +}; + int tegra_register_pm_notifier(struct notifier_block *nb); int tegra_unregister_pm_notifier(struct notifier_block *nb); +extern enum tegra_suspend_mode current_suspend_mode; #endif /* _LINUX_TEGRA_PM_H_ */ diff --git a/sound/soc/tegra/tegra_rt5639.c b/sound/soc/tegra/tegra_rt5639.c index fcea25dfe11..28e81f761b9 100644 --- a/sound/soc/tegra/tegra_rt5639.c +++ b/sound/soc/tegra/tegra_rt5639.c @@ -1036,6 +1036,7 @@ static int tegra_rt5639_init(struct snd_soc_pcm_runtime *rtd) if (gpio_is_valid(pdata->gpio_hp_det)) { tegra_rt5639_hp_jack_gpio.gpio = pdata->gpio_hp_det; + tegra_rt5639_hp_jack_gpio.wake = true; tegra_rt5639_hp_jack_gpio.invert = !pdata->gpio_hp_det_active_high; snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, -- 2.39.2