/*
 * Driver init function
 */
static int __init OMAPLFB_Init(void)
{
#if defined(LDM_PLATFORM)
	DEBUG_PRINTK("Registering platform driver");
	if (platform_driver_register(&omaplfb_driver))
		return -ENODEV;
#if 0
	DEBUG_PRINTK("Registering device driver");
	if (platform_device_register(&omaplfb_device))
	{
		WARNING_PRINTK("Unable to register platform device");
		platform_driver_unregister(&omaplfb_driver);
		if(OMAPLFBDeinit() != OMAP_OK)
			WARNING_PRINTK("Driver cleanup failed\n");
		return -ENODEV;
	}
#endif

#if defined(SGX_EARLYSUSPEND) && defined(CONFIG_HAS_EARLYSUSPEND)
	register_early_suspend(&omaplfb_early_suspend);
	DEBUG_PRINTK("Registered early suspend support");
#endif

#endif
	return 0;
}
/*
 * Driver init function
 */
static int __init omap_sgx_dc_init(void)
{
	if(create_display_devices() != OMAP_OK)
	{
		WARNING_PRINTK("Driver init failed");
		return -ENODEV;
	}

#if defined(LDM_PLATFORM)
	DEBUG_PRINTK("Registering platform driver");
	if (platform_driver_register(&omap_sgx_dc_driver))
	{
		WARNING_PRINTK("Unable to register platform driver");
		if(destroy_display_devices() != OMAP_OK)
			WARNING_PRINTK("Driver cleanup failed\n");
		return -ENODEV;
	}

#if defined(SGX_EARLYSUSPEND)
	driver_early_suspend.suspend = DriverSuspend_Entry;
        driver_early_suspend.resume = DriverResume_Entry;
        driver_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
        register_early_suspend(&driver_early_suspend);
	DEBUG_PRINTK("Registered early suspend support");
#endif

#endif
	return 0;
}
Beispiel #3
0
/*
 * Driver init function
 */
static int __init OMAPLFB_Init(void)
{
	int Major;
	if(OMAPLFBInit() != OMAP_OK)
	{
		WARNING_PRINTK("Driver init failed");
		return -ENODEV;
	}

#if defined(LDM_PLATFORM)
	DEBUG_PRINTK("Registering platform driver");
	if (platform_driver_register(&omaplfb_driver))
	{
		WARNING_PRINTK("Unable to register platform driver");
		if(OMAPLFBDeinit() != OMAP_OK)
			WARNING_PRINTK("Driver cleanup failed\n");
		return -ENODEV;
	}
	Major = register_chrdev(OMAPLFB_MAJOR,"omaplfb",&omaplfb_fops);
	if (Major < 0)
		printk("unable to get major  %d for fb devs!!!!\n", Major);

#if defined(SGX_EARLYSUSPEND)
	omaplfb_early_suspend.suspend = OMAPLFBDriverSuspend_Entry;
        omaplfb_early_suspend.resume = OMAPLFBDriverResume_Entry;
        //omaplfb_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;	
	omaplfb_early_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING;
        register_early_suspend(&omaplfb_early_suspend);
	DEBUG_PRINTK("Registered early suspend support");
#endif

#endif
	return 0;
}
/*
 * Driver exit function
 */
static IMG_VOID __exit omap_sgx_dc_deinit(IMG_VOID)
{
#if defined(LDM_PLATFORM)
	DEBUG_PRINTK("Removing platform driver");
	platform_driver_unregister(&omap_sgx_dc_driver);
#if defined(SGX_EARLYSUSPEND)
        unregister_early_suspend(&driver_early_suspend);
#endif
#endif
	if(destroy_display_devices() != OMAP_OK)
		WARNING_PRINTK("Driver cleanup failed");
}
/*
 * Closes the display.
 * in: hDevice
 */
static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE hDevice)
{
	struct OMAP_DISP_DEVINFO *psDevInfo =
		(struct OMAP_DISP_DEVINFO*) hDevice;
	struct omap_display_device *display = psDevInfo->display;

	if(display->close(display))
		WARNING_PRINTK("Unable to close properly display '%s'",
			display->name);

	return PVRSRV_OK;
}
Beispiel #6
0
/*
 * Present frame and synchronize with the display to prevent tearing
 * On DSI panels the sync function is used to handle FRAMEDONE IRQ
 * On DPI panels the wait_for_vsync is used to handle VSYNC IRQ
 * in: psDevInfo
 */
void OMAPLFBPresentSync(OMAPLFB_DEVINFO *psDevInfo,
	OMAPLFB_FLIP_ITEM *psFlipItem)
{
	struct fb_info *framebuffer = psDevInfo->psLINFBInfo;
	struct omapfb_info *ofbi = FB2OFB(framebuffer);
	struct omap_dss_device *display;
	struct omapfb2_device *fbdev = ofbi->fbdev;
	struct omap_dss_driver *driver;
	struct omap_overlay_manager *manager;
	int err = 1;

	omapfb_lock(fbdev);

// [email protected] Backup the Display device for using later [START]
#if defined(CONFIG_MACH_LGE_OMAP3)
	Prev_disp = display = fb2display(framebuffer);
#else
	display = fb2display(framebuffer);
#endif	
// [email protected] Backup the Display device for using later [END]
	/* The framebuffer doesn't have a display attached, just bail out */
	if (!display) {
		omapfb_unlock(fbdev);
		return;
	}

	driver = display->driver;
	manager = display->manager;

	if (driver && driver->sync &&
		driver->get_update_mode(display) == OMAP_DSS_UPDATE_MANUAL) {
		/* Wait first for the DSI bus to be released then update */
		err = driver->sync(display);
		OMAPLFBFlipNoLock(psDevInfo->psSwapChain,
			(unsigned long)psFlipItem->sSysAddr->uiAddr);
	} else if (manager && manager->wait_for_vsync) {
		/*
		 * Update the video pipelines registers then wait until the
		 * frame is shown with a VSYNC
		 */
		OMAPLFBFlipNoLock(psDevInfo->psSwapChain,
			(unsigned long)psFlipItem->sSysAddr->uiAddr);
		err = manager->wait_for_vsync(manager);
	}

	if (err)
		WARNING_PRINTK("Unable to sync with display %u!",
			psDevInfo->uDeviceID);

	omapfb_unlock(fbdev);
}
Beispiel #7
0
/*
 * Driver exit function
 */
static IMG_VOID __exit OMAPLFB_Cleanup(IMG_VOID)
{    
	/* Unregister the device */
	 unregister_chrdev(OMAPLFB_MAJOR, "omaplfb");
#if defined(LDM_PLATFORM)
	DEBUG_PRINTK("Removing platform driver");
	platform_driver_unregister(&omaplfb_driver);
#if defined(SGX_EARLYSUSPEND)
        unregister_early_suspend(&omaplfb_early_suspend);
#endif
#endif
	if(OMAPLFBDeinit() != OMAP_OK)
		WARNING_PRINTK("Driver cleanup failed");
}
static int omaplfb_remove(struct platform_device *pdev)
{
	struct omaplfb_device *odev;

	odev = platform_get_drvdata(pdev);

	omaplfb_remove_sysfs(odev);

	if (OMAPLFBDeinit() != OMAP_OK)
		WARNING_PRINTK("Driver cleanup failed");

	kfree(odev);

	return 0;
}
/*
 * Opens the display.
 * in: ui32DeviceID, phDevice
 * out: psSystemBufferSyncData
 */
static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 ui32DeviceID,
                                 IMG_HANDLE *phDevice,
                                 PVRSRV_SYNC_DATA* psSystemBufferSyncData)
{
	struct OMAP_DISP_DEVINFO *psDevInfo;
	struct omap_display_device *display;
	int i;

	psDevInfo = 0;
	for(i = 0; i < display_devices_count; i++)
	{
		if(ui32DeviceID == (&pDisplayDevices[i])->ulDeviceID)
		{
			psDevInfo = &pDisplayDevices[i];
			break;
		}
	}

	if(!psDevInfo)
	{
		WARNING_PRINTK("Unable to identify display device with id %i",
			(int)ui32DeviceID);
		return OMAP_ERROR_INVALID_DEVICE;
	}

	psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
	display = psDevInfo->display;

	DEBUG_PRINTK("Opening display %lu '%s'",psDevInfo->ulDeviceID,
		display->name);

	/* TODO: Explain here why ORIENTATION_VERTICAL is used*/
	if(display->open(display, ORIENTATION_VERTICAL | ORIENTATION_INVERT))
		ERROR_PRINTK("Unable to open properly display '%s'",
			psDevInfo->display->name);

	display->present_buffer(display->main_buffer);

	/* TODO: Turn on display here? */

	*phDevice = (IMG_HANDLE)psDevInfo;

	return PVRSRV_OK;
}
Beispiel #10
0
/*
 * Synchronize with the display to prevent tearing
 * On DSI panels the display->sync function is used to handle FRAMEDONE IRQ
 * On DPI panels the display->wait_vsync is used to handle VSYNC IRQ
 * in: psDevInfo
 */
void OMAPLFBPresentSync(OMAPLFB_DEVINFO *psDevInfo,
	OMAPLFB_FLIP_ITEM *psFlipItem)
{
	struct fb_info * framebuffer = psDevInfo->psLINFBInfo;
	struct omapfb_info *ofbi = FB2OFB(framebuffer);
	struct omapfb2_device *fbdev = ofbi->fbdev;
	struct omap_dss_device *display;
	int err = 1;

	omapfb_lock(fbdev);

	display = fb2display(framebuffer);

	/* The framebuffer doesn't have a display attached, just bail out */
	if (!display) {
		omapfb_unlock(fbdev);
		return;
	}

	if (display->sync &&
		display->get_update_mode(display) == OMAP_DSS_UPDATE_MANUAL) {
		/* Wait first for the DSI bus to be released then update */
		err = display->sync(display);
		OMAPLFBFlipNoLock(psDevInfo->psSwapChain,
			(unsigned long)psFlipItem->sSysAddr->uiAddr);
	} else if (display->wait_vsync) {
		/*
		 * Update the video pipelines registers then wait until the
		 * frame is shown with a VSYNC
		 */
		OMAPLFBFlipNoLock(psDevInfo->psSwapChain,
			(unsigned long)psFlipItem->sSysAddr->uiAddr);
		err = display->wait_vsync(display);
	}

	if (err)
		WARNING_PRINTK("Unable to sync with display %u!",
			psDevInfo->uDeviceID);

	omapfb_unlock(fbdev);
}
/*
 * Gets the available formats for the display.
 * in: hDevice
 * out: pui32NumFormats, psFormat
 */
static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE hDevice,
                                  IMG_UINT32 *pui32NumFormats,
                                  DISPLAY_FORMAT *psFormat)
{
	struct OMAP_DISP_DEVINFO *psDevInfo;
	if(!hDevice || !pui32NumFormats)
	{
		ERROR_PRINTK("Invalid parameters");
		return PVRSRV_ERROR_INVALID_PARAMS;
	}

	psDevInfo = (struct OMAP_DISP_DEVINFO*)hDevice;
	*pui32NumFormats = 1;

	if(psFormat)
		psFormat[0] = psDevInfo->sDisplayFormat;
	else
		WARNING_PRINTK("Display format is null for"
			" display %lu", psDevInfo->ulDeviceID);

	return PVRSRV_OK;
}
/*
 * Gets the available dimensions for the display.
 * in: hDevice, psFormat
 * out: pui32NumDims, psDim
 */
static PVRSRV_ERROR EnumDCDims(IMG_HANDLE hDevice,
                               DISPLAY_FORMAT *psFormat,
                               IMG_UINT32 *pui32NumDims,
                               DISPLAY_DIMS *psDim)
{
	struct OMAP_DISP_DEVINFO *psDevInfo;
	if(!hDevice || !psFormat || !pui32NumDims)
	{
		ERROR_PRINTK("Invalid parameters");
		return PVRSRV_ERROR_INVALID_PARAMS;
	}

	psDevInfo = (struct OMAP_DISP_DEVINFO*)hDevice;
	*pui32NumDims = 1;

	if(psDim)
		psDim[0] = psDevInfo->sDisplayDim;
	else
		WARNING_PRINTK("Display dimensions are null for"
			" display %lu", psDevInfo->ulDeviceID);

	return PVRSRV_OK;
}
/*
 * Sets the display state.
 * in: ui32State, hDevice
 */
static IMG_VOID SetDCState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
{
	struct OMAP_DISP_DEVINFO *psDevInfo =
		(struct OMAP_DISP_DEVINFO*) hDevice;

	switch (ui32State)
	{
		case DC_STATE_FLUSH_COMMANDS:
			DEBUG_PRINTK("Setting state to flush commands for"
				" display %lu", psDevInfo->ulDeviceID);
			SetFlushStateExternal(psDevInfo, OMAP_TRUE);
			break;
		case DC_STATE_NO_FLUSH_COMMANDS:
			DEBUG_PRINTK("Setting state to not flush commands for"
				" display %lu", psDevInfo->ulDeviceID);
			SetFlushStateExternal(psDevInfo, OMAP_FALSE);
			break;
		default:
			WARNING_PRINTK("Unknown command state %u for display"
				" %lu", (unsigned int)ui32State,
				psDevInfo->ulDeviceID);
			break;
	}
}
/*
 * Performs a flip. This function takes the necessary steps to present
 * the buffer to be flipped in the display.
 * in: hCmdCookie, ui32DataSize, pvData
 */
static IMG_BOOL ProcessFlip(IMG_HANDLE  hCmdCookie,
                            IMG_UINT32  ui32DataSize,
                            IMG_VOID   *pvData)
{
	DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
	struct OMAP_DISP_DEVINFO *psDevInfo;
	struct OMAP_DISP_BUFFER *psBuffer;
	struct OMAP_DISP_SWAPCHAIN *psSwapChain;
	struct omap_display_device *display;
#if defined(SYS_USING_INTERRUPTS)
	struct OMAP_DISP_FLIP_ITEM* psFlipItem;
#endif

	if(!hCmdCookie || !pvData)
	{
		WARNING_PRINTK("Ignoring call with NULL parameters");
		return IMG_FALSE;
	}

	psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)pvData;

	if (psFlipCmd == IMG_NULL ||
		sizeof(DISPLAYCLASS_FLIP_COMMAND) != ui32DataSize)
	{
		WARNING_PRINTK("NULL command or command data size is wrong");
		return IMG_FALSE;
	}

	psDevInfo = (struct OMAP_DISP_DEVINFO*)psFlipCmd->hExtDevice;
	psBuffer = (struct OMAP_DISP_BUFFER*)psFlipCmd->hExtBuffer;
	psSwapChain = (struct OMAP_DISP_SWAPCHAIN*) psFlipCmd->hExtSwapChain;
	display = psDevInfo->display;

	mutex_lock(&psDevInfo->sSwapChainLockMutex);

	if (psDevInfo->bDeviceSuspended)
	{
		/* If is suspended then assume the commands are completed */
		psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(
			hCmdCookie, IMG_TRUE);
		goto ExitTrueUnlock;
	}

#if defined(SYS_USING_INTERRUPTS)

	if( psFlipCmd->ui32SwapInterval == 0 ||
		psSwapChain->bFlushCommands == OMAP_TRUE)
	{
#endif
		display->present_buffer(psBuffer->display_buffer);
		psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(
			hCmdCookie, IMG_TRUE);

#if defined(SYS_USING_INTERRUPTS)
		goto ExitTrueUnlock;
	}

	psFlipItem = &psSwapChain->psFlipItems[psSwapChain->ulInsertIndex];

	if(psFlipItem->bValid == OMAP_FALSE)
	{
		unsigned long ulMaxIndex = psSwapChain->ulBufferCount - 1;

		psFlipItem->bFlipped = OMAP_FALSE;

		/*
		 * The buffer is queued here, must be consumed by the workqueue
		 */
		psFlipItem->hCmdComplete = (OMAP_HANDLE)hCmdCookie;
		psFlipItem->ulSwapInterval =
			(unsigned long)psFlipCmd->ui32SwapInterval;
		psFlipItem->sSysAddr = &psBuffer->sSysAddr;
		psFlipItem->bValid = OMAP_TRUE;
		psFlipItem->display_buffer = psBuffer->display_buffer;

		psSwapChain->ulInsertIndex++;
		if(psSwapChain->ulInsertIndex > ulMaxIndex)
			psSwapChain->ulInsertIndex = 0;

		/* Give work to the workqueue to sync with the display */
		queue_work(psDevInfo->sync_display_wq,
			&psDevInfo->sync_display_work);

		goto ExitTrueUnlock;
	}

	mutex_unlock(&psDevInfo->sSwapChainLockMutex);
	return IMG_FALSE;
#endif

ExitTrueUnlock:
	mutex_unlock(&psDevInfo->sSwapChainLockMutex);
	return IMG_TRUE;
}
/*
 * Extracts the framebuffer data from the kernel driver
 * in: psDevInfo
 */
static enum OMAP_ERROR init_display_device(struct OMAP_DISP_DEVINFO *psDevInfo,
	struct omap_display_device *display)
{
	int buffers_available = display->buffers_available;

	/* Extract the needed data from the display struct */
	DEBUG_PRINTK("Display '%s' id %i information:", display->name,
		display->id);
	DEBUG_PRINTK("*Width, height: %u,%u", display->width,
		display->height);
	DEBUG_PRINTK("*Rotation: %u", display->rotation);
	DEBUG_PRINTK("*Stride: %u bytes", display->byte_stride);
	DEBUG_PRINTK("*Buffers available: %u", buffers_available);
	DEBUG_PRINTK("*Bytes per pixel: %u (%u bpp)",
		display->bytes_per_pixel, display->bits_per_pixel);

	if(display->bits_per_pixel == 16)
	{
		if(display->pixel_format == RGB_565)
		{
			DEBUG_PRINTK("*Format: RGB565");
			psDevInfo->sDisplayFormat.pixelformat =
				PVRSRV_PIXEL_FORMAT_RGB565;
		}
		else
			WARNING_PRINTK("*Format: Unknown framebuffer"
				"format");
	}
	else if(display->bits_per_pixel == 24 ||
		display->bits_per_pixel == 32)
	{
		if(display->pixel_format == ARGB_8888)
		{
			DEBUG_PRINTK("*Format: ARGB8888");
			psDevInfo->sDisplayFormat.pixelformat =
				PVRSRV_PIXEL_FORMAT_ARGB8888;

		}
		else
			WARNING_PRINTK("*Format: Unknown framebuffer"
				"format");
	}
	else
		WARNING_PRINTK("*Format: Unknown framebuffer format");

	if(display->main_buffer)
	{
		DEBUG_PRINTK("*Bytes per buffer: %lu",
			display->main_buffer->size);
		DEBUG_PRINTK("*Main buffer physical address: 0x%lx",
			display->main_buffer->physical_addr);
		DEBUG_PRINTK("*Main buffer virtual address: 0x%lx",
			display->main_buffer->virtual_addr);
		DEBUG_PRINTK("*Main buffer size: %lu bytes",
			display->main_buffer->size);
	}
	else
	{
		psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = 0;
		ERROR_PRINTK("*No main buffer found for display '%s'",
			display->name);
		return OMAP_ERROR_INIT_FAILURE;
	}

	psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = buffers_available;
	mutex_init(&psDevInfo->sSwapChainLockMutex);
	psDevInfo->psSwapChain = 0;
	psDevInfo->bFlushCommands = OMAP_FALSE;
	psDevInfo->bDeviceSuspended = OMAP_FALSE;

	if(psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers > 1)
	{
		if(MAX_BUFFERS_FLIPPING == 1)
		{
			DEBUG_PRINTK("Flipping support is possible"
				" but you decided not to use it");
		}

		DEBUG_PRINTK("*Flipping support");
		if(psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers >
			MAX_BUFFERS_FLIPPING)
		psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers =
			MAX_BUFFERS_FLIPPING;
	}
	else
	{
		DEBUG_PRINTK("*Flipping not supported");
	}

	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;

	/* Get the display and framebuffer needed info */
	strncpy(psDevInfo->sDisplayInfo.szDisplayName,
		DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);

	psDevInfo->sDisplayDim.ui32Width = display->width;
	psDevInfo->sDisplayDim.ui32Height = display->height;
	psDevInfo->sDisplayDim.ui32ByteStride = display->byte_stride;
	psDevInfo->sSystemBuffer.sSysAddr.uiAddr =
		display->main_buffer->physical_addr;
	psDevInfo->sSystemBuffer.sCPUVAddr =
		(IMG_CPU_VIRTADDR) display->main_buffer->virtual_addr;
	psDevInfo->sSystemBuffer.ulBufferSize = display->main_buffer->size;
	psDevInfo->display = display;

	return OMAP_OK;
}