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

📄 tridentfb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	tmp = (htotal >> 8) & 0x01;	tmp |= (hdispend >> 7) & 0x02;	tmp |= (hsyncstart >> 5) & 0x08;	tmp |= (hblankstart >> 4) & 0x10;	write3X4(par, HorizOverflow, tmp);	tmp = 0x40;	if (vblankstart & 0x200) tmp |= 0x20;//FIXME	if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80;  /* double scan for 200 line modes */	write3X4(par, VGA_CRTC_MAX_SCAN, tmp);	write3X4(par, VGA_CRTC_LINE_COMPARE, 0xFF);	write3X4(par, VGA_CRTC_PRESET_ROW, 0);	write3X4(par, VGA_CRTC_MODE, 0xC3);	write3X4(par, LinearAddReg, 0x20);	/* enable linear addressing */	tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80;	/* enable access extended memory */	write3X4(par, CRTCModuleTest, tmp);	tmp = read3CE(par, MiscIntContReg) & ~0x4;	if (info->var.vmode & FB_VMODE_INTERLACED)		tmp |= 0x4;	write3CE(par, MiscIntContReg, tmp);	/* enable GE for text acceleration */	write3X4(par, GraphEngReg, 0x80);	switch (bpp) {	case 8:		tmp = 0x00;		break;	case 16:		tmp = 0x05;		break;	case 24:		tmp = 0x29;		break;	case 32:		tmp = 0x09;		break;	}	write3X4(par, PixelBusReg, tmp);	tmp = read3X4(par, DRAMControl);	if (!is_oldprotect(par->chip_id))		tmp |= 0x10;	if (iscyber(par->chip_id))		tmp |= 0x20;	write3X4(par, DRAMControl, tmp);	/* both IO, linear enable */	write3X4(par, InterfaceSel, read3X4(par, InterfaceSel) | 0x40);	if (!is_xp(par->chip_id))		write3X4(par, Performance, read3X4(par, Performance) | 0x10);	/* MMIO & PCI read and write burst enable */	if (par->chip_id != TGUI9440 && par->chip_id != IMAGE975)		write3X4(par, PCIReg, read3X4(par, PCIReg) | 0x06);	vga_mm_wseq(par->io_virt, 0, 3);	vga_mm_wseq(par->io_virt, 1, 1); /* set char clock 8 dots wide */	/* enable 4 maps because needed in chain4 mode */	vga_mm_wseq(par->io_virt, 2, 0x0F);	vga_mm_wseq(par->io_virt, 3, 0);	vga_mm_wseq(par->io_virt, 4, 0x0E); /* memory mode enable bitmaps ?? */	/* convert from picoseconds to kHz */	vclk = PICOS2KHZ(info->var.pixclock);	/* divide clock by 2 if 32bpp chain4 mode display and CPU path */	tmp = read3CE(par, MiscExtFunc) & 0xF0;	if (bpp == 32 || (par->chip_id == TGUI9440 && bpp == 16)) {		tmp |= 8;		vclk *= 2;	}	set_vclk(par, vclk);	write3CE(par, MiscExtFunc, tmp | 0x12);	write3CE(par, 0x5, 0x40);	/* no CGA compat, allow 256 col */	write3CE(par, 0x6, 0x05);	/* graphics mode */	write3CE(par, 0x7, 0x0F);	/* planes? */	/* graphics mode and support 256 color modes */	writeAttr(par, 0x10, 0x41);	writeAttr(par, 0x12, 0x0F);	/* planes */	writeAttr(par, 0x13, 0);	/* horizontal pel panning */	/* colors */	for (tmp = 0; tmp < 0x10; tmp++)		writeAttr(par, tmp, tmp);	fb_readb(par->io_virt + VGA_IS1_RC);	/* flip-flop to index */	t_outb(par, 0x20, VGA_ATT_W);		/* enable attr */	switch (bpp) {	case 8:		tmp = 0;		break;	case 16:		tmp = 0x30;		break;	case 24:	case 32:		tmp = 0xD0;		break;	}	t_inb(par, VGA_PEL_IW);	t_inb(par, VGA_PEL_MSK);	t_inb(par, VGA_PEL_MSK);	t_inb(par, VGA_PEL_MSK);	t_inb(par, VGA_PEL_MSK);	t_outb(par, tmp, VGA_PEL_MSK);	t_inb(par, VGA_PEL_IW);	if (par->flatpanel)		set_number_of_lines(par, info->var.yres);	info->fix.line_length = info->var.xres_virtual * bpp / 8;	set_lwidth(par, info->fix.line_length / 8);	if (!(info->flags & FBINFO_HWACCEL_DISABLED))		par->init_accel(par, info->var.xres_virtual, bpp);	info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;	info->cmap.len = (bpp == 8) ? 256 : 16;	debug("exit\n");	return 0;}/* Set one color register */static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,			       unsigned blue, unsigned transp,			       struct fb_info *info){	int bpp = info->var.bits_per_pixel;	struct tridentfb_par *par = info->par;	if (regno >= info->cmap.len)		return 1;	if (bpp == 8) {		t_outb(par, 0xFF, VGA_PEL_MSK);		t_outb(par, regno, VGA_PEL_IW);		t_outb(par, red >> 10, VGA_PEL_D);		t_outb(par, green >> 10, VGA_PEL_D);		t_outb(par, blue >> 10, VGA_PEL_D);	} else if (regno < 16) {		if (bpp == 16) {	/* RGB 565 */			u32 col;			col = (red & 0xF800) | ((green & 0xFC00) >> 5) |				((blue & 0xF800) >> 11);			col |= col << 16;			((u32 *)(info->pseudo_palette))[regno] = col;		} else if (bpp == 32)		/* ARGB 8888 */			((u32 *)info->pseudo_palette)[regno] =				((transp & 0xFF00) << 16)	|				((red & 0xFF00) << 8)		|				((green & 0xFF00))		|				((blue & 0xFF00) >> 8);	}	return 0;}/* Try blanking the screen. For flat panels it does nothing */static int tridentfb_blank(int blank_mode, struct fb_info *info){	unsigned char PMCont, DPMSCont;	struct tridentfb_par *par = info->par;	debug("enter\n");	if (par->flatpanel)		return 0;	t_outb(par, 0x04, 0x83C8); /* Read DPMS Control */	PMCont = t_inb(par, 0x83C6) & 0xFC;	DPMSCont = read3CE(par, PowerStatus) & 0xFC;	switch (blank_mode) {	case FB_BLANK_UNBLANK:		/* Screen: On, HSync: On, VSync: On */	case FB_BLANK_NORMAL:		/* Screen: Off, HSync: On, VSync: On */		PMCont |= 0x03;		DPMSCont |= 0x00;		break;	case FB_BLANK_HSYNC_SUSPEND:		/* Screen: Off, HSync: Off, VSync: On */		PMCont |= 0x02;		DPMSCont |= 0x01;		break;	case FB_BLANK_VSYNC_SUSPEND:		/* Screen: Off, HSync: On, VSync: Off */		PMCont |= 0x02;		DPMSCont |= 0x02;		break;	case FB_BLANK_POWERDOWN:		/* Screen: Off, HSync: Off, VSync: Off */		PMCont |= 0x00;		DPMSCont |= 0x03;		break;	}	write3CE(par, PowerStatus, DPMSCont);	t_outb(par, 4, 0x83C8);	t_outb(par, PMCont, 0x83C6);	debug("exit\n");	/* let fbcon do a softblank for us */	return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;}static struct fb_ops tridentfb_ops = {	.owner = THIS_MODULE,	.fb_setcolreg = tridentfb_setcolreg,	.fb_pan_display = tridentfb_pan_display,	.fb_blank = tridentfb_blank,	.fb_check_var = tridentfb_check_var,	.fb_set_par = tridentfb_set_par,	.fb_fillrect = tridentfb_fillrect,	.fb_copyarea = tridentfb_copyarea,	.fb_imageblit = tridentfb_imageblit,#ifdef CONFIG_FB_TRIDENT_ACCEL	.fb_sync = tridentfb_sync,#endif};static int __devinit trident_pci_probe(struct pci_dev *dev,				       const struct pci_device_id *id){	int err;	unsigned char revision;	struct fb_info *info;	struct tridentfb_par *default_par;	int chip3D;	int chip_id;	err = pci_enable_device(dev);	if (err)		return err;	info = framebuffer_alloc(sizeof(struct tridentfb_par), &dev->dev);	if (!info)		return -ENOMEM;	default_par = info->par;	chip_id = id->device;#ifndef CONFIG_FB_TRIDENT_ACCEL	noaccel = 1;#endif	/* If PCI id is 0x9660 then further detect chip type */	if (chip_id == TGUI9660) {		revision = vga_io_rseq(RevisionID);		switch (revision) {		case 0x21:			chip_id = PROVIDIA9685;			break;		case 0x22:		case 0x23:			chip_id = CYBER9397;			break;		case 0x2A:			chip_id = CYBER9397DVD;			break;		case 0x30:		case 0x33:		case 0x34:		case 0x35:		case 0x38:		case 0x3A:		case 0xB3:			chip_id = CYBER9385;			break;		case 0x40 ... 0x43:			chip_id = CYBER9382;			break;		case 0x4A:			chip_id = CYBER9388;			break;		default:			break;		}	}	chip3D = is3Dchip(chip_id);	if (is_xp(chip_id)) {		default_par->init_accel = xp_init_accel;		default_par->wait_engine = xp_wait_engine;		default_par->fill_rect = xp_fill_rect;		default_par->copy_rect = xp_copy_rect;		tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADEXP;	} else if (is_blade(chip_id)) {		default_par->init_accel = blade_init_accel;		default_par->wait_engine = blade_wait_engine;		default_par->fill_rect = blade_fill_rect;		default_par->copy_rect = blade_copy_rect;		default_par->image_blit = blade_image_blit;		tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADE3D;	} else if (chip3D) {			/* 3DImage family left */		default_par->init_accel = image_init_accel;		default_par->wait_engine = image_wait_engine;		default_par->fill_rect = image_fill_rect;		default_par->copy_rect = image_copy_rect;		tridentfb_fix.accel = FB_ACCEL_TRIDENT_3DIMAGE;	} else { 				/* TGUI 9440/96XX family */		default_par->init_accel = tgui_init_accel;		default_par->wait_engine = xp_wait_engine;		default_par->fill_rect = tgui_fill_rect;		default_par->copy_rect = tgui_copy_rect;		tridentfb_fix.accel = FB_ACCEL_TRIDENT_TGUI;	}	default_par->chip_id = chip_id;	/* setup MMIO region */	tridentfb_fix.mmio_start = pci_resource_start(dev, 1);	tridentfb_fix.mmio_len = pci_resource_len(dev, 1);	if (!request_mem_region(tridentfb_fix.mmio_start,				tridentfb_fix.mmio_len, "tridentfb")) {		debug("request_region failed!\n");		framebuffer_release(info);		return -1;	}	default_par->io_virt = ioremap_nocache(tridentfb_fix.mmio_start,					       tridentfb_fix.mmio_len);	if (!default_par->io_virt) {		debug("ioremap failed\n");		err = -1;		goto out_unmap1;	}	enable_mmio(default_par);	/* setup framebuffer memory */	tridentfb_fix.smem_start = pci_resource_start(dev, 0);	tridentfb_fix.smem_len = get_memsize(default_par);	if (!request_mem_region(tridentfb_fix.smem_start,				tridentfb_fix.smem_len, "tridentfb")) {		debug("request_mem_region failed!\n");		disable_mmio(info->par);		err = -1;		goto out_unmap1;	}	info->screen_base = ioremap_nocache(tridentfb_fix.smem_start,					    tridentfb_fix.smem_len);	if (!info->screen_base) {		debug("ioremap failed\n");		err = -1;		goto out_unmap2;	}	default_par->flatpanel = is_flatpanel(default_par);	if (default_par->flatpanel)		nativex = get_nativex(default_par);	info->fix = tridentfb_fix;	info->fbops = &tridentfb_ops;	info->pseudo_palette = default_par->pseudo_pal;	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;	if (!noaccel && default_par->init_accel) {		info->flags &= ~FBINFO_HWACCEL_DISABLED;		info->flags |= FBINFO_HWACCEL_COPYAREA;		info->flags |= FBINFO_HWACCEL_FILLRECT;	} else		info->flags |= FBINFO_HWACCEL_DISABLED;	info->pixmap.addr = kmalloc(4096, GFP_KERNEL);	if (!info->pixmap.addr) {		err = -ENOMEM;		goto out_unmap2;	}	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;	if (default_par->image_blit) {		info->flags |= FBINFO_HWACCEL_IMAGEBLIT;		info->pixmap.scan_align = 4;	}	if (noaccel) {		printk(KERN_DEBUG "disabling acceleration\n");		info->flags |= FBINFO_HWACCEL_DISABLED;		info->pixmap.scan_align = 1;	}	if (!fb_find_mode(&info->var, info,			  mode_option, NULL, 0, NULL, bpp)) {		err = -EINVAL;		goto out_unmap2;	}	err = fb_alloc_cmap(&info->cmap, 256, 0);	if (err < 0)		goto out_unmap2;	info->var.activate |= FB_ACTIVATE_NOW;	info->device = &dev->dev;	if (register_framebuffer(info) < 0) {		printk(KERN_ERR "tridentfb: could not register framebuffer\n");		fb_dealloc_cmap(&info->cmap);		err = -EINVAL;		goto out_unmap2;	}	output("fb%d: %s frame buffer device %dx%d-%dbpp\n",	   info->node, info->fix.id, info->var.xres,	   info->var.yres, info->var.bits_per_pixel);	pci_set_drvdata(dev, info);	return 0;out_unmap2:	kfree(info->pixmap.addr);	if (info->screen_base)		iounmap(info->screen_base);	release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);	disable_mmio(info->par);out_unmap1:	if (default_par->io_virt)		iounmap(default_par->io_virt);	release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);	framebuffer_release(info);	return err;}static void __devexit trident_pci_remove(struct pci_dev *dev){	struct fb_info *info = pci_get_drvdata(dev);	struct tridentfb_par *par = info->par;	unregister_framebuffer(info);	iounmap(par->io_virt);	iounmap(info->screen_base);	release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);	release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);	pci_set_drvdata(dev, NULL);	kfree(info->pixmap.addr);	framebuffer_release(info);}/* List of boards that we are trying to support */static struct pci_device_id trident_devices[] = {	{PCI_VENDOR_ID_TRIDENT,	BLADE3D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEi7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEi7D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEAi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEE4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	TGUI9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	TGUI9660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	IMAGE975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	IMAGE985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBER9320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBER9388, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBER9520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBER9525DVD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBER9397, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBER9397DVD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEXPAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEXPm8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{PCI_VENDOR_ID_TRIDENT,	CYBERBLADEXPm16, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{0,}};MODULE_DEVICE_TABLE(pci, trident_devices);static struct pci_driver tridentfb_pci_driver = {	.name = "tridentfb",	.id_table = trident_devices,	.probe = trident_pci_probe,	.remove = __devexit_p(trident_pci_remove)};/* * Parse user specified options (`video=trident:') * example: *	video=trident:800x600,bpp=16,noaccel */#ifndef MODULEstatic int __init tridentfb_setup(char *options){	char *opt;	if (!options || !*options)		return 0;	while ((opt = strsep(&options, ",")) != NULL) {		if (!*opt)			continue;		if (!strncmp(opt, "noaccel", 7))			noaccel = 1;		else if (!strncmp(opt, "fp", 2))			fp = 1;		else if (!strncmp(opt, "crt", 3))			fp = 0;		else if (!strncmp(opt, "bpp=", 4))			bpp = simple_strtoul(opt + 4, NULL, 0);		else if (!strncmp(opt, "center", 6))			center = 1;		else if (!strncmp(opt, "stretch", 7))			stretch = 1;		else if (!strncmp(opt, "memsize=", 8))			memsize = simple_strtoul(opt + 8, NULL, 0);		else if (!strncmp(opt, "memdiff=", 8))			memdiff = simple_strtoul(opt + 8, NULL, 0);		else if (!strncmp(opt, "nativex=", 8))			nativex = simple_strtoul(opt + 8, NULL, 0);		else			mode_option = opt;	}	return 0;}#endifstatic int __init tridentfb_init(void){#ifndef MODULE	char *option = NULL;	if (fb_get_options("tridentfb", &option))		return -ENODEV;	tridentfb_setup(option);#endif	return pci_register_driver(&tridentfb_pci_driver);}static void __exit tridentfb_exit(void){	pci_unregister_driver(&tridentfb_pci_driver);}module_init(tridentfb_init);module_exit(tridentfb_exit);MODULE_AUTHOR("Jani Monoses <jani@iv.ro>");MODULE_DESCRIPTION("Framebuffer driver for Trident cards");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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