diff options
author | Pablo Ceballos <pceballos@nvidia.com> | 2013-10-09 14:01:48 -0700 |
---|---|---|
committer | Mitch Luban <mluban@nvidia.com> | 2013-10-17 09:57:23 -0700 |
commit | c169f3f2fcc55422dd319a620b26654effe2aed1 (patch) | |
tree | b3947e774879ac52c010417eadf317a275a691fd /arch/arm/mach-tegra/powergate-t12x.c | |
parent | fcbe240c620dc16abe8b09092c23f385c9ca49c2 (diff) |
arm: tegra: T124 DIS and VE powergate dependency
The DIS partition cannot be powergated without the VE partition first
being powergated. Implement this dependency using the ref-counts.
Bug 1310335
Bug 1350333
Change-Id: I4686816260e7e966635dc4786d07d7d390254c59
Signed-off-by: Pablo Ceballos <pceballos@nvidia.com>
Reviewed-on: http://git-master/r/288574
Reviewed-on: http://git-master/r/298773
Reviewed-by: Mitch Luban <mluban@nvidia.com>
Tested-by: Mitch Luban <mluban@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/powergate-t12x.c')
-rw-r--r-- | arch/arm/mach-tegra/powergate-t12x.c | 80 |
1 files changed, 39 insertions, 41 deletions
diff --git a/arch/arm/mach-tegra/powergate-t12x.c b/arch/arm/mach-tegra/powergate-t12x.c index 7c602a944e71..43087a9f4b94 100644 --- a/arch/arm/mach-tegra/powergate-t12x.c +++ b/arch/arm/mach-tegra/powergate-t12x.c @@ -489,58 +489,24 @@ static inline int tegra12x_unpowergate(int id) return 0; } -static int tegra12x_venc_powergate(int id) -{ - int ret = 0; - int ref_count = atomic_read(&ref_count_venc); - - if (!TEGRA_IS_VENC_POWERGATE_ID(id)) - return -EINVAL; - - ref_count = atomic_dec_return(&ref_count_venc); - - if (ref_count > 0) - return ret; - - if (ref_count <= 0) - ret = tegra12x_powergate(id); - - return ret; -} - -static int tegra12x_venc_unpowergate(int id) -{ - int ret = 0; - - if (!TEGRA_IS_VENC_POWERGATE_ID(id)) - return -EINVAL; - - atomic_inc(&ref_count_venc); - ret = tegra12x_unpowergate(id); - - return ret; -} - static int tegra12x_disp_powergate(int id) { int ret = 0; int ref_counta = atomic_read(&ref_count_dispa); int ref_countb = atomic_read(&ref_count_dispb); - - if (!TEGRA_IS_DISP_POWERGATE_ID(id)) - return -EINVAL; + int ref_countve = atomic_read(&ref_count_venc); if (id == TEGRA_POWERGATE_DISA) { ref_counta = atomic_dec_return(&ref_count_dispa); WARN_ONCE(ref_counta < 0, "DISPA ref count underflow"); - } else { + } else if (id == TEGRA_POWERGATE_DISB) { if (ref_countb > 0) ref_countb = atomic_dec_return(&ref_count_dispb); if (ref_countb <= 0) CHECK_RET(tegra12x_powergate(TEGRA_POWERGATE_DISB)); } - if ((ref_counta <= 0) && (ref_countb <= 0)) { + if ((ref_counta <= 0) && (ref_countb <= 0) && (ref_countve <= 0)) { CHECK_RET(tegra12x_powergate(TEGRA_POWERGATE_SOR)); CHECK_RET(tegra12x_powergate(TEGRA_POWERGATE_DISA)); } @@ -551,16 +517,13 @@ static int tegra12x_disp_unpowergate(int id) { int ret; - if (!TEGRA_IS_DISP_POWERGATE_ID(id)) - return -EINVAL; - /* always unpowergate dispA and SOR partition */ CHECK_RET(tegra12x_unpowergate(TEGRA_POWERGATE_DISA)); CHECK_RET(tegra12x_unpowergate(TEGRA_POWERGATE_SOR)); if (id == TEGRA_POWERGATE_DISA) atomic_inc(&ref_count_dispa); - else { + else if (id == TEGRA_POWERGATE_DISB) { atomic_inc(&ref_count_dispb); ret = tegra12x_unpowergate(TEGRA_POWERGATE_DISB); } @@ -568,6 +531,41 @@ static int tegra12x_disp_unpowergate(int id) return ret; } +static int tegra12x_venc_powergate(int id) +{ + int ret = 0; + int ref_count = atomic_read(&ref_count_venc); + + if (!TEGRA_IS_VENC_POWERGATE_ID(id)) + return -EINVAL; + + ref_count = atomic_dec_return(&ref_count_venc); + + if (ref_count > 0) + return ret; + + if (ref_count <= 0) { + CHECK_RET(tegra12x_powergate(id)); + CHECK_RET(tegra12x_disp_powergate(id)); + } + + return ret; +} + +static int tegra12x_venc_unpowergate(int id) +{ + int ret = 0; + + if (!TEGRA_IS_VENC_POWERGATE_ID(id)) + return -EINVAL; + + CHECK_RET(tegra12x_disp_unpowergate(id)); + + atomic_inc(&ref_count_venc); + CHECK_RET(tegra12x_unpowergate(id)); + + return ret; +} int tegra12x_powergate_partition(int id) { |