fbdev.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,214 行 · 第 1/4 页

C
2,214
字号
	u16 fg, bg;	int i;	par->riva.ShowHideCursor(&par->riva, 0);	if (cursor->set & FB_CUR_SETPOS) {		u32 xx, yy, temp;		info->cursor.image.dx = cursor->image.dx;		info->cursor.image.dy = cursor->image.dy;		yy = cursor->image.dy - info->var.yoffset;		xx = cursor->image.dx - info->var.xoffset;		temp = xx & 0xFFFF;		temp |= yy << 16;		par->riva.PRAMDAC[0x0000300/4] = temp;	}	if (cursor->set & FB_CUR_SETSIZE) {		info->cursor.image.height = cursor->image.height;		info->cursor.image.width = cursor->image.width;		memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);	}	if (cursor->set & FB_CUR_SETCMAP) {		info->cursor.image.bg_color = cursor->image.bg_color;		info->cursor.image.fg_color = cursor->image.fg_color;	}	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETCUR)) {		u32 bg_idx = info->cursor.image.bg_color;		u32 fg_idx = info->cursor.image.fg_color;		u32 s_pitch = (info->cursor.image.width+7) >> 3;		u32 d_pitch = MAX_CURS/8;		u8 *dat = (u8 *) cursor->image.data;		u8 *msk = (u8 *) info->cursor.mask;		u8 src[64];					info->cursor.image.data = cursor->image.data;		switch (info->cursor.rop) {		case ROP_XOR:			for (i = 0; i < s_pitch * info->cursor.image.height;			     i++)				src[i] = dat[i] ^ msk[i];			break;		case ROP_COPY:		default:			for (i = 0; i < s_pitch * info->cursor.image.height;			     i++)				src[i] = dat[i] & msk[i];			break;		}				fb_sysmove_buf_aligned(info, &info->sprite, data, d_pitch, src,				       s_pitch, info->cursor.image.height);		bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |		     ((info->cmap.green[bg_idx] & 0xf8) << 2) |		     ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15;		fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |		     ((info->cmap.green[fg_idx] & 0xf8) << 2) |		     ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;		par->riva.LockUnlock(&par->riva, 0);		rivafb_load_cursor_image(par, data, bg, fg,					 info->cursor.image.width, 					 info->cursor.image.height);	}	if (info->cursor.enable)		par->riva.ShowHideCursor(&par->riva, 1);	return 0;}static int rivafb_sync(struct fb_info *info){	struct riva_par *par = (struct riva_par *)info->par;	wait_for_idle(par);	return 0;}/* ------------------------------------------------------------------------- * * * initialization helper functions * * ------------------------------------------------------------------------- *//* kernel interface */static struct fb_ops riva_fb_ops = {	.owner 		= THIS_MODULE,	.fb_open	= rivafb_open,	.fb_release	= rivafb_release,	.fb_check_var 	= rivafb_check_var,	.fb_set_par 	= rivafb_set_par,	.fb_setcolreg 	= rivafb_setcolreg,	.fb_pan_display	= rivafb_pan_display,	.fb_blank 	= rivafb_blank,	.fb_fillrect 	= rivafb_fillrect,	.fb_copyarea 	= rivafb_copyarea,	.fb_imageblit 	= rivafb_imageblit,	.fb_cursor	= rivafb_cursor,		.fb_sync 	= rivafb_sync,};static int __devinit riva_set_fbinfo(struct fb_info *info){	unsigned int cmap_len;	NVTRACE_ENTER();	info->flags = FBINFO_DEFAULT		    | FBINFO_HWACCEL_XPAN		    | FBINFO_HWACCEL_YPAN		    | FBINFO_HWACCEL_COPYAREA		    | FBINFO_HWACCEL_FILLRECT		    | FBINFO_HWACCEL_IMAGEBLIT	            | FBINFO_MISC_MODESWITCHLATE;	info->var = rivafb_default_var;	info->fix.visual = (info->var.bits_per_pixel == 8) ?				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;	info->pseudo_palette = pseudo_palette;	cmap_len = riva_get_cmap_len(&info->var);	fb_alloc_cmap(&info->cmap, cmap_len, 0);		info->pixmap.size = 64 * 1024;	info->pixmap.buf_align = 4;	info->pixmap.scan_align = 4;	info->pixmap.flags = FB_PIXMAP_SYSTEM;	info->var.yres_virtual = -1;	NVTRACE_LEAVE();	return (rivafb_check_var(&info->var, info));}#ifdef CONFIG_PPC_OFstatic int riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd){	struct riva_par *par = (struct riva_par *) info->par;	struct device_node *dp;	unsigned char *pedid = NULL;	unsigned char *disptype = NULL;	static char *propnames[] = {		"DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL };	int i;	NVTRACE_ENTER();	dp = pci_device_to_OF_node(pd);	for (; dp != NULL; dp = dp->child) {		disptype = (unsigned char *)get_property(dp, "display-type", NULL);		if (disptype == NULL)			continue;		if (strncmp(disptype, "LCD", 3) != 0)			continue;		for (i = 0; propnames[i] != NULL; ++i) {			pedid = (unsigned char *)				get_property(dp, propnames[i], NULL);			if (pedid != NULL) {		par->EDID = pedid;		return 1;			}		}	}	NVTRACE_LEAVE();		return 0;}#endif /* CONFIG_PPC_OF */static void riva_update_default_var(struct fb_var_screeninfo *var, struct fb_info *info){	struct fb_monspecs *specs = &info->monspecs;	struct fb_videomode modedb;	NVTRACE_ENTER();	/* respect mode options */	if (mode_option) {		fb_find_mode(var, info, mode_option,			     specs->modedb, specs->modedb_len,			     NULL, 8);	} else if (specs->modedb != NULL) {		/* get preferred timing */		if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {			int i;			for (i = 0; i < specs->modedb_len; i++) {				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {					modedb = specs->modedb[i];					break;				}			}		} else {			/* otherwise, get first mode in database */			modedb = specs->modedb[0];		}		var->bits_per_pixel = 8;		riva_update_var(var, &modedb);	}	var->accel_flags |= FB_ACCELF_TEXT;	NVTRACE_LEAVE();}static void riva_get_EDID(struct fb_info *info, struct pci_dev *pdev){	struct riva_par *par;	int i;	NVTRACE_ENTER();#ifdef CONFIG_PPC_OF	if (!riva_get_EDID_OF(info, pdev))		printk("rivafb: could not retrieve EDID from OF\n");#else	/* XXX use other methods later */#ifdef CONFIG_FB_RIVA_I2C	par = (struct riva_par *) info->par;	riva_create_i2c_busses(par);	for (i = par->bus; i >= 1; i--) {		riva_probe_i2c_connector(par, i, &par->EDID);		if (par->EDID) {			printk("rivafb: Found EDID Block from BUS %i\n", i);			break;		}	}	riva_delete_i2c_busses(par);#endif#endif	NVTRACE_LEAVE();}static void riva_get_edidinfo(struct fb_info *info){	struct fb_var_screeninfo *var = &rivafb_default_var;	struct riva_par *par = (struct riva_par *) info->par;	fb_edid_to_monspecs(par->EDID, &info->monspecs);	riva_update_default_var(var, info);	/* if user specified flatpanel, we respect that */	if (info->monspecs.input & FB_DISP_DDI)		par->FlatPanel = 1;}/* ------------------------------------------------------------------------- * * * PCI bus * * ------------------------------------------------------------------------- */static int __devinit rivafb_probe(struct pci_dev *pd,			     	const struct pci_device_id *ent){	struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];	struct riva_par *default_par;	struct fb_info *info;	NVTRACE_ENTER();	assert(pd != NULL);	assert(rci != NULL);	info = kmalloc(sizeof(struct fb_info), GFP_KERNEL);	if (!info)		goto err_out;	default_par = kmalloc(sizeof(struct riva_par), GFP_KERNEL);	if (!default_par)		goto err_out_kfree;	memset(info, 0, sizeof(struct fb_info));	memset(default_par, 0, sizeof(struct riva_par));	default_par->pdev = pd;	info->pixmap.addr = kmalloc(64 * 1024, GFP_KERNEL);	if (info->pixmap.addr == NULL)		goto err_out_kfree1;	memset(info->pixmap.addr, 0, 64 * 1024);	if (pci_enable_device(pd)) {		printk(KERN_ERR PFX "cannot enable PCI device\n");		goto err_out_enable;	}	if (pci_request_regions(pd, "rivafb")) {		printk(KERN_ERR PFX "cannot request PCI regions\n");		goto err_out_request;	}	strcat(rivafb_fix.id, rci->name);	default_par->riva.Architecture = rci->arch_rev;	default_par->Chipset = (pd->vendor << 16) | pd->device;	printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset);		default_par->FlatPanel = flatpanel;	if (flatpanel == 1)		printk(KERN_INFO PFX "flatpanel support enabled\n");	default_par->forceCRTC = forceCRTC;		rivafb_fix.mmio_len = pci_resource_len(pd, 0);	rivafb_fix.smem_len = pci_resource_len(pd, 1);	{		/* enable IO and mem if not already done */		unsigned short cmd;		pci_read_config_word(pd, PCI_COMMAND, &cmd);		cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);		pci_write_config_word(pd, PCI_COMMAND, cmd);	}		rivafb_fix.mmio_start = pci_resource_start(pd, 0);	rivafb_fix.smem_start = pci_resource_start(pd, 1);	default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,					 rivafb_fix.mmio_len);	if (!default_par->ctrl_base) {		printk(KERN_ERR PFX "cannot ioremap MMIO base\n");		goto err_out_free_base0;	}	info->par = default_par;	switch (default_par->riva.Architecture) {	case NV_ARCH_03:		/* Riva128's PRAMIN is in the "framebuffer" space		 * Since these cards were never made with more than 8 megabytes		 * we can safely allocate this separately.		 */		default_par->riva.PRAMIN = ioremap(rivafb_fix.smem_start + 0x00C00000, 0x00008000);		if (!default_par->riva.PRAMIN) {			printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n");			goto err_out_free_nv3_pramin;		}		rivafb_fix.accel = FB_ACCEL_NV3;		default_par->bus = 1;		break;	case NV_ARCH_04:	case NV_ARCH_10:	case NV_ARCH_20:		default_par->riva.PCRTC0 = (unsigned *)(default_par->ctrl_base + 0x00600000);		default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000);		rivafb_fix.accel = FB_ACCEL_NV4;		default_par->bus = 2;		break;	}	riva_common_setup(default_par);	if (default_par->riva.Architecture == NV_ARCH_03) {		default_par->riva.PCRTC = default_par->riva.PCRTC0 = default_par->riva.PGRAPH;	}	rivafb_fix.smem_len = riva_get_memlen(default_par) * 1024;	default_par->dclk_max = riva_get_maxdclk(default_par) * 1000;	info->screen_base = ioremap(rivafb_fix.smem_start,				    rivafb_fix.smem_len);	if (!info->screen_base) {		printk(KERN_ERR PFX "cannot ioremap FB base\n");		goto err_out_free_base1;	}#ifdef CONFIG_MTRR	if (!nomtrr) {		default_par->mtrr.vram = mtrr_add(rivafb_fix.smem_start,					   	  rivafb_fix.smem_len,					    	  MTRR_TYPE_WRCOMB, 1);		if (default_par->mtrr.vram < 0) {			printk(KERN_ERR PFX "unable to setup MTRR\n");		} else {			default_par->mtrr.vram_valid = 1;			/* let there be speed */			printk(KERN_INFO PFX "RIVA MTRR set to ON\n");		}	}#endif /* CONFIG_MTRR */	info->fbops = &riva_fb_ops;	info->fix = rivafb_fix;	riva_get_EDID(info, pd);	riva_get_edidinfo(info);	if (riva_set_fbinfo(info) < 0) {		printk(KERN_ERR PFX "error setting initial video mode\n");		goto err_out_iounmap_fb;	}	if (register_framebuffer(info) < 0) {		printk(KERN_ERR PFX			"error registering riva framebuffer\n");		goto err_out_iounmap_fb;	}	pci_set_drvdata(pd, info);	printk(KERN_INFO PFX		"PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n",		default_par->riva.Architecture,		RIVAFB_VERSION,		info->fix.id,		info->fix.smem_len / (1024 * 1024),		info->fix.smem_start);#ifdef CONFIG_PMAC_BACKLIGHT	if (default_par->FlatPanel && _machine == _MACH_Pmac)	register_backlight_controller(&riva_backlight_controller,						default_par, "mnca");#endif	NVTRACE_LEAVE();	return 0;err_out_iounmap_fb:	iounmap(info->screen_base);err_out_free_base1:	if (default_par->riva.Architecture == NV_ARCH_03) 		iounmap((caddr_t)default_par->riva.PRAMIN);err_out_free_nv3_pramin:	iounmap(default_par->ctrl_base);err_out_free_base0:	pci_release_regions(pd);err_out_request:	pci_disable_device(pd);err_out_enable:	kfree(info->pixmap.addr);err_out_kfree1:	kfree(default_par);err_out_kfree:	kfree(info);err_out:	return -ENODEV;}static void __exit rivafb_remove(struct pci_dev *pd){	struct fb_info *info = pci_get_drvdata(pd);	struct riva_par *par = (struct riva_par *) info->par;		NVTRACE_ENTER();	if (!info)		return;	unregister_framebuffer(info);#ifdef CONFIG_MTRR	if (par->mtrr.vram_valid)		mtrr_del(par->mtrr.vram, info->fix.smem_start,			 info->fix.smem_len);#endif /* CONFIG_MTRR */	iounmap(par->ctrl_base);	iounmap(info->screen_base);	if (par->riva.Architecture == NV_ARCH_03)		iounmap((caddr_t)par->riva.PRAMIN);	pci_release_regions(pd);	pci_disable_device(pd);	fb_destroy_modedb(info->monspecs.modedb);	kfree(info->pixmap.addr);	kfree(par);	kfree(info);	pci_set_drvdata(pd, NULL);	NVTRACE_LEAVE();}/* ------------------------------------------------------------------------- * * * initialization * * ------------------------------------------------------------------------- */#ifndef MODULEint __init rivafb_setup(char *options){	char *this_opt;	NVTRACE_ENTER();	if (!options || !*options)		return 0;	while ((this_opt = strsep(&options, ",")) != NULL) {		if (!strncmp(this_opt, "forceCRTC", 9)) {			char *p;						p = this_opt + 9;			if (!*p || !*(++p)) continue; 			forceCRTC = *p - '0';			if (forceCRTC < 0 || forceCRTC > 1) 				forceCRTC = -1;		} else if (!strncmp(this_opt, "flatpanel", 9)) {			flatpanel = 1;#ifdef CONFIG_MTRR		} else if (!strncmp(this_opt, "nomtrr", 6)) {			nomtrr = 1;#endif		} else if (!strncmp(this_opt, "strictmode", 10)) {			strictmode = 1;		} else			mode_option = this_opt;	}	NVTRACE_LEAVE();	return 0;}#endif /* !MODULE */static struct pci_driver rivafb_driver = {	.name		= "rivafb",	.id_table	= rivafb_pci_tbl,	.probe		= rivafb_probe,	.remove		= __exit_p(rivafb_remove),};/* ------------------------------------------------------------------------- * * * modularization * * ------------------------------------------------------------------------- */int __init rivafb_init(void){	if (pci_register_driver(&rivafb_driver) > 0)		return 0;	pci_unregister_driver(&rivafb_driver);	return -ENODEV;}#ifdef MODULEstatic void __exit rivafb_exit(void){	pci_unregister_driver(&rivafb_driver);}module_init(rivafb_init);module_exit(rivafb_exit);MODULE_PARM(flatpanel, "i");MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. (0 or 1=enabled) (default=0)");MODULE_PARM(forceCRTC, "i");MODULE_PARM_DESC(forceCRTC, "Forces usage of a particular CRTC in case autodetection fails. (0 or 1) (default=autodetect)");#ifdef CONFIG_MTRRMODULE_PARM(nomtrr, "i");MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");MODULE_PARM(strictmode, "i");MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");#endif#endif /* MODULE */MODULE_AUTHOR("Ani Joshi, maintainer");MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2, and the GeForce series");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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