From 40acaf74889e9efcf2304f4a3cd34794152faf47 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E6=9D=9C=E5=9D=A4=E6=98=8E?= Date: Wed, 4 May 2011 14:16:44 +0800 Subject: [PATCH] gpu: add support of enter power off while gpu in idle for a long time --- .../XAQ2/hal/kernel/gc_hal_kernel_hardware.c | 40 +++++++++++++++++++ .../rk29/vivante/hal/inc/gc_hal_options.h | 16 +++++++- .../os/linux/kernel/gc_hal_kernel_device.c | 3 +- .../os/linux/kernel/gc_hal_kernel_driver.c | 19 ++++----- 4 files changed, 67 insertions(+), 11 deletions(-) diff --git a/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c b/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c index ab1f0cfba511..5f086e2133af 100755 --- a/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c +++ b/drivers/staging/rk29/vivante/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c @@ -93,6 +93,24 @@ inline void cal_run_idle(gceCHIPPOWERSTATE State) #endif +#if gcdENABLE_LONG_IDLE_POWEROFF +#include +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; diff --git a/drivers/staging/rk29/vivante/hal/inc/gc_hal_options.h b/drivers/staging/rk29/vivante/hal/inc/gc_hal_options.h index f4158b80905c..eb3debc75133 100755 --- a/drivers/staging/rk29/vivante/hal/inc/gc_hal_options.h +++ b/drivers/staging/rk29/vivante/hal/inc/gc_hal_options.h @@ -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 2 + + +/* + gcdENABLE_LONG_IDLE_POWEROFF + + ³¤Ê±¼äIDLEºó½øÈëPowerOff, ¸Ã¹¦ÄÜ¿ªÆôºóÐèÒª°ÑEarlySuspend¹¦Äܹصô + ÕâÑù¿ÉÒÔʹijЩ²»Ê¹ÓÃGPUµÄ³¡¾°µÄ¹¦ºÄ½øÒ»²½½µµÍ£¬ÈçÊÓƵ²¥·Åʱ£¬Ò»¼¶´ý»úʱ£¬ + »ò³¤Ê±¼ä²»²Ù×÷½çÃ浫»¹Î´½øÈëÒ»¼¶´ý»ú */ -#define gcdENABLE_DELAY_EARLY_SUSPEND 0 +#define gcdENABLE_LONG_IDLE_POWEROFF 1 #endif /* __gc_hal_options_h_ */ diff --git a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_device.c b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_device.c index bf3e657489b1..6efee265b58e 100755 --- a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_device.c +++ b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_device.c @@ -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; diff --git a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c index 142b96c177ae..29fb592e7db4 100755 --- a/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c +++ b/drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_driver.c @@ -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 @@ gpu_probe_fail: 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(); -- 2.34.1