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

📄 tgafb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	dealign = depos & 7;	sealign = sepos & 7;	/* ??? The documentation appears to be incorrect (or very	   misleading) wrt how pixel shifting works in backward copy	   mode, i.e. when PIXELSHIFT is negative.  I give up for now.	   Do handle the common case of co-aligned backward copies,	   but frob everything else back on generic code.  */	if (dealign != sealign) {		cfb_copyarea(info, area);		return;	}	/* We begin the copy with the trailing pixels of the	   unaligned destination.  */	mask_first = (1ul << dealign) - 1;	left = width - dealign;	/* Care for small copies.  */	if (dealign > width) {		mask_first ^= (1ul << (dealign - width)) - 1;		left = 0;	}	/* Next copy full words at a time.  */	n32 = left / 32;	left %= 32;	/* Finally copy the unaligned head of the span.  */	mask_last = -1 << (32 - left);	tga_regs = par->tga_regs_base;	tga_fb = par->tga_fb_base;	/* Set up the MODE and PIXELSHIFT registers.  */	__raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_COPY, tga_regs+TGA_MODE_REG);	__raw_writel(0, tga_regs+TGA_PIXELSHIFT_REG);	wmb();	for (i = 0; i < height; ++i) {		unsigned long j;		void __iomem *sfb;		void __iomem *dfb;		sfb = tga_fb + sepos;		dfb = tga_fb + depos;		if (mask_first) {			__raw_writel(mask_first, sfb);			wmb();			__raw_writel(mask_first, dfb);			wmb();		}		for (j = 0; j < n32; ++j) {			sfb -= 32;			dfb -= 32;			__raw_writel(0xffffffff, sfb);			wmb();			__raw_writel(0xffffffff, dfb);			wmb();		}		if (mask_last) {			sfb -= 32;			dfb -= 32;			__raw_writel(mask_last, sfb);			wmb();			__raw_writel(mask_last, dfb);			wmb();		}		sepos += yincr;		depos += yincr;	}	/* Reset the MODE register to normal.  */	__raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);}static voidtgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area) {	unsigned long dx, dy, width, height, sx, sy, vxres, vyres;	unsigned long line_length, bpp;	dx = area->dx;	dy = area->dy;	width = area->width;	height = area->height;	sx = area->sx;	sy = area->sy;	vxres = info->var.xres_virtual;	vyres = info->var.yres_virtual;	line_length = info->fix.line_length;	/* The top left corners must be in the virtual screen.  */	if (dx > vxres || sx > vxres || dy > vyres || sy > vyres)		return;	/* Clip the destination.  */	if (dx + width > vxres)		width = vxres - dx;	if (dy + height > vyres)		height = vyres - dy;	/* The source must be completely inside the virtual screen.  */	if (sx + width > vxres || sy + height > vyres)		return;	bpp = info->var.bits_per_pixel;	/* Detect copies of the entire line.  */	if (width * (bpp >> 3) == line_length) {		if (bpp == 8)			copyarea_line_8bpp(info, dy, sy, height, width);		else			copyarea_line_32bpp(info, dy, sy, height, width);	}	/* ??? The documentation is unclear to me exactly how the pixelshift	   register works in 32bpp mode.  Since I don't have hardware to test,	   give up for now and fall back on the generic routines.  */	else if (bpp == 32)		cfb_copyarea(info, area);	/* Detect overlapping source and destination that requires	   a backward copy.  */	else if (dy == sy && dx > sx && dx < sx + width)		copyarea_backward_8bpp(info, dx, dy, sx, sy, height,				       width, line_length, area);	else		copyarea_foreward_8bpp(info, dx, dy, sx, sy, height,				       width, line_length);}/* *  Initialisation */static voidtgafb_init_fix(struct fb_info *info){	struct tga_par *par = (struct tga_par *)info->par;	int tga_bus_pci = TGA_BUS_PCI(par->dev);	int tga_bus_tc = TGA_BUS_TC(par->dev);	u8 tga_type = par->tga_type;	const char *tga_type_name = NULL;	switch (tga_type) {	case TGA_TYPE_8PLANE:		if (tga_bus_pci)			tga_type_name = "Digital ZLXp-E1";		if (tga_bus_tc)			tga_type_name = "Digital ZLX-E1";		break;	case TGA_TYPE_24PLANE:		if (tga_bus_pci)			tga_type_name = "Digital ZLXp-E2";		if (tga_bus_tc)			tga_type_name = "Digital ZLX-E2";		break;	case TGA_TYPE_24PLUSZ:		if (tga_bus_pci)			tga_type_name = "Digital ZLXp-E3";		if (tga_bus_tc)			tga_type_name = "Digital ZLX-E3";		break;	default:		tga_type_name = "Unknown";		break;	}	strlcpy(info->fix.id, tga_type_name, sizeof(info->fix.id));	info->fix.type = FB_TYPE_PACKED_PIXELS;	info->fix.type_aux = 0;	info->fix.visual = (tga_type == TGA_TYPE_8PLANE			    ? FB_VISUAL_PSEUDOCOLOR			    : FB_VISUAL_DIRECTCOLOR);	info->fix.line_length = par->xres * (par->bits_per_pixel >> 3);	info->fix.smem_start = (size_t) par->tga_fb_base;	info->fix.smem_len = info->fix.line_length * par->yres;	info->fix.mmio_start = (size_t) par->tga_regs_base;	info->fix.mmio_len = 512;	info->fix.xpanstep = 0;	info->fix.ypanstep = 0;	info->fix.ywrapstep = 0;	info->fix.accel = FB_ACCEL_DEC_TGA;	/*	 * These are needed by fb_set_logo_truepalette(), so we	 * set them here for 24-plane cards.	 */	if (tga_type != TGA_TYPE_8PLANE) {		info->var.red.length = 8;		info->var.green.length = 8;		info->var.blue.length = 8;		info->var.red.offset = 16;		info->var.green.offset = 8;		info->var.blue.offset = 0;	}}static int tgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){	/* We just use this to catch switches out of graphics mode. */	tgafb_set_par(info); /* A bit of overkill for BASE_ADDR reset. */	return 0;}static int __devinittgafb_register(struct device *dev){	static const struct fb_videomode modedb_tc = {		/* 1280x1024 @ 72 Hz, 76.8 kHz hsync */		"1280x1024@72", 0, 1280, 1024, 7645, 224, 28, 33, 3, 160, 3,		FB_SYNC_ON_GREEN, FB_VMODE_NONINTERLACED	};	static unsigned int const fb_offset_presets[4] = {		TGA_8PLANE_FB_OFFSET,		TGA_24PLANE_FB_OFFSET,		0xffffffff,		TGA_24PLUSZ_FB_OFFSET	};	const struct fb_videomode *modedb_tga = NULL;	resource_size_t bar0_start = 0, bar0_len = 0;	const char *mode_option_tga = NULL;	int tga_bus_pci = TGA_BUS_PCI(dev);	int tga_bus_tc = TGA_BUS_TC(dev);	unsigned int modedbsize_tga = 0;	void __iomem *mem_base;	struct fb_info *info;	struct tga_par *par;	u8 tga_type;	int ret = 0;	/* Enable device in PCI config.  */	if (tga_bus_pci && pci_enable_device(to_pci_dev(dev))) {		printk(KERN_ERR "tgafb: Cannot enable PCI device\n");		return -ENODEV;	}	/* Allocate the fb and par structures.  */	info = framebuffer_alloc(sizeof(struct tga_par), dev);	if (!info) {		printk(KERN_ERR "tgafb: Cannot allocate memory\n");		return -ENOMEM;	}	par = info->par;	dev_set_drvdata(dev, info);	/* Request the mem regions.  */	ret = -ENODEV;	if (tga_bus_pci) {		bar0_start = pci_resource_start(to_pci_dev(dev), 0);		bar0_len = pci_resource_len(to_pci_dev(dev), 0);	}	if (tga_bus_tc) {		bar0_start = to_tc_dev(dev)->resource.start;		bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1;	}	if (!request_mem_region (bar0_start, bar0_len, "tgafb")) {		printk(KERN_ERR "tgafb: cannot reserve FB region\n");		goto err0;	}	/* Map the framebuffer.  */	mem_base = ioremap_nocache(bar0_start, bar0_len);	if (!mem_base) {		printk(KERN_ERR "tgafb: Cannot map MMIO\n");		goto err1;	}	/* Grab info about the card.  */	tga_type = (readl(mem_base) >> 12) & 0x0f;	par->dev = dev;	par->tga_mem_base = mem_base;	par->tga_fb_base = mem_base + fb_offset_presets[tga_type];	par->tga_regs_base = mem_base + TGA_REGS_OFFSET;	par->tga_type = tga_type;	if (tga_bus_pci)		par->tga_chip_rev = (to_pci_dev(dev))->revision;	if (tga_bus_tc)		par->tga_chip_rev = TGA_READ_REG(par, TGA_START_REG) & 0xff;	/* Setup framebuffer.  */	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |		      FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;	info->fbops = &tgafb_ops;	info->screen_base = par->tga_fb_base;	info->pseudo_palette = par->palette;	/* This should give a reasonable default video mode.  */	if (tga_bus_pci) {		mode_option_tga = mode_option_pci;	}	if (tga_bus_tc) {		mode_option_tga = mode_option_tc;		modedb_tga = &modedb_tc;		modedbsize_tga = 1;	}	ret = fb_find_mode(&info->var, info,			   mode_option ? mode_option : mode_option_tga,			   modedb_tga, modedbsize_tga, NULL,			   tga_type == TGA_TYPE_8PLANE ? 8 : 32);	if (ret == 0 || ret == 4) {		printk(KERN_ERR "tgafb: Could not find valid video mode\n");		ret = -EINVAL;		goto err1;	}	if (fb_alloc_cmap(&info->cmap, 256, 0)) {		printk(KERN_ERR "tgafb: Could not allocate color map\n");		ret = -ENOMEM;		goto err1;	}	tgafb_set_par(info);	tgafb_init_fix(info);	if (register_framebuffer(info) < 0) {		printk(KERN_ERR "tgafb: Could not register framebuffer\n");		ret = -EINVAL;		goto err1;	}	if (tga_bus_pci) {		pr_info("tgafb: DC21030 [TGA] detected, rev=0x%02x\n",			par->tga_chip_rev);		pr_info("tgafb: at PCI bus %d, device %d, function %d\n",			to_pci_dev(dev)->bus->number,			PCI_SLOT(to_pci_dev(dev)->devfn),			PCI_FUNC(to_pci_dev(dev)->devfn));	}	if (tga_bus_tc)		pr_info("tgafb: SFB+ detected, rev=0x%02x\n",			par->tga_chip_rev);	pr_info("fb%d: %s frame buffer device at 0x%lx\n",		info->node, info->fix.id, (long)bar0_start);	return 0; err1:	if (mem_base)		iounmap(mem_base);	release_mem_region(bar0_start, bar0_len); err0:	framebuffer_release(info);	return ret;}static void __devexittgafb_unregister(struct device *dev){	resource_size_t bar0_start = 0, bar0_len = 0;	int tga_bus_pci = TGA_BUS_PCI(dev);	int tga_bus_tc = TGA_BUS_TC(dev);	struct fb_info *info = NULL;	struct tga_par *par;	info = dev_get_drvdata(dev);	if (!info)		return;	par = info->par;	unregister_framebuffer(info);	fb_dealloc_cmap(&info->cmap);	iounmap(par->tga_mem_base);	if (tga_bus_pci) {		bar0_start = pci_resource_start(to_pci_dev(dev), 0);		bar0_len = pci_resource_len(to_pci_dev(dev), 0);	}	if (tga_bus_tc) {		bar0_start = to_tc_dev(dev)->resource.start;		bar0_len = to_tc_dev(dev)->resource.end - bar0_start + 1;	}	release_mem_region(bar0_start, bar0_len);	framebuffer_release(info);}static void __devexittgafb_exit(void){	tc_unregister_driver(&tgafb_tc_driver);	pci_unregister_driver(&tgafb_pci_driver);}#ifndef MODULEstatic int __devinittgafb_setup(char *arg){	char *this_opt;	if (arg && *arg) {		while ((this_opt = strsep(&arg, ","))) {			if (!*this_opt)				continue;			if (!strncmp(this_opt, "mode:", 5))				mode_option = this_opt+5;			else				printk(KERN_ERR				       "tgafb: unknown parameter %s\n",				       this_opt);		}	}	return 0;}#endif /* !MODULE */static int __devinittgafb_init(void){	int status;#ifndef MODULE	char *option = NULL;	if (fb_get_options("tgafb", &option))		return -ENODEV;	tgafb_setup(option);#endif	status = pci_register_driver(&tgafb_pci_driver);	if (!status)		status = tc_register_driver(&tgafb_tc_driver);	return status;}/* *  Modularisation */module_init(tgafb_init);module_exit(tgafb_exit);MODULE_DESCRIPTION("Framebuffer driver for TGA/SFB+ chipset");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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