enum PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(u32 ui32DeviceIndex, enum PVR_POWER_STATE eNewPowerState, u32 ui32CallerID, IMG_BOOL bRetainMutex) { enum PVRSRV_ERROR eError; struct SYS_DATA *psSysData; eError = SysAcquireData(&psSysData); if (eError != PVRSRV_OK) return eError; eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE); if (eError != PVRSRV_OK) return eError; #if defined(PDUMP) if (eNewPowerState == PVRSRV_POWER_Unspecified) { eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_POWER_STATE_D0); if (eError != PVRSRV_OK) goto Exit; eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_POWER_STATE_D0); if (eError != PVRSRV_OK) goto Exit; PDUMPSUSPEND(); } #endif eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState); if (eError != PVRSRV_OK) { if (eNewPowerState == PVRSRV_POWER_Unspecified) PDUMPRESUME(); goto Exit; } eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState); if (eNewPowerState == PVRSRV_POWER_Unspecified) PDUMPRESUME(); Exit: if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVSetDevicePowerStateKM : " "Transition to %d FAILED 0x%x", eNewPowerState, eError); } if (!bRetainMutex || (eError != PVRSRV_OK)) PVRSRVPowerUnlock(ui32CallerID); return eError; }
IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32CallerID) { PVRSRV_ERROR eError = PVRSRV_OK; PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl; #if defined(SYS_SUPPORTS_SGX_IDLE_CALLBACK) if (!psDevInfo->bSGXIdle && ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) != 0)) { psDevInfo->bSGXIdle = IMG_TRUE; SysSGXIdleTransition(psDevInfo->bSGXIdle); } else if (psDevInfo->bSGXIdle && ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) == 0)) { psDevInfo->bSGXIdle = IMG_FALSE; SysSGXIdleTransition(psDevInfo->bSGXIdle); } #endif if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) && ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0)) { psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER; PDUMPSUSPEND(); #if defined(SYS_CUSTOM_POWERDOWN) eError = SysPowerDownMISR(psDeviceNode, ui32CallerID); #else eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_OFF, ui32CallerID, IMG_FALSE); if (eError == PVRSRV_OK) { SGXPostActivePowerEvent(psDeviceNode, ui32CallerID); } #endif if (eError == PVRSRV_ERROR_RETRY) { psSGXHostCtl->ui32InterruptClearFlags &= ~PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER; eError = PVRSRV_OK; } PDUMPRESUME(); } if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%u", eError)); } }
IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32CallerID) { PVRSRV_ERROR eError = PVRSRV_OK; PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl; #if defined(SYS_SUPPORTS_SGX_IDLE_CALLBACK) if (!psDevInfo->bSGXIdle && ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) != 0)) { psDevInfo->bSGXIdle = IMG_TRUE; SysSGXIdleTransition(psDevInfo->bSGXIdle); } else if (psDevInfo->bSGXIdle && ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) == 0)) { psDevInfo->bSGXIdle = IMG_FALSE; SysSGXIdleTransition(psDevInfo->bSGXIdle); } #endif /** * Quickly check (without lock) if there is an APM event we should handle. * This check fails most of the time so we don't want to incur lock overhead. * Check the flags in the reverse order that microkernel clears them to prevent * us from seeing an inconsistent state. */ if (((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0) && ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0)) { eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE); if (eError == PVRSRV_ERROR_RETRY) return; if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SGXTestActivePowerEvent failed to acquire lock - " "ui32CallerID:%d eError:%u", ui32CallerID, eError)); return; } /** * Check again (with lock) if APM event has been cleared or handled. A race * condition may allow multiple threads to pass the quick check. */ if (((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) || ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0)) { PVRSRVPowerUnlock(ui32CallerID); return; } psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER; PDUMPSUSPEND(); #if defined(SYS_CUSTOM_POWERDOWN) eError = SysPowerDownMISR(psDeviceNode, ui32CallerID); #else eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_OFF); if (eError == PVRSRV_OK) { SGXPostActivePowerEvent(psDeviceNode, ui32CallerID); } #endif PVRSRVPowerUnlock(ui32CallerID); PDUMPRESUME(); } if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%u", eError)); } }
IMG_EXPORT PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex, PVRSRV_DEV_POWER_STATE eNewPowerState, IMG_UINT32 ui32CallerID, IMG_BOOL bRetainMutex) { PVRSRV_ERROR eError; SYS_DATA *psSysData; SysAcquireData(&psSysData); eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE); if(eError != PVRSRV_OK) { return eError; } #if defined(PDUMP) if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) { eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON); if(eError != PVRSRV_OK) { goto Exit; } eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON); if (eError != PVRSRV_OK) { goto Exit; } PDUMPSUSPEND(); } #endif eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState); if(eError != PVRSRV_OK) { if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) { PDUMPRESUME(); } goto Exit; } eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState); if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) { PDUMPRESUME(); } Exit: if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetDevicePowerStateKM : Transition to %d FAILED 0x%x", eNewPowerState, eError)); } if (!bRetainMutex || (eError != PVRSRV_OK)) { PVRSRVPowerUnlock(ui32CallerID); } return eError; }