/*! ****************************************************************************** @Function PVRSRVPowerUnlock @Description Release the mutex for power transitions @Return PVRSRV_ERROR ******************************************************************************/ IMG_EXPORT IMG_VOID PVRSRVPowerUnlock() { PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); OSLockRelease(psPVRSRVData->hPowerLock); }
/*! ****************************************************************************** @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(); }
PVRSRV_ERROR CacheOpQueue(PVRSRV_CACHE_OP uiCacheOp) { PVRSRV_DATA *psData = PVRSRVGetPVRSRVData(); psData->uiCacheOp = SetCacheOp(psData->uiCacheOp, uiCacheOp); return PVRSRV_OK; }
/*! ****************************************************************************** @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; }
/* PVRSRVConnectionConnect*/ PVRSRV_ERROR PVRSRVConnectionConnect(IMG_PVOID *ppvPrivData, IMG_PVOID pvOSData) { PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); CONNECTION_DATA *psConnection; PVRSRV_ERROR eError = PVRSRV_OK; /* Allocate per-process data area */ psConnection = OSAllocMem(sizeof(*psConnection)); if (psConnection == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: Couldn't allocate per-process data (%d)", eError)); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psConnection, 0, sizeof(*psConnection)); /* Call environment specific per process init function */ eError = OSConnectionPrivateDataInit(&psConnection->hOsPrivateData, pvOSData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: OSConnectionPrivateDataInit failed (%d)", eError)); goto failure; } /* Allocate handle base for this process */ eError = PVRSRVAllocHandleBase(&psConnection->psHandleBase); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: Couldn't allocate handle base for process (%d)", eError)); goto failure; } /* Create a resource manager context for the process */ eError = PVRSRVResManConnect(psPVRSRVData->hResManDeferContext, &psConnection->hResManContext); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: Couldn't register with the resource manager")); goto failure; } *ppvPrivData = psConnection; return eError; failure: (IMG_VOID)FreeConnectionData(psConnection); return eError; }
/*! ****************************************************************************** @Function PVRSRVIsDevicePowered @Description Whether the device is powered, for the purposes of lockup detection. @Input ui32DeviceIndex : device index @Return IMG_BOOL ******************************************************************************/ IMG_EXPORT IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex) { PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); PVRSRV_DEV_POWER_STATE ePowerState; if (OSLockIsLocked(psPVRSRVData->hPowerLock)) { return IMG_FALSE; } if (PVRSRVGetDevicePowerState(ui32DeviceIndex, &ePowerState) != PVRSRV_OK) { return IMG_FALSE; } return (ePowerState == PVRSRV_DEV_POWER_STATE_ON); }
PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex, PFN_PRE_POWER pfnDevicePrePower, PFN_POST_POWER pfnDevicePostPower, PFN_SYS_DEV_PRE_POWER pfnSystemPrePower, PFN_SYS_DEV_POST_POWER pfnSystemPostPower, PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange, PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange, IMG_HANDLE hDevCookie, PVRSRV_DEV_POWER_STATE eCurrentPowerState, PVRSRV_DEV_POWER_STATE eDefaultPowerState) { PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); PVRSRV_POWER_DEV *psPowerDevice; if (pfnDevicePrePower == IMG_NULL && pfnDevicePostPower == IMG_NULL) { return PVRSRVRemovePowerDevice(ui32DeviceIndex); } psPowerDevice = OSAllocMem(sizeof(PVRSRV_POWER_DEV)); if (psPowerDevice == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterPowerDevice: Failed to alloc PVRSRV_POWER_DEV")); return PVRSRV_ERROR_OUT_OF_MEMORY; } /* setup device for power manager */ psPowerDevice->pfnDevicePrePower = pfnDevicePrePower; psPowerDevice->pfnDevicePostPower = pfnDevicePostPower; psPowerDevice->pfnSystemPrePower = pfnSystemPrePower; psPowerDevice->pfnSystemPostPower = pfnSystemPostPower; psPowerDevice->pfnPreClockSpeedChange = pfnPreClockSpeedChange; psPowerDevice->pfnPostClockSpeedChange = pfnPostClockSpeedChange; psPowerDevice->hDevCookie = hDevCookie; psPowerDevice->ui32DeviceIndex = ui32DeviceIndex; psPowerDevice->eCurrentPowerState = eCurrentPowerState; psPowerDevice->eDefaultPowerState = eDefaultPowerState; /* insert into power device list */ List_PVRSRV_POWER_DEV_Insert(&(psPVRSRVData->psPowerDeviceList), psPowerDevice); return (PVRSRV_OK); }
/*! ****************************************************************************** @Function PVRSRVGetDevicePowerState @Description Return the device power state @Input ui32DeviceIndex : device index @Output psPowerState : Current power state @Return PVRSRV_ERROR_UNKNOWN_POWER_STATE if device could not be found. PVRSRV_OK otherwise. ******************************************************************************/ IMG_EXPORT PVRSRV_ERROR PVRSRVGetDevicePowerState(IMG_UINT32 ui32DeviceIndex, PPVRSRV_DEV_POWER_STATE pePowerState) { PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); PVRSRV_POWER_DEV *psPowerDevice; psPowerDevice = (PVRSRV_POWER_DEV*) List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList, &MatchPowerDeviceIndex_AnyVaCb, ui32DeviceIndex); if (psPowerDevice == IMG_NULL) { return PVRSRV_ERROR_UNKNOWN_POWER_STATE; } *pePowerState = psPowerDevice->eCurrentPowerState; return PVRSRV_OK; }
/*! ****************************************************************************** @Function PVRSRVDevicePostPowerStateKM @Description Perform device-specific processing required after a power transition @Input bAllDevices : IMG_TRUE - All devices IMG_FALSE - Use ui32DeviceIndex @Input ui32DeviceIndex : device index @Input eNewPowerState : New power state @Return PVRSRV_ERROR ******************************************************************************/ static PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices, IMG_UINT32 ui32DeviceIndex, PVRSRV_DEV_POWER_STATE eNewPowerState, IMG_BOOL bForced) { PVRSRV_ERROR eError; PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); /* Loop through the power devices. */ eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psPVRSRVData->psPowerDeviceList, &PVRSRVDevicePostPowerStateKM_AnyVaCb, bAllDevices, ui32DeviceIndex, eNewPowerState, bForced); return eError; }
/*! ****************************************************************************** @Function PVRSRVPowerLock @Description Obtain the mutex for power transitions. Only allowed when system power is on. @Return PVRSRV_ERROR_RETRY or PVRSRV_OK ******************************************************************************/ IMG_EXPORT PVRSRV_ERROR PVRSRVPowerLock() { PVRSRV_ERROR eError; PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); /* Only allow to take powerlock when the system power is on */ if (_IsSystemStatePowered(psPVRSRVData->eCurrentPowerState)) { OSLockAcquire(psPVRSRVData->hPowerLock); eError = PVRSRV_OK; } else { eError = PVRSRV_ERROR_RETRY; } return eError; }
/*! ****************************************************************************** @Function PVRSRVRemovePowerDevice @Description Removes device from power management register. Device is located by Device Index @Input ui32DeviceIndex : device index @Return PVRSRV_ERROR ******************************************************************************/ PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex) { PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); PVRSRV_POWER_DEV *psPowerDev; /* find device in list and remove it */ psPowerDev = (PVRSRV_POWER_DEV*) List_PVRSRV_POWER_DEV_Any_va(psPVRSRVData->psPowerDeviceList, &MatchPowerDeviceIndex_AnyVaCb, ui32DeviceIndex); if (psPowerDev) { List_PVRSRV_POWER_DEV_Remove(psPowerDev); OSFreeMem(psPowerDev); /*not nulling pointer, copy on stack*/ } return (PVRSRV_OK); }
/*! ****************************************************************************** @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; }
/*! ****************************************************************************** @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; }
/*! ****************************************************************************** @Function PVRSRVForcedPowerLock @Description Obtain the mutex for power transitions regardless of system power state @Return PVRSRV_ERROR_RETRY or PVRSRV_OK ******************************************************************************/ IMG_EXPORT IMG_VOID PVRSRVForcedPowerLock() { PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); OSLockAcquire(psPVRSRVData->hPowerLock); }
static int PVRSRVDRMLoad(struct drm_device *dev, unsigned long flags) { struct pvr_drm_dev_priv *psDevPriv; int iRes = 0; #if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING) PVRSRV_ERROR eError; #endif PVR_TRACE(("PVRSRVDRMLoad")); #if defined(LDM_PLATFORM) /* The equivalent is done for PCI modesetting drivers by drm_get_pci_dev() */ platform_set_drvdata(dev->platformdev, dev); #endif psDevPriv = kzalloc(sizeof *psDevPriv, GFP_KERNEL); if (psDevPriv == NULL) { PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate DRM device private data", __FUNCTION__)); iRes = -ENOMEM; goto error_exit; } dev->dev_private = psDevPriv; /* Module initialisation */ iRes = PVRSRVSystemInit(dev); if (iRes != 0) { PVR_DPF((PVR_DBG_ERROR, "%s: System initialisation failed (error = %d)", __FUNCTION__, iRes)); goto error_free_dev_priv; } psDevPriv->dev_node = List_PVRSRV_DEVICE_NODE_Any(PVRSRVGetPVRSRVData()->psDeviceNodeList, PVRSRVFindRGXDevNode); if (psDevPriv->dev_node == NULL) { PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get Rogue device node", __FUNCTION__)); iRes = -ENODEV; goto error_system_deinit; } #if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING) /* Acquire the system data so it can be used by our interrupt handler */ eError = SysAcquireSystemData(psDevPriv->dev_node->psDevConfig->hSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire system data", __FUNCTION__)); iRes = -EINVAL; goto error_system_deinit; } psDevPriv->hSysData = psDevPriv->dev_node->psDevConfig->hSysData; if (psDevPriv->dev_node->psDevConfig->bIRQIsShared) { dev->driver->driver_features |= DRIVER_IRQ_SHARED; } iRes = drm_irq_install(dev); if (iRes != 0) { PVR_DPF((PVR_DBG_ERROR, "%s: Failed to install interrupt handler (error = %d)", __FUNCTION__, iRes)); goto error_system_data_release; } #endif #if defined(SUPPORT_DRM_DC_MODULE) iRes = PVRSRVDRMDisplayInit(dev); if (iRes != 0) { #if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING) goto error_irq_uninstall; #else goto error_system_deinit; #endif } #else drm_mode_config_init(dev); #endif /* defined(SUPPORT_DRM_DC_MODULE) */ goto exit; #if defined(SUPPORT_SYSTEM_INTERRUPT_HANDLING) #if defined(SUPPORT_DRM_DC_MODULE) error_irq_uninstall: drm_irq_uninstall(dev); #endif error_system_data_release: SysReleaseSystemData(psDevPriv->hSysData); #endif error_system_deinit: PVRSRVSystemDeInit(); error_free_dev_priv: dev->dev_private = NULL; kfree(psDevPriv); error_exit: wake_up_interruptible(&sWaitForInit); bInitFailed = IMG_TRUE; exit: bInitComplete = IMG_TRUE; return iRes; }