gpu: add support of enter power off while gpu in idle for a long time

This commit is contained in:
杜坤明 2011-05-04 14:16:44 +08:00
parent 3901afba10
commit 40acaf7488
4 changed files with 67 additions and 11 deletions

View File

@ -93,6 +93,24 @@ inline void cal_run_idle(gceCHIPPOWERSTATE State)
#endif
#if gcdENABLE_LONG_IDLE_POWEROFF
#include <linux/workqueue.h>
struct delayed_work poweroff_work;
static gckHARDWARE gHardware = gcvNULL;
void time_to_poweroff(struct work_struct *work)
{
gceSTATUS status;
if(NULL==gHardware) return;
status = gckHARDWARE_SetPowerManagementState(gHardware, gcvPOWER_OFF_BROADCAST);
if (gcmIS_ERROR(status))
{
printk("%s fail!\n", __func__);
return;
}
}
#endif
/******************************************************************************\
********************************* Support Code *********************************
\******************************************************************************/
@ -433,6 +451,11 @@ gckHARDWARE_Construct(
/* Return pointer to the gckHARDWARE object. */
*Hardware = hardware;
#if gcdENABLE_LONG_IDLE_POWEROFF
INIT_DELAYED_WORK(&poweroff_work, time_to_poweroff);
gHardware = hardware;
#endif
/* Success. */
gcmkFOOTER_ARG("*Hardware=0x%x", *Hardware);
return gcvSTATUS_OK;
@ -2963,6 +2986,17 @@ gckHARDWARE_SetPowerManagementState(
os = Hardware->os;
gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
#if gcdENABLE_LONG_IDLE_POWEROFF
if(gcvPOWER_IDLE_BROADCAST==State) {
cancel_delayed_work_sync(&poweroff_work);
schedule_delayed_work(&poweroff_work, 5*HZ);
} else if(gcvPOWER_OFF_BROADCAST==State) {
// NULL
} else {
cancel_delayed_work_sync(&poweroff_work);
}
#endif
/* Convert the broadcast power state. */
switch (State)
{
@ -3068,6 +3102,12 @@ gckHARDWARE_SetPowerManagementState(
if ((flag == 0) || (Hardware->settingPowerState))
{
#if gcdENABLE_LONG_IDLE_POWEROFF
if( (gcvPOWER_OFF==Hardware->chipPowerState) && (gcvPOWER_OFF==State) && (gcvFALSE==broadcast) )
{
Hardware->broadcast = gcvFALSE;
}
#endif
/* Release the power mutex. */
Hardware->powerProcess = 0;
Hardware->powerThread = 0;

View File

@ -274,13 +274,27 @@
*/
#define gcdENABLE_MEM_CACHE 2
/*
gcdENABLE_DELAY_EARLY_SUSPEND
gpu_early_suspend中使用延时工作队列来执行suspend,
gpu_early_suspend过早执行导致用户线程的事情还处理干净
0: 使early_suspend功能
1: 使delay的early_suspend功能
2: early_suspend功能
*/
#define gcdENABLE_DELAY_EARLY_SUSPEND 0
#define gcdENABLE_DELAY_EARLY_SUSPEND 2
/*
gcdENABLE_LONG_IDLE_POWEROFF
IDLE后进入PowerOff, EarlySuspend功能关掉
使使GPU的场景的功耗进一步降低
*/
#define gcdENABLE_LONG_IDLE_POWEROFF 1
#endif /* __gc_hal_options_h_ */

View File

@ -488,7 +488,7 @@ gckGALDEVICE_Construct(
device->registerBase = (gctPOINTER) ioremap_nocache(RegisterMemBase,
RegisterMemSize);
if (!device->registerBase)
{
{
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
"[galcore] gckGALDEVICE_Construct: Unable to map location->0x%lX for size->%ld",
RegisterMemBase,
@ -496,6 +496,7 @@ gckGALDEVICE_Construct(
return gcvSTATUS_OUT_OF_RESOURCES;
}
printk("---- gpu regbase: 0x%08x ---- \n", (unsigned int)device->registerBase);
physical += RegisterMemSize;

View File

@ -151,7 +151,7 @@ void gputimer_callback(unsigned long arg)
}
#endif
#if gcdENABLE_DELAY_EARLY_SUSPEND
#if (1==gcdENABLE_DELAY_EARLY_SUSPEND)
struct delayed_work suspend_work;
void real_suspend(struct work_struct *work)
{
@ -770,11 +770,10 @@ module_exit(drv_exit);
#if CONFIG_HAS_EARLYSUSPEND
static void gpu_early_suspend(struct early_suspend *h)
{
#if gcdENABLE_DELAY_EARLY_SUSPEND
#if (1==gcdENABLE_DELAY_EARLY_SUSPEND)
schedule_delayed_work(&suspend_work, 5*HZ);
#else
gceSTATUS status;
status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_OFF);
if (gcmIS_ERROR(status))
@ -789,7 +788,7 @@ static void gpu_early_resume(struct early_suspend *h)
{
gceSTATUS status;
#if gcdENABLE_DELAY_EARLY_SUSPEND
#if (1==gcdENABLE_DELAY_EARLY_SUSPEND)
cancel_delayed_work_sync(&suspend_work);
#endif
status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_ON);
@ -843,10 +842,12 @@ static int __devinit gpu_probe(struct platform_device *pdev)
#endif
#if CONFIG_HAS_EARLYSUSPEND
//register_early_suspend(&gpu_early_suspend_info);
#if (2!=gcdENABLE_DELAY_EARLY_SUSPEND)
register_early_suspend(&gpu_early_suspend_info);
#endif
#endif
#if gcdENABLE_DELAY_EARLY_SUSPEND
#if (1==gcdENABLE_DELAY_EARLY_SUSPEND)
INIT_DELAYED_WORK(&suspend_work, real_suspend);
#endif
@ -863,7 +864,7 @@ static int __devinit gpu_probe(struct platform_device *pdev)
static int __devinit gpu_remove(struct platform_device *pdev)
{
#if gcdENABLE_DELAY_EARLY_SUSPEND
#if (1==gcdENABLE_DELAY_EARLY_SUSPEND)
cancel_delayed_work_sync(&suspend_work);
#endif
drv_exit();
@ -875,7 +876,7 @@ static int __devinit gpu_suspend(struct platform_device *dev, pm_message_t state
gceSTATUS status;
gckGALDEVICE device;
#if gcdENABLE_DELAY_EARLY_SUSPEND
#if (1==gcdENABLE_DELAY_EARLY_SUSPEND)
cancel_delayed_work_sync(&suspend_work);
#endif
device = platform_get_drvdata(dev);
@ -911,7 +912,7 @@ static int __devinit gpu_resume(struct platform_device *dev)
static void __devinit gpu_shutdown(struct platform_device *dev)
{
#if gcdENABLE_DELAY_EARLY_SUSPEND
#if (1==gcdENABLE_DELAY_EARLY_SUSPEND)
cancel_delayed_work_sync(&suspend_work);
#endif
drv_exit();