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

📄 cyber2000fb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		break;		case 1:	/* soft blank */		cyber2000_grphw(0x16, 0x00, cfb);		for (i = 0; i < NR_PALETTE; i++) {			cyber2000fb_writeb(i, 0x3c8, cfb);			cyber2000fb_writeb(0, 0x3c9, cfb);			cyber2000fb_writeb(0, 0x3c9, cfb);			cyber2000fb_writeb(0, 0x3c9, cfb);		}		break;	default: /* unblank */		cyber2000_grphw(0x16, 0x00, cfb);		for (i = 0; i < NR_PALETTE; i++) {			cyber2000fb_writeb(i, 0x3c8, cfb);			cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);			cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);			cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);		}		break;	}}/* * Get the currently displayed virtual consoles colormap. */static intgen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){	fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);	return 0;}/* * Get the currently displayed virtual consoles fixed part of the display. */static intgen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){	*fix = info->fix;	return 0;}/* * Get the current user defined part of the display. */static intgen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){	*var = info->var;	return 0;}static struct fb_ops cyber2000fb_ops = {	owner:		THIS_MODULE,	fb_set_var:	cyber2000fb_set_var,	fb_set_cmap:	cyber2000fb_set_cmap,	fb_pan_display:	cyber2000fb_pan_display,	fb_get_fix:	gen_get_fix,	fb_get_var:	gen_get_var,	fb_get_cmap:	gen_get_cmap,};/* * Enable access to the extended registers */static void cyber2000fb_enable_extregs(struct cfb_info *cfb){	cfb->func_use_count += 1;	if (cfb->func_use_count == 1) {		int old;		old = cyber2000_grphr(FUNC_CTL, cfb);		cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL, cfb);	}}/* * Disable access to the extended registers */static void cyber2000fb_disable_extregs(struct cfb_info *cfb){	if (cfb->func_use_count == 1) {		int old;		old = cyber2000_grphr(FUNC_CTL, cfb);		cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL, cfb);	}	cfb->func_use_count -= 1;}/* * This is the only "static" reference to the internal data structures * of this driver.  It is here solely at the moment to support the other * CyberPro modules external to this driver. */static struct cfb_info		*int_cfb_info;/* * Attach a capture/tv driver to the core CyberX0X0 driver. */int cyber2000fb_attach(struct cyberpro_info *info, int idx){	if (int_cfb_info != NULL) {		info->dev	      = int_cfb_info->dev;		info->regs	      = int_cfb_info->regs;		info->fb	      = int_cfb_info->fb.screen_base;		info->fb_size	      = int_cfb_info->fb.fix.smem_len;		info->enable_extregs  = cyber2000fb_enable_extregs;		info->disable_extregs = cyber2000fb_disable_extregs;		info->info            = int_cfb_info;		strncpy(info->dev_name, int_cfb_info->fb.fix.id, sizeof(info->dev_name));		MOD_INC_USE_COUNT;	}	return int_cfb_info != NULL;}/* * Detach a capture/tv driver from the core CyberX0X0 driver. */void cyber2000fb_detach(int idx){	MOD_DEC_USE_COUNT;}EXPORT_SYMBOL(cyber2000fb_attach);EXPORT_SYMBOL(cyber2000fb_detach);/* * These parameters give * 640x480, hsync 31.5kHz, vsync 60Hz */static struct fb_videomode __devinitdata cyber2000fb_default_mode = {	refresh:	60,	xres:		640,	yres:		480,	pixclock:	39722,	left_margin:	56,	right_margin:	16,	upper_margin:	34,	lower_margin:	9,	hsync_len:	88,	vsync_len:	2,	sync:		FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,	vmode:		FB_VMODE_NONINTERLACED};static char igs_regs[] __devinitdata = {					0x12, 0x00,	0x13, 0x00,					0x16, 0x00,			0x31, 0x00,	0x32, 0x00,	0x50, 0x00,	0x51, 0x00,	0x52, 0x00,	0x53, 0x00,	0x54, 0x00,	0x55, 0x00,	0x56, 0x00,	0x57, 0x01,	0x58, 0x00,	0x59, 0x00,	0x5a, 0x00,	0x70, 0x0b,					0x73, 0x30,	0x74, 0x0b,	0x75, 0x17,	0x76, 0x00,	0x7a, 0xc8};/* * We need to wake up the CyberPro, and make sure its in linear memory * mode.  Unfortunately, this is specific to the platform and card that * we are running on. * * On x86 and ARM, should we be initialising the CyberPro first via the * IO registers, and then the MMIO registers to catch all cases?  Can we * end up in the situation where the chip is in MMIO mode, but not awake * on an x86 system? * * Note that on the NetWinder, the firmware automatically detects the * type, width and size, and leaves this in extended registers 0x71 and * 0x72 for us. */static inline void cyberpro_init_hw(struct cfb_info *cfb, int at_boot){	int i;	/*	 * Wake up the CyberPro.	 */#ifdef __sparc__#ifdef __sparc_v9__#error "You loose, consult DaveM."#else	/*	 * SPARC does not have an "outb" instruction, so we generate	 * I/O cycles storing into a reserved memory space at	 * physical address 0x3000000	 */	{		unsigned char *iop;		iop = ioremap(0x3000000, 0x5000);		if (iop == NULL) {			prom_printf("iga5000: cannot map I/O\n");			return -ENOMEM;		}		writeb(0x18, iop + 0x46e8);		writeb(0x01, iop + 0x102);		writeb(0x08, iop + 0x46e8);		writeb(0x33, iop + 0x3ce);		writeb(0x01, iop + 0x3cf);		iounmap((void *)iop);	}#endif	if (at_boot) {		/*		 * Use mclk from BIOS.  Only read this if we're		 * initialising this card for the first time.		 * FIXME: what about hotplug?		 */		cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);		cfb->mclk_div  = cyber2000_grphr(MCLK_DIV, cfb);	}#endif#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)	/*	 * x86 and MIPS are simple, we just do regular	 * outb's instead of cyber2000fb_writeb.	 */	outb(0x18, 0x46e8);	outb(0x01, 0x102);	outb(0x08, 0x46e8);	outb(0x33, 0x3ce);	outb(0x01, 0x3cf);	if (at_boot) {		/*		 * Use mclk from BIOS.  Only read this if we're		 * initialising this card for the first time.		 * FIXME: what about hotplug?		 */		cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);		cfb->mclk_div  = cyber2000_grphr(MCLK_DIV, cfb);	}#endif#ifdef __arm__	cyber2000fb_writeb(0x18, 0x46e8, cfb);	cyber2000fb_writeb(0x01, 0x102, cfb);	cyber2000fb_writeb(0x08, 0x46e8, cfb);	cyber2000fb_writeb(0x33, 0x3ce, cfb);	cyber2000fb_writeb(0x01, 0x3cf, cfb);	/*	 * MCLK on the NetWinder and the Shark is fixed at 75MHz	 */	cfb->mclk_mult = 0xdb;	cfb->mclk_div  = 0x54;#endif	/*	 * Initialise the CyberPro	 */	for (i = 0; i < sizeof(igs_regs); i += 2)		cyber2000_grphw(igs_regs[i], igs_regs[i+1], cfb);	if (at_boot) {		/*		 * get the video RAM size and width from the VGA register.		 * This should have been already initialised by the BIOS,		 * but if it's garbage, claim default 1MB VRAM (woody)		 */		cfb->mem_ctl1 = cyber2000_grphr(MEM_CTL1, cfb);		cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2, cfb);	} else {		/*		 * Reprogram the MEM_CTL1 and MEM_CTL2 registers		 */		cyber2000_grphw(MEM_CTL1, cfb->mem_ctl1, cfb);		cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2, cfb);	}	/*	 * Ensure thatwe are using the correct PLL.	 * (CyberPro 5000's may be programmed to use	 * an additional set of PLLs.	 */	cyber2000fb_writeb(0xba, 0x3ce, cfb);	cyber2000fb_writeb(cyber2000fb_readb(0x3cf, cfb) & 0x80, 0x3cf, cfb);}static struct cfb_info * __devinitcyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id, char *name){	struct cfb_info *cfb;	cfb = kmalloc(sizeof(struct cfb_info) + sizeof(struct display) +		       sizeof(u32) * 16, GFP_KERNEL);	if (!cfb)		return NULL;	memset(cfb, 0, sizeof(struct cfb_info) + sizeof(struct display));	cfb->currcon		= -1;	cfb->dev		= dev;	if (id->driver_data == FB_ACCEL_IGS_CYBER5000)		cfb->ref_ps	= 40690; // 24.576 MHz	else		cfb->ref_ps	= 69842; // 14.31818 MHz (69841?)	cfb->divisors[0]	= 1;	cfb->divisors[1]	= 2;	cfb->divisors[2]	= 4;	if (id->driver_data == FB_ACCEL_IGS_CYBER2000)		cfb->divisors[3] = 8;	else		cfb->divisors[3] = 6;	strcpy(cfb->fb.fix.id, name);	cfb->fb.fix.type	= FB_TYPE_PACKED_PIXELS;	cfb->fb.fix.type_aux	= 0;	cfb->fb.fix.xpanstep	= 0;	cfb->fb.fix.ypanstep	= 1;	cfb->fb.fix.ywrapstep	= 0;	cfb->fb.fix.accel	= id->driver_data;	cfb->fb.var.nonstd	= 0;	cfb->fb.var.activate	= FB_ACTIVATE_NOW;	cfb->fb.var.height	= -1;	cfb->fb.var.width	= -1;	cfb->fb.var.accel_flags	= FB_ACCELF_TEXT;	strcpy(cfb->fb.modename, cfb->fb.fix.id);	strcpy(cfb->fb.fontname, default_font);	cfb->fb.fbops		= &cyber2000fb_ops;	cfb->fb.changevar	= NULL;	cfb->fb.switch_con	= cyber2000fb_switch;	cfb->fb.updatevar	= cyber2000fb_updatevar;	cfb->fb.blank		= cyber2000fb_blank;	cfb->fb.flags		= FBINFO_FLAG_DEFAULT;	cfb->fb.disp		= (struct display *)(cfb + 1);	cfb->fb.pseudo_palette	= (void *)(cfb->fb.disp + 1);	fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0);	return cfb;}static void __devinitcyberpro_free_fb_info(struct cfb_info *cfb){	if (cfb) {		/*		 * Free the colourmap		 */		fb_alloc_cmap(&cfb->fb.cmap, 0, 0);		kfree(cfb);	}}/* * Parse Cyber2000fb options.  Usage: *  video=cyber2000:font:fontname */intcyber2000fb_setup(char *options){	char *opt;	if (!options || !*options)		return 0;	while ((opt = strsep(&options, ",")) != NULL) {		if (!*opt)			continue;		if (strncmp(opt, "font:", 5) == 0) {			strncpy(default_font_storage, opt + 5, sizeof(default_font_storage));			default_font = default_font_storage;			continue;		}		printk(KERN_ERR "CyberPro20x0: unknown parameter: %s\n", opt);	}	return 0;}static int __devinitcyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id){	struct cfb_info *cfb;	u_int h_sync, v_sync;	u_long smem_size;	char name[16];	int err;	sprintf(name, "CyberPro%4X", id->device);	err = pci_enable_device(dev);	if (err)		return err;	err = pci_request_regions(dev, name);	if (err)		return err;	err = -ENOMEM;	cfb = cyberpro_alloc_fb_info(dev, id, name);	if (!cfb)		goto failed_release;	cfb->region = ioremap(pci_resource_start(dev, 0),			      pci_resource_len(dev, 0));	if (!cfb->region)		goto failed_ioremap;	cfb->regs = cfb->region + MMIO_OFFSET;	cyberpro_init_hw(cfb, 1);	switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) {	case MEM_CTL2_SIZE_4MB:	smem_size = 0x00400000; break;	case MEM_CTL2_SIZE_2MB:	smem_size = 0x00200000; break;	default:		smem_size = 0x00100000; break;	}	/*	 * Hmm, we _need_ a portable way of finding the address for	 * the remap stuff, both for mmio and for smem.	 */	cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;	cfb->fb.fix.smem_start = pci_resource_start(dev, 0);	cfb->fb.fix.mmio_len   = MMIO_SIZE;	cfb->fb.fix.smem_len   = smem_size;	cfb->fb.screen_base    = cfb->region;	if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,	    		  &cyber2000fb_default_mode, 8)) {		printk("%s: no valid mode found\n", cfb->fb.fix.id);		goto failed;	}	cfb->fb.var.yres_virtual = cfb->fb.fix.smem_len * 8 /			(cfb->fb.var.bits_per_pixel * cfb->fb.var.xres_virtual);	if (cfb->fb.var.yres_virtual < cfb->fb.var.yres)		cfb->fb.var.yres_virtual = cfb->fb.var.yres;	cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);	/*	 * Calculate the hsync and vsync frequencies.  Note that	 * we split the 1e12 constant up so that we can preserve	 * the precision and fit the results into 32-bit registers.	 *  (1953125000 * 512 = 1e12)	 */	h_sync = 1953125000 / cfb->fb.var.pixclock;	h_sync = h_sync * 512 / (cfb->fb.var.xres + cfb->fb.var.left_margin +		 cfb->fb.var.right_margin + cfb->fb.var.hsync_len);	v_sync = h_sync / (cfb->fb.var.yres + cfb->fb.var.upper_margin +		 cfb->fb.var.lower_margin + cfb->fb.var.vsync_len);	printk(KERN_INFO "%s: %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",		cfb->fb.fix.id, cfb->fb.fix.smem_len >> 10,		cfb->fb.var.xres, cfb->fb.var.yres,		h_sync / 1000, h_sync % 1000, v_sync);	err = register_framebuffer(&cfb->fb);	if (err < 0)		goto failed;	/*	 * Our driver data	 */	pci_set_drvdata(dev, cfb);	if (int_cfb_info == NULL)		int_cfb_info = cfb;	return 0;failed:	iounmap(cfb->region);failed_ioremap:	cyberpro_free_fb_info(cfb);failed_release:	pci_release_regions(dev);	return err;}static void __devexit cyberpro_remove(struct pci_dev *dev){	struct cfb_info *cfb = pci_get_drvdata(dev);	if (cfb) {		/*		 * If unregister_framebuffer fails, then		 * we will be leaving hooks that could cause		 * oopsen laying around.		 */		if (unregister_framebuffer(&cfb->fb))			printk(KERN_WARNING "%s: danger Will Robinson, "				"danger danger!  Oopsen imminent!\n",				cfb->fb.fix.id);		iounmap(cfb->region);		cyberpro_free_fb_info(cfb);		/*		 * Ensure that the driver data is no longer		 * valid.		 */		pci_set_drvdata(dev, NULL);		if (cfb == int_cfb_info)			int_cfb_info = NULL;		pci_release_regions(dev);	}}static int cyberpro_suspend(struct pci_dev *dev, u32 state){	return 0;}/* * Re-initialise the CyberPro hardware */static int cyberpro_resume(struct pci_dev *dev){	struct cfb_info *cfb = pci_get_drvdata(dev);	if (cfb) {		cyberpro_init_hw(cfb, 0);		/*		 * Restore the old video mode and the palette.		 * We also need to tell fbcon to redraw the console.		 */		cfb->fb.var.activate = FB_ACTIVATE_NOW;		cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);	}	return 0;}static struct pci_device_id cyberpro_pci_table[] __devinitdata = {	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2000 },	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2010 },	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER5000 },	{ 0, }};static struct pci_driver cyberpro_driver = {	name:		"CyberPro",	probe:		cyberpro_probe,	remove:		__devexit_p(cyberpro_remove),	suspend:	cyberpro_suspend,	resume:		cyberpro_resume,	id_table:	cyberpro_pci_table};/* * I don't think we can use the "module_init" stuff here because * the fbcon stuff may not be initialised yet.  Hence the #ifdef * around module_init. */int __init cyber2000fb_init(void){	return pci_module_init(&cyberpro_driver);}static void __exit cyberpro_exit(void){	pci_unregister_driver(&cyberpro_driver);}#ifdef MODULEmodule_init(cyber2000fb_init);#endifmodule_exit(cyberpro_exit);MODULE_AUTHOR("Russell King");MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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