/*! ****************************************************************************** @Function POOL_PoolCreate ******************************************************************************/ IMG_RESULT POOL_PoolCreate( IMG_HANDLE * phPoolHandle ) { POOL_sResPool * psResPool; IMG_UINT32 ui32Result; IMG_ASSERT(gInitialised); /* Allocate a pool structure...*/ psResPool = IMG_MALLOC(sizeof(*psResPool)); IMG_ASSERT(psResPool != IMG_NULL); if (psResPool == IMG_NULL) { return IMG_ERROR_OUT_OF_MEMORY; } IMG_MEMSET(psResPool, 0, sizeof(*psResPool)); /* Initialise the pool info...*/ LST_init(&psResPool->sFreeResList); LST_init(&psResPool->sActResList); /* Create mutex...*/ ui32Result = SYSOSKM_CreateMutex(&psResPool->hMutexHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_create_mutex; } /* Create context for the Id generator...*/ ui32Result = IDGEN_CreateContext(POOL_IDGEN_MAX_ID, POOL_IDGEN_BLOCK_SIZE,IMG_FALSE, &psResPool->hIdGenHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_create_context; } /* Disable interrupts. */ SYSOSKM_DisableInt(); /* Add to list of pools...*/ LST_add(&gsPoolList, psResPool); /* Enable interrupts. */ SYSOSKM_EnableInt(); /* Return handle to pool...*/ *phPoolHandle = psResPool; return IMG_SUCCESS; /* Error handling. */ error_create_context: SYSOSKM_DestroyMutex(psResPool->hMutexHandle); error_create_mutex: IMG_FREE(psResPool); return ui32Result; }
/*! ****************************************************************************** @Function VDECDDUTILS_CreateStrUnit @Description this function allocate a structure for a complete data unit ******************************************************************************/ IMG_RESULT VDECDDUTILS_CreateStrUnit( VDECDD_sStrUnit ** ppsStrUnit, LST_T * sBSList ) { VDECDD_sStrUnit * psStrUnit; BSPP_sBitStrSeg * psBitStrSeg; VDEC_MALLOC(psStrUnit); IMG_ASSERT(psStrUnit != IMG_NULL); if (psStrUnit == IMG_NULL) { return IMG_ERROR_OUT_OF_MEMORY; } VDEC_BZERO(psStrUnit); if (sBSList != IMG_NULL) { // copy BS list to this list LST_init(&psStrUnit->sBitStrSegList); for ( psBitStrSeg = LST_first( sBSList); psBitStrSeg != NULL; psBitStrSeg = LST_first(sBSList) ) { psBitStrSeg = LST_removeHead(sBSList); LST_add(&psStrUnit->sBitStrSegList,psBitStrSeg); } } *ppsStrUnit = psStrUnit; return IMG_SUCCESS; }
/*! ****************************************************************************** @Function SYSDEVU_Initialise ******************************************************************************/ IMG_RESULT SYSDEVU_Initialise(IMG_VOID) { /* If not initialised...*/ if (!gSysDevInitialised) { IMG_RESULT eResult; eResult = SYSOSKM_CreateAtomic(&gsActiveOpenCnt); IMG_ASSERT(eResult == IMG_SUCCESS); if (eResult != IMG_SUCCESS) { return eResult; } LST_init(&gsDevList); eResult = SYSOSKM_CreateMutex(&hNextDeviceIdMutex); IMG_ASSERT(eResult == IMG_SUCCESS); if (eResult != IMG_SUCCESS) { return eResult; } /* use a magic number to help detect dereferences of DeviceId when (wrongly) casted as a pointer */ gui32NextDeviceId = 0xbeef00; /* Now we are initialised...*/ gSysDevInitialised = IMG_TRUE; } return IMG_SUCCESS; }
/*! ****************************************************************************** @Function POOL_Initialise ******************************************************************************/ IMG_RESULT POOL_Initialise(IMG_VOID) { /* Disable interrupts. */ SYSOSKM_DisableInt(); /* If not initialised...*/ if (!gInitialised) { /* Initialise the list of pools. */ LST_init(&gsPoolList); /* Set initialised flag...*/ gInitialised = IMG_TRUE; } /* Enable interrupts. */ SYSOSKM_EnableInt(); /* Return success...*/ return IMG_SUCCESS; }
/*! ****************************************************************************** @Function VDECDDUTILS_CreateStrUnitOld @Description this function allocate a structure for a complete data unit ******************************************************************************/ IMG_RESULT VDECDDUTILS_CreateStrUnitOld( VDECDD_sStrUnit ** ppsStrUnit, BSPP_sSequHdrInfo * psSeqInfo, BSPP_sPictHdrInfo * psPicInfo, LST_T * sBSList ) { VDECDD_sStrUnit * psStrUnit; BSPP_sBitStrSeg * psBitStrSeg; VDEC_MALLOC(psStrUnit); IMG_ASSERT(psStrUnit != IMG_NULL); if (psStrUnit == IMG_NULL) { return IMG_ERROR_OUT_OF_MEMORY; } VDEC_BZERO(psStrUnit); if (sBSList != IMG_NULL) { // copy BS list to this list LST_init(&psStrUnit->sBitStrSegList); for ( psBitStrSeg = LST_first( sBSList); psBitStrSeg != NULL; psBitStrSeg = LST_first(sBSList) ) { psBitStrSeg = LST_removeHead(sBSList); LST_add(&psStrUnit->sBitStrSegList,psBitStrSeg); } } if(psSeqInfo !=IMG_NULL) { psStrUnit->psSequHdrInfo = psSeqInfo; psStrUnit->psSequHdrInfo->ui32RefCount = 1; } psStrUnit->psPictHdrInfo = psPicInfo; *ppsStrUnit = psStrUnit; return IMG_SUCCESS; }
/*! ****************************************************************************** @Function perflog_InitialiseFile @Description Initialises new file in performance logger directory. @Output pFileHandler : file to be initialised @Input pszFileName : name of created file @Input psPerfLogDir : directory where new file will be stored @Return IMG_SUCCESS in case when file has been initialised successfully, error code otherwise ******************************************************************************/ static IMG_RESULT perflog_InitialiseFile( perflog_FileHandler *pFileHandler, const IMG_CHAR *pszFileName, struct dentry *psPerfLogDir ) { if(pFileHandler == NULL || pszFileName == NULL || psPerfLogDir == NULL) { REPORT(REPORT_MODULE_PERFLOG, REPORT_ERR, "Performance logger cannot create buffer: invalid parameters"); return IMG_ERROR_INVALID_PARAMETERS; } //creates mutex that sync access to list of buffers if( SYSOSKM_CreateMutex(&pFileHandler->hMutexHandle) != IMG_SUCCESS) { REPORT(REPORT_MODULE_PERFLOG, REPORT_ERR, "Performance logger cannot create internal mutex"); return IMG_ERROR_FATAL; } //initialises list of buffers LST_init(&pFileHandler->sBufferList); //creates new file in debug file system pFileHandler->psFile = debugfs_create_file(pszFileName, 0644, psPerfLogDir, NULL, &perflog_FileOps); IMG_ASSERT(pFileHandler->psFile != IMG_NULL); if(pFileHandler->psFile == IMG_NULL) { SYSOSKM_DestroyMutex(pFileHandler->hMutexHandle); REPORT(REPORT_MODULE_PERFLOG, REPORT_ERR, "Performance logger cannot create file in debug file system"); return IMG_ERROR_FATAL; } return IMG_SUCCESS; }
/*! ****************************************************************************** @Function DMANKM_RegisterDevice ******************************************************************************/ IMG_RESULT DMANKM_RegisterDevice(IMG_CHAR * pszDeviceName, DMANKM_pfnDevRegister pfnDevRegister) { DMANKM_sDevContext * psDevContext; IMG_UINT32 ui32Result; /* If the device context list is not initialised...*/ if (!gbDevListInitialised) { /* Initialise the device context list...*/ LST_init(&gsDevList); gbDevListInitialised = IMG_TRUE; } /* Locate the device - ensure it's not registered twice...*/ ui32Result = DMANKM_LocateDevice(pszDeviceName, (IMG_HANDLE *) &psDevContext); if (ui32Result != IMG_ERROR_DEVICE_NOT_FOUND) { IMG_ASSERT(ui32Result == IMG_ERROR_DEVICE_NOT_FOUND); return IMG_ERROR_GENERIC_FAILURE; } /* Allocate a device context structure...*/ psDevContext = IMG_MALLOC(sizeof(*psDevContext)); if (psDevContext == IMG_NULL ) { IMG_ASSERT(psDevContext != IMG_NULL); return IMG_ERROR_OUT_OF_MEMORY; } IMG_MEMSET(psDevContext, 0, sizeof(*psDevContext)); /* Setup the device context...*/ psDevContext->ui32DeviceId = gui32NextDeviceID; gui32NextDeviceID++; psDevContext->pszDeviceName = IMG_STRDUP(pszDeviceName); if (psDevContext->pszDeviceName == IMG_NULL ) { IMG_ASSERT(psDevContext->pszDeviceName != IMG_NULL); ui32Result = IMG_ERROR_OUT_OF_MEMORY; goto error_dev_name; } psDevContext->pfnDevRegister = pfnDevRegister; psDevContext->ui8ApmPpmFlags = 0; ui32Result = SYSOSKM_CreateMutex(&psDevContext->hMutexHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_create_mutex; } LST_init(&psDevContext->sConnList); /* Disable interrupts...*/ SYSOSKM_DisableInt(); /* Add device to list...*/ LST_add(&gsDevList, psDevContext); /* Re-enable interrupts...*/ SYSOSKM_EnableInt(); /* If initialised...*/ if (gDmanKmInitialised) { /* Call device registration function...*/ ui32Result = psDevContext->pfnDevRegister(&psDevContext->sDevRegister); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_dev_register; } /* Set default if required...*/ if (psDevContext->sDevRegister.ui32ConnFlags == 0) { psDevContext->sDevRegister.ui32ConnFlags = DMAN_CFLAG_EXCLUSIVE; } } /* Return success...*/ return IMG_SUCCESS; /* Error handling. */ error_dev_register: SYSOSKM_DisableInt(); LST_remove(&gsDevList, psDevContext); SYSOSKM_EnableInt(); SYSOSKM_DestroyMutex(psDevContext->hMutexHandle); error_create_mutex: IMG_FREE(psDevContext->pszDeviceName); error_dev_name: IMG_FREE(psDevContext); return ui32Result; }
/*! ****************************************************************************** @Function DMANKM_OpenDevice ******************************************************************************/ IMG_RESULT DMANKM_OpenDevice(IMG_HANDLE hDevHandle, DMAN_eOpenMode eOpenMode, IMG_HANDLE * phConnHandle, IMG_UINT32 * pui32ConnId) { DMANKM_sDevContext * psDevContext = (DMANKM_sDevContext *) hDevHandle; DMANKM_sConnContext * psConnContext; DMANKM_sConnContext * psInitConnContext = IMG_NULL; IMG_UINT32 ui32Result; IMG_HANDLE hProcessId; /* Check mode. */ if ((eOpenMode != DMAN_OMODE_EXCLUSIVE) && (eOpenMode != DMAN_OMODE_SHARED)) { IMG_ASSERT(IMG_FALSE); return IMG_ERROR_INVALID_PARAMETERS; } /* Loop over the device connections to see if this process already has a connection...*/ hProcessId = SYSOSKM_GetProcessId(); psConnContext = (DMANKM_sConnContext *) LST_first(&psDevContext->sConnList); while (psConnContext != IMG_NULL ) { /* If process already has a connection. */ if (psConnContext->hProcessId == hProcessId) { /* Update the open count...*/ psConnContext->ui32OpenCnt++; /* Return the connection handle and/or id...*/ if (phConnHandle != IMG_NULL ) { *phConnHandle = psConnContext; } if (pui32ConnId != IMG_NULL ) { *pui32ConnId = psConnContext->ui32ConnId; } /* Return success...*/ return IMG_SUCCESS; } /* Look at next connection. */ psConnContext = (DMANKM_sConnContext *) LST_next(psConnContext); } /* See if we have a connection exclusive access required or only exclusive access available. */ psConnContext = (DMANKM_sConnContext *) LST_first(&psDevContext->sConnList); if ((psConnContext != IMG_NULL )&& ( (eOpenMode == DMAN_OMODE_EXCLUSIVE) || (psConnContext->psDevContext->sDevRegister.ui32ConnFlags == DMAN_CFLAG_EXCLUSIVE) ) ){ IMG_ASSERT(IMG_FALSE); return IMG_ERROR_DEVICE_UNAVAILABLE; } /* Allocate connection context...*/ psConnContext = IMG_MALLOC(sizeof(*psConnContext)); if (psConnContext == IMG_NULL ) { IMG_ASSERT(psConnContext != IMG_NULL); return IMG_ERROR_OUT_OF_MEMORY; } IMG_MEMSET(psConnContext, 0, sizeof(*psConnContext)); /* Initialise list of resource allocator...*/ LST_init(&psConnContext->sAttachList); /* Setup connection context...*/ psConnContext->psDevContext = psDevContext; psConnContext->ui32OpenCnt = 1; psConnContext->hProcessId = hProcessId; /* Update the count of connections...*/ psDevContext->ui32ConnCnt++; /* If this is the first connection...*/ if (psDevContext->ui32ConnCnt == 1) { /* Create resource bucket for connections and attachments...*/ RMAN_Initialise(); ui32Result = RMAN_CreateBucket(&psDevContext->hResBHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_create_bucket; } } /* Add to list of connections...*/ LST_add(&psDevContext->sConnList, psConnContext); ui32Result = RMAN_RegisterResource(psDevContext->hResBHandle, DMAN_CONN_TYPE_ID, IMG_NULL, psConnContext, &psConnContext->hResHandle, &psConnContext->ui32ConnId); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_register_resource; } /* Register with the Process Manager in case the process dies...*/ ui32Result = PMAN_Initialise(); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_pman_init; } PMAN_RegisterProcessLostCb(dmankm_fnProcessLostCb, psConnContext, &psConnContext->hProcLostCbHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_pman_register_cb; } /* If this the first connection and initialise function...*/ if ((psDevContext->ui32ConnCnt == 1) && (psDevContext->sDevRegister.pfnDevInit != IMG_NULL )) { /* Allocate implicit connection context...*/ psInitConnContext = IMG_MALLOC(sizeof(*psInitConnContext)); if (psInitConnContext == IMG_NULL ) { IMG_ASSERT(psInitConnContext != IMG_NULL); ui32Result = IMG_ERROR_OUT_OF_MEMORY; goto error_init_conn_ctx; } IMG_MEMSET(psInitConnContext, 0, sizeof(*psInitConnContext)); /* Associated this connection with the device and process...*/ psInitConnContext->psDevContext = psDevContext; psInitConnContext->ui32OpenCnt = 1; psInitConnContext->hProcessId = hProcessId; /* Mark this as the init connection...*/ psInitConnContext->bInitConn = IMG_TRUE; /* Add implicit to list of connections...*/ LST_add(&psDevContext->sConnList, psInitConnContext); ui32Result = RMAN_RegisterResource(psDevContext->hResBHandle, DMAN_CONN_TYPE_ID, IMG_NULL, psInitConnContext, &psInitConnContext->hResHandle, &psInitConnContext->ui32ConnId); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_register_resource_init_ctx; } IMG_ASSERT( (psDevContext->sDevRegister.ui32ConnFlags == DMAN_CFLAG_EXCLUSIVE) || (psDevContext->sDevRegister.ui32ConnFlags == DMAN_CFLAG_SHARED)); /* If it's not a pseudo device... */ if ((psDevContext->sDevRegister.ui32DevFlags & DMAN_DFLAG_PSEUDO_DEVICE) == 0) { /* Open the device...*/ ui32Result = SYSDEVU_OpenDevice(psDevContext->pszDeviceName, &psDevContext->hSysDevHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_open_device; } /* Power the device on. */ SYSDEVU_SetPowerState(psDevContext->hSysDevHandle, SYSOSKM_POWERSTATE_S0, IMG_FALSE); } ui32Result = psDevContext->sDevRegister.pfnDevInit(psDevContext, psInitConnContext, &psDevContext->pvDevInstanceData); if (ui32Result != IMG_SUCCESS) { REPORT(REPORT_MODULE_DMAN, REPORT_ERR, "dev init failed (%d)", ui32Result); goto error_dev_init; } /* If there is a Device Kernel mode HISR...*/ if (psDevContext->sDevRegister.pfnDevKmHisr != IMG_NULL ) { IMG_ASSERT(psDevContext->sDevRegister.pfnDevKmLisr != IMG_NULL); ui32Result = SYSOSKM_CreateKmHisr(&dmankm_fnDevKmHisr, psDevContext, &psDevContext->hHISRHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_create_km_hisr; } } /* If there is a Device Kernel mode LISR...*/ if (psDevContext->sDevRegister.pfnDevKmLisr != IMG_NULL ) { /* Register the LISR wrapper...*/ SYSDEVU_RegisterDevKmLisr(psDevContext->hSysDevHandle, &dmankm_fnDevKmLisr, psDevContext); } } /* If connect/open function...*/ if (psDevContext->sDevRegister.pfnDevConnect != IMG_NULL ) { ui32Result = psDevContext->sDevRegister.pfnDevConnect(psConnContext, psDevContext->pvDevInstanceData, &psConnContext->pvDevConnectionData); IMG_ASSERT( ui32Result == IMG_SUCCESS || ui32Result == IMG_ERROR_INTERRUPTED); if (ui32Result != IMG_SUCCESS && ui32Result != IMG_ERROR_INTERRUPTED) { goto error_dev_connect; } } /* Return the connection handle and/or id...*/ if (phConnHandle != IMG_NULL ) { *phConnHandle = psConnContext; } if (pui32ConnId != IMG_NULL ) { *pui32ConnId = psConnContext->ui32ConnId; } /* Return success...*/ return ui32Result; /* Error handling. */ error_dev_connect: /* If this not the first connection or there's no initialise function...*/ if ((1 != psDevContext->ui32ConnCnt) || (IMG_NULL == psDevContext->sDevRegister.pfnDevInit)) { /* ...skip de-initialisation of this part. */ goto error_init_conn_ctx; } if (IMG_NULL != psDevContext->sDevRegister.pfnDevKmHisr) { SYSOSKM_DestroyKmHisr(psDevContext->hHISRHandle); } error_create_km_hisr: if (IMG_NULL != psDevContext->sDevRegister.pfnDevDeinit) { psDevContext->sDevRegister.pfnDevDeinit(psDevContext, psInitConnContext, psDevContext->pvDevInstanceData); } error_dev_init: if ((psDevContext->sDevRegister.ui32DevFlags & DMAN_DFLAG_PSEUDO_DEVICE) == 0) { SYSDEVU_CloseDevice(psDevContext->hSysDevHandle); } error_open_device: RMAN_FreeResource(psInitConnContext->hResHandle); error_register_resource_init_ctx: LST_remove(&psDevContext->sConnList, psInitConnContext); IMG_FREE(psInitConnContext); error_init_conn_ctx: PMAN_RemoveProcessLostCb(psConnContext->hProcLostCbHandle); /* release per-process resources in PMAN, allocated inside PMAN_RegisterProcessLostCb. We have to use device disconnect, although the device wasn't actually initialised, because no other function is exposed by PMAN */ PMAN_DevDisconnectComplete(hProcessId); error_pman_register_cb: error_pman_init: RMAN_FreeResource(psConnContext->hResHandle); error_register_resource: LST_remove(&psDevContext->sConnList,psConnContext); if (1 == psDevContext->ui32ConnCnt) { RMAN_DestroyBucket(psDevContext->hResBHandle); } error_create_bucket: psDevContext->ui32ConnCnt--; IMG_FREE(psConnContext); return ui32Result; }
/*! ****************************************************************************** @Function POOL_ResRegister ******************************************************************************/ IMG_RESULT POOL_ResRegister( IMG_HANDLE hPoolHandle, POOL_pfnDestructor pfnDestructor, IMG_VOID * pvParam, IMG_UINT32 ui32SizevParam, IMG_BOOL bAlloc, IMG_UINT32 * pui32ResId, IMG_HANDLE * phPoolResHandle ) { POOL_sResPool * psResPool = hPoolHandle; POOL_sResource * psResource; IMG_UINT32 ui32Result; IMG_ASSERT(gInitialised); IMG_ASSERT(psResPool != IMG_NULL); if (!gInitialised || psResPool == IMG_NULL) { ui32Result = IMG_ERROR_INVALID_PARAMETERS; goto error_nolock; } /* Allocate a resource structure...*/ psResource = IMG_MALLOC(sizeof(*psResource)); IMG_ASSERT(psResource != IMG_NULL); if (psResource == IMG_NULL) { return IMG_ERROR_OUT_OF_MEMORY; } IMG_MEMSET(psResource, 0, sizeof(*psResource)); /* Setup the resource...*/ psResource->pfnDestructor = pfnDestructor; psResource->pvParam = pvParam; psResource->ui32SizevParam = ui32SizevParam; psResource->psResPool = psResPool; LST_init(&psResource->sCloneResList); /* Lock the pool...*/ SYSOSKM_LockMutex(psResPool->hMutexHandle); /* Set resource id...*/ ui32Result = IDGEN_AllocId(psResPool->hIdGenHandle, (IMG_HANDLE)psResource, &psResource->ui32ResId); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { IMG_FREE(psResource); /* Unlock the pool...*/ SYSOSKM_UnlockMutex(psResPool->hMutexHandle); return ui32Result; } /* If allocated or free callback not set...*/ if ( (bAlloc) || (psResPool->pfnFree != IMG_NULL) ) { /* Add to active list...*/ LST_add(&psResPool->sActResList, psResource); psResource->ui32RefCnt++; } else { /* Add to free list...*/ LST_add(&psResPool->sFreeResList, psResource); } /* Return the resource id...*/ if (pui32ResId != IMG_NULL) { *pui32ResId = psResource->ui32ResId; } /* Return the handle to the resource...*/ if (phPoolResHandle != IMG_NULL) { *phPoolResHandle = psResource; } /* Unlock the pool...*/ SYSOSKM_UnlockMutex(psResPool->hMutexHandle); /* If free callback set...*/ if (psResPool->pfnFree != IMG_NULL) { /* Call the free callback...*/ psResPool->pfnFree(psResource->ui32ResId, psResource->pvParam); } /* Return IMG_SUCCESS...*/ return IMG_SUCCESS; error_nolock: return ui32Result; }
/*! ****************************************************************************** @Function MMU_DeviceCreate ******************************************************************************/ IMG_RESULT MMU_DeviceCreate( MMU_eMmuType eMmuType, VDEC_eTileScheme eTileScheme, VDECDDMMU_pfnDeviceCallback pfnDeviceCallback, MSVDXIO_sMemPool sMemPool, IMG_VOID * pvCallbackParameter, IMG_UINT32 ui32PtdAlignment, IMG_HANDLE * phMmuDevHandle ) { IMG_RESULT ui32Result = IMG_SUCCESS; IMG_BOOL bTiling = IMG_TRUE; TALMMU_eMMUType eTalMmuType = TALMMU_MMUTYPE_4K_PAGES_32BIT_ADDR; IMG_UINT32 i; MMU_sDevContext * psDevContext; TALMMU_sDevMemInfo sDevMemInfo; // Set the TAL MMU type. switch (eMmuType) { case MMU_TYPE_32BIT: eTalMmuType = TALMMU_MMUTYPE_4K_PAGES_32BIT_ADDR; break; case MMU_TYPE_36BIT: eTalMmuType = TALMMU_MMUTYPE_4K_PAGES_36BIT_ADDR; break; case MMU_TYPE_40BIT: eTalMmuType = TALMMU_MMUTYPE_4K_PAGES_40BIT_ADDR; break; default: return IMG_ERROR_INVALID_PARAMETERS; } /* Allocate a device context structure...*/ VDEC_MALLOC(psDevContext); IMG_ASSERT(psDevContext != IMG_NULL); if (psDevContext == IMG_NULL) { REPORT(REPORT_MODULE_MMU, REPORT_ERR, "Failed to allocate memory for MMU device context"); return IMG_ERROR_OUT_OF_MEMORY; } VDEC_BZERO(psDevContext); /* Initialise stream list. */ LST_init(&psDevContext->sStrList); psDevContext->pfnDeviceCallback = pfnDeviceCallback; psDevContext->pvCallbackParameter = pvCallbackParameter; /* Initialise TALMMU. */ ui32Result = TALMMU_Initialise(); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_tal_init; } /* Create an MMU template */ sDevMemInfo.pszDeviceName = "VDEC"; sDevMemInfo.ui32DeviceId = 0; sDevMemInfo.eMMUType = eTalMmuType; sDevMemInfo.eDevFlags = TALMMU_DEVFLAGS_NONE; sDevMemInfo.pszPageDirMemSpaceName = "MEM"; sDevMemInfo.pszPageTableMemSpaceName = IMG_NULL; sDevMemInfo.ui32PageSize = DEV_MMU_PAGE_SIZE; sDevMemInfo.ui32PageTableDirAlignment = ui32PtdAlignment; sDevMemInfo.eMemAttrib = (SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE); sDevMemInfo.eMemPool = sMemPool.eMemPoolId; sDevMemInfo.eTilingScheme = (eTileScheme == VDEC_TS1_512x8) ? TALMMU_MMUTILING_SCHEME_1 : TALMMU_MMUTILING_SCHEME_0; ui32Result = TALMMU_DevMemTemplateCreate(&sDevMemInfo, &psDevContext->hDevMemTemplate); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_tal_template; } TALMMU_AddCallback(psDevContext->hDevMemTemplate, mmu_Callback, (IMG_PVOID)psDevContext); /* Add heaps to template */ for (i = 0; i < MMU_HEAP_MAX; i++) { sHeapInfo.ui32HeapId = asMmuHeaps[i].eHeapId; sHeapInfo.eHeapType = asMmuHeaps[i].eHeapType; sHeapInfo.pszMemSpaceName = asMmuHeaps[i].pszMemSpace; sHeapInfo.bTiled = (bTiling && asMmuHeaps[i].ui32TileStride) ? IMG_TRUE : IMG_FALSE; sHeapInfo.ui32BaseDevVirtAddr = asMmuHeaps[i].ui32StartOffset; sHeapInfo.ui32Size = asMmuHeaps[i].ui32Size; sHeapInfo.ui32XTileStride = 0; if (asMmuHeaps[i].ui32TileStride) { IMG_UINT32 ui32HwTileStride; IMG_UINT32 ui32Log2HwTileStride = 0; ui32HwTileStride = asMmuHeaps[i].ui32TileStride; // Calculate HW tile stride. // HW tile stride = log2((tile_stride / tile_width)/ 2) ui32HwTileStride >>= 1; switch (eTileScheme) { case VDEC_TS0_256x16: ui32HwTileStride >>= 8; break; case VDEC_TS1_512x8: ui32HwTileStride >>= 9; break; default: IMG_ASSERT(0); break; } ui32HwTileStride >>= 1; while (ui32HwTileStride) { ui32HwTileStride >>= 1; ui32Log2HwTileStride++; } // Calculated hardware coded stride value. ui32HwTileStride = ui32Log2HwTileStride; sHeapInfo.ui32XTileStride = ui32HwTileStride; } ui32Result = TALMMU_DevMemHeapAdd(psDevContext->hDevMemTemplate, &sHeapInfo); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_tal_heap; } }