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

📄 carminefb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	mode = c_get_disp_reg(par, CARMINE_DISP_REG_DCM1);	mode = (mode & ~CARMINE_DISP_DCM_MASK) |		(par->res->disp_mode & CARMINE_DISP_DCM_MASK);	/* enable video output and layer 0 */	mode |= CARMINE_DEN | CARMINE_L0E;	c_set_disp_reg(par, CARMINE_DISP_REG_DCM1, mode);}static int carmine_set_par(struct fb_info *info){	struct carmine_fb *par = info->par;	int ret;	ret = carmine_find_mode(&info->var);	if (ret < 0)		return ret;	par->new_mode = ret;	if (par->cur_mode != par->new_mode) {		par->cur_mode = par->new_mode;		par->res = &car_modes[par->new_mode];		carmine_init_display_param(par);		set_display_parameters(par);	}	info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;	return 0;}static int init_hardware(struct carmine_hw *hw){	u32 flags;	u32 loops;	u32 ret;	/* Initalize Carmine */	/* Sets internal clock */	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE,			CARMINE_DFLT_IP_CLOCK_ENABLE);	/* Video signal output is turned off */	c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);	c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);	/* Software reset */	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 1);	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 0);	/* I/O mode settings */	flags = CARMINE_DFLT_IP_DCTL_IO_CONT1 << 16 |		CARMINE_DFLT_IP_DCTL_IO_CONT0;	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_IOCONT1_IOCONT0,			flags);	/* DRAM initial sequence */	flags = CARMINE_DFLT_IP_DCTL_MODE << 16 | CARMINE_DFLT_IP_DCTL_ADD;	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD,			flags);	flags = CARMINE_DFLT_IP_DCTL_SET_TIME1 << 16 |		CARMINE_DFLT_IP_DCTL_EMODE;	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_SETTIME1_EMODE,			flags);	flags = CARMINE_DFLT_IP_DCTL_REFRESH << 16 |		CARMINE_DFLT_IP_DCTL_SET_TIME2;	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_REFRESH_SETTIME2,			flags);	flags = CARMINE_DFLT_IP_DCTL_RESERVE2 << 16 |		CARMINE_DFLT_IP_DCTL_FIFO_DEPTH;	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV2_RSV1, flags);	flags = CARMINE_DFLT_IP_DCTL_DDRIF2 << 16 | CARMINE_DFLT_IP_DCTL_DDRIF1;	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_DDRIF2_DDRIF1,			flags);	flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |		CARMINE_DFLT_IP_DCTL_STATES;	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,			flags);	/* Executes DLL reset */	if (CARMINE_DCTL_DLL_RESET) {		for (loops = 0; loops < CARMINE_DCTL_INIT_WAIT_LIMIT; loops++) {			ret = c_get_hw_reg(hw, CARMINE_DCTL_REG +					CARMINE_DCTL_REG_RSV0_STATES);			ret &= CARMINE_DCTL_REG_STATES_MASK;			if (!ret)				break;			mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL);		}		if (loops >= CARMINE_DCTL_INIT_WAIT_LIMIT) {			printk(KERN_ERR "DRAM init failed\n");			return -EIO;		}	}	flags = CARMINE_DFLT_IP_DCTL_MODE_AFT_RST << 16 |		CARMINE_DFLT_IP_DCTL_ADD;	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, flags);	flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |		CARMINE_DFLT_IP_DCTL_STATES_AFT_RST;	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,			flags);	/* Initialize the write back register */	c_set_hw_reg(hw, CARMINE_WB_REG + CARMINE_WB_REG_WBM,			CARMINE_WB_REG_WBM_DEFAULT);	/* Initialize the Kottos registers */	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRINTM, 0);	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRERRM, 0);	/* Set DC offsets */	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PX, 0);	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PY, 0);	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LX, 0);	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LY, 0);	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TX, 0);	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TY, 0);	return 0;}static struct fb_ops carminefb_ops = {	.owner		= THIS_MODULE,	.fb_fillrect	= cfb_fillrect,	.fb_copyarea	= cfb_copyarea,	.fb_imageblit	= cfb_imageblit,	.fb_check_var	= carmine_check_var,	.fb_set_par	= carmine_set_par,	.fb_setcolreg	= carmine_setcolreg,};static int __devinit alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,		int smem_offset, struct device *device, struct fb_info **rinfo){	int ret;	struct fb_info *info;	struct carmine_fb *par;	info = framebuffer_alloc(sizeof *par, device);	if (!info)		return -ENOMEM;	par = info->par;	par->display_reg = regs;	par->smem_offset = smem_offset;	info->screen_base = smem_base + smem_offset;	info->screen_size = CARMINE_DISPLAY_MEM;	info->fbops = &carminefb_ops;	info->fix = carminefb_fix;	info->pseudo_palette = par->pseudo_palette;	info->flags = FBINFO_DEFAULT;	ret = fb_alloc_cmap(&info->cmap, 256, 1);	if (ret < 0)		goto err_free_fb;	if (fb_mode > ARRAY_SIZE(carmine_modedb))		fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;	par->cur_mode = par->new_mode = ~0;	ret = fb_find_mode(&info->var, info, fb_mode_str, carmine_modedb,			ARRAY_SIZE(carmine_modedb),			&carmine_modedb[fb_mode], 32);	if (!ret || ret == 4) {		ret = -EINVAL;		goto err_dealloc_cmap;	}	fb_videomode_to_modelist(carmine_modedb, ARRAY_SIZE(carmine_modedb),			&info->modelist);	ret = register_framebuffer(info);	if (ret < 0)		goto err_dealloc_cmap;	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,			info->fix.id);	*rinfo = info;	return 0;err_dealloc_cmap:	fb_dealloc_cmap(&info->cmap);err_free_fb:	framebuffer_release(info);	return ret;}static void cleanup_fb_device(struct fb_info *info){	if (info) {		unregister_framebuffer(info);		fb_dealloc_cmap(&info->cmap);		framebuffer_release(info);	}}static int __devinit carminefb_probe(struct pci_dev *dev,		const struct pci_device_id *ent){	struct carmine_hw *hw;	struct device *device = &dev->dev;	struct fb_info *info;	int ret;	ret = pci_enable_device(dev);	if (ret)		return ret;	ret = -ENOMEM;	hw = kzalloc(sizeof *hw, GFP_KERNEL);	if (!hw)		goto err_enable_pci;	carminefb_fix.mmio_start = pci_resource_start(dev, CARMINE_CONFIG_BAR);	carminefb_fix.mmio_len = pci_resource_len(dev, CARMINE_CONFIG_BAR);	if (!request_mem_region(carminefb_fix.mmio_start,				carminefb_fix.mmio_len,				"carminefb regbase")) {		printk(KERN_ERR "carminefb: Can't reserve regbase.\n");		ret = -EBUSY;		goto err_free_hw;	}	hw->v_regs = ioremap_nocache(carminefb_fix.mmio_start,			carminefb_fix.mmio_len);	if (!hw->v_regs) {		printk(KERN_ERR "carminefb: Can't remap %s register.\n",				carminefb_fix.id);		goto err_free_reg_mmio;	}	carminefb_fix.smem_start = pci_resource_start(dev, CARMINE_MEMORY_BAR);	carminefb_fix.smem_len = pci_resource_len(dev, CARMINE_MEMORY_BAR);	/* The memory area tends to be very large (256 MiB). Remap only what	 * is required for that largest resolution to avoid remaps at run	 * time	 */	if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM)		carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM;	else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) {		printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d "				"are required.", carminefb_fix.smem_len,				CARMINE_TOTAL_DIPLAY_MEM);		goto err_free_reg_mmio;	}	if (!request_mem_region(carminefb_fix.smem_start,				carminefb_fix.smem_len,	"carminefb smem")) {		printk(KERN_ERR "carminefb: Can't reserve smem.\n");		goto err_unmap_vregs;	}	hw->screen_mem = ioremap_nocache(carminefb_fix.smem_start,			carminefb_fix.smem_len);	if (!hw->screen_mem) {		printk(KERN_ERR "carmine: Can't ioremap smem area.\n");		release_mem_region(carminefb_fix.smem_start,				carminefb_fix.smem_len);		goto err_reg_smem;	}	ret = init_hardware(hw);	if (ret)		goto err_unmap_screen;	info = NULL;	if (fb_displays & CARMINE_USE_DISPLAY0) {		ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP0_REG,				hw->screen_mem, CARMINE_DISPLAY_MEM * 0,				device, &info);		if (ret)			goto err_deinit_hw;	}	hw->fb[0] = info;	info = NULL;	if (fb_displays & CARMINE_USE_DISPLAY1) {		ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP1_REG,				hw->screen_mem, CARMINE_DISPLAY_MEM * 1,				device, &info);		if (ret)			goto err_cleanup_fb0;	}	hw->fb[1] = info;	info = NULL;	pci_set_drvdata(dev, hw);	return 0;err_cleanup_fb0:	cleanup_fb_device(hw->fb[0]);err_deinit_hw:	/* disable clock, etc */	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);err_unmap_screen:	iounmap(hw->screen_mem);err_reg_smem:	release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);err_unmap_vregs:	iounmap(hw->v_regs);err_free_reg_mmio:	release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);err_free_hw:	kfree(hw);err_enable_pci:	pci_disable_device(dev);	return ret;}static void __devexit carminefb_remove(struct pci_dev *dev){	struct carmine_hw *hw = pci_get_drvdata(dev);	struct fb_fix_screeninfo fix;	int i;	/* in case we use only fb1 and not fb1 */	if (hw->fb[0])		fix = hw->fb[0]->fix;	else		fix = hw->fb[1]->fix;	/* deactivate display(s) and switch clocks */	c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);	c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);	for (i = 0; i < MAX_DISPLAY; i++)		cleanup_fb_device(hw->fb[i]);	iounmap(hw->screen_mem);	release_mem_region(fix.smem_start, fix.smem_len);	iounmap(hw->v_regs);	release_mem_region(fix.mmio_start, fix.mmio_len);	pci_set_drvdata(dev, NULL);	pci_disable_device(dev);	kfree(hw);}#define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cfstatic struct pci_device_id carmine_devices[] __devinitdata = {{	PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)},	{0, 0, 0, 0, 0, 0, 0}};MODULE_DEVICE_TABLE(pci, carmine_devices);static struct pci_driver carmine_pci_driver = {	.name		= "carminefb",	.id_table	= carmine_devices,	.probe		= carminefb_probe,	.remove		= __devexit_p(carminefb_remove),};static int __init carminefb_init(void){	if (!(fb_displays &		(CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1))) {		printk(KERN_ERR "If you disable both displays than you don't "				"need the driver at all\n");		return -EINVAL;	}	return pci_register_driver(&carmine_pci_driver);}module_init(carminefb_init);static void __exit carminefb_cleanup(void){	pci_unregister_driver(&carmine_pci_driver);}module_exit(carminefb_cleanup);MODULE_AUTHOR("Sebastian Siewior <bigeasy@linutronix.de>");MODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices");MODULE_LICENSE("GPL v2");

⌨️ 快捷键说明

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