summaryrefslogtreecommitdiff
path: root/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c')
-rw-r--r--drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c177
1 files changed, 105 insertions, 72 deletions
diff --git a/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c b/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c
index 70c2cd6b9d4b..a17d2fdb7747 100644
--- a/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c
+++ b/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c
@@ -217,50 +217,17 @@ _IdentifyHardware(
return status;
}
-static gctTHREADFUNCRESULT gctTHREADFUNCTYPE
-_TimeIdleThread(
- gctTHREADFUNCPARAMETER ThreadParameter
+#if gcdPOWEROFF_TIMEOUT
+void
+_VGPowerTimerFunction(
+ gctPOINTER Data
)
{
- gctUINT32 currentTime = 0;
- gctBOOL isAfter = gcvFALSE;
- gceCHIPPOWERSTATE state;
-
- /* Cast the object. */
- gckVGHARDWARE hardware = (gckVGHARDWARE) ThreadParameter;
-
- while(gcvTRUE)
- {
- gcmkVERIFY_OK(gckOS_WaitSignal(hardware->os,
- hardware->idleSignal, gcvINFINITE));
-
- if (hardware->killThread)
- {
- break;
- }
-
- do
- {
- gcmkVERIFY_OK(gckOS_GetTicks(&currentTime));
-
- gcmkVERIFY_OK(
- gckOS_TicksAfter(currentTime, hardware->powerOffTime, &isAfter));
-
- if (isAfter)
- {
- gcmkVERIFY_OK(gckVGHARDWARE_SetPowerManagementState(
- hardware, gcvPOWER_OFF_BROADCAST));
- }
-
- gcmkVERIFY_OK(gckOS_Delay(hardware->os, 200));
-
- gcmkVERIFY_OK(gckVGHARDWARE_QueryPowerManagementState(
- hardware, &state));
-
- } while (state == gcvPOWER_IDLE);
- }
- return 0;
+ gckVGHARDWARE hardware = (gckVGHARDWARE)Data;
+ gcmkVERIFY_OK(
+ gckVGHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF_TIMEOUT));
}
+#endif
/******************************************************************************\
****************************** gckVGHARDWARE API code *****************************
@@ -338,15 +305,21 @@ gckVGHARDWARE_Construct(
hardware->chipMinorFeatures2 = chipMinorFeatures2;
hardware->powerMutex = gcvNULL;
- hardware->idleSignal = gcvNULL;
hardware->chipPowerState = gcvPOWER_ON;
hardware->chipPowerStateGlobal = gcvPOWER_ON;
hardware->clockState = gcvTRUE;
hardware->powerState = gcvTRUE;
- hardware->powerOffTimeout = gcdPOWEROFF_TIMEOUT;
+
hardware->powerOffTime = 0;
- hardware->timeIdleThread = gcvNULL;
- hardware->killThread = gcvFALSE;
+#if gcdPOWEROFF_TIMEOUT
+ hardware->powerOffTimeout = gcdPOWEROFF_TIMEOUT;
+
+ gcmkVERIFY_OK(gckOS_CreateTimer(Os,
+ _VGPowerTimerFunction,
+ (gctPOINTER)hardware,
+ &hardware->powerOffTimer));
+#endif
+
/* Determine whether FE 2.0 is present. */
hardware->fe20 = ((((gctUINT32) (hardware->chipFeatures)) >> (0 ? 28:28) & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))));
@@ -365,18 +338,10 @@ gckVGHARDWARE_Construct(
gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(hardware, -1));
gcmkERR_BREAK(gckOS_CreateMutex(Os, &hardware->powerMutex));
- gcmkERR_BREAK(gckOS_CreateSignal(Os, gcvFALSE, &hardware->idleSignal));
/* Enable power management by default. */
hardware->powerManagement = gcvTRUE;
- gcmkERR_BREAK(gckOS_StartThread(
- hardware->os,
- _TimeIdleThread,
- hardware,
- &hardware->timeIdleThread
- ));
-
/* Return pointer to the gckVGHARDWARE object. */
*Hardware = hardware;
@@ -386,6 +351,14 @@ gckVGHARDWARE_Construct(
}
while (gcvFALSE);
+#if gcdPOWEROFF_TIMEOUT
+ if (hardware->powerOffTimer != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
+ }
+#endif
+
if (hardware->pageTableDirty != gcvNULL)
{
gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
@@ -428,10 +401,6 @@ gckVGHARDWARE_Destroy(
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
- Hardware->killThread = gcvTRUE;
- gcmkVERIFY_OK(gckOS_Signal(Hardware->os, Hardware->idleSignal, gcvTRUE));
- gcmkVERIFY_OK(gckOS_StopThread(Hardware->os, Hardware->timeIdleThread));
-
/* Mark the object as unknown. */
Hardware->object.type = gcvOBJ_UNKNOWN;
@@ -441,11 +410,10 @@ gckVGHARDWARE_Destroy(
Hardware->os, Hardware->powerMutex));
}
- if (Hardware->idleSignal != gcvNULL)
- {
- gcmkVERIFY_OK(gckOS_DestroySignal(
- Hardware->os, Hardware->idleSignal));
- }
+#if gcdPOWEROFF_TIMEOUT
+ gcmkVERIFY_OK(gckOS_StopTimer(Hardware->os, Hardware->powerOffTimer));
+ gcmkVERIFY_OK(gckOS_DestroyTimer(Hardware->os, Hardware->powerOffTimer));
+#endif
if (Hardware->pageTableDirty != gcvNULL)
{
@@ -1510,11 +1478,15 @@ gckVGHARDWARE_SetPowerManagementState(
gctBOOL commitMutex = gcvFALSE;
gctBOOL mutexAcquired = gcvFALSE;
+#if gcdPOWEROFF_TIMEOUT
+ gctBOOL timeout = gcvFALSE;
+ gctBOOL isAfter = gcvFALSE;
+ gctUINT32 currentTime;
+#endif
+
gctBOOL broadcast = gcvFALSE;
gctUINT32 process, thread;
gctBOOL global = gcvFALSE;
- gctUINT32 currentTime;
-
#if gcdENABLE_PROFILING
gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
@@ -1661,6 +1633,16 @@ gckVGHARDWARE_SetPowerManagementState(
global = gcvTRUE;
break;
+#if gcdPOWEROFF_TIMEOUT
+ case gcvPOWER_OFF_TIMEOUT:
+ /* Convert to OFF and note we are inside broadcast. */
+ State = gcvPOWER_OFF;
+ broadcast = gcvTRUE;
+ /* Check time out */
+ timeout = gcvTRUE;
+ break;
+#endif
+
default:
break;
}
@@ -1719,6 +1701,31 @@ gckVGHARDWARE_SetPowerManagementState(
flag = flags[Hardware->chipPowerState][State];
/*clock = clocks[State];*/
+#if gcdPOWEROFF_TIMEOUT
+ if (timeout)
+ {
+ gcmkONERROR(gckOS_GetTicks(&currentTime));
+
+ gcmkONERROR(
+ gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
+
+ /* powerOffTime is pushed forward, give up.*/
+ if (isAfter
+ /* Expect a transition start from IDLE. */
+ || (Hardware->chipPowerState == gcvPOWER_ON)
+ || (Hardware->chipPowerState == gcvPOWER_OFF)
+ )
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ }
+#endif
+
if (flag == 0)
{
/* Release the power mutex. */
@@ -1742,6 +1749,18 @@ gckVGHARDWARE_SetPowerManagementState(
return gcvSTATUS_OK;
}
}
+ else
+ {
+ if (flag & gcvPOWER_FLAG_ACQUIRE)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+ acquired = gcvTRUE;
+
+ /* avoid acquiring again. */
+ flag &= ~gcvPOWER_FLAG_ACQUIRE;
+ }
+ }
if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
{
@@ -1858,14 +1877,6 @@ gckVGHARDWARE_SetPowerManagementState(
Hardware->chipPowerStateGlobal = State;
}
- if (State == gcvPOWER_IDLE)
- {
- gcmkVERIFY_OK(gckOS_Signal(os, Hardware->idleSignal, gcvTRUE));
- }
- /* Reset power off time */
- gcmkVERIFY_OK(gckOS_GetTicks(&currentTime));
- Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
-
if (commitMutex)
{
/* Acquire the mutex. */
@@ -1875,6 +1886,28 @@ gckVGHARDWARE_SetPowerManagementState(
));
}
+#if gcdPOWEROFF_TIMEOUT
+ /* Reset power off time */
+ gcmkONERROR(gckOS_GetTicks(&currentTime));
+
+ Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
+
+ if (State == gcvPOWER_IDLE)
+ {
+ /* Start a timer to power off GPU when GPU enters IDLE or SUSPEND. */
+ gcmkVERIFY_OK(gckOS_StartTimer(os,
+ Hardware->powerOffTimer,
+ Hardware->powerOffTimeout));
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "Cancel powerOfftimer");
+
+ /* Cancel running timer when GPU enters ON or OFF. */
+ gcmkVERIFY_OK(gckOS_StopTimer(os, Hardware->powerOffTimer));
+ }
+#endif
+
/* Release the power mutex. */
gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));