sstfb.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,724 行 · 第 1/4 页

C
1,724
字号
	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 = (struct sstfb_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 | EN_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 */int  __init 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_cursor	= soft_cursor,	.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;	struct all_info {		struct fb_info info;		struct sstfb_par par;		u32 pseudo_palette[16];	} *all;		/* Enable device in PCI config. */	if ((err=pci_enable_device(pdev))) {		eprintk("cannot enable device\n");		return err;	}	/* Allocate the fb and par structures.  */	all = kmalloc(sizeof(*all), GFP_KERNEL);	if (!all)		return -ENOMEM;	memset(all, 0, sizeof(*all));	pci_set_drvdata(pdev, all);		info = &all->info;	par  = info->par = &all->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;	pci_read_config_byte(pdev, PCI_REVISION_ID, &par->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")) {		eprintk("cannot reserve mmio memory\n");		goto fail_mmio_mem;	}	if (!request_mem_region(fix->smem_start, 0x400000,"sstfb FB")) {		eprintk("cannot reserve fb memory\n");		goto fail_fb_mem;	}	par->mmio_vbase = (u_long) ioremap_nocache(fix->mmio_start,					fix->mmio_len);	if (!par->mmio_vbase) {		eprintk("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) {		eprintk("cannot remap framebuffer %#lx\n",		        fix->smem_start);		goto fail_fb_remap;	}	if (!sst_init(info, par)) {		eprintk("Init failed\n");		goto fail;	}	sst_get_memsize(info, &fix->smem_len);	strlcpy(fix->id, spec->name, sizeof(fix->id));	iprintk("%s (revision %d) with %s dac\n",		fix->id, par->revision, par->dac_sw.name);	iprintk("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->currcon	= -1;	info->pseudo_palette = &all->pseudo_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.	 */	fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */		if ( mode_option &&	     fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16)) {		eprintk("can't set supplied video mode. Using default\n");		info->var = sstfb_default;	} else		info->var = sstfb_default;	if (sstfb_check_var(&info->var, info)) {		eprintk("invalid default video mode.\n");		goto fail;	}	if (sstfb_set_par(info)) {		eprintk("can't set default video mode.\n");		goto fail;	}		fb_alloc_cmap(&info->cmap, 256, 0);	/* register fb */	if (register_framebuffer(info) < 0) {		eprintk("can't register framebuffer.\n");		goto fail;	}	if (1) /* set to 0 to see an initial bitmap instead */		sstfb_clear_screen(info);	else		sstfb_drawdebugimage(info);	printk(KERN_INFO "fb%d: %s frame buffer device at 0x%p\n",	       info->node, fix->id, info->screen_base);	return 0;fail:	iounmap(info->screen_base);fail_fb_remap:	iounmap((void *)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:	kfree(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 = (struct sstfb_par *) info->par;		sst_shutdown(info);	unregister_framebuffer(info);	iounmap(info->screen_base);	iounmap((void*)par->mmio_vbase);	release_mem_region(info->fix.smem_start, 0x400000);	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);	kfree(info);}static struct pci_device_id sstfb_id_tbl[] = {	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO1 },	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO2 },	{ 0 },};static struct pci_driver sstfb_driver = {	.name		= "sstfb",	.id_table	= sstfb_id_tbl,	.probe		= sstfb_probe,	.remove		= __devexit_p(sstfb_remove),};int __devinit sstfb_init(void){#ifndef MODULE	char *option = NULL;	if (fb_get_options("sstfb", &option))		return -ENODEV;	sstfb_setup(option);#endif	return pci_module_init(&sstfb_driver);}void __devexit sstfb_exit(void){	pci_unregister_driver(&sstfb_driver);}/* * testing and debugging functions */static int sstfb_dump_regs(struct fb_info *info){#ifdef SST_DEBUG	static struct { u32 reg ; const char *reg_name;}  pci_regs[] = {		{ PCI_INIT_ENABLE, "initenable"},		{ PCI_VCLK_ENABLE, "enable vclk"},		{ PCI_VCLK_DISABLE, "disable vclk"},	};	static struct { u32 reg ; const char *reg_name;}  sst_regs[] = {		{FBIINIT0,"fbiinit0"},		{FBIINIT1,"fbiinit1"},		{FBIINIT2,"fbiinit2"},		{FBIINIT3,"fbiinit3"},		{FBIINIT4,"fbiinit4"},		{FBIINIT5,"fbiinit5"},		{FBIINIT6,"fbiinit6"},		{FBIINIT7,"fbiinit7"},		{LFBMODE,"lfbmode"},		{FBZMODE,"fbzmode"},	};	const int pci_s = sizeof(pci_regs)/sizeof(pci_regs[0]);	const int sst_s = sizeof(sst_regs)/sizeof(sst_regs[0]);	struct sstfb_par *par = (struct sstfb_par *) info->par;	struct pci_dev *dev = par->dev;	u32 pci_res[pci_s];	u32 sst_res[sst_s];	int i;	for (i=0; i<pci_s; i++) {		pci_read_config_dword(dev, pci_regs[i].reg, &pci_res[i]);	}	for (i=0; i<sst_s; i++) {		sst_res[i] = sst_read(sst_regs[i].reg);	}	dprintk("hardware register dump:\n");	for (i=0; i<pci_s; i++) {		dprintk("%s %0#10x\n", pci_regs[i].reg_name, pci_res[i]);	}	for (i=0; i<sst_s; i++) {		dprintk("%s %0#10x\n", sst_regs[i].reg_name, sst_res[i]);	}	return 0;#else	return -EINVAL;#endif}static void sstfb_fillrect_softw( struct fb_info *info, const struct fb_fillrect *rect){	unsigned long fbbase_virt = (unsigned long) info->screen_base;	int x, y, w = info->var.bits_per_pixel == 16 ? 2 : 4;	u32 color = rect->color, height = rect->height;	unsigned long p;		if (w==2) color |= color<<16;	for (y=rect->dy; height; y++, height--) {		p = fbbase_virt + y*info->fix.line_length + rect->dx*w;		x = rect->width;		if (w==2) x>>=1;		while (x) {			writel(color, p);			p += 4;			x--;		}	}}static void sstfb_drawrect_XY( struct fb_info *info, int x, int y,		int w, int h, int color, int hwfunc){	struct fb_fillrect rect;	rect.dx = x;	rect.dy = y;	rect.height = h;	rect.width = w;	rect.color = color;	rect.rop = ROP_COPY;	if (hwfunc)		sstfb_fillrect(info, &rect);	else		sstfb_fillrect_softw(info, &rect);}/* print some squares on the fb */static void sstfb_drawdebugimage(struct fb_info *info){	static int idx;	/* clear screen */	sstfb_clear_screen(info);	   	idx = (idx+1) & 1;	/* white rect */	sstfb_drawrect_XY(info, 0, 0, 50, 50, 0xffff, idx);		/* blue rect */	sstfb_drawrect_XY(info, 50, 50, 50, 50, 0x001f, idx);	/* green rect */	sstfb_drawrect_XY(info, 100, 100, 80, 80, 0x07e0, idx);		/* red rect */	sstfb_drawrect_XY(info, 250, 250, 120, 100, 0xf800, idx);}module_init(sstfb_init);#ifdef MODULEmodule_exit(sstfb_exit);#endifMODULE_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_PARM(mem, "i");MODULE_PARM_DESC(mem, "Size of frame buffer memory in MB (1, 2, 4 MB, default=autodetect)");MODULE_PARM(vgapass, "i");MODULE_PARM_DESC(vgapass, "Enable VGA PassThrough mode (0 or 1) (default=0)");MODULE_PARM(clipping , "i");MODULE_PARM_DESC(clipping, "Enable clipping (slower, safer) (0 or 1) (default=1)");MODULE_PARM(gfxclk , "i");MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in MHz. DANGEROUS. (default=auto)");MODULE_PARM(slowpci, "i");MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");

⌨️ 快捷键说明

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