static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE hDevice, IMG_HANDLE hSwapChain, IMG_UINT32 *pui32BufferCount, IMG_HANDLE *phBuffer) { MTKLFB_DEVINFO *psDevInfo; MTKLFB_SWAPCHAIN *psSwapChain; PVRSRV_ERROR eError; unsigned i; if(!hDevice || !hSwapChain || !pui32BufferCount || !phBuffer) { xlog_printk(ANDROID_LOG_ERROR, DRIVER_PREFIX, "%s: invalid params\n", __FUNCTION__); return PVRSRV_ERROR_INVALID_PARAMS; } psDevInfo = (MTKLFB_DEVINFO*)hDevice; psSwapChain = (MTKLFB_SWAPCHAIN*)hSwapChain; MTKLFBCreateSwapChainLock(psDevInfo); if (SwapChainHasChanged(psDevInfo, psSwapChain)) { xlog_printk(ANDROID_LOG_ERROR, DRIVER_PREFIX, "%s: Device %u: Swap chain mismatch\n", __FUNCTION__, psDevInfo->uiFBDevID); eError = PVRSRV_ERROR_INVALID_PARAMS; goto Exit; } *pui32BufferCount = (IMG_UINT32)psSwapChain->ulBufferCount; for(i=0; i<psSwapChain->ulBufferCount; i++) { phBuffer[i] = (IMG_HANDLE)&psSwapChain->psBuffer[i]; } eError = PVRSRV_OK; Exit: MTKLFBCreateSwapChainUnLock(psDevInfo); return eError; }
static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice, IMG_HANDLE hSwapChain) { MTKLFB_DEVINFO *psDevInfo; MTKLFB_SWAPCHAIN *psSwapChain; MTKLFB_ERROR eError; if(!hDevice || !hSwapChain) { return PVRSRV_ERROR_INVALID_PARAMS; } psDevInfo = (MTKLFB_DEVINFO*)hDevice; psSwapChain = (MTKLFB_SWAPCHAIN*)hSwapChain; MTKLFBCreateSwapChainLock(psDevInfo); if (SwapChainHasChanged(psDevInfo, psSwapChain)) { printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Swap chain mismatch\n", __FUNCTION__, psDevInfo->uiFBDevID); eError = PVRSRV_ERROR_INVALID_PARAMS; goto ExitUnLock; } MTKLFBDestroySwapQueue(psSwapChain); eError = MTKLFBDisableLFBEventNotification(psDevInfo); if (eError != MTKLFB_OK) { printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't disable framebuffer event notification\n", __FUNCTION__, psDevInfo->uiFBDevID); } MTKLFBFreeKernelMem(psSwapChain->psBuffer); MTKLFBFreeKernelMem(psSwapChain); psDevInfo->psSwapChain = NULL; MTKLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer); (void) MTKLFBCheckModeAndSync(psDevInfo); eError = PVRSRV_OK; ExitUnLock: MTKLFBCreateSwapChainUnLock(psDevInfo); return eError; }
static IMG_BOOL ProcessFlip(IMG_HANDLE hCmdCookie, IMG_UINT32 ui32DataSize, IMG_VOID *pvData) { DISPLAYCLASS_FLIP_COMMAND *psFlipCmd; MTKLFB_DEVINFO *psDevInfo; MTKLFB_BUFFER *psBuffer; MTKLFB_SWAPCHAIN *psSwapChain; if(!hCmdCookie || !pvData) { xlog_printk(ANDROID_LOG_ERROR, DRIVER_PREFIX, "hCmdCookie(%p) or pvData(%p) is NULL\n", hCmdCookie, pvData); return IMG_FALSE; } psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)pvData; if (psFlipCmd == IMG_NULL) { xlog_printk(ANDROID_LOG_ERROR, DRIVER_PREFIX, "psFlipCmd is NULL\n"); return IMG_FALSE; } psDevInfo = (MTKLFB_DEVINFO*)psFlipCmd->hExtDevice; psBuffer = (MTKLFB_BUFFER*)psFlipCmd->hExtBuffer; psSwapChain = (MTKLFB_SWAPCHAIN*) psFlipCmd->hExtSwapChain; MTKLFBCreateSwapChainLock(psDevInfo); if (SwapChainHasChanged(psDevInfo, psSwapChain)) { DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u (PVR Device ID %u): The swap chain has been destroyed\n", __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID)); } else { psBuffer->hCmdComplete = (MTKLFB_HANDLE)hCmdCookie; psBuffer->ulSwapInterval = (unsigned long)psFlipCmd->ui32SwapInterval; MTKLFBQueueBufferForSwap(psSwapChain, psBuffer); } MTKLFBCreateSwapChainUnLock(psDevInfo); return IMG_TRUE; }
static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice, IMG_UINT32 ui32Flags, DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib, DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib, IMG_UINT32 ui32BufferCount, PVRSRV_SYNC_DATA **ppsSyncData, IMG_UINT32 ui32OEMFlags, IMG_HANDLE *phSwapChain, IMG_UINT32 *pui32SwapChainID) { MTKLFB_DEVINFO *psDevInfo; MTKLFB_SWAPCHAIN *psSwapChain; MTKLFB_BUFFER *psBuffer; IMG_UINT32 i; PVRSRV_ERROR eError; IMG_UINT32 ui32BuffersToSkip; UNREFERENCED_PARAMETER(ui32OEMFlags); if(!hDevice || !psDstSurfAttrib || !psSrcSurfAttrib || !ppsSyncData || !phSwapChain) { return PVRSRV_ERROR_INVALID_PARAMS; } psDevInfo = (MTKLFB_DEVINFO*)hDevice; if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0) { return PVRSRV_ERROR_NOT_SUPPORTED; } MTKLFBCreateSwapChainLock(psDevInfo); if(psDevInfo->psSwapChain != NULL) { eError = PVRSRV_ERROR_FLIP_CHAIN_EXISTS; goto ExitUnLock; } if(ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers) { eError = PVRSRV_ERROR_TOOMANYBUFFERS; goto ExitUnLock; } if ((psDevInfo->sFBInfo.ulRoundedBufferSize * (unsigned long)ui32BufferCount) > psDevInfo->sFBInfo.ulFBSize) { eError = PVRSRV_ERROR_TOOMANYBUFFERS; goto ExitUnLock; } ui32BuffersToSkip = psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers - ui32BufferCount; if(psDstSurfAttrib->pixelformat != psDevInfo->sDisplayFormat.pixelformat || psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sDisplayDim.ui32ByteStride || psDstSurfAttrib->sDims.ui32Width != psDevInfo->sDisplayDim.ui32Width || psDstSurfAttrib->sDims.ui32Height != psDevInfo->sDisplayDim.ui32Height) { eError = PVRSRV_ERROR_INVALID_PARAMS; goto ExitUnLock; } if(psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat || psDstSurfAttrib->sDims.ui32ByteStride != psSrcSurfAttrib->sDims.ui32ByteStride || psDstSurfAttrib->sDims.ui32Width != psSrcSurfAttrib->sDims.ui32Width || psDstSurfAttrib->sDims.ui32Height != psSrcSurfAttrib->sDims.ui32Height) { eError = PVRSRV_ERROR_INVALID_PARAMS; goto ExitUnLock; } UNREFERENCED_PARAMETER(ui32Flags); #if defined(PVR_MTKFB3_UPDATE_MODE) if (!MTKLFBSetUpdateMode(psDevInfo, PVR_MTKFB3_UPDATE_MODE)) { xlog_printk(ANDROID_LOG_WARN, DRIVER_PREFIX, DRIVER_PREFIX ": %s: Device %u: Couldn't set frame buffer update mode %d\n", __FUNCTION__, psDevInfo->uiFBDevID, PVR_MTKFB3_UPDATE_MODE); } #endif psSwapChain = (MTKLFB_SWAPCHAIN*)MTKLFBAllocKernelMem(sizeof(MTKLFB_SWAPCHAIN)); if(!psSwapChain) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ExitUnLock; } psBuffer = (MTKLFB_BUFFER*)MTKLFBAllocKernelMem(sizeof(MTKLFB_BUFFER) * ui32BufferCount); if(!psBuffer) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorFreeSwapChain; } psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount; psSwapChain->psBuffer = psBuffer; psSwapChain->bNotVSynced = MTKLFB_TRUE; psSwapChain->uiFBDevID = psDevInfo->uiFBDevID; for(i=0; i<ui32BufferCount-1; i++) { psBuffer[i].psNext = &psBuffer[i+1]; } psBuffer[i].psNext = &psBuffer[0]; for (i = 0; i < ui32BufferCount; i++) { IMG_UINT32 ui32SwapBuffer = i + ui32BuffersToSkip; IMG_UINT32 ui32BufferOffset = ui32SwapBuffer * (IMG_UINT32)psDevInfo->sFBInfo.ulRoundedBufferSize; psBuffer[i].psSyncData = ppsSyncData[i]; psBuffer[i].sSysAddr.uiAddr = psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset; psBuffer[i].sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr + ui32BufferOffset; psBuffer[i].ulYOffset = ui32BufferOffset / psDevInfo->sFBInfo.ulByteStride; psBuffer[i].psDevInfo = psDevInfo; MTKLFBInitBufferForSwap(&psBuffer[i]); } if (MTKLFBCreateSwapQueue(psSwapChain) != MTKLFB_OK) { xlog_printk(ANDROID_LOG_WARN, DRIVER_PREFIX, DRIVER_PREFIX ": %s: Device %u: Failed to create workqueue\n", __FUNCTION__, psDevInfo->uiFBDevID); eError = PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR; goto ErrorFreeBuffers; } if (MTKLFBEnableLFBEventNotification(psDevInfo)!= MTKLFB_OK) { eError = PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT; xlog_printk(ANDROID_LOG_WARN, DRIVER_PREFIX, DRIVER_PREFIX ": %s: Device %u: Couldn't enable framebuffer event notification\n", __FUNCTION__, psDevInfo->uiFBDevID); goto ErrorDestroySwapQueue; } psDevInfo->uiSwapChainID++; if (psDevInfo->uiSwapChainID == 0) { psDevInfo->uiSwapChainID++; } psSwapChain->uiSwapChainID = psDevInfo->uiSwapChainID; psDevInfo->psSwapChain = psSwapChain; *pui32SwapChainID = psDevInfo->uiSwapChainID; *phSwapChain = (IMG_HANDLE)psSwapChain; eError = PVRSRV_OK; goto ExitUnLock; ErrorDestroySwapQueue: MTKLFBDestroySwapQueue(psSwapChain); ErrorFreeBuffers: MTKLFBFreeKernelMem(psBuffer); ErrorFreeSwapChain: MTKLFBFreeKernelMem(psSwapChain); ExitUnLock: MTKLFBCreateSwapChainUnLock(psDevInfo); return eError; }
int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(struct drm_device unref__ *dev, void *arg, struct drm_file unref__ *pFile) { uint32_t *puiArgs; uint32_t uiCmd; unsigned uiPVRDevID; int ret = 0; MTKLFB_DEVINFO *psDevInfo; if (arg == NULL) { return -EFAULT; } puiArgs = (uint32_t *)arg; uiCmd = puiArgs[PVR_DRM_DISP_ARG_CMD]; uiPVRDevID = puiArgs[PVR_DRM_DISP_ARG_DEV]; psDevInfo = MTKLFBPVRDevIDToDevInfo(uiPVRDevID); if (psDevInfo == NULL) { return -EINVAL; } switch (uiCmd) { case PVR_DRM_DISP_CMD_LEAVE_VT: case PVR_DRM_DISP_CMD_ENTER_VT: { MTKLFB_BOOL bLeaveVT = (uiCmd == PVR_DRM_DISP_CMD_LEAVE_VT); DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: PVR Device %u: %s\n", __FUNCTION__, uiPVRDevID, bLeaveVT ? "Leave VT" : "Enter VT")); MTKLFBCreateSwapChainLock(psDevInfo); MTKLFBAtomicBoolSet(&psDevInfo->sLeaveVT, bLeaveVT); if (psDevInfo->psSwapChain != NULL) { flush_workqueue(psDevInfo->psSwapChain->psWorkQueue); if (bLeaveVT) { MTKLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer); (void) MTKLFBCheckModeAndSync(psDevInfo); } } MTKLFBCreateSwapChainUnLock(psDevInfo); (void) MTKLFBUnblankDisplay(psDevInfo); break; } case PVR_DRM_DISP_CMD_ON: case PVR_DRM_DISP_CMD_STANDBY: case PVR_DRM_DISP_CMD_SUSPEND: case PVR_DRM_DISP_CMD_OFF: { int iFBMode; #if defined(DEBUG) { const char *pszMode; switch(uiCmd) { case PVR_DRM_DISP_CMD_ON: pszMode = "On"; break; case PVR_DRM_DISP_CMD_STANDBY: pszMode = "Standby"; break; case PVR_DRM_DISP_CMD_SUSPEND: pszMode = "Suspend"; break; case PVR_DRM_DISP_CMD_OFF: pszMode = "Off"; break; default: pszMode = "(Unknown Mode)"; break; } printk (KERN_WARNING DRIVER_PREFIX ": %s: PVR Device %u: Display %s\n", __FUNCTION__, uiPVRDevID, pszMode); } #endif switch(uiCmd) { case PVR_DRM_DISP_CMD_ON: iFBMode = FB_BLANK_UNBLANK; break; case PVR_DRM_DISP_CMD_STANDBY: iFBMode = FB_BLANK_HSYNC_SUSPEND; break; case PVR_DRM_DISP_CMD_SUSPEND: iFBMode = FB_BLANK_VSYNC_SUSPEND; break; case PVR_DRM_DISP_CMD_OFF: iFBMode = FB_BLANK_POWERDOWN; break; default: return -EINVAL; } MTKLFBCreateSwapChainLock(psDevInfo); if (psDevInfo->psSwapChain != NULL) { flush_workqueue(psDevInfo->psSwapChain->psWorkQueue); } acquire_console_sem(); ret = fb_blank(psDevInfo->psLINFBInfo, iFBMode); release_console_sem(); MTKLFBCreateSwapChainUnLock(psDevInfo); break; } default: { ret = -EINVAL; break; } } return ret; }