From: 陈亮 Date: Tue, 24 Jun 2014 06:11:32 +0000 (-0700) Subject: disable vdd_gpu when early suspend X-Git-Tag: firefly_0821_release~5054 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=89169e1bb9106e64512de3de0ef043d4a5d9ec68;p=firefly-linux-kernel-4.4.55.git disable vdd_gpu when early suspend Signed-off-by: 陈亮 --- diff --git a/arch/arm/boot/dts/rk3288-p977_8846.dts b/arch/arm/boot/dts/rk3288-p977_8846.dts index 26a26576d8c0..7a7c6b1678ff 100755 --- a/arch/arm/boot/dts/rk3288-p977_8846.dts +++ b/arch/arm/boot/dts/rk3288-p977_8846.dts @@ -346,8 +346,8 @@ regulator-name = "vdd_gpu"; regulator-min-microvolt = <712500>; regulator-max-microvolt = <1500000>; - regulator-always-on; - regulator-boot-on; + //regulator-always-on; + //regulator-boot-on; regulator-initial-mode = <0x2>; regulator-initial-state = <3>; regulator-state-mem { diff --git a/arch/arm/boot/dts/rk3288-tb.dts b/arch/arm/boot/dts/rk3288-tb.dts index 53799123cc60..1ff6ae730612 100755 --- a/arch/arm/boot/dts/rk3288-tb.dts +++ b/arch/arm/boot/dts/rk3288-tb.dts @@ -887,8 +887,8 @@ rk808_dcdc2_reg: regulator@1 { regulator-name= "vdd_gpu"; - regulator-always-on; - regulator-boot-on; + //regulator-always-on; + //regulator-boot-on; }; rk808_dcdc3_reg: regulator@2 { diff --git a/arch/arm/mach-rockchip/dvfs.c b/arch/arm/mach-rockchip/dvfs.c index eaa3136a1563..d6c70be7a862 100644 --- a/arch/arm/mach-rockchip/dvfs.c +++ b/arch/arm/mach-rockchip/dvfs.c @@ -21,6 +21,9 @@ #include #include #include +#include +#include +#include "../../../drivers/clk/rockchip/clk-pd.h" extern int rockchip_tsadc_get_temp(int chn); @@ -32,6 +35,108 @@ static struct dvfs_node *clk_cpu_dvfs_node; static unsigned int target_temp = 80; static int temp_limit_enable = 1; +static int pd_gpu_off, early_suspend; +static DEFINE_MUTEX(switch_vdd_gpu_mutex); +struct regulator *vdd_gpu_regulator; + +static int vdd_gpu_reboot_notifier_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + int ret; + + DVFS_DBG("%s: enable vdd_gpu\n", __func__); + mutex_lock(&switch_vdd_gpu_mutex); + if (!regulator_is_enabled(vdd_gpu_regulator)) + ret = regulator_enable(vdd_gpu_regulator); + mutex_unlock(&switch_vdd_gpu_mutex); + + return NOTIFY_OK; +} + +static struct notifier_block vdd_gpu_reboot_notifier = { + .notifier_call = vdd_gpu_reboot_notifier_event, +}; + +static int clk_pd_gpu_notifier_call(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + int ret; + + mutex_lock(&switch_vdd_gpu_mutex); + switch (event) { + case RK_CLK_PD_PREPARE: + pd_gpu_off = 0; + if (early_suspend) { + if (!regulator_is_enabled(vdd_gpu_regulator)) + ret = regulator_enable(vdd_gpu_regulator); + } + break; + case RK_CLK_PD_UNPREPARE: + pd_gpu_off = 1; + if (early_suspend) { + if (regulator_is_enabled(vdd_gpu_regulator)) + ret = regulator_disable(vdd_gpu_regulator); + } + break; + default: + break; + } + mutex_unlock(&switch_vdd_gpu_mutex); + + return NOTIFY_OK; +} + +static struct notifier_block clk_pd_gpu_notifier = { + .notifier_call = clk_pd_gpu_notifier_call, +}; + + +static int early_suspend_notifier_call(struct notifier_block *self, + unsigned long action, void *data) +{ + struct fb_event *event = data; + int blank_mode = *((int *)event->data); + int ret; + + mutex_lock(&switch_vdd_gpu_mutex); + if (action == FB_EARLY_EVENT_BLANK) { + switch (blank_mode) { + case FB_BLANK_UNBLANK: + early_suspend = 0; + if (pd_gpu_off) { + if (!regulator_is_enabled(vdd_gpu_regulator)) + ret = regulator_enable( + vdd_gpu_regulator); + } + break; + default: + break; + } + } else if (action == FB_EVENT_BLANK) { + switch (blank_mode) { + case FB_BLANK_POWERDOWN: + early_suspend = 1; + if (pd_gpu_off) { + if (regulator_is_enabled(vdd_gpu_regulator)) + ret = regulator_disable( + vdd_gpu_regulator); + } + + break; + default: + break; + } + } + mutex_unlock(&switch_vdd_gpu_mutex); + + return NOTIFY_OK; +} + +static struct notifier_block early_suspend_notifier = { + .notifier_call = early_suspend_notifier_call, +}; + + static void dvfs_volt_up_delay(struct vd_node *vd, int new_volt, int old_volt) { int u_time; @@ -1395,6 +1500,17 @@ static int __init dvfs_init(void) queue_delayed_work_on(0, dvfs_wq, &dvfs_temp_limit_work, 0*HZ); } + vdd_gpu_regulator = dvfs_get_regulator("vdd_gpu"); + if (!IS_ERR_OR_NULL(vdd_gpu_regulator)) { + struct clk *clk = clk_get(NULL, "pd_gpu"); + + if (clk) + rk_clk_pd_notifier_register(clk, &clk_pd_gpu_notifier); + + fb_register_client(&early_suspend_notifier); + register_reboot_notifier(&vdd_gpu_reboot_notifier); + } + return ret; } diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c index b4af52f96c1f..559d92c273bd 100644 --- a/drivers/cpufreq/rockchip-cpufreq.c +++ b/drivers/cpufreq/rockchip-cpufreq.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "../../../drivers/clk/rockchip/clk-pd.h" extern void dvfs_disable_temp_limit(void); @@ -174,11 +175,26 @@ static int cpufreq_scale_rate_for_dvfs(struct clk *clk, unsigned long rate) static int cpufreq_init_cpu0(struct cpufreq_policy *policy) { unsigned int i; + int ret; + struct regulator *vdd_gpu_regulator; + gpu_is_mali400 = cpu_is_rk3188(); clk_gpu_dvfs_node = clk_get_dvfs_node("clk_gpu"); if (clk_gpu_dvfs_node){ clk_enable_dvfs(clk_gpu_dvfs_node); + vdd_gpu_regulator = dvfs_get_regulator("vdd_gpu"); + if (!IS_ERR_OR_NULL(vdd_gpu_regulator)) { + if (!regulator_is_enabled(vdd_gpu_regulator)) { + ret = regulator_enable(vdd_gpu_regulator); + arm_pm_restart('h', NULL); + } + /* make sure vdd_gpu_regulator is in use, + so it will not be disable by regulator_init_complete*/ + ret = regulator_enable(vdd_gpu_regulator); + if (ret != 0) + arm_pm_restart('h', NULL); + } if (gpu_is_mali400) dvfs_clk_enable_limit(clk_gpu_dvfs_node, 133000000, 600000000); }