/*! ****************************************************************************** @Function PVRSRVDevicePreClockSpeedChange @Description Notification from system layer that a device clock speed change is about to happen. @Input ui32DeviceIndex : device index @Input bIdleDevice : whether the device should be idled @Input pvInfo @Return IMG_VOID ******************************************************************************/ PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex, IMG_BOOL bIdleDevice, IMG_VOID *pvInfo) { PVRSRV_ERROR eError = PVRSRV_OK; PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); PVRSRV_POWER_DEV *psPowerDevice; PVR_UNREFERENCED_PARAMETER(pvInfo); /*search the device and then do the pre clock speed change*/ psPowerDevice = (PVRSRV_POWER_DEV*) List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList, &MatchPowerDeviceIndex_AnyVaCb, ui32DeviceIndex); do { /* This mutex is released in PVRSRVDevicePostClockSpeedChange. */ eError = PVRSRVPowerLock(); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePreClockSpeedChange : failed to acquire lock, error:0x%x", eError)); return eError; } if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange) { eError = psPowerDevice->pfnPreClockSpeedChange(psPowerDevice->hDevCookie, bIdleDevice, psPowerDevice->eCurrentPowerState); if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED)) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePreClockSpeedChange : Device %u failed, error:0x%x", ui32DeviceIndex, eError)); } else if (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED) { PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVDevicePreClockSpeedChange : Device %u denied transition to IDLE", ui32DeviceIndex)); PVRSRVPowerUnlock(); OSSleepms(1); } } } while (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED); if (eError != PVRSRV_OK) { PVRSRVPowerUnlock(); } return eError; }
/*! ****************************************************************************** @Function PVRSRVDevicePostClockSpeedChange @Description Notification from system layer that a device clock speed change has just happened. @Input ui32DeviceIndex : device index @Input bIdleDevice : whether the device had been idled @Input pvInfo @Return IMG_VOID ******************************************************************************/ IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex, IMG_BOOL bIdleDevice, IMG_VOID *pvInfo) { PVRSRV_ERROR eError; PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); PVRSRV_POWER_DEV *psPowerDevice; PVR_UNREFERENCED_PARAMETER(pvInfo); /*search the device and then do the post clock speed change*/ psPowerDevice = (PVRSRV_POWER_DEV*) List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList, &MatchPowerDeviceIndex_AnyVaCb, ui32DeviceIndex); if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange) { eError = psPowerDevice->pfnPostClockSpeedChange(psPowerDevice->hDevCookie, bIdleDevice, psPowerDevice->eCurrentPowerState); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePostClockSpeedChange : Device %u failed, error:0x%x", ui32DeviceIndex, eError)); } } /* This mutex was acquired in PVRSRVDevicePreClockSpeedChange. */ PVRSRVPowerUnlock(); }
IMG_EXPORT PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID, IMG_BOOL bSystemPowerEvent) { PVRSRV_ERROR eError; SYS_DATA *psSysData; IMG_UINT32 ui32Timeout = 1000000; #if defined(SUPPORT_LMA) ui32Timeout *= 60; #endif SysAcquireData(&psSysData); #if defined(SYS_CUSTOM_POWERLOCK_WRAP) eError = SysPowerLockWrap(psSysData); if (eError != PVRSRV_OK) { return eError; } #endif do { eError = OSLockResource(&psSysData->sPowerStateChangeResource, ui32CallerID); if (eError == PVRSRV_OK) { break; } else if (ui32CallerID == ISR_ID) { eError = PVRSRV_ERROR_RETRY; break; } OSWaitus(1); ui32Timeout--; } while (ui32Timeout > 0); #if defined(SYS_CUSTOM_POWERLOCK_WRAP) if (eError != PVRSRV_OK) { SysPowerLockUnwrap(psSysData); } #endif if ((eError == PVRSRV_OK) && !bSystemPowerEvent && !_IsSystemStatePowered(psSysData->eCurrentPowerState)) { PVRSRVPowerUnlock(ui32CallerID); eError = PVRSRV_ERROR_RETRY; } return eError; }
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; }
PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex, IMG_BOOL bIdleDevice, IMG_VOID *pvInfo) { PVRSRV_ERROR eError = PVRSRV_OK; SYS_DATA *psSysData; PVRSRV_POWER_DEV *psPowerDevice; PVR_UNREFERENCED_PARAMETER(pvInfo); SysAcquireData(&psSysData); if (bIdleDevice) { eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePreClockSpeedChange : failed to acquire lock, error:0x%lx", eError)); return eError; } } psPowerDevice = (PVRSRV_POWER_DEV*) List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList, MatchPowerDeviceIndex_AnyVaCb, ui32DeviceIndex); if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange) { eError = psPowerDevice->pfnPreClockSpeedChange(psPowerDevice->hDevCookie, bIdleDevice, psPowerDevice->eCurrentPowerState); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePreClockSpeedChange : Device %lu failed, error:0x%lx", ui32DeviceIndex, eError)); } } if (bIdleDevice && eError != PVRSRV_OK) { PVRSRVPowerUnlock(KERNEL_ID); } return eError; }
enum PVRSRV_ERROR PVRSRVSystemPrePowerStateKM( enum PVR_POWER_STATE eNewPowerState) { enum PVRSRV_ERROR eError; struct SYS_DATA *psSysData; enum PVR_POWER_STATE eNewDevicePowerState; eError = SysAcquireData(&psSysData); if (eError != PVRSRV_OK) return eError; eError = PVRSRVPowerLock(KERNEL_ID, IMG_TRUE); if (eError != PVRSRV_OK) return eError; if (_IsSystemStatePowered(eNewPowerState) != _IsSystemStatePowered(psSysData->eCurrentPowerState)) { if (_IsSystemStatePowered(eNewPowerState)) eNewDevicePowerState = PVRSRV_POWER_Unspecified; else eNewDevicePowerState = PVRSRV_POWER_STATE_D3; eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState); if (eError != PVRSRV_OK) goto ErrorExit; } if (eNewPowerState != psSysData->eCurrentPowerState) { eError = SysSystemPrePowerState(eNewPowerState); if (eError != PVRSRV_OK) goto ErrorExit; } return eError; ErrorExit: PVR_DPF(PVR_DBG_ERROR, "PVRSRVSystemPrePowerStateKM: " "Transition from %d to %d FAILED 0x%x", psSysData->eCurrentPowerState, eNewPowerState, eError); psSysData->eFailedPowerState = eNewPowerState; PVRSRVPowerUnlock(KERNEL_ID); return eError; }
enum PVRSRV_ERROR PVRSRVSystemPostPowerStateKM( enum PVR_POWER_STATE eNewPowerState) { enum PVRSRV_ERROR eError; struct SYS_DATA *psSysData; enum PVR_POWER_STATE eNewDevicePowerState; eError = SysAcquireData(&psSysData); if (eError != PVRSRV_OK) goto Exit; if (eNewPowerState != psSysData->eCurrentPowerState) { eError = SysSystemPostPowerState(eNewPowerState); if (eError != PVRSRV_OK) goto Exit; } if (_IsSystemStatePowered(eNewPowerState) != _IsSystemStatePowered(psSysData->eCurrentPowerState)) { if (_IsSystemStatePowered(eNewPowerState)) eNewDevicePowerState = PVRSRV_POWER_Unspecified; else eNewDevicePowerState = PVRSRV_POWER_STATE_D3; eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState); if (eError != PVRSRV_OK) goto Exit; } PVR_DPF(PVR_DBG_WARNING, "PVRSRVSystemPostPowerStateKM: " "System Power Transition from %d to %d OK", psSysData->eCurrentPowerState, eNewPowerState); psSysData->eCurrentPowerState = eNewPowerState; Exit: PVRSRVPowerUnlock(KERNEL_ID); if (_IsSystemStatePowered(eNewPowerState) && PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL)) PVRSRVCommandCompleteCallbacks(); return eError; }
enum PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(u32 ui32DeviceIndex, IMG_BOOL bIdleDevice, void *pvInfo) { enum PVRSRV_ERROR eError = PVRSRV_OK; struct SYS_DATA *psSysData; struct PVRSRV_POWER_DEV *psPowerDevice; PVR_UNREFERENCED_PARAMETER(pvInfo); eError = SysAcquireData(&psSysData); if (eError != PVRSRV_OK) return eError; psPowerDevice = psSysData->psPowerDeviceList; while (psPowerDevice) { if (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex) if (psPowerDevice->pfnPreClockSpeedChange) { eError = psPowerDevice-> pfnPreClockSpeedChange(psPowerDevice-> hDevCookie, bIdleDevice, psPowerDevice-> eCurrentPowerState); if (eError != PVRSRV_OK) { pr_err ("pfnPreClockSpeedChange failed\n"); PVR_DPF(PVR_DBG_ERROR, "PVRSRVDevicePreClockSpeedChange : " "Device %lu failed, error:0x%lx", ui32DeviceIndex, eError); break; } } psPowerDevice = psPowerDevice->psNext; } if (bIdleDevice && eError != PVRSRV_OK) PVRSRVPowerUnlock(KERNEL_ID); return eError; }
static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode) { PVRSRV_ERROR eError; eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVPowerLock call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex)); return eError; } eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_DEFAULT); PVRSRVPowerUnlock(KERNEL_ID); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex)); } 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 /** * 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)); } }
/*! ****************************************************************************** @Function PVRSRVSetPowerStateKM @Description Set the system into a new state @Input eNewPowerState : @Input bForced : TRUE if the transition should not fail (e.g. OS request) @Return PVRSRV_ERROR ******************************************************************************/ IMG_EXPORT PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState, IMG_BOOL bForced) { PVRSRV_ERROR eError; PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); IMG_UINT uiStage = 0; PVRSRV_DEV_POWER_STATE eNewDevicePowerState = _IsSystemStatePowered(eNewSysPowerState)? PVRSRV_DEV_POWER_STATE_DEFAULT : PVRSRV_DEV_POWER_STATE_OFF; /* require a proper power state */ if (eNewSysPowerState == PVRSRV_SYS_POWER_STATE_Unspecified) { return PVRSRV_ERROR_INVALID_PARAMS; } /* no power transition requested, so do nothing */ if (eNewSysPowerState == psPVRSRVData->eCurrentPowerState) { return PVRSRV_OK; } /* Prevent simultaneous SetPowerStateKM calls */ PVRSRVForcedPowerLock(); /* Perform pre transitions: first device and then sys layer */ eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState, bForced); if (eError != PVRSRV_OK) { uiStage++; goto ErrorExit; } eError = PVRSRVSysPrePowerState(eNewSysPowerState, bForced); if (eError != PVRSRV_OK) { uiStage++; goto ErrorExit; } /* Perform system-specific post power transitions: first sys layer and then device */ eError = PVRSRVSysPostPowerState(eNewSysPowerState, bForced); if (eError != PVRSRV_OK) { uiStage++; goto ErrorExit; } eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState, bForced); if (eError != PVRSRV_OK) { uiStage++; goto ErrorExit; } psPVRSRVData->eCurrentPowerState = eNewSysPowerState; psPVRSRVData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified; PVRSRVPowerUnlock(); /* Reprocess the devices' queues in case commands were blocked during the power transition. */ if (_IsSystemStatePowered(eNewSysPowerState) && PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL)) { PVRSRVCheckStatus(IMG_NULL); } return PVRSRV_OK; ErrorExit: /* save the power state for the re-attempt */ psPVRSRVData->eFailedPowerState = eNewSysPowerState; PVRSRVPowerUnlock(); PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetPowerStateKM: Transition from %d to %d FAILED (%s) at stage %d, forced: %d. Dumping debug info.", psPVRSRVData->eCurrentPowerState, eNewSysPowerState, PVRSRVGetErrorStringKM(eError), uiStage, bForced)); PVRSRVDebugRequest(DEBUG_REQUEST_VERBOSITY_MAX); 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; }
/*! ****************************************************************************** @Function PVRSRVDeinitialiseDevice @Description This De-inits device @Input ui32DevIndex : Index to the required device @Return PVRSRV_ERROR : ******************************************************************************/ PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex) { PVRSRV_DEVICE_NODE *psDeviceNode; SYS_DATA *psSysData; PVRSRV_ERROR eError; SysAcquireData(&psSysData); psDeviceNode = (PVRSRV_DEVICE_NODE*) List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, &MatchDeviceKM_AnyVaCb, ui32DevIndex, IMG_TRUE); if (!psDeviceNode) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: requested device %d is not present", ui32DevIndex)); return PVRSRV_ERROR_DEVICEID_NOT_FOUND; } eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVPowerLock call")); return eError; } /* Power down the device if necessary. */ eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex, PVRSRV_DEV_POWER_STATE_OFF); PVRSRVPowerUnlock(KERNEL_ID); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call")); return eError; } /* Free the dissociated device memory. */ eError = ResManFreeResByCriteria(psDeviceNode->hResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, IMG_NULL, 0); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call")); return eError; } /* De-init the device. */ if(psDeviceNode->pfnDeInitDevice != IMG_NULL) { eError = psDeviceNode->pfnDeInitDevice(psDeviceNode); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed DeInitDevice call")); return eError; } } /* Close the device's resource manager context. */ PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE); psDeviceNode->hResManContext = IMG_NULL; /* remove node from list */ List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode); /* deallocate id and memory */ (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex); OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL); /*not nulling pointer, out of scope*/ return (PVRSRV_OK); }
IMG_EXPORT PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM, IMG_HANDLE hSwapChain) { PVRSRV_ERROR eError; PVRSRV_QUEUE_INFO *psQueue; PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DC_SWAPCHAIN *psSwapChain; DISPLAYCLASS_FLIP_COMMAND *psFlipCmd; IMG_UINT32 ui32NumSrcSyncs = 1; PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2]; PVRSRV_COMMAND *psCommand; if(!hDeviceKM || !hSwapChain) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } #if defined(SUPPORT_LMA) eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE); if(eError != PVRSRV_OK) { return eError; } #endif psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); psSwapChain = (PVRSRV_DC_SWAPCHAIN*)hSwapChain; psQueue = psSwapChain->psQueue; apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo; if(psSwapChain->psLastFlipBuffer) { if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo) { apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo; ui32NumSrcSyncs++; } } eError = PVRSRVInsertCommandKM (psQueue, &psCommand, psDCInfo->ui32DeviceID, DC_FLIP_COMMAND, 0, IMG_NULL, ui32NumSrcSyncs, apsSrcSync, sizeof(DISPLAYCLASS_FLIP_COMMAND)); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue")); goto Exit; } psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData; psFlipCmd->hExtDevice = psDCInfo->hExtDevice; psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain; psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer; psFlipCmd->hPrivateTag = IMG_NULL; psFlipCmd->ui32ClipRectCount = 0; psFlipCmd->ui32SwapInterval = 1; eError = PVRSRVSubmitCommandKM (psQueue, psCommand); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to submit command")); goto Exit; } LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) { if(PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) != PVRSRV_ERROR_PROCESSING_BLOCKED) { goto ProcessedQueues; } OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT); } END_LOOP_UNTIL_TIMEOUT(); PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to process queues")); eError = PVRSRV_ERROR_GENERIC; goto Exit; ProcessedQueues: psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer; eError = PVRSRV_OK; Exit: #if defined(SUPPORT_LMA) PVRSRVPowerUnlock(KERNEL_ID); #endif return eError; }
IMG_EXPORT PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState) { PVRSRV_ERROR eError = PVRSRV_OK; SYS_DATA *psSysData; PVRSRV_DEV_POWER_STATE eNewDevicePowerState; SysAcquireData(&psSysData); if (eNewSysPowerState != psSysData->eCurrentPowerState) { eError = SysSystemPostPowerState(eNewSysPowerState); if (eError != PVRSRV_OK) { goto Exit; } } if (_IsSystemStatePowered(eNewSysPowerState) != _IsSystemStatePowered(psSysData->eCurrentPowerState)) { if (_IsSystemStatePowered(eNewSysPowerState)) { eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT; } else { eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF; } eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState); if (eError != PVRSRV_OK) { goto Exit; } } PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSystemPostPowerStateKM: System Power Transition from %d to %d OK", psSysData->eCurrentPowerState, eNewSysPowerState)); psSysData->eCurrentPowerState = eNewSysPowerState; Exit: PVRSRVPowerUnlock(KERNEL_ID); if (_IsSystemStatePowered(eNewSysPowerState) && PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL)) { PVRSRVCommandCompleteCallbacks(); } return eError; }
IMG_EXPORT PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState) { PVRSRV_ERROR eError; SYS_DATA *psSysData; PVRSRV_DEV_POWER_STATE eNewDevicePowerState; SysAcquireData(&psSysData); eError = PVRSRVPowerLock(KERNEL_ID, IMG_TRUE); if(eError != PVRSRV_OK) { return eError; } if (_IsSystemStatePowered(eNewSysPowerState) != _IsSystemStatePowered(psSysData->eCurrentPowerState)) { if (_IsSystemStatePowered(eNewSysPowerState)) { eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT; } else { eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF; } eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState); if (eError != PVRSRV_OK) { goto ErrorExit; } } if (eNewSysPowerState != psSysData->eCurrentPowerState) { eError = SysSystemPrePowerState(eNewSysPowerState); if (eError != PVRSRV_OK) { goto ErrorExit; } } return eError; ErrorExit: PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemPrePowerStateKM: Transition from %d to %d FAILED 0x%x", psSysData->eCurrentPowerState, eNewSysPowerState, eError)); psSysData->eFailedPowerState = eNewSysPowerState; PVRSRVPowerUnlock(KERNEL_ID); return 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; }