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

📄 lxfb_core.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
static int __init lxfb_map_video_memory(struct fb_info *info,					struct pci_dev *dev){	struct lxfb_par *par = info->par;	int ret;	ret = pci_enable_device(dev);	if (ret)		return ret;	ret = pci_request_region(dev, 0, "lxfb-framebuffer");	if (ret)		return ret;	ret = pci_request_region(dev, 1, "lxfb-gp");	if (ret)		return ret;	ret = pci_request_region(dev, 2, "lxfb-vg");	if (ret)		return ret;	ret = pci_request_region(dev, 3, "lxfb-vip");	if (ret)		return ret;	info->fix.smem_start = pci_resource_start(dev, 0);	info->fix.smem_len = fbsize ? fbsize : lx_framebuffer_size();	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);	ret = -ENOMEM;	if (info->screen_base == NULL)		return ret;	par->gp_regs = ioremap(pci_resource_start(dev, 1),				pci_resource_len(dev, 1));	if (par->gp_regs == NULL)		return ret;	par->dc_regs = ioremap(pci_resource_start(dev, 2),			       pci_resource_len(dev, 2));	if (par->dc_regs == NULL)		return ret;	par->df_regs = ioremap(pci_resource_start(dev, 3),			       pci_resource_len(dev, 3));	if (par->df_regs == NULL)		return ret;	writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);	writel(info->fix.smem_start & 0xFF000000,	       par->dc_regs + DC_PHY_MEM_OFFSET);	writel(0, par->dc_regs + DC_UNLOCK);	dev_info(&dev->dev, "%d KB of video memory at 0x%lx\n",		 info->fix.smem_len / 1024, info->fix.smem_start);	return 0;}static struct fb_ops lxfb_ops = {	.owner		= THIS_MODULE,	.fb_check_var	= lxfb_check_var,	.fb_set_par	= lxfb_set_par,	.fb_setcolreg	= lxfb_setcolreg,	.fb_blank       = lxfb_blank,	/* No HW acceleration for now. */	.fb_fillrect	= cfb_fillrect,	.fb_copyarea	= cfb_copyarea,	.fb_imageblit	= cfb_imageblit,};static struct fb_info * __init lxfb_init_fbinfo(struct device *dev){	struct lxfb_par *par;	struct fb_info *info;	/* Alloc enough space for the pseudo palette. */	info = framebuffer_alloc(sizeof(struct lxfb_par) + sizeof(u32) * 16,				 dev);	if (!info)		return NULL;	par = info->par;	strcpy(info->fix.id, "Geode LX");	info->fix.type		= FB_TYPE_PACKED_PIXELS;	info->fix.type_aux	= 0;	info->fix.xpanstep	= 0;	info->fix.ypanstep	= 0;	info->fix.ywrapstep	= 0;	info->fix.accel		= FB_ACCEL_NONE;	info->var.nonstd	= 0;	info->var.activate	= FB_ACTIVATE_NOW;	info->var.height	= -1;	info->var.width	= -1;	info->var.accel_flags = 0;	info->var.vmode	= FB_VMODE_NONINTERLACED;	info->fbops		= &lxfb_ops;	info->flags		= FBINFO_DEFAULT;	info->node		= -1;	info->pseudo_palette	= (void *)par + sizeof(struct lxfb_par);	info->var.grayscale	= 0;	return info;}static int __init lxfb_probe(struct pci_dev *pdev,			     const struct pci_device_id *id){	struct lxfb_par *par;	struct fb_info *info;	int ret;	struct fb_videomode *modedb_ptr;	int modedb_size;	info = lxfb_init_fbinfo(&pdev->dev);	if (info == NULL)		return -ENOMEM;	par = info->par;	ret = lxfb_map_video_memory(info, pdev);	if (ret < 0) {		dev_err(&pdev->dev,			"failed to map frame buffer or controller registers\n");		goto err;	}	/* Set up the desired outputs */	par->output = 0;	par->output |= (nopanel) ? 0 : OUTPUT_PANEL;	par->output |= (nocrt) ? 0 : OUTPUT_CRT;	/* Set up the mode database */	modedb_ptr = (struct fb_videomode *) geode_modedb;	modedb_size = ARRAY_SIZE(geode_modedb);	ret = fb_find_mode(&info->var, info, mode_option,			   modedb_ptr, modedb_size, NULL, 16);	if (ret == 0 || ret == 4) {		dev_err(&pdev->dev, "could not find valid video mode\n");		ret = -EINVAL;		goto err;	}	/* Clear the screen of garbage, unless noclear was specified,	 * in which case we assume the user knows what he is doing */	if (!noclear)		memset_io(info->screen_base, 0, info->fix.smem_len);	/* Set the mode */	lxfb_check_var(&info->var, info);	lxfb_set_par(info);	if (register_framebuffer(info) < 0) {		ret = -EINVAL;		goto err;	}	pci_set_drvdata(pdev, info);	printk(KERN_INFO "fb%d: %s frame buffer device\n",		info->node, info->fix.id);	return 0;err:	if (info->screen_base) {		iounmap(info->screen_base);		pci_release_region(pdev, 0);	}	if (par->gp_regs) {		iounmap(par->gp_regs);		pci_release_region(pdev, 1);	}	if (par->dc_regs) {		iounmap(par->dc_regs);		pci_release_region(pdev, 2);	}	if (par->df_regs) {		iounmap(par->df_regs);		pci_release_region(pdev, 3);	}	if (info)		framebuffer_release(info);	return ret;}static void lxfb_remove(struct pci_dev *pdev){	struct fb_info *info = pci_get_drvdata(pdev);	struct lxfb_par *par = info->par;	unregister_framebuffer(info);	iounmap(info->screen_base);	pci_release_region(pdev, 0);	iounmap(par->gp_regs);	pci_release_region(pdev, 1);	iounmap(par->dc_regs);	pci_release_region(pdev, 2);	iounmap(par->df_regs);	pci_release_region(pdev, 3);	pci_set_drvdata(pdev, NULL);	framebuffer_release(info);}static struct pci_device_id lxfb_id_table[] = {	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_VIDEO) },	{ 0, }};MODULE_DEVICE_TABLE(pci, lxfb_id_table);static struct pci_driver lxfb_driver = {	.name		= "lxfb",	.id_table	= lxfb_id_table,	.probe		= lxfb_probe,	.remove		= lxfb_remove,};#ifndef MODULEstatic int __init lxfb_setup(char *options){	char *opt;	if (!options || !*options)		return 0;	while ((opt = strsep(&options, ",")) != NULL) {		if (!*opt)			continue;		if (!strncmp(opt, "fbsize:", 7))			fbsize = simple_strtoul(opt+7, NULL, 0);		else if (!strcmp(opt, "noclear"))			noclear = 1;		else if (!strcmp(opt, "nopanel"))			nopanel = 1;		else if (!strcmp(opt, "nocrt"))			nocrt = 1;		else			mode_option = opt;	}	return 0;}#endifstatic int __init lxfb_init(void){#ifndef MODULE	char *option = NULL;	if (fb_get_options("lxfb", &option))		return -ENODEV;	lxfb_setup(option);#endif	return pci_register_driver(&lxfb_driver);}static void __exit lxfb_cleanup(void){	pci_unregister_driver(&lxfb_driver);}module_init(lxfb_init);module_exit(lxfb_cleanup);module_param(mode_option, charp, 0);MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");module_param(fbsize, int, 0);MODULE_PARM_DESC(fbsize, "video memory size");MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode LX");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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