Esempio n. 1
0
static int present_buffer_virtual(struct omap_display_buffer *buffer)
{
	/*
	 * TODO: Support for ORIENTATION_VERTICAL is in place,
	 * ORIENTATION_HORIZONTAL is missing
	 */
	struct omap_display_device *display_virtual = buffer->display;
	struct omap_display_device *display_primary;
	struct omap_display_device *display_secondary;
	struct omap_display_buffer temp_buffer;
	unsigned int buffer_offset;

	if (display_virtual->id != OMAP_DISPID_VIRTUAL) {
		ERR_PRINT("Not a virtual display");
		BUG();
	}

	display_primary = omap_display_get(OMAP_DISPID_PRIMARY);
	display_secondary = omap_display_get(OMAP_DISPID_SECONDARY);
	/*
	 * Calculate offset without page alignment round up otherwise second
	 * display may see incorrect data
	 */
	buffer_offset = display_primary->height * display_virtual->byte_stride;

	/* The first buffer will be the base */
	temp_buffer.physical_addr = buffer->physical_addr;
	temp_buffer.virtual_addr = buffer->virtual_addr;
	temp_buffer.size = buffer->size >> 1;

	if (display_virtual->features & ORIENTATION_INVERT) {
		/* Secondary display has the base */
		temp_buffer.display = display_secondary;
		display_secondary->present_buffer(&temp_buffer);
	} else {
		/* Primary display has the base */
		temp_buffer.display = display_primary;
		display_primary->present_buffer(&temp_buffer);
	}

	/* Remaining display will show the rest */
	temp_buffer.physical_addr = buffer->physical_addr + buffer_offset;
	temp_buffer.virtual_addr = buffer->virtual_addr + buffer_offset;

	if (display_virtual->features & ORIENTATION_INVERT) {
		temp_buffer.display = display_primary;
		display_primary->present_buffer(&temp_buffer);
	} else {
		temp_buffer.display = display_secondary;
		display_secondary->present_buffer(&temp_buffer);
	}

	return 0;
}
Esempio n. 2
0
static int display_sync_virtual(struct omap_display_device *display_virtual)
{
	/*
	 * XXX: This function only waits for the primary display it should
	 * be adapted to the customer needs since waiting for the primary
	 * AND the secondary display may take too long for a single sync.
	 */
	struct omap_display_device *display_primary;

	if (display_virtual->id != OMAP_DISPID_VIRTUAL) {
		ERR_PRINT("Not a virtual display");
		BUG();
	}

	display_primary = omap_display_get(OMAP_DISPID_PRIMARY);
	return display_primary->sync(display_primary);
}
/*
 *  Initialization routine for the 3rd party display driver
 */
static enum OMAP_ERROR create_display_devices(void)
{
	PFN_CMD_PROC pfnCmdProcList[OMAP_DC_CMD_COUNT];
	IMG_UINT32 aui32SyncCountList[OMAP_DC_CMD_COUNT][2];
	int i;
	unsigned int bytes_to_alloc;

	DEBUG_PRINTK("Initializing 3rd party display driver");

	/* Ask for the number of displays available */
	omap_display_init();
	/* TODO: allow more displays */
	display_devices_count = 1; // omap_display_count();

	DEBUG_PRINTK("Found %i displays", display_devices_count);

	/*
	 * Obtain the function pointer for the jump table from kernel
	 * services to fill it with the function pointers that we want
	 */
	if(get_pvr_dc_jtable ("PVRGetDisplayClassJTable",
		&pfnGetPVRJTable) != OMAP_OK)
	{
		ERROR_PRINTK("Unable to get the function to get the"
			" jump table display->services");
		return OMAP_ERROR_INIT_FAILURE;
	}

	/*
	 * Allocate the display device structures, one per display available
	 */
	bytes_to_alloc =
		sizeof(struct OMAP_DISP_DEVINFO) * display_devices_count;
	pDisplayDevices = (struct OMAP_DISP_DEVINFO *) kmalloc(
		bytes_to_alloc, GFP_KERNEL);
	if(!pDisplayDevices)
	{
		pDisplayDevices = NULL;
		ERROR_PRINTK("Out of memory");
		return OMAP_ERROR_OUT_OF_MEMORY;
	}
	memset(pDisplayDevices, 0, bytes_to_alloc);

	/*
	 * Initialize each display device
	 */
	for(i = 0; i < display_devices_count; i++)
	{
		struct omap_display_device *display;
		struct OMAP_DISP_DEVINFO * psDevInfo;
		enum omap_display_id id;

		psDevInfo = &pDisplayDevices[i];
		psDevInfo->display = 0;

		id = OMAP_DISPID_VIRTUAL;

		/*
		 * TODO: Modify this to allow primary, secondary,
		 * not only virtual
		 */
#if 0
		switch(i)
		{
			case 0:
				id = OMAP_DISPID_PRIMARY;
				break;
			case 1:
				id = OMAP_DISPID_SECONDARY;
				break;
			case 2:
				id = OMAP_DISPID_TERTIARY;
				break;
			case 3:
				id = OMAP_DISPID_VIRTUAL;
				break;
			default:
				ERROR_PRINTK("Invalid display type %i", i);
				BUG();
		}

#endif

		display = omap_display_get(id);
		if(!display)
			continue;

		if(init_display_device(psDevInfo, display) != OMAP_OK)
		{
			ERROR_PRINTK("Unable to initialize display '%s' type"
				" %u", display->name, display->id);
			continue;
#if 0
			kfree(pDisplayDevices);
			pDisplayDevices = NULL;
			return OMAP_ERROR_INIT_FAILURE;
#endif
		}

		/*
		 * Populate each display device structure
		*/
		if(!(*pfnGetPVRJTable)(&psDevInfo->sPVRJTable))
		{
			ERROR_PRINTK("Unable to get the jump table"
				" display->services for display '%s'",
				display->name);
			return OMAP_ERROR_INIT_FAILURE;
		}

		/* Populate the function table that services will use */
		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;

		/* Register the display device */
		if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice(
			&psDevInfo->sDCJTable,
			(IMG_UINT32*) &psDevInfo->ulDeviceID) != PVRSRV_OK)
		{
			ERROR_PRINTK("Unable to register the jump table"
				" services->display");
			return OMAP_ERROR_DEVICE_REGISTER_FAILED;
		}

		DEBUG_PRINTK("Display '%s' registered with the GPU with"
			" id %lu", display->name, psDevInfo->ulDeviceID);

		/*
		 * Register the ProcessFlip function to notify when a frame is
		 * ready to be flipped
		 */
		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, OMAP_DC_CMD_COUNT) != PVRSRV_OK)
		{
			ERROR_PRINTK("Unable to register callback for "
				"ProcessFlip command");
			return OMAP_ERROR_CANT_REGISTER_CALLBACK;
		}

	}
	return OMAP_OK;
}
Esempio n. 4
0
static int populate_virtual_display_info(struct omap_display_device *display)
{
	struct omap_display_device *display_primary ;
	struct omap_display_device *display_secondary;
	int i;

	display->id = OMAP_DISPID_VIRTUAL;
	display->name = "virtual";

	display_primary = omap_display_get(OMAP_DISPID_PRIMARY);
	display_secondary = omap_display_get(OMAP_DISPID_SECONDARY);

	if (!display_primary) {
		ERR_PRINT("Primary display doesn't exist");
		return 1;
	} else if (!display_secondary) {
		ERR_PRINT("Secondary display doesn't exist");
		return 1;
	}

	/* Combine primary and secondary display resolutions */
	if (display_primary->width != display_secondary->width ||
		display_primary->height != display_secondary->height) {
		ERR_PRINT("Primary and seconday displays resolution are not"
			" the same");
		return 1;
	}

	/*
	 * TODO: Here it is hardcoded the resolution asumming a vertical
	 * virtual config, what about horizontal?
	 */
	display->width = display_primary->width;
	display->height = display_primary->height * 2;

	if (display_primary->bits_per_pixel !=
		display_secondary->bits_per_pixel) {
		ERR_PRINT("Primary and seconday displays format are"
			" not the same");
		return 1;
	}

	display->bits_per_pixel = display_primary->bits_per_pixel;
	switch (display->bits_per_pixel) {
	case 16:
		/*
		 * TODO: Asume RGB_565, maybe need to double check in
		 * the DSS if this is true
		 */
		display->pixel_format = RGB_565;
		display->bytes_per_pixel = 2;
		break;
	case 24: /* 24 bits are encapsulated with 32 bits */
	case 32:
		/*
		 * TODO: Asume ARGB_8888, maybe need to double check in
		 * the DSS if this is true
		 */
		display->pixel_format = ARGB_8888;
		display->bytes_per_pixel = 4;
		break;
	default:
		ERR_PRINT("Unable to handle %i bpp",
			display->bits_per_pixel);
		return 1;
	}

	/* TODO: Asumming a vertical virtual config too for stride */
	display->byte_stride = display->bytes_per_pixel * display->width;
	display->rotation = OMAP_DSS_ROT_0; /* Asume rotation 0 degrees */
	display->main_buffer = 0;
	display->flip_chain = 0;

	/* Add the primary and secondary overlay managers */
	for (i = 0; i < OMAP_DISP_MAX_MANAGERS; i++)
		display->overlay_managers[i] = 0;

	display->overlay_managers[0] = display_primary->overlay_managers[0];
	display->overlay_managers[1] = display_secondary->overlay_managers[0];
	display->overlay_managers_count = 2;

	/* Assign function pointers for display operations */
	display->open = open_display;
	display->close = close_display;
	display->create_flip_chain = create_flip_chain;
	display->destroy_flip_chain = destroy_flip_chain;
	display->rotate = rotate_display;
	display->present_buffer = present_buffer_virtual;
	display->sync = display_sync_virtual;
	display->present_buffer_sync = present_buffer_sync_virtual;

	display->main_buffer = create_main_buffer(display);
	if (!display->main_buffer)
		WRN_PRINT("Failed to create main buffer for '%s'",
			display->name);

	display->buffers_available = get_max_buffers(display);

	/* Just print some display info */
	DBG_PRINT("Found display '%s' (%i,%i) %i bpp (%i bytes per pixel)"
		" rotation %i", display->name, display->width, display->height,
		display->bits_per_pixel, display->bytes_per_pixel,
		display->rotation);

	return 0;
}
Esempio n. 5
0
static int present_buffer_sync_virtual(struct omap_display_buffer *buffer)
{
	/*
	 * TODO: Support for ORIENTATION_VERTICAL is in place,
	 * ORIENTATION_HORIZONTAL is missing. Some code can be reduced here,
	 * it will be simplified in the future.
	 */
	struct omap_display_device *display_virtual = buffer->display;
	struct omap_display_device *display_primary;
	struct omap_display_device *display_secondary;
	struct omap_display_buffer temp_buffer_top;
	struct omap_display_buffer temp_buffer_bottom;
	unsigned int buffer_offset;

	if (display_virtual->id != OMAP_DISPID_VIRTUAL) {
		ERR_PRINT("Not a virtual display");
		BUG();
	}

	display_primary = omap_display_get(OMAP_DISPID_PRIMARY);
	display_secondary = omap_display_get(OMAP_DISPID_SECONDARY);
	/*
	 * Calculate offset without page alignment round up otherwise second
	 * display may see incorrect data
	 */
	buffer_offset = display_primary->height * display_virtual->byte_stride;

	/* The first buffer will be the top */
	temp_buffer_top.physical_addr = buffer->physical_addr;
	temp_buffer_top.virtual_addr = buffer->virtual_addr;
	temp_buffer_top.size = buffer->size >> 1;
	/* Then the bottom */
	temp_buffer_bottom.physical_addr = buffer->physical_addr +
		buffer_offset;
	temp_buffer_bottom.virtual_addr = buffer->virtual_addr + buffer_offset;
	temp_buffer_bottom.size = buffer->size >> 1;

	if (display_virtual->features & ORIENTATION_INVERT) {
		/* Secondary display has the base */
		temp_buffer_top.display = display_secondary;
		temp_buffer_bottom.display = display_primary;
		vdisp_sync_primary.buffer = &temp_buffer_bottom;
		vdisp_sync_secondary.buffer = &temp_buffer_top;
	} else {
		/* Primary display has the base */
		temp_buffer_top.display = display_primary;
		temp_buffer_bottom.display = display_secondary;
		vdisp_sync_primary.buffer = &temp_buffer_top;
		vdisp_sync_secondary.buffer = &temp_buffer_bottom;
	}

	/* Launch the workqueues for each display to present independently */
	queue_work(vdisp_wq_primary,
		(struct work_struct *)&vdisp_sync_primary);
	queue_work(vdisp_wq_secondary,
		(struct work_struct *)&vdisp_sync_secondary);

	/* Wait until each display sync and present */
	flush_workqueue(vdisp_wq_primary);
	flush_workqueue(vdisp_wq_secondary);

	return 0;
}