From: Finley Xiao Date: Wed, 1 Jun 2016 08:15:54 +0000 (+0800) Subject: MALI: rockchip: add power-off-delay function X-Git-Tag: firefly_0821_release~2462 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b6b24819f586d7b20f867e855c7bafbe4af45eff;p=firefly-linux-kernel-4.4.55.git MALI: rockchip: add power-off-delay function As gpu power on and off frequently, and the interval time is smaller than the polling time of devfreq, add power-off-delay function to ensure devfreq work fine. Change-Id: Iba2405c9ead91a437233f1fedf2f3555703aa9e1 Signed-off-by: Finley Xiao --- diff --git a/drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c b/drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c old mode 100755 new mode 100644 index 9514daf42a8a..df15a9a6901b --- a/drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c +++ b/drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c @@ -17,6 +17,7 @@ #include #include +#include #include "mali_kbase_rk.h" @@ -49,6 +50,28 @@ static void rk_pm_disable_clk(struct kbase_device *kbdev); /*---------------------------------------------------------------------------*/ +static void rk_pm_power_off_delay_work(struct work_struct *work) +{ + struct rk_context *platform = + container_of(to_delayed_work(work), struct rk_context, work); + struct kbase_device *kbdev = platform->kbdev; + + if (!platform->is_powered) { + D("mali_dev is already powered off."); + return; + } + + if (pm_runtime_enabled(kbdev->dev)) { + D("to put_sync_suspend mali_dev."); + pm_runtime_put_sync_suspend(kbdev->dev); + } + + rk_pm_disable_regulator(kbdev); + + platform->is_powered = false; + KBASE_TIMELINE_GPU_POWER(kbdev, 0); +} + static int kbase_platform_rk_init(struct kbase_device *kbdev) { struct rk_context *platform; @@ -60,14 +83,40 @@ static int kbase_platform_rk_init(struct kbase_device *kbdev) } platform->is_powered = false; + platform->kbdev = kbdev; + + platform->delay_ms = 200; + if (of_property_read_u32(kbdev->dev->of_node, "power-off-delay-ms", + &platform->delay_ms)) + W("power-off-delay-ms not available."); + + platform->power_off_wq = create_freezable_workqueue("gpu_power_off_wq"); + if (!platform->power_off_wq) { + E("couldn't create workqueue"); + return -ENOMEM; + } + INIT_DEFERRABLE_WORK(&platform->work, rk_pm_power_off_delay_work); kbdev->platform_context = (void *)platform; + pm_runtime_enable(kbdev->dev); return 0; } static void kbase_platform_rk_term(struct kbase_device *kbdev) { + struct rk_context *platform = + (struct rk_context *)kbdev->platform_context; + + pm_runtime_disable(kbdev->dev); + kbdev->platform_context = NULL; + + if (platform) { + destroy_workqueue(platform->power_off_wq); + platform->is_powered = false; + platform->kbdev = NULL; + kfree(platform); + } } struct kbase_platform_funcs_conf platform_funcs = { @@ -90,16 +139,22 @@ static int rk_pm_callback_power_on(struct kbase_device *kbdev) { int ret = 1; /* Assume GPU has been powered off */ int err = 0; - struct rk_context *platform; + struct rk_context *platform = + (struct rk_context *)kbdev->platform_context; + + cancel_delayed_work_sync(&platform->work); + + err = rk_pm_enable_clk(kbdev); + if (err) { + E("failed to enable clk: %d", err); + return err; + } - platform = (struct rk_context *)kbdev->platform_context; if (platform->is_powered) { - W("mali_device is already powered."); + D("mali_device is already powered."); return 0; } - D("powering on."); - /* we must enable vdd_gpu before pd_gpu_in_chip. */ err = rk_pm_enable_regulator(kbdev); if (err) { @@ -123,12 +178,6 @@ static int rk_pm_callback_power_on(struct kbase_device *kbdev) } } - err = rk_pm_enable_clk(kbdev); /* clk is not relative to pd. */ - if (err) { - E("failed to enable clk: %d", err); - return err; - } - platform->is_powered = true; KBASE_TIMELINE_GPU_POWER(kbdev, 1); @@ -140,44 +189,18 @@ static void rk_pm_callback_power_off(struct kbase_device *kbdev) struct rk_context *platform = (struct rk_context *)kbdev->platform_context; - if (!platform->is_powered) { - W("mali_dev is already powered off."); - return; - } - - D("powering off."); - - platform->is_powered = false; - KBASE_TIMELINE_GPU_POWER(kbdev, 0); - rk_pm_disable_clk(kbdev); - - if (pm_runtime_enabled(kbdev->dev)) { - pm_runtime_mark_last_busy(kbdev->dev); - D("to put_sync_suspend mali_dev."); - pm_runtime_put_sync_suspend(kbdev->dev); - } - - rk_pm_disable_regulator(kbdev); + queue_delayed_work(platform->power_off_wq, &platform->work, + msecs_to_jiffies(platform->delay_ms)); } int rk_kbase_device_runtime_init(struct kbase_device *kbdev) { - pm_runtime_set_autosuspend_delay(kbdev->dev, 200); - pm_runtime_use_autosuspend(kbdev->dev); - - /* no need to call pm_runtime_set_active here. */ - - D("to enable pm_runtime."); - pm_runtime_enable(kbdev->dev); - return 0; } void rk_kbase_device_runtime_disable(struct kbase_device *kbdev) { - D("to disable pm_runtime."); - pm_runtime_disable(kbdev->dev); } struct kbase_pm_callback_conf pm_callbacks = { diff --git a/drivers/gpu/arm/midgard/platform/rk/mali_kbase_rk.h b/drivers/gpu/arm/midgard/platform/rk/mali_kbase_rk.h index a4ebd50415bb..d6db811d1fce 100644 --- a/drivers/gpu/arm/midgard/platform/rk/mali_kbase_rk.h +++ b/drivers/gpu/arm/midgard/platform/rk/mali_kbase_rk.h @@ -24,6 +24,10 @@ */ struct rk_context { bool is_powered; + struct kbase_device *kbdev; + struct workqueue_struct *power_off_wq; + struct delayed_work work; + unsigned int delay_ms; }; #endif /* _MALI_KBASE_RK_H_ */