⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ffb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/** *	ffb_imageblit - Copies a image from system memory to the screen. * *	@info: frame buffer structure that represents a single frame buffer *	@image: structure defining the image. */static void ffb_imageblit(struct fb_info *info, const struct fb_image *image){	struct ffb_par *par = (struct ffb_par *)info->par;	struct ffb_fbc __iomem *fbc = par->fbc;	const u8 *data = image->data;	unsigned long flags;	u32 fg, bg, xy;	u64 fgbg;	int i, width, stride;	if (image->depth > 1) {		cfb_imageblit(info, image);		return;	}	fg = ((u32 *)info->pseudo_palette)[image->fg_color];	bg = ((u32 *)info->pseudo_palette)[image->bg_color];	fgbg = ((u64) fg << 32) | (u64) bg;	xy = (image->dy << 16) | image->dx;	width = image->width;	stride = ((width + 7) >> 3);	spin_lock_irqsave(&par->lock, flags);	if (fgbg != *(u64 *)&par->fg_cache) {		FFBFifo(par, 2);		upa_writeq(fgbg, &fbc->fg);		*(u64 *)&par->fg_cache = fgbg;	}	if (width >= 32) {		FFBFifo(par, 1);		upa_writel(32, &fbc->fontw);	}	while (width >= 32) {		const u8 *next_data = data + 4;		FFBFifo(par, 1);		upa_writel(xy, &fbc->fontxy);		xy += (32 << 0);		for (i = 0; i < image->height; i++) {			u32 val = (((u32)data[0] << 24) |				   ((u32)data[1] << 16) |				   ((u32)data[2] <<  8) |				   ((u32)data[3] <<  0));			FFBFifo(par, 1);			upa_writel(val, &fbc->font);			data += stride;		}		data = next_data;		width -= 32;	}	if (width) {		FFBFifo(par, 2);		upa_writel(width, &fbc->fontw);		upa_writel(xy, &fbc->fontxy);		for (i = 0; i < image->height; i++) {			u32 val = (((u32)data[0] << 24) |				   ((u32)data[1] << 16) |				   ((u32)data[2] <<  8) |				   ((u32)data[3] <<  0));			FFBFifo(par, 1);			upa_writel(val, &fbc->font);			data += stride;		}	}	spin_unlock_irqrestore(&par->lock, flags);}static void ffb_fixup_var_rgb(struct fb_var_screeninfo *var){	var->red.offset = 0;	var->red.length = 8;	var->green.offset = 8;	var->green.length = 8;	var->blue.offset = 16;	var->blue.length = 8;	var->transp.offset = 0;	var->transp.length = 0;}/** *	ffb_setcolreg - Sets a color register. * *	@regno: boolean, 0 copy local, 1 get_user() function *	@red: frame buffer colormap structure *	@green: The green value which can be up to 16 bits wide *	@blue:  The blue value which can be up to 16 bits wide. *	@transp: If supported the alpha value which can be up to 16 bits wide. *	@info: frame buffer info structure */static int ffb_setcolreg(unsigned regno,			 unsigned red, unsigned green, unsigned blue,			 unsigned transp, struct fb_info *info){	u32 value;	if (regno >= 16)		return 1;	red >>= 8;	green >>= 8;	blue >>= 8;	value = (blue << 16) | (green << 8) | red;	((u32 *)info->pseudo_palette)[regno] = value;	return 0;}/** *	ffb_blank - Optional function.  Blanks the display. *	@blank_mode: the blank mode we want. *	@info: frame buffer structure that represents a single frame buffer */static int ffb_blank(int blank, struct fb_info *info){	struct ffb_par *par = (struct ffb_par *)info->par;	struct ffb_dac __iomem *dac = par->dac;	unsigned long flags;	u32 val;	int i;	spin_lock_irqsave(&par->lock, flags);	FFBWait(par);	upa_writel(FFB_DAC_TGEN, &dac->type);	val = upa_readl(&dac->value);	switch (blank) {	case FB_BLANK_UNBLANK: /* Unblanking */		val |= FFB_DAC_TGEN_VIDE;		par->flags &= ~FFB_FLAG_BLANKED;		break;	case FB_BLANK_NORMAL: /* Normal blanking */	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */	case FB_BLANK_POWERDOWN: /* Poweroff */		val &= ~FFB_DAC_TGEN_VIDE;		par->flags |= FFB_FLAG_BLANKED;		break;	}	upa_writel(FFB_DAC_TGEN, &dac->type);	upa_writel(val, &dac->value);	for (i = 0; i < 10; i++) {		upa_writel(FFB_DAC_TGEN, &dac->type);		upa_readl(&dac->value);	}	spin_unlock_irqrestore(&par->lock, flags);	return 0;}static struct sbus_mmap_map ffb_mmap_map[] = {	{		.voff	= FFB_SFB8R_VOFF,		.poff	= FFB_SFB8R_POFF,		.size	= 0x0400000	},	{		.voff	= FFB_SFB8G_VOFF,		.poff	= FFB_SFB8G_POFF,		.size	= 0x0400000	},	{		.voff	= FFB_SFB8B_VOFF,		.poff	= FFB_SFB8B_POFF,		.size	= 0x0400000	},	{		.voff	= FFB_SFB8X_VOFF,		.poff	= FFB_SFB8X_POFF,		.size	= 0x0400000	},	{		.voff	= FFB_SFB32_VOFF,		.poff	= FFB_SFB32_POFF,		.size	= 0x1000000	},	{		.voff	= FFB_SFB64_VOFF,		.poff	= FFB_SFB64_POFF,		.size	= 0x2000000	},	{		.voff	= FFB_FBC_REGS_VOFF,		.poff	= FFB_FBC_REGS_POFF,		.size	= 0x0002000	},	{		.voff	= FFB_BM_FBC_REGS_VOFF,		.poff	= FFB_BM_FBC_REGS_POFF,		.size	= 0x0002000	},	{		.voff	= FFB_DFB8R_VOFF,		.poff	= FFB_DFB8R_POFF,		.size	= 0x0400000	},	{		.voff	= FFB_DFB8G_VOFF,		.poff	= FFB_DFB8G_POFF,		.size	= 0x0400000	},	{		.voff	= FFB_DFB8B_VOFF,		.poff	= FFB_DFB8B_POFF,		.size	= 0x0400000	},	{		.voff	= FFB_DFB8X_VOFF,		.poff	= FFB_DFB8X_POFF,		.size	= 0x0400000	},	{		.voff	= FFB_DFB24_VOFF,		.poff	= FFB_DFB24_POFF,		.size	= 0x1000000	},	{		.voff	= FFB_DFB32_VOFF,		.poff	= FFB_DFB32_POFF,		.size	= 0x1000000	},	{		.voff	= FFB_FBC_KREGS_VOFF,		.poff	= FFB_FBC_KREGS_POFF,		.size	= 0x0002000	},	{		.voff	= FFB_DAC_VOFF,		.poff	= FFB_DAC_POFF,		.size	= 0x0002000	},	{		.voff	= FFB_PROM_VOFF,		.poff	= FFB_PROM_POFF,		.size	= 0x0010000	},	{		.voff	= FFB_EXP_VOFF,		.poff	= FFB_EXP_POFF,		.size	= 0x0002000	},	{		.voff	= FFB_DFB422A_VOFF,		.poff	= FFB_DFB422A_POFF,		.size	= 0x0800000	},	{		.voff	= FFB_DFB422AD_VOFF,		.poff	= FFB_DFB422AD_POFF,		.size	= 0x0800000	},	{		.voff	= FFB_DFB24B_VOFF,		.poff	= FFB_DFB24B_POFF,		.size	= 0x1000000	},	{		.voff	= FFB_DFB422B_VOFF,		.poff	= FFB_DFB422B_POFF,		.size	= 0x0800000	},	{		.voff	= FFB_DFB422BD_VOFF,		.poff	= FFB_DFB422BD_POFF,		.size	= 0x0800000	},	{		.voff	= FFB_SFB16Z_VOFF,		.poff	= FFB_SFB16Z_POFF,		.size	= 0x0800000	},	{		.voff	= FFB_SFB8Z_VOFF,		.poff	= FFB_SFB8Z_POFF,		.size	= 0x0800000	},	{		.voff	= FFB_SFB422_VOFF,		.poff	= FFB_SFB422_POFF,		.size	= 0x0800000	},	{		.voff	= FFB_SFB422D_VOFF,		.poff	= FFB_SFB422D_POFF,		.size	= 0x0800000	},	{ .size = 0 }};static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma){	struct ffb_par *par = (struct ffb_par *)info->par;	return sbusfb_mmap_helper(ffb_mmap_map,				  par->physbase, par->fbsize,				  0, vma);}static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg){	struct ffb_par *par = (struct ffb_par *)info->par;	return sbusfb_ioctl_helper(cmd, arg, info,				   FBTYPE_CREATOR, 24, par->fbsize);}/* *  Initialisation */static void ffb_init_fix(struct fb_info *info){	struct ffb_par *par = (struct ffb_par *)info->par;	const char *ffb_type_name;	if (!(par->flags & FFB_FLAG_AFB)) {		if ((par->board_type & 0x7) == 0x3)			ffb_type_name = "Creator 3D";		else			ffb_type_name = "Creator";	} else		ffb_type_name = "Elite 3D";	strlcpy(info->fix.id, ffb_type_name, sizeof(info->fix.id));	info->fix.type = FB_TYPE_PACKED_PIXELS;	info->fix.visual = FB_VISUAL_TRUECOLOR;	/* Framebuffer length is the same regardless of resolution. */	info->fix.line_length = 8192;	info->fix.accel = FB_ACCEL_SUN_CREATOR;}static int __devinit ffb_probe(struct of_device *op,			       const struct of_device_id *match){	struct device_node *dp = op->node;	struct ffb_fbc __iomem *fbc;	struct ffb_dac __iomem *dac;	struct fb_info *info;	struct ffb_par *par;	u32 dac_pnum, dac_rev, dac_mrev;	int err;	info = framebuffer_alloc(sizeof(struct ffb_par), &op->dev);	err = -ENOMEM;	if (!info)		goto out_err;	par = info->par;	spin_lock_init(&par->lock);	par->fbc = of_ioremap(&op->resource[2], 0,			      sizeof(struct ffb_fbc), "ffb fbc");	if (!par->fbc)		goto out_release_fb;	par->dac = of_ioremap(&op->resource[1], 0,			      sizeof(struct ffb_dac), "ffb dac");	if (!par->dac)		goto out_unmap_fbc;	par->rop_cache = FFB_ROP_NEW;	par->physbase = op->resource[0].start;	/* Don't mention copyarea, so SCROLL_REDRAW is always	 * used.  It is the fastest on this chip.	 */	info->flags = (FBINFO_DEFAULT |		       /* FBINFO_HWACCEL_COPYAREA | */		       FBINFO_HWACCEL_FILLRECT |		       FBINFO_HWACCEL_IMAGEBLIT);	info->fbops = &ffb_ops;	info->screen_base = (char *) par->physbase + FFB_DFB24_POFF;	info->pseudo_palette = par->pseudo_palette;	sbusfb_fill_var(&info->var, dp, 32);	par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4);	ffb_fixup_var_rgb(&info->var);	info->var.accel_flags = FB_ACCELF_TEXT;	if (!strcmp(dp->name, "SUNW,afb"))		par->flags |= FFB_FLAG_AFB;	par->board_type = of_getintprop_default(dp, "board_type", 0);	fbc = par->fbc;	if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)		upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);	dac = par->dac;	upa_writel(FFB_DAC_DID, &dac->type);	dac_pnum = upa_readl(&dac->value);	dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT;	dac_pnum = (dac_pnum & FFB_DAC_DID_PNUM) >> FFB_DAC_DID_PNUM_SHIFT;	upa_writel(FFB_DAC_UCTRL, &dac->type);	dac_mrev = upa_readl(&dac->value);	dac_mrev = (dac_mrev & FFB_DAC_UCTRL_MANREV) >>		FFB_DAC_UCTRL_MANREV_SHIFT;	/* Elite3D has different DAC revision numbering, and no DAC revisions	 * have the reversed meaning of cursor enable.  Otherwise, Pacifica 1	 * ramdacs with manufacturing revision less than 3 have inverted	 * cursor logic.  We identify Pacifica 1 as not Pacifica 2, the	 * latter having a part number value of 0x236e.	 */	if ((par->flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {		par->flags &= ~FFB_FLAG_INVCURSOR;	} else {		if (dac_mrev < 3)			par->flags |= FFB_FLAG_INVCURSOR;	}	ffb_switch_from_graph(par);	/* Unblank it just to be sure.  When there are multiple	 * FFB/AFB cards in the system, or it is not the OBP	 * chosen console, it will have video outputs off in	 * the DAC.	 */	ffb_blank(FB_BLANK_UNBLANK, info);	if (fb_alloc_cmap(&info->cmap, 256, 0))		goto out_unmap_dac;	ffb_init_fix(info);	err = register_framebuffer(info);	if (err < 0)		goto out_dealloc_cmap;	dev_set_drvdata(&op->dev, info);	printk(KERN_INFO "%s: %s at %016lx, type %d, "	       "DAC pnum[%x] rev[%d] manuf_rev[%d]\n",	       dp->full_name,	       ((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),	       par->physbase, par->board_type,	       dac_pnum, dac_rev, dac_mrev);	return 0;out_dealloc_cmap:	fb_dealloc_cmap(&info->cmap);out_unmap_dac:	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));out_unmap_fbc:	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));out_release_fb:	framebuffer_release(info);out_err:	return err;}static int __devexit ffb_remove(struct of_device *op){	struct fb_info *info = dev_get_drvdata(&op->dev);	struct ffb_par *par = info->par;	unregister_framebuffer(info);	fb_dealloc_cmap(&info->cmap);	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));	of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));	framebuffer_release(info);	dev_set_drvdata(&op->dev, NULL);	return 0;}static const struct of_device_id ffb_match[] = {	{		.name = "SUNW,ffb",	},	{		.name = "SUNW,afb",	},	{},};MODULE_DEVICE_TABLE(of, ffb_match);static struct of_platform_driver ffb_driver = {	.name		= "ffb",	.match_table	= ffb_match,	.probe		= ffb_probe,	.remove		= __devexit_p(ffb_remove),};static int __init ffb_init(void){	if (fb_get_options("ffb", NULL))		return -ENODEV;	return of_register_driver(&ffb_driver, &of_bus_type);}static void __exit ffb_exit(void){	of_unregister_driver(&ffb_driver);}module_init(ffb_init);module_exit(ffb_exit);MODULE_DESCRIPTION("framebuffer driver for Creator/Elite3D chipsets");MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");MODULE_VERSION("2.0");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -