Esempio n. 1
0
int omap_display_initialize(void)
{
	/*
	 * TODO: Is there a better way to check if list is already created?
	 */
	if (!omap_display_list) {
		DBG_PRINT("Initializing driver");
		if (create_display_list()) {
			ERR_PRINT("Error loading driver");
			return 1;
		}
	}

	vdisp_wq_primary = __create_workqueue("vdisp_wq_primary", 1, 1, 1);
	vdisp_wq_secondary = __create_workqueue("vdisp_wq_secondary", 1, 1, 1);
	INIT_WORK((struct work_struct *)&vdisp_sync_primary,
		vdisp_sync_handler);
	INIT_WORK((struct work_struct *)&vdisp_sync_secondary,
		vdisp_sync_handler);

	return 0;
}
Esempio n. 2
0
MTKLFB_ERROR MTKLFBCreateSwapQueue(MTKLFB_SWAPCHAIN *psSwapChain)
{
	
	psSwapChain->psWorkQueue = __create_workqueue(DEVNAME, 1, 1, 1);
	if (psSwapChain->psWorkQueue == NULL)
	{
		printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: create_singlethreaded_workqueue failed\n", __FUNCTION__, psSwapChain->uiFBDevID);

		return (MTKLFB_ERROR_INIT_FAILURE);
	}

	return (MTKLFB_OK);
}
OMAPLFB_ERROR OMAPLFBCreateSwapQueue(OMAPLFB_SWAPCHAIN *psSwapChain)
{
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34))
        psSwapChain->psWorkQueue = __create_workqueue(DEVNAME, 1, 1, 1);
#else	
	psSwapChain->psWorkQueue = create_workqueue(DEVNAME);
#endif
	if (psSwapChain->psWorkQueue == NULL)
	{
		printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: create_singlethreaded_workqueue failed\n", __FUNCTION__, psSwapChain->uiFBDevID);

		return (OMAPLFB_ERROR_INIT_FAILURE);
	}

	return (OMAPLFB_OK);
}
Esempio n. 4
0
/* Create a swap chain work queue */
OMAPLFB_ERROR OMAPLFBCreateSwapQueue(OMAPLFB_SWAPCHAIN *psSwapChain)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
	/*
	 * Calling alloc_ordered_workqueue with the WQ_FREEZABLE and
	 * WQ_MEM_RECLAIM flags set, (currently) has the same effect as
	 * calling create_freezable_workqueue. None of the other WQ
	 * flags are valid. Setting WQ_MEM_RECLAIM should allow the
	 * workqueue to continue to service the swap chain in low memory
	 * conditions, preventing the driver from holding on to
	 * resources longer than it needs to.
	 */
#if (LINUX_VERSION_CODE == KERNEL_VERSION(2,6,37))
	psSwapChain->psWorkQueue = alloc_ordered_workqueue(DEVNAME, WQ_FREEZEABLE | WQ_MEM_RECLAIM);
#else
	psSwapChain->psWorkQueue = alloc_ordered_workqueue(DEVNAME, WQ_FREEZABLE | WQ_MEM_RECLAIM);
#endif

#else
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
	psSwapChain->psWorkQueue = create_freezable_workqueue(DEVNAME);
#else
	/*
	 * Create a single-threaded, freezable, rt-prio workqueue.
	 * Such workqueues are frozen with user threads when a system
	 * suspends, before driver suspend entry points are called.
	 * This ensures this driver will not call into the Linux
	 * framebuffer driver after the latter is suspended.
	 */
	psSwapChain->psWorkQueue = __create_workqueue(DEVNAME, 1, 1, 1);
#endif
#endif
	if (psSwapChain->psWorkQueue == NULL)
	{
		printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: Couldn't create workqueue\n", __FUNCTION__, psSwapChain->uiFBDevID);

		return (OMAPLFB_ERROR_INIT_FAILURE);
	}

	return (OMAPLFB_OK);
}
Esempio n. 5
0
OMAPLFB_ERROR OMAPLFBCreateSwapQueue(OMAPLFB_SWAPCHAIN *psSwapChain)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
	
	psSwapChain->psWorkQueue = alloc_ordered_workqueue(DEVNAME, WQ_FREEZABLE | WQ_MEM_RECLAIM);
#else
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
	psSwapChain->psWorkQueue = create_freezable_workqueue(DEVNAME);
#else
	
	psSwapChain->psWorkQueue = __create_workqueue(DEVNAME, 1, 1, 1);
#endif
#endif
	if (psSwapChain->psWorkQueue == NULL)
	{
		printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: Couldn't create workqueue\n", __FUNCTION__, psSwapChain->uiFBDevID);

		return (OMAPLFB_ERROR_INIT_FAILURE);
	}

	return (OMAPLFB_OK);
}
/*
 * Creates a swap chain. Called when a 3D application begins.
 * in: hDevice, ui32Flags, ui32BufferCount, psDstSurfAttrib, psSrcSurfAttrib
 * ui32OEMFlags
 * out: phSwapChain, ppsSyncData, pui32SwapChainID
 */
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)
{
	struct OMAP_DISP_DEVINFO *psDevInfo;
	struct OMAP_DISP_SWAPCHAIN *psSwapChain;
	struct OMAP_DISP_BUFFER *psBuffer;
	struct OMAP_DISP_FLIP_ITEM *psFlipItems;
	IMG_UINT32 i;
	PVRSRV_ERROR eError;
	IMG_UINT32 ui32BuffersToSkip;
	struct omap_display_device *display;
	int err;

	if(!hDevice || !psDstSurfAttrib || !psSrcSurfAttrib ||
		!ppsSyncData || !phSwapChain)
	{
		ERROR_PRINTK("Invalid parameters");
		return PVRSRV_ERROR_INVALID_PARAMS;
	}
	psDevInfo = (struct OMAP_DISP_DEVINFO*)hDevice;

	if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0)
	{
		ERROR_PRINTK("Unable to operate with 0 MaxSwapChains for"
			" display %lu", psDevInfo->ulDeviceID);
		return PVRSRV_ERROR_NOT_SUPPORTED;
	}

	if(psDevInfo->psSwapChain != NULL)
	{
		ERROR_PRINTK("Swap chain already exists for"
			" display %lu", psDevInfo->ulDeviceID);
		return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
	}

	if(ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
	{
		ERROR_PRINTK("Too many buffers. Trying to use %u buffers while"
			" there is only %u available for display %lu",
			(unsigned int)ui32BufferCount,
			(unsigned int)psDevInfo->
			sDisplayInfo.ui32MaxSwapChainBuffers,
			psDevInfo->ulDeviceID);
		return PVRSRV_ERROR_TOOMANYBUFFERS;
	}

	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))
	{
		ERROR_PRINTK("Destination surface attributes differ from the"
			" current framebuffer for display %lu",
			psDevInfo->ulDeviceID);
		return PVRSRV_ERROR_INVALID_PARAMS;
	}

	if((psDstSurfAttrib->pixelformat !=
		psSrcSurfAttrib->pixelformat) ||
		(psDstSurfAttrib->sDims.ui32ByteStride !=
		psSrcSurfAttrib->sDims.ui32ByteStride) ||
		(psDstSurfAttrib->sDims.ui32Width !=
		psSrcSurfAttrib->sDims.ui32Width) ||
		(psDstSurfAttrib->sDims.ui32Height !=
		psSrcSurfAttrib->sDims.ui32Height))
	{
		ERROR_PRINTK("Destination surface attributes differ from the"
			" target destination surface for display %lu",
			psDevInfo->ulDeviceID);
		return PVRSRV_ERROR_INVALID_PARAMS;
	}

	/* Create the flip chain in display side */
	display = psDevInfo->display;
	/* TODO: What about TILER buffers? */
	/*
	 * Creating the flip chain with the maximum number of buffers
	 * we will decide which ones will be used later
	 */
	err = display->create_flip_chain(
		display, psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers);
	if(err)
	{
		ERROR_PRINTK("Unable to create the flip chain for '%s' display"
			" id %lu", display->name, psDevInfo->ulDeviceID);
		return PVRSRV_ERROR_INVALID_PARAMS;
	}

	/* Allocate memory needed for the swap chain */
	psSwapChain = (struct OMAP_DISP_SWAPCHAIN*) kmalloc(
		sizeof(struct OMAP_DISP_SWAPCHAIN), GFP_KERNEL);
	if(!psSwapChain)
	{
		ERROR_PRINTK("Out of memory to allocate swap chain for"
			" display %lu", psDevInfo->ulDeviceID);
		return PVRSRV_ERROR_OUT_OF_MEMORY;
	}

	DEBUG_PRINTK("Creating swap chain for display %lu",
		psDevInfo->ulDeviceID );

	/* Allocate memory for the buffer abstraction structures */
	psBuffer = (struct OMAP_DISP_BUFFER*) kmalloc(
		sizeof(struct OMAP_DISP_BUFFER) * ui32BufferCount, GFP_KERNEL);
	if(!psBuffer)
	{
		ERROR_PRINTK("Out of memory to allocate the buffer"
			" abstraction structures for display %lu",
			psDevInfo->ulDeviceID);
		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
		goto ErrorFreeSwapChain;
	}

	/* Allocate memory for the flip item abstraction structures */
	psFlipItems = (struct OMAP_DISP_FLIP_ITEM *) kmalloc (
		sizeof(struct OMAP_DISP_FLIP_ITEM) * ui32BufferCount,
		GFP_KERNEL);
	if (!psFlipItems)
	{
		ERROR_PRINTK("Out of memory to allocate the flip item"
			" abstraction structures for display %lu",
			psDevInfo->ulDeviceID);
		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
		goto ErrorFreeBuffers;
	}

	/* Assign to the swap chain structure the initial data */
	psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount;
	psSwapChain->psBuffer = psBuffer;
	psSwapChain->psFlipItems = psFlipItems;
	psSwapChain->ulInsertIndex = 0;
	psSwapChain->ulRemoveIndex = 0;
	psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable;
	psSwapChain->pvDevInfo = (void*)psDevInfo;

	/*
	 * Init the workqueue (single thread, freezable and real time)
	 * and its own work for this display
	 */
	INIT_WORK(&psDevInfo->sync_display_work, display_sync_handler);
	psDevInfo->sync_display_wq =
		__create_workqueue("pvr_display_sync_wq", 1, 1, 1);

	DEBUG_PRINTK("Swap chain will have %u buffers for display %lu",
		(unsigned int)ui32BufferCount, psDevInfo->ulDeviceID);
	/* Link the buffers available like a circular list */
	for(i=0; i<ui32BufferCount-1; i++)
	{
		psBuffer[i].psNext = &psBuffer[i+1];
	}
	psBuffer[i].psNext = &psBuffer[0];

	/* Initialize each buffer abstraction structure */
	for(i=0; i<ui32BufferCount; i++)
	{
		/* Get the needed buffers from the display flip chain */
		IMG_UINT32 ui32SwapBuffer = i + ui32BuffersToSkip;
		struct omap_display_buffer * flip_buffer =
			display->flip_chain->buffers[ui32SwapBuffer];
		psBuffer[i].display_buffer = flip_buffer;
		psBuffer[i].psSyncData = ppsSyncData[i];
		psBuffer[i].sSysAddr.uiAddr = flip_buffer->physical_addr;
		psBuffer[i].sCPUVAddr =
			(IMG_CPU_VIRTADDR) flip_buffer->virtual_addr;
		DEBUG_PRINTK("Display %lu buffer index %u has physical "
			"address 0x%x",
			psDevInfo->ulDeviceID,
			(unsigned int)i,
			(unsigned int)psBuffer[i].sSysAddr.uiAddr);
	}

	/* Initialize each flip item abstraction structure */
	for(i=0; i<ui32BufferCount; i++)
	{
		psFlipItems[i].bValid = OMAP_FALSE;
		psFlipItems[i].bFlipped = OMAP_FALSE;
		psFlipItems[i].bCmdCompleted = OMAP_FALSE;
		psFlipItems[i].display_buffer = 0;
	}

	mutex_lock(&psDevInfo->sSwapChainLockMutex);

	psDevInfo->psSwapChain = psSwapChain;
	psSwapChain->bFlushCommands = psDevInfo->bFlushCommands;
	if (psSwapChain->bFlushCommands)
		psSwapChain->ulSetFlushStateRefCount = 1;
	else
		psSwapChain->ulSetFlushStateRefCount = 0;

	mutex_unlock(&psDevInfo->sSwapChainLockMutex);

	*phSwapChain = (IMG_HANDLE)psSwapChain;

	return PVRSRV_OK;

ErrorFreeBuffers:
	kfree(psBuffer);
ErrorFreeSwapChain:
	kfree(psSwapChain);

	return eError;
}