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

📄 sstfb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	struct sstfb_par *par = info->par;	u8 pll_ctrl;	sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL);	pll_ctrl = sst_dac_read(DACREG_ICS_PLLDATA);	switch(clock) {	case VID_CLOCK:		sst_dac_write(DACREG_ICS_PLLWMA, 0x0);	/* CLK0, f0 */		sst_dac_write(DACREG_ICS_PLLDATA, t->m);		sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);		/* selects freq f0 for clock 0 */		sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);		sst_dac_write(DACREG_ICS_PLLDATA,		              (pll_ctrl & 0xd8)		              | DACREG_ICS_CLK0		              | DACREG_ICS_CLK0_0);		break;	case GFX_CLOCK :		sst_dac_write(DACREG_ICS_PLLWMA, 0xa);	/* CLK1, fA */		sst_dac_write(DACREG_ICS_PLLDATA, t->m);		sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);		/* selects freq fA for clock 1 */		sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);		sst_dac_write(DACREG_ICS_PLLDATA,		              (pll_ctrl & 0xef) | DACREG_ICS_CLK1_A);		break;	default:		dprintk("%s: wrong clock code '%d'\n",		        __func__, clock);		return 0;		}	udelay(300);	return 1;}static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp){	struct sstfb_par *par = info->par;	u8 cr0;	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */	sst_dac_read(DACREG_RMR);	/* read 4 times RMR */	sst_dac_read(DACREG_RMR);	sst_dac_read(DACREG_RMR);	sst_dac_read(DACREG_RMR);	/* the fifth time,  CR0 is read */	cr0 = sst_dac_read(DACREG_RMR);	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */	sst_dac_read(DACREG_RMR);	/* read 4 times RMR */	sst_dac_read(DACREG_RMR);	sst_dac_read(DACREG_RMR);	sst_dac_read(DACREG_RMR);	/* cr0 */	switch(bpp) {	case 16:		sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_16BPP);		break;	default:		dprintk("%s: bad depth '%u'\n", __func__, bpp);		break;	}}static void sst_set_vidmod_ics(struct fb_info *info, const int bpp){	struct sstfb_par *par = info->par;	switch(bpp) {	case 16:		sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP);		break;	default:		dprintk("%s: bad depth '%u'\n", __func__, bpp);		break;	}}/* * detect dac type * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset, * dram refresh disabled, FbiInit remaped. * TODO: mmh.. maybe i shoud put the "prerequisite" in the func ... */static struct dac_switch dacs[] __devinitdata = {	{	.name		= "TI TVP3409",		.detect		= sst_detect_ti,		.set_pll	= sst_set_pll_att_ti,		.set_vidmod	= sst_set_vidmod_att_ti },	{	.name		= "AT&T ATT20C409",		.detect		= sst_detect_att,		.set_pll	= sst_set_pll_att_ti,		.set_vidmod	= sst_set_vidmod_att_ti },	{	.name		= "ICS ICS5342",		.detect		= sst_detect_ics,		.set_pll	= sst_set_pll_ics,		.set_vidmod	= sst_set_vidmod_ics },};static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par){	int i, ret = 0;	for (i = 0; i < ARRAY_SIZE(dacs); i++) {		ret = dacs[i].detect(info);		if (ret)			break;	}	if (!ret)		return 0;	f_dprintk("%s found %s\n", __func__, dacs[i].name);	par->dac_sw = dacs[i];	return 1;}/* * Internal Routines */static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par){	u32 fbiinit0, fbiinit1, fbiinit4;	struct pci_dev *dev = par->dev;	struct pll_timing gfx_timings;	struct sst_spec *spec;	int Fout;	int gfx_clock;	spec = &voodoo_spec[par->type];	f_ddprintk(" fbiinit0   fbiinit1   fbiinit2   fbiinit3   fbiinit4  "	           " fbiinit6\n");	f_ddprintk("%0#10x %0#10x %0#10x %0#10x %0#10x %0#10x\n",	            sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2),	            sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6));	/* disable video clock */	pci_write_config_dword(dev, PCI_VCLK_DISABLE, 0);	/* enable writing to init registers, disable pci fifo */	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);	/* reset video */	sst_set_bits(FBIINIT1, VIDEO_RESET);	sst_wait_idle();	/* reset gfx + pci fifo */	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);	sst_wait_idle();	/* unreset fifo */	/*sst_unset_bits(FBIINIT0, FIFO_RESET);	sst_wait_idle();*/	/* unreset FBI */	/*sst_unset_bits(FBIINIT0, FBI_RESET);	sst_wait_idle();*/	/* disable dram refresh */	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);	sst_wait_idle();	/* remap fbinit2/3 to dac */	pci_write_config_dword(dev, PCI_INIT_ENABLE,				PCI_EN_INIT_WR | PCI_REMAP_DAC );	/* detect dac type */	if (!sst_detect_dactype(info, par)) {		printk(KERN_ERR "sstfb: unknown dac type.\n");		//FIXME watch it: we are not in a safe state, bad bad bad.		return 0;	}	/* set graphic clock */	gfx_clock = spec->default_gfx_clock;	if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {		printk(KERN_INFO "sstfb: Using supplied graphic freq : %dMHz\n", gfxclk);		 gfx_clock = gfxclk *1000;	} else if (gfxclk) {		printk(KERN_WARNING "sstfb: %dMhz is way out of spec! Using default\n", gfxclk);	}	sst_calc_pll(gfx_clock, &Fout, &gfx_timings);	par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);	/* disable fbiinit remap */	pci_write_config_dword(dev, PCI_INIT_ENABLE,	                       PCI_EN_INIT_WR| PCI_EN_FIFO_WR );	/* defaults init registers */	/* FbiInit0: unreset gfx, unreset fifo */	fbiinit0 = FBIINIT0_DEFAULT;	fbiinit1 = FBIINIT1_DEFAULT;	fbiinit4 = FBIINIT4_DEFAULT;	par->vgapass = vgapass;	if (par->vgapass)		fbiinit0 &= ~DIS_VGA_PASSTHROUGH;	else		fbiinit0 |= DIS_VGA_PASSTHROUGH;	if (slowpci) {		fbiinit1 |= SLOW_PCI_WRITES;		fbiinit4 |= SLOW_PCI_READS;	} else {		fbiinit1 &= ~SLOW_PCI_WRITES;		fbiinit4 &= ~SLOW_PCI_READS;	}	sst_write(FBIINIT0, fbiinit0);	sst_wait_idle();	sst_write(FBIINIT1, fbiinit1);	sst_wait_idle();	sst_write(FBIINIT2, FBIINIT2_DEFAULT);	sst_wait_idle();	sst_write(FBIINIT3, FBIINIT3_DEFAULT);	sst_wait_idle();	sst_write(FBIINIT4, fbiinit4);	sst_wait_idle();	if (IS_VOODOO2(par)) {		sst_write(FBIINIT6, FBIINIT6_DEFAULT);		sst_wait_idle();	}	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);	pci_write_config_dword(dev, PCI_VCLK_ENABLE, 0);	return 1;}static void  __devexit sst_shutdown(struct fb_info *info){	struct sstfb_par *par = info->par;	struct pci_dev *dev = par->dev;	struct pll_timing gfx_timings;	int Fout;	/* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);	sst_set_bits(FBIINIT1, VIDEO_RESET | EN_BLANKING);	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);	sst_wait_idle();	pci_write_config_dword(dev, PCI_INIT_ENABLE,	                       PCI_EN_INIT_WR | PCI_REMAP_DAC);	/* set 20Mhz gfx clock */	sst_calc_pll(20000, &Fout, &gfx_timings);	par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);	/* TODO maybe shutdown the dac, vrefresh and so on... */	pci_write_config_dword(dev, PCI_INIT_ENABLE,	                       PCI_EN_INIT_WR);	sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | DIS_VGA_PASSTHROUGH);	pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);	/* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct	 * from start ? */	pci_write_config_dword(dev, PCI_INIT_ENABLE, 0);}/* * Interface to the world */static int  __devinit sstfb_setup(char *options){	char *this_opt;	if (!options || !*options)		return 0;	while ((this_opt = strsep(&options, ",")) != NULL) {		if (!*this_opt) continue;		f_ddprintk("option %s\n", this_opt);		if (!strcmp(this_opt, "vganopass"))			vgapass = 0;		else if (!strcmp(this_opt, "vgapass"))			vgapass = 1;		else if (!strcmp(this_opt, "clipping"))		        clipping = 1;		else if (!strcmp(this_opt, "noclipping"))		        clipping = 0;		else if (!strcmp(this_opt, "fastpci"))		        slowpci = 0;		else if (!strcmp(this_opt, "slowpci"))		        slowpci = 1;		else if (!strncmp(this_opt, "mem:",4))			mem = simple_strtoul (this_opt+4, NULL, 0);		else if (!strncmp(this_opt, "gfxclk:",7))			gfxclk = simple_strtoul (this_opt+7, NULL, 0);		else			mode_option = this_opt;	}	return 0;}static struct fb_ops sstfb_ops = {	.owner		= THIS_MODULE,	.fb_check_var	= sstfb_check_var,	.fb_set_par	= sstfb_set_par,	.fb_setcolreg	= sstfb_setcolreg,	.fb_fillrect	= cfb_fillrect, /* sstfb_fillrect */	.fb_copyarea	= cfb_copyarea, /* sstfb_copyarea */	.fb_imageblit	= cfb_imageblit,	.fb_ioctl	= sstfb_ioctl,};static int __devinit sstfb_probe(struct pci_dev *pdev,			const struct pci_device_id *id){	struct fb_info *info;	struct fb_fix_screeninfo *fix;	struct sstfb_par *par;	struct sst_spec *spec;	int err;	/* Enable device in PCI config. */	if ((err=pci_enable_device(pdev))) {		printk(KERN_ERR "cannot enable device\n");		return err;	}	/* Allocate the fb and par structures.  */	info = framebuffer_alloc(sizeof(struct sstfb_par), &pdev->dev);	if (!info)		return -ENOMEM;	pci_set_drvdata(pdev, info);		par  = info->par;	fix  = &info->fix;		par->type = id->driver_data;	spec = &voodoo_spec[par->type];	f_ddprintk("found device : %s\n", spec->name);	par->dev = pdev;	par->revision = pdev->revision;	fix->mmio_start = pci_resource_start(pdev,0);	fix->mmio_len	= 0x400000;	fix->smem_start = fix->mmio_start + 0x400000;	if (!request_mem_region(fix->mmio_start, fix->mmio_len, "sstfb MMIO")) {		printk(KERN_ERR "sstfb: cannot reserve mmio memory\n");		goto fail_mmio_mem;	}	if (!request_mem_region(fix->smem_start, 0x400000,"sstfb FB")) {		printk(KERN_ERR "sstfb: cannot reserve fb memory\n");		goto fail_fb_mem;	}	par->mmio_vbase = ioremap_nocache(fix->mmio_start,					fix->mmio_len);	if (!par->mmio_vbase) {		printk(KERN_ERR "sstfb: cannot remap register area %#lx\n",		        fix->mmio_start);		goto fail_mmio_remap;	}	info->screen_base = ioremap_nocache(fix->smem_start, 0x400000);	if (!info->screen_base) {		printk(KERN_ERR "sstfb: cannot remap framebuffer %#lx\n",		        fix->smem_start);		goto fail_fb_remap;	}	if (!sst_init(info, par)) {		printk(KERN_ERR "sstfb: Init failed\n");		goto fail;	}	sst_get_memsize(info, &fix->smem_len);	strlcpy(fix->id, spec->name, sizeof(fix->id));	printk(KERN_INFO "%s (revision %d) with %s dac\n",		fix->id, par->revision, par->dac_sw.name);	printk(KERN_INFO "framebuffer at %#lx, mapped to 0x%p, size %dMB\n",	        fix->smem_start, info->screen_base,	        fix->smem_len >> 20);	f_ddprintk("regbase_virt: %#lx\n", par->mmio_vbase);	f_ddprintk("membase_phys: %#lx\n", fix->smem_start);	f_ddprintk("fbbase_virt: %p\n", info->screen_base);	info->flags	= FBINFO_DEFAULT;	info->fbops	= &sstfb_ops;	info->pseudo_palette = par->palette;	fix->type	= FB_TYPE_PACKED_PIXELS;	fix->visual	= FB_VISUAL_TRUECOLOR;	fix->accel	= FB_ACCEL_NONE;  /* FIXME */	/*	 * According to the specs, the linelength must be of 1024 *pixels*	 * and the 24bpp mode is in fact a 32 bpp mode (and both are in	 * fact dithered to 16bit).	 */	fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */		fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);	if (sstfb_check_var(&info->var, info)) {		printk(KERN_ERR "sstfb: invalid video mode.\n");		goto fail;	}	if (sstfb_set_par(info)) {		printk(KERN_ERR "sstfb: can't set default video mode.\n");		goto fail;	}		fb_alloc_cmap(&info->cmap, 256, 0);	/* register fb */	info->device = &pdev->dev;	if (register_framebuffer(info) < 0) {		printk(KERN_ERR "sstfb: can't register framebuffer.\n");		goto fail;	}	sstfb_clear_screen(info);	if (device_create_file(info->dev, &device_attrs[0]))		printk(KERN_WARNING "sstfb: can't create sysfs entry.\n");	printk(KERN_INFO "fb%d: %s frame buffer device at 0x%p\n",	       info->node, fix->id, info->screen_base);	return 0;fail:	fb_dealloc_cmap(&info->cmap);	iounmap(info->screen_base);fail_fb_remap:	iounmap(par->mmio_vbase);fail_mmio_remap:	release_mem_region(fix->smem_start, 0x400000);fail_fb_mem:	release_mem_region(fix->mmio_start, info->fix.mmio_len);fail_mmio_mem:	framebuffer_release(info);	return -ENXIO; 	/* no voodoo detected */}static void __devexit sstfb_remove(struct pci_dev *pdev){	struct sstfb_par *par;	struct fb_info *info;	info = pci_get_drvdata(pdev);	par = info->par;		device_remove_file(info->dev, &device_attrs[0]);	sst_shutdown(info);	iounmap(info->screen_base);	iounmap(par->mmio_vbase);	release_mem_region(info->fix.smem_start, 0x400000);	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);	fb_dealloc_cmap(&info->cmap);	unregister_framebuffer(info);	framebuffer_release(info);}static const struct pci_device_id sstfb_id_tbl[] = {	{ PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO ),		.driver_data = ID_VOODOO1, },	{ PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2),		.driver_data = ID_VOODOO2, },	{ 0 },};static struct pci_driver sstfb_driver = {	.name		= "sstfb",	.id_table	= sstfb_id_tbl,	.probe		= sstfb_probe,	.remove		= __devexit_p(sstfb_remove),};static int __devinit sstfb_init(void){	char *option = NULL;	if (fb_get_options("sstfb", &option))		return -ENODEV;	sstfb_setup(option);	return pci_register_driver(&sstfb_driver);}static void __devexit sstfb_exit(void){	pci_unregister_driver(&sstfb_driver);}module_init(sstfb_init);module_exit(sstfb_exit);MODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>");MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards");MODULE_LICENSE("GPL");module_param(mem, int, 0);MODULE_PARM_DESC(mem, "Size of frame buffer memory in MB (1, 2, 4 MB, default=autodetect)");module_param(vgapass, bool, 0);MODULE_PARM_DESC(vgapass, "Enable VGA PassThrough mode (0 or 1) (default=0)");module_param(clipping, bool, 0);MODULE_PARM_DESC(clipping, "Enable clipping (slower, safer) (0 or 1) (default=1)");module_param(gfxclk, int, 0);MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in MHz. DANGEROUS. (default=auto)");module_param(slowpci, bool, 0);MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");module_param(mode_option, charp, 0);MODULE_PARM_DESC(mode_option, "Initial video mode (default=" DEFAULT_VIDEO_MODE ")");

⌨️ 快捷键说明

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