/*! ****************************************************************************** @Function PVRSRVSetDevicePowerStateKM @Description Set the Device into a new state @Input ui32DeviceIndex : device index @Input eNewPowerState : New power state @Input bForced : TRUE if the transition should not fail (e.g. OS request) @Return PVRSRV_ERROR ******************************************************************************/ IMG_EXPORT PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex, PVRSRV_DEV_POWER_STATE eNewPowerState, IMG_BOOL bForced) { PVRSRV_DATA* psPVRSRVData = PVRSRVGetPVRSRVData(); PVRSRV_ERROR eError; PVRSRV_DEV_POWER_STATE eOldPowerState; eError = PVRSRVGetDevicePowerState(ui32DeviceIndex, &eOldPowerState); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVSetDevicePowerStateKM: Couldn't read power state.")); eOldPowerState = PVRSRV_DEV_POWER_STATE_DEFAULT; } #if defined(PDUMP) if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) { /* Pdump a power-up regardless of the default state. Then disable pdump and transition to the default power state. This ensures that a power-up is always present in the pdump when necessary. */ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON, bForced); if(eError != PVRSRV_OK) { goto Exit; } eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON, bForced); if (eError != PVRSRV_OK) { goto Exit; } PDUMPPOWCMDSTART(); } #endif /* PDUMP */ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState, bForced); if(eError != PVRSRV_OK) { if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) { PDUMPPOWCMDEND(); } goto Exit; } eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState, bForced); if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) { PDUMPPOWCMDEND(); } /* Signal Device Watchdog Thread about power mode change. */ if (eOldPowerState != eNewPowerState && eNewPowerState == PVRSRV_DEV_POWER_STATE_ON) { psPVRSRVData->ui32DevicesWatchdogPwrTrans++; if (psPVRSRVData->ui32DevicesWatchdogTimeout == DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT) { if (psPVRSRVData->hDevicesWatchdogEvObj) { eError = OSEventObjectSignal(psPVRSRVData->hDevicesWatchdogEvObj); PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal"); } } } Exit: if (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED) { PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSetDevicePowerStateKM : Transition to %d was denied, Forced=%d", eNewPowerState, bForced)); } else if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_WARNING, "PVRSRVSetDevicePowerStateKM : Transition to %d FAILED (%s)", eNewPowerState, PVRSRVGetErrorStringKM(eError))); } return eError; }
PVRSRV_ERROR RGXPreKickCacheCommand(PVRSRV_RGXDEV_INFO *psDevInfo) { PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode; RGXFWIF_KCCB_CMD sFlushCmd; PVRSRV_ERROR eError = PVRSRV_OK; RGXFWIF_DM eDMcount = RGXFWIF_DM_MAX; if (!ui32CacheOpps) { goto _PVRSRVPowerLock_Exit; } sFlushCmd.eCmdType = RGXFWIF_KCCB_CMD_MMUCACHE; /* Set which memory context this command is for (all ctxs for now) */ ui32CacheOpps |= RGXFWIF_MMUCACHEDATA_FLAGS_CTX_ALL; #if 0 sFlushCmd.uCmdData.sMMUCacheData.psMemoryContext = ??? #endif /* PVRSRVPowerLock guarantees atomicity between commands and global variables consistency. * This is helpful in a scenario with several applications allocating resources. */ eError = PVRSRVPowerLock(); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_WARNING, "RGXPreKickCacheCommand: failed to acquire powerlock (%s)", PVRSRVGetErrorStringKM(eError))); goto _PVRSRVPowerLock_Exit; } PDUMPPOWCMDSTART(); eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON, IMG_FALSE); PDUMPPOWCMDEND(); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_WARNING, "RGXPreKickCacheCommand: failed to transition RGX to ON (%s)", PVRSRVGetErrorStringKM(eError))); goto _PVRSRVSetDevicePowerStateKM_Exit; } sFlushCmd.uCmdData.sMMUCacheData.ui32Flags = ui32CacheOpps; sFlushCmd.uCmdData.sMMUCacheData.ui32CacheSequenceNum = ++ui32CacheOpSequence; #if defined(PDUMP) PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit MMU flush and invalidate (flags = 0x%08x, cache operation sequence = %u)", ui32CacheOpps, ui32CacheOpSequence); #endif ui32CacheOpps = 0; /* Schedule MMU cache command */ do { eDMcount--; eError = RGXSendCommandRaw(psDevInfo, eDMcount, &sFlushCmd, sizeof(RGXFWIF_KCCB_CMD), PDUMP_FLAGS_CONTINUOUS); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"RGXPreKickCacheCommand: Failed to schedule MMU cache command \ to DM=%d with error (%u)", eDMcount, eError)); break; } } while(eDMcount > 0); _PVRSRVSetDevicePowerStateKM_Exit: PVRSRVPowerUnlock(); _PVRSRVPowerLock_Exit: return eError; }