예제 #1
0
/*
 * Presents the flip in the display with the framebuffer API
 * in: psSwapChain, aPhyAddr
 */
static void OMAPLFBFlipNoLock(OMAPLFB_SWAPCHAIN *psSwapChain,
	unsigned long aPhyAddr)
{
	OMAPLFB_DEVINFO	*psDevInfo = (OMAPLFB_DEVINFO *)psSwapChain->pvDevInfo;
	struct fb_info * framebuffer = psDevInfo->psLINFBInfo;

	/* Get the framebuffer physical address base */
	unsigned long fb_base_phyaddr =
		psDevInfo->sSystemBuffer.sSysAddr.uiAddr;

	/* Calculate the virtual Y to move in the framebuffer */
	framebuffer->var.yoffset =
		(aPhyAddr - fb_base_phyaddr) / framebuffer->fix.line_length;
	framebuffer->var.activate = FB_ACTIVATE_FORCE;
	fb_set_var(framebuffer, &framebuffer->var);
}
예제 #2
0
void fb_init(void)
{
    Debug("fb_init()\n");
    fb_open();
    fb_get_var();
    memcpy(&saved_var, &fb_var, sizeof(struct fb_var_screeninfo));
    //saved_var = fb_var;
    if (fb_var.xoffset || fb_var.yoffset || fb_var.accel_flags) {
	fb_var.xoffset = 0;
	fb_var.yoffset = 0;
	fb_var.accel_flags = 0;
	fb_set_var();
    }
    fb_get_fix();
    var_fix_validate();
    memcpy(&saved_fix, &fb_fix, sizeof(struct fb_var_screeninfo));
    //saved_fix = fb_fix;
    switch (fb_fix.visual) {
	case FB_VISUAL_MONO01:
	case FB_VISUAL_MONO10:
	case FB_VISUAL_TRUECOLOR:
	    /* no colormap */
	    break;

	case FB_VISUAL_PSEUDOCOLOR:
	case FB_VISUAL_STATIC_PSEUDOCOLOR:
	    cmap_init(1<<fb_var.bits_per_pixel);
	    break;

	case FB_VISUAL_DIRECTCOLOR:
	    cmap_init(1<<(max(max(fb_var.red.length, fb_var.green.length),
			      max(fb_var.blue.length, fb_var.transp.length))));
	    break;
    }
    if (fb_cmap.len) {
	fb_get_cmap();
	saved_cmap = fb_cmap;
	ALLOC_AND_SAVE_COMPONENT(red);
	ALLOC_AND_SAVE_COMPONENT(green);
	ALLOC_AND_SAVE_COMPONENT(blue);
	if (fb_cmap.transp)
	    ALLOC_AND_SAVE_COMPONENT(transp);
    }
    fb_map();
    fb_save();
    fb_clear();
}
예제 #3
0
static IMG_VOID S3C_Flip(S3C_LCD_DEVINFO  *psDevInfo,
					   S3C_FRAME_BUFFER *fb)
{
	struct fb_var_screeninfo sFBVar;
	int res;
	unsigned long ulYResVirtual;

	S3C_CONSOLE_LOCK();

	sFBVar = psDevInfo->psFBInfo->var;

	sFBVar.xoffset = 0;
	sFBVar.yoffset = fb->yoffset;

	ulYResVirtual = fb->yoffset + sFBVar.yres;

	if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual)
	{
		sFBVar.xres_virtual = sFBVar.xres;
		sFBVar.yres_virtual = ulYResVirtual;

		sFBVar.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;

		res = fb_set_var(psDevInfo->psFBInfo, &sFBVar);
		if (res != 0)
		{
			printk("%s: fb_set_var failed (Y Offset: %d, Error: %d)\n", __FUNCTION__, fb->yoffset, res);	}
	}
	else
	{
		res = fb_pan_display(psDevInfo->psFBInfo, &sFBVar);
		if (res != 0)
		{
			printk( "%s: fb_pan_display failed (Y Offset: %d, Error: %d)\n", __FUNCTION__, fb->yoffset, res);
		}
	}

	if (gPVRPanDisplaySignal) {
		psDevInfo->sPVRJTable.pfnPVRSRVOEMFunction(
			OEM_COMPLETE_PREPARE_DISPLAY,
			&(fb->yoffset), sizeof(int),
			IMG_NULL, 0);
	}

	S3C_CONSOLE_UNLOCK();
}
예제 #4
0
static void lcd_init_fb(struct fb_info *info)
{
	struct fb_var_screeninfo var;

	memset(&var, 0, sizeof(var));

	fb_videomode_to_var(&var, &video_modes[0]);

	var.activate = FB_ACTIVATE_ALL;
	var.yres_virtual = var.yres * 3;

	acquire_console_sem();
	info->flags |= FBINFO_MISC_USEREVENT;
	fb_set_var(info, &var);
	info->flags &= ~FBINFO_MISC_USEREVENT;
	release_console_sem();
}
예제 #5
0
/* Flip display to given buffer */
void XBLFBFlip(XBLFB_DEVINFO *psDevInfo, XBLFB_BUFFER *psBuffer)
{
	struct fb_var_screeninfo sFBVar;
	int res;
	unsigned long ulYResVirtual;

	XBLFB_CONSOLE_LOCK();

	sFBVar = psDevInfo->psLINFBInfo->var;

	sFBVar.xoffset = 0;
	sFBVar.yoffset = psBuffer->ulYOffset;

	ulYResVirtual = psBuffer->ulYOffset + sFBVar.yres;

#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
	
	if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual)
#endif 
	{
		sFBVar.xres_virtual = sFBVar.xres;
		sFBVar.yres_virtual = ulYResVirtual;

		sFBVar.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;

		res = fb_set_var(psDevInfo->psLINFBInfo, &sFBVar);
		if (res != 0)
		{
			printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
		}
	}
#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
	else
	{
		res = fb_pan_display(psDevInfo->psLINFBInfo, &sFBVar);
                //                printk("fb_pan_display-----------------------\n");
                
		if (res != 0)
		{
                    printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
		}
	}
#endif 

	XBLFB_CONSOLE_UNLOCK();
}
예제 #6
0
static void lcd_init_fb(struct fb_info *info)
{
	struct fb_var_screeninfo var;

	memset(&var, 0, sizeof(var));

	fb_videomode_to_var(&var, &mode);

	var.activate = FB_ACTIVATE_ALL;

	acquire_console_sem();
	info->flags |= FBINFO_MISC_USEREVENT;
	fb_set_var(info, &var);
	fb_blank(info, FB_BLANK_UNBLANK);
	info->flags &= ~FBINFO_MISC_USEREVENT;
	release_console_sem();
}
예제 #7
0
void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer)
{
	struct fb_var_screeninfo sFBVar;
	int res;
	unsigned long ulYResVirtual;

	acquire_console_sem();

	sFBVar = psDevInfo->psLINFBInfo->var;

	sFBVar.xoffset = 0;
	sFBVar.yoffset = psBuffer->ulYOffset;

	ulYResVirtual = psBuffer->ulYOffset + sFBVar.yres;

	
	if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual)
	{
		sFBVar.xres_virtual = sFBVar.xres;
		sFBVar.yres_virtual = ulYResVirtual;

		sFBVar.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;

		res = fb_set_var(psDevInfo->psLINFBInfo, &sFBVar);
		if (res != 0)
		{
			printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
		}
	}
	else
	{
		res = fb_pan_display(psDevInfo->psLINFBInfo, &sFBVar);
		if (res != 0)
		{
                        printk (" fb_pan api failed \n");
			printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
		}
	}

	release_console_sem();
}
static void lcd_init_fb(struct fb_info *info)
{
	struct fb_var_screeninfo var;

	memset(&var, 0, sizeof(var));

	fb_videomode_to_var(&var, &video_modes[0]);

	if (machine_is_mx31_3ds()) {
		var.upper_margin = 0;
		var.left_margin = 0;
	}

	var.activate = FB_ACTIVATE_ALL;
	var.yres_virtual = var.yres * 2;

	acquire_console_sem();
	info->flags |= FBINFO_MISC_USEREVENT;
	fb_set_var(info, &var);
	info->flags &= ~FBINFO_MISC_USEREVENT;
	release_console_sem();
}
static IMG_VOID S3C_Flip(S3C_LCD_DEVINFO  *psDevInfo,
					   S3C_FRAME_BUFFER *fb)
{
	struct fb_var_screeninfo sFBVar;
	int res;
	unsigned long ulYResVirtual;

	acquire_console_sem();

	sFBVar = psDevInfo->psFBInfo->var;

	sFBVar.xoffset = 0;
	sFBVar.yoffset = fb->yoffset;

	ulYResVirtual = fb->yoffset + sFBVar.yres;

	if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual)
	{
		sFBVar.xres_virtual = sFBVar.xres;
		sFBVar.yres_virtual = ulYResVirtual;

		sFBVar.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;

		res = fb_set_var(psDevInfo->psFBInfo, &sFBVar);
		if (res != 0)
		{
			printk("%s: fb_set_var failed (Y Offset: %d, Error: %d)\n", __FUNCTION__, fb->yoffset, res);	}
	}
	else
	{
		res = fb_pan_display(psDevInfo->psFBInfo, &sFBVar);
		if (res != 0)
		{
			printk( "%s: fb_pan_display failed (Y Offset: %d, Error: %d)\n", __FUNCTION__, fb->yoffset, res);
		}
	}

	release_console_sem();
}
예제 #10
0
static void sh_mobile_fb_reconfig(struct fb_info *info)
{
	struct sh_mobile_lcdc_chan *ch = info->par;
	struct fb_videomode mode1, mode2;
	struct fb_event event;
	int evnt = FB_EVENT_MODE_CHANGE_ALL;

	if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par))
		/* More framebuffer users are active */
		return;

	fb_var_to_videomode(&mode1, &ch->display_var);
	fb_var_to_videomode(&mode2, &info->var);

	if (fb_mode_is_equal(&mode1, &mode2))
		return;

	/* Display has been re-plugged, framebuffer is free now, reconfigure */
	if (fb_set_var(info, &ch->display_var) < 0)
		/* Couldn't reconfigure, hopefully, can continue as before */
		return;

	if (info->var.nonstd)
		info->fix.line_length = mode1.xres;
	else
		info->fix.line_length = mode1.xres * (ch->cfg.bpp / 8);

	/*
	 * fb_set_var() calls the notifier change internally, only if
	 * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a
	 * user event, we have to call the chain ourselves.
	 */
	event.info = info;
	event.data = &mode1;
	fb_notifier_call_chain(evnt, &event);
}
예제 #11
0
static
void DC_FBDEV_ContextConfigure(IMG_HANDLE hDisplayContext,
								   IMG_UINT32 ui32PipeCount,
								   PVRSRV_SURFACE_CONFIG_INFO *pasSurfAttrib,
								   IMG_HANDLE *ahBuffers,
								   IMG_UINT32 ui32DisplayPeriod,
								   IMG_HANDLE hConfigData)
{
	DC_FBDEV_CONTEXT *psDeviceContext = hDisplayContext;
	DC_FBDEV_DEVICE *psDeviceData = psDeviceContext->psDeviceData;
	struct fb_var_screeninfo sVar = psDeviceData->psLINFBInfo->var;
	int err;

	PVR_UNREFERENCED_PARAMETER(ui32PipeCount);
	PVR_UNREFERENCED_PARAMETER(pasSurfAttrib);
	PVR_UNREFERENCED_PARAMETER(ui32DisplayPeriod);

	if(psDeviceContext->hLastConfigData)
		DCDisplayConfigurationRetired(psDeviceContext->hLastConfigData);

	sVar.yoffset = 0;

	if(ui32PipeCount == 0)
	{
		/* If the pipe count is zero, we're tearing down. Don't record
		 * any new configurations, but still allow the display to pan
		 * back to buffer 0.
		 */
		psDeviceContext->hLastConfigData = IMG_NULL;

		/*
			We still need to "retire" this NULL flip as that signals back to
			the DC core that we've finished doing what we need to do
			and it can destroy the display context
		*/
		DCDisplayConfigurationRetired(hConfigData);
	}
	else
	{
		BUG_ON(ahBuffers == IMG_NULL);

		if(psDeviceData->bCanFlip)
		{
			DC_FBDEV_BUFFER *psBuffer = ahBuffers[0];
			sVar.yoffset = sVar.yres * psBuffer->ui32BufferID;
		}

		psDeviceContext->hLastConfigData = hConfigData;
	}

	/* MTK: set BGRA */
	sVar.bits_per_pixel = 32;
	sVar.transp.offset  = 24;
	sVar.transp.length  = 8;
	sVar.red.offset     = 16;
	sVar.red.length     = 8;
	sVar.green.offset   = 8;
	sVar.green.length   = 8;
	sVar.blue.offset    = 0;
	sVar.blue.length    = 8;

	if(lock_fb_info(psDeviceData->psLINFBInfo))
	{
		console_lock();

		/* If we're supposed to be able to flip, but the yres_virtual
		 * has been changed to an unsupported (smaller) value, we need
		 * to change it back (this is a workaround for some Linux fbdev
		 * drivers that seem to lose any modifications to yres_virtual
		 * after a blank.)
		 */
		if(psDeviceData->bCanFlip &&
		   sVar.yres_virtual < sVar.yres * NUM_PREFERRED_BUFFERS)
		{
			sVar.activate = FB_ACTIVATE_NOW;
			sVar.yres_virtual = sVar.yres * NUM_PREFERRED_BUFFERS;

			err = fb_set_var(psDeviceData->psLINFBInfo, &sVar);
			if(err)
				pr_err("fb_set_var failed (err=%d)\n", err);
		}
		else
		{
			err = fb_pan_display(psDeviceData->psLINFBInfo, &sVar);
			if(err)
				pr_err("fb_pan_display failed (err=%d)\n", err);
		}

		console_unlock();
		unlock_fb_info(psDeviceData->psLINFBInfo);
	}
}
/* Flip display to given buffer */
void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer)
{
	struct fb_var_screeninfo sFBVar;
	int res;

	OMAPLFB_CONSOLE_LOCK();

	sFBVar = psDevInfo->psLINFBInfo->var;

	sFBVar.xoffset = 0;
	sFBVar.yoffset = psBuffer->ulYOffset;

#if defined(CONFIG_DSSCOMP)
	/*
	 * If flipping to a NULL buffer, blank the screen to prevent
	 * warnings/errors from the display subsystem.
	 */
	if (psBuffer->sSysAddr.uiAddr == 0)
	{
		struct omap_dss_device *psDSSDev = fb2display(psDevInfo->psLINFBInfo);
		OMAP_DSS_MANAGER(psDSSMan, psDSSDev);

		if (psDSSMan != NULL && psDSSMan->blank != NULL)
		{
			res = psDSSMan->blank(psDSSMan, false);
			if (res != 0)
			{
				DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: DSS manager blank call failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res));
			}
		}
	}

	{
		/*
		 * If using DSSCOMP, we need to use dsscomp queuing for normal
		 * framebuffer updates, so that previously used overlays get
		 * automatically disabled, and manager gets dirtied.  We can
		 * do that because DSSCOMP takes ownership of all pipelines on
		 * a manager.
		 */
		struct fb_fix_screeninfo sFBFix = psDevInfo->psLINFBInfo->fix;
		struct dsscomp_setup_dispc_data d =
		{
			.num_ovls = 1,
			.num_mgrs = 1,
			.mgrs[0].alpha_blending = 1,
			.ovls[0] =
			{
				.cfg =
				{
					.win.w = sFBVar.xres,
					.win.h = sFBVar.yres,
					.crop.x = sFBVar.xoffset,
					.crop.y = sFBVar.yoffset,
					.crop.w = sFBVar.xres,
					.crop.h = sFBVar.yres,
					.width = sFBVar.xres_virtual,
					.height = sFBVar.yres_virtual,
					.stride = sFBFix.line_length,
					.enabled = (psBuffer->sSysAddr.uiAddr != 0),
					.global_alpha = 255,
				},
			},
		};

		/* do not map buffer into TILER1D as it is contiguous */
		struct tiler_pa_info *pas[] = { NULL };

		d.ovls[0].ba = (u32) psBuffer->sSysAddr.uiAddr;

		omapfb_mode_to_dss_mode(&sFBVar, &d.ovls[0].cfg.color_mode);

		res = dsscomp_gralloc_queue(&d, pas, true, NULL, NULL);
		if (res != 0)
		{
			DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX ": %s: Device %u: dsscomp_gralloc_queue failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res));
		}
	}
#else /* defined(CONFIG_DSSCOMP) */
	{
		unsigned long ulYResVirtual = psBuffer->ulYOffset + sFBVar.yres;

		/*
		 * PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY should be defined to 
		 * work around flipping problems seen with the Taal LCDs on
		 * Blaze.
		 * The work around is safe to use with other types of screen
		 * on Blaze (e.g. HDMI) and on other platforms (e.g. Panda
		 * board).
		 */
#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
		/*
		 * Attempt to change the virtual screen resolution if it is too
		 * small.  Note that fb_set_var also pans the display.
		 */
		if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual)
#endif /* !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) */
		{
			sFBVar.xres_virtual = sFBVar.xres;
			sFBVar.yres_virtual = ulYResVirtual;

			sFBVar.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;

			res = fb_set_var(psDevInfo->psLINFBInfo, &sFBVar);
			if (res != 0)
			{
				printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
			}
		}
#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
		else
		{
			res = fb_pan_display(psDevInfo->psLINFBInfo, &sFBVar);
			if (res != 0)
			{
				printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
			}
		}
#endif /* !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY) */
	}
#endif /* defined(CONFIG_DSSCOMP) */

	OMAPLFB_CONSOLE_UNLOCK();
}
예제 #13
0
static int merrifield_fb_probe(struct pci_dev *pdev,
                               const struct pci_device_id *id)
{
    int ret;
    struct fb_info *info = NULL;
    int fb_base = 0;
    int width = H_ACTIVE;
    int height = V_ACTIVE;

    ret = pci_enable_device(pdev);
    if (ret) {
        dev_err(&pdev->dev, "failed to enable device!\n");
        goto failure;
    }

    info = framebuffer_alloc(0, &pdev->dev);
    if (!info) {
        dev_err(&pdev->dev, "framebuffer allocation failure.\n");
        goto failure;
    }

    merrifield_fb_fix.mmio_start = pci_resource_start(pdev, 0);
    merrifield_fb_fix.mmio_len = pci_resource_len(pdev, 0);

    if (!request_mem_region(merrifield_fb_fix.mmio_start,
                            merrifield_fb_fix.mmio_len, DRV_NAME)) {
        dev_err(&pdev->dev, "mmio request_mem_region failure!\n");
        goto failure;
    }

    io_virt = ioremap_nocache(merrifield_fb_fix.mmio_start,
                              merrifield_fb_fix.mmio_len);

    pci_read_config_dword(pdev, 0x5C, &fb_base);

    /* Allocate enough for up 2 x 16-bit frame buffers at
     * our given resolution which is used for double buffering */
    merrifield_fb_fix.smem_start = fb_base;
    merrifield_fb_fix.smem_len = H_ACTIVE * V_ACTIVE * 4;

    info->screen_base = ioremap_nocache(merrifield_fb_fix.smem_start,
                                        merrifield_fb_fix.smem_len);
    info->fix = merrifield_fb_fix;
    info->fbops = &merrifield_fb_ops;
    info->flags =
        FBINFO_DEFAULT | FBINFO_HWACCEL_DISABLED | FBINFO_FLAG_DEFAULT;
    strcat(info->fix.id, DRV_NAME);
    info->var.activate = FB_ACTIVATE_NOW;
    info->device = &pdev->dev;

    ret = fb_alloc_cmap(&info->cmap, 256, 0);
    if (ret < 0) {
        dev_err(&pdev->dev, "cmap allocation failure.\n");
        goto failure;
    }

    /* RGB 5:6:5 */
    info->pseudo_palette = &info->cmap;
    info->cmap.len = 16;
    info->fix.type = FB_TYPE_PACKED_PIXELS;
    info->fix.visual = FB_VISUAL_TRUECOLOR;
    info->fix.line_length = width * 2;
    info->fix.accel = FB_ACCEL_NONE;
    info->fix.ypanstep = 1;
    info->fix.smem_start = merrifield_fb_fix.smem_start;
    info->fix.smem_len = merrifield_fb_fix.smem_len;
    info->var.xres = width;
    info->var.yres = height;
    info->var.xres_virtual = width;
    info->var.yres_virtual = height * 2;
    info->var.bits_per_pixel = 16;
    info->var.height = height;
    info->var.width = width;
    info->var.red.offset = 11;
    info->var.red.length = 5;
    info->var.green.offset = 5;
    info->var.green.length = 6;
    info->var.blue.offset = 0;
    info->var.blue.length = 5;

    ret = fb_set_var(info, &info->var);
    if (ret) {
        dev_err(&pdev->dev, "error setting var info\n");
        goto failure;
    }

    info->pixmap.addr = kmalloc(4096, GFP_KERNEL);
    if (!info->pixmap.addr) {
        dev_err(&pdev->dev, "pixmap allocation failure\n");
        goto failure;
    }

    info->pixmap.size = 4096;
    info->pixmap.buf_align = 4;
    info->pixmap.scan_align = 1;
    info->pixmap.access_align = 32;
    info->pixmap.flags = FB_PIXMAP_SYSTEM;

    pci_set_drvdata(pdev, info);
    if (register_framebuffer(info) < 0) {
        dev_err(&pdev->dev, "could not register framebuffer\n");
        goto failure;
    }

    init_display_controller_registers();

    return 0;

failure:
    merrifield_fb_remove(pdev);

    return ret;
}
예제 #14
0
static int mxc_elcdif_fb_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct mxc_elcdif_fb_data *data;
	struct resource *res;
	struct fb_info *fbi;
	struct mxc_fb_platform_data *pdata = pdev->dev.platform_data;
	const struct fb_videomode *mode;
	struct fb_videomode m;
	int num;

	fbi = framebuffer_alloc(sizeof(struct mxc_elcdif_fb_data), &pdev->dev);
	if (fbi == NULL) {
		ret = -ENOMEM;
		goto out;
	}

	data = (struct mxc_elcdif_fb_data *)fbi->par;
	data->cur_blank = data->next_blank = FB_BLANK_UNBLANK;

	fbi->var.activate = FB_ACTIVATE_NOW;
	fbi->fbops = &mxc_elcdif_fb_ops;
	fbi->flags = FBINFO_FLAG_DEFAULT;
	fbi->pseudo_palette = data->pseudo_palette;

	ret = fb_alloc_cmap(&fbi->cmap, 16, 0);
	if (ret)
		goto out;

	g_elcdif_dev = &pdev->dev;

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res == NULL) {
		dev_err(&pdev->dev, "cannot get IRQ resource\n");
		ret = -ENODEV;
		goto err0;
	}
	data->dma_irq = res->start;

	ret = request_irq(data->dma_irq, lcd_irq_handler, 0,
			  "mxc_elcdif_fb", data);
	if (ret) {
		dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n",
				data->dma_irq, ret);
		goto err0;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		ret = -ENODEV;
		goto err1;
	}
	elcdif_base = ioremap(res->start, SZ_4K);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (res) {
		fbi->fix.smem_len = res->end - res->start + 1;
		fbi->fix.smem_start = res->start;
		fbi->screen_base = ioremap(fbi->fix.smem_start,
					   fbi->fix.smem_len);
	}

	strcpy(fbi->fix.id, "mxc_elcdif_fb");

	fbi->var.xres = 800;
	fbi->var.yres = 480;

	if (pdata && !data->output_pix_fmt)
		data->output_pix_fmt = pdata->interface_pix_fmt;

	INIT_LIST_HEAD(&fbi->modelist);

	if (pdata && pdata->mode && pdata->num_modes)
		fb_videomode_to_modelist(pdata->mode, pdata->num_modes,
				&fbi->modelist);

	if (mxc_disp_mode.num_modes) {
		int i;
		mode = mxc_disp_mode.mode;
		num = mxc_disp_mode.num_modes;

		for (i = 0; i < num; i++) {
			/*
			 * FIXME now we do not support interlaced
			 * mode for ddc mode
			 */
			if ((mxc_disp_mode.dev_mode
				& MXC_DISP_DDC_DEV) &&
				(mode[i].vmode & FB_VMODE_INTERLACED))
				continue;
			else {
				dev_dbg(&pdev->dev, "Added mode %d:", i);
				dev_dbg(&pdev->dev,
					"xres = %d, yres = %d, freq = %d, vmode = %d, flag = %d\n",
					mode[i].xres, mode[i].yres,	mode[i].refresh, mode[i].vmode,
					mode[i].flag);
				fb_add_videomode(&mode[i], &fbi->modelist);
			}
		}
	}

	if (!fb_mode && pdata && pdata->mode_str)
		fb_mode = pdata->mode_str;

	if (fb_mode) {
		dev_dbg(&pdev->dev, "default video mode %s\n", fb_mode);
		ret = fb_find_mode(&fbi->var, fbi, fb_mode, NULL, 0, NULL,
				   default_bpp);
		if ((ret == 1) || (ret == 2)) {
			fb_var_to_videomode(&m, &fbi->var);
			dump_fb_videomode(&m);
			mode = fb_find_nearest_mode(&m,
				&fbi->modelist);
			fb_videomode_to_var(&fbi->var, mode);
		} else if (pdata && pdata->mode && pdata->num_modes) {
			ret = fb_find_mode(&fbi->var, fbi, fb_mode, pdata->mode,
					pdata->num_modes, NULL, default_bpp);
			if (!ret) {
				dev_err(fbi->device,
					"No valid video mode found");
				goto err2;
			}
		} else {
			dev_err(fbi->device,
				"No valid video mode found");
			goto err2;
		}
	}

	mxc_elcdif_fb_check_var(&fbi->var, fbi);

	fbi->var.xres_virtual = fbi->var.xres;
	fbi->var.yres_virtual = fbi->var.yres * 3;

	mxc_elcdif_fb_set_fix(fbi);

	if (!res || !res->end)
		if (mxc_elcdif_fb_map_video_memory(fbi) < 0) {
			ret = -ENOMEM;
			goto err2;
		}

	g_elcdif_axi_clk = clk_get(g_elcdif_dev, "elcdif_axi");
	if (g_elcdif_axi_clk == NULL) {
		dev_err(&pdev->dev, "can't get ELCDIF axi clk\n");
		ret = -ENODEV;
		goto err3;
	}
	g_elcdif_pix_clk = clk_get(g_elcdif_dev, "elcdif_pix");
	if (g_elcdif_pix_clk == NULL) {
		dev_err(&pdev->dev, "can't get ELCDIF pix clk\n");
		ret = -ENODEV;
		goto err3;
	}
	/*
	 * Set an appropriate pixel clk rate first, so that we can
	 * access ELCDIF registers.
	 */
	clk_set_rate(g_elcdif_pix_clk, 25000000);

	fbi->var.activate |= FB_ACTIVATE_FORCE;
	console_lock();
	fbi->flags |= FBINFO_MISC_USEREVENT;
	ret = fb_set_var(fbi, &fbi->var);
	fbi->flags &= ~FBINFO_MISC_USEREVENT;
	console_unlock();

	if (data->cur_blank == FB_BLANK_UNBLANK) {
		console_lock();
		fb_blank(fbi, FB_BLANK_UNBLANK);
		console_unlock();
	}

	ret = register_framebuffer(fbi);
	if (ret)
		goto err3;

	platform_set_drvdata(pdev, fbi);

	return 0;
err3:
	mxc_elcdif_fb_unmap_video_memory(fbi);
err2:
	iounmap(elcdif_base);
err1:
	free_irq(data->dma_irq, data);
err0:
	fb_dealloc_cmap(&fbi->cmap);
	framebuffer_release(fbi);
out:
	return ret;
}
예제 #15
0
static void det_worker(struct work_struct *work)
{
	BYTE HPD, HPDChange ;
	char event_string[16];
	char *envp[] = { event_string, NULL };

	CheckHDMITX(&HPD, &HPDChange);
	if (HPDChange) {
		/* cable connection changes */
		if (HPD) {
			ite661x.cable_plugin = 1;
			sprintf(event_string, "EVENT=plugin");

			/* make sure fb is powerdown */
			acquire_console_sem();
			fb_blank(ite661x.fbi, FB_BLANK_POWERDOWN);
			release_console_sem();

			if (ite661x_read_edid(ite661x.fbi) < 0)
				dev_err(&ite661x.client->dev,
					"ite661x: read edid fail\n");
			else {
				ParseEDID(ite661x.edid + 128);
				if (ite661x.fbi->monspecs.modedb_len > 0) {
					int i;
					const struct fb_videomode *mode;
					struct fb_videomode m;

					fb_destroy_modelist(&ite661x.fbi->modelist);

					for (i = 0; i < ite661x.fbi->monspecs.modedb_len; i++) {
						/*FIXME now we do not support interlaced mode */
						if (!(ite661x.fbi->monspecs.modedb[i].vmode & FB_VMODE_INTERLACED))
							fb_add_videomode(&ite661x.fbi->monspecs.modedb[i],
									&ite661x.fbi->modelist);
					}

					fb_var_to_videomode(&m, &ite661x.fbi->var);
					mode = fb_find_nearest_mode(&m,
							&ite661x.fbi->modelist);

					fb_videomode_to_var(&ite661x.fbi->var, mode);

					ite661x.fbi->var.activate |= FB_ACTIVATE_FORCE;
					acquire_console_sem();
					ite661x.fbi->flags |= FBINFO_MISC_USEREVENT;
					fb_set_var(ite661x.fbi, &ite661x.fbi->var);
					ite661x.fbi->flags &= ~FBINFO_MISC_USEREVENT;
					release_console_sem();
				}

				acquire_console_sem();
				fb_blank(ite661x.fbi, FB_BLANK_UNBLANK);
				release_console_sem();
				HDMITX_SetOutput();
			}
		} else {
			ite661x.cable_plugin = 0;
			sprintf(event_string, "EVENT=plugout");
			acquire_console_sem();
			fb_blank(ite661x.fbi, FB_BLANK_POWERDOWN);
			release_console_sem();
			DisableAudioOutput();
			DisableVideoOutput();
		}
		kobject_uevent_env(&ite661x.pdev->dev.kobj, KOBJ_CHANGE, envp);
	}
	enable_irq(ite661x.client->irq);
}
static void det_worker(struct work_struct *work)
{
	int dat;
	char event_string[16];
	char *envp[] = { event_string, NULL };

	dev_dbg(&sii902x.pdev->dev, "%s\n", __func__);

	dat = i2c_smbus_read_byte_data(sii902x.client, 0x3D);
	if (dat & 0x1) {
		/* cable connection changes */
		if (dat & 0x4) {
			sii902x.cable_plugin = 1;
			dev_dbg(&sii902x.pdev->dev, "EVENT=plugin\n");
			sprintf(event_string, "EVENT=plugin");

			if (sii902x_read_edid(sii902x.fbi) < 0)
				dev_err(&sii902x.client->dev,
					"Sii902x: read edid fail\n");
			else {
				if (sii902x.fbi->monspecs.modedb_len > 0) {

					int i;
					const struct fb_videomode *mode;
					struct fb_videomode m;

					fb_destroy_modelist(&sii902x.fbi->modelist);

					for (i = 0; i < sii902x.fbi->monspecs.modedb_len; i++) {
						/*FIXME now we do not support interlaced mode */
						mode = &sii902x.fbi->monspecs.modedb[i];

						if (!(mode->vmode & FB_VMODE_INTERLACED)) {

							dev_dbg(&sii902x.pdev->dev, "Added mode %d:", i);
							dev_dbg(&sii902x.pdev->dev,
								"xres = %d, yres = %d, freq = %d, vmode = %d, flag = %d\n",
								mode->xres, mode->yres, mode->refresh,
								mode->vmode, mode->flag);

							fb_add_videomode(mode, &sii902x.fbi->modelist);
						}
					}

					fb_var_to_videomode(&m, &sii902x.fbi->var);
					dump_fb_videomode(&m);

					mode = fb_find_nearest_mode(&m,
							&sii902x.fbi->modelist);

					fb_videomode_to_var(&sii902x.fbi->var, mode);

					sii902x.fbi->var.activate |= FB_ACTIVATE_FORCE;
					console_lock();
					sii902x.fbi->flags |= FBINFO_MISC_USEREVENT;
					fb_set_var(sii902x.fbi, &sii902x.fbi->var);
					sii902x.fbi->flags &= ~FBINFO_MISC_USEREVENT;
					console_unlock();
				}
				/* Power on sii902x */
				sii902x_poweron();
			}
		} else {
			sii902x.cable_plugin = 0;
			dev_dbg(&sii902x.pdev->dev, "EVENT=plugout\n");
			sprintf(event_string, "EVENT=plugout");
			/* Power off sii902x */
			sii902x_poweroff();
		}
		kobject_uevent_env(&sii902x.pdev->dev.kobj, KOBJ_CHANGE, envp);
	}
	i2c_smbus_write_byte_data(sii902x.client, 0x3D, dat);

	dev_dbg(&sii902x.pdev->dev, "exit %s\n", __func__);

}
static MTKLFB_ERROR MTKLFBInitFBDev(MTKLFB_DEVINFO *psDevInfo)
{
	struct fb_info *psLINFBInfo;
	struct module *psLINFBOwner;
	MTKLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
	MTKLFB_ERROR eError = MTKLFB_ERROR_GENERIC;
	unsigned long FBSize;
	unsigned long ulLCM;
	unsigned uiFBDevID = psDevInfo->uiFBDevID;

	MTKLFB_CONSOLE_LOCK();

	psLINFBInfo = registered_fb[uiFBDevID];
	if (psLINFBInfo == NULL)
	{
		eError = MTKLFB_ERROR_INVALID_DEVICE;
		goto ErrorRelSem;
	}

#ifdef USE_RGBA_8888_FB
    {
        int res;
        struct fb_var_screeninfo info;
        info = psLINFBInfo->var;

        info.activate       = FB_ACTIVATE_NOW;

        info.bits_per_pixel = 32;
        info.transp.offset  = 24;
        info.transp.length  = 8;
        info.red.offset     = 0;
        info.red.length     = 8;
        info.green.offset   = 8;
        info.green.length   = 8;
        info.blue.offset    = 16;
        info.blue.length    = 8;

        res = fb_set_var(psLINFBInfo, &info);

        if (res != 0)
        {
            xlog_printk(ANDROID_LOG_INFO, DRIVER_PREFIX, DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Error: %d)\n", __FUNCTION__, uiFBDevID, res);
            eError = MTKLFB_ERROR_INIT_FAILURE;
            goto ErrorRelSem;
        }
    }
#endif

	FBSize = (psLINFBInfo->screen_size) != 0 ?
					psLINFBInfo->screen_size :
					psLINFBInfo->fix.smem_len;

	
	if (FBSize == 0 || psLINFBInfo->fix.line_length == 0)
	{
		eError = MTKLFB_ERROR_INVALID_DEVICE;
		goto ErrorRelSem;
	}

	psLINFBOwner = psLINFBInfo->fbops->owner;
	if (!try_module_get(psLINFBOwner))
	{
		xlog_printk(ANDROID_LOG_INFO, DRIVER_PREFIX, DRIVER_PREFIX
			": %s: Device %u: Couldn't get framebuffer module\n", __FUNCTION__, uiFBDevID);

		goto ErrorRelSem;
	}

	if (psLINFBInfo->fbops->fb_open != NULL)
	{
		int res;

		res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0);
		if (res != 0)
		{
			xlog_printk(ANDROID_LOG_INFO, DRIVER_PREFIX, DRIVER_PREFIX
				" %s: Device %u: Couldn't open framebuffer(%d)\n", __FUNCTION__, uiFBDevID, res);

			goto ErrorModPut;
		}
	}

	psDevInfo->psLINFBInfo = psLINFBInfo;

	ulLCM = LCM(psLINFBInfo->fix.line_length, MTKLFB_PAGE_SIZE);

	DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
			": Device %u: Framebuffer physical address: 0x%lx\n",
			psDevInfo->uiFBDevID, psLINFBInfo->fix.smem_start));
	DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
			": Device %u: Framebuffer virtual address: 0x%lx\n",
			psDevInfo->uiFBDevID, (unsigned long)psLINFBInfo->screen_base));
	DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
			": Device %u: Framebuffer size: %lu\n",
			psDevInfo->uiFBDevID, FBSize));
	DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
			": Device %u: Framebuffer virtual width: %u\n",
			psDevInfo->uiFBDevID, psLINFBInfo->var.xres_virtual));
	DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
			": Device %u: Framebuffer virtual height: %u\n",
			psDevInfo->uiFBDevID, psLINFBInfo->var.yres_virtual));
	DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
			": Device %u: Framebuffer width: %u\n",
			psDevInfo->uiFBDevID, psLINFBInfo->var.xres));
	DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
			": Device %u: Framebuffer height: %u\n",
			psDevInfo->uiFBDevID, psLINFBInfo->var.yres));
	DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
			": Device %u: Framebuffer stride: %u\n",
			psDevInfo->uiFBDevID, psLINFBInfo->fix.line_length));
	DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
			": Device %u: LCM of stride and page size: %lu\n",
			psDevInfo->uiFBDevID, ulLCM));

	
	psPVRFBInfo->sSysAddr.uiAddr = psLINFBInfo->fix.smem_start;
	psPVRFBInfo->sCPUVAddr = psLINFBInfo->screen_base;

	psPVRFBInfo->ulWidth = psLINFBInfo->var.xres;
	psPVRFBInfo->ulHeight = psLINFBInfo->var.yres;
	psPVRFBInfo->ulByteStride =  psLINFBInfo->fix.line_length;
	psPVRFBInfo->ulFBSize = FBSize;
	psPVRFBInfo->ulBufferSize = psPVRFBInfo->ulHeight * psPVRFBInfo->ulByteStride;
	
	psPVRFBInfo->ulRoundedBufferSize = RoundUpToMultiple(psPVRFBInfo->ulBufferSize, ulLCM);

	if(psLINFBInfo->var.bits_per_pixel == 16)
	{
		if((psLINFBInfo->var.red.length == 5) &&
			(psLINFBInfo->var.green.length == 6) && 
			(psLINFBInfo->var.blue.length == 5) && 
			(psLINFBInfo->var.red.offset == 11) &&
			(psLINFBInfo->var.green.offset == 5) && 
			(psLINFBInfo->var.blue.offset == 0) && 
			(psLINFBInfo->var.red.msb_right == 0))
		{
			psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB565;
		}
		else
		{
			xlog_printk(ANDROID_LOG_INFO, DRIVER_PREFIX, DRIVER_PREFIX ": %s: Device %u: Unknown FB format\n", __FUNCTION__, uiFBDevID);
		}
	}
	else if(psLINFBInfo->var.bits_per_pixel == 32)
	{
		if((psLINFBInfo->var.red.length == 8) &&
			(psLINFBInfo->var.green.length == 8) && 
			(psLINFBInfo->var.blue.length == 8) && 
			(psLINFBInfo->var.red.offset == 16) &&
			(psLINFBInfo->var.green.offset == 8) && 
			(psLINFBInfo->var.blue.offset == 0) && 
			(psLINFBInfo->var.red.msb_right == 0))
		{
			psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_ARGB8888;
		}
		else if((psLINFBInfo->var.red.length == 8) &&
			(psLINFBInfo->var.green.length == 8) && 
			(psLINFBInfo->var.blue.length == 8) && 
			(psLINFBInfo->var.red.offset == 0) &&
			(psLINFBInfo->var.green.offset == 8) && 
			(psLINFBInfo->var.blue.offset == 16) && 
			(psLINFBInfo->var.red.msb_right == 0))
		{
			// yu-fu: PVR2D does not support ABGR8888 ...
			psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_ARGB8888;
		}
		else
		{
			xlog_printk(ANDROID_LOG_INFO, DRIVER_PREFIX, DRIVER_PREFIX ": %s: Device %u: Unknown FB format\n", __FUNCTION__, uiFBDevID);
		}
	}	
	else
	{
		xlog_printk(ANDROID_LOG_INFO, DRIVER_PREFIX, DRIVER_PREFIX ": %s: Device %u: Unknown FB format\n", __FUNCTION__, uiFBDevID);
	}

	psDevInfo->sFBInfo.ulPhysicalWidthmm =
		((int)psLINFBInfo->var.width  > 0) ? psLINFBInfo->var.width  : 0;

	psDevInfo->sFBInfo.ulPhysicalHeightmm =
		((int)psLINFBInfo->var.height > 0) ? psLINFBInfo->var.height : 0;

	
	psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
	psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;

	eError = MTKLFB_OK;
	goto ErrorRelSem;

ErrorModPut:
	module_put(psLINFBOwner);
ErrorRelSem:
	MTKLFB_CONSOLE_UNLOCK();

	return eError;
}
예제 #18
0
/* hack hack ;-) */
int proc_video_videomode_write(struct file* file, const char __user* buf, unsigned long count, void* data)
{
	char* page;
	ssize_t ret = -ENOMEM;
	/* int result; */
	int vLoop;
	int new_count;
	char* myString = kmalloc(count + 1, GFP_KERNEL);
	void* fb;
	struct fb_info *info;
#ifdef VERY_VERBOSE
	printk("%s %ld - ", __FUNCTION__, count);
#endif
	mutex_lock(&(ProcDeviceContext->DvbContext->Lock));
	fb = stmfb_get_fbinfo_ptr();
	info = (struct fb_info*) fb;
	page = (char*)__get_free_page(GFP_KERNEL);
	if (page)
	{
		int modeToSet = -1;
		int aktmode = -1;
		ret = -EFAULT;
		if (copy_from_user(page, buf, count))
			goto out;
		/* Dagobert: echo add a \n which will be counted as a char */
		if (page[count - 1] == '\n')
			new_count = count - 1;
		else
			new_count = count;
		strncpy(myString, page, new_count);
		myString[new_count] = '\0';
#ifdef VERY_VERBOSE
		printk("%s\n", myString);
#endif
		//whithout -1 write a unsupportet string hangs the driver
		for (vLoop = 0; vLoop < (sizeof(Options) / sizeof(struct Modes)) - 1; vLoop++)
		{
			if (Options[vLoop].xres     == info->var.xres &&
					Options[vLoop].yres     == info->var.yres &&
					Options[vLoop].vxres    == info->var.xres_virtual &&
					Options[vLoop].vyres    == info->var.yres_virtual &&
					Options[vLoop].pixclock == info->var.pixclock &&
					Options[vLoop].left     == info->var.left_margin &&
					Options[vLoop].right    == info->var.right_margin &&
					Options[vLoop].upper    == info->var.upper_margin &&
					Options[vLoop].lower    == info->var.lower_margin &&
					Options[vLoop].hslen    == info->var.hsync_len &&
					Options[vLoop].vslen    == info->var.vsync_len &&
					Options[vLoop].sync     == info->var.sync/* &&
                    Options[vLoop].vmode    == info->var.vmode*/)
			{
				aktmode = vLoop;
			}
			if (strncmp(myString, Options[vLoop].name, new_count) == 0)
			{
				printk("Found mode to set %s at %d\n",  Options[vLoop].name, vLoop);
				modeToSet = vLoop;
			}
		}
		if (aktmode == modeToSet)
			modeToSet = -1;
		if (modeToSet != -1)
		{
			struct fb_var_screeninfo screen_info;
			int createNew = 0;
			memcpy(&screen_info, &info->var, sizeof(struct fb_var_screeninfo));
			if (fb != NULL)
			{
				int err;
				/* otherwise we got EBUSY from stmfb device */
				/* Dagobert: Bugfix: "demux stop" bug; ticket #10 */
				if (ProcDeviceContext != NULL)
				{
					if (ProcDeviceContext->VideoState.play_state != VIDEO_STOPPED)
						VideoIoctlStop(ProcDeviceContext, 1);
					if (isDisplayCreated(BACKEND_VIDEO_ID, ProcDeviceContext->Id))
					{
						createNew = 1;
#ifdef VERY_VERBOSE
						printk("delete display\n");
#endif
						DvbDisplayDelete(BACKEND_VIDEO_ID, ProcDeviceContext->Id);
					}
				}
				info->flags |= FBINFO_MISC_USEREVENT;
				screen_info.xres = Options[modeToSet].xres;         /* visible resolution */
				screen_info.yres = Options[modeToSet].yres;
				screen_info.xres_virtual = Options[modeToSet].vxres;        /* virtual resolution */
				screen_info.yres_virtual = Options[modeToSet].vyres;
				screen_info.pixclock = Options[modeToSet].pixclock;
				screen_info.left_margin = Options[modeToSet].left;
				screen_info.right_margin = Options[modeToSet].right;
				screen_info.upper_margin = Options[modeToSet].upper;
				screen_info.lower_margin = Options[modeToSet].lower;
				screen_info.hsync_len = Options[modeToSet].hslen;
				screen_info.vsync_len = Options[modeToSet].vslen;
				screen_info.sync = Options[modeToSet].sync;
				screen_info.vmode = Options[modeToSet].vmode;
				screen_info.activate = FB_ACTIVATE_FORCE;
				err = fb_set_var(fb, &screen_info);
				if (err != 0)
					printk("error setting new resolution %d\n", err);
				if ((ProcDeviceContext != NULL) && (createNew == 1))
				{
#ifdef VERY_VERBOSE
					printk("create new display\n");
#endif
					DisplayCreate(BACKEND_VIDEO_ID, ProcDeviceContext->Id);
					VideoIoctlPlay(ProcDeviceContext);
					err = DvbStreamSetOutputWindow(ProcDeviceContext->VideoStream,
												   0, 0, Options[modeToSet].xres, Options[modeToSet].yres);
					if (err != 0)
					{
						printk("failed to set output window %d, %d, %d\n",  Options[modeToSet].xres,  Options[modeToSet].yres, err);
					}
#ifdef VERY_VERBOSE
					else
						printk("set output window to %d, %d ok\n",  Options[modeToSet].xres,  Options[modeToSet].yres);
#endif
				}
			}
			else
			{
				printk("Cannot get stmfb_info struct\n");
			}
		}
		/* always return count to avoid endless loop */
		ret = count;
	}
out:
	free_page((unsigned long)page);
	kfree(myString);
	mutex_unlock(&(ProcDeviceContext->DvbContext->Lock));
	return ret;
}
예제 #19
0
int proc_video_pal_h_start_write(struct file* file, const char __user* buf, unsigned long count, void* data)
{
	char* page;
	ssize_t ret = -ENOMEM;
	/* int result; */
	int value;
	char* myString = kmalloc(count + 1, GFP_KERNEL);
#ifdef VERY_VERBOSE
	printk("%s %ld - ", __FUNCTION__, count);
#endif
	mutex_lock(&(ProcDeviceContext->DvbContext->Lock));
	page = (char*)__get_free_page(GFP_KERNEL);
	if (page)
	{
		void* fb;
		struct fb_info* info;
		struct fb_var_screeninfo screen_info;
		int createNew = 0;
		ret = -EFAULT;
		if (copy_from_user(page, buf, count))
			goto out;
		strncpy(myString, page, count);
		myString[count] = '\0';
#ifdef VERY_VERBOSE
		printk("%s\n", myString);
#endif
		sscanf(myString, "%x", &value);
		fb = stmfb_get_fbinfo_ptr();
		info = (struct fb_info*) fb;
		memcpy(&screen_info, &info->var, sizeof(struct fb_var_screeninfo));
		if (fb != NULL)
		{
			int err;
			/* otherwise we got EBUSY from stmfb device */
			/* Dagobert: Bugfix: "demux stop" bug; ticket #10 */
			if (ProcDeviceContext != NULL)
			{
				if (ProcDeviceContext->VideoState.play_state != VIDEO_STOPPED)
					VideoIoctlStop(ProcDeviceContext, 1);
				if (isDisplayCreated(BACKEND_VIDEO_ID, ProcDeviceContext->Id))
				{
					createNew = 1;
#ifdef VERY_VERBOSE
					printk("delete display\n");
#endif
					DvbDisplayDelete(BACKEND_VIDEO_ID, ProcDeviceContext->Id);
				}
			}
			info->flags |= FBINFO_MISC_USEREVENT;
			screen_info.left_margin = value;
			err = fb_set_var(fb, &screen_info);
			if (err != 0)
				printk("error setting new resolution %d\n", err);
			if ((ProcDeviceContext != NULL) && (createNew == 1))
			{
#ifdef VERY_VERBOSE
				printk("create new display\n");
#endif
				DisplayCreate(BACKEND_VIDEO_ID, ProcDeviceContext->Id);
				VideoIoctlPlay(ProcDeviceContext);
				err = DvbStreamSetOutputWindow(ProcDeviceContext->VideoStream,
											   0, 0, screen_info.xres, screen_info.yres);
				if (err != 0)
				{
					printk("failed to set output window %d, %d, %d\n",  screen_info.xres,  screen_info.yres, err);
				}
#ifdef VERY_VERBOSE
				else
					printk("set output window to %d, %d ok\n",  screen_info.xres,  screen_info.yres);
#endif
			}
		}
		else
		{
			printk("Cannot get stmfb_info struct\n");
		}
		/* always return count to avoid endless loop */
		ret = count;
	}
out:
	free_page((unsigned long)page);
	kfree(myString);
	mutex_unlock(&(ProcDeviceContext->DvbContext->Lock));
	return ret;
}
예제 #20
0
파일: stmfb.c 프로젝트: Firmeware/driver
/*
 *  stmfb_createfb
 *  Create framebuffer related state and register with upper layers
 */
static int stmfb_createfb(struct stmfb_info *i, int display, const char *name)
{
  int ret;
  unsigned long nPages;
  int fb_registered = 0;
  const struct stmcore_display_pipeline_data * const pd =
    *((struct stmcore_display_pipeline_data **) i->platformDevice->dev.platform_data);

  DPRINTK("\n");

  /*
   * Copy all available display modes into the modelist, before we parse
   * the module parameters to get the default mode.
   */
  stmfb_enumerate_modes(i);

  /*
   * Need to set the framebuffer operation table and get hold of the display
   * plane before parsing the module parameters so fb_find_mode can work.
   */
  i->info.fbops = &stmfb_ops;

  if((ret = stmfb_parse_module_parameters(i, display)) < 0)
    goto failed0;

  /* can create blitter only after module parameters have been parsed */
  if((ret = stmfb_probe_get_blitter(i,pd))<0)
    goto failed0;

  nPages = (i->ulFBSize + PAGE_SIZE - 1) / PAGE_SIZE;

  i->FBPart = bpa2_find_part ("bigphysarea");
  i->ulPFBBase = i->FBPart ? bpa2_alloc_pages (i->FBPart, nPages, 0, GFP_KERNEL)
                           : 0;
  if (!i->ulPFBBase)
  {
    printk(KERN_WARNING "Failed to allocate fb%d memory, requested size = %lu\n",display, i->ulFBSize);
    ret = -ENOMEM;
    goto failed0;
  }

  /* try to allocate memory from BPA2 as additional memory for graphics
     operations. Basically, this is not vital, but driver loading will still
     fail if an auxsize has been specified in the module parameters which can
     not be satisfied, either because no BPA2 partition 'gfx-memory' exists,
     or if it's not large enough for the given auxsize. */
  /* Please note that due to hardware limitations, this can actually be a bit
     complex (2 & 3):
     1) we look for partitions labelled 'gfx-memory-[0...x]', each of which
        should be 64MB in size and be aligned to a 64MB bank. This makes the
        process quite easy for us.
     2) Failing that, we try to use a partition labelled 'gfx-memory'. Now we
        have to make sure ourselves that each allocation does not cross a 64MB
        bank boundary.
     3) Failing that, too, or in case the 'gfx-memory' partition not being
        large enough to accomodate for the amount of gfx memory requested in
        the module options, we will do the same but this time use the
        'bigphysarea' partition. */
  /* So, either one can configure several 'gfx-memory-%d' partitions
     (preferred, to have maximum control over placement of gfx memory), just
     use one large 'gfx-memory' partition, or configure nothing at all and be
     limited to 'bigphysarea' memory.
     The combined memory of all the allocations will be made available to
     DirectFB. */
  /* FIXME: this code is way too complex! */
#define MEMORY64MB_SIZE      (1<<26)
  if (i->AuxSize[0])
  {
    /* aux memory was requested */
    unsigned int       idx;        /* index into i->AuxPart[] */
    /* order of partnames is important here! */
    static const char *partnames[] = { "gfx-memory-%d", "gfx-memory", "bigphysarea" };
    unsigned int       partnameidx /* index into partnames[] */,
                       partidx     /* index in case of 'gfx-memory-%d' */;
    char               partname[14]; /* real name in case of 'gfx-memory-%d' */
    struct bpa2_part  *part;
    unsigned long      still_needed = i->AuxSize[0];

    unsigned long      this_alloc;
    int                alignment;

    partidx = 0;
    /* find a partition suitable for us, in the preferred order, as outlined
       above */
    for (partnameidx = 0; partnameidx < ARRAY_SIZE (partnames); ++partnameidx)
    {
      sprintf (partname, partnames[partnameidx], 0);
      part = bpa2_find_part (partname);
      if (part)
        break;
    }

    if (!part)
    {
      printk (KERN_ERR "no BPA2 partitions found for auxmem!\n");
      goto failed_bigphys;
    }

    idx = 0;

restart:
    if (still_needed >= MEMORY64MB_SIZE)
    {
      /* we first try to satisfy from a 64MB aligned region */
      this_alloc = MEMORY64MB_SIZE;
      /* don't request a specific alignment if individual 'gfx-memory-%d'
         partitions are configured in the kernel */
      alignment  = (partnameidx == 0) ? 0 : MEMORY64MB_SIZE / PAGE_SIZE;
    }
    else
    {
      /* if requested size is < 64MB, we are optimistic and hope it will
         fit into one 64MB bank without alignment restrictions. This
         doesn't mean we will be happy with a region crossing that
         boundary, i.e. we will still make sure all restrictions are met.
         We are really being just optimistic here. */
      this_alloc = still_needed;
      alignment  = 0;
    }

    while (part && idx < ARRAY_SIZE (i->AuxPart) && still_needed)
    {
      int           this_pages;
      unsigned long base;

      printk (KERN_INFO "trying to alloc %lu bytes (align: %.4x, still needed:"
                        " %lu) from '%s' for GFX%d auxmem\n",
              this_alloc, alignment, still_needed, partname, display);

      this_pages = (this_alloc + PAGE_SIZE - 1) / PAGE_SIZE;
      base = bpa2_alloc_pages (part, this_pages, alignment, GFP_KERNEL);
      if (base)
      {
        /* make sure it doesn't cross a 64MB boundary. At some point we will
           be using the new BPA2 allocator API... */
        if ((base & ~(MEMORY64MB_SIZE - 1)) != ((base + this_alloc - 1) & ~(MEMORY64MB_SIZE - 1)))
        {
          unsigned long topAddress;

          printk ("%s: %8.lx + %lu (%d pages) crosses a 64MB boundary, retrying!\n",
                  __FUNCTION__, base, this_alloc, this_pages);

          /* free and try a new reservation with different attributes,
             hoping nobody requests bpa2 memory in between... */
          bpa2_free_pages (part, base);

          if (partnameidx == 0)
          {
            /* if we have 'gfx-memory-%d' partitions, try the next one */
            /* Getting here doesn't neccessarily mean there is an error in
               the BPA2 partition definition. This can happen if e.g. two
               framebuffers are configured and the auxmem size requested is
               larger but not a multiple of 64MB (since we are optimistic and
               try to re-use partially used partitions), so don't be tempted
               to put a WARN_ON() here! */
            sprintf (partname, partnames[partnameidx], ++partidx);
            part = bpa2_find_part (partname);
            continue;
          }

          if (still_needed == this_alloc && alignment == 0)
          {
            /* this can only happen on the last chunk of memory needed. So
               we first try to fit it into its own region.
               I.e. we first try to put the last chunk into a partly used
               bank. If we succeed, but the chunk now spans a boundary
               (which gets us here), we try to put it into its own
               bank. If that fails, too, we will come back again (this
               time with alignment == 1) and split the chunk into two. */
            alignment = MEMORY64MB_SIZE / PAGE_SIZE;
            continue;
          }

          /* standard case, allocate up to the end of current 64MB bank,
             effectively splitting the current chunk into two. */
#define _ALIGN_UP(addr,size)    (((addr)+((size)-1))&(~((size)-1)))
          topAddress = _ALIGN_UP (base, MEMORY64MB_SIZE);
          this_alloc = topAddress - base;
          this_pages = (this_alloc + PAGE_SIZE - 1) / PAGE_SIZE;

          /* alignment should be 0 or 1 here */
          WARN_ON (alignment != 0
                   && alignment != 1);
          base = bpa2_alloc_pages (part, this_pages, alignment, GFP_KERNEL);
          if (!base)
          {
            /* shouldn't happen here, since we just moments ago suceeded in
               allocating even more memory than now, so we don't know what
               to do and kindof panic ...*/
            break;
          }
        }

        /* we now have found a more or less nice place to chill. */
        i->AuxPart[idx] = part;
        i->AuxBase[idx] = base;
        i->AuxSize[idx] = this_alloc;
        ++idx;

        still_needed -= this_alloc;

        printk (KERN_INFO "success: base: %.8lx, still needed: %lu\n",
                base, still_needed);

        if (still_needed >= MEMORY64MB_SIZE)
        {
          /* we first try to satisfy from a 64MB aligned region */
          this_alloc = MEMORY64MB_SIZE;
          alignment  = (partnameidx == 0) ? 0 : MEMORY64MB_SIZE / PAGE_SIZE;
        }
        else
        {
          /* if requested size is < 64MB we are on the last chunk of memory
             blocks. We are otimistic and hope it will fit into a possibly
             already partly used 64MB bank without alignment restrictions,
             i.e. we hope it will not span a 64MB boundary. If that's not
             the case, we will again use an alignment of 64MB, so as to
             reduce scattering of the auxmem chunks. */
          this_alloc = still_needed;
          alignment  = 0;

          /* if using 'gfx-memory-%d' partitions, try to share the last
             chunk with another chunk (in a possibly partly used
             partition). */
          if (partnameidx == 0)
            partidx = -1;
        }

        if (partnameidx == 0)
        {
          /* in case we are using 'gfx-memory-%d' as partition name, make
             sure we advance to the next partition */
          sprintf (partname, partnames[partnameidx], ++partidx);
          part = bpa2_find_part (partname);
        }
      }
      else
      {
        if (alignment > 1)
        {
          if (still_needed == this_alloc)
            /* make sure not to get into an endless loop which would be
               switching around the alignment all the time. */
            alignment = 1;
          else
            /* try again with different alignment rules */
            alignment = 0;
        }
        else
        {
          /* failed: couldn't allocate any memory at all, even without any
             alignment restrictions.
             1) In case there are 'gfx-memory-%d' partitions, we advance
                to the next one.
             2) In case we had been using 'gfx-memory' as partition name,
                we now try 'bigphysarea'*/
          if (partnameidx == 0)
          {
            /* use next 'gfx-memory-%d' partition */
            BUG_ON (strcmp (partnames[partnameidx], "gfx-memory-%d"));
            sprintf (partname, partnames[partnameidx], ++partidx);
            part = bpa2_find_part (partname);
          }
          else if (partnameidx == 1)
          {
            /* advance from 'gfx-memory' to 'bigphysarea' partition name */
            BUG_ON (strcmp (partnames[partnameidx], "gfx-memory"));
            sprintf (partname, partnames[++partnameidx], 0);
            BUG_ON (strcmp (partnames[partnameidx], "bigphysarea"));
            part = bpa2_find_part (partname);
            goto restart;
          }
          else
            /* that's it, there are no partitions left to check for auxmem */
            break;
        }
      }
    }

    if (still_needed)
    {
      /* not enough chill space configured for BPA2 */
      printk (KERN_WARNING "Failed to allocate enough fb%d auxmem "
                           "(still need %lu bytes)\n",
              display, still_needed);
      ret = -ENOMEM;
      goto failed_auxmem;
    }
  }

  if(stm_display_plane_connect_to_output(i->pFBPlane, i->pFBMainOutput) < 0)
  {
    printk(KERN_ERR "fb%d display cannot be connected to display output pipeline, this is very bad!\n",display);
    ret = -EIO;
    goto failed_auxmem;
  }

  if(stm_display_plane_lock(i->pFBPlane) < 0)
  {
    printk(KERN_WARNING "fb%d display plane may already be in use by another driver\n",display);
    ret = -EBUSY;
    goto failed_auxmem;
  }

  i->main_config.activate = STMFBIO_ACTIVATE_IMMEDIATE;
  if(stmfb_set_output_configuration(&i->main_config,i)<0)
  {
    printk(KERN_WARNING "fb%d main output configuration is unsupported\n",display);
    ret = -EINVAL;
    goto failed_auxmem;
  }

  /*
   * Get the framebuffer layer default extended var state and capabilities
   */
  i->current_var_ex.layerid = 0;

  if((ret = stmfb_encode_var_ex(&i->current_var_ex, i)) < 0)
  {
    printk(KERN_WARNING "fb%d failed to get display plane's extended capabilities\n",display);
    goto failed_auxmem;
  }

  /* Setup the framebuffer info for registration */
  i->info.screen_base = ioremap_nocache(i->ulPFBBase,i->ulFBSize);
  i->info.flags       = FBINFO_DEFAULT |
                        FBINFO_PARTIAL_PAN_OK |
                        FBINFO_HWACCEL_YPAN;

  strcpy(i->info.fix.id, name);  /* identification string */

  i->info.fix.smem_start  = i->ulPFBBase;                /* Start of frame buffer mem (physical address)               */
  i->info.fix.smem_len    = i->ulFBSize;                 /* Length of frame buffer mem as the device sees it           */
  i->info.fix.mmio_start  = pd->mmio;                    /* memory mapped register access     */
  i->info.fix.mmio_len    = pd->mmio_len;                /* Length of Memory Mapped I/O       */
  i->info.fix.type        = FB_TYPE_PACKED_PIXELS;       /* see FB_TYPE_*                     */
  i->info.fix.type_aux    = 0;                           /* Interleave for interleaved Planes */
  i->info.fix.xpanstep    = 0;                           /* zero if no hardware panning       */
  i->info.fix.ypanstep    = 1;                           /* zero if no hardware panning       */
  i->info.fix.ywrapstep   = 0;                           /* zero if no hardware ywrap         */

  i->info.pseudo_palette = &i->pseudo_palette;

  if(fb_alloc_cmap(&i->info.cmap, 256, 1)<0)
  {
    printk(KERN_ERR "fb%d unable to allocate colour map\n",display);
    ret = -ENOMEM;
    goto failed_ioremap;
  }

  if(i->info.cmap.len != 256)
  {
    printk(KERN_ERR "fb%d WTF colour map length is wrong????\n",display);
  }

  if (register_framebuffer(&i->info) < 0)
  {
    printk(KERN_ERR "fb%d register =_framebuffer failed!\n",display);
    ret = -ENODEV;
    goto failed_cmap;
  }

  /*
   * If there was no console activated on the registered framebuffer, we have
   * to force the display mode be updated. This sequence is cribbed from the
   * matroxfb driver.
   */
  if(!i->current_videomode_valid)
  {
    i->info.var.activate |= FB_ACTIVATE_FORCE;
    if((ret = fb_set_var(&i->info, &i->info.var))<0)
    {
      printk(KERN_WARNING "fb%d failed to set default display mode, display pipeline may already be in use\n",display);
      goto failed_register;
    }
  }

//#if (defined(UFS912) || defined(HS7110) || defined(HS7119) || defined(HS7420) || defined(HS7429) || defined(HS7810A) || defined(HS7819) || defined(ATEMIO520) || defined(ATEMIO530) || defined(SPARK) || defined(AT7500)) && defined(__TDT__)
  // WORKAROUND: Clear the framebuffer 
  memset(i->info.screen_base, 0x00, i->ulFBSize);
//#endif

  stmfb_init_class_device(i);

  DPRINTK("out\n");

  return 0;

failed_register:
  fb_registered = 1;
  unregister_framebuffer (&i->info);

failed_cmap:
  fb_dealloc_cmap (&i->info.cmap);

failed_ioremap:
  iounmap (i->info.screen_base);
  i->info.screen_base = NULL;

failed_auxmem:
  stmfb_destroy_auxmem (i);

failed_bigphys:
  bpa2_free_pages (i->FBPart, i->ulPFBBase);
  i->ulPFBBase = 0;
  i->FBPart = NULL;

failed0:
  if (!fb_registered)
    /* unregister_framebuffer() does fb_destroy_modelist() for us, so don't
       destroy it twice! */
    fb_destroy_modelist (&i->info.modelist);

  return ret;
}
예제 #21
0
void OMAPLFBFlip(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_BUFFER *psBuffer)
{
	struct fb_var_screeninfo sFBVar;
	int res;
	unsigned long ulYResVirtual;

	OMAPLFB_CONSOLE_LOCK();

	sFBVar = psDevInfo->psLINFBInfo->var;

	sFBVar.xoffset = 0;
	sFBVar.yoffset = psBuffer->ulYOffset;

	ulYResVirtual = psBuffer->ulYOffset + sFBVar.yres;

#if defined(CONFIG_DSSCOMP)
	{
		
		struct fb_fix_screeninfo sFBFix = psDevInfo->psLINFBInfo->fix;
		struct dsscomp_setup_dispc_data d =
		{
			.num_ovls = 1,
			.num_mgrs = 1,
			.mgrs[0].alpha_blending = 1,
			.ovls[0] =
			{
				.cfg =
				{
					.win.w = sFBVar.xres,
					.win.h = sFBVar.yres,
					.crop.x = sFBVar.xoffset,
					.crop.y = sFBVar.yoffset,
					.crop.w = sFBVar.xres,
					.crop.h = sFBVar.yres,
					.width = sFBVar.xres_virtual,
					.height = sFBVar.yres_virtual,
					.stride = sFBFix.line_length,
					.enabled = 1,
					.global_alpha = 255,
				},
			},
		};

		
		struct tiler_pa_info *pas[] = { NULL };

		d.ovls[0].ba = sFBFix.smem_start;
		omapfb_mode_to_dss_mode(&sFBVar, &d.ovls[0].cfg.color_mode);

		res = dsscomp_gralloc_queue(&d, pas, true, NULL, NULL);
	}
#else 
	
#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
	
	if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual)
#endif 
	{
		sFBVar.xres_virtual = sFBVar.xres;
		sFBVar.yres_virtual = ulYResVirtual;

		sFBVar.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;

		res = fb_set_var(psDevInfo->psLINFBInfo, &sFBVar);
		if (res != 0)
		{
			printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_set_var failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
		}
	}
#if !defined(PVR_OMAPLFB_DONT_USE_FB_PAN_DISPLAY)
	else
	{
		res = fb_pan_display(psDevInfo->psLINFBInfo, &sFBVar);
		if (res != 0)
		{
			printk(KERN_ERR DRIVER_PREFIX ": %s: Device %u: fb_pan_display failed (Y Offset: %lu, Error: %d)\n", __FUNCTION__, psDevInfo->uiFBDevID, psBuffer->ulYOffset, res);
		}
	}
#endif 
#endif 

	OMAPLFB_CONSOLE_UNLOCK();
}