コード例 #1
0
S3C_BC_ERROR S3C_BC_Unregister(void)
{
	S3C_BC_DEVINFO *psDevInfo;

	psDevInfo = GetAnchorPtr();

	if (!psDevInfo)
	{
		return (S3C_BC_ERROR_GENERIC);
	}

	psDevInfo->ulRefCount--;

	if (psDevInfo->ulRefCount == 0)
	{
		PVRSRV_BC_BUFFER2SRV_KMJTABLE	*psJTable = &psDevInfo->sPVRJTable;

		if (psJTable->pfnPVRSRVRemoveBCDevice(psDevInfo->ulDeviceID) != PVRSRV_OK)
		{
			return (S3C_BC_ERROR_GENERIC);
		}

		BCFreeKernelMem(psDevInfo);

		SetAnchorPtr(0);
	}

	return (S3C_BC_OK);
}
コード例 #2
0
OMAP_ERROR OMAPLFBDeinit(void)
{
	OMAPLFB_DEVINFO *psDevInfo, *psDevFirst;

	psDevFirst = GetAnchorPtr();
	psDevInfo = psDevFirst;

	
	if (psDevInfo == NULL)
	{
		return (OMAP_ERROR_GENERIC);
	}

	
	psDevInfo->ulRefCount--;

	if (psDevInfo->ulRefCount == 0)
	{
		
		PVRSRV_DC_DISP2SRV_KMJTABLE	*psJTable = &psDevInfo->sPVRJTable;

		if (psDevInfo->sPVRJTable.pfnPVRSRVRemoveCmdProcList (psDevInfo->ulDeviceID, OMAPLFB_COMMAND_COUNT) != PVRSRV_OK)
		{
			return (OMAP_ERROR_GENERIC);
		}

		
		if (psJTable->pfnPVRSRVRemoveDCDevice(psDevInfo->ulDeviceID) != PVRSRV_OK)
		{
			return (OMAP_ERROR_GENERIC);
		}
		
		DeInitDev(psDevInfo);

		
		OMAPLFBFreeKernelMem(psDevInfo);
	}
	
	
	SetAnchorPtr(NULL);

	
	return (OMAP_OK);
}
コード例 #3
0
DC_ERROR Deinit(void)
{
	DC_NOHW_DEVINFO *psDevInfo, *psDevFirst;
#if !defined(USE_BASE_VIDEO_FRAMEBUFFER)
	unsigned long i;
#endif

	psDevFirst = GetAnchorPtr();
	psDevInfo = psDevFirst;

	
	if (psDevInfo == 0)
	{
		return (DC_ERROR_GENERIC);
	}

	
	psDevInfo->ulRefCount--;

	if (psDevInfo->ulRefCount == 0UL)
	{
		
		PVRSRV_DC_DISP2SRV_KMJTABLE	*psJTable = &psDevInfo->sPVRJTable;

		
		if (psJTable->pfnPVRSRVRemoveDCDevice((IMG_UINT32)psDevInfo->uiDeviceID) != PVRSRV_OK)
		{
			return (DC_ERROR_GENERIC);
		}

		if (psDevInfo->sPVRJTable.pfnPVRSRVRemoveCmdProcList(psDevInfo->uiDeviceID,
															 DC_NOHW_COMMAND_COUNT) != PVRSRV_OK)
		{
			return (DC_ERROR_GENERIC);
		}

		if (ClosePVRServices(psDevInfo->hPVRServices) != DC_OK)
		{
			psDevInfo->hPVRServices = 0;
			return (DC_ERROR_GENERIC);
		}

#if !defined(USE_BASE_VIDEO_FRAMEBUFFER)
		for(i=0; i<DC_NOHW_MAX_BACKBUFFERS; i++)
		{
			if (psDevInfo->asBackBuffers[i].sCPUVAddr)
			{
				#if defined(DC_NOHW_DISCONTIG_BUFFERS)
				FreeDiscontigMemory(psDevInfo->ui32BufferSize,
							 psDevInfo->asBackBuffers[i].hMemChunk,
							 psDevInfo->asBackBuffers[i].sCPUVAddr,
							 psDevInfo->asBackBuffers[i].psSysAddr);
				#else

				FreeContigMemory(psDevInfo->ui32BufferSize,
							 psDevInfo->asBackBuffers[i].hMemChunk,
							 psDevInfo->asBackBuffers[i].sCPUVAddr,
							 SysPAddrToCpuPAddr(psDevInfo->asBackBuffers[i].sSysAddr));
				#endif
			}
		}
#endif 

		
		FreeKernelMem(psDevInfo);
	}

#if defined (ENABLE_DISPLAY_MODE_TRACKING)
	CloseMiniport();
#endif
	
	SetAnchorPtr(0);

	
	return (DC_OK);
}
コード例 #4
0
DC_ERROR Init(void)
{
	DC_NOHW_DEVINFO *psDevInfo;
	DC_ERROR         eError;
	unsigned long    ulBBuf;
	unsigned long    ulNBBuf;
	



	



	

	psDevInfo = GetAnchorPtr();

	if (psDevInfo == 0)
	{
		PFN_CMD_PROC  pfnCmdProcList[DC_NOHW_COMMAND_COUNT];
		IMG_UINT32    aui32SyncCountList[DC_NOHW_COMMAND_COUNT][2];

		
		psDevInfo = (DC_NOHW_DEVINFO *)AllocKernelMem(sizeof(*psDevInfo));

		if(!psDevInfo)
		{
			eError = DC_ERROR_OUT_OF_MEMORY;
			goto ExitError;
		}

		
		memset(psDevInfo, 0, sizeof(*psDevInfo));

		
		SetAnchorPtr((void*)psDevInfo);

		
		psDevInfo->ulRefCount = 0UL;

		if(OpenPVRServices(&psDevInfo->hPVRServices) != DC_OK)
		{
			eError = DC_ERROR_INIT_FAILURE;
			goto ExitFreeDevInfo;
		}
		if(GetLibFuncAddr (psDevInfo->hPVRServices, "PVRGetDisplayClassJTable", &pfnGetPVRJTable) != DC_OK)
		{
			eError = DC_ERROR_INIT_FAILURE;
			goto ExitCloseServices;
		}

		
		if((*pfnGetPVRJTable)(&psDevInfo->sPVRJTable) == IMG_FALSE)
		{
			eError = DC_ERROR_INIT_FAILURE;
			goto ExitCloseServices;
		}

		

		psDevInfo->psSwapChain = 0;
		psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0UL;
		psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 1UL;
		psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1UL;
		psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = DC_NOHW_MAX_BACKBUFFERS;
		strncpy(psDevInfo->sDisplayInfo.szDisplayName, DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);

		psDevInfo->ulNumFormats = 1UL;

		psDevInfo->ulNumDims = 1UL;

#if defined(DC_NOHW_GET_BUFFER_DIMENSIONS)
		if (!GetBufferDimensions(&psDevInfo->asDisplayDimList[0].ui32Width,
			&psDevInfo->asDisplayDimList[0].ui32Height,
			&psDevInfo->asDisplayFormatList[0].pixelformat,
			&psDevInfo->asDisplayDimList[0].ui32ByteStride))
		{
			eError = DC_ERROR_INIT_FAILURE;
			goto ExitCloseServices;
		}
#else	
	#if defined (ENABLE_DISPLAY_MODE_TRACKING)
		
		psDevInfo->asDisplayFormatList[0].pixelformat = DC_NOHW_BUFFER_PIXEL_FORMAT;
		psDevInfo->asDisplayDimList[0].ui32Width =  0;
		psDevInfo->asDisplayDimList[0].ui32Height =  0;
		psDevInfo->asDisplayDimList[0].ui32ByteStride = 0;
	#else
		psDevInfo->asDisplayFormatList[0].pixelformat = DC_NOHW_BUFFER_PIXEL_FORMAT;
		psDevInfo->asDisplayDimList[0].ui32Width =  DC_NOHW_BUFFER_WIDTH;
		psDevInfo->asDisplayDimList[0].ui32Height =  DC_NOHW_BUFFER_HEIGHT;
		psDevInfo->asDisplayDimList[0].ui32ByteStride = DC_NOHW_BUFFER_BYTE_STRIDE;
	#endif
#endif	

		psDevInfo->sSysFormat = psDevInfo->asDisplayFormatList[0];
		psDevInfo->sSysDims.ui32Width = psDevInfo->asDisplayDimList[0].ui32Width;
		psDevInfo->sSysDims.ui32Height = psDevInfo->asDisplayDimList[0].ui32Height;
		psDevInfo->sSysDims.ui32ByteStride = psDevInfo->asDisplayDimList[0].ui32ByteStride;
		psDevInfo->ui32BufferSize = psDevInfo->sSysDims.ui32Height * psDevInfo->sSysDims.ui32ByteStride;


		
		for(ulBBuf=0; ulBBuf<DC_NOHW_MAX_BACKBUFFERS; ulBBuf++)
		{
#if defined(USE_BASE_VIDEO_FRAMEBUFFER) || defined (ENABLE_DISPLAY_MODE_TRACKING)
			psDevInfo->asBackBuffers[ulBBuf].sSysAddr.uiAddr = IMG_NULL;
			psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr = IMG_NULL;
#else
#if defined(DC_NOHW_DISCONTIG_BUFFERS)
			if (AllocDiscontigMemory(psDevInfo->ui32BufferSize,
								  &psDevInfo->asBackBuffers[ulBBuf].hMemChunk,
								  &psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr,
								  &psDevInfo->asBackBuffers[ulBBuf].psSysAddr) != DC_OK)
			{
				eError = DC_ERROR_INIT_FAILURE;
				goto ExitFreeMem;
			}
#else
			IMG_CPU_PHYADDR		sBufferCPUPAddr;

			if (AllocContigMemory(psDevInfo->ui32BufferSize,
								  &psDevInfo->asBackBuffers[ulBBuf].hMemChunk,
								  &psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr,
								  &sBufferCPUPAddr) != DC_OK)
			{
				eError = DC_ERROR_INIT_FAILURE;
				goto ExitFreeMem;
			}

			psDevInfo->asBackBuffers[ulBBuf].sSysAddr =  CpuPAddrToSysPAddr(sBufferCPUPAddr);
#endif
#endif 
			
			psDevInfo->asBackBuffers[ulBBuf].sDevVAddr.uiAddr = 0UL;
			psDevInfo->asBackBuffers[ulBBuf].hSwapChain = 0;
			psDevInfo->asBackBuffers[ulBBuf].psSyncData = 0;
			psDevInfo->asBackBuffers[ulBBuf].psNext = 0;
		}

		

		psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
		psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
		psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
		psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
		psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
		psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
		psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
		psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
		psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
		psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
		psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
		psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
		psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
		psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
		psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
		psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer;
		psDevInfo->sDCJTable.pfnSwapToDCSystem = SwapToDCSystem;
		psDevInfo->sDCJTable.pfnSetDCState = IMG_NULL;

		
		if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice (&psDevInfo->sDCJTable,
															&psDevInfo->uiDeviceID ) != PVRSRV_OK)
		{
			eError = DC_ERROR_DEVICE_REGISTER_FAILED;
			goto ExitFreeMem;
		}

		

		pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;

		

		aui32SyncCountList[DC_FLIP_COMMAND][0] = 0UL;
		aui32SyncCountList[DC_FLIP_COMMAND][1] = 2UL;

		



		if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList(psDevInfo->uiDeviceID,
															   &pfnCmdProcList[0],
															   aui32SyncCountList,
															   DC_NOHW_COMMAND_COUNT) != PVRSRV_OK)
		{
			eError = DC_ERROR_CANT_REGISTER_CALLBACK;
			goto ExitRemoveDevice;
		}
	}

	
	psDevInfo->ulRefCount++;

	
	return (DC_OK);

ExitRemoveDevice:
	(IMG_VOID) psDevInfo->sPVRJTable.pfnPVRSRVRemoveDCDevice(psDevInfo->uiDeviceID);

ExitFreeMem:
	ulNBBuf = ulBBuf;
	for(ulBBuf=0; ulBBuf<ulNBBuf; ulBBuf++)
	{
#if defined(DC_NOHW_DISCONTIG_BUFFERS)
		FreeDiscontigMemory(psDevInfo->ui32BufferSize,
			 psDevInfo->asBackBuffers[ulBBuf].hMemChunk,
			 psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr,
			 psDevInfo->asBackBuffers[ulBBuf].psSysAddr);
#else
#if !defined(USE_BASE_VIDEO_FRAMEBUFFER)

		FreeContigMemory(psDevInfo->ui32BufferSize,
			 psDevInfo->asBackBuffers[ulBBuf].hMemChunk,
			 psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr,
			 SysPAddrToCpuPAddr(psDevInfo->asBackBuffers[ulBBuf].sSysAddr));


#endif 
#endif 
	}

ExitCloseServices:
	(void)ClosePVRServices(psDevInfo->hPVRServices);

ExitFreeDevInfo:
	FreeKernelMem(psDevInfo);
	SetAnchorPtr(0);

ExitError:
	return eError;
}
コード例 #5
0
OMAP_ERROR OMAPLFBInit(void)
{
	OMAPLFB_DEVINFO		*psDevInfo;

	psDevInfo = GetAnchorPtr();
	
	if (psDevInfo == NULL)
	{
		PFN_CMD_PROC	 		pfnCmdProcList[OMAPLFB_COMMAND_COUNT];
		IMG_UINT32				aui32SyncCountList[OMAPLFB_COMMAND_COUNT][2];
		
		psDevInfo = (OMAPLFB_DEVINFO *)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_DEVINFO));

		if(!psDevInfo)
		{
			return (OMAP_ERROR_OUT_OF_MEMORY);
		}

		
		memset(psDevInfo, 0, sizeof(OMAPLFB_DEVINFO));

		
		SetAnchorPtr((void*)psDevInfo);

		
		psDevInfo->ulRefCount = 0;

		
		if(InitDev(psDevInfo) != OMAP_OK)
		{
			return (OMAP_ERROR_INIT_FAILURE);
		}

		if(OMAPLFBGetLibFuncAddr ("PVRGetDisplayClassJTable", &pfnGetPVRJTable) != OMAP_OK)
		{
			return (OMAP_ERROR_INIT_FAILURE);
		}

		
		if(!(*pfnGetPVRJTable)(&psDevInfo->sPVRJTable))
		{
			return (OMAP_ERROR_INIT_FAILURE);
		}

		spin_lock_init(&psDevInfo->sSwapChainLock);

		psDevInfo->psSwapChain = 0;
		psDevInfo->bFlushCommands = OMAP_FALSE;
		psDevInfo->bDeviceSuspended = OMAP_FALSE;

		psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = (IMG_UINT32)(psDevInfo->sFBInfo.ulFBSize / psDevInfo->sFBInfo.ulRoundedBufferSize);
		if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers == 0)
		{
			psDevInfo->sDisplayInfo.ui32MaxSwapChains = 0;
			psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 0;
		}
		else
		{
			psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1;
			psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 3;
		}
		psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0;

		strncpy(psDevInfo->sDisplayInfo.szDisplayName, DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);
	
		psDevInfo->sDisplayFormat.pixelformat = psDevInfo->sFBInfo.ePixelFormat;
		psDevInfo->sDisplayDim.ui32Width      = (IMG_UINT32)psDevInfo->sFBInfo.ulWidth;
		psDevInfo->sDisplayDim.ui32Height     = (IMG_UINT32)psDevInfo->sFBInfo.ulHeight;
		psDevInfo->sDisplayDim.ui32ByteStride = (IMG_UINT32)psDevInfo->sFBInfo.ulByteStride;

		DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
			": Maximum number of swap chain buffers: %lu\n",
			psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));

		psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
		psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr;
		psDevInfo->sSystemBuffer.ulBufferSize = psDevInfo->sFBInfo.ulRoundedBufferSize;

		

		psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
		psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
		psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
		psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
		psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
		psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
		psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
		psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
		psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
		psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
		psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
		psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
		psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
		psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
		psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
		psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer;
		psDevInfo->sDCJTable.pfnSwapToDCSystem = SwapToDCSystem;
		psDevInfo->sDCJTable.pfnSetDCState = SetDCState;

		
		if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice (
			&psDevInfo->sDCJTable,
			&psDevInfo->ulDeviceID ) != PVRSRV_OK)
		{
			return (OMAP_ERROR_DEVICE_REGISTER_FAILED);
		}
		
		
		pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;

		
		aui32SyncCountList[DC_FLIP_COMMAND][0] = 0; 
		aui32SyncCountList[DC_FLIP_COMMAND][1] = 2; 

		



		if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList (psDevInfo->ulDeviceID,
																&pfnCmdProcList[0],
																aui32SyncCountList,
																OMAPLFB_COMMAND_COUNT) != PVRSRV_OK)
		{
			printk(KERN_WARNING DRIVER_PREFIX ": Can't register callback\n");
			return (OMAP_ERROR_CANT_REGISTER_CALLBACK);
		}

	}

	
	psDevInfo->ulRefCount++;

	
	return (OMAP_OK);
	
	}
コード例 #6
0
S3C_BC_ERROR S3C_BC_Register(void)
{
	S3C_BC_DEVINFO	*psDevInfo;
	int i;
	unsigned long addr;

	IMG_UINT32 pixelformat;

	struct fb_info *fbinfo = registered_fb[0];

	g_screen_w = (int)fbinfo->var.xres;
	g_screen_h = (int)fbinfo->var.yres;

	if ( g_screen_w < g_screen_h )
	{
		IMG_UINT32 t = g_screen_w;
		g_screen_w = g_screen_h;
		g_screen_h = t;
	}

	if (16 == (int)fbinfo->var.bits_per_pixel)
	{
		pixelformat = PVRSRV_PIXEL_FORMAT_RGB565;
		g_screen_stride = g_screen_w*2;
	}
	else
	{
		pixelformat = PVRSRV_PIXEL_FORMAT_ARGB8888;
		g_screen_stride = g_screen_w*4;
	}

	g_buffer_size = ((g_screen_h * g_screen_stride + S3C_BC_DEVICE_PHYS_PAGE_SIZE - 1) & ~(S3C_BC_DEVICE_PHYS_PAGE_SIZE-1));

	psDevInfo = GetAnchorPtr();

	if (!psDevInfo)
	{
		psDevInfo = (S3C_BC_DEVINFO *)BCAllocKernelMem(sizeof(S3C_BC_DEVINFO));

		if(!psDevInfo)
		{
			return (S3C_BC_ERROR_OUT_OF_MEMORY);/* failure */
		}

		SetAnchorPtr((void*)psDevInfo);

		psDevInfo->ulRefCount = 0;
		
		psDevInfo->ulDeviceID = S3C_BC_DEVICE_ID;
	
		if(BCGetLibFuncAddr ("PVRGetBufferClassJTable", &pfnGetPVRJTable) != S3C_BC_OK)
		{
			return (S3C_BC_ERROR_INIT_FAILURE);
		}

		if(!(*pfnGetPVRJTable)(&psDevInfo->sPVRJTable))
		{
			return (S3C_BC_ERROR_INIT_FAILURE);
		}


		psDevInfo->sBufferInfo.pixelformat        = pixelformat;
		psDevInfo->sBufferInfo.ui32Width          = g_screen_w;
		psDevInfo->sBufferInfo.ui32Height         = g_screen_h;
		psDevInfo->sBufferInfo.ui32ByteStride     = g_screen_stride;
		psDevInfo->sBufferInfo.ui32BufferDeviceID = S3C_BC_DEVICE_ID;
		psDevInfo->sBufferInfo.ui32Flags          = 0;
		psDevInfo->sBufferInfo.ui32BufferCount    = S3C_BC_DEVICE_BUFFER_COUNT;

		addr = S3C_BC_DEVICE_PHYS_ADDR_START;
		for(i = 0; i < S3C_BC_DEVICE_BUFFER_COUNT; i++, addr += g_buffer_size)
		{
			psDevInfo->sSystemBuffer[i].sSysAddr.uiAddr = (IMG_UINTPTR_T)addr;
		}

		psDevInfo->sBCJTable.ui32TableSize    = sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE);
		psDevInfo->sBCJTable.pfnOpenBCDevice  = OpenBCDevice;
		psDevInfo->sBCJTable.pfnCloseBCDevice = CloseBCDevice;
		psDevInfo->sBCJTable.pfnGetBCBuffer   = GetBCBuffer;
		psDevInfo->sBCJTable.pfnGetBCInfo     = GetBCInfo;
		psDevInfo->sBCJTable.pfnGetBufferAddr = GetBCBufferAddr;

		if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterBCDevice (&psDevInfo->sBCJTable,
										(IMG_UINT32*)&psDevInfo->ulDeviceID ) != PVRSRV_OK)
		{
			return (S3C_BC_ERROR_DEVICE_REGISTER_FAILED);
		}
	}

	psDevInfo->ulRefCount++;

	return (S3C_BC_OK);
}
/*
 *	Deinit
 */
DC_ERROR Deinit(void)
{
	DC_NOHW_DEVINFO *psDevInfo, *psDevFirst;
#if !defined(USE_BASE_VIDEO_FRAMEBUFFER)
	unsigned long i;
#endif

	psDevFirst = GetAnchorPtr();
	psDevInfo = psDevFirst;

	/* check DevInfo has been setup */
	if (psDevInfo == 0)
	{
		return (DC_ERROR_GENERIC);/* failure */
	}

	/* decrement ref count */
	psDevInfo->ulRefCount--;

	if (psDevInfo->ulRefCount == 0UL)
	{
		/* all references gone - de-init device information */
		PVRSRV_DC_DISP2SRV_KMJTABLE	*psJTable = &psDevInfo->sPVRJTable;

		/* Remove display class device from kernel services device register */
		if (psJTable->pfnPVRSRVRemoveDCDevice((IMG_UINT32)psDevInfo->uiDeviceID) != PVRSRV_OK)
		{
			return (DC_ERROR_GENERIC);/* failure */
		}

		if (psDevInfo->sPVRJTable.pfnPVRSRVRemoveCmdProcList(psDevInfo->uiDeviceID,
															 DC_NOHW_COMMAND_COUNT) != PVRSRV_OK)
		{
			return (DC_ERROR_GENERIC);/* failure */
		}

		if (ClosePVRServices(psDevInfo->hPVRServices) != DC_OK)
		{
			psDevInfo->hPVRServices = 0;
			return (DC_ERROR_GENERIC);/* failure */
		}

#if !defined(USE_BASE_VIDEO_FRAMEBUFFER)
		for(i=0; i<DC_NOHW_MAX_BACKBUFFERS; i++)
		{
			if (psDevInfo->asBackBuffers[i].sCPUVAddr)
			{
				#if defined(DC_NOHW_DISCONTIG_BUFFERS)
				FreeDiscontigMemory(psDevInfo->ui32BufferSize,
							 psDevInfo->asBackBuffers[i].hMemChunk,
							 psDevInfo->asBackBuffers[i].sCPUVAddr,
							 psDevInfo->asBackBuffers[i].psSysAddr);
				#else

				FreeContigMemory(psDevInfo->ui32BufferSize,
							 psDevInfo->asBackBuffers[i].hMemChunk,
							 psDevInfo->asBackBuffers[i].sCPUVAddr,
							 SysPAddrToCpuPAddr(psDevInfo->asBackBuffers[i].sSysAddr));
				#endif
			}
		}
#endif /* #if !defined(USE_BASE_VIDEO_FRAMEBUFFER) */

		/* de-allocate data structure */
		FreeKernelMem(psDevInfo);
	}

#if defined (ENABLE_DISPLAY_MODE_TRACKING)
	CloseMiniport();
#endif
	/* clear the top-level anchor */
	SetAnchorPtr(0);

	/* return success */
	return (DC_OK);
}
DC_ERROR Init(void)
{
	DC_NOHW_DEVINFO *psDevInfo;
	DC_ERROR         eError;
	unsigned long    ulBBuf;
	unsigned long    ulNBBuf;
	/*
		- connect to services
		- register with services
		- allocate and setup private data structure
	*/


	/*
		in kernel driver, data structures must be anchored to something for subsequent retrieval
		this may be a single global pointer or TLS or something else - up to you
		call API to retrieve this ptr
	*/

	/*
		get the anchor pointer
	*/
	psDevInfo = GetAnchorPtr();

	if (psDevInfo == 0)
	{
		PFN_CMD_PROC  pfnCmdProcList[DC_NOHW_COMMAND_COUNT];
		IMG_UINT32    aui32SyncCountList[DC_NOHW_COMMAND_COUNT][2];

		/* allocate device info. structure */
		psDevInfo = (DC_NOHW_DEVINFO *)AllocKernelMem(sizeof(*psDevInfo));

		if(!psDevInfo)
		{
			eError = DC_ERROR_OUT_OF_MEMORY;/* failure */
			goto ExitError;
		}

		/* initialise allocation */
		memset(psDevInfo, 0, sizeof(*psDevInfo));

		/* set the top-level anchor */
		SetAnchorPtr((void*)psDevInfo);

		/* set ref count */
		psDevInfo->ulRefCount = 0UL;

		if(OpenPVRServices(&psDevInfo->hPVRServices) != DC_OK)
		{
			eError = DC_ERROR_INIT_FAILURE;
			goto ExitFreeDevInfo;
		}
		if(GetLibFuncAddr (psDevInfo->hPVRServices, "PVRGetDisplayClassJTable", &pfnGetPVRJTable) != DC_OK)
		{
			eError = DC_ERROR_INIT_FAILURE;
			goto ExitCloseServices;
		}

		/* got the kernel services function table */
		if((*pfnGetPVRJTable)(&psDevInfo->sPVRJTable) == IMG_FALSE)
		{
			eError = DC_ERROR_INIT_FAILURE;
			goto ExitCloseServices;
		}

		/*
			Setup the devinfo
		*/
		psDevInfo->psSwapChain = 0;
		psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0UL;
		psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 1UL;
		psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1UL;
		psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = DC_NOHW_MAX_BACKBUFFERS;
		strncpy(psDevInfo->sDisplayInfo.szDisplayName, DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);

		psDevInfo->ulNumFormats = 1UL;

		psDevInfo->ulNumDims = 1UL;

#if defined(DC_NOHW_GET_BUFFER_DIMENSIONS)
		if (!GetBufferDimensions(&psDevInfo->asDisplayDimList[0].ui32Width,
			&psDevInfo->asDisplayDimList[0].ui32Height,
			&psDevInfo->asDisplayFormatList[0].pixelformat,
			&psDevInfo->asDisplayDimList[0].ui32ByteStride))
		{
			eError = DC_ERROR_INIT_FAILURE;
			goto ExitCloseServices;
		}
#else	/* defined(DC_NOHW_GET_BUFFER_DIMENSIONS) */
	#if defined (ENABLE_DISPLAY_MODE_TRACKING)
		// Set sizes to zero to force re-alloc on display mode change.
		psDevInfo->asDisplayFormatList[0].pixelformat = DC_NOHW_BUFFER_PIXEL_FORMAT;
		psDevInfo->asDisplayDimList[0].ui32Width =  0;
		psDevInfo->asDisplayDimList[0].ui32Height =  0;
		psDevInfo->asDisplayDimList[0].ui32ByteStride = 0;
	#else
		psDevInfo->asDisplayFormatList[0].pixelformat = DC_NOHW_BUFFER_PIXEL_FORMAT;
		psDevInfo->asDisplayDimList[0].ui32Width =  DC_NOHW_BUFFER_WIDTH;
		psDevInfo->asDisplayDimList[0].ui32Height =  DC_NOHW_BUFFER_HEIGHT;
		psDevInfo->asDisplayDimList[0].ui32ByteStride = DC_NOHW_BUFFER_BYTE_STRIDE;
	#endif
#endif	/* defined(DC_NOHW_GET_BUFFER_DIMENSIONS) */

		psDevInfo->sSysFormat = psDevInfo->asDisplayFormatList[0];
		psDevInfo->sSysDims.ui32Width = psDevInfo->asDisplayDimList[0].ui32Width;
		psDevInfo->sSysDims.ui32Height = psDevInfo->asDisplayDimList[0].ui32Height;
		psDevInfo->sSysDims.ui32ByteStride = psDevInfo->asDisplayDimList[0].ui32ByteStride;
		psDevInfo->ui32BufferSize = psDevInfo->sSysDims.ui32Height * psDevInfo->sSysDims.ui32ByteStride;


		/* setup swapchain details */
		for(ulBBuf=0; ulBBuf<DC_NOHW_MAX_BACKBUFFERS; ulBBuf++)
		{
#if defined(USE_BASE_VIDEO_FRAMEBUFFER) || defined (ENABLE_DISPLAY_MODE_TRACKING)
			psDevInfo->asBackBuffers[ulBBuf].sSysAddr.uiAddr = IMG_NULL;
			psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr = IMG_NULL;
#else
#if defined(DC_NOHW_DISCONTIG_BUFFERS)
			if (AllocDiscontigMemory(psDevInfo->ui32BufferSize,
								  &psDevInfo->asBackBuffers[ulBBuf].hMemChunk,
								  &psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr,
								  &psDevInfo->asBackBuffers[ulBBuf].psSysAddr) != DC_OK)
			{
				eError = DC_ERROR_INIT_FAILURE;
				goto ExitFreeMem;
			}
#else
			IMG_CPU_PHYADDR		sBufferCPUPAddr;

			if (AllocContigMemory(psDevInfo->ui32BufferSize,
								  &psDevInfo->asBackBuffers[ulBBuf].hMemChunk,
								  &psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr,
								  &sBufferCPUPAddr) != DC_OK)
			{
				eError = DC_ERROR_INIT_FAILURE;
				goto ExitFreeMem;
			}

			psDevInfo->asBackBuffers[ulBBuf].sSysAddr =  CpuPAddrToSysPAddr(sBufferCPUPAddr);
#endif
#endif /* #if defined(USE_BASE_VIDEO_FRAMEBUFFER) */
			/* sDevVAddr not meaningful for nohw */
			psDevInfo->asBackBuffers[ulBBuf].sDevVAddr.uiAddr = 0UL;
			psDevInfo->asBackBuffers[ulBBuf].hSwapChain = 0;
			psDevInfo->asBackBuffers[ulBBuf].psSyncData = 0;
			psDevInfo->asBackBuffers[ulBBuf].psNext = 0;
		}

		/*
			setup the DC Jtable so SRVKM can call into this driver
		*/
		psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
		psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
		psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
		psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
		psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
		psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
		psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
		psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
		psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
		psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
		psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
		psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
		psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
		psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
		psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
		psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer;
		psDevInfo->sDCJTable.pfnSetDCState = IMG_NULL;

		/* register device with services and retrieve device index */
		if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice (&psDevInfo->sDCJTable,
															&psDevInfo->uiDeviceID ) != PVRSRV_OK)
		{
			eError = DC_ERROR_DEVICE_REGISTER_FAILED;
			goto ExitFreeMem;
		}

		/*
			setup private command processing function table
		*/
		pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;

		/*
			and associated sync count(s)
		*/
		aui32SyncCountList[DC_FLIP_COMMAND][0] = 0UL;/* no writes */
		aui32SyncCountList[DC_FLIP_COMMAND][1] = 2UL;/* 2 reads: To / From */

		/*
			register private command processing functions with
			the Command Queue Manager and setup the general
			command complete function in the devinfo
		*/
		if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList(psDevInfo->uiDeviceID,
															   &pfnCmdProcList[0],
															   aui32SyncCountList,
															   DC_NOHW_COMMAND_COUNT) != PVRSRV_OK)
		{
			eError = DC_ERROR_CANT_REGISTER_CALLBACK;
			goto ExitRemoveDevice;
		}
	}

	/* increment the ref count */
	psDevInfo->ulRefCount++;

	/* return success */
	return (DC_OK);

ExitRemoveDevice:
	(IMG_VOID) psDevInfo->sPVRJTable.pfnPVRSRVRemoveDCDevice(psDevInfo->uiDeviceID);

ExitFreeMem:
	ulNBBuf = ulBBuf;
	for(ulBBuf=0; ulBBuf<ulNBBuf; ulBBuf++)
	{
#if defined(DC_NOHW_DISCONTIG_BUFFERS)
		FreeDiscontigMemory(psDevInfo->ui32BufferSize,
			 psDevInfo->asBackBuffers[ulBBuf].hMemChunk,
			 psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr,
			 psDevInfo->asBackBuffers[ulBBuf].psSysAddr);
#else
#if !defined(USE_BASE_VIDEO_FRAMEBUFFER)

		FreeContigMemory(psDevInfo->ui32BufferSize,
			 psDevInfo->asBackBuffers[ulBBuf].hMemChunk,
			 psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr,
			 SysPAddrToCpuPAddr(psDevInfo->asBackBuffers[ulBBuf].sSysAddr));


#endif /* #if defined(USE_BASE_VIDEO_FRAMEBUFFER) */
#endif /* #if defined(DC_NOHW_DISCONTIG_BUFFERS) */
	}

ExitCloseServices:
	(void)ClosePVRServices(psDevInfo->hPVRServices);

ExitFreeDevInfo:
	FreeKernelMem(psDevInfo);
	SetAnchorPtr(0);

ExitError:
	return eError;
}